]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: do not install BGP FS entries, while table range not obtained
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 23 May 2018 12:14:53 +0000 (14:14 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 25 May 2018 13:49:38 +0000 (15:49 +0200)
Sometimes at startup, BGP Flowspec may be allocated a routing table
identifier not in the range of the predefined table range.
This issue is due to the fact that BGP peering goes up, while the BGP
did not yet retrieve the Table Range allocator.
The fix is done so that BGP PBR entries are not installed while
routing table identifier range is not obtained. Once the routing table
identifier is obtained, parse the FS entries and check that all selected
entries are installed, and if not, install it.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_pbr.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c

index 6ba5293daeb2ca8797d5a24020a9492a56faaed7..1054ea402743cd981ed7c76e2194a06835e05c63 100644 (file)
@@ -1347,6 +1347,7 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
                         bool nlri_update)
 {
        struct bgp_pbr_entry_main api;
+       struct bgp_info_extra *extra = bgp_info_extra_get(info);
 
        if (afi == AFI_IP6)
                return; /* IPv6 not supported */
@@ -1357,12 +1358,26 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
        api.vrf_id = bgp->vrf_id;
        api.afi = afi;
 
-       if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) {
+       if (!bgp_zebra_tm_chunk_obtained()) {
                if (BGP_DEBUG(pbr, PBR_ERROR))
-                       zlog_err("%s: cancel updating entry in bgp pbr",
+                       zlog_err("%s: table chunk not obtained yet",
                                 __func__);
                return;
        }
+       /* already installed */
+       if (nlri_update && extra->bgp_fs_pbr) {
+               if (BGP_DEBUG(pbr, PBR_ERROR))
+                       zlog_err("%s: entry %p already installed in bgp pbr",
+                                __func__, info);
+               return;
+       }
+
+       if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) {
+               if (BGP_DEBUG(pbr, PBR_ERROR))
+                       zlog_err("%s: cancel updating entry %p in bgp pbr",
+                                __func__, info);
+               return;
+       }
        bgp_pbr_handle_entry(bgp, info, &api, nlri_update);
 }
 
index d41831d46bd9dde859f731e60839c8f1167d9753..7a6b80f3a202ca24237ba921e621eaa40b3dd3e5 100644 (file)
@@ -1001,6 +1001,7 @@ static bool bgp_tm_status_connected;
 static bool bgp_tm_chunk_obtained;
 #define BGP_FLOWSPEC_TABLE_CHUNK 100000
 static uint32_t bgp_tm_min, bgp_tm_max, bgp_tm_chunk_size;
+struct bgp *bgp_tm_bgp;
 
 static int bgp_zebra_tm_connect(struct thread *t)
 {
@@ -1024,8 +1025,11 @@ static int bgp_zebra_tm_connect(struct thread *t)
                if (!bgp_tm_chunk_obtained) {
                        if (bgp_zebra_get_table_range(bgp_tm_chunk_size,
                                                      &bgp_tm_min,
-                                                     &bgp_tm_max) >= 0)
+                                                     &bgp_tm_max) >= 0) {
                                bgp_tm_chunk_obtained = true;
+                               /* parse non installed entries */
+                               bgp_zebra_announce_table(bgp_tm_bgp, AFI_IP, SAFI_FLOWSPEC);
+                       }
                }
        }
        thread_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
@@ -1033,6 +1037,11 @@ static int bgp_zebra_tm_connect(struct thread *t)
        return 0;
 }
 
+bool bgp_zebra_tm_chunk_obtained(void)
+{
+       return bgp_tm_chunk_obtained;
+}
+
 uint32_t bgp_zebra_tm_get_id(void)
 {
        static int table_id;
@@ -1042,7 +1051,7 @@ uint32_t bgp_zebra_tm_get_id(void)
        return bgp_tm_min++;
 }
 
-void bgp_zebra_init_tm_connect(void)
+void bgp_zebra_init_tm_connect(struct bgp *bgp)
 {
        int delay = 1;
 
@@ -1054,6 +1063,7 @@ void bgp_zebra_init_tm_connect(void)
        bgp_tm_chunk_obtained = false;
        bgp_tm_min = bgp_tm_max = 0;
        bgp_tm_chunk_size = BGP_FLOWSPEC_TABLE_CHUNK;
+       bgp_tm_bgp = bgp;
        thread_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
                         &bgp_tm_thread_connect);
 }
index 7ac40fecff6c431bca9be10b48383690f2889a43..e3c88b9db664712e4eab521a4faef8da42214cef 100644 (file)
@@ -24,8 +24,9 @@
 #include "vxlan.h"
 
 extern void bgp_zebra_init(struct thread_master *master);
-extern void bgp_zebra_init_tm_connect(void);
+extern void bgp_zebra_init_tm_connect(struct bgp *bgp);
 extern uint32_t bgp_zebra_tm_get_id(void);
+extern bool bgp_zebra_tm_chunk_obtained(void);
 extern void bgp_zebra_destroy(void);
 extern int bgp_zebra_get_table_range(uint32_t chunk_size,
                                     uint32_t *start, uint32_t *end);
index ab13a37d9d1fd5cb09a57490c9366f833158eba2..69297cd3e4598be05227a72a9ca553db418a7dd0 100644 (file)
@@ -1988,7 +1988,7 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
 
        if (safi == SAFI_FLOWSPEC) {
                /* connect to table manager */
-               bgp_zebra_init_tm_connect();
+               bgp_zebra_init_tm_connect(bgp);
        }
        return ret;
 }