bgpd: flowspec code support for ipv6

until now, the assumption was done in bgp flowspec code that the
information contained was an ipv4 flowspec prefix. now that it is
possible to handle ipv4 or ipv6 flowspec prefixes, that information is
stored in prefix_flowspec attribute. Also, some unlocking is done in
order to process ipv4 and ipv6 flowspec entries.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2019-10-14 18:02:22 +02:00
parent e4552d667a
commit 1840384bae
11 changed files with 62 additions and 32 deletions

View file

@ -2692,7 +2692,8 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
bgp_fs_nlri_get_string((unsigned char *)fs->prefix.ptr,
fs->prefix.prefixlen,
return_string,
NLRI_STRING_FORMAT_DEBUG, NULL);
NLRI_STRING_FORMAT_DEBUG, NULL,
family2afi(fs->prefix.family));
snprintf(str, size, "FS %s Match{%s}", afi2str(afi),
return_string);
} else

View file

@ -33,7 +33,8 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_errors.h"
static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len)
static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len,
afi_t afi)
{
uint32_t offset = 0;
int type;
@ -48,7 +49,8 @@ static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len)
ret = bgp_flowspec_ip_address(
BGP_FLOWSPEC_VALIDATE_ONLY,
nlri_content + offset,
len - offset, NULL, &error);
len - offset, NULL, &error,
afi);
break;
case FLOWSPEC_IP_PROTOCOL:
case FLOWSPEC_PORT:
@ -103,11 +105,6 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
afi = packet->afi;
safi = packet->safi;
if (afi == AFI_IP6) {
flog_err(EC_LIB_DEVELOPMENT, "BGP flowspec IPv6 not supported");
return BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED;
}
if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT_EXTENDED) {
flog_err(EC_BGP_FLOWSPEC_PACKET,
"BGP flowspec nlri length maximum reached (%u)",
@ -137,7 +134,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
psize);
return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
if (bgp_fs_nlri_validate(pnt, psize) < 0) {
if (bgp_fs_nlri_validate(pnt, psize, afi) < 0) {
flog_err(
EC_BGP_FLOWSPEC_PACKET,
"Bad flowspec format or NLRI options not supported");
@ -147,6 +144,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
p.prefixlen = 0;
/* Flowspec encoding is in bytes */
p.u.prefix_flowspec.prefixlen = psize;
p.u.prefix_flowspec.family = afi2family(afi);
temp = XCALLOC(MTYPE_TMP, psize);
memcpy(temp, pnt, psize);
p.u.prefix_flowspec.ptr = (uintptr_t) temp;
@ -161,7 +159,8 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
p.u.prefix_flowspec.ptr,
p.u.prefix_flowspec.prefixlen,
return_string,
NLRI_STRING_FORMAT_MIN, NULL);
NLRI_STRING_FORMAT_MIN, NULL,
afi);
snprintf(ec_string, sizeof(ec_string),
"EC{none}");
if (attr && attr->ecommunity) {

View file

@ -41,7 +41,8 @@ extern int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
char *return_string, int format,
json_object *json_path);
json_object *json_path,
afi_t afi);
extern void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,

View file

@ -76,6 +76,7 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len,
return ret;
}
bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
struct prefix *input, int prefix_check)
{
@ -84,6 +85,7 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
int ret = 0, error = 0;
uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr;
size_t len = pfs->u.prefix_flowspec.prefixlen;
afi_t afi = family2afi(pfs->u.prefix_flowspec.family);
struct prefix compare;
error = 0;
@ -98,7 +100,8 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
nlri_content+offset,
len - offset,
&compare, &error);
&compare, &error,
afi);
if (ret <= 0)
break;
if (prefix_check &&
@ -158,7 +161,8 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
uint8_t *nlri_ptr,
uint32_t max_len,
void *result, int *error)
void *result, int *error,
afi_t afi)
{
char *display = (char *)result; /* for return_string */
struct prefix *prefix = (struct prefix *)result;
@ -417,7 +421,8 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
}
int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
struct bgp_pbr_entry_main *bpem)
struct bgp_pbr_entry_main *bpem,
afi_t afi)
{
int offset = 0, error = 0;
struct prefix *prefix;
@ -444,7 +449,8 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
nlri_content + offset,
len - offset,
prefix, &error);
prefix, &error,
afi);
if (error < 0)
flog_err(EC_BGP_FLOWSPEC_PACKET,
"%s: flowspec_ip_address error %d",
@ -599,7 +605,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
/* return 1 if FS entry invalid or no NH IP */
bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
struct prefix *p)
struct prefix *p, afi_t afi)
{
struct bgp_pbr_entry_main api;
int i;
@ -615,9 +621,15 @@ bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
api_action = &api.actions[i];
if (api_action->action != ACTION_REDIRECT_IP)
continue;
p->family = AF_INET;
p->prefixlen = IPV4_MAX_BITLEN;
p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
p->family = afi2family(afi);
if (afi == AFI_IP) {
p->prefixlen = IPV4_MAX_BITLEN;
p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
} else {
p->prefixlen = IPV6_MAX_BITLEN;
memcpy(&p->u.prefix6, &api_action->u.zr.redirect_ip_v6,
sizeof(struct in6_addr));
}
return false;
}
return true;

View file

@ -39,7 +39,8 @@ extern int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
extern int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
uint8_t *nlri_ptr,
uint32_t max_len,
void *result, int *error);
void *result, int *error,
afi_t afi);
extern int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
uint8_t *nlri_ptr,
@ -48,13 +49,14 @@ extern int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
struct bgp_pbr_entry_main;
extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
struct bgp_pbr_entry_main *bpem);
struct bgp_pbr_entry_main *bpem,
afi_t afi);
extern bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
struct prefix *input,
int prefix_check);
extern bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
struct prefix *nh);
struct prefix *nh, afi_t afi);
#endif /* _FRR_BGP_FLOWSPEC_UTIL_H */

View file

@ -93,7 +93,8 @@ static const struct message bgp_flowspec_display_min[] = {
*/
void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
char *return_string, int format,
json_object *json_path)
json_object *json_path,
afi_t afi)
{
uint32_t offset = 0;
int type;
@ -127,7 +128,8 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
type_util,
nlri_content+offset,
len - offset,
local_string, &error);
local_string, &error,
afi);
if (ret <= 0)
break;
if (json_path) {
@ -263,7 +265,12 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
json_object *json_ecom_path = NULL;
json_object *json_time_path = NULL;
char timebuf[BGP_UPTIME_LEN];
struct bgp_dest *dest = NULL;
if (path)
dest = path->net;
if (dest)
bgp_dest_get_bgp_table_info(dest);
/* Print prefix */
if (p != NULL) {
if (p->family != AF_FLOWSPEC)
@ -282,7 +289,9 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
p->u.prefix_flowspec.prefixlen,
return_string,
display,
json_nlri_path);
json_nlri_path,
family2afi(p->u.prefix_flowspec
.family));
if (display == NLRI_STRING_FORMAT_LARGE)
vty_out(vty, "%s", return_string);
else if (display == NLRI_STRING_FORMAT_DEBUG)

View file

@ -544,7 +544,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
if (!pi->peer)
return -1;
return bgp_flowspec_get_first_nh(pi->peer->bgp,
pi, p);
pi, p, afi);
}
memset(p, 0, sizeof(struct prefix));
switch (afi) {

View file

@ -668,6 +668,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
}
/* return -1 if build or validation failed */
int bgp_pbr_build_and_validate_entry(const struct prefix *p,
struct bgp_path_info *path,
struct bgp_pbr_entry_main *api)
@ -679,13 +680,13 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
struct bgp_pbr_entry_action *api_action;
struct prefix *src = NULL, *dst = NULL;
int valid_prefix = 0;
afi_t afi = AFI_IP;
struct bgp_pbr_entry_action *api_action_redirect_ip = NULL;
bool discard_action_found = false;
afi_t afi = family2afi(p->u.prefix_flowspec.family);
/* extract match from flowspec entries */
ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr,
p->u.prefix_flowspec.prefixlen, api);
p->u.prefix_flowspec.prefixlen, api, afi);
if (ret < 0)
return -1;
/* extract actiosn from flowspec ecom list */
@ -2598,8 +2599,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, const struct prefix *p,
{
struct bgp_pbr_entry_main api;
if (afi == AFI_IP6)
return; /* IPv6 not supported */
if (safi != SAFI_FLOWSPEC)
return; /* not supported */
/* Make Zebra API structure. */

View file

@ -79,6 +79,7 @@ struct bgp_pbr_entry_action {
vrf_id_t redirect_vrf;
struct _pbr_redirect_ip {
struct in_addr redirect_ip_v4;
struct in6_addr redirect_ip_v6;
uint8_t duplicate;
} zr;
uint8_t marking_dscp;

View file

@ -10008,11 +10008,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
if (dest_p->family == AF_FLOWSPEC) {
char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
bgp_fs_nlri_get_string(
(unsigned char *)
dest_p->u.prefix_flowspec.ptr,
dest_p->u.prefix_flowspec.prefixlen,
retstr, NLRI_STRING_FORMAT_MIN, NULL);
retstr, NLRI_STRING_FORMAT_MIN, NULL,
family2afi(dest_p->u.prefix_flowspec.family));
if (first)
vty_out(vty, "\"%s/%d\": ", retstr,
dest_p->u.prefix_flowspec

View file

@ -594,10 +594,14 @@ route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
memset(&api, 0, sizeof(api));
if (family2afi(p->u.prefix_flowspec.family) != afi)
return RMAP_NOMATCH;
/* extract match from flowspec entries */
ret = bgp_flowspec_match_rules_fill(
(uint8_t *)p->u.prefix_flowspec.ptr,
p->u.prefix_flowspec.prefixlen, &api);
p->u.prefix_flowspec.prefixlen, &api,
afi);
if (ret < 0)
return RMAP_NOMATCH;
if (api.match_bitmask & PREFIX_DST_PRESENT ||