]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Ignore EVPN routes from CLAG peer when VNI comes up
authorMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Thu, 17 Aug 2017 06:19:58 +0000 (23:19 -0700)
committerMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Thu, 17 Aug 2017 06:19:58 +0000 (23:19 -0700)
There are two parts to this commit:
1. create a database of self tunnel-ip for used in martian nexthop check
In a CLAG setup, the tunnel-ip (VNI UP) notification comes before the clag-anycast-ip comes up in the system.
This was causing our self next hop check to fail and we were instaling routes with martian nexthop in zebra.
We need to keep this info in a seperate database for all local tunnel-ip.
This database will be used in parallel with the self next hop database to martian nexthop checks.
2. When a local VNI comes up, update the tunnel-ip database and filter routes in the RD table if necessary
In case of EVPN we might receive routes from clag peer before the clag-anycast ip and VNI is up on the system.
We will store the routes in the RD table for later processing.
When VNI comes UP, we loop thorugh all the routes and install them in zebra if required.
However, we were missing the martian nexthop check in this code path.
From now onwards, when a VNI comes UP,
we will first update the tunnel-ip database
We then loop through all the routes in RD table and apply martian next hop filter if required.

Things not covered in this commit but are required:

This processing is needed in general when an address becomes a connected address.
We need to loop through all the routes in BGP and apply martian nexthop filter if necessary.
This will be taken care in a seperate bug

Ticket:CM-17271/CM-16911
Reviewed By: ccr-6542
Testing Done: Manual

Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_memory.c
bgpd/bgp_memory.h
bgpd/bgp_nexthop.c
bgpd/bgp_nexthop.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h

index 109c98f81cbf31162ecb17e72f3095fec0f13fa6..d9735e7ffa052b5a73690b202c9e986a71afdde8 100644 (file)
@@ -46,6 +46,7 @@
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_nexthop.h"
 
 /*
  * Definitions and external declarations.
@@ -1200,6 +1201,13 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
                return 0;
        }
 
+       /* Update the tunnel-ip hash */
+       bgp_tip_del(bgp, &vpn->originator_ip);
+       bgp_tip_add(bgp, &originator_ip);
+
+       /* filter routes as martian nexthop db has changed */
+       bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+
        /* Need to withdraw type-3 route as the originator IP is part
         * of the key.
         */
@@ -1392,12 +1400,12 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
                                            bgp_evpn_route_type rtype,
                                            int install)
 {
-       afi_t afi;
-       safi_t safi;
-       struct bgp_node *rd_rn, *rn;
-       struct bgp_table *table;
-       struct bgp_info *ri;
-       int ret;
+       afi_t                   afi;
+       safi_t                  safi;
+       struct bgp_node         *rd_rn, *rn;
+       struct bgp_table        *table;
+       struct bgp_info         *ri;
+       int                     ret;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1432,7 +1440,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
                                if (is_route_matching_for_vni(bgp, vpn, ri)) {
                                        if (install)
                                                ret = install_evpn_route_entry(
-                                                       bgp, vpn, evp, ri);
+                                               bgp, vpn, evp, ri);
                                        else
                                                ret = uninstall_evpn_route_entry(
                                                        bgp, vpn, evp, ri);
@@ -2563,6 +2571,79 @@ int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
        return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 0);
 }
 
+/* filter routes which have martian next hops */
+int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp)
+{
+       afi_t                   afi;
+       safi_t                  safi;
+       struct bgp_node         *rd_rn, *rn;
+       struct bgp_table        *table;
+       struct bgp_info         *ri;
+
+       afi = AFI_L2VPN;
+       safi = SAFI_EVPN;
+
+       /* Walk entire global routing table and evaluate routes which could be
+        * imported into this VPN. Note that we cannot just look at the routes
+        * for the VNI's RD -
+        * remote routes applicable for this VNI could have any RD.
+        */
+       /* EVPN routes are a 2-level table. */
+       for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
+            rd_rn = bgp_route_next(rd_rn)) {
+               table = (struct bgp_table *)(rd_rn->info);
+               if (!table)
+                       continue;
+
+               for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+
+                       for (ri = rn->info; ri; ri = ri->next) {
+
+                               /* Consider "valid" remote routes applicable for
+                                * this VNI. */
+                               if (!(ri->type == ZEBRA_ROUTE_BGP
+                                     && ri->sub_type == BGP_ROUTE_NORMAL))
+                                       continue;
+
+                               if (bgp_nexthop_self(bgp,
+                                       ri->attr->nexthop)) {
+
+                                       char attr_str[BUFSIZ];
+                                       char pbuf[PREFIX_STRLEN];
+
+                                       bgp_dump_attr(ri->attr, attr_str,
+                                                     BUFSIZ);
+
+                                       if (bgp_debug_update(ri->peer, &rn->p,
+                                                            NULL, 1))
+                                               zlog_debug(
+                                                       "%u: prefix %s with "
+                                                       "attr %s - DENIED"
+                                                       "due to martian or seld"
+                                                       "nexthop",
+                                                       bgp->vrf_id,
+                                                       prefix2str(
+                                                               &rn->p,
+                                                               pbuf,
+                                                               sizeof(pbuf)),
+                                                       attr_str);
+
+                                       bgp_evpn_unimport_route(bgp, afi, safi,
+                                                               &rn->p, ri);
+
+                                       bgp_rib_remove(rn, ri, ri->peer,
+                                                      afi, safi);
+
+
+                               }
+
+                       }
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Handle del of a local MACIP.
  */
@@ -2658,6 +2739,11 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
         */
        delete_routes_for_vni(bgp, vpn);
 
+       /*
+        * tunnel is no longer active, del tunnel ip address from tip_hash
+        */
+       bgp_tip_del(bgp, &vpn->originator_ip);
+
        /* Clear "live" flag and see if hash needs to be freed. */
        UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
        if (!is_vni_configured(vpn))
@@ -2703,15 +2789,22 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
                                bgp->vrf_id, vni);
                        return -1;
                }
+
        }
 
-       /* if the VNI is live already, there is nothibng more to do */
+       /* if the VNI is live already, there is nothing more to do */
        if (is_vni_live(vpn))
                return 0;
 
        /* Mark as "live" */
        SET_FLAG(vpn->flags, VNI_FLAG_LIVE);
 
+       /* tunnel is now active, add tunnel-ip to db */
+       bgp_tip_add(bgp, &originator_ip);
+
+       /* filter routes as nexthop database has changed */
+       bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+
        /* Create EVPN type-3 route and schedule for processing. */
        build_evpn_type3_prefix(&p, vpn->originator_ip);
        if (update_evpn_route(bgp, vpn, &p, 0)) {
index e9b7857212cd79db3979b0fe612a7bc4dc0c4752..ef63199395de47dcf5be67be03b94aea6f630063 100644 (file)
@@ -38,6 +38,7 @@ extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
                                 struct prefix *p, struct bgp_info *ri);
 extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
                                   struct prefix *p, struct bgp_info *ri);
+extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp);
 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,
index 3df40fa87a1fcb5237a273033fc8d3c09ab4d64b..37054ce4258360d01af93b8a5266947da7ba31c2 100644 (file)
@@ -101,6 +101,7 @@ DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
 DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
 DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
 DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
+DEFINE_MTYPE(BGPD, TIP_ADDR, "BGP own tunnel-ip address")
 
 DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
 DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
index 152cfaeaf220cc5ed8efd146e22f350b5cdf7fdd..35b83a040153e003d8baaf62a0c5773914dc0d97 100644 (file)
@@ -97,6 +97,7 @@ DECLARE_MTYPE(BGP_DAMP_ARRAY)
 DECLARE_MTYPE(BGP_REGEXP)
 DECLARE_MTYPE(BGP_AGGREGATE)
 DECLARE_MTYPE(BGP_ADDR)
+DECLARE_MTYPE(TIP_ADDR)
 
 DECLARE_MTYPE(BGP_REDIST)
 DECLARE_MTYPE(BGP_FILTER_NAME)
index 63a84684bbdf9b4cd012aea57c19061d644e3caf..b988fbf738be876ca563e9a3b199c4e64e46f86f 100644 (file)
@@ -88,11 +88,86 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
                }
 }
 
-/* BGP own address structure */
-struct bgp_addr {
-       struct in_addr addr;
-       int refcnt;
-};
+static void *bgp_tip_hash_alloc(void *p)
+{
+       const struct in_addr    *val = (const struct in_addr *)p;
+       struct tip_addr         *addr;
+
+       addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
+       addr->refcnt = 0;
+       addr->addr.s_addr = val->s_addr;
+
+       return addr;
+}
+
+static void bgp_tip_hash_free(void *addr)
+{
+       XFREE(MTYPE_TIP_ADDR, addr);
+}
+
+static unsigned int bgp_tip_hash_key_make(void *p)
+{
+       const struct tip_addr   *addr = p;
+
+       return jhash_1word(addr->addr.s_addr, 0);
+}
+
+static int bgp_tip_hash_cmp(const void *p1, const void *p2)
+{
+       const struct tip_addr   *addr1 = p1;
+       const struct tip_addr   *addr2 = p2;
+
+       return addr1->addr.s_addr == addr2->addr.s_addr;
+}
+
+void bgp_tip_hash_init(struct bgp *bgp)
+{
+       bgp->tip_hash = hash_create(bgp_tip_hash_key_make,
+                                       bgp_tip_hash_cmp, NULL);
+}
+
+void bgp_tip_hash_destroy(struct bgp *bgp)
+{
+       if (bgp->tip_hash == NULL)
+               return;
+       hash_clean(bgp->tip_hash, bgp_tip_hash_free);
+       hash_free(bgp->tip_hash);
+       bgp->tip_hash = NULL;
+}
+
+void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
+{
+       struct tip_addr         tmp;
+       struct tip_addr         *addr;
+
+       tmp.addr = *tip;
+
+       addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
+       if (!addr)
+               return;
+
+       addr->refcnt++;
+}
+
+void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
+{
+       struct tip_addr         tmp;
+       struct tip_addr         *addr;
+
+       tmp.addr = *tip;
+
+       addr = hash_lookup(bgp->tip_hash, &tmp);
+       /* may have been deleted earlier by bgp_interface_down() */
+       if (addr == NULL)
+               return;
+
+       addr->refcnt--;
+
+       if (addr->refcnt == 0) {
+               hash_release(bgp->tip_hash, addr);
+               XFREE(MTYPE_TIP_ADDR, addr);
+       }
+}
 
 static void *bgp_address_hash_alloc(void *p)
 {
@@ -304,6 +379,7 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
 int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
 {
        struct bgp_addr tmp, *addr;
+       struct tip_addr tmp_tip, *tip;
 
        tmp.addr = nh_addr;
 
@@ -311,6 +387,11 @@ int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
        if (addr)
                return 1;
 
+       tmp_tip.addr = nh_addr;
+       tip = hash_lookup(bgp->tip_hash, &tmp_tip);
+       if (tip)
+               return 1;
+
        return 0;
 }
 
index 37dad577c2666627f19e975b74ddb36776fd7a7b..b482778fdfd427bb7787f3e2f2f99dbb6188994f 100644 (file)
@@ -66,6 +66,18 @@ struct bgp_nexthop_cache {
        struct bgp *bgp;
 };
 
+/* BGP own address structure */
+struct bgp_addr {
+       struct in_addr addr;
+       int refcnt;
+};
+
+/* Own tunnel-ip address structure */
+struct tip_addr {
+       struct in_addr addr;
+       int refcnt;
+};
+
 extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
                              int *, int *);
 extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
@@ -82,5 +94,9 @@ extern void bgp_scan_finish(struct bgp *bgp);
 extern void bgp_scan_vty_init(void);
 extern void bgp_address_init(struct bgp *bgp);
 extern void bgp_address_destroy(struct bgp *bgp);
+extern void bgp_tip_add(struct bgp *bgp, struct in_addr *tip);
+extern void bgp_tip_del(struct bgp *bgp, struct in_addr *tip);
+extern void bgp_tip_hash_init(struct bgp *bgp);
+extern void bgp_tip_hash_destroy(struct bgp *bgp);
 
 #endif /* _QUAGGA_BGP_NEXTHOP_H */
index 35f793f8612b61a24dee0699fde8afceef0e54d2..fc226428338abe14d18cd105c7c386157528e300 100644 (file)
@@ -2384,7 +2384,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
 /* Unconditionally remove the route from the RIB, without taking
  * damping into consideration (eg, because the session went down)
  */
-static void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
+void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
                           struct peer *peer, afi_t afi, safi_t safi)
 {
        bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
index 1a1817bad35642410d83b8b13e4049be4a57b175..93d79e5059a95bf98b28746a299625ca0f490acd 100644 (file)
@@ -293,6 +293,8 @@ static inline int bgp_fibupd_safi(safi_t safi)
 }
 
 /* Prototypes. */
+extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
+                          struct peer *peer, afi_t afi, safi_t safi);
 extern void bgp_process_queue_init(void);
 extern void bgp_route_init(void);
 extern void bgp_route_finish(void);
index 2fc75ea5a23c4f9075ba541fbac71a7be4ea7a40..ad73f96d55a0e216e1d64abb3b09d7550a05d597 100644 (file)
@@ -2107,10 +2107,10 @@ static void bgp_zebra_connected(struct zclient *zclient)
 static int bgp_zebra_process_local_vni(int command, struct zclient *zclient,
                                       zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       vni_t vni;
-       struct bgp *bgp;
-       struct in_addr vtep_ip;
+       struct stream           *s;
+       vni_t                   vni;
+       struct bgp              *bgp;
+       struct in_addr          vtep_ip;
 
        s = zclient->ibuf;
        vni = stream_getl(s);
index d7733fbacd3db1a70602abb44f36b811445ab186..f48ba6af245c033eaecb1b8690f71c4dace1d63e 100644 (file)
@@ -2934,6 +2934,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
        bgp = bgp_create(as, name, inst_type);
        bgp_router_id_set(bgp, &bgp->router_id_zebra);
        bgp_address_init(bgp);
+       bgp_tip_hash_init(bgp);
        bgp_scan_init(bgp);
        *bgp_val = bgp;
 
@@ -3158,6 +3159,7 @@ static void bgp_free(struct bgp *bgp)
 
        bgp_scan_finish(bgp);
        bgp_address_destroy(bgp);
+       bgp_tip_hash_destroy(bgp);
 
        bgp_evpn_cleanup(bgp);
 
index bfdddc69b1e93bb901bbcbfa48cc4a65c943aa93..344b850fb4a32e1c8a0583bac1ed39d0a8ef2aae 100644 (file)
@@ -318,6 +318,10 @@ struct bgp {
 
        struct hash *address_hash;
 
+       /* DB for all local tunnel-ips - used mainly for martian checks
+          Currently it only has all VxLan tunnel IPs*/
+       struct hash *tip_hash;
+
        /* Static route configuration.  */
        struct bgp_table *route[AFI_MAX][SAFI_MAX];