summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_ecommunity.c6
-rw-r--r--bgpd/bgp_ecommunity.h3
-rw-r--r--bgpd/bgp_flowspec_vty.c26
-rw-r--r--bgpd/bgp_pbr.c94
-rw-r--r--bgpd/bgp_pbr.h1
-rw-r--r--bgpd/bgp_zebra.c37
6 files changed, 132 insertions, 35 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index f2aac3646c..c7fabb396a 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -1052,7 +1052,8 @@ bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
}
int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
- struct bgp_pbr_entry_action *api)
+ struct bgp_pbr_entry_action *api,
+ afi_t afi)
{
if (ecom_eval->val[1] == ECOMMUNITY_TRAFFIC_RATE) {
api->action = ACTION_TRAFFICRATE;
@@ -1076,7 +1077,8 @@ int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
} else if (ecom_eval->val[1] == ECOMMUNITY_REDIRECT_VRF) {
/* must use external function */
return 0;
- } else if (ecom_eval->val[1] == ECOMMUNITY_REDIRECT_IP_NH) {
+ } else if (ecom_eval->val[1] == ECOMMUNITY_REDIRECT_IP_NH &&
+ afi == AFI_IP) {
/* see draft-ietf-idr-flowspec-redirect-ip-02
* Q1: how come a ext. community can host ipv6 address
* Q2 : from cisco documentation:
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 812bcc46e7..8ae3b44bab 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -222,7 +222,8 @@ extern bool ecommunity_del_val(struct ecommunity *ecom,
struct ecommunity_val *eval);
struct bgp_pbr_entry_action;
extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
- struct bgp_pbr_entry_action *api);
+ struct bgp_pbr_entry_action *api,
+ afi_t afi);
extern void bgp_compute_aggregate_ecommunity(
struct bgp_aggregate *aggregate,
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index 4b1d26b2fe..3e3366bf8b 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -325,10 +325,28 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
json_object_array_add(json_paths,
json_ecom_path);
}
- if (attr->nexthop.s_addr != 0 &&
- display == NLRI_STRING_FORMAT_LARGE)
- vty_out(vty, "\tNLRI NH %-16s\n",
- inet_ntoa(attr->nexthop));
+ if (display == NLRI_STRING_FORMAT_LARGE) {
+ char local_buff[INET6_ADDRSTRLEN];
+
+ local_buff[0] = '\0';
+ if (p->u.prefix_flowspec.family == AF_INET &&
+ attr->nexthop.s_addr != 0)
+ inet_ntop(AF_INET,
+ &attr->nexthop.s_addr,
+ local_buff,
+ INET6_ADDRSTRLEN);
+ else if (p->u.prefix_flowspec.family == AF_INET6 &&
+ attr->mp_nexthop_len != 0 &&
+ attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV4 &&
+ attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV4)
+ inet_ntop(AF_INET6,
+ &attr->mp_nexthop_global,
+ local_buff,
+ INET6_ADDRSTRLEN);
+ if (local_buff[0] != '\0')
+ vty_out(vty, "\tNLRI NH %s\n",
+ local_buff);
+ }
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
peer_uptime(path->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 715781143f..9446575611 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -248,6 +248,7 @@ struct bgp_pbr_val_mask {
struct bgp_pbr_filter {
uint8_t type;
vrf_id_t vrf_id;
+ uint8_t family;
struct prefix *src;
struct prefix *dst;
uint8_t bitmask_iprule;
@@ -793,9 +794,10 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
* do not overwrite
* draft-ietf-idr-flowspec-redirect
*/
- if (api_action_redirect_ip) {
- if (api_action_redirect_ip->u.zr
- .redirect_ip_v4.s_addr
+ if (api_action_redirect_ip &&
+ p->u.prefix_flowspec.family == AF_INET) {
+ if (api_action_redirect_ip->u
+ .zr.redirect_ip_v4.s_addr
!= INADDR_ANY)
continue;
if (path->attr->nexthop.s_addr
@@ -807,13 +809,42 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
api_action_redirect_ip->u.zr.duplicate
= ecom_eval->val[7];
continue;
- } else {
+ } else if (api_action_redirect_ip &&
+ p->u.prefix_flowspec.family == AF_INET6) {
+ if (memcmp(&api_action_redirect_ip->u
+ .zr.redirect_ip_v6,
+ &in6addr_any,
+ sizeof(struct in6_addr)))
+ continue;
+ if (path->attr->mp_nexthop_len == 0 ||
+ path->attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV4 ||
+ path->attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_VPNV4)
+ continue;
+ memcpy(&api_action_redirect_ip->u
+ .zr.redirect_ip_v6,
+ &path->attr->mp_nexthop_global,
+ sizeof(struct in6_addr));
+ api_action_redirect_ip->u.zr.duplicate
+ = ecom_eval->val[7];
+ continue;
+ } else if (p->u.prefix_flowspec.family == AF_INET) {
api_action->action = ACTION_REDIRECT_IP;
api_action->u.zr.redirect_ip_v4.s_addr =
path->attr->nexthop.s_addr;
api_action->u.zr.duplicate =
ecom_eval->val[7];
api_action_redirect_ip = api_action;
+ } else if (p->u.prefix_flowspec.family == AF_INET6) {
+ api_action->action = ACTION_REDIRECT_IP;
+ memcpy(&api_action->u
+ .zr.redirect_ip_v6,
+ &path->attr->mp_nexthop_global,
+ sizeof(struct in6_addr));
+ api_action->u.zr.duplicate
+ = ecom_eval->val[7];
+ api_action_redirect_ip = api_action;
}
} else if ((ecom_eval->val[0] ==
(char)ECOMMUNITY_ENCODE_IP) &&
@@ -845,7 +876,8 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
(char)ECOMMUNITY_ENCODE_TRANS_EXP)
continue;
ret = ecommunity_fill_pbr_action(ecom_eval,
- api_action);
+ api_action,
+ afi);
if (ret != 0)
continue;
if ((api_action->action == ACTION_TRAFFICRATE) &&
@@ -1181,6 +1213,7 @@ uint32_t bgp_pbr_action_hash_key(const void *arg)
pbra = arg;
key = jhash_1word(pbra->table_id, 0x4312abde);
key = jhash_1word(pbra->fwmark, key);
+ key = jhash_1word(pbra->afi, key);
return key;
}
@@ -1198,6 +1231,9 @@ bool bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
if (r1->vrf_id != r2->vrf_id)
return false;
+ if (r1->afi != r2->afi)
+ return false;
+
if (memcmp(&r1->nh, &r2->nh, sizeof(struct nexthop)))
return false;
@@ -1515,18 +1551,25 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
ptr += delta;
}
break;
- case ACTION_REDIRECT_IP:
- char local_buff[INET_ADDRSTRLEN];
+ case ACTION_REDIRECT_IP: {
+ char local_buff[INET6_ADDRSTRLEN];
+ void *ptr_ip;
INCREMENT_DISPLAY(ptr, nb_items, len);
- if (inet_ntop(AF_INET,
- &api->actions[i].u.zr.redirect_ip_v4,
- local_buff, INET_ADDRSTRLEN) != NULL)
+ if (api->afi == AF_INET)
+ ptr_ip = &api->actions[i].u.zr.redirect_ip_v4;
+ else
+ ptr_ip = &api->actions[i].u.zr.redirect_ip_v6;
+ if (inet_ntop(afi2family(api->afi),
+ ptr_ip, local_buff,
+ INET6_ADDRSTRLEN) != NULL) {
delta = snprintf(ptr, len,
"@redirect ip nh %s", local_buff);
len -= delta;
ptr += delta;
+ }
break;
+ }
case ACTION_REDIRECT: {
struct vrf *vrf;
@@ -1639,7 +1682,7 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
if (bpa->installed && bpa->table_id != 0) {
bgp_send_pbr_rule_action(bpa, NULL, false);
bgp_zebra_announce_default(bpa->bgp, &(bpa->nh),
- AFI_IP,
+ bpa->afi,
bpa->table_id,
false);
bpa->installed = false;
@@ -1794,12 +1837,12 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(
temp.flags |= MATCH_IP_SRC_SET;
prefix_copy(&temp2.src, bpf->src);
} else
- temp2.src.family = AF_INET;
+ temp2.src.family = bpf->family;
if (bpf->dst) {
temp.flags |= MATCH_IP_DST_SET;
prefix_copy(&temp2.dst, bpf->dst);
} else
- temp2.dst.family = AF_INET;
+ temp2.dst.family = bpf->family;
if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
if (bpf->protocol == IPPROTO_ICMP)
temp.flags |= MATCH_ICMP_SET;
@@ -2200,6 +2243,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
if (nh)
memcpy(&temp3.nh, nh, sizeof(struct nexthop));
temp3.vrf_id = bpf->vrf_id;
+ temp3.afi = family2afi(bpf->family);
bpa = hash_get(bgp->pbr_action_hash, &temp3,
bgp_pbr_action_alloc_intern);
@@ -2258,7 +2302,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
if (!bpa->installed && !bpa->install_in_progress) {
bgp_send_pbr_rule_action(bpa, NULL, true);
bgp_zebra_announce_default(bgp, nh,
- AFI_IP, bpa->table_id, true);
+ bpa->afi,
+ bpa->table_id, true);
}
/* ip rule add */
if (bpr && !bpr->installed)
@@ -2377,11 +2422,11 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
if (bpf->src)
prefix_copy(&temp2.src, bpf->src);
else
- temp2.src.family = AF_INET;
+ temp2.src.family = bpf->family;
if (bpf->dst)
prefix_copy(&temp2.dst, bpf->dst);
else
- temp2.dst.family = AF_INET;
+ temp2.dst.family = bpf->family;
temp2.src_port_min = src_port ? src_port->min_port : 0;
temp2.dst_port_min = dst_port ? dst_port->min_port : 0;
temp2.src_port_max = src_port ? src_port->max_port : 0;
@@ -2428,7 +2473,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
if (!bpa->installed && !bpa->install_in_progress) {
bgp_send_pbr_rule_action(bpa, NULL, true);
bgp_zebra_announce_default(bgp, nh,
- AFI_IP, bpa->table_id, true);
+ bpa->afi, bpa->table_id, true);
}
/* ipset create */
@@ -2690,6 +2735,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
bpf.protocol = proto;
bpf.src_port = srcp;
bpf.dst_port = dstp;
+ bpf.family = afi2family(api->afi);
if (!add) {
bgp_pbr_policyroute_remove_from_zebra(bgp, path, &bpf, &bpof);
return;
@@ -2739,10 +2785,18 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
*/
break;
case ACTION_REDIRECT_IP:
- nh.type = NEXTHOP_TYPE_IPV4;
- nh.gate.ipv4.s_addr =
- api->actions[i].u.zr.redirect_ip_v4.s_addr;
nh.vrf_id = api->vrf_id;
+ if (api->afi == AFI_IP) {
+ nh.type = NEXTHOP_TYPE_IPV4;
+ nh.gate.ipv4.s_addr =
+ api->actions[i].u.zr.
+ redirect_ip_v4.s_addr;
+ } else {
+ nh.type = NEXTHOP_TYPE_IPV6;
+ memcpy(&nh.gate.ipv6,
+ &api->actions[i].u.zr.redirect_ip_v6,
+ sizeof(struct in6_addr));
+ }
bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
&nh, &rate);
/* XXX combination with REDIRECT_VRF
diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h
index 403300dc03..ff333d2f10 100644
--- a/bgpd/bgp_pbr.h
+++ b/bgpd/bgp_pbr.h
@@ -260,6 +260,7 @@ struct bgp_pbr_action {
bool install_in_progress;
uint32_t refcnt;
struct bgp *bgp;
+ afi_t afi;
};
extern struct bgp_pbr_rule *bgp_pbr_rule_lookup(vrf_id_t vrf_id,
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 87936f1dd6..bf32d493bc 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2356,7 +2356,10 @@ static void bgp_encode_pbr_rule_action(struct stream *s,
struct bgp_pbr_rule *pbr)
{
struct prefix pfx;
+ uint8_t fam = AF_INET;
+ if (pbra && pbra->nh.type == NEXTHOP_TYPE_IPV6)
+ fam = AF_INET6;
stream_putl(s, 0); /* seqno unused */
if (pbr)
stream_putl(s, pbr->priority);
@@ -2376,7 +2379,7 @@ static void bgp_encode_pbr_rule_action(struct stream *s,
memcpy(&pfx, &(pbr->src), sizeof(struct prefix));
else {
memset(&pfx, 0, sizeof(pfx));
- pfx.family = AF_INET;
+ pfx.family = fam;
}
stream_putc(s, pfx.family);
stream_putc(s, pfx.prefixlen);
@@ -2388,7 +2391,7 @@ static void bgp_encode_pbr_rule_action(struct stream *s,
memcpy(&pfx, &(pbr->dst), sizeof(struct prefix));
else {
memset(&pfx, 0, sizeof(pfx));
- pfx.family = AF_INET;
+ pfx.family = fam;
}
stream_putc(s, pfx.family);
stream_putc(s, pfx.prefixlen);
@@ -3063,14 +3066,14 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
struct zapi_route api;
struct prefix p;
- if (!nh || nh->type != NEXTHOP_TYPE_IPV4
+ if (!nh || (nh->type != NEXTHOP_TYPE_IPV4
+ && nh->type != NEXTHOP_TYPE_IPV6)
|| nh->vrf_id == VRF_UNKNOWN)
return;
memset(&p, 0, sizeof(struct prefix));
- /* default route */
- if (afi != AFI_IP)
+ if (afi != AFI_IP && afi != AFI_IP6)
return;
- p.family = AF_INET;
+ p.family = afi2family(afi);
memset(&api, 0, sizeof(api));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
@@ -3086,7 +3089,7 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
/* redirect IP */
- if (nh->gate.ipv4.s_addr != INADDR_ANY) {
+ if (afi == AFI_IP && nh->gate.ipv4.s_addr != INADDR_ANY) {
char buff[PREFIX_STRLEN];
api_nh->vrf_id = nh->vrf_id;
@@ -3095,7 +3098,25 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
inet_ntop(AF_INET, &(nh->gate.ipv4), buff, INET_ADDRSTRLEN);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_info("BGP: %s default route to %s table %d (redirect IP)",
+ zlog_debug("BGP: %s default route to %s table %d (redirect IP)",
+ announce ? "adding" : "withdrawing",
+ buff, table_id);
+ zclient_route_send(announce ? ZEBRA_ROUTE_ADD
+ : ZEBRA_ROUTE_DELETE,
+ zclient, &api);
+ } else if (afi == AFI_IP6 &&
+ memcmp(&nh->gate.ipv6,
+ &in6addr_any, sizeof(struct in6_addr))) {
+ char buff[PREFIX_STRLEN];
+
+ api_nh->vrf_id = nh->vrf_id;
+ memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6,
+ sizeof(struct in6_addr));
+ api_nh->type = NEXTHOP_TYPE_IPV6;
+
+ inet_ntop(AF_INET6, &(nh->gate.ipv6), buff, INET_ADDRSTRLEN);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("BGP: %s default route to %s table %d (redirect IP)",
announce ? "adding" : "withdrawing",
buff, table_id);
zclient_route_send(announce ? ZEBRA_ROUTE_ADD