Merge pull request #2665 from chiragshah6/evpn_dev

bgpd: support evpn nd ext community
This commit is contained in:
Russ White 2018-07-24 11:55:08 -04:00 committed by GitHub
commit bbc7adf1b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 167 additions and 30 deletions

View File

@ -1890,6 +1890,16 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
/* Check if this is a Gateway MAC-IP advertisement */ /* Check if this is a Gateway MAC-IP advertisement */
attr->default_gw = bgp_attr_default_gw(attr); attr->default_gw = bgp_attr_default_gw(attr);
/* Handle scenario where router flag ecommunity is not
* set but default gw ext community is present.
* Use default gateway, set and propogate R-bit.
*/
if (attr->default_gw)
attr->router_flag = 1;
/* Check EVPN Neighbor advertisement flags, R-bit */
bgp_attr_evpn_na_flag(attr, &attr->router_flag);
/* Extract the Rmac, if any */ /* Extract the Rmac, if any */
bgp_attr_rmac(attr, &attr->rmac); bgp_attr_rmac(attr, &attr->rmac);

View File

@ -185,6 +185,9 @@ struct attr {
/* Flag for default gateway extended community in EVPN */ /* Flag for default gateway extended community in EVPN */
uint8_t default_gw; uint8_t default_gw;
/* NA router flag (R-bit) support in EVPN */
uint8_t router_flag;
/* route tag */ /* route tag */
route_tag_t tag; route_tag_t tag;

View File

@ -210,6 +210,39 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
return 0; return 0;
} }
/*
* return true if attr contains router flag extended community
*/
void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag)
{
struct ecommunity *ecom;
int i;
uint8_t val;
ecom = attr->ecommunity;
if (!ecom || !ecom->size)
return;
/* If there is a evpn na extendd community set router_flag */
for (i = 0; i < ecom->size; i++) {
uint8_t *pnt;
uint8_t type, sub_type;
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
type = *pnt++;
sub_type = *pnt++;
if (type == ECOMMUNITY_ENCODE_EVPN &&
sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
val = *pnt++;
if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) {
*router_flag = 1;
break;
}
}
}
}
/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */ /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
struct prefix *dst) struct prefix *dst)

View File

@ -65,4 +65,6 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
uint8_t *sticky); uint8_t *sticky);
extern uint8_t bgp_attr_default_gw(struct attr *attr); extern uint8_t bgp_attr_default_gw(struct attr *attr);
extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */ #endif /* _QUAGGA_BGP_ATTR_EVPN_H */

View File

@ -48,8 +48,11 @@
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02 #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d #define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01 #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02
/* Low-order octet of the Extended Communities type field for OPAQUE types */ /* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c

View File

@ -730,10 +730,13 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
struct ecommunity ecom_sticky; struct ecommunity ecom_sticky;
struct ecommunity ecom_default_gw; struct ecommunity ecom_default_gw;
struct ecommunity ecom_rmac; struct ecommunity ecom_rmac;
struct ecommunity ecom_na;
struct ecommunity_val eval; struct ecommunity_val eval;
struct ecommunity_val eval_sticky; struct ecommunity_val eval_sticky;
struct ecommunity_val eval_default_gw; struct ecommunity_val eval_default_gw;
struct ecommunity_val eval_rmac; struct ecommunity_val eval_rmac;
struct ecommunity_val eval_na;
bgp_encap_types tnl_type; bgp_encap_types tnl_type;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct ecommunity *ecom; struct ecommunity *ecom;
@ -798,6 +801,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
ecommunity_merge(attr->ecommunity, &ecom_default_gw); ecommunity_merge(attr->ecommunity, &ecom_default_gw);
} }
if (attr->router_flag) {
memset(&ecom_na, 0, sizeof(ecom_na));
encode_na_flag_extcomm(&eval_na, attr->router_flag);
ecom_na.size = 1;
ecom_na.val = (uint8_t *)eval_na.val;
attr->ecommunity = ecommunity_merge(attr->ecommunity,
&ecom_na);
}
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
} }
@ -1089,6 +1101,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
{ {
struct bgp_info *old_select, *new_select; struct bgp_info *old_select, *new_select;
struct bgp_info_pair old_and_new; struct bgp_info_pair old_and_new;
struct prefix_evpn *evp;
afi_t afi = AFI_L2VPN; afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN; safi_t safi = SAFI_EVPN;
int ret = 0; int ret = 0;
@ -1100,6 +1113,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
old_select = old_and_new.old; old_select = old_and_new.old;
new_select = old_and_new.new; new_select = old_and_new.new;
evp = (struct prefix_evpn *)&rn->p;
/* If the best path hasn't changed - see if there is still something to /* If the best path hasn't changed - see if there is still something to
* update * update
* to zebra RIB. * to zebra RIB.
@ -1115,6 +1129,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
if (old_select->attr->default_gw) if (old_select->attr->default_gw)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
if (is_evpn_prefix_ipaddr_v6(evp) &&
old_select->attr->router_flag)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
ret = evpn_zebra_install( ret = evpn_zebra_install(
bgp, vpn, (struct prefix_evpn *)&rn->p, bgp, vpn, (struct prefix_evpn *)&rn->p,
old_select->attr->nexthop, flags); old_select->attr->nexthop, flags);
@ -1148,6 +1166,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
if (new_select->attr->default_gw) if (new_select->attr->default_gw)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
if (is_evpn_prefix_ipaddr_v6(evp) &&
new_select->attr->router_flag)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
new_select->attr->nexthop, flags); new_select->attr->nexthop, flags);
/* If an old best existed and it was a "local" route, the only /* If an old best existed and it was a "local" route, the only
@ -1695,6 +1717,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0; attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0;
attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0; attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
attr.router_flag = CHECK_FLAG(flags,
ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? 1 : 0;
/* PMSI is only needed for type-3 routes */ /* PMSI is only needed for type-3 routes */
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
@ -1993,11 +2017,13 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky, 0, 1, &ri, &attr_sticky, 0, 1, &ri,
0); 0);
else if (evpn_route_is_def_gw(bgp, rn)) else if (evpn_route_is_def_gw(bgp, rn)) {
if (is_evpn_prefix_ipaddr_v6(evp))
attr_def_gw.router_flag = 1;
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_def_gw, 0, 1, &ri, &attr_def_gw, 0, 1, &ri,
0); 0);
else } else
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr, 0, 1, &ri, 0); &attr, 0, 1, &ri, 0);
} }

View File

@ -311,6 +311,16 @@ static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq,
eval->val[7] = seq & 0xff; eval->val[7] = seq & 0xff;
} }
static inline void encode_na_flag_extcomm(struct ecommunity_val *eval,
uint8_t na_flag)
{
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ND;
if (na_flag)
eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG;
}
static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
struct prefix *ip) struct prefix *ip)
{ {

View File

@ -448,6 +448,8 @@ enum zapi_iptable_notify_owner {
/* Zebra MAC types */ /* Zebra MAC types */
#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/ #define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/ #define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */
#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */
struct zclient_options { struct zclient_options {
bool receive_notify; bool receive_notify;

View File

@ -122,7 +122,7 @@ extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
int local); int local);
extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac); struct ethaddr *mac, uint8_t flags);
extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip); extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
/* /*

View File

@ -2159,6 +2159,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
char buf2[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN];
int mac_present = 0; int mac_present = 0;
uint8_t ext_learned; uint8_t ext_learned;
uint8_t router_flag;
ndm = NLMSG_DATA(h); ndm = NLMSG_DATA(h);
@ -2249,6 +2250,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
} }
ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0;
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug( zlog_debug(
@ -2271,7 +2273,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (ndm->ndm_state & NUD_VALID) if (ndm->ndm_state & NUD_VALID)
return zebra_vxlan_handle_kernel_neigh_update( return zebra_vxlan_handle_kernel_neigh_update(
ifp, link_if, &ip, &mac, ndm->ndm_state, ifp, link_if, &ip, &mac, ndm->ndm_state,
ext_learned); ext_learned, router_flag);
return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip); return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
} }
@ -2405,7 +2407,8 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
} }
static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac, uint32_t flags, int cmd) struct ethaddr *mac, uint8_t flags,
uint16_t state, int cmd)
{ {
struct { struct {
struct nlmsghdr n; struct nlmsghdr n;
@ -2428,11 +2431,10 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
req.ndm.ndm_state = flags; req.ndm.ndm_state = state;
req.ndm.ndm_ifindex = ifp->ifindex; req.ndm.ndm_ifindex = ifp->ifindex;
req.ndm.ndm_type = RTN_UNICAST; req.ndm.ndm_type = RTN_UNICAST;
req.ndm.ndm_flags = NTF_EXT_LEARNED; req.ndm.ndm_flags = flags;
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
@ -2440,12 +2442,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s", zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x",
nl_msg_type_to_str(cmd), nl_msg_type_to_str(cmd),
nl_family_to_str(req.ndm.ndm_family), ifp->name, nl_family_to_str(req.ndm.ndm_family), ifp->name,
ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)), ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
: "null"); : "null", flags);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0); 0);
@ -2466,14 +2468,15 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
} }
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac) struct ethaddr *mac, uint8_t flags)
{ {
return netlink_neigh_update2(ifp, ip, mac, NUD_NOARP, RTM_NEWNEIGH); return netlink_neigh_update2(ifp, ip, mac, flags,
NUD_NOARP, RTM_NEWNEIGH);
} }
int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
{ {
return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH); return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
} }
/* /*

View File

@ -462,7 +462,7 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
} }
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac) struct ethaddr *mac, uint8_t flags)
{ {
return 0; return 0;
} }

View File

@ -33,6 +33,9 @@
#include "jhash.h" #include "jhash.h"
#include "vlan.h" #include "vlan.h"
#include "vxlan.h" #include "vxlan.h"
#ifdef GNU_LINUX
#include <linux/neighbour.h>
#endif
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/rt.h" #include "zebra/rt.h"
@ -282,6 +285,7 @@ static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt)
ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf); ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf);
if (width > wctx->addr_width) if (width > wctx->addr_width)
wctx->addr_width = width; wctx->addr_width = width;
} }
/* /*
@ -327,6 +331,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
else else
json_object_boolean_true_add(json, "defaultGateway"); json_object_boolean_true_add(json, "defaultGateway");
} }
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
if (!json)
vty_out(vty, " Router");
}
if (json == NULL) if (json == NULL)
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
@ -432,11 +440,11 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
return; return;
} }
num_neigh = hashcount(zvni->neigh_table); num_neigh = hashcount(zvni->neigh_table);
if (json == NULL) if (json == NULL) {
vty_out(vty, vty_out(vty,
"\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
zvni->vni, num_neigh); zvni->vni, num_neigh);
else { } else {
json_vni = json_object_new_object(); json_vni = json_object_new_object();
json_object_int_add(json_vni, "numArpNd", num_neigh); json_object_int_add(json_vni, "numArpNd", num_neigh);
snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni); snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
@ -458,9 +466,10 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
wctx.json = json_vni; wctx.json = json_vni;
hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
if (json == NULL) if (json == NULL) {
vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
"Type", "MAC", "Remote VTEP"); "Type", "MAC", "Remote VTEP");
}
hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
if (json) if (json)
@ -1556,6 +1565,9 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW)) if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
/* Set router flag (R-bit) based on local neigh entry add */
if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
ZEBRA_MACIP_ADD); ZEBRA_MACIP_ADD);
@ -1579,6 +1591,8 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
struct zebra_if *zif; struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl; struct zebra_l2info_vxlan *vxl;
struct interface *vlan_if; struct interface *vlan_if;
uint8_t flags;
int ret = 0;
if (!(n->flags & ZEBRA_NEIGH_REMOTE)) if (!(n->flags & ZEBRA_NEIGH_REMOTE))
return 0; return 0;
@ -1591,8 +1605,13 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
if (!vlan_if) if (!vlan_if)
return -1; return -1;
#ifdef GNU_LINUX
return kernel_add_neigh(vlan_if, &n->ip, &n->emac); flags = NTF_EXT_LEARNED;
if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
flags |= NTF_ROUTER;
ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags);
#endif
return ret;
} }
/* /*
@ -1814,6 +1833,9 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
/* Set "local" forwarding info. */ /* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW); SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
/* Set Router flag (R-bit) */
if (ip->ipa_type == IPADDR_V6)
SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
memcpy(&n->emac, macaddr, ETH_ALEN); memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex; n->ifindex = ifp->ifindex;
@ -1823,10 +1845,10 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug( zlog_debug(
"SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP", "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
ifp->name, ifp->ifindex, zvni->vni, ifp->name, ifp->ifindex, zvni->vni,
prefix_mac2str(macaddr, buf, sizeof(buf)), prefix_mac2str(macaddr, buf, sizeof(buf)),
ipaddr2str(ip, buf2, sizeof(buf2))); ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
@ -1969,7 +1991,8 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
static int zvni_local_neigh_update(zebra_vni_t *zvni, static int zvni_local_neigh_update(zebra_vni_t *zvni,
struct interface *ifp, struct interface *ifp,
struct ipaddr *ip, struct ipaddr *ip,
struct ethaddr *macaddr) struct ethaddr *macaddr,
uint8_t router_flag)
{ {
char buf[ETHER_ADDR_STRLEN]; char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN];
@ -2087,15 +2110,19 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
return 0; return 0;
} }
/*Set router flag (R-bit) */
if (router_flag)
SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
/* Inform BGP. */ /* Inform BGP. */
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u", zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
ipaddr2str(ip, buf2, sizeof(buf2)), ipaddr2str(ip, buf2, sizeof(buf2)),
prefix_mac2str(macaddr, buf, sizeof(buf)), prefix_mac2str(macaddr, buf, sizeof(buf)),
zvni->vni); zvni->vni, n->flags);
ZEBRA_NEIGH_SET_ACTIVE(n); ZEBRA_NEIGH_SET_ACTIVE(n);
return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0); return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
} }
static int zvni_remote_neigh_update(zebra_vni_t *zvni, static int zvni_remote_neigh_update(zebra_vni_t *zvni,
@ -3366,14 +3393,22 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
*/ */
static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
{ {
uint8_t flags;
int ret = 0;
if (!is_l3vni_oper_up(zl3vni)) if (!is_l3vni_oper_up(zl3vni))
return -1; return -1;
if (!(n->flags & ZEBRA_NEIGH_REMOTE) if (!(n->flags & ZEBRA_NEIGH_REMOTE)
|| !(n->flags & ZEBRA_NEIGH_REMOTE_NH)) || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
return 0; return 0;
#ifdef GNU_LINUX
return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac); flags = NTF_EXT_LEARNED;
if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
flags |= NTF_ROUTER;
ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags);
#endif
return ret;
} }
/* /*
@ -4517,9 +4552,11 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
wctx.zvni = zvni; wctx.zvni = zvni;
wctx.vty = vty; wctx.vty = vty;
wctx.addr_width = 15;
wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
wctx.r_vtep_ip = vtep_ip; wctx.r_vtep_ip = vtep_ip;
wctx.json = json; wctx.json = json;
hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
if (use_json) { if (use_json) {
@ -4948,7 +4985,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
struct ipaddr *ip, struct ipaddr *ip,
struct ethaddr *macaddr, struct ethaddr *macaddr,
uint16_t state, uint16_t state,
uint8_t ext_learned) uint8_t ext_learned,
uint8_t router_flag)
{ {
char buf[ETHER_ADDR_STRLEN]; char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN];
@ -4979,7 +5017,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
/* Is this about a local neighbor or a remote one? */ /* Is this about a local neighbor or a remote one? */
if (!ext_learned) if (!ext_learned)
return zvni_local_neigh_update(zvni, ifp, ip, macaddr); return zvni_local_neigh_update(zvni, ifp, ip, macaddr,
router_flag);
return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state); return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
} }
@ -5366,6 +5405,10 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
n->r_vtep_ip = vtep_ip; n->r_vtep_ip = vtep_ip;
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
/* Set router flag (R-bit) to this Neighbor entry */
if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
/* Install the entry. */ /* Install the entry. */
zvni_neigh_install(zvni, n); zvni_neigh_install(zvni, n);
} }

View File

@ -124,7 +124,8 @@ extern int zebra_vxlan_svi_down(struct interface *ifp,
struct interface *link_if); struct interface *link_if);
extern int zebra_vxlan_handle_kernel_neigh_update( extern int zebra_vxlan_handle_kernel_neigh_update(
struct interface *ifp, struct interface *link_if, struct ipaddr *ip, struct interface *ifp, struct interface *link_if, struct ipaddr *ip,
struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned); struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned,
uint8_t router_flag);
extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
struct interface *link_if, struct interface *link_if,
struct ipaddr *ip); struct ipaddr *ip);

View File

@ -331,6 +331,7 @@ struct zebra_neigh_t_ {
#define ZEBRA_NEIGH_REMOTE 0x02 #define ZEBRA_NEIGH_REMOTE 0x02
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */ #define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
#define ZEBRA_NEIGH_DEF_GW 0x08 #define ZEBRA_NEIGH_DEF_GW 0x08
#define ZEBRA_NEIGH_ROUTER_FLAG 0x10
enum zebra_neigh_state state; enum zebra_neigh_state state;