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
#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;
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:
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)",
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");
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;
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) {
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,
return ret;
}
+
bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
struct prefix *input, int prefix_check)
{
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;
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
nlri_content+offset,
len - offset,
- &compare, &error);
+ &compare, &error,
+ afi);
if (ret <= 0)
break;
if (prefix_check &&
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;
}
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;
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",
/* 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;
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;
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,
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 */
*/
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;
type_util,
nlri_content+offset,
len - offset,
- local_string, &error);
+ local_string, &error,
+ afi);
if (ret <= 0)
break;
if (json_path) {
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)
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)
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) {
}
/* 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)
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 */
{
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. */
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;
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
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 ||