Merge branch 'frr/pull/822' ("EVPN fixes")

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2017-08-09 21:34:10 +02:00
commit 695bb8f0d1
33 changed files with 2845 additions and 869 deletions

View File

@ -2606,10 +2606,9 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
stream_putc(s, pkt_safi); /* SAFI */
/* Nexthop AFI */
if (afi == AFI_IP && safi == SAFI_UNICAST) {
if (afi == AFI_IP
&& (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
} else if (safi == SAFI_LABELED_UNICAST)
nh_afi = afi;
else
nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
@ -2800,8 +2799,7 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
if (attrlenfield > 0xff) {
/* 2-octet length field */
stream_putc(s,
BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, attrtype);
stream_putw(s, attrlenfield & 0xffff);
@ -3040,14 +3038,13 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
if (attr->community->size * 4 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putw(s, attr->community->size * 4);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putc(s, attr->community->size * 4);
@ -3062,14 +3059,13 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
PEER_FLAG_SEND_LARGE_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (attr->lcommunity->size * 12 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
stream_putw(s, attr->lcommunity->size * 12);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
stream_putc(s, attr->lcommunity->size * 12);
@ -3122,15 +3118,13 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
if (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED) {
if (attr->ecommunity->size * 8 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
stream_putw(s, attr->ecommunity->size * 8);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
stream_putc(s, attr->ecommunity->size * 8);
@ -3197,8 +3191,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
label_index = attr->label_index;
if (label_index != BGP_INVALID_LABEL_INDEX) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_PREFIX_SID);
stream_putc(s, 10);
@ -3227,8 +3220,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
*/
aspath = aspath_delete_confed_seq(aspath);
stream_putc(s,
BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_AS4_PATH);
aspath_sizep = stream_get_endp(s);
@ -3414,14 +3406,13 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
/* Community attribute. */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
if (attr->community->size * 4 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putw(s, attr->community->size * 4);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putc(s, attr->community->size * 4);
@ -3432,14 +3423,13 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
/* Large Community attribute. */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
if (attr->lcommunity->size * 12 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
stream_putw(s, attr->lcommunity->size * 12);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
stream_putc(s, attr->lcommunity->size * 12);
@ -3485,8 +3475,7 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
/* Prefix SID */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_PREFIX_SID);
stream_putc(s, 10);

View File

@ -169,7 +169,7 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
prefix_copy(src, dst);
memset(dst, 0, sizeof(struct prefix));
p_evpn_p = &(dst->u.prefix_evpn);
dst->family = AF_ETHERNET;
dst->family = AF_EVPN;
p_evpn_p->route_type = evpn_type;
if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
p_evpn_p->eth_tag = eth_tag;

View File

@ -347,8 +347,8 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
s = zclient->obuf;
stream_reset(s);
zclient_create_header(
s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
zclient_create_header(s, add ? ZEBRA_REMOTE_MACIP_ADD
: ZEBRA_REMOTE_MACIP_DEL,
bgp->vrf_id);
stream_putl(s, vpn->vni);
stream_put(s, &p->prefix.mac.octet, ETH_ALEN); /* Mac Addr */
@ -400,8 +400,8 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
s = zclient->obuf;
stream_reset(s);
zclient_create_header(
s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL,
zclient_create_header(s, add ? ZEBRA_REMOTE_VTEP_ADD
: ZEBRA_REMOTE_VTEP_DEL,
bgp->vrf_id);
stream_putl(s, vpn->vni);
if (IS_EVPN_PREFIX_IPADDR_V4(p))
@ -472,7 +472,7 @@ static void add_mac_mobility_to_attr(u_int32_t seq_num, struct attr *attr)
{
struct ecommunity ecom_tmp;
struct ecommunity_val eval;
struct ecommunity *ecom_mm;
u_int8_t *ecom_val_ptr;
int i;
u_int8_t *pnt;
int type = 0;
@ -482,7 +482,7 @@ static void add_mac_mobility_to_attr(u_int32_t seq_num, struct attr *attr)
encode_mac_mobility_extcomm(0, seq_num, &eval);
/* Find current MM ecommunity */
ecom_mm = NULL;
ecom_val_ptr = NULL;
if (attr->ecommunity) {
for (i = 0; i < attr->ecommunity->size; i++) {
@ -493,17 +493,17 @@ static void add_mac_mobility_to_attr(u_int32_t seq_num, struct attr *attr)
if (type == ECOMMUNITY_ENCODE_EVPN
&& sub_type
== ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) {
ecom_mm = (struct ecommunity *)
attr->ecommunity->val
+ (i * 8);
ecom_val_ptr =
(u_int8_t *)(attr->ecommunity->val
+ (i * 8));
break;
}
}
}
/* Update the existing MM ecommunity */
if (ecom_mm) {
memcpy(ecom_mm->val, eval.val, sizeof(char) * ECOMMUNITY_SIZE);
if (ecom_val_ptr) {
memcpy(ecom_val_ptr, eval.val, sizeof(char) * ECOMMUNITY_SIZE);
}
/* Add MM to existing */
else {
@ -704,7 +704,7 @@ static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn)
static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
afi_t afi, safi_t safi, struct bgp_node *rn,
struct attr *attr, int add, int vni_table,
struct bgp_info **ri)
struct bgp_info **ri, u_char flags)
{
struct bgp_info *tmp_ri;
struct bgp_info *local_ri, *remote_ri;
@ -751,8 +751,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* remote, we have to initiate appropriate MAC mobility steps.
* This
* is applicable when updating the VNI routing table.
* We need to skip mobility steps for g/w macs (local mac on g/w
* SVI) advertised in EVPN.
* This will ensure that local routes are preferred for g/w macs
*/
if (remote_ri) {
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MAC_TYPE_GW)) {
u_int32_t cur_seqnum;
/* Add MM extended community to route. */
@ -811,7 +814,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* and schedule for processing.
*/
static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
struct prefix_evpn *p, u_char sticky)
struct prefix_evpn *p, u_char flags)
{
struct bgp_node *rn;
struct attr attr;
@ -828,7 +831,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
attr.nexthop = vpn->originator_ip;
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr.sticky = sticky;
attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0;
/* Set up RT and ENCAP extended community. */
build_evpn_route_extcomm(vpn, &attr);
@ -839,7 +842,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
/* Create or update route entry. */
route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
1, 1, &ri);
1, 1, &ri, flags);
assert(ri);
attr_new = ri->attr;
@ -860,7 +863,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
(struct prefix *)p, &vpn->prd);
update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, 0,
&global_ri);
&global_ri, flags);
/* Schedule for processing and unlock node. */
bgp_process(bgp, rn, afi, safi);
@ -998,10 +1001,10 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
if (evpn_route_is_sticky(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky, 0, 1, &ri);
&attr_sticky, 0, 1, &ri, 0);
else
update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
0, 1, &ri);
0, 1, &ri, 0);
/* If a local route exists for this prefix, we need to update
* the global routing table too.
@ -1022,7 +1025,7 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
(struct prefix *)evp, &vpn->prd);
assert(rd_rn);
update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0,
0, &global_ri);
0, &global_ri, 0);
/* Schedule for processing and unlock node. */
bgp_process(bgp, rd_rn, afi, safi);
@ -1190,6 +1193,12 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
{
struct prefix_evpn p;
/* If VNI is not live, we only need to update the originator ip */
if (!is_vni_live(vpn)) {
vpn->originator_ip = originator_ip;
return 0;
}
/* Need to withdraw type-3 route as the originator IP is part
* of the key.
*/
@ -1631,8 +1640,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
(struct prefix *)&p, &vpn->prd);
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0,
&ri);
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0, &ri,
0);
/* Schedule for processing and unlock node. */
bgp_process(bgp, global_rn, afi, safi);
@ -1665,7 +1674,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
(struct prefix *)evp, &vpn->prd);
assert(global_rn);
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1,
0, &global_ri);
0, &global_ri, 0);
/* Schedule for processing and unlock node. */
bgp_process(bgp, global_rn, afi, safi);
@ -1798,7 +1807,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
/* Make EVPN prefix. */
memset(&p, 0, sizeof(struct prefix_evpn));
p.family = AF_ETHERNET;
p.family = AF_EVPN;
p.prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p.prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
@ -1887,7 +1896,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
/* Make EVPN prefix. */
memset(&p, 0, sizeof(struct prefix_evpn));
p.family = AF_ETHERNET;
p.family = AF_EVPN;
p.prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p.prefix.route_type = BGP_EVPN_IMET_ROUTE;
@ -1952,7 +1961,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
/* Make EVPN prefix. */
memset(&p, 0, sizeof(struct prefix_evpn));
p.family = AF_ETHERNET;
p.family = AF_EVPN;
p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
/* Additional information outside of prefix - ESI and GW IP */
@ -2021,7 +2030,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
struct evpn_addr *p_evpn_p;
memset(&temp, 0, 16);
if (p->family != AF_ETHERNET)
if (p->family != AF_EVPN)
return;
p_evpn_p = &(p->u.prefix_evpn);
@ -2204,7 +2213,7 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
PREFIX2STR_BUFFER));
}
} else {
/* Currently, this is to cater to other AF_ETHERNET code. */
/* For EVPN route types not supported yet. */
}
return (buf);
@ -2586,7 +2595,7 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
* Handle add of a local MACIP.
*/
int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
struct ipaddr *ip, u_char sticky)
struct ipaddr *ip, u_char flags)
{
struct bgpevpn *vpn;
struct prefix_evpn p;
@ -2606,13 +2615,15 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
/* Create EVPN type-2 route and schedule for processing. */
build_evpn_type2_prefix(&p, mac, ip);
if (update_evpn_route(bgp, vpn, &p, sticky)) {
if (update_evpn_route(bgp, vpn, &p, flags)) {
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
zlog_err(
"%u:Failed to create Type-2 route, VNI %u %sMAC %s IP %s",
bgp->vrf_id, vpn->vni, sticky ? "sticky" : "",
"%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s",
bgp->vrf_id, vpn->vni,
CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? "sticky gateway"
: "",
prefix_mac2str(mac, buf, sizeof(buf)),
ipaddr2str(ip, buf2, sizeof(buf2)));
return -1;
@ -2671,14 +2682,15 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
/* Lookup VNI. If present and no change, exit. */
vpn = bgp_evpn_lookup_vni(bgp, vni);
if (vpn && is_vni_live(vpn)) {
if (IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
if (vpn) {
if (is_vni_live(vpn)
&& IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
/* Probably some other param has changed that we don't
* care about. */
return 0;
/* Local tunnel endpoint IP address has changed */
return handle_tunnel_ip_change(bgp, vpn, originator_ip);
handle_tunnel_ip_change(bgp, vpn, originator_ip);
}
/* Create or update as appropriate. */
@ -2692,6 +2704,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
}
}
/* if the VNI is live already, there is nothibng more to do */
if (is_vni_live(vpn))
return 0;
/* Mark as "live" */
SET_FLAG(vpn->flags, VNI_FLAG_LIVE);

View File

@ -42,7 +42,7 @@ extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip,
u_char sticky);
u_char flags);
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip);

View File

@ -58,6 +58,9 @@ struct bgpevpn {
#define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */
#define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */
/* Flag to indicate if we are advertising the g/w mac ip for this VNI*/
u_int8_t advertise_gw_macip;
/* Id for deriving the RD automatically for this VNI */
u_int16_t rd_id;
@ -171,7 +174,7 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
struct ipaddr *ip)
{
memset(p, 0, sizeof(struct prefix_evpn));
p->family = AF_ETHERNET;
p->family = AF_EVPN;
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
memcpy(&p->prefix.mac.octet, mac->octet, ETH_ALEN);
@ -184,7 +187,7 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
struct in_addr originator_ip)
{
memset(p, 0, sizeof(struct prefix_evpn));
p->family = AF_ETHERNET;
p->family = AF_EVPN;
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
p->prefix.ip.ipa_type = IPADDR_V4;

View File

@ -195,6 +195,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn)
vty_out(vty, " RD: %s\n",
prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
vty_out(vty, " Originator IP: %s\n", inet_ntoa(vpn->originator_ip));
vty_out(vty, " Advertise-gw-macip : %s\n",
vpn->advertise_gw_macip ? "Yes" : "No");
vty_out(vty, " Import Route Target:\n");
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
@ -1641,6 +1643,51 @@ static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp)
vty);
}
/*
* evpn - enable advertisement of default g/w
*/
static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
{
if (!vpn) {
if (bgp->advertise_gw_macip)
return;
bgp->advertise_gw_macip = 1;
bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
} else {
if (vpn->advertise_gw_macip)
return;
vpn->advertise_gw_macip = 1;
bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
vpn->vni);
}
return;
}
/*
* evpn - disable advertisement of default g/w
*/
static void evpn_unset_advertise_default_gw(struct bgp *bgp,
struct bgpevpn *vpn)
{
if (!vpn) {
if (!bgp->advertise_gw_macip)
return;
bgp->advertise_gw_macip = 0;
bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
} else {
if (!vpn->advertise_gw_macip)
return;
vpn->advertise_gw_macip = 0;
bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
vpn->vni);
}
return;
}
/*
* EVPN (VNI advertisement) enabled. Register with zebra.
*/
@ -1700,6 +1747,9 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
}
}
if (vpn->advertise_gw_macip)
vty_out(vty, " advertise-default-gw\n");
vty_out(vty, " exit-vni\n");
}
}
@ -1712,6 +1762,77 @@ static void write_vni_config_for_entry(struct hash_backet *backet,
}
#if defined(HAVE_CUMULUS)
DEFUN (bgp_evpn_advertise_default_gw_vni,
bgp_evpn_advertise_default_gw_vni_cmd,
"advertise-default-gw",
"Advertise defualt g/w mac-ip routes in EVPN for a VNI\n")
{
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
if (!bgp)
return CMD_WARNING;
if (!vpn)
return CMD_WARNING;
evpn_set_advertise_default_gw(bgp, vpn);
return CMD_SUCCESS;
}
DEFUN (no_bgp_evpn_advertise_default_vni_gw,
no_bgp_evpn_advertise_default_gw_vni_cmd,
"no advertise-default-gw",
NO_STR
"Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
{
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
if (!bgp)
return CMD_WARNING;
if (!vpn)
return CMD_WARNING;
evpn_unset_advertise_default_gw(bgp, vpn);
return CMD_SUCCESS;
}
DEFUN (bgp_evpn_advertise_default_gw,
bgp_evpn_advertise_default_gw_cmd,
"advertise-default-gw",
"Advertise All defualt g/w mac-ip routes in EVPN\n")
{
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
if (!bgp)
return CMD_WARNING;
evpn_set_advertise_default_gw(bgp, NULL);
return CMD_SUCCESS;
}
DEFUN (no_bgp_evpn_advertise_default_gw,
no_bgp_evpn_advertise_default_gw_cmd,
"no advertise-default-gw",
NO_STR
"Withdraw All default g/w mac-ip routes from EVPN\n")
{
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
if (!bgp)
return CMD_WARNING;
evpn_unset_advertise_default_gw(bgp, NULL);
return CMD_SUCCESS;
}
DEFUN (bgp_evpn_advertise_all_vni,
bgp_evpn_advertise_all_vni_cmd,
"advertise-all-vni",
@ -1739,86 +1860,95 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_vni,
show_bgp_evpn_vni_cmd,
"show bgp evpn vni",
/*
* Display VNI information - for all or a specific VNI
*/
DEFUN (show_bgp_l2vpn_evpn_vni,
show_bgp_l2vpn_evpn_vni_cmd,
"show bgp l2vpn evpn vni [(1-16777215)]",
SHOW_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Show VNI\n")
{
struct bgp *bgp;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
vty_out(vty, "Advertise All VNI flag: %s\n",
bgp->advertise_all_vni ? "Enabled" : "Disabled");
evpn_show_all_vnis(vty, bgp);
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_vni_num,
show_bgp_evpn_vni_num_cmd,
"show bgp evpn vni (1-16777215)",
SHOW_STR
BGP_STR
"Address family modifier\n"
"Show VNI\n"
"VNI number\n")
{
vni_t vni;
struct bgp *bgp;
vni_t vni;
int idx = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
vni = strtoul(argv[4]->arg, NULL, 10);
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
if (argc == ((idx + 1) + 1)) {
vty_out(vty, "Advertise gateway macip flag: %s\n",
bgp->advertise_gw_macip ? "Enabled" : "Disabled");
/* Display all VNIs */
vty_out(vty, "Advertise All VNI flag: %s\n",
bgp->advertise_all_vni ? "Enabled" : "Disabled");
evpn_show_all_vnis(vty, bgp);
} else {
/* Display specific VNI */
vni = strtoul(argv[argc - 1]->arg, NULL, 10);
evpn_show_vni(vty, bgp, vni);
}
return CMD_SUCCESS;
}
/* `show bgp evpn summary' commands. */
DEFUN (show_bgp_evpn_summary,
show_bgp_evpn_summary_cmd,
"show bgp evpn summary [json]",
/*
* Display EVPN neighbor summary.
*/
DEFUN (show_bgp_l2vpn_evpn_summary,
show_bgp_l2vpn_evpn_summary_cmd,
"show bgp l2vpn evpn summary [json]",
SHOW_STR
BGP_STR
"EVPN\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"Summary of BGP neighbor status\n"
"JavaScript Object Notation\n")
JSON_STR)
{
u_char uj = use_json(argc, argv);
return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
}
/* Show bgp evpn route */
DEFUN (show_bgp_evpn_route,
show_bgp_evpn_route_cmd,
"show bgp evpn route [type <macip|multicast>]",
/*
* Display global EVPN routing table.
*/
DEFUN (show_bgp_l2vpn_evpn_route,
show_bgp_l2vpn_evpn_route_cmd,
"show bgp l2vpn evpn route [type <macip|multicast>]",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"Specify Route type\n"
"MAC-IP (Type-2) route\n"
"Multicast (Type-3) route\n")
{
struct bgp *bgp;
int idx = 0;
int type = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
if (argc == 6) {
if (strncmp(argv[5]->arg, "ma", 2) == 0)
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
if (argc == ((idx + 1) + 3)) {
/* Specific type is requested */
if (strncmp(argv[argc - 1]->arg, "ma", 2) == 0)
type = BGP_EVPN_MAC_IP_ROUTE;
else if (strncmp(argv[5]->arg, "mu", 2) == 0)
else if (strncmp(argv[argc - 1]->arg, "mu", 2) == 0)
type = BGP_EVPN_IMET_ROUTE;
else
return CMD_WARNING;
@ -1828,13 +1958,17 @@ DEFUN (show_bgp_evpn_route,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_route_rd,
show_bgp_evpn_route_rd_cmd,
"show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
/*
* Display global EVPN routing table for specific RD.
*/
DEFUN (show_bgp_l2vpn_evpn_route_rd,
show_bgp_l2vpn_evpn_route_rd_cmd,
"show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"Route Distinguisher\n"
"ASN:XX or A.B.C.D:XX\n"
"Specify Route type\n"
@ -1844,22 +1978,27 @@ DEFUN (show_bgp_evpn_route_rd,
struct bgp *bgp;
int ret;
struct prefix_rd prd;
int idx = 0;
int type = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
ret = str2prefix_rd(argv[5]->arg, &prd);
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
ret = str2prefix_rd(argv[idx + 3]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher\n");
return CMD_WARNING;
}
if (argc == 8) {
if (strncmp(argv[7]->arg, "ma", 2) == 0)
if (argc == ((idx + 1) + 5)) {
/* Specific type is requested */
if (strncmp(argv[argc - 1]->arg, "ma", 2) == 0)
type = BGP_EVPN_MAC_IP_ROUTE;
else if (strncmp(argv[7]->arg, "mu", 2) == 0)
else if (strncmp(argv[argc - 1]->arg, "mu", 2) == 0)
type = BGP_EVPN_IMET_ROUTE;
else
return CMD_WARNING;
@ -1869,13 +2008,17 @@ DEFUN (show_bgp_evpn_route_rd,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_route_rd_macip,
show_bgp_evpn_route_rd_macip_cmd,
"show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
/*
* Display global EVPN routing table for specific RD and MACIP.
*/
DEFUN (show_bgp_l2vpn_evpn_route_rd_macip,
show_bgp_l2vpn_evpn_route_rd_macip_cmd,
"show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"Route Distinguisher\n"
"ASN:XX or A.B.C.D:XX\n"
"MAC\n"
@ -1888,23 +2031,28 @@ DEFUN (show_bgp_evpn_route_rd_macip,
struct prefix_rd prd;
struct ethaddr mac;
struct ipaddr ip;
int idx = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
ret = str2prefix_rd(argv[5]->arg, &prd);
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
ret = str2prefix_rd(argv[idx + 3]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher\n");
return CMD_WARNING;
}
if (!prefix_str2mac(argv[7]->arg, &mac)) {
if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
vty_out(vty, "%% Malformed MAC address\n");
return CMD_WARNING;
}
memset(&ip, 0, sizeof(ip));
if (argc == 10 && argv[9]->arg != NULL) {
if (str2ipaddr(argv[9]->arg, &ip) != 0) {
if (argc == (idx + 1 + 7) && argv[argc - 1]->arg != NULL) {
/* Specific MAC+IP requested */
if (str2ipaddr(argv[argc - 1]->arg, &ip) != 0) {
vty_out(vty, "%% Malformed IP address\n");
return CMD_WARNING;
}
@ -1914,13 +2062,17 @@ DEFUN (show_bgp_evpn_route_rd_macip,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_route_vni,
show_bgp_evpn_route_vni_cmd,
"show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
/*
* Display per-VNI EVPN routing table.
*/
DEFUN (show_bgp_l2vpn_evpn_route_vni,
show_bgp_l2vpn_evpn_route_vni_cmd,
"show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"VNI number\n"
"Specify Route type\n"
@ -1933,25 +2085,29 @@ DEFUN (show_bgp_evpn_route_vni,
struct bgp *bgp;
struct in_addr vtep_ip;
int type = 0;
int idx = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
vtep_ip.s_addr = 0;
vni = strtoul(argv[5]->arg, NULL, 10);
vni = strtoul(argv[idx + 3]->arg, NULL, 10);
if (argc == 8 && argv[6]->arg) {
if (strncmp(argv[6]->arg, "type", 4) == 0) {
if (strncmp(argv[7]->arg, "ma", 2) == 0)
if (argc == (idx + 1 + 5) && argv[idx + 4]->arg) {
if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
type = BGP_EVPN_MAC_IP_ROUTE;
else if (strncmp(argv[7]->arg, "mu", 2) == 0)
else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
type = BGP_EVPN_IMET_ROUTE;
else
return CMD_WARNING;
} else if (strncmp(argv[6]->arg, "vtep", 4) == 0) {
if (!inet_aton(argv[7]->arg, &vtep_ip)) {
} else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
vty_out(vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
@ -1963,13 +2119,17 @@ DEFUN (show_bgp_evpn_route_vni,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_route_vni_macip,
show_bgp_evpn_route_vni_macip_cmd,
"show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
/*
* Display per-VNI EVPN routing table for specific MACIP.
*/
DEFUN (show_bgp_l2vpn_evpn_route_vni_macip,
show_bgp_l2vpn_evpn_route_vni_macip_cmd,
"show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD]",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"VNI number\n"
"MAC\n"
@ -1981,19 +2141,23 @@ DEFUN (show_bgp_evpn_route_vni_macip,
struct bgp *bgp;
struct ethaddr mac;
struct ipaddr ip;
int idx = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
vni = strtoul(argv[5]->arg, NULL, 10);
if (!prefix_str2mac(argv[7]->arg, &mac)) {
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
vni = strtoul(argv[idx + 3]->arg, NULL, 10);
if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
vty_out(vty, "%% Malformed MAC address\n");
return CMD_WARNING;
}
memset(&ip, 0, sizeof(ip));
if (argc == 10 && argv[9]->arg != NULL) {
if (str2ipaddr(argv[9]->arg, &ip) != 0) {
if (argc == (idx + 1 + 7) && argv[idx + 7]->arg != NULL) {
if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
vty_out(vty, "%% Malformed IP address\n");
return CMD_WARNING;
}
@ -2003,13 +2167,17 @@ DEFUN (show_bgp_evpn_route_vni_macip,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_route_vni_multicast,
show_bgp_evpn_route_vni_multicast_cmd,
"show bgp evpn route vni (1-16777215) multicast A.B.C.D",
/*
* Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
*/
DEFUN (show_bgp_l2vpn_evpn_route_vni_multicast,
show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
"show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"VNI number\n"
"Multicast (Type-3) route\n"
@ -2019,13 +2187,17 @@ DEFUN (show_bgp_evpn_route_vni_multicast,
struct bgp *bgp;
int ret;
struct in_addr orig_ip;
int idx = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
vni = strtoul(argv[5]->arg, NULL, 10);
ret = inet_aton(argv[7]->arg, &orig_ip);
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
vni = strtoul(argv[idx + 3]->arg, NULL, 10);
ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
if (!ret) {
vty_out(vty, "%% Malformed Originating Router IP address\n");
return CMD_WARNING;
@ -2035,13 +2207,17 @@ DEFUN (show_bgp_evpn_route_vni_multicast,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_route_vni_all,
show_bgp_evpn_route_vni_all_cmd,
"show bgp evpn route vni all [vtep A.B.C.D]",
/*
* Display per-VNI EVPN routing table - for all VNIs.
*/
DEFUN (show_bgp_l2vpn_evpn_route_vni_all,
show_bgp_l2vpn_evpn_route_vni_all_cmd,
"show bgp l2vpn evpn route vni all [vtep A.B.C.D]",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
"Display EVPN route information\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"All VNIs\n"
"Remote VTEP\n"
@ -2049,14 +2225,18 @@ DEFUN (show_bgp_evpn_route_vni_all,
{
struct bgp *bgp;
struct in_addr vtep_ip;
int idx = 0;
bgp = bgp_get_default();
if (!bgp)
return CMD_WARNING;
if (!argv_find(argv, argc, "evpn", &idx))
return CMD_WARNING;
vtep_ip.s_addr = 0;
if (argc == 8 && argv[7]->arg) {
if (!inet_aton(argv[7]->arg, &vtep_ip)) {
if (argc == (idx + 1 + 5) && argv[idx + 5]->arg) {
if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
vty_out(vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
@ -2066,12 +2246,16 @@ DEFUN (show_bgp_evpn_route_vni_all,
return CMD_SUCCESS;
}
DEFUN (show_bgp_evpn_import_rt,
show_bgp_evpn_import_rt_cmd,
"show bgp evpn import-rt",
/*
* Display EVPN import route-target hash table
*/
DEFUN (show_bgp_l2vpn_evpn_import_rt,
show_bgp_l2vpn_evpn_import_rt_cmd,
"show bgp l2vpn evpn import-rt",
SHOW_STR
BGP_STR
"Address family modifier\n"
L2VPN_HELP_STR
EVPN_HELP_STR
"Show import route target\n")
{
struct bgp *bgp;
@ -2084,6 +2268,97 @@ DEFUN (show_bgp_evpn_import_rt,
return CMD_SUCCESS;
}
#if defined(HAVE_CUMULUS)
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
"show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
"Show VNI\n"
"VNI number\n")
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
"show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
"Summary of BGP neighbor status\n"
JSON_STR)
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
"show bgp evpn route [type <macip|multicast>]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"Specify Route type\n"
"MAC-IP (Type-2) route\n"
"Multicast (Type-3) route\n")
ALIAS_HIDDEN(
show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
"show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"Route Distinguisher\n"
"ASN:XX or A.B.C.D:XX\n"
"Specify Route type\n"
"MAC-IP (Type-2) route\n"
"Multicast (Type-3) route\n")
ALIAS_HIDDEN(
show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
"show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"Route Distinguisher\n"
"ASN:XX or A.B.C.D:XX\n"
"MAC\n"
"MAC address (e.g., 00:e0:ec:20:12:62)\n"
"IP\n"
"IP address (IPv4 or IPv6)\n")
ALIAS_HIDDEN(
show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
"show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"VNI number\n"
"Specify Route type\n"
"MAC-IP (Type-2) route\n"
"Multicast (Type-3) route\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
show_bgp_evpn_route_vni_macip_cmd,
"show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"VNI number\n"
"MAC\n"
"MAC address (e.g., 00:e0:ec:20:12:62)\n"
"IP\n"
"IP address (IPv4 or IPv6)\n")
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
show_bgp_evpn_route_vni_multicast_cmd,
"show bgp evpn route vni (1-16777215) multicast A.B.C.D",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"VNI number\n"
"Multicast (Type-3) route\n"
"Originating Router IP address\n")
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
"show bgp evpn route vni all [vtep A.B.C.D]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
"All VNIs\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
"show bgp evpn import-rt",
SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
#endif
DEFUN_NOSH (bgp_evpn_vni,
bgp_evpn_vni_cmd,
"vni (1-16777215)",
@ -2290,11 +2565,11 @@ DEFUN (bgp_evpn_vni_rt,
if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
ecomadd = ecommunity_str2com(argv[2]->arg,
ECOMMUNITY_ROUTE_TARGET, 0);
ecommunity_str(ecomadd);
if (!ecomadd) {
vty_out(vty, "%% Malformed Route Target list\n");
return CMD_WARNING;
}
ecommunity_str(ecomadd);
/* Do nothing if we already have this import route-target */
if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
@ -2305,11 +2580,11 @@ DEFUN (bgp_evpn_vni_rt,
if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
ecomadd = ecommunity_str2com(argv[2]->arg,
ECOMMUNITY_ROUTE_TARGET, 0);
ecommunity_str(ecomadd);
if (!ecomadd) {
vty_out(vty, "%% Malformed Route Target list\n");
return CMD_WARNING;
}
ecommunity_str(ecomadd);
/* Do nothing if we already have this export route-target */
if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
@ -2372,11 +2647,11 @@ DEFUN (no_bgp_evpn_vni_rt,
}
ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
ecommunity_str(ecomdel);
if (!ecomdel) {
vty_out(vty, "%% Malformed Route Target list\n");
return CMD_WARNING;
}
ecommunity_str(ecomdel);
if (rt_type == RT_TYPE_IMPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
@ -2484,6 +2759,11 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
bgp_config_write_family_header(vty, afi, safi, write);
vty_out(vty, " advertise-all-vni\n");
}
if (bgp->advertise_gw_macip) {
bgp_config_write_family_header(vty, afi, safi, write);
vty_out(vty, " advertise-default-gw\n");
}
}
void bgp_ethernetvpn_init(void)
@ -2509,10 +2789,24 @@ void bgp_ethernetvpn_init(void)
#if defined(HAVE_CUMULUS)
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
/* "show bgp l2vpn evpn" commands. */
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
install_element(VIEW_NODE,
&show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
/* "show bgp evpn" commands. */
install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
install_element(VIEW_NODE, &show_bgp_evpn_vni_num_cmd);
install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
@ -2532,5 +2826,9 @@ void bgp_ethernetvpn_init(void)
install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
install_element(BGP_EVPN_VNI_NODE,
&bgp_evpn_advertise_default_gw_vni_cmd);
install_element(BGP_EVPN_VNI_NODE,
&no_bgp_evpn_advertise_default_gw_vni_cmd);
#endif
}

View File

@ -1580,10 +1580,18 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) {
struct bgp_info info;
struct bgp_info_extra dummy_info_extra;
struct attr dummy_attr;
info.peer = peer;
info.attr = attr;
if (ri->extra) {
memcpy(&dummy_info_extra, ri->extra,
sizeof(struct bgp_info_extra));
info.extra = &dummy_info_extra;
}
/* don't confuse inbound and outbound setting */
RESET_FLAG(attr->rmap_change_flags);
@ -6238,6 +6246,9 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty)
} else
len += vty_out(vty, "/%d", p->prefixlen);
} else if (p->family == AF_ETHERNET) {
prefix2str(p, buf, PREFIX_STRLEN);
len = vty_out(vty, "%s", buf);
} else if (p->family == AF_EVPN) {
#if defined(HAVE_CUMULUS)
len = vty_out(vty, "%s",
bgp_evpn_route2str((struct prefix_evpn *)p, buf,
@ -6505,15 +6516,14 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
len = vty_out(
vty, "%s",
binfo->peer->conf_if);
len =
7 - len; /* len of IPv6
len = 16 - len; /* len of IPv6
addr + max
len of def
ifname */
if (len < 1)
vty_out(vty, "\n%*s",
45, " ");
36, " ");
else
vty_out(vty, "%*s", len,
" ");
@ -6801,7 +6811,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
if (attr) {
if (((p->family == AF_INET)
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
|| (safi == SAFI_EVPN && p->family == AF_ETHERNET
|| (safi == SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
@ -6826,7 +6836,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
}
} else if (((p->family == AF_INET6)
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
|| (safi == SAFI_EVPN && p->family == AF_ETHERNET
|| (safi == SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
char buf_a[BUFSIZ];
@ -7326,7 +7336,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
/* Line2 display Next-hop, Neighbor, Router-id */
/* Display the nexthop */
if ((p->family == AF_INET || p->family == AF_ETHERNET)
if ((p->family == AF_INET || p->family == AF_ETHERNET ||
p->family == AF_EVPN)
&& (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN
|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
@ -10232,6 +10243,10 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi,
enum bgp_show_type type, u_char use_json)
{
/* labeled-unicast routes live in the unicast table */
if (safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
if (!peer || !peer->afc[afi][safi]) {
if (use_json) {
json_object *json_no = NULL;

View File

@ -54,6 +54,9 @@
#include "bgpd/bgp_lcommunity.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_vty.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
@ -572,6 +575,106 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
route_match_ip_route_source_prefix_list_compile,
route_match_ip_route_source_prefix_list_free};
/* `match mac address MAC_ACCESS_LIST' */
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_mac_address(void *rule,
struct prefix *prefix,
route_map_object_t type,
void *object)
{
struct access_list *alist;
struct prefix p;
if (type == RMAP_BGP) {
alist = access_list_lookup(AFI_L2VPN, (char *)rule);
if (alist == NULL)
return RMAP_NOMATCH;
if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
return RMAP_NOMATCH;
p.family = AF_ETHERNET;
p.prefixlen = ETH_ALEN * 8;
p.u.prefix_eth = prefix->u.prefix_evpn.mac;
return (access_list_apply(alist, &p)
== FILTER_DENY
? RMAP_NOMATCH
: RMAP_MATCH);
}
return RMAP_NOMATCH;
}
/* Route map `mac address' match statement. `arg' should be
access-list name. */
static void *route_match_mac_address_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}
/* Free route map's compiled `ip address' value. */
static void route_match_mac_address_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
/* Route map commands for mac address matching. */
struct route_map_rule_cmd route_match_mac_address_cmd = {
"mac address", route_match_mac_address, route_match_mac_address_compile,
route_match_mac_address_free};
/* `match vni' */
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_vni(void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
vni_t vni = 0;
struct bgp_info *bgp_info = NULL;
if (type == RMAP_BGP) {
vni = *((vni_t *)rule);
bgp_info = (struct bgp_info *)object;
if (vni == label2vni(&bgp_info->extra->label))
return RMAP_MATCH;
}
return RMAP_NOMATCH;
}
/* Route map `vni' match statement. */
static void *route_match_vni_compile(const char *arg)
{
vni_t *vni = NULL;
char *end = NULL;
vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
if (!vni)
return NULL;
*vni = strtoul(arg, &end, 10);
if (*end != '\0')
return NULL;
return vni;
}
/* Free route map's compiled `vni' value. */
static void route_match_vni_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
/* Route map commands for vni matching. */
struct route_map_rule_cmd route_match_evpn_vni_cmd = {
"evpn vni", route_match_vni, route_match_vni_compile,
route_match_vni_free};
/* `match local-preference LOCAL-PREF' */
/* Match function return 1 if match is success else return zero. */
@ -2994,6 +3097,55 @@ static void bgp_route_map_event(route_map_event_t event, const char *rmap_name)
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
}
DEFUN (match_mac_address,
match_mac_address_cmd,
"match mac address WORD",
MATCH_STR
"mac address\n"
"Match address of route\n"
"MAC Access-list name\n")
{
return bgp_route_match_add(vty, "mac address", argv[3]->arg,
RMAP_EVENT_FILTER_ADDED);
}
DEFUN (no_match_mac_address,
no_match_mac_address_cmd,
"no match mac address WORD",
NO_STR
MATCH_STR
"mac\n"
"Match address of route\n"
"MAC acess-list name\n")
{
return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
RMAP_EVENT_FILTER_DELETED);
}
DEFUN (match_evpn_vni,
match_evpn_vni_cmd,
"match evpn vni (1-16777215)",
MATCH_STR
EVPN_HELP_STR
"Match VNI\n"
"VNI ID\n")
{
return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_evpn_vni,
no_match_evpn_vni_cmd,
"no match evpn vni (1-16777215)",
NO_STR
MATCH_STR
EVPN_HELP_STR
"Match VNI\n"
"VNI ID\n")
{
return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
RMAP_EVENT_MATCH_DELETED);
}
DEFUN (match_peer,
match_peer_cmd,
@ -4351,6 +4503,8 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_probability_cmd);
route_map_install_match(&route_match_interface_cmd);
route_map_install_match(&route_match_tag_cmd);
route_map_install_match(&route_match_mac_address_cmd);
route_map_install_match(&route_match_evpn_vni_cmd);
route_map_install_set(&route_set_ip_nexthop_cmd);
route_map_install_set(&route_set_local_pref_cmd);
@ -4381,6 +4535,10 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
install_element(RMAP_NODE, &match_mac_address_cmd);
install_element(RMAP_NODE, &no_match_mac_address_cmd);
install_element(RMAP_NODE, &match_evpn_vni_cmd);
install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
install_element(RMAP_NODE, &match_aspath_cmd);
install_element(RMAP_NODE, &no_match_aspath_cmd);

View File

@ -12047,6 +12047,8 @@ void bgp_vty_init(void)
install_element(BGP_VPNV4_NODE, &no_neighbor_route_map_cmd);
install_element(BGP_VPNV6_NODE, &neighbor_route_map_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_route_map_cmd);
install_element(BGP_EVPN_NODE, &neighbor_route_map_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_route_map_cmd);
/* "neighbor unsuppress-map" commands. */
install_element(BGP_NODE, &neighbor_unsuppress_map_hidden_cmd);

View File

@ -2034,6 +2034,29 @@ void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer)
zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0);
}
int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
{
struct stream *s = NULL;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return 0;
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
return 0;
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_ADVERTISE_DEFAULT_GW, bgp->vrf_id);
stream_putc(s, advertise);
stream_put3(s, vni);
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
{
struct stream *s;
@ -2120,7 +2143,7 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
int ipa_len;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
u_char sticky;
u_char flags;
memset(&ip, 0, sizeof(ip));
s = zclient->ibuf;
@ -2140,21 +2163,20 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
(ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6;
stream_get(&ip.ip.addr, s, ipa_len);
}
sticky = stream_getc(s);
flags = stream_getc(s);
bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp)
return 0;
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("%u:Recv MACIP %s %sMAC %s IP %s VNI %u", vrf_id,
(command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
sticky ? "sticky " : "",
prefix_mac2str(&mac, buf, sizeof(buf)),
zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u",
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
flags, prefix_mac2str(&mac, buf, sizeof(buf)),
ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
if (command == ZEBRA_MACIP_ADD)
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, sticky);
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags);
else
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
}

View File

@ -21,6 +21,8 @@
#ifndef _QUAGGA_BGP_ZEBRA_H
#define _QUAGGA_BGP_ZEBRA_H
#include "vxlan.h"
extern void bgp_zebra_init(struct thread_master *master);
extern void bgp_zebra_destroy(void);
extern int bgp_if_update_all(void);
@ -57,6 +59,7 @@ extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t,
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
vrf_id_t);
extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
extern int bgp_zebra_num_connects(void);

View File

@ -380,6 +380,9 @@ struct bgp {
/* EVI hash table */
struct hash *vnihash;
/* EVPN enable - advertise gateway macip routes */
int advertise_gw_macip;
/* EVPN enable - advertise local VNIs and their MACs etc. */
int advertise_all_vni;
@ -1488,7 +1491,8 @@ static inline int peer_group_af_configured(struct peer_group *group)
|| peer->afc[AFI_IP6][SAFI_MULTICAST]
|| peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc[AFI_IP6][SAFI_ENCAP] || peer->afc[AFI_IP6][SAFI_EVPN])
|| peer->afc[AFI_IP6][SAFI_ENCAP]
|| peer->afc[AFI_L2VPN][SAFI_EVPN])
return 1;
return 0;
}

View File

@ -21,6 +21,8 @@
#include "command.h"
#include "vty.h"
#include "json.h"
#include "ldpd/ldpd.h"
#include "ldpd/ldp_vty.h"
#include "ldpd/ldp_vty_cmds_clippy.c"
@ -586,7 +588,7 @@ DEFPY (ldp_show_mpls_ldp_binding,
"IPv6 Address Family\n"
"Label Information Base (LIB) information\n"
"Show detailed information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_binding(vty, af, detail, json));
}
@ -601,7 +603,7 @@ DEFPY (ldp_show_mpls_ldp_discovery,
"IPv6 Address Family\n"
"Discovery Hello Information\n"
"Show detailed information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_discovery(vty, af, detail, json));
}
@ -615,7 +617,7 @@ DEFPY (ldp_show_mpls_ldp_interface,
"IPv4 Address Family\n"
"IPv6 Address Family\n"
"interface information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_interface(vty, af, json));
}
@ -627,7 +629,7 @@ DEFPY (ldp_show_mpls_ldp_capabilities,
"MPLS information\n"
"Label Distribution Protocol\n"
"Display LDP Capabilities information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_capabilities(vty, json));
}
@ -640,7 +642,7 @@ DEFPY (ldp_show_mpls_ldp_neighbor,
"Label Distribution Protocol\n"
"Neighbor information\n"
"Show detailed information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_neighbor(vty, 0, detail, json));
}
@ -653,7 +655,7 @@ DEFPY (ldp_show_mpls_ldp_neighbor_capabilities,
"Label Distribution Protocol\n"
"Neighbor information\n"
"Display neighbor capability information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_neighbor(vty, 1, NULL, json));
}
@ -665,7 +667,7 @@ DEFPY (ldp_show_l2vpn_atom_binding,
"Show information about Layer2 VPN\n"
"Show Any Transport over MPLS information\n"
"Show AToM label binding information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_atom_binding(vty, json));
}
@ -677,7 +679,7 @@ DEFPY (ldp_show_l2vpn_atom_vc,
"Show information about Layer2 VPN\n"
"Show Any Transport over MPLS information\n"
"Show AToM virtual circuit information\n"
"JavaScript Object Notation\n")
JSON_STR)
{
return (ldp_vty_show_atom_vc(vty, json));
}

View File

@ -101,6 +101,7 @@ const char *node_names[] = {
"ipv4 access list", // ACCESS_NODE,
"ipv4 prefix list", // PREFIX_NODE,
"ipv6 access list", // ACCESS_IPV6_NODE,
"MAC access list", // ACCESS_MAC_NODE,
"ipv6 prefix list", // PREFIX_IPV6_NODE,
"as list", // AS_LIST_NODE,
"community list", // COMMUNITY_LIST_NODE,

View File

@ -123,6 +123,7 @@ enum node_type {
ACCESS_NODE, /* Access list node. */
PREFIX_NODE, /* Prefix list node. */
ACCESS_IPV6_NODE, /* Access list node. */
ACCESS_MAC_NODE, /* MAC access list node*/
PREFIX_IPV6_NODE, /* Prefix list node. */
AS_LIST_NODE, /* AS list node. */
COMMUNITY_LIST_NODE, /* Community list node. */

View File

@ -90,6 +90,14 @@ struct access_master {
void (*delete_hook)(struct access_list *);
};
/* Static structure for mac access_list's master. */
static struct access_master access_master_mac = {
{NULL, NULL},
{NULL, NULL},
NULL,
NULL,
};
/* Static structure for IPv4 access_list's master. */
static struct access_master access_master_ipv4 = {
{NULL, NULL},
@ -112,6 +120,8 @@ static struct access_master *access_master_get(afi_t afi)
return &access_master_ipv4;
else if (afi == AFI_IP6)
return &access_master_ipv6;
else if (afi == AFI_L2VPN)
return &access_master_mac;
return NULL;
}
@ -173,7 +183,7 @@ static int filter_match_cisco(struct filter *mfilter, struct prefix *p)
/* If filter match to the prefix then return 1. */
static int filter_match_zebra(struct filter *mfilter, struct prefix *p)
{
struct filter_zebra *filter;
struct filter_zebra *filter = NULL;
filter = &mfilter->u.zfilter;
@ -365,9 +375,7 @@ static struct access_list *access_list_get(afi_t afi, const char *name)
enum filter_type access_list_apply(struct access_list *access, void *object)
{
struct filter *filter;
struct prefix *p;
p = (struct prefix *)object;
struct prefix *p = (struct prefix *)object;
if (access == NULL)
return FILTER_DENY;
@ -390,6 +398,7 @@ void access_list_add_hook(void (*func)(struct access_list *access))
{
access_master_ipv4.add_hook = func;
access_master_ipv6.add_hook = func;
access_master_mac.add_hook = func;
}
/* Delete hook function. */
@ -397,6 +406,7 @@ void access_list_delete_hook(void (*func)(struct access_list *access))
{
access_master_ipv4.delete_hook = func;
access_master_ipv6.delete_hook = func;
access_master_mac.delete_hook = func;
}
/* Add new filter to the end of specified access_list. */
@ -515,11 +525,11 @@ static struct filter *filter_lookup_zebra(struct access_list *access,
filter = &mfilter->u.zfilter;
if (filter->exact == new->exact
&& mfilter->type
== mnew->type &&prefix_same(&filter->prefix,
&new->prefix))
&& mfilter->type == mnew->type) {
if (prefix_same(&filter->prefix, &new->prefix))
return mfilter;
}
}
return NULL;
}
@ -1252,6 +1262,12 @@ static int filter_set_zebra(struct vty *vty, const char *name_str,
"IPv6 address prefix/prefixlen is malformed\n");
return CMD_WARNING_CONFIG_FAILED;
}
} else if (afi == AFI_L2VPN) {
ret = str2prefix_eth(prefix_str, (struct prefix_eth *)&p);
if (ret <= 0) {
vty_out(vty, "MAC address is malformed\n");
return CMD_WARNING;
}
} else
return CMD_WARNING_CONFIG_FAILED;
@ -1274,7 +1290,6 @@ static int filter_set_zebra(struct vty *vty, const char *name_str,
access_list_filter_add(access, mfilter);
} else {
struct filter *delete_filter;
delete_filter = filter_lookup_zebra(access, mfilter);
if (delete_filter)
access_list_filter_delete(access, delete_filter);
@ -1285,6 +1300,64 @@ static int filter_set_zebra(struct vty *vty, const char *name_str,
return CMD_SUCCESS;
}
DEFUN (mac_access_list,
mac_access_list_cmd,
"mac access-list WORD <deny|permit> MAC",
"Add a mac access-list\n"
"Add an access list entry\n"
"MAC zebra access-list name\n"
"Specify packets to reject\n"
"Specify packets to forward\n"
"MAC address to match. e.g. 00:01:00:01:00:01\n")
{
return filter_set_zebra(vty, argv[2]->arg, argv[3]->arg, AFI_L2VPN,
argv[4]->arg, 0, 1);
}
DEFUN (no_mac_access_list,
no_mac_access_list_cmd,
"no mac access-list WORD <deny|permit> MAC",
NO_STR
"Remove a mac access-list\n"
"Remove an access list entry\n"
"MAC zebra access-list name\n"
"Specify packets to reject\n"
"Specify packets to forward\n"
"MAC address to match. e.g. 00:01:00:01:00:01\n")
{
return filter_set_zebra(vty, argv[3]->arg, argv[4]->arg, AFI_L2VPN,
argv[5]->arg, 0, 0);
}
DEFUN (mac_access_list_any,
mac_access_list_any_cmd,
"mac access-list WORD <deny|permit> any",
"Add a mac access-list\n"
"Add an access list entry\n"
"MAC zebra access-list name\n"
"Specify packets to reject\n"
"Specify packets to forward\n"
"MAC address to match. e.g. 00:01:00:01:00:01\n")
{
return filter_set_zebra(vty, argv[2]->arg, argv[3]->arg, AFI_L2VPN,
"00:00:00:00:00:00", 0, 1);
}
DEFUN (no_mac_access_list_any,
no_mac_access_list_any_cmd,
"no mac access-list WORD <deny|permit> any",
NO_STR
"Remove a mac access-list\n"
"Remove an access list entry\n"
"MAC zebra access-list name\n"
"Specify packets to reject\n"
"Specify packets to forward\n"
"MAC address to match. e.g. 00:01:00:01:00:01\n")
{
return filter_set_zebra(vty, argv[3]->arg, argv[4]->arg, AFI_L2VPN,
"00:00:00:00:00:00", 0, 0);
}
DEFUN (access_list_exact,
access_list_exact_cmd,
"access-list WORD <deny|permit> A.B.C.D/M [exact-match]",
@ -1666,12 +1739,15 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
filter = &mfilter->u.cfilter;
if (write) {
vty_out(vty, "%s IP%s access list %s\n",
vty_out(vty, "%s %s access list %s\n",
mfilter->cisco ? (filter->extended
? "Extended"
: "Standard")
: "Zebra",
afi == AFI_IP6 ? "v6" : "",
(afi == AFI_IP)
? ("IP")
: ((afi == AFI_IP6) ? ("IPv6 ")
: ("MAC ")),
access->name);
write = 0;
}
@ -1710,12 +1786,15 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
filter = &mfilter->u.cfilter;
if (write) {
vty_out(vty, "%s IP%s access list %s\n",
vty_out(vty, "%s %s access list %s\n",
mfilter->cisco ? (filter->extended
? "Extended"
: "Standard")
: "Zebra",
afi == AFI_IP6 ? "v6" : "",
(afi == AFI_IP)
? ("IP")
: ((afi == AFI_IP6) ? ("IPv6 ")
: ("MAC ")),
access->name);
write = 0;
}
@ -1746,6 +1825,28 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
return CMD_SUCCESS;
}
/* show MAC access list - this only has MAC filters for now*/
DEFUN (show_mac_access_list,
show_mac_access_list_cmd,
"show mac access-list",
SHOW_STR
"mac access lists\n"
"List mac access lists\n")
{
return filter_show(vty, NULL, AFI_L2VPN);
}
DEFUN (show_mac_access_list_name,
show_mac_access_list_name_cmd,
"show mac access-list WORD",
SHOW_STR
"mac access lists\n"
"List mac access lists\n"
"mac address\n")
{
return filter_show(vty, argv[3]->arg, AFI_L2VPN);
}
DEFUN (show_ip_access_list,
show_ip_access_list_cmd,
"show ip access-list",
@ -1844,10 +1945,17 @@ void config_write_access_zebra(struct vty *vty, struct filter *mfilter)
if (p->prefixlen == 0 && !filter->exact)
vty_out(vty, " any");
else
else if (p->family == AF_INET6 || p->family == AF_INET)
vty_out(vty, " %s/%d%s",
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
p->prefixlen, filter->exact ? " exact-match" : "");
else if (p->family == AF_ETHERNET) {
if (p->prefixlen == 0)
vty_out(vty, " any");
else
vty_out(vty, " %s", prefix_mac2str(&(p->u.prefix_eth),
buf, sizeof(buf)));
}
vty_out(vty, "\n");
}
@ -1866,15 +1974,19 @@ static int config_write_access(struct vty *vty, afi_t afi)
for (access = master->num.head; access; access = access->next) {
if (access->remark) {
vty_out(vty, "%saccess-list %s remark %s\n",
afi == AFI_IP ? "" : "ipv6 ", access->name,
access->remark);
(afi == AFI_IP) ? ("")
: ((afi == AFI_IP6) ? ("ipv6 ")
: ("mac ")),
access->name, access->remark);
write++;
}
for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
vty_out(vty, "%saccess-list %s %s",
afi == AFI_IP ? "" : "ipv6 ", access->name,
filter_type_str(mfilter));
(afi == AFI_IP) ? ("")
: ((afi == AFI_IP6) ? ("ipv6 ")
: ("mac ")),
access->name, filter_type_str(mfilter));
if (mfilter->cisco)
config_write_access_cisco(vty, mfilter);
@ -1888,15 +2000,19 @@ static int config_write_access(struct vty *vty, afi_t afi)
for (access = master->str.head; access; access = access->next) {
if (access->remark) {
vty_out(vty, "%saccess-list %s remark %s\n",
afi == AFI_IP ? "" : "ipv6 ", access->name,
access->remark);
(afi == AFI_IP) ? ("")
: ((afi == AFI_IP6) ? ("ipv6 ")
: ("mac ")),
access->name, access->remark);
write++;
}
for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
vty_out(vty, "%saccess-list %s %s",
afi == AFI_IP ? "" : "ipv6 ", access->name,
filter_type_str(mfilter));
(afi == AFI_IP) ? ("")
: ((afi == AFI_IP6) ? ("ipv6 ")
: ("mac ")),
access->name, filter_type_str(mfilter));
if (mfilter->cisco)
config_write_access_cisco(vty, mfilter);
@ -1909,6 +2025,56 @@ static int config_write_access(struct vty *vty, afi_t afi)
return write;
}
static struct cmd_node access_mac_node = {
ACCESS_MAC_NODE, "", /* Access list has no interface. */
1};
static int config_write_access_mac(struct vty *vty)
{
return config_write_access(vty, AFI_L2VPN);
}
static void access_list_reset_mac(void)
{
struct access_list *access;
struct access_list *next;
struct access_master *master;
master = access_master_get(AFI_L2VPN);
if (master == NULL)
return;
for (access = master->num.head; access; access = next) {
next = access->next;
access_list_delete(access);
}
for (access = master->str.head; access; access = next) {
next = access->next;
access_list_delete(access);
}
assert(master->num.head == NULL);
assert(master->num.tail == NULL);
assert(master->str.head == NULL);
assert(master->str.tail == NULL);
}
/* Install vty related command. */
static void access_list_init_mac(void)
{
install_node(&access_mac_node, config_write_access_mac);
install_element(ENABLE_NODE, &show_mac_access_list_cmd);
install_element(ENABLE_NODE, &show_mac_access_list_name_cmd);
/* Zebra access-list */
install_element(CONFIG_NODE, &mac_access_list_cmd);
install_element(CONFIG_NODE, &no_mac_access_list_cmd);
install_element(CONFIG_NODE, &mac_access_list_any_cmd);
install_element(CONFIG_NODE, &no_mac_access_list_any_cmd);
}
/* Access-list node. */
static struct cmd_node access_node = {ACCESS_NODE,
"", /* Access list has no interface. */
@ -2050,10 +2216,12 @@ void access_list_init()
{
access_list_init_ipv4();
access_list_init_ipv6();
access_list_init_mac();
}
void access_list_reset()
{
access_list_reset_ipv4();
access_list_reset_ipv6();
access_list_reset_mac();
}

View File

@ -917,6 +917,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),
DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK),
DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI),
DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW),
DESC_ENTRY(ZEBRA_VNI_ADD),
DESC_ENTRY(ZEBRA_VNI_DEL),
DESC_ENTRY(ZEBRA_REMOTE_VTEP_ADD),

View File

@ -37,390 +37,262 @@ static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
static const struct in6_addr maskbytes6[] = {
/* /0 */ {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /1 */
{{{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /2 */
{{{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /3 */
{{{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /4 */
{{{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /5 */
{{{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /6 */
{{{0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /7 */
{{{0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /8 */
{{{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /9 */
{{{0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /10 */
{{{0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /11 */
{{{0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /12 */
{{{0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /13 */
{{{0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /14 */
{{{0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /15 */
{{{0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /16 */
{{{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /17 */
{{{0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /18 */
{{{0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /19 */
{{{0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /20 */
{{{0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /21 */
{{{0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /22 */
{{{0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /23 */
{{{0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /24 */
{{{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /25 */
{{{0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /26 */
{{{0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /27 */
{{{0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /28 */
{{{0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /29 */
{{{0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /30 */
{{{0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /31 */
{{{0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /32 */
{{{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /33 */
{{{0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /34 */
{{{0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /35 */
{{{0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /36 */
{{{0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /37 */
{{{0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /38 */
{{{0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /39 */
{{{0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /40 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /41 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /42 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /43 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /44 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /45 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /46 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /47 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /48 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /49 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /50 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /51 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /52 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /53 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /54 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /55 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /56 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /57 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /58 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /59 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /60 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /61 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /62 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /63 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /64 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /65 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /66 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /67 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /68 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /69 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /70 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /71 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /72 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /73 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /74 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /75 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /76 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /77 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /78 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /79 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /80 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /81 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /82 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /83 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /84 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /85 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /86 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /87 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /88 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /89 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x00, 0x00}}},
/* /90 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc0, 0x00, 0x00, 0x00, 0x00}}},
/* /91 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0x00, 0x00, 0x00, 0x00}}},
/* /92 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00}}},
/* /93 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x00, 0x00, 0x00, 0x00}}},
/* /94 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x00, 0x00, 0x00}}},
/* /95 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00}}},
/* /96 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00}}},
/* /97 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00}}},
/* /98 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00}}},
/* /99 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xe0, 0x00, 0x00, 0x00}}},
/* /100 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0x00, 0x00, 0x00}}},
/* /101 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x00, 0x00, 0x00}}},
/* /102 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x00, 0x00, 0x00}}},
/* /103 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0x00, 0x00, 0x00}}},
/* /104 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00}}},
/* /105 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00}}},
/* /106 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xc0, 0x00, 0x00}}},
/* /107 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x00, 0x00}}},
/* /108 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00}}},
/* /109 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x00, 0x00}}},
/* /110 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00}}},
/* /111 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00}}},
/* /112 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00}}},
/* /113 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00}}},
/* /114 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x00}}},
/* /115 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00}}},
/* /116 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00}}},
/* /117 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x00}}},
/* /118 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x00}}},
/* /119 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00}}},
/* /120 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00}}},
/* /121 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80}}},
/* /122 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0}}},
/* /123 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0}}},
/* /124 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0}}},
/* /125 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8}}},
/* /126 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc}}},
/* /127 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe}}},
/* /128 */
{{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff}}}};
/* /1 */ {{{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /2 */ {{{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /3 */ {{{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /4 */ {{{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /5 */ {{{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /6 */ {{{0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /7 */ {{{0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /8 */ {{{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /9 */ {{{0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /10 */ {{{0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /11 */ {{{0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /12 */ {{{0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /13 */ {{{0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /14 */ {{{0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /15 */ {{{0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /16 */ {{{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /17 */ {{{0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /18 */ {{{0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /19 */ {{{0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /20 */ {{{0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /21 */ {{{0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /22 */ {{{0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /23 */ {{{0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /24 */ {{{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /25 */ {{{0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /26 */ {{{0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /27 */ {{{0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /28 */ {{{0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /29 */ {{{0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /30 */ {{{0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /31 */ {{{0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /32 */ {{{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /33 */ {{{0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /34 */ {{{0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /35 */ {{{0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /36 */ {{{0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /37 */ {{{0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /38 */ {{{0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /39 */ {{{0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /40 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /41 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /42 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /43 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /44 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /45 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /46 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /47 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /48 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /49 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /50 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /51 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /52 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /53 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /54 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /55 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /56 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /57 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /58 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /59 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /60 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /61 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /62 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /63 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /64 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /65 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /66 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /67 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /68 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /69 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /70 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /71 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /72 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /73 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /74 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /75 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /76 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /77 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /78 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /79 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /80 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /81 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /82 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /83 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /84 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /85 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /86 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /87 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /88 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}}},
/* /89 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00}}},
/* /90 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00}}},
/* /91 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00}}},
/* /92 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00}}},
/* /93 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00}}},
/* /94 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00}}},
/* /95 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00}}},
/* /96 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}}},
/* /97 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00}}},
/* /98 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00}}},
/* /99 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00}}},
/* /100 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00}}},
/* /101 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00}}},
/* /102 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00}}},
/* /103 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00}}},
/* /104 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}},
/* /105 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00}}},
/* /106 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00}}},
/* /107 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00}}},
/* /108 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00}}},
/* /109 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00}}},
/* /110 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00}}},
/* /111 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00}}},
/* /112 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00}}},
/* /113 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00}}},
/* /114 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00}}},
/* /115 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00}}},
/* /116 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00}}},
/* /117 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00}}},
/* /118 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00}}},
/* /119 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00}}},
/* /120 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}}},
/* /121 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80}}},
/* /122 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0}}},
/* /123 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0}}},
/* /124 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0}}},
/* /125 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8}}},
/* /126 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}}},
/* /127 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}}},
/* /128 */ {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}}};
/* Number of bits in prefix type. */
#ifndef PNBBY
@ -429,6 +301,18 @@ static const struct in6_addr maskbytes6[] = {
#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
static int is_zero_mac(const struct ethaddr *mac)
{
int i = 0;
for (i = 0; i < ETH_ALEN; i++) {
if (mac->octet[i])
return 0;
}
return 1;
}
unsigned int prefix_bit(const u_char *prefix, const u_char prefixlen)
{
unsigned int offset = prefixlen / 8;
@ -450,6 +334,8 @@ int str2family(const char *string)
return AF_INET6;
else if (!strcmp("ethernet", string))
return AF_ETHERNET;
else if (!strcmp("evpn", string))
return AF_EVPN;
return -1;
}
@ -462,6 +348,7 @@ int afi2family(afi_t afi)
return AF_INET6;
else if (afi == AFI_L2VPN)
return AF_ETHERNET;
/* NOTE: EVPN code should NOT use this interface. */
return 0;
}
@ -471,7 +358,7 @@ afi_t family2afi(int family)
return AFI_IP;
else if (family == AF_INET6)
return AFI_IP6;
else if (family == AF_ETHERNET)
else if (family == AF_ETHERNET || family == AF_EVPN)
return AFI_L2VPN;
return 0;
}
@ -577,6 +464,9 @@ void prefix_copy(struct prefix *dest, const struct prefix *src)
else if (src->family == AF_INET6)
dest->u.prefix6 = src->u.prefix6;
else if (src->family == AF_ETHERNET) {
memcpy(&dest->u.prefix_eth, &src->u.prefix_eth,
sizeof(struct ethaddr));
} else if (src->family == AF_EVPN) {
memcpy(&dest->u.prefix_evpn, &src->u.prefix_evpn,
sizeof(struct evpn_addr));
} else if (src->family == AF_UNSPEC) {
@ -615,6 +505,10 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2)
&p2->u.prefix6.s6_addr))
return 1;
if (p1->family == AF_ETHERNET)
if (!memcmp(&p1->u.prefix_eth, &p2->u.prefix_eth,
sizeof(struct ethaddr)))
return 1;
if (p1->family == AF_EVPN)
if (!memcmp(&p1->u.prefix_evpn, &p2->u.prefix_evpn,
sizeof(struct evpn_addr)))
return 1;
@ -679,6 +573,8 @@ int prefix_common_bits(const struct prefix *p1, const struct prefix *p2)
if (p1->family == AF_INET6)
length = IPV6_MAX_BYTELEN;
if (p1->family == AF_ETHERNET)
length = ETH_ALEN;
if (p1->family == AF_EVPN)
length = 8 * sizeof(struct evpn_addr);
if (p1->family != p2->family || !length)
@ -707,6 +603,8 @@ const char *prefix_family_str(const struct prefix *p)
return "inet6";
if (p->family == AF_ETHERNET)
return "ether";
if (p->family == AF_EVPN)
return "evpn";
return "unspec";
}
@ -783,6 +681,13 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
const char *str_addr = str;
unsigned int a[6];
int i;
bool slash = false;
if (!strcmp(str, "any")) {
memset(p, 0, sizeof(*p));
p->family = AF_ETHERNET;
return 1;
}
/* Find slash inside string. */
pnt = strchr(str, '/');
@ -800,6 +705,7 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
*(cp + (pnt - str)) = '\0';
str_addr = cp;
slash = true;
}
/* Convert string to prefix. */
@ -814,6 +720,15 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
}
p->prefixlen = plen;
p->family = AF_ETHERNET;
/*
* special case to allow old configurations to work
* Since all zero's is implicitly meant to allow
* a comparison to zero, let's assume
*/
if (!slash && is_zero_mac(&(p->eth_addr)))
p->prefixlen = 0;
ret = 1;
done:
@ -1063,6 +978,7 @@ int prefix_blen(const struct prefix *p)
break;
case AF_ETHERNET:
return ETH_ALEN;
break;
}
return 0;
}
@ -1090,7 +1006,7 @@ int str2prefix(const char *str, struct prefix *p)
return 0;
}
static const char *prefixeth2str(const struct prefix *p, char *str, int size)
static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
{
u_char family;
char buf[PREFIX2STR_BUFFER];
@ -1134,12 +1050,8 @@ static const char *prefixeth2str(const struct prefix *p, char *str, int size)
PREFIX2STR_BUFFER),
p->prefixlen);
} else {
sprintf(str, "UNK AF_ETHER prefix");
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d",
p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1],
p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3],
p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5],
p->prefixlen);
sprintf(str, "Unsupported EVPN route type %d",
p->u.prefix_evpn.route_type);
}
return str;
@ -1159,7 +1071,13 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
break;
case AF_ETHERNET:
prefixeth2str(p, str, size);
snprintf(str, size, "%s/%d",
prefix_mac2str(&p->u.prefix_eth, buf, sizeof(buf)),
p->prefixlen);
break;
case AF_EVPN:
prefixevpn2str(p, str, size);
break;
default:

View File

@ -116,7 +116,18 @@ struct evpn_addr {
#endif
#endif
/* IPv4 and IPv6 unified prefix structure. */
/* The 'family' in the prefix structure is internal to FRR and need not
* map to standard OS AF_ definitions except where needed for interacting
* with the kernel. However, AF_ definitions are currently in use and
* prevalent across the code. Define a new FRR-specific AF for EVPN to
* distinguish between 'ethernet' (MAC-only) and 'evpn' prefixes and
* ensure it does not conflict with any OS AF_ definition.
*/
#if !defined(AF_EVPN)
#define AF_EVPN (AF_MAX + 1)
#endif
/* FRR generic prefix structure. */
struct prefix {
u_char family;
u_char prefixlen;
@ -131,7 +142,7 @@ struct prefix {
struct ethaddr prefix_eth; /* AF_ETHERNET */
u_char val[8];
uintptr_t ptr;
struct evpn_addr prefix_evpn;
struct evpn_addr prefix_evpn; /* AF_EVPN */
} u __attribute__((aligned(8)));
};
@ -356,6 +367,7 @@ static inline int ipv6_martian(struct in6_addr *addr)
}
extern int all_digit(const char *);
extern int macstr2prefix_evpn(const char *str, struct prefix_evpn *p);
/* NOTE: This routine expects the address argument in network byte order. */
static inline int ipv4_martian(struct in_addr *addr)

View File

@ -111,6 +111,7 @@ typedef enum {
ZEBRA_FEC_REGISTER,
ZEBRA_FEC_UNREGISTER,
ZEBRA_FEC_UPDATE,
ZEBRA_ADVERTISE_DEFAULT_GW,
ZEBRA_ADVERTISE_ALL_VNI,
ZEBRA_VNI_ADD,
ZEBRA_VNI_DEL,
@ -305,6 +306,10 @@ struct zapi_pw_status {
uint32_t status;
};
/* Zebra MAC types */
#define ZEBRA_MAC_TYPE_STICKY 0x01 /* Sticky MAC*/
#define ZEBRA_MAC_TYPE_GW 0x02 /* gateway (SVI) mac*/
/* Prototypes of zebra client service functions. */
extern struct zclient *zclient_new(struct thread_master *);
extern void zclient_init(struct zclient *, int, u_short);

View File

@ -432,6 +432,8 @@ end
ctx_keys.append("address-family ipv6 unicast")
elif line == "address-family ipv4":
ctx_keys.append("address-family ipv4 unicast")
elif line == "address-family evpn":
ctx_keys.append("address-family l2vpn evpn")
else:
ctx_keys.append(line)
@ -745,6 +747,37 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, None))
lines_to_add_to_del.append(((tmpline,), None))
if (len(ctx_keys) == 3 and
ctx_keys[0].startswith('router bgp') and
ctx_keys[1] == 'address-family l2vpn evpn' and
ctx_keys[2].startswith('vni')):
re_route_target = re.search('^route-target import (.*)$', line) if line is not None else False
if re_route_target:
rt = re_route_target.group(1).strip()
route_target_import_line = line
route_target_export_line = "route-target export %s" % rt
route_target_both_line = "route-target both %s" % rt
found_route_target_export_line = line_exist(lines_to_del, ctx_keys, route_target_export_line)
found_route_target_both_line = line_exist(lines_to_add, ctx_keys, route_target_both_line)
'''
If the running configs has
route-target import 1:1
route-target export 1:1
and the config we are reloading against has
route-target both 1:1
then we can ignore deleting the import/export and ignore adding the 'both'
'''
if found_route_target_export_line and found_route_target_both_line:
lines_to_del_to_del.append((ctx_keys, route_target_import_line))
lines_to_del_to_del.append((ctx_keys, route_target_export_line))
lines_to_add_to_del.append((ctx_keys, route_target_both_line))
if not deleted:
found_add_line = line_exist(lines_to_add, ctx_keys, line)
@ -822,6 +855,13 @@ def compare_context_objects(newconf, running):
elif "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) > 1 and delete_bgpd:
continue
# Delete an entire vni sub-context under "address-family l2vpn evpn"
elif ("router bgp" in running_ctx_keys[0] and
len(running_ctx_keys) > 2 and
running_ctx_keys[1].startswith('address-family l2vpn evpn') and
running_ctx_keys[2].startswith('vni ')):
lines_to_del.append((running_ctx_keys, None))
elif ("router bgp" in running_ctx_keys[0] and
len(running_ctx_keys) > 1 and
running_ctx_keys[1].startswith('address-family')):

View File

@ -1164,7 +1164,7 @@ DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
}
#if defined(HAVE_CUMULUS)
DEFUNSH(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd,
DEFUNSH_HIDDEN(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd,
"address-family evpn",
"Enter Address Family command mode\n"
"EVPN Address family\n")

View File

@ -224,6 +224,10 @@ void vtysh_config_parse_line(void *arg, const char *line)
strlen("ipv6 access-list"))
== 0)
config = config_get(ACCESS_IPV6_NODE, line);
else if (strncmp(line, "mac access-list",
strlen("mac access-list"))
== 0)
config = config_get(ACCESS_MAC_NODE, line);
else if (strncmp(line, "ip prefix-list",
strlen("ip prefix-list"))
== 0)
@ -302,9 +306,10 @@ void vtysh_config_parse_line(void *arg, const char *line)
#define NO_DELIMITER(I) \
((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
|| (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE \
|| (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \
|| (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \
|| (I) == AAA_NODE || (I) == VRF_DEBUG_NODE || (I) == MPLS_NODE)
|| (I) == ACCESS_IPV6_NODE || (I) == ACCESS_MAC_NODE \
|| (I) == PREFIX_IPV6_NODE || (I) == SERVICE_NODE \
|| (I) == FORWARDING_NODE || (I) == DEBUG_NODE || (I) == AAA_NODE \
|| (I) == VRF_DEBUG_NODE || (I) == MPLS_NODE)
/* Display configuration to file pointer. */
void vtysh_config_dump(FILE *fp)

View File

@ -251,6 +251,8 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
*zif_type = ZEBRA_IF_VLAN;
else if (strcmp(kind, "vxlan") == 0)
*zif_type = ZEBRA_IF_VXLAN;
else if (strcmp(kind, "macvlan") == 0)
*zif_type = ZEBRA_IF_MACVLAN;
}
// Temporary Assignments to compile on older platforms.
@ -401,15 +403,18 @@ static int get_iflink_speed(const char *ifname)
/* use ioctl to get IP address of an interface */
sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sd < 0) {
zlog_debug("Failure to read interface %s speed: %d %s", ifname,
errno, safe_strerror(errno));
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Failure to read interface %s speed: %d %s",
ifname, errno, safe_strerror(errno));
return 0;
}
/* Get the current link state for the interface */
rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata);
if (rc < 0) {
zlog_debug("IOCTL failure to read interface %s speed: %d %s",
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"IOCTL failure to read interface %s speed: %d %s",
ifname, errno, safe_strerror(errno));
ecmd.speed_hi = 0;
ecmd.speed = 0;

View File

@ -190,6 +190,7 @@ typedef enum {
ZEBRA_IF_VRF, /* VRF device */
ZEBRA_IF_BRIDGE, /* bridge device */
ZEBRA_IF_VLAN, /* VLAN sub-interface */
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
ZEBRA_IF_OTHER, /* Anything else */
} zebra_iftype_t;
@ -295,6 +296,9 @@ static inline void zebra_if_set_ziftype(struct interface *ifp,
#define IS_ZEBRA_IF_VXLAN(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN)
#define IS_ZEBRA_IF_MACVLAN(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_MACVLAN)
#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type \
== ZEBRA_IF_SLAVE_BRIDGE)

View File

@ -41,6 +41,7 @@
#include "zebra/debug.h"
#include "zebra/router-id.h"
#include "zebra/zebra_memory.h"
#include "zebra/zebra_vxlan.h"
#define ZEBRA_PTM_SUPPORT
@ -402,6 +403,8 @@ void zebra_interface_address_add_update(struct interface *ifp,
zlog_warn(
"WARNING: advertising address to clients that is not yet usable.");
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 1);
router_id_add_address(ifc);
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
@ -428,6 +431,8 @@ void zebra_interface_address_delete_update(struct interface *ifp,
prefix2str(p, buf, sizeof(buf)), ifc->ifp->name);
}
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0);
router_id_del_address(ifc);
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))

View File

@ -1321,8 +1321,8 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
default:
break;
}
vty_out(vty, "%s",
CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) ? " (installed)"
vty_out(vty, "%s", CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
? " (installed)"
: "");
vty_out(vty, "\n");
}
@ -2807,6 +2807,8 @@ void zebra_mpls_close_tables(struct zebra_vrf *zvrf)
hash_free(zvrf->lsp_table);
hash_clean(zvrf->slsp_table, NULL);
hash_free(zvrf->slsp_table);
route_table_finish(zvrf->fec_table[AFI_IP]);
route_table_finish(zvrf->fec_table[AFI_IP6]);
}
/*

View File

@ -107,6 +107,11 @@ struct zebra_vrf {
*/
int advertise_all_vni;
/*
* Whether we are advertising g/w macip in EVPN or not.
*/
int advertise_gw_macip;
/* Route Installs */
uint64_t installs;
uint64_t removals;

View File

@ -2285,89 +2285,100 @@ DEFUN (show_vrf,
DEFUN (show_evpn_vni,
show_evpn_vni_cmd,
"show evpn vni",
"show evpn vni [json]",
SHOW_STR
"EVPN\n"
"VxLAN information\n")
"VxLAN information\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
u_char uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_vnis(vty, zvrf);
zebra_vxlan_print_vnis(vty, zvrf, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_vni_vni,
show_evpn_vni_vni_cmd,
"show evpn vni " CMD_VNI_RANGE,
"show evpn vni " CMD_VNI_RANGE "[json]",
SHOW_STR
"EVPN\n"
"VxLAN Network Identifier\n"
"VNI number\n")
"VNI number\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
u_char uj = use_json(argc, argv);
vni = strtoul(argv[3]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_vni(vty, zvrf, vni);
zebra_vxlan_print_vni(vty, zvrf, vni, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni,
show_evpn_mac_vni_cmd,
"show evpn mac vni " CMD_VNI_RANGE,
"show evpn mac vni " CMD_VNI_RANGE "[json]",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"VNI number\n")
"VNI number\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
u_char uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_vni(vty, zvrf, vni);
zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni_all,
show_evpn_mac_vni_all_cmd,
"show evpn mac vni all",
"show evpn mac vni all [json]",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"All VNIs\n")
"All VNIs\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
u_char uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_all_vni(vty, zvrf);
zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni_all_vtep,
show_evpn_mac_vni_all_vtep_cmd,
"show evpn mac vni all vtep A.B.C.D",
"show evpn mac vni all vtep A.B.C.D [json]",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"All VNIs\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
"Remote VTEP IP address\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
struct in_addr vtep_ip;
u_char uj = use_json(argc, argv);
if (!inet_aton(argv[6]->arg, &vtep_ip)) {
if (!uj)
vty_out(vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip);
zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
return CMD_SUCCESS;
}
@ -2400,112 +2411,125 @@ DEFUN (show_evpn_mac_vni_mac,
DEFUN (show_evpn_mac_vni_vtep,
show_evpn_mac_vni_vtep_cmd,
"show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D",
"show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
"Remote VTEP IP address\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
struct in_addr vtep_ip;
u_char uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
if (!inet_aton(argv[6]->arg, &vtep_ip)) {
if (!uj)
vty_out(vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip);
zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni,
show_evpn_neigh_vni_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE,
"show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n")
"VNI number\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
u_char uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_vni(vty, zvrf, vni);
zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni_all,
show_evpn_neigh_vni_all_cmd,
"show evpn arp-cache vni all",
"show evpn arp-cache vni all [json]",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"All VNIs\n")
"All VNIs\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
u_char uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_all_vni(vty, zvrf);
zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni_neigh,
show_evpn_neigh_vni_neigh_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD",
"show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Neighbor\n"
"Neighbor address (IPv4 or IPv6 address)\n")
"Neighbor address (IPv4 or IPv6 address)\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
struct ipaddr ip;
u_char uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
if (str2ipaddr(argv[6]->arg, &ip) != 0) {
if (!uj)
vty_out(vty, "%% Malformed Neighbor address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip);
zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni_vtep,
show_evpn_neigh_vni_vtep_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D",
"show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
"Remote VTEP IP address\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
struct in_addr vtep_ip;
u_char uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
if (!inet_aton(argv[6]->arg, &vtep_ip)) {
if (!uj)
vty_out(vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip);
zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
return CMD_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -41,33 +41,44 @@
#define ZEBRA_VXLIF_MASTER_CHANGE 0x2
#define ZEBRA_VXLIF_VLAN_CHANGE 0x4
#define VNI_STR_LEN 32
extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni);
vni_t vni, u_char use_json);
extern void zebra_vxlan_print_macs_all_vni(struct vty *vty,
struct zebra_vrf *zvrf);
struct zebra_vrf *zvrf,
u_char use_json);
extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
struct zebra_vrf *zvrf,
struct in_addr vtep_ip);
struct in_addr vtep_ip,
u_char use_json);
extern void zebra_vxlan_print_specific_mac_vni(struct vty *vty,
struct zebra_vrf *zvrf,
vni_t vni, struct ethaddr *mac);
extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni,
struct in_addr vtep_ip);
struct in_addr vtep_ip,
u_char use_json);
extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni);
vni_t vni, u_char use_json);
extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty,
struct zebra_vrf *zvrf);
struct zebra_vrf *zvrf,
u_char use_json);
extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
struct zebra_vrf *zvrf,
vni_t vni, struct ipaddr *ip);
vni_t vni, struct ipaddr *ip,
u_char use_json);
extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni,
struct in_addr vtep_ip);
struct in_addr vtep_ip,
u_char use_json);
extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni);
extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf);
vni_t vni, u_char use_json);
extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
u_char use_json);
extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
int add);
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
extern int zebra_vxlan_svi_down(struct interface *ifp,
struct interface *link_if);
@ -104,6 +115,9 @@ extern int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock,
u_short length,
struct zebra_vrf *zvrf);

View File

@ -63,6 +63,9 @@ struct zebra_vni_t_ {
/* VNI - key */
vni_t vni;
/* Flag for advertising gw macip */
u_int8_t advertise_gw_macip;
/* Corresponding VxLAN interface. */
struct interface *vxlan_if;
@ -112,6 +115,9 @@ struct zebra_mac_t_ {
} fwd_info;
u_int32_t neigh_refcnt;
/* List of neigh associated with this mac */
struct list *neigh_list;
};
/*
@ -134,8 +140,19 @@ struct mac_walk_ctx {
struct vty *vty; /* Used by VTY handlers */
u_int32_t count; /* Used by VTY handlers */
struct json_object *json; /* Used for JSON Output */
};
enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
#define IS_ZEBRA_NEIGH_ACTIVE(n) n->state == ZEBRA_NEIGH_ACTIVE
#define IS_ZEBRA_NEIGH_INACTIVE(n) n->state == ZEBRA_NEIGH_INACTIVE
#define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE
#define ZEBRA_NEIGH_SET_INACTIVE(n) n->state = ZEBRA_NEIGH_INACTIVE
/*
* Neighbor hash table.
*
@ -161,6 +178,8 @@ struct zebra_neigh_t_ {
#define ZEBRA_NEIGH_LOCAL 0x01
#define ZEBRA_NEIGH_REMOTE 0x02
enum zebra_neigh_state state;
/* Remote VTEP IP - applicable only for remote neighbors. */
struct in_addr r_vtep_ip;
};
@ -186,6 +205,7 @@ struct neigh_walk_ctx {
struct vty *vty; /* Used by VTY handlers */
u_int32_t count; /* Used by VTY handlers */
u_char addr_width; /* Used by VTY handlers */
struct json_object *json; /* Used for JSON Output */
};
#endif /* _ZEBRA_VXLAN_PRIVATE_H */

View File

@ -2533,6 +2533,9 @@ static int zebra_client_read(struct thread *thread)
case ZEBRA_FEC_UNREGISTER:
zserv_fec_unregister(client, sock, length);
break;
case ZEBRA_ADVERTISE_DEFAULT_GW:
zebra_vxlan_advertise_gw_macip(client, sock, length, zvrf);
break;
case ZEBRA_ADVERTISE_ALL_VNI:
zebra_vxlan_advertise_all_vni(client, sock, length, zvrf);
break;