]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Add an ability to filter UPDATEs using neighbor with prefix-list
authorDonatas Abraitis <donatas@opensourcerouting.org>
Fri, 17 Nov 2023 06:39:33 +0000 (08:39 +0200)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Wed, 22 Nov 2023 06:06:33 +0000 (08:06 +0200)
Before this patch we didn't have an option to filter debug UPDATE messages
by specifying an arbitrary prefix, prefix-list or so. We had/have only an option
to specify:

```
* debug bgp updates in 10.0.0.1
* debug bgp updates prefix 10.0.1.0/24
```

Now adding:

```
* debug bgp updates <in|out> 10.0.0.1 prefix-list plist
```

CLI output:

```
r2# show debugging
MGMT debugging status:

Zebra debugging status:

BGP debugging status:
  BGP updates debugging is on (inbound) for 192.168.2.6 with prefix-list debug

Staticd debugging status

r2# show running-config | include prefix-list debug
debug bgp updates in 192.168.2.6 prefix-list debug
r2#
```

Logs:

```
BGP: [PCFFM-WMARW] 192.168.2.3(r3) rcvd UPDATE wlen 0 attrlen 28 alen 5
BGP: [PCFFM-WMARW] 192.168.2.3(r3) rcvd UPDATE wlen 0 attrlen 28 alen 4
BGP: [PCFFM-WMARW] 192.168.2.3(r3) rcvd UPDATE wlen 0 attrlen 0 alen 0
BGP: [M59KS-A3ZXZ] bgp_update_receive: rcvd End-of-RIB for IPv4 Unicast from 192.168.2.3 in vrf default
BGP: [PCFFM-WMARW] 192.168.2.4(r4) rcvd UPDATE wlen 0 attrlen 28 alen 5
BGP: [PCFFM-WMARW] 192.168.2.4(r4) rcvd UPDATE wlen 0 attrlen 28 alen 4
BGP: [PCFFM-WMARW] 192.168.2.4(r4) rcvd UPDATE wlen 0 attrlen 0 alen 0
BGP: [M59KS-A3ZXZ] bgp_update_receive: rcvd End-of-RIB for IPv4 Unicast from 192.168.2.4 in vrf default
BGP: [PCFFM-WMARW] 192.168.1.1(r1) rcvd UPDATE wlen 0 attrlen 29 alen 5
BGP: [PCFFM-WMARW] 192.168.2.6(r6) rcvd UPDATE wlen 0 attrlen 28 alen 5
BGP: [XXWBM-V772F] 192.168.2.6(r6) rcvd UPDATE w/ attr: nexthop 192.168.2.6, origin ?, metric 0, path 65006
BGP: [YCKEM-GB33T] 192.168.2.6(r6) rcvd 172.16.16.254/32 IPv4 unicast <<<<<<<<<<<<
BGP: [PCFFM-WMARW] 192.168.2.6(r6) rcvd UPDATE wlen 0 attrlen 28 alen 4
BGP: [PCFFM-WMARW] 192.168.2.6(r6) rcvd UPDATE wlen 0 attrlen 0 alen 0
BGP: [M59KS-A3ZXZ] bgp_update_receive: rcvd End-of-RIB for IPv4 Unicast from 192.168.2.6 in vrf default
BGP: [PCFFM-WMARW] 192.168.2.5(r5) rcvd UPDATE wlen 0 attrlen 28 alen 5
BGP: [PCFFM-WMARW] 192.168.2.5(r5) rcvd UPDATE wlen 0 attrlen 28 alen 4
BGP: [PCFFM-WMARW] 192.168.2.5(r5) rcvd UPDATE wlen 0 attrlen 0 alen 0
BGP: [M59KS-A3ZXZ] bgp_update_receive: rcvd End-of-RIB for IPv4 Unicast from 192.168.2.5 in vrf default
BGP: [PCFFM-WMARW] 192.168.1.1(r1) rcvd UPDATE wlen 0 attrlen 29 alen 5
BGP: [PCFFM-WMARW] 192.168.7.7(r7) rcvd UPDATE wlen 0 attrlen 0 alen 0
BGP: [M59KS-A3ZXZ] bgp_update_receive: rcvd End-of-RIB for IPv4 Unicast from 192.168.7.7 in vrf default
```

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
bgpd/bgp_debug.c
bgpd/bgp_debug.h

index 123a1cacf3fe2d71d8b11c3bc77b2ae9818ac230..059f921ed10abcca691b4f66685de02091afa5f4 100644 (file)
@@ -216,6 +216,7 @@ static void bgp_debug_list_free(struct list *list)
                        listnode_delete(list, filter);
                        prefix_free(&filter->p);
                        XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
+                       XFREE(MTYPE_BGP_DEBUG_STR, filter->plist_name);
                        XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
                }
 }
@@ -238,6 +239,10 @@ static void bgp_debug_list_print(struct vty *vty, const char *desc,
                        if (filter->host)
                                vty_out(vty, " %s", filter->host);
 
+                       if (filter->plist_name)
+                               vty_out(vty, " with prefix-list %s",
+                                       filter->plist_name);
+
                        if (filter->p && filter->p->family == AF_EVPN)
                                bgp_debug_print_evpn_prefix(vty, "", filter->p);
                        else if (filter->p)
@@ -261,7 +266,11 @@ static int bgp_debug_list_conf_print(struct vty *vty, const char *desc,
 
        if (list && !list_isempty(list)) {
                for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
-                       if (filter->host) {
+                       if (filter->host && filter->plist_name) {
+                               vty_out(vty, "%s %s prefix-list %s\n", desc,
+                                       filter->host, filter->plist_name);
+                               write++;
+                       } else if (filter->host) {
                                vty_out(vty, "%s %s\n", desc, filter->host);
                                write++;
                        }
@@ -286,7 +295,8 @@ static int bgp_debug_list_conf_print(struct vty *vty, const char *desc,
 }
 
 static void bgp_debug_list_add_entry(struct list *list, const char *host,
-                                    const struct prefix *p)
+                                    const struct prefix *p,
+                                    const char *plist_name)
 {
        struct bgp_debug_filter *filter;
 
@@ -302,6 +312,9 @@ static void bgp_debug_list_add_entry(struct list *list, const char *host,
                prefix_copy(filter->p, p);
        }
 
+       if (plist_name)
+               filter->plist_name = XSTRDUP(MTYPE_BGP_DEBUG_STR, plist_name);
+
        listnode_add(list, filter);
 }
 
@@ -315,6 +328,7 @@ static bool bgp_debug_list_remove_entry(struct list *list, const char *host,
                if (host && strcmp(filter->host, host) == 0) {
                        listnode_delete(list, filter);
                        XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
+                       XFREE(MTYPE_BGP_DEBUG_STR, filter->plist_name);
                        XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
                        return true;
                } else if (p && filter->p->prefixlen == p->prefixlen
@@ -330,16 +344,20 @@ static bool bgp_debug_list_remove_entry(struct list *list, const char *host,
 }
 
 static bool bgp_debug_list_has_entry(struct list *list, const char *host,
-                                    const struct prefix *p)
+                                    const struct prefix *p,
+                                    const char *plist_name)
 {
        struct bgp_debug_filter *filter;
        struct listnode *node, *nnode;
 
        for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
-               if (host) {
-                       if (strcmp(filter->host, host) == 0) {
+               if (host && plist_name) {
+                       if (strmatch(filter->host, host) && filter->plist_name &&
+                           strmatch(filter->plist_name, plist_name))
+                               return true;
+               } else if (host) {
+                       if (strmatch(filter->host, host))
                                return true;
-                       }
                } else if (p) {
                        if (filter->p->prefixlen == p->prefixlen
                            && prefix_match(filter->p, p)) {
@@ -353,7 +371,7 @@ static bool bgp_debug_list_has_entry(struct list *list, const char *host,
 
 bool bgp_debug_peer_updout_enabled(char *host)
 {
-       return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
+       return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL,
                                         NULL));
 }
 
@@ -780,14 +798,15 @@ DEFUN (debug_bgp_neighbor_events_peer,
                bgp_debug_neighbor_events_peers = list_new();
 
        if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, host,
-                                    NULL)) {
+                                    NULL, NULL)) {
                vty_out(vty,
                        "BGP neighbor-events debugging is already enabled for %s\n",
                        host);
                return CMD_SUCCESS;
        }
 
-       bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL);
+       bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL,
+                                NULL);
 
        if (vty->node == CONFIG_NODE)
                DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS);
@@ -927,14 +946,15 @@ DEFUN (debug_bgp_keepalive_peer,
        if (!bgp_debug_keepalive_peers)
                bgp_debug_keepalive_peers = list_new();
 
-       if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL)) {
+       if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL,
+                                    NULL)) {
                vty_out(vty,
                        "BGP keepalive debugging is already enabled for %s\n",
                        host);
                return CMD_SUCCESS;
        }
 
-       bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL);
+       bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL, NULL);
 
        if (vty->node == CONFIG_NODE)
                DEBUG_ON(keepalive, KEEPALIVE);
@@ -1015,15 +1035,16 @@ DEFPY (debug_bgp_bestpath_prefix,
        if (!bgp_debug_bestpath_prefixes)
                bgp_debug_bestpath_prefixes = list_new();
 
-       if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL,
-                                    prefix)) {
+       if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, prefix,
+                                    NULL)) {
                vty_out(vty,
                        "BGP bestpath debugging is already enabled for %s\n",
                        prefix_str);
                return CMD_SUCCESS;
        }
 
-       bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, prefix);
+       bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, prefix,
+                                NULL);
 
        if (vty->node == CONFIG_NODE) {
                DEBUG_ON(bestpath, BESTPATH);
@@ -1150,9 +1171,9 @@ DEFUN (debug_bgp_update_direct,
        return CMD_SUCCESS;
 }
 
-DEFUN (debug_bgp_update_direct_peer,
+DEFPY (debug_bgp_update_direct_peer,
        debug_bgp_update_direct_peer_cmd,
-       "debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD>",
+       "debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD> [prefix-list PREFIXLIST_NAME$plist]",
        DEBUG_STR
        BGP_STR
        "BGP updates\n"
@@ -1160,7 +1181,9 @@ DEFUN (debug_bgp_update_direct_peer,
        "Outbound updates\n"
        "BGP neighbor IP address to debug\n"
        "BGP IPv6 neighbor to debug\n"
-       "BGP neighbor on interface to debug\n")
+       "BGP neighbor on interface to debug\n"
+       "Use prefix-list to filter prefixes to debug\n"
+       "Name of prefix-list\n")
 {
        int idx_in_out = 3;
        int idx_peer = 4;
@@ -1180,7 +1203,7 @@ DEFUN (debug_bgp_update_direct_peer,
 
        if (inbound) {
                if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, host,
-                                            NULL)) {
+                                            NULL, plist)) {
                        vty_out(vty,
                                "BGP inbound update debugging is already enabled for %s\n",
                                host);
@@ -1190,7 +1213,7 @@ DEFUN (debug_bgp_update_direct_peer,
 
        else {
                if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
-                                            NULL)) {
+                                            NULL, plist)) {
                        vty_out(vty,
                                "BGP outbound update debugging is already enabled for %s\n",
                                host);
@@ -1199,14 +1222,15 @@ DEFUN (debug_bgp_update_direct_peer,
        }
 
        if (inbound)
-               bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL);
+               bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL,
+                                        plist);
        else {
                struct peer *peer;
                struct peer_af *paf;
                int afidx;
 
-               bgp_debug_list_add_entry(bgp_debug_update_out_peers, host,
-                                        NULL);
+               bgp_debug_list_add_entry(bgp_debug_update_out_peers, host, NULL,
+                                        plist);
                peer = bgp_find_peer(vty, host);
 
                if (peer) {
@@ -1283,7 +1307,7 @@ DEFUN (no_debug_bgp_update_direct,
 
 DEFUN (no_debug_bgp_update_direct_peer,
        no_debug_bgp_update_direct_peer_cmd,
-       "no debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD>",
+       "no debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD> [prefix-list PREFIXLIST_NAME]",
        NO_STR
        DEBUG_STR
        BGP_STR
@@ -1292,7 +1316,9 @@ DEFUN (no_debug_bgp_update_direct_peer,
        "Outbound updates\n"
        "BGP neighbor IP address to debug\n"
        "BGP IPv6 neighbor to debug\n"
-       "BGP neighbor on interface to debug\n")
+       "BGP neighbor on interface to debug\n"
+       "Use prefix-list to filter prefixes to debug\n"
+       "Name of prefix-list\n")
 {
        int idx_in_out = 4;
        int idx_peer = 5;
@@ -1414,15 +1440,15 @@ DEFPY (debug_bgp_update_prefix_afi_safi,
        if (!bgp_debug_update_prefixes)
                bgp_debug_update_prefixes = list_new();
 
-       if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL,
-                                    &argv_p)) {
+       if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, &argv_p,
+                                    NULL)) {
                vty_out(vty,
                        "BGP updates debugging is already enabled for %pFX\n",
                        &argv_p);
                return CMD_SUCCESS;
        }
 
-       bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, &argv_p);
+       bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, &argv_p, NULL);
 
        if (vty->node == CONFIG_NODE) {
                DEBUG_ON(update, UPDATE_PREFIX);
@@ -1510,14 +1536,15 @@ DEFPY (debug_bgp_update_prefix,
        if (!bgp_debug_update_prefixes)
                bgp_debug_update_prefixes = list_new();
 
-       if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, prefix)) {
+       if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, prefix,
+                                    NULL)) {
                vty_out(vty,
                        "BGP updates debugging is already enabled for %s\n",
                        prefix_str);
                return CMD_SUCCESS;
        }
 
-       bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, prefix);
+       bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, prefix, NULL);
 
        if (vty->node == CONFIG_NODE) {
                DEBUG_ON(update, UPDATE_PREFIX);
@@ -1647,13 +1674,14 @@ DEFPY (debug_bgp_zebra_prefix,
        if (!bgp_debug_zebra_prefixes)
                bgp_debug_zebra_prefixes = list_new();
 
-       if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, prefix)) {
+       if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, prefix,
+                                    NULL)) {
                vty_out(vty, "BGP zebra debugging is already enabled for %s\n",
                        prefix_str);
                return CMD_SUCCESS;
        }
 
-       bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, prefix);
+       bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, prefix, NULL);
 
        if (vty->node == CONFIG_NODE)
                DEBUG_ON(zebra, ZEBRA);
@@ -2510,7 +2538,8 @@ static int bgp_debug_per_prefix(const struct prefix *p,
 /* Return true if this peer is on the per_peer_list of peers to debug
  * for BGP_DEBUG_TYPE
  */
-static bool bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type,
+static bool bgp_debug_per_peer(char *host, const struct prefix *p,
+                              unsigned long term_bgp_debug_type,
                               unsigned int BGP_DEBUG_TYPE,
                               struct list *per_peer_list)
 {
@@ -2522,17 +2551,28 @@ static bool bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type,
                if (!per_peer_list || list_isempty(per_peer_list))
                        return true;
 
-               else {
-                       if (!host)
-                               return false;
+               if (!host)
+                       return false;
 
-                       for (ALL_LIST_ELEMENTS(per_peer_list, node, nnode,
-                                              filter))
-                               if (strcmp(filter->host, host) == 0)
-                                       return true;
+               for (ALL_LIST_ELEMENTS(per_peer_list, node, nnode, filter))
+                       if (strmatch(filter->host, host) &&
+                           filter->plist_name && p) {
+                               struct prefix_list *plist;
+                               afi_t afi = family2afi(p->family);
 
-                       return false;
-               }
+                               plist = prefix_list_lookup(afi,
+                                                          filter->plist_name);
+
+                               if (!plist)
+                                       continue;
+
+                               return prefix_list_apply(plist, p) ==
+                                      PREFIX_PERMIT;
+                       } else if (strmatch(filter->host, host)) {
+                               return true;
+                       }
+
+               return false;
        }
 
        return false;
@@ -2545,7 +2585,7 @@ bool bgp_debug_neighbor_events(const struct peer *peer)
        if (peer)
                host = peer->host;
 
-       return bgp_debug_per_peer(host, term_bgp_debug_neighbor_events,
+       return bgp_debug_per_peer(host, NULL, term_bgp_debug_neighbor_events,
                                  BGP_DEBUG_NEIGHBOR_EVENTS,
                                  bgp_debug_neighbor_events_peers);
 }
@@ -2557,7 +2597,7 @@ bool bgp_debug_keepalive(const struct peer *peer)
        if (peer)
                host = peer->host;
 
-       return bgp_debug_per_peer(host, term_bgp_debug_keepalive,
+       return bgp_debug_per_peer(host, NULL, term_bgp_debug_keepalive,
                                  BGP_DEBUG_KEEPALIVE,
                                  bgp_debug_keepalive_peers);
 }
@@ -2571,7 +2611,7 @@ bool bgp_debug_update(const struct peer *peer, const struct prefix *p,
                host = peer->host;
 
        if (inbound) {
-               if (bgp_debug_per_peer(host, term_bgp_debug_update,
+               if (bgp_debug_per_peer(host, p, term_bgp_debug_update,
                                       BGP_DEBUG_UPDATE_IN,
                                       bgp_debug_update_in_peers))
                        return true;
@@ -2579,7 +2619,7 @@ bool bgp_debug_update(const struct peer *peer, const struct prefix *p,
 
        /* outbound */
        else {
-               if (bgp_debug_per_peer(host, term_bgp_debug_update,
+               if (bgp_debug_per_peer(host, p, term_bgp_debug_update,
                                       BGP_DEBUG_UPDATE_OUT,
                                       bgp_debug_update_out_peers))
                        return true;
index 118325e0a34e715b93d504e39c9304470a4acbd4..4e930c244ce44617b7b821af3cd64bb22d5ce8ce 100644 (file)
@@ -96,6 +96,7 @@ extern struct list *bgp_debug_zebra_prefixes;
 
 struct bgp_debug_filter {
        char *host;
+       char *plist_name;
        struct prefix *p;
 };