]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: enhance show bgp ipv4 flowspec <IP>
authorPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 15 Mar 2018 12:32:04 +0000 (13:32 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 30 Mar 2018 12:01:06 +0000 (14:01 +0200)
This command gives detail about a FS entry which contains an IP that
matches one of the rules of the FS entry. The output is the same output
as when one does show bgp ipv4 flowspec detail

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

index 6b7a3d0063d646a85e2d6a39ad585042b6be155b..7391a7b80aeb60bf0db06f84765c8e838d353239 100644 (file)
 #include "zebra.h"
 
 #include "prefix.h"
+
+#include "bgp_table.h"
 #include "bgp_flowspec_util.h"
+#include "bgp_flowspec_private.h"
 
 static void hex2bin(uint8_t *hex, int *bin)
 {
@@ -288,3 +291,106 @@ int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
                *error = -1;
        return offset;
 }
+
+
+static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
+                                        struct prefix *input,
+                                        int prefix_check)
+{
+       uint32_t offset = 0;
+       int type;
+       int ret = 0, error = 0;
+       uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr;
+       size_t len = pfs->u.prefix_flowspec.prefixlen;
+       struct prefix compare;
+
+       error = 0;
+       while (offset < len-1 && error >= 0) {
+               type = nlri_content[offset];
+               offset++;
+               switch (type) {
+               case FLOWSPEC_DEST_PREFIX:
+               case FLOWSPEC_SRC_PREFIX:
+                       memset(&compare, 0, sizeof(struct prefix));
+                       ret = bgp_flowspec_ip_address(
+                                       BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
+                                       nlri_content+offset,
+                                       len - offset,
+                                       &compare, &error);
+                       if (ret <= 0)
+                               break;
+                       if (prefix_check &&
+                           compare.prefixlen != input->prefixlen)
+                               break;
+                       if (compare.family != input->family)
+                               break;
+                       if ((input->family == AF_INET) &&
+                           IPV4_ADDR_SAME(&input->u.prefix4,
+                                          &compare.u.prefix4))
+                               return true;
+                       if ((input->family == AF_INET6) &&
+                           IPV6_ADDR_SAME(&input->u.prefix6.s6_addr,
+                                          &compare.u.prefix6.s6_addr))
+                               return true;
+                       break;
+               case FLOWSPEC_IP_PROTOCOL:
+               case FLOWSPEC_PORT:
+               case FLOWSPEC_DEST_PORT:
+               case FLOWSPEC_SRC_PORT:
+               case FLOWSPEC_ICMP_TYPE:
+               case FLOWSPEC_ICMP_CODE:
+                       ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_VALIDATE_ONLY,
+                                                    nlri_content+offset,
+                                                    len - offset,
+                                                    NULL, &error);
+                       break;
+               case FLOWSPEC_TCP_FLAGS:
+                       ret = bgp_flowspec_tcpflags_decode(
+                                               BGP_FLOWSPEC_VALIDATE_ONLY,
+                                               nlri_content+offset,
+                                               len - offset,
+                                               NULL, &error);
+                       break;
+               case FLOWSPEC_PKT_LEN:
+               case FLOWSPEC_DSCP:
+                       ret = bgp_flowspec_op_decode(
+                                               BGP_FLOWSPEC_VALIDATE_ONLY,
+                                               nlri_content + offset,
+                                               len - offset, NULL,
+                                               &error);
+                       break;
+               case FLOWSPEC_FRAGMENT:
+                       ret = bgp_flowspec_fragment_type_decode(
+                                               BGP_FLOWSPEC_VALIDATE_ONLY,
+                                               nlri_content + offset,
+                                               len - offset, NULL,
+                                               &error);
+                       break;
+               default:
+                       error = -1;
+                       break;
+               }
+               offset += ret;
+       }
+       return false;
+}
+
+struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi,
+                                              struct bgp_table *rib,
+                                              struct prefix *match,
+                                              int prefix_check)
+{
+       struct bgp_node *rn;
+       struct prefix *prefix;
+
+       for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
+               prefix = &rn->p;
+
+               if (prefix->family != AF_FLOWSPEC)
+                       continue;
+
+               if (bgp_flowspec_contains_prefix(prefix, match, prefix_check))
+                       return rn;
+       }
+       return NULL;
+}
index 5d262dbbc788971db1b479e6cb6b6652a7484909..aa214611021defb8803dc6abe391b81373b029c7 100644 (file)
@@ -51,4 +51,8 @@ extern int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
                                             uint32_t max_len,
                                             void *result, int *error);
 
+extern struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi,
+                                                     struct bgp_table *rib,
+                                                     struct prefix *match,
+                                                     int prefix_check);
 #endif /* _FRR_BGP_FLOWSPEC_UTIL_H */
index ad3d57a9ae817aed36ae5ebe8ed375a39ecbeaa0..e4769fe1d67748d37bf30d3ec8f3d3d20a39f4d4 100644 (file)
@@ -74,6 +74,7 @@
 #include "bgpd/bgp_evpn.h"
 #include "bgpd/bgp_evpn_vty.h"
 #include "bgpd/bgp_flowspec.h"
+#include "bgpd/bgp_flowspec_util.h"
 
 #ifndef VTYSH_EXTRACT_PL
 #include "bgpd/bgp_route_clippy.c"
@@ -8724,6 +8725,18 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
 
                        bgp_unlock_node(rm);
                }
+       } else if (safi == SAFI_FLOWSPEC) {
+               rn = bgp_flowspec_get_match_per_ip(afi, rib,
+                                                  &match, prefix_check);
+               if (rn != NULL) {
+                       route_vty_out_flowspec(vty, &rn->p,
+                                              rn->info, use_json ?
+                                              NLRI_STRING_FORMAT_JSON :
+                                              NLRI_STRING_FORMAT_LARGE,
+                                              json_paths);
+                       display++;
+                       bgp_unlock_node(rn);
+               }
        } else {
                header = 1;