return 0;
}
-/* Prefix SID attribute
- * draft-ietf-idr-bgp-prefix-sid-05
+/*
+ * Read an individual SID value returning how much data we have read
+ * Returns 0 if there was an error that needs to be passed up the stack
*/
-static bgp_attr_parse_ret_t
-bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
- struct bgp_nlri *mp_update)
+static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
+ int32_t length,
+ struct bgp_attr_parser_args *args,
+ struct bgp_nlri *mp_update)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
- int type;
- int length;
uint32_t label_index;
struct in6_addr ipv6_sid;
uint32_t srgb_base;
uint32_t srgb_range;
int srgb_count;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
-
- type = stream_getc(peer->curr);
- length = stream_getw(peer->curr);
-
if (type == BGP_PREFIX_SID_LABEL_INDEX) {
if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
zlog_err(
- "Prefix SID label index length is %d instead of %d",
- length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
+ "Prefix SID label index length is %d instead of %d",
+ length,
+ BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
+ return bgp_attr_malformed(args,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
}
/* Ignore flags and reserved */
/* Fetch the label index and see if it is valid. */
label_index = stream_getl(peer->curr);
if (label_index == BGP_INVALID_LABEL_INDEX)
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
- args->total);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ args->total);
/* Store label index; subsequently, we'll check on
* address-family */
if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
zlog_err("Prefix SID IPv6 length is %d instead of %d",
length, BGP_PREFIX_SID_IPV6_LENGTH);
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
+ return bgp_attr_malformed(args,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
}
/* Ignore reserved */
return BGP_ATTR_PARSE_PROCEED;
}
+/* Prefix SID attribute
+ * draft-ietf-idr-bgp-prefix-sid-05
+ */
+bgp_attr_parse_ret_t
+bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
+ struct bgp_nlri *mp_update)
+{
+ struct peer *const peer = args->peer;
+ struct attr *const attr = args->attr;
+ bgp_attr_parse_ret_t ret;
+
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
+
+ while (tlength) {
+ int32_t type, length;
+
+ type = stream_getc(peer->curr);
+ length = stream_getw(peer->curr);
+
+ ret = bgp_attr_psid_sub(type, length, args, mp_update);
+
+ if (ret != BGP_ATTR_PARSE_PROCEED)
+ return ret;
+ /*
+ * Subtract length + the T and the L
+ * since length is the Vector portion
+ */
+ tlength -= length + 3;
+
+ if (tlength < 0) {
+ zlog_err("Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
+ length);
+ return bgp_attr_malformed(args,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
+ }
+
+ return BGP_ATTR_PARSE_PROCEED;
+}
+
/* PMSI tunnel attribute (RFC 6514)
* Basic validation checks done here.
*/
startp);
break;
case BGP_ATTR_PREFIX_SID:
- ret = bgp_attr_prefix_sid(&attr_args, mp_update);
+ ret = bgp_attr_prefix_sid(length,
+ &attr_args, mp_update);
break;
case BGP_ATTR_PMSI_TUNNEL:
ret = bgp_attr_pmsi_tunnel(&attr_args);
struct bgp_nlri *);
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *);
+extern bgp_attr_parse_ret_t
+bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
+ struct bgp_nlri *mp_update);
extern struct bgp_attr_encap_subtlv *
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
dst->family = AF_EVPN;
p_evpn_p->route_type = evpn_type;
if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
- p_evpn_p->eth_tag = eth_tag;
- p_evpn_p->ip_prefix_length = p2.prefixlen;
+ p_evpn_p->prefix_addr.eth_tag = eth_tag;
+ p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) {
- SET_IPADDR_V4(&p_evpn_p->ip);
- memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
+ SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
+ memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
+ &src->u.prefix4,
sizeof(struct in_addr));
dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
} else {
- SET_IPADDR_V6(&p_evpn_p->ip);
- memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
+ SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
+ memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
+ &src->u.prefix6,
sizeof(struct in6_addr));
dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
}
s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
bgp->vrf_id);
stream_putl(s, vpn->vni);
- stream_put(s, &p->prefix.mac.octet, ETH_ALEN); /* Mac Addr */
+ stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN); /* Mac Addr */
/* IP address length and IP address, if any. */
- if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+ if (is_evpn_prefix_ipaddr_none(p))
stream_putl(s, 0);
else {
- ipa_len = IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BYTELEN
+ ipa_len = is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BYTELEN
: IPV6_MAX_BYTELEN;
stream_putl(s, ipa_len);
- stream_put(s, &p->prefix.ip.ip.addr, ipa_len);
+ stream_put(s, &p->prefix.macip_addr.ip.ip.addr, ipa_len);
}
stream_put_in_addr(s, &remote_vtep_ip);
zlog_debug(
"Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s",
add ? "ADD" : "DEL", vpn->vni,
- prefix_mac2str(&p->prefix.mac, buf1, sizeof(buf1)),
- ipaddr2str(&p->prefix.ip, buf3, sizeof(buf3)), flags,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
+ buf1, sizeof(buf1)),
+ ipaddr2str(&p->prefix.macip_addr.ip,
+ buf3, sizeof(buf3)), flags,
inet_ntop(AF_INET, &remote_vtep_ip, buf2,
sizeof(buf2)));
s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL,
bgp->vrf_id);
stream_putl(s, vpn->vni);
- if (IS_EVPN_PREFIX_IPADDR_V4(p))
- stream_put_in_addr(s, &p->prefix.ip.ipaddr_v4);
- else if (IS_EVPN_PREFIX_IPADDR_V6(p)) {
+ if (is_evpn_prefix_ipaddr_v4(p))
+ stream_put_in_addr(s, &p->prefix.imet_addr.ip.ipaddr_v4);
+ else if (is_evpn_prefix_ipaddr_v6(p)) {
zlog_err(
"Bad remote IP when trying to %s remote VTEP for VNI %u",
add ? "ADD" : "DEL", vpn->vni);
if (bgp_debug_zebra(NULL))
zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s",
add ? "ADD" : "DEL", vpn->vni,
- inet_ntoa(p->prefix.ip.ipaddr_v4));
+ inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
return zclient_send_message(zclient);
}
* these routes.
*/
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
- (IS_EVPN_PREFIX_IPADDR_V4(p) ||
- !IN6_IS_ADDR_LINKLOCAL(&p->prefix.ip.ipaddr_v6)) &&
+ (is_evpn_prefix_ipaddr_v4(p) ||
+ !IN6_IS_ADDR_LINKLOCAL(&p->prefix.macip_addr.ip.ipaddr_v6)) &&
CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
add_l3_ecomm = 1;
if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue;
- if (IS_EVPN_PREFIX_IPADDR_V6(evp) &&
- IN6_IS_ADDR_LINKLOCAL(&evp->prefix.ip.ipaddr_v6))
+ if (is_evpn_prefix_ipaddr_v6(evp) &&
+ IN6_IS_ADDR_LINKLOCAL(&evp->prefix.macip_addr.ip.ipaddr_v6))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_ip6_ll, 0, 1, &ri, 0);
else {
char buf1[PREFIX_STRLEN];
memset(pp, 0, sizeof(struct prefix));
- if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
- ip_prefix_from_type2_prefix(evp, pp);
- else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
- ip_prefix_from_type5_prefix(evp, pp);
+ ip_prefix_from_evpn_prefix(evp, pp);
if (bgp_debug_zebra(NULL)) {
zlog_debug(
/* Create (or fetch) route within the VRF. */
/* NOTE: There is no RD here. */
- if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+ if (is_evpn_prefix_ipaddr_v4(evp)) {
afi = AFI_IP;
safi = SAFI_UNICAST;
rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
- } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+ } else if (is_evpn_prefix_ipaddr_v6(evp)) {
afi = AFI_IP6;
safi = SAFI_UNICAST;
rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
char buf1[PREFIX_STRLEN];
memset(pp, 0, sizeof(struct prefix));
- if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
- ip_prefix_from_type2_prefix(evp, pp);
- else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
- ip_prefix_from_type5_prefix(evp, pp);
+ ip_prefix_from_evpn_prefix(evp, pp);
if (bgp_debug_zebra(NULL)) {
zlog_debug(
/* Locate route within the VRF. */
/* NOTE: There is no RD here. */
- if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+ if (is_evpn_prefix_ipaddr_v4(evp)) {
afi = AFI_IP;
safi = SAFI_UNICAST;
rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
continue;
/* if not a mac+ip route skip this route */
- if (!(IS_EVPN_PREFIX_IPADDR_V4(evp)
- || IS_EVPN_PREFIX_IPADDR_V6(evp)))
+ if (!(is_evpn_prefix_ipaddr_v4(evp)
+ || is_evpn_prefix_ipaddr_v6(evp)))
continue;
for (ri = rn->info; ri; ri = ri->next) {
/* if it is type-2 route and not a mac+ip route skip this route */
if ((evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
- && !(IS_EVPN_PREFIX_IPADDR_V4(evp)
- || IS_EVPN_PREFIX_IPADDR_V6(evp)))
+ && !(is_evpn_prefix_ipaddr_v4(evp)
+ || is_evpn_prefix_ipaddr_v6(evp)))
return 0;
for (ALL_LIST_ELEMENTS(vrfs, node, nnode, bgp_vrf)) {
/* Copy Ethernet Tag */
memcpy(ð_tag, pfx, 4);
- p.prefix.eth_tag = ntohl(eth_tag);
+ p.prefix.macip_addr.eth_tag = ntohl(eth_tag);
pfx += 4;
/* Get the MAC Addr len */
/* Get the MAC Addr */
if (macaddr_len == (ETH_ALEN * 8)) {
- memcpy(&p.prefix.mac.octet, pfx, ETH_ALEN);
+ memcpy(&p.prefix.macip_addr.mac.octet, pfx, ETH_ALEN);
pfx += ETH_ALEN;
} else {
zlog_err(
if (ipaddr_len) {
ipaddr_len /= 8; /* Convert to bytes. */
- p.prefix.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
+ p.prefix.macip_addr.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
? IPADDR_V4
: IPADDR_V6;
- memcpy(&p.prefix.ip.ip.addr, pfx, ipaddr_len);
+ memcpy(&p.prefix.macip_addr.ip.ip.addr, pfx, ipaddr_len);
}
pfx += ipaddr_len;
/* Copy Ethernet Tag */
memcpy(ð_tag, pfx, 4);
- p.prefix.eth_tag = ntohl(eth_tag);
+ p.prefix.imet_addr.eth_tag = ntohl(eth_tag);
pfx += 4;
/* Get the IP. */
ipaddr_len = *pfx++;
if (ipaddr_len == IPV4_MAX_BITLEN) {
- p.prefix.ip.ipa_type = IPADDR_V4;
- memcpy(&p.prefix.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
+ p.prefix.imet_addr.ip.ipa_type = IPADDR_V4;
+ memcpy(&p.prefix.imet_addr.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
} else {
zlog_err(
"%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
/* Fetch Ethernet Tag. */
memcpy(ð_tag, pfx, 4);
- p.prefix.eth_tag = ntohl(eth_tag);
+ p.prefix.prefix_addr.eth_tag = ntohl(eth_tag);
pfx += 4;
/* Fetch IP prefix length. */
peer->bgp->vrf_id, peer->host, ippfx_len);
return -1;
}
- p.prefix.ip_prefix_length = ippfx_len;
+ p.prefix.prefix_addr.ip_prefix_length = ippfx_len;
/* Determine IPv4 or IPv6 prefix */
/* Since the address and GW are from the same family, this just becomes
* a simple check on the total size.
*/
if (psize == 34) {
- SET_IPADDR_V4(&p.prefix.ip);
- memcpy(&p.prefix.ip.ipaddr_v4, pfx, 4);
+ SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
+ memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
pfx += 4;
memcpy(&evpn.gw_ip.ipv4, pfx, 4);
pfx += 4;
} else {
- SET_IPADDR_V6(&p.prefix.ip);
- memcpy(&p.prefix.ip.ipaddr_v6, pfx, 16);
+ SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
+ memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx, 16);
pfx += 16;
memcpy(&evpn.gw_ip.ipv6, pfx, 16);
pfx += 16;
/* len denites the total len of IP and GW-IP in the route
IP and GW-IP have to be both ipv4 or ipv6
*/
- if (IS_IPADDR_V4(&p_evpn_p->ip))
+ if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
len = 8; /* IP and GWIP are both ipv4 */
else
len = 32; /* IP and GWIP are both ipv6 */
stream_put(s, &(attr->evpn_overlay.eth_s_id), 10);
else
stream_put(s, &temp, 10);
- stream_putl(s, p_evpn_p->eth_tag);
- stream_putc(s, p_evpn_p->ip_prefix_length);
- if (IS_IPADDR_V4(&p_evpn_p->ip))
- stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr);
+ stream_putl(s, p_evpn_p->prefix_addr.eth_tag);
+ stream_putc(s, p_evpn_p->prefix_addr.ip_prefix_length);
+ if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
+ stream_put_ipv4(s, p_evpn_p->prefix_addr.ip.ipaddr_v4.s_addr);
else
- stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16);
+ stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16);
if (attr) {
- if (IS_IPADDR_V4(&p_evpn_p->ip))
+ if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
stream_put_ipv4(s,
attr->evpn_overlay.gw_ip.ipv4.s_addr);
else
stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16);
} else {
- if (IS_IPADDR_V4(&p_evpn_p->ip))
+ if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
stream_put_ipv4(s, 0);
else
stream_put(s, &temp, 16);
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
json_object_int_add(json, "routeType", p->prefix.route_type);
- json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+ json_object_int_add(json, "ethTag",
+ p->prefix.imet_addr.eth_tag);
json_object_int_add(json, "ipLen",
- IS_EVPN_PREFIX_IPADDR_V4(p)
+ is_evpn_prefix_ipaddr_v4(p)
? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN);
json_object_string_add(json, "ip",
- inet_ntoa(p->prefix.ip.ipaddr_v4));
+ inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
} else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
- if (IS_EVPN_PREFIX_IPADDR_NONE(p)) {
+ if (is_evpn_prefix_ipaddr_none(p)) {
json_object_int_add(json, "routeType",
p->prefix.route_type);
- json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+ json_object_int_add(json, "ethTag",
+ p->prefix.macip_addr.eth_tag);
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
json_object_string_add(json, "mac",
- prefix_mac2str(&p->prefix.mac,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
buf1,
sizeof(buf1)));
} else {
uint8_t family;
- family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+ family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
: AF_INET6;
json_object_int_add(json, "routeType",
p->prefix.route_type);
- json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+ json_object_int_add(json, "ethTag",
+ p->prefix.macip_addr.eth_tag);
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
json_object_string_add(json, "mac",
- prefix_mac2str(&p->prefix.mac,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
buf1,
sizeof(buf1)));
json_object_int_add(json, "ipLen",
- IS_EVPN_PREFIX_IPADDR_V4(p)
+ is_evpn_prefix_ipaddr_v4(p)
? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN);
json_object_string_add(
json, "ip",
- inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+ inet_ntop(family,
+ &p->prefix.macip_addr.ip.ip.addr,
+ buf2,
PREFIX2STR_BUFFER));
}
} else {
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
- p->prefix.eth_tag,
- IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BITLEN
+ p->prefix.imet_addr.eth_tag,
+ is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN,
- inet_ntoa(p->prefix.ip.ipaddr_v4));
+ inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
} else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
- if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+ if (is_evpn_prefix_ipaddr_none(p))
snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]",
p->prefix.route_type,
- p->prefix.eth_tag,
+ p->prefix.macip_addr.eth_tag,
8 * ETH_ALEN,
- prefix_mac2str(&p->prefix.mac, buf1,
+ prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
sizeof(buf1)));
else {
uint8_t family;
- family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+ family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
: AF_INET6;
snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]:[%d]:[%s]",
p->prefix.route_type,
- p->prefix.eth_tag,
+ p->prefix.macip_addr.eth_tag,
8 * ETH_ALEN,
- prefix_mac2str(&p->prefix.mac, buf1,
+ prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
sizeof(buf1)),
family == AF_INET ? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN,
- inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+ inet_ntop(family,
+ &p->prefix.macip_addr.ip.ip.addr,
+ buf2,
PREFIX2STR_BUFFER));
}
} else if (p->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]",
p->prefix.route_type,
- p->prefix.eth_tag,
- p->prefix.ip_prefix_length,
- IS_EVPN_PREFIX_IPADDR_V4(p)
- ? inet_ntoa(p->prefix.ip.ipaddr_v4)
- : inet6_ntoa(p->prefix.ip.ipaddr_v6));
+ p->prefix.prefix_addr.eth_tag,
+ p->prefix.prefix_addr.ip_prefix_length,
+ is_evpn_prefix_ipaddr_v4(p)
+ ? inet_ntoa(p->prefix.prefix_addr.ip.ipaddr_v4)
+ : inet6_ntoa(p->prefix.prefix_addr.ip.ipaddr_v6));
} else {
/* For EVPN route types not supported yet. */
snprintf(buf, len, "(unsupported route type %d)",
switch (evp->prefix.route_type) {
case BGP_EVPN_MAC_IP_ROUTE:
- if (IS_EVPN_PREFIX_IPADDR_V4(evp))
+ if (is_evpn_prefix_ipaddr_v4(evp))
ipa_len = IPV4_MAX_BYTELEN;
- else if (IS_EVPN_PREFIX_IPADDR_V6(evp))
+ else if (is_evpn_prefix_ipaddr_v6(evp))
ipa_len = IPV6_MAX_BYTELEN;
/* RD, ESI, EthTag, MAC+len, IP len, [IP], 1 VNI */
len = 8 + 10 + 4 + 1 + 6 + 1 + ipa_len + 3;
stream_put(s, &attr->evpn_overlay.eth_s_id, ESI_LEN);
else
stream_put(s, 0, 10);
- stream_putl(s, evp->prefix.eth_tag); /* Ethernet Tag ID */
+ stream_putl(s, evp->prefix.macip_addr.eth_tag); /* Ethernet Tag ID */
stream_putc(s, 8 * ETH_ALEN); /* Mac Addr Len - bits */
- stream_put(s, evp->prefix.mac.octet, 6); /* Mac Addr */
- stream_putc(s, 8 * ipa_len); /* IP address Length */
- if (ipa_len) /* IP */
- stream_put(s, &evp->prefix.ip.ip.addr, ipa_len);
+ stream_put(s, evp->prefix.macip_addr.mac.octet, 6); /* Mac Addr */
+ stream_putc(s, 8 * ipa_len); /* IP address Length */
+ if (ipa_len) /* IP */
+ stream_put(s, &evp->prefix.macip_addr.ip.ip.addr,
+ ipa_len);
/* 1st label is the L2 VNI */
stream_put(s, label, BGP_LABEL_BYTES);
/* Include 2nd label (L3 VNI) if advertising MAC+IP */
case BGP_EVPN_IMET_ROUTE:
stream_putc(s, 17); // TODO: length - assumes IPv4 address
stream_put(s, prd->val, 8); /* RD */
- stream_putl(s, evp->prefix.eth_tag); /* Ethernet Tag ID */
+ stream_putl(s, evp->prefix.imet_addr.eth_tag); /* Ethernet Tag ID */
stream_putc(s, IPV4_MAX_BITLEN); /* IP address Length - bits */
/* Originating Router's IP Addr */
- stream_put_in_addr(s, &evp->prefix.ip.ipaddr_v4);
+ stream_put_in_addr(s, &evp->prefix.imet_addr.ip.ipaddr_v4);
break;
case BGP_EVPN_IP_PREFIX_ROUTE:
struct prefix *ip)
{
memset(ip, 0, sizeof(struct prefix));
- if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+ if (is_evpn_prefix_ipaddr_v4(evp)) {
ip->family = AF_INET;
- ip->prefixlen = evp->prefix.ip_prefix_length;
- memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
+ ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+ memcpy(&(ip->u.prefix4), &(evp->prefix.prefix_addr.ip.ip),
IPV4_MAX_BYTELEN);
- } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+ } else if (is_evpn_prefix_ipaddr_v6(evp)) {
ip->family = AF_INET6;
- ip->prefixlen = evp->prefix.ip_prefix_length;
- memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
+ ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+ memcpy(&(ip->u.prefix6), &(evp->prefix.prefix_addr.ip.ip),
IPV6_MAX_BYTELEN);
}
}
if (evp->family != AF_EVPN)
return 0;
- return ((evp->u.prefix_evpn.ip_prefix_length == 0) ? 1 : 0);
+ return ((evp->u.prefix_evpn.prefix_addr.ip_prefix_length == 0) ?
+ 1 : 0);
}
static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
struct prefix *ip)
{
memset(ip, 0, sizeof(struct prefix));
- if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+ if (is_evpn_prefix_ipaddr_v4(evp)) {
ip->family = AF_INET;
ip->prefixlen = IPV4_MAX_BITLEN;
- memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
+ memcpy(&(ip->u.prefix4), &(evp->prefix.macip_addr.ip.ip),
IPV4_MAX_BYTELEN);
- } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+ } else if (is_evpn_prefix_ipaddr_v6(evp)) {
ip->family = AF_INET6;
ip->prefixlen = IPV6_MAX_BITLEN;
- memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
+ memcpy(&(ip->u.prefix6), &(evp->prefix.macip_addr.ip.ip),
IPV6_MAX_BYTELEN);
}
}
+static inline void ip_prefix_from_evpn_prefix(struct prefix_evpn *evp,
+ struct prefix *ip)
+{
+ if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
+ ip_prefix_from_type2_prefix(evp, ip);
+ else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
+ ip_prefix_from_type5_prefix(evp, ip);
+}
+
static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
struct ethaddr *mac,
struct ipaddr *ip)
p->family = AF_EVPN;
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
- memcpy(&p->prefix.mac.octet, mac->octet, ETH_ALEN);
- p->prefix.ip.ipa_type = IPADDR_NONE;
+ memcpy(&p->prefix.macip_addr.mac.octet, mac->octet, ETH_ALEN);
+ p->prefix.macip_addr.ip.ipa_type = IPADDR_NONE;
if (ip)
- memcpy(&p->prefix.ip, ip, sizeof(*ip));
+ memcpy(&p->prefix.macip_addr.ip, ip, sizeof(*ip));
}
static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
memset(evp, 0, sizeof(struct prefix_evpn));
evp->family = AF_EVPN;
evp->prefixlen = EVPN_TYPE_5_ROUTE_PREFIXLEN;
- evp->prefix.ip_prefix_length = ip_prefix->prefixlen;
evp->prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
- evp->prefix.ip.ipa_type = ip.ipa_type;
- memcpy(&evp->prefix.ip, &ip, sizeof(struct ipaddr));
+ evp->prefix.prefix_addr.ip_prefix_length = ip_prefix->prefixlen;
+ evp->prefix.prefix_addr.ip.ipa_type = ip.ipa_type;
+ memcpy(&evp->prefix.prefix_addr.ip, &ip, sizeof(struct ipaddr));
}
static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
p->family = AF_EVPN;
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
- p->prefix.ip.ipa_type = IPADDR_V4;
- p->prefix.ip.ipaddr_v4 = originator_ip;
+ p->prefix.imet_addr.ip.ipa_type = IPADDR_V4;
+ p->prefix.imet_addr.ip.ipaddr_v4 = originator_ip;
}
static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
struct bgp_encap_type_vxlan bet;
memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
- bet.vnid = p->u.prefix_evpn.eth_tag;
+ bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
bgp_encap_type_vxlan_to_tlv(&bet, &attr);
}
if (bgp_static->router_mac) {
return CMD_WARNING_CONFIG_FAILED;
}
if ((gw_ip.family == AF_INET
- && IS_EVPN_PREFIX_IPADDR_V6(
+ && is_evpn_prefix_ipaddr_v6(
(struct prefix_evpn *)&p))
|| (gw_ip.family == AF_INET6
- && IS_EVPN_PREFIX_IPADDR_V4(
+ && is_evpn_prefix_ipaddr_v4(
(struct prefix_evpn *)&p))) {
vty_out(vty,
"%% GatewayIp family differs with IP prefix\n");
vty_out(vty, "%s", str);
XFREE(MTYPE_TMP, str);
- if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) {
+ if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
vty_out(vty, "/%s",
inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
- } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) {
+ } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
vty_out(vty, "/%s",
inet_ntop(AF_INET6,
&(attr->evpn_overlay.gw_ip.ipv6), buf,
prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
if (p->u.prefix_evpn.route_type == 5) {
char local_buf[PREFIX_STRLEN];
- uint8_t family = IS_EVPN_PREFIX_IPADDR_V4((
+ uint8_t family = is_evpn_prefix_ipaddr_v4((
struct prefix_evpn *)p)
? AF_INET
: AF_INET6;
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
+ inet_ntop(family,
+ &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
local_buf, PREFIX_STRLEN);
sprintf(buf, "%s/%u", local_buf,
- p->u.prefix_evpn.ip_prefix_length);
+ p->u.prefix_evpn.prefix_addr.ip_prefix_length);
} else {
prefix2str(p, buf, sizeof(buf));
}
sizeof(buf2));
vty_out(vty,
" network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
- buf, rdbuf, p->u.prefix_evpn.eth_tag,
+ buf, rdbuf,
+ p->u.prefix_evpn.prefix_addr.eth_tag,
decode_label(&bgp_static->label), esi, buf2,
macrouter);
p.family = AF_ETHERNET;
p.prefixlen = ETH_ALEN * 8;
- p.u.prefix_eth = prefix->u.prefix_evpn.mac;
+ p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
return (access_list_apply(alist, &p) == FILTER_DENY
? RMAP_NOMATCH
return 0;
}
-static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
+static const char *prefixevpn_ead2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ snprintf(str, size, "Unsupported EVPN prefix");
+ return str;
+}
+
+static const char *prefixevpn_macip2str(const struct prefix_evpn *p, char *str,
+ int size)
{
uint8_t family;
char buf[PREFIX2STR_BUFFER];
char buf2[ETHER_ADDR_STRLEN];
- if (p->u.prefix_evpn.route_type == 2) {
- if (IS_EVPN_PREFIX_IPADDR_NONE((struct prefix_evpn *)p))
- snprintf(str, size, "[%d]:[%s]/%d",
- p->u.prefix_evpn.route_type,
- prefix_mac2str(&p->u.prefix_evpn.mac, buf2,
- sizeof(buf2)),
- p->prefixlen);
- else {
- family = IS_EVPN_PREFIX_IPADDR_V4(
- (struct prefix_evpn *)p)
- ? AF_INET
- : AF_INET6;
- snprintf(str, size, "[%d]:[%s]:[%s]/%d",
- p->u.prefix_evpn.route_type,
- prefix_mac2str(&p->u.prefix_evpn.mac, buf2,
- sizeof(buf2)),
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
- buf, PREFIX2STR_BUFFER),
- p->prefixlen);
- }
- } else if (p->u.prefix_evpn.route_type == 3) {
- family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
- ? AF_INET
- : AF_INET6;
- snprintf(str, size, "[%d]:[%s]/%d", p->u.prefix_evpn.route_type,
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
- PREFIX2STR_BUFFER),
+ if (is_evpn_prefix_ipaddr_none(p))
+ snprintf(str, size, "[%d]:[%s]/%d",
+ p->prefix.route_type,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
+ buf2, sizeof(buf2)),
p->prefixlen);
- } else if (p->u.prefix_evpn.route_type == 5) {
- family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
+ else {
+ family = is_evpn_prefix_ipaddr_v4(p)
? AF_INET
: AF_INET6;
- snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
- p->u.prefix_evpn.route_type, p->u.prefix_evpn.eth_tag,
- inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
- PREFIX2STR_BUFFER),
- p->u.prefix_evpn.ip_prefix_length, p->prefixlen);
- } else {
- sprintf(str, "Unsupported EVPN route type %d",
- p->u.prefix_evpn.route_type);
+ snprintf(str, size, "[%d]:[%s]:[%s]/%d",
+ p->prefix.route_type,
+ prefix_mac2str(&p->prefix.macip_addr.mac,
+ buf2, sizeof(buf2)),
+ inet_ntop(family,
+ &p->prefix.macip_addr.ip.ip.addr,
+ buf, PREFIX2STR_BUFFER),
+ p->prefixlen);
}
+ return str;
+}
+
+static const char *prefixevpn_imet2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ uint8_t family;
+ char buf[PREFIX2STR_BUFFER];
+
+ family = is_evpn_prefix_ipaddr_v4(p)
+ ? AF_INET
+ : AF_INET6;
+ snprintf(str, size, "[%d]:[%s]/%d", p->prefix.route_type,
+ inet_ntop(family,
+ &p->prefix.imet_addr.ip.ip.addr, buf,
+ PREFIX2STR_BUFFER),
+ p->prefixlen);
+ return str;
+}
+static const char *prefixevpn_es2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ snprintf(str, size, "Unsupported EVPN prefix");
+ return str;
+}
+
+static const char *prefixevpn_prefix2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ uint8_t family;
+ char buf[PREFIX2STR_BUFFER];
+
+ family = is_evpn_prefix_ipaddr_v4(p)
+ ? AF_INET
+ : AF_INET6;
+ snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
+ p->prefix.route_type,
+ p->prefix.prefix_addr.eth_tag,
+ inet_ntop(family,
+ &p->prefix.prefix_addr.ip.ip.addr, buf,
+ PREFIX2STR_BUFFER),
+ p->prefix.prefix_addr.ip_prefix_length,
+ p->prefixlen);
+ return str;
+}
+
+static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
+ int size)
+{
+ switch (p->prefix.route_type) {
+ case 1:
+ return prefixevpn_ead2str(p, str, size);
+ case 2:
+ return prefixevpn_macip2str(p, str, size);
+ case 3:
+ return prefixevpn_imet2str(p, str, size);
+ case 4:
+ return prefixevpn_es2str(p, str, size);
+ case 5:
+ return prefixevpn_prefix2str(p, str, size);
+ default:
+ snprintf(str, size, "Unsupported EVPN prefix");
+ break;
+ }
return str;
}
break;
case AF_EVPN:
- prefixevpn2str(p, str, size);
+ prefixevpn2str((const struct prefix_evpn *)p, str, size);
break;
case AF_FLOWSPEC:
#define PREFIX_LEN_ROUTE_TYPE_5_IPV4 (18*8)
#define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8)
-/* EVPN address (RFC 7432) */
-struct evpn_addr {
- uint8_t route_type;
+typedef struct esi_t_ {
+ uint8_t val[10];
+} esi_t;
+
+struct evpn_ead_addr {
+ esi_t esi;
+ uint32_t eth_tag;
+};
+
+struct evpn_macip_addr {
+ uint32_t eth_tag;
uint8_t ip_prefix_length;
struct ethaddr mac;
+ struct ipaddr ip;
+};
+
+struct evpn_imet_addr {
uint32_t eth_tag;
+ uint8_t ip_prefix_length;
struct ipaddr ip;
-#if 0
- union
- {
- uint8_t addr;
- struct in_addr v4_addr;
- struct in6_addr v6_addr;
- } ip;
-#endif
};
-#define IS_EVPN_PREFIX_IPADDR_NONE(evp) IS_IPADDR_NONE(&(evp)->prefix.ip)
-#define IS_EVPN_PREFIX_IPADDR_V4(evp) IS_IPADDR_V4(&(evp)->prefix.ip)
-#define IS_EVPN_PREFIX_IPADDR_V6(evp) IS_IPADDR_V6(&(evp)->prefix.ip)
+struct evpn_es_addr {
+ esi_t esi;
+ uint8_t ip_prefix_length;
+ struct ipaddr ip;
+};
+
+struct evpn_prefix_addr {
+ uint32_t eth_tag;
+ uint8_t ip_prefix_length;
+ struct ipaddr ip;
+};
+
+/* EVPN address (RFC 7432) */
+struct evpn_addr {
+ uint8_t route_type;
+ union {
+ struct evpn_ead_addr _ead_addr;
+ struct evpn_macip_addr _macip_addr;
+ struct evpn_imet_addr _imet_addr;
+ struct evpn_es_addr _es_addr;
+ struct evpn_prefix_addr _prefix_addr;
+ } u;
+#define ead_addr u._ead_addr
+#define macip_addr u._macip_addr
+#define imet_addr u._imet_addr
+#define es_addr u._es_addr
+#define prefix_addr u._prefix_addr
+};
/*
* A struct prefix contains an address family, a prefix length, and an
struct evpn_addr prefix __attribute__((aligned(8)));
};
+static inline int is_evpn_prefix_ipaddr_none(const struct prefix_evpn *evp)
+{
+ if (evp->prefix.route_type == 2)
+ return IS_IPADDR_NONE(&(evp)->prefix.macip_addr.ip);
+ if (evp->prefix.route_type == 3)
+ return IS_IPADDR_NONE(&(evp)->prefix.imet_addr.ip);
+ if (evp->prefix.route_type == 5)
+ return IS_IPADDR_NONE(&(evp)->prefix.prefix_addr.ip);
+ return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v4(const struct prefix_evpn *evp)
+{
+ if (evp->prefix.route_type == 2)
+ return IS_IPADDR_V4(&(evp)->prefix.macip_addr.ip);
+ if (evp->prefix.route_type == 3)
+ return IS_IPADDR_V4(&(evp)->prefix.imet_addr.ip);
+ if (evp->prefix.route_type == 5)
+ return IS_IPADDR_V4(&(evp)->prefix.prefix_addr.ip);
+ return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp)
+{
+ if (evp->prefix.route_type == 2)
+ return IS_IPADDR_V6(&(evp)->prefix.macip_addr.ip);
+ if (evp->prefix.route_type == 3)
+ return IS_IPADDR_V6(&(evp)->prefix.imet_addr.ip);
+ if (evp->prefix.route_type == 5)
+ return IS_IPADDR_V6(&(evp)->prefix.prefix_addr.ip);
+ return 0;
+}
+
/* Prefix for a generic pointer */
struct prefix_ptr {
uint8_t family;
},
{NULL, NULL, {0}, 0, 0}};
+static struct test_segment mp_prefix_sid[] = {
+ {
+ "PREFIX-SID",
+ "PREFIX-SID Test 1",
+ {
+ 0x01, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02,
+ 0x03, 0x00, 0x08, 0x00,
+ 0x00, 0x0a, 0x1b, 0xfe,
+ 0x00, 0x00, 0x0a
+ },
+ .len = 21,
+ .parses = SHOULD_PARSE,
+ },
+ {NULL, NULL, { 0 }, 0, 0},
+};
+
/* nlri_parse indicates 0 on successful parse, and -1 otherwise.
* attr_parse indicates BGP_ATTR_PARSE_PROCEED/0 on success,
* and BGP_ATTR_PARSE_ERROR/-1 or lower negative ret on err.
printf("%s: %s\n", t->name, t->desc);
- if (type == BGP_ATTR_MP_REACH_NLRI)
+ switch (type) {
+ case BGP_ATTR_MP_REACH_NLRI:
parse_ret = bgp_mp_reach_parse(&attr_args, &nlri);
- else
+ break;
+ case BGP_ATTR_MP_UNREACH_NLRI:
parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
+ break;
+ case BGP_ATTR_PREFIX_SID:
+ parse_ret = bgp_attr_prefix_sid(t->len, &attr_args, &nlri);
+ break;
+ default:
+ printf("unknown type");
+ return;
+ }
if (!parse_ret) {
iana_afi_t pkt_afi;
iana_safi_t pkt_safi;
if (!parse_ret) {
if (type == BGP_ATTR_MP_REACH_NLRI)
nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 0);
- else
+ else if (type == BGP_ATTR_MP_UNREACH_NLRI)
nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 1);
}
handle_result(peer, t, parse_ret, nlri_ret);
parse_test(peer, &mp_unreach_segments[i++],
BGP_ATTR_MP_UNREACH_NLRI);
+ i = 0;
+ while (mp_prefix_sid[i].name)
+ parse_test(peer, &mp_prefix_sid[i++],
+ BGP_ATTR_PREFIX_SID);
printf("failures: %d\n", failed);
return failed;
}