]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: support evpn nd ext community 2665/head
authorChirag Shah <chirag@cumulusnetworks.com>
Sat, 7 Jul 2018 04:46:46 +0000 (21:46 -0700)
committerChirag Shah <chirag@cumulusnetworks.com>
Tue, 17 Jul 2018 20:06:41 +0000 (13:06 -0700)
EVPN ND ext community support NA flag R-bit, to have proxy ND.

Set R-bit in EVPN NA if a given router is default gateway or there is a
local
router attached, which can be determine based on local neighbor entry.

Implement BGP ext community attribute to generate and parse  R-bit and
pass along zebra to program neigh entry in kernel.

Upon receiving MAC/IP update with community type 0x06 and sub_type 0x08,
pass the R-bit to zebra to program neigh entry.

Set NTF_ROUTER in neigh entry and inform kernel to do proxy NA for EVPN.

Ref:
https://tools.ietf.org/html/draft-ietf-bess-evpn-na-flags-01

Ticket:CM-21712, CM-21711
Reviewed By:
Testing Done:
Configure Local vni enabled L3 Gateway, which would act as router,
checked
show evpn arp-cache vni x ip <ip of svi> on originated and remote VTEPs.
"Router" flag is set.

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
14 files changed:
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_attr_evpn.c
bgpd/bgp_attr_evpn.h
bgpd/bgp_ecommunity.h
bgpd/bgp_evpn.c
bgpd/bgp_evpn_private.h
lib/zclient.h
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h
zebra/zebra_vxlan_private.h

index 6596e7cfa2643d1e4b650ecdeb4d5705d3762230..e5ad5e23387ab3fa2bc348f0afd9bb050292ce0c 100644 (file)
@@ -1890,6 +1890,16 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
        /* Check if this is a Gateway MAC-IP advertisement */
        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 */
        bgp_attr_rmac(attr, &attr->rmac);
 
index f17c2a68e4533780614a99586205adfb62667412..883b129136220645e80aa1d63947e4dbda0170c3 100644 (file)
@@ -185,6 +185,9 @@ struct attr {
        /* Flag for default gateway extended community in EVPN */
        uint8_t default_gw;
 
+       /* NA router flag (R-bit) support in EVPN */
+       uint8_t router_flag;
+
        /* route tag */
        route_tag_t tag;
 
index 14ff01ada54c09eb56466857557959c30f71d90d..88e520fdc508c24de4fdd1014124cd9cf3dee105 100644 (file)
@@ -210,6 +210,39 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
        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 */
 extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
                                 struct prefix *dst)
index 7454b81b966870903f72b4ce05365aebef73fa8d..b036702151d0e01957bec7d693bd765a1374dd6d 100644 (file)
@@ -65,4 +65,6 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
                                             uint8_t *sticky);
 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 */
index 2f59308d65fd1f0f0eedfbfa9637c61ea0e3da25..c71f371a9738e2c91171c6cc8c789b4f9acf93ad 100644 (file)
 #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC    0x03
 #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_ND_ROUTER_FLAG         0x01
+#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG       0x02
 
 /* Low-order octet of the Extended Communities type field for OPAQUE types */
 #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP     0x0c
index a026df59a06f717fb0cf05e630c1439d491f62e8..73f225784cb903827577b4727a74d9a042732fe8 100644 (file)
@@ -730,10 +730,13 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
        struct ecommunity ecom_sticky;
        struct ecommunity ecom_default_gw;
        struct ecommunity ecom_rmac;
+       struct ecommunity ecom_na;
        struct ecommunity_val eval;
        struct ecommunity_val eval_sticky;
        struct ecommunity_val eval_default_gw;
        struct ecommunity_val eval_rmac;
+       struct ecommunity_val eval_na;
+
        bgp_encap_types tnl_type;
        struct listnode *node, *nnode;
        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);
        }
 
+       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);
 }
 
@@ -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_pair old_and_new;
+       struct prefix_evpn *evp;
        afi_t afi = AFI_L2VPN;
        safi_t safi = SAFI_EVPN;
        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;
        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
         * update
         * 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);
                        if (old_select->attr->default_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(
                                bgp, vpn, (struct prefix_evpn *)&rn->p,
                                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);
                if (new_select->attr->default_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,
                                         new_select->attr->nexthop, flags);
                /* 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.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 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 */
        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,
                                                        &attr_sticky, 0, 1, &ri,
                                                        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,
                                                        &attr_def_gw, 0, 1, &ri,
                                                        0);
-                       else
+                       else
                                update_evpn_route_entry(bgp, vpn, afi, safi, rn,
                                                        &attr, 0, 1, &ri, 0);
                }
index bf6a24dea61e793a7cb16ff9b4640f3b0ad7c8d0..d89716ca399a01c3cf9e5f9e84bd3b6cddcf875d 100644 (file)
@@ -311,6 +311,16 @@ static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq,
        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,
                                               struct prefix *ip)
 {
index ad98b8db8776d39d7bd2f65839184e5dc4893f57..7c045f62f1bc897347758e3e151a32fb8a58108f 100644 (file)
@@ -448,6 +448,8 @@ enum zapi_iptable_notify_owner {
 /* Zebra MAC types */
 #define ZEBRA_MACIP_TYPE_STICKY                0x01 /* Sticky 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 {
        bool receive_notify;
index 57e62e4f6ee5cc9963ce6ab5ee8e719bc5abb6b2..e40bae3a3e475f37a271d21f988ae2106a938984 100644 (file)
@@ -122,7 +122,7 @@ extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
                          int local);
 
 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);
 
 /*
index 485abc3f1230331d214f325be3922f6af3a0fb3d..7225fc80ffb7c7208a0de679eeb02c04b7d37e20 100644 (file)
@@ -2151,6 +2151,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        char buf2[INET6_ADDRSTRLEN];
        int mac_present = 0;
        uint8_t ext_learned;
+       uint8_t router_flag;
 
        ndm = NLMSG_DATA(h);
 
@@ -2241,6 +2242,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;
+               router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0;
 
                if (IS_ZEBRA_DEBUG_KERNEL)
                        zlog_debug(
@@ -2263,7 +2265,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
                if (ndm->ndm_state & NUD_VALID)
                        return zebra_vxlan_handle_kernel_neigh_update(
                                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);
        }
@@ -2391,7 +2393,8 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
 }
 
 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 nlmsghdr n;
@@ -2414,11 +2417,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_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
        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_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;
        addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
@@ -2426,12 +2428,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
                addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
 
        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_family_to_str(req.ndm.ndm_family), ifp->name,
                           ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
                           mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
-                              : "null");
+                              : "null", flags);
 
        return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
                            0);
@@ -2452,14 +2454,15 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
 }
 
 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)
 {
-       return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH);
+       return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
 }
 
 /*
index cba0376300abe962f47d5fa70108e9e150698bcf..c0b815644bbbd6b62ce104dcd5ad9b4648f82abf 100644 (file)
@@ -460,7 +460,7 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
 }
 
 int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
-                    struct ethaddr *mac)
+                    struct ethaddr *mac, uint8_t flags)
 {
        return 0;
 }
index 59f0cf52f0a1b46664f472442b23090663d568c3..71ae3ab39d6560e0bc24757e97a736cca1ec11fd 100644 (file)
@@ -33,6 +33,9 @@
 #include "jhash.h"
 #include "vlan.h"
 #include "vxlan.h"
+#ifdef GNU_LINUX
+#include <linux/neighbour.h>
+#endif
 
 #include "zebra/rib.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);
        if (width > wctx->addr_width)
                wctx->addr_width = width;
+
 }
 
 /*
@@ -327,6 +331,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
                else
                        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)
                vty_out(vty, "\n");
 }
@@ -432,11 +440,11 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
                return;
        }
        num_neigh = hashcount(zvni->neigh_table);
-       if (json == NULL)
+       if (json == NULL) {
                vty_out(vty,
                        "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
                        zvni->vni, num_neigh);
-       else {
+       else {
                json_vni = json_object_new_object();
                json_object_int_add(json_vni, "numArpNd", num_neigh);
                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;
        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",
                        "Type", "MAC", "Remote VTEP");
+       }
        hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
 
        if (json)
@@ -1553,6 +1562,9 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
 
        if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_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,
                                             ZEBRA_MACIP_ADD);
@@ -1576,6 +1588,8 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
        struct zebra_if *zif;
        struct zebra_l2info_vxlan *vxl;
        struct interface *vlan_if;
+       uint8_t flags;
+       int ret = 0;
 
        if (!(n->flags & ZEBRA_NEIGH_REMOTE))
                return 0;
@@ -1588,8 +1602,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);
        if (!vlan_if)
                return -1;
-
-       return kernel_add_neigh(vlan_if, &n->ip, &n->emac);
+#ifdef GNU_LINUX
+       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;
 }
 
 /*
@@ -1811,6 +1830,9 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
        /* Set "local" forwarding info. */
        SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
        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);
        n->ifindex = ifp->ifindex;
 
@@ -1820,10 +1842,10 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
 
        if (IS_ZEBRA_DEBUG_VXLAN)
                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,
                        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);
 
@@ -1966,7 +1988,8 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
 static int zvni_local_neigh_update(zebra_vni_t *zvni,
                                   struct interface *ifp,
                                   struct ipaddr *ip,
-                                  struct ethaddr *macaddr)
+                                  struct ethaddr *macaddr,
+                                  uint8_t router_flag)
 {
        char buf[ETHER_ADDR_STRLEN];
        char buf2[INET6_ADDRSTRLEN];
@@ -2084,15 +2107,19 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                return 0;
        }
 
+       /*Set router flag (R-bit) */
+       if (router_flag)
+               SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+
        /* Inform BGP. */
        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)),
                           prefix_mac2str(macaddr, buf, sizeof(buf)),
-                          zvni->vni);
+                          zvni->vni, n->flags);
        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,
@@ -3362,14 +3389,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)
 {
+       uint8_t flags;
+       int ret = 0;
+
        if (!is_l3vni_oper_up(zl3vni))
                return -1;
 
        if (!(n->flags & ZEBRA_NEIGH_REMOTE)
            || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
                return 0;
-
-       return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac);
+#ifdef GNU_LINUX
+       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;
 }
 
 /*
@@ -4513,9 +4548,11 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
        memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
        wctx.zvni = zvni;
        wctx.vty = vty;
+       wctx.addr_width = 15;
        wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
        wctx.r_vtep_ip = vtep_ip;
        wctx.json = json;
+       hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
        hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
 
        if (use_json) {
@@ -4944,7 +4981,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
                                           struct ipaddr *ip,
                                           struct ethaddr *macaddr,
                                           uint16_t state,
-                                          uint8_t ext_learned)
+                                          uint8_t ext_learned,
+                                          uint8_t router_flag)
 {
        char buf[ETHER_ADDR_STRLEN];
        char buf2[INET6_ADDRSTRLEN];
@@ -4975,7 +5013,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
 
        /* Is this about a local neighbor or a remote one? */
        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);
 }
@@ -5353,6 +5392,10 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
                        n->r_vtep_ip = vtep_ip;
                        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. */
                        zvni_neigh_install(zvni, n);
                }
index 34d115275102ddab077e868e43cbcbd4661e69b7..2732ef72edfd9e8408af0b0b532a81388102cb43 100644 (file)
@@ -124,7 +124,8 @@ extern int zebra_vxlan_svi_down(struct interface *ifp,
                                struct interface *link_if);
 extern int zebra_vxlan_handle_kernel_neigh_update(
        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,
                                       struct interface *link_if,
                                       struct ipaddr *ip);
index fa7075f2de875ccaea81645178f32336e10d28a6..57b9a279c93bf22429d9e2f886cb45354261850f 100644 (file)
@@ -329,6 +329,7 @@ struct zebra_neigh_t_ {
 #define ZEBRA_NEIGH_REMOTE    0x02
 #define ZEBRA_NEIGH_REMOTE_NH    0x04 /* neigh entry for remote vtep */
 #define ZEBRA_NEIGH_DEF_GW    0x08
+#define ZEBRA_NEIGH_ROUTER_FLAG 0x10
 
        enum zebra_neigh_state state;