]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: evpn pip handle svi ip route
authorChirag Shah <chirag@cumulusnetworks.com>
Fri, 9 Aug 2019 01:58:03 +0000 (18:58 -0700)
committerChirag Shah <chirag@cumulusnetworks.com>
Fri, 22 Nov 2019 15:53:32 +0000 (07:53 -0800)
By default announct Self Type-2 routes with
system IP as nexthop and system MAC as
nexthop.

An API to check type-2 is self route via
checking ipv4/ipv6 address from connected interfaces list.

An API to extract RMAC and nexthop for type-2
routes based on advertise-svi-ip knob is enabled.

When advertise-pip is enabled/disabled, trigger type-2
route update. For self type-2 routes to use
anycast or individual (rmac, nexthop) addresses.

Ticket:CM-26190
Reviewed By:
Testing Done:

Enable 'advertise-svi-ip' knob in bgp default instance.
the vrf instance svi ip is advertised with nexthop
as default instance router-id and RMAC as system MAC.

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
bgpd/bgp_evpn.c
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_route.h
lib/zclient.h
zebra/zebra_vxlan.c
zebra/zebra_vxlan_private.h

index 49b2b7d1ed21dc80dc62a1c13c37acb65d9f7969..c31073cc8ff9fe1c5f6ae077c7ad6e80fb6997d3 100644 (file)
@@ -494,6 +494,39 @@ static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn,
        }
 }
 
+static void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn,
+                                     struct prefix_evpn *p,
+                                     struct attr *attr, uint8_t flags)
+{
+       struct bgp *bgp_vrf = vpn->bgp_vrf;
+
+       memset(&attr->rmac, 0, sizeof(struct ethaddr));
+       if (!bgp_vrf)
+               return;
+
+       if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+               /* Copy sys (pip) RMAC and PIP IP as nexthop
+                * in case of route is self MAC-IP,
+                * advertise-pip and advertise-svi-ip features
+                * are enabled.
+                * Otherwise, for all host MAC-IP route's
+                * copy anycast RMAC
+                */
+               if (CHECK_FLAG(flags, BGP_EVPN_MACIP_TYPE_SVI_IP)
+                   && bgp_evpn_is_svi_macip_enabled(vpn)) {
+                       /* copy sys rmac */
+                       memcpy(&attr->rmac, &bgp_vrf->evpn_info->pip_rmac,
+                              ETH_ALEN);
+                       if (bgp_vrf->evpn_info->advertise_pip &&
+                           bgp_vrf->evpn_info->is_anycast_mac) {
+                               attr->nexthop = bgp_vrf->evpn_info->pip_ip;
+                               attr->mp_nexthop_global_in =
+                                       bgp_vrf->evpn_info->pip_ip;
+                       }
+               } else
+                       memcpy(&attr->rmac, &bgp_vrf->rmac, ETH_ALEN);
+       }
+}
 /*
  * Create RT extended community automatically from passed information:
  * of the form AS:VNI.
@@ -1685,6 +1718,9 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
 
                memcpy(&tmp_pi->extra->label, label, sizeof(label));
                tmp_pi->extra->num_labels = num_labels;
+               /* Mark route as self type-2 route */
+               if (flags && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP))
+                       tmp_pi->extra->af_flags = BGP_EVPN_MACIP_TYPE_SVI_IP;
                bgp_path_info_add(rn, tmp_pi);
        } else {
                tmp_pi = local_pi;
@@ -1828,8 +1864,29 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
        }
 
        /* router mac is only needed for type-2 routes here. */
-       if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-               bgpevpn_get_rmac(vpn, &attr.rmac);
+       if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+               uint8_t af_flags = 0;
+
+               if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP))
+                       SET_FLAG(af_flags, BGP_EVPN_MACIP_TYPE_SVI_IP);
+
+               bgp_evpn_get_rmac_nexthop(vpn, p, &attr, af_flags);
+
+               if (bgp_debug_zebra(NULL)) {
+                       char buf[ETHER_ADDR_STRLEN];
+                       char buf1[PREFIX_STRLEN];
+
+                       zlog_debug("VRF %s vni %u type-2 route evp %s RMAC %s nexthop %s",
+                                  vpn->bgp_vrf ?
+                                  vrf_id_to_name(vpn->bgp_vrf->vrf_id) : " ",
+                                  vpn->vni,
+                                  prefix2str(p, buf1, sizeof(buf1)),
+                                  prefix_mac2str(&attr.rmac, buf,
+                                                 sizeof(buf)),
+                                  inet_ntoa(attr.mp_nexthop_global_in));
+               }
+       }
+
        vni2label(vpn->vni, &(attr.label));
 
        /* Include L3 VNI related RTs and RMAC for type-2 routes, if they're
@@ -2104,7 +2161,8 @@ static int update_all_type2_routes(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;
-               bgpevpn_get_rmac(vpn, &attr.rmac);
+               bgp_evpn_get_rmac_nexthop(vpn, evp, &attr,
+                                         tmp_pi->extra->af_flags);
 
                if (evpn_route_is_sticky(bgp, rn))
                        attr.sticky = 1;
@@ -2114,6 +2172,19 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
                                attr.router_flag = 1;
                }
 
+               if (bgp_debug_zebra(NULL)) {
+                       char buf[ETHER_ADDR_STRLEN];
+                       char buf1[PREFIX_STRLEN];
+
+                       zlog_debug("VRF %s vni %u evp %s RMAC %s nexthop %s",
+                                  vpn->bgp_vrf ?
+                                  vrf_id_to_name(vpn->bgp_vrf->vrf_id) : " ",
+                                  vpn->vni,
+                                  prefix2str(evp, buf1, sizeof(buf1)),
+                                  prefix_mac2str(&attr.rmac, buf, sizeof(buf)),
+                                  inet_ntoa(attr.mp_nexthop_global_in));
+               }
+
                /* Add L3 VNI RTs and RMAC for non IPv6 link-local if
                 * using L3 VNI for type-2 routes also.
                 */
@@ -2301,7 +2372,7 @@ static int bgp_evpn_vni_flood_mode_get(struct bgp *bgp,
  * situations need the route in the per-VNI table as well as the global
  * table to be updated (as attributes change).
  */
-static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
+int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
 {
        int ret;
        struct prefix_evpn p;
index a0c05e34f8cf71bbd402df7046b286b76b92dead..76cf8b2cd618e6990dd8fac3d1bbd0a7d7fa3a98 100644 (file)
@@ -511,6 +511,16 @@ static inline int is_es_local(struct evpnes *es)
        return CHECK_FLAG(es->flags, EVPNES_LOCAL) ? 1 : 0;
 }
 
+static inline bool bgp_evpn_is_svi_macip_enabled(struct bgpevpn *vpn)
+{
+       struct bgp *bgp_evpn = NULL;
+
+       bgp_evpn = bgp_get_evpn();
+
+       return (bgp_evpn->evpn_info->advertise_svi_macip ||
+               vpn->advertise_svi_macip);
+}
+
 extern void bgp_evpn_install_uninstall_default_route(struct bgp *bgp_vrf,
                                                     afi_t afi, safi_t safi,
                                                     bool add);
@@ -553,4 +563,5 @@ extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi,
                                      struct ipaddr *originator_ip);
 extern void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es);
 extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni);
+extern int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn);
 #endif /* _BGP_EVPN_PRIVATE_H */
index 882716cf37bd3aa5a8e8624327c65b6b1f7915f4..5508ab99b4d7d75669a82956840945ba6aa21492 100644 (file)
@@ -3767,7 +3767,17 @@ DEFPY (bgp_evpn_advertise_pip_ip_mac,
        }
 
        if (is_evpn_enabled()) {
+               struct listnode *node = NULL;
+               struct bgpevpn *vpn = NULL;
+
                update_advertise_vrf_routes(bgp_vrf);
+
+               /* Update (svi) type-2 routes */
+               for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
+                       if (!bgp_evpn_is_svi_macip_enabled(vpn))
+                               continue;
+                       update_routes_for_vni(bgp_evpn, vpn);
+               }
        }
 
        return CMD_SUCCESS;
index a710873ea7936da75eebd7779c53c57b0da04869..b9f3f3f7620119988f3cc6eebb11673c287ba0c4 100644 (file)
@@ -114,6 +114,10 @@ struct bgp_path_info_extra {
        mpls_label_t label[BGP_MAX_LABELS];
        uint32_t num_labels;
 
+       /* af specific flags */
+       uint16_t af_flags;
+#define BGP_EVPN_MACIP_TYPE_SVI_IP (1 << 0)
+
 #if ENABLE_BGP_VNC
        union {
 
index ebf3e6450f00192f536501ce4c7e1f072ad28d97..7adb294a31d4e20e33c6f7e111f9911f1dc7f309 100644 (file)
@@ -490,6 +490,7 @@ enum zapi_iptable_notify_owner {
 #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 */
+#define ZEBRA_MACIP_TYPE_SVI_IP                0x10 /* SVI MAC-IP */
 
 enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
 
index ba441d7a74665c132996921dda8c87eb6cf85933..b2cb726faca978b0ba87ef26d13bb767fef6d273 100644 (file)
@@ -2493,6 +2493,8 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
        /* 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);
+       if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_SVI_IP))
+               SET_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP);
 
        return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
                             seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
@@ -2813,6 +2815,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
                                              n->flags, n->loc_seq);
        } else if (advertise_svi_macip_enabled(zvni)) {
 
+               SET_FLAG(n->flags, ZEBRA_NEIGH_SVI_IP);
                if (IS_ZEBRA_DEBUG_VXLAN)
                        zlog_debug(
                        "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
index 784dcdb9d859819b882702f3b4c633408dd29afc..f0bda44fb923028a34add59a65b1f3e52aafa024 100644 (file)
@@ -366,6 +366,7 @@ struct zebra_neigh_t_ {
 #define ZEBRA_NEIGH_DEF_GW    0x08
 #define ZEBRA_NEIGH_ROUTER_FLAG 0x10
 #define ZEBRA_NEIGH_DUPLICATE 0x20
+#define ZEBRA_NEIGH_SVI_IP 0x40
 
        enum zebra_neigh_state state;