summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2019-07-09 16:12:21 +0200
committerGitHub <noreply@github.com>2019-07-09 16:12:21 +0200
commit5ace71fff7be4e6d90e05d19f915c0e9dae7aea1 (patch)
tree721f08d214f7450255d2eeed75c4653cf4f59852
parentMerge pull request #4643 from pguibert6WIND/pytest_compat (diff)
parentbgpd: extend bgp routemap prefix-list to flowspec entries (diff)
downloadfrr-5ace71fff7be4e6d90e05d19f915c0e9dae7aea1.tar.xz
frr-5ace71fff7be4e6d90e05d19f915c0e9dae7aea1.zip
Merge pull request #4511 from pguibert6WIND/flowspec_some_fixes
Flowspec some fixes
-rw-r--r--bgpd/bgp_pbr.c21
-rw-r--r--bgpd/bgp_pbr.h1
-rw-r--r--bgpd/bgp_routemap.c83
-rw-r--r--bgpd/bgp_zebra.c1
-rw-r--r--lib/pbr.h1
-rw-r--r--zebra/zapi_msg.c1
-rw-r--r--zebra/zebra_pbr.c7
-rw-r--r--zebra/zebra_pbr.h1
8 files changed, 92 insertions, 24 deletions
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 5eef6ac6c..2d50d1c9e 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -698,6 +698,7 @@ int bgp_pbr_build_and_validate_entry(struct prefix *p,
int valid_prefix = 0;
afi_t afi = AFI_IP;
struct bgp_pbr_entry_action *api_action_redirect_ip = NULL;
+ bool discard_action_found = false;
/* extract match from flowspec entries */
ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr,
@@ -805,10 +806,22 @@ int bgp_pbr_build_and_validate_entry(struct prefix *p,
api_action);
if (ret != 0)
continue;
+ if ((api_action->action == ACTION_TRAFFICRATE) &&
+ api->actions[i].u.r.rate == 0)
+ discard_action_found = true;
}
api->action_num++;
}
}
+ /* if ECOMMUNITY_TRAFFIC_RATE = 0 as action
+ * then reduce the API action list to that action
+ */
+ if (api->action_num > 1 && discard_action_found) {
+ api->action_num = 1;
+ memset(&api->actions[0], 0,
+ sizeof(struct bgp_pbr_entry_action));
+ api->actions[0].action = ACTION_TRAFFICRATE;
+ }
/* validate if incoming matc/action is compatible
* with our policy routing engine
@@ -977,6 +990,7 @@ uint32_t bgp_pbr_match_hash_key(const void *arg)
key = jhash(&pbm->tcp_mask_flags, 2, key);
key = jhash(&pbm->dscp_value, 1, key);
key = jhash(&pbm->fragment, 1, key);
+ key = jhash(&pbm->protocol, 1, key);
return jhash_1word(pbm->type, key);
}
@@ -1016,6 +1030,9 @@ bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
if (r1->fragment != r2->fragment)
return false;
+
+ if (r1->protocol != r2->protocol)
+ return false;
return true;
}
@@ -2162,6 +2179,10 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
temp.fragment = bpf->fragment->val;
}
+ if (bpf->protocol) {
+ temp.protocol = bpf->protocol;
+ temp.flags |= MATCH_PROTOCOL_SET;
+ }
temp.action = bpa;
bpm = hash_get(bgp->pbr_match_hash, &temp,
bgp_pbr_match_alloc_intern);
diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h
index b368d8892..393b08da4 100644
--- a/bgpd/bgp_pbr.h
+++ b/bgpd/bgp_pbr.h
@@ -186,6 +186,7 @@ struct bgp_pbr_match {
uint16_t tcp_mask_flags;
uint8_t dscp_value;
uint8_t fragment;
+ uint8_t protocol;
vrf_id_t vrf_id;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index e43f9486f..24c8cc442 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -60,6 +60,8 @@
#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_vty.h"
#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_pbr.h"
+#include "bgpd/bgp_flowspec_util.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
@@ -569,24 +571,67 @@ struct route_map_rule_cmd route_match_ip_route_source_cmd = {
"ip route-source", route_match_ip_route_source,
route_match_ip_route_source_compile, route_match_ip_route_source_free};
-/* `match ip address prefix-list PREFIX_LIST' */
+static route_map_result_t route_match_prefix_list_flowspec(afi_t afi,
+ struct prefix_list *plist,
+ const struct prefix *p)
+{
+ int ret;
+ struct bgp_pbr_entry_main api;
+
+ memset(&api, 0, sizeof(api));
+
+ /* extract match from flowspec entries */
+ ret = bgp_flowspec_match_rules_fill(
+ (uint8_t *)p->u.prefix_flowspec.ptr,
+ p->u.prefix_flowspec.prefixlen, &api);
+ if (ret < 0)
+ return RMAP_NOMATCH;
+ if (api.match_bitmask & PREFIX_DST_PRESENT ||
+ api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
+ if (family2afi((&api.dst_prefix)->family) != afi)
+ return RMAP_NOMATCH;
+ return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
+ ? RMAP_NOMATCH
+ : RMAP_MATCH;
+ } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
+ api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
+ if (family2afi((&api.src_prefix)->family) != afi)
+ return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
+ ? RMAP_NOMATCH
+ : RMAP_MATCH);
+ }
+ return RMAP_NOMATCH;
+}
+/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_address_prefix_list(void *rule, afi_t afi,
+ const struct prefix *prefix,
+ route_map_object_t type, void *object)
{
struct prefix_list *plist;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ if (type != RMAP_BGP)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, prefix) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(afi, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
+
+ if (prefix->family == AF_FLOWSPEC)
+ return route_match_prefix_list_flowspec(afi, plist,
+ prefix);
+ return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
+}
+
+static route_map_result_t
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ return route_match_address_prefix_list(rule, AFI_IP, prefix, type,
+ object);
}
static void *route_match_ip_address_prefix_list_compile(const char *arg)
@@ -2540,18 +2585,8 @@ static route_map_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
- struct prefix_list *plist;
-
- if (type == RMAP_BGP && prefix->family == AF_INET6) {
- plist = prefix_list_lookup(AFI_IP6, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
-
- return (prefix_list_apply(plist, prefix) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return route_match_address_prefix_list(rule, AFI_IP6, prefix, type,
+ object);
}
static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index c0f2dfca1..71f7f6d0e 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2436,6 +2436,7 @@ static void bgp_encode_pbr_iptable_match(struct stream *s,
stream_putw(s, pbm->tcp_mask_flags);
stream_putc(s, pbm->dscp_value);
stream_putc(s, pbm->fragment);
+ stream_putc(s, pbm->protocol);
}
/* BGP has established connection with Zebra. */
diff --git a/lib/pbr.h b/lib/pbr.h
index 1425e679c..ecd50447e 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -121,6 +121,7 @@ struct pbr_rule {
#define MATCH_PKT_LEN_INVERSE_SET (1 << 8)
#define MATCH_FRAGMENT_INVERSE_SET (1 << 9)
#define MATCH_ICMP_SET (1 << 10)
+#define MATCH_PROTOCOL_SET (1 << 11)
extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
struct pbr_rule *zrule);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 61200806b..9a638f8e7 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2432,6 +2432,7 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS)
STREAM_GETW(s, zpi.tcp_mask_flags);
STREAM_GETC(s, zpi.dscp_value);
STREAM_GETC(s, zpi.fragment);
+ STREAM_GETC(s, zpi.protocol);
STREAM_GETL(s, zpi.nb_interface);
zebra_pbr_iptable_update_interfacelist(s, &zpi);
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index a82dd4c24..f95a4ff95 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -373,6 +373,7 @@ uint32_t zebra_pbr_iptable_hash_key(const void *arg)
key = jhash_1word(iptable->tcp_flags, key);
key = jhash_1word(iptable->tcp_mask_flags, key);
key = jhash_1word(iptable->dscp_value, key);
+ key = jhash_1word(iptable->protocol, key);
key = jhash_1word(iptable->fragment, key);
key = jhash_1word(iptable->vrf_id, key);
@@ -414,6 +415,8 @@ bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
return false;
if (r1->fragment != r2->fragment)
return false;
+ if (r1->protocol != r2->protocol)
+ return false;
return true;
}
@@ -1095,6 +1098,10 @@ static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable,
" not" : "", lookup_msg(fragment_value_str,
iptable->fragment, val_str));
}
+ if (iptable->protocol) {
+ vty_out(vty, "\t protocol %d\n",
+ iptable->protocol);
+ }
ret = hook_call(zebra_pbr_iptable_get_stat, iptable, &pkts,
&bytes);
if (ret && pkts > 0)
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index cc1cc5acd..fcc9c5c39 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -145,6 +145,7 @@ struct zebra_pbr_iptable {
uint16_t tcp_mask_flags;
uint8_t dscp_value;
uint8_t fragment;
+ uint8_t protocol;
uint32_t nb_interface;