]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: flowspec pbr entries listed on the bgp information entry
authorPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 28 Jun 2018 15:26:22 +0000 (17:26 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 24 Jul 2018 10:17:57 +0000 (12:17 +0200)
Because one flowspec entry can create 1-N bgp pbr entries, the list is
now updated and visible. Also, because the bgp_extra structure is used,
this list is flushed when the bgp_extra structure is deleted.

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

index c695e7f12509b22132eca3db7f94e32400ef2a55..3f450fc4ed65031938e15bfea5591691c14a7bab 100644 (file)
@@ -332,16 +332,32 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
                struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
 
                if (extra->bgp_fs_pbr) {
+                       struct listnode *node;
                        struct bgp_pbr_match_entry *bpme;
                        struct bgp_pbr_match *bpm;
+                       int unit = 0;
+                       struct list *list_bpm;
 
-                       bpme = (struct bgp_pbr_match_entry *)extra->bgp_fs_pbr;
-                       bpm = bpme->backpointer;
-                       vty_out(vty, "\tinstalled in PBR");
-                       if (bpm)
-                               vty_out(vty, " (%s)\n", bpm->ipset_name);
-                       else
-                               vty_out(vty, "\n");
+                       list_bpm = list_new();
+                       if (listcount(extra->bgp_fs_pbr))
+                               vty_out(vty, "\tinstalled in PBR");
+                       for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_pbr,
+                                                 node, bpme)) {
+                               bpm = bpme->backpointer;
+                               if (listnode_lookup(list_bpm, bpm))
+                                       continue;
+                               listnode_add(list_bpm, bpm);
+                               if (unit == 0)
+                                       vty_out(vty, " (");
+                               else
+                                       vty_out(vty, ", ");
+                               vty_out(vty, "%s", bpm->ipset_name);
+                               unit++;
+                       }
+                       if (unit)
+                               vty_out(vty, ")");
+                       vty_out(vty, "\n");
+                       list_delete_all_node(list_bpm);
                } else
                        vty_out(vty, "\tnot installed in PBR\n");
        }
index b5ddfd4b2112a9eadc9da3937e8f6271469bcd9d..9152307c99ac4c4de69cbd328f6dde8ae55502c0 100644 (file)
@@ -1225,7 +1225,8 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
                        /* unlink bgp_info to bpme */
                        bgp_info = (struct bgp_info *)bpme->bgp_info;
                        extra = bgp_info_extra_get(bgp_info);
-                       extra->bgp_fs_pbr = NULL;
+                       if (extra->bgp_fs_pbr)
+                               listnode_delete(extra->bgp_fs_pbr, bpme);
                        bpme->bgp_info = NULL;
                }
        }
@@ -1597,6 +1598,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
        struct bgp_pbr_range_port *src_port;
        struct bgp_pbr_range_port *dst_port;
        struct bgp_pbr_range_port *pkt_len;
+       bool bpme_found = false;
 
        if (!bpf)
                return;
@@ -1817,8 +1819,21 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
                bpme->install_in_progress = false;
                /* link bgp info to bpme */
                bpme->bgp_info = (void *)binfo;
-       }
+       } else
+               bpme_found = true;
 
+       /* already installed */
+       if (bpme_found && bpme) {
+               struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
+
+               if (extra && extra->bgp_fs_pbr &&
+                   listnode_lookup(extra->bgp_fs_pbr, bpme)) {
+                       if (BGP_DEBUG(pbr, PBR_ERROR))
+                               zlog_err("%s: entry %p/%p already installed in bgp pbr",
+                                        __func__, binfo, bpme);
+                       return;
+               }
+       }
        /* BGP FS: append entry to zebra
         * - policies are not routing entries and as such
         * route replace semantics don't necessarily follow
@@ -2195,7 +2210,6 @@ 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 */
@@ -2212,13 +2226,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
                                 __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))
index f10f7425c6a6a6a79de38e1f94db50077bb32bf9..d54a5da1fbd53a51e4d859fcf1e83856117c63f7 100644 (file)
@@ -196,6 +196,10 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
 
        if (e->bgp_orig)
                bgp_unlock(e->bgp_orig);
+
+       if ((*extra)->bgp_fs_pbr)
+               list_delete_all_node((*extra)->bgp_fs_pbr);
+       (*extra)->bgp_fs_pbr = NULL;
        XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
 
        *extra = NULL;
index 72923901b837cca1a3ea4f73a9d6b6871c0f9625..dfef9a8f79158c20f27cca79f92c59798b9cd018 100644 (file)
@@ -147,7 +147,7 @@ struct bgp_info_extra {
         */
        struct prefix nexthop_orig;
        /* presence of FS pbr entry */
-       void *bgp_fs_pbr;
+       struct list *bgp_fs_pbr;
 };
 
 struct bgp_info {
index 714f6791c14c2bed7ee435395817b42ef73900d5..7123875f77d81083d375dc7e0dc75ae827d6ae22 100644 (file)
@@ -2074,7 +2074,9 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient,
                        /* link bgp_info to bpme */
                        bgp_info = (struct bgp_info *)bgp_pbime->bgp_info;
                        extra = bgp_info_extra_get(bgp_info);
-                       extra->bgp_fs_pbr = (void *)bgp_pbime;
+                       if (extra->bgp_fs_pbr == NULL)
+                               extra->bgp_fs_pbr = list_new();
+                       listnode_add(extra->bgp_fs_pbr, bgp_pbime);
                }
                break;
        case ZAPI_IPSET_ENTRY_FAIL_REMOVE: