forked from Mirror/frr
bgpd: replace custom union gw_addr with struct ipaddr
BGP EVPN custom `union gw_addr` is basically the same thing as a common `struct ipaddr` but it lacks the address family which is needed in some cases. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
parent
b04c1e9997
commit
860e740b36
|
@ -304,15 +304,3 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool is_zero_gw_ip(const union gw_addr *gw_ip, const afi_t afi)
|
|
||||||
{
|
|
||||||
if (afi == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&gw_ip->ipv6))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (afi == AF_INET && gw_ip->ipv4.s_addr == INADDR_ANY)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,6 @@
|
||||||
|
|
||||||
struct attr;
|
struct attr;
|
||||||
|
|
||||||
union gw_addr {
|
|
||||||
struct in_addr ipv4;
|
|
||||||
struct in6_addr ipv6;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum overlay_index_type {
|
enum overlay_index_type {
|
||||||
OVERLAY_INDEX_TYPE_NONE,
|
OVERLAY_INDEX_TYPE_NONE,
|
||||||
OVERLAY_INDEX_GATEWAY_IP,
|
OVERLAY_INDEX_GATEWAY_IP,
|
||||||
|
@ -45,7 +40,7 @@ enum overlay_index_type {
|
||||||
struct bgp_route_evpn {
|
struct bgp_route_evpn {
|
||||||
enum overlay_index_type type;
|
enum overlay_index_type type;
|
||||||
esi_t eth_s_id;
|
esi_t eth_s_id;
|
||||||
union gw_addr gw_ip;
|
struct ipaddr gw_ip;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool str2esi(const char *str, esi_t *id);
|
extern bool str2esi(const char *str, esi_t *id);
|
||||||
|
@ -64,6 +59,4 @@ extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag,
|
||||||
bool *proxy);
|
bool *proxy);
|
||||||
extern uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg);
|
extern uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg);
|
||||||
|
|
||||||
extern bool is_zero_gw_ip(const union gw_addr *gw_ip, afi_t afi);
|
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
|
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
|
||||||
|
|
|
@ -1335,7 +1335,8 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
|
||||||
if (src_attr &&
|
if (src_attr &&
|
||||||
!IN6_IS_ADDR_UNSPECIFIED(&src_attr->mp_nexthop_global)) {
|
!IN6_IS_ADDR_UNSPECIFIED(&src_attr->mp_nexthop_global)) {
|
||||||
attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
|
attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
|
||||||
memcpy(&attr.evpn_overlay.gw_ip.ipv6,
|
SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
|
||||||
|
memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
|
||||||
&src_attr->mp_nexthop_global,
|
&src_attr->mp_nexthop_global,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1345,8 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
|
||||||
BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
|
BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
|
||||||
if (src_attr && src_attr->nexthop.s_addr != 0) {
|
if (src_attr && src_attr->nexthop.s_addr != 0) {
|
||||||
attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
|
attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
|
||||||
memcpy(&attr.evpn_overlay.gw_ip.ipv4,
|
SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
|
||||||
|
memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
|
||||||
&src_attr->nexthop, sizeof(struct in_addr));
|
&src_attr->nexthop, sizeof(struct in_addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2470,11 +2472,11 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||||
|
|
||||||
if (afi == AFI_IP6) {
|
if (afi == AFI_IP6) {
|
||||||
memcpy(&attr.mp_nexthop_global,
|
memcpy(&attr.mp_nexthop_global,
|
||||||
&attr.evpn_overlay.gw_ip.ipv6,
|
&attr.evpn_overlay.gw_ip.ipaddr_v6,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
|
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
|
||||||
} else {
|
} else {
|
||||||
attr.nexthop = attr.evpn_overlay.gw_ip.ipv4;
|
attr.nexthop = attr.evpn_overlay.gw_ip.ipaddr_v4;
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4041,7 +4043,6 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||||
uint32_t eth_tag;
|
uint32_t eth_tag;
|
||||||
mpls_label_t label; /* holds the VNI as in the packet */
|
mpls_label_t label; /* holds the VNI as in the packet */
|
||||||
int ret;
|
int ret;
|
||||||
afi_t gw_afi;
|
|
||||||
bool is_valid_update = true;
|
bool is_valid_update = true;
|
||||||
|
|
||||||
/* Type-5 route should be 34 or 58 bytes:
|
/* Type-5 route should be 34 or 58 bytes:
|
||||||
|
@ -4100,17 +4101,17 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||||
SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
|
SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
|
||||||
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
|
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
|
||||||
pfx += 4;
|
pfx += 4;
|
||||||
memcpy(&evpn.gw_ip.ipv4, pfx, 4);
|
SET_IPADDR_V4(&evpn.gw_ip);
|
||||||
|
memcpy(&evpn.gw_ip.ipaddr_v4, pfx, 4);
|
||||||
pfx += 4;
|
pfx += 4;
|
||||||
gw_afi = AF_INET;
|
|
||||||
} else {
|
} else {
|
||||||
SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
|
SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
|
||||||
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx,
|
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx,
|
||||||
IPV6_MAX_BYTELEN);
|
IPV6_MAX_BYTELEN);
|
||||||
pfx += IPV6_MAX_BYTELEN;
|
pfx += IPV6_MAX_BYTELEN;
|
||||||
memcpy(&evpn.gw_ip.ipv6, pfx, IPV6_MAX_BYTELEN);
|
SET_IPADDR_V6(&evpn.gw_ip);
|
||||||
|
memcpy(&evpn.gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN);
|
||||||
pfx += IPV6_MAX_BYTELEN;
|
pfx += IPV6_MAX_BYTELEN;
|
||||||
gw_afi = AF_INET6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the VNI (in MPLS label field). Stored as bytes here. */
|
/* Get the VNI (in MPLS label field). Stored as bytes here. */
|
||||||
|
@ -4127,20 +4128,20 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||||
* An update containing a non-zero gateway IP and a non-zero ESI
|
* An update containing a non-zero gateway IP and a non-zero ESI
|
||||||
* at the same time is should be treated as withdraw
|
* at the same time is should be treated as withdraw
|
||||||
*/
|
*/
|
||||||
if (bgp_evpn_is_esi_valid(&evpn.eth_s_id)
|
if (bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
|
||||||
&& !is_zero_gw_ip(&evpn.gw_ip, gw_afi)) {
|
!ipaddr_is_zero(&evpn.gw_ip)) {
|
||||||
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
|
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
|
||||||
"%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.",
|
"%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.",
|
||||||
peer->host);
|
peer->host);
|
||||||
is_valid_update = false;
|
is_valid_update = false;
|
||||||
} else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id))
|
} else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id))
|
||||||
evpn.type = OVERLAY_INDEX_ESI;
|
evpn.type = OVERLAY_INDEX_ESI;
|
||||||
else if (!is_zero_gw_ip(&evpn.gw_ip, gw_afi))
|
else if (!ipaddr_is_zero(&evpn.gw_ip))
|
||||||
evpn.type = OVERLAY_INDEX_GATEWAY_IP;
|
evpn.type = OVERLAY_INDEX_GATEWAY_IP;
|
||||||
if (attr) {
|
if (attr) {
|
||||||
if (is_zero_mac(&attr->rmac)
|
if (is_zero_mac(&attr->rmac) &&
|
||||||
&& !bgp_evpn_is_esi_valid(&evpn.eth_s_id)
|
!bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
|
||||||
&& is_zero_gw_ip(&evpn.gw_ip, gw_afi) && label == 0) {
|
ipaddr_is_zero(&evpn.gw_ip) && label == 0) {
|
||||||
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
|
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
|
||||||
"%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero",
|
"%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero",
|
||||||
peer->host);
|
peer->host);
|
||||||
|
@ -4213,9 +4214,10 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
|
||||||
bgp_attr_get_evpn_overlay(attr);
|
bgp_attr_get_evpn_overlay(attr);
|
||||||
|
|
||||||
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
|
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
|
||||||
stream_put_ipv4(s, evpn_overlay->gw_ip.ipv4.s_addr);
|
stream_put_ipv4(s,
|
||||||
|
evpn_overlay->gw_ip.ipaddr_v4.s_addr);
|
||||||
else
|
else
|
||||||
stream_put(s, &(evpn_overlay->gw_ip.ipv6), 16);
|
stream_put(s, &(evpn_overlay->gw_ip.ipaddr_v6), 16);
|
||||||
} else {
|
} else {
|
||||||
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
|
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
|
||||||
stream_put_ipv4(s, 0);
|
stream_put_ipv4(s, 0);
|
||||||
|
|
|
@ -6097,13 +6097,13 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
|
||||||
if (bgp_static->gatewayIp.family == AF_INET) {
|
if (bgp_static->gatewayIp.family == AF_INET) {
|
||||||
SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
|
SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
|
||||||
memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
|
memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
|
||||||
&bgp_static->gatewayIp.u.prefix4,
|
&bgp_static->gatewayIp.u.prefix4,
|
||||||
IPV4_MAX_BYTELEN);
|
IPV4_MAX_BYTELEN);
|
||||||
} else if (bgp_static->gatewayIp.family == AF_INET6) {
|
} else if (bgp_static->gatewayIp.family == AF_INET6) {
|
||||||
SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
|
SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
|
||||||
memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
|
memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
|
||||||
&bgp_static->gatewayIp.u.prefix6,
|
&bgp_static->gatewayIp.u.prefix6,
|
||||||
IPV6_MAX_BYTELEN);
|
IPV6_MAX_BYTELEN);
|
||||||
}
|
}
|
||||||
memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
|
memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
|
||||||
if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
|
if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
|
||||||
|
@ -9497,10 +9497,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
|
||||||
|
|
||||||
const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
|
const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
|
||||||
|
|
||||||
if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
|
ipaddr2str(&eo->gw_ip, buf, BUFSIZ);
|
||||||
inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
|
|
||||||
else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
|
|
||||||
inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
|
|
||||||
|
|
||||||
if (!json_path)
|
if (!json_path)
|
||||||
vty_out(vty, "/%s", buf);
|
vty_out(vty, "/%s", buf);
|
||||||
|
@ -9913,12 +9910,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
|
||||||
&& attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
|
&& attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
|
||||||
char gwip_buf[INET6_ADDRSTRLEN];
|
char gwip_buf[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
|
ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
|
||||||
inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
|
sizeof(gwip_buf));
|
||||||
gwip_buf, sizeof(gwip_buf));
|
|
||||||
else
|
|
||||||
inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
|
|
||||||
gwip_buf, sizeof(gwip_buf));
|
|
||||||
|
|
||||||
if (json_paths)
|
if (json_paths)
|
||||||
json_object_string_add(json_path, "gatewayIP",
|
json_object_string_add(json_path, "gatewayIP",
|
||||||
|
|
13
lib/ipaddr.h
13
lib/ipaddr.h
|
@ -170,6 +170,19 @@ static inline int ipaddr_cmp(const struct ipaddr *a, const struct ipaddr *b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool ipaddr_is_zero(const struct ipaddr *ip)
|
||||||
|
{
|
||||||
|
switch (ip->ipa_type) {
|
||||||
|
case IPADDR_NONE:
|
||||||
|
return true;
|
||||||
|
case IPADDR_V4:
|
||||||
|
return ip->ipaddr_v4.s_addr == INADDR_ANY;
|
||||||
|
case IPADDR_V6:
|
||||||
|
return IN6_IS_ADDR_UNSPECIFIED(&ip->ipaddr_v6);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _FRR_ATTRIBUTE_PRINTFRR
|
#ifdef _FRR_ATTRIBUTE_PRINTFRR
|
||||||
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
|
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue