summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_flowspec_util.c106
-rw-r--r--bgpd/bgp_flowspec_util.h4
-rw-r--r--bgpd/bgp_route.c13
3 files changed, 123 insertions, 0 deletions
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 6b7a3d0063..7391a7b80a 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -21,7 +21,10 @@
#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;
+}
diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h
index 5d262dbbc7..aa21461102 100644
--- a/bgpd/bgp_flowspec_util.h
+++ b/bgpd/bgp_flowspec_util.h
@@ -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 */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index ad3d57a9ae..e4769fe1d6 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -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;