diff options
author | Russ White <russ@riw.us> | 2019-07-09 16:12:21 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-09 16:12:21 +0200 |
commit | 5ace71fff7be4e6d90e05d19f915c0e9dae7aea1 (patch) | |
tree | 721f08d214f7450255d2eeed75c4653cf4f59852 | |
parent | Merge pull request #4643 from pguibert6WIND/pytest_compat (diff) | |
parent | bgpd: extend bgp routemap prefix-list to flowspec entries (diff) | |
download | frr-5ace71fff7be4e6d90e05d19f915c0e9dae7aea1.tar.xz frr-5ace71fff7be4e6d90e05d19f915c0e9dae7aea1.zip |
Merge pull request #4511 from pguibert6WIND/flowspec_some_fixes
Flowspec some fixes
-rw-r--r-- | bgpd/bgp_pbr.c | 21 | ||||
-rw-r--r-- | bgpd/bgp_pbr.h | 1 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 83 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 1 | ||||
-rw-r--r-- | lib/pbr.h | 1 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 1 | ||||
-rw-r--r-- | zebra/zebra_pbr.c | 7 | ||||
-rw-r--r-- | zebra/zebra_pbr.h | 1 |
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. */ @@ -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; |