Skip to content

Commit

Permalink
Merge pull request #6821 from Niral-Networks/niral_6VPE_6PE_fix
Browse files Browse the repository at this point in the history
BGP : Fix for nexthop as IPv4 mapped IPv6 address
  • Loading branch information
sworleys committed Aug 4, 2020
2 parents 35b82b0 + 92d6f76 commit c117742
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 13 deletions.
17 changes: 15 additions & 2 deletions bgpd/bgp_nht.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
: AFI_IP;

/* Validation for the ipv4 mapped ipv6 nexthop. */
if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
afi = AFI_IP;
}

/* This will return true if the global IPv6 NH is a link local
* addr */
if (make_prefix(afi, pi, &p) < 0)
Expand Down Expand Up @@ -533,6 +538,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
: 0;
struct bgp_dest *net = pi->net;
const struct prefix *p_orig = bgp_dest_get_prefix(net);
struct in_addr ipv4;

if (p_orig->family == AF_FLOWSPEC) {
if (!pi->peer)
Expand All @@ -548,8 +554,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
p->u.prefix4 = p_orig->u.prefix4;
p->prefixlen = p_orig->prefixlen;
} else {
p->u.prefix4 = pi->attr->nexthop;
p->prefixlen = IPV4_MAX_BITLEN;
if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
ipv4_mapped_ipv6_to_ipv4(
&pi->attr->mp_nexthop_global, &ipv4);
p->u.prefix4 = ipv4;
p->prefixlen = IPV4_MAX_BITLEN;
} else {
p->u.prefix4 = pi->attr->nexthop;
p->prefixlen = IPV4_MAX_BITLEN;
}
}
break;
case AFI_IP6:
Expand Down
12 changes: 12 additions & 0 deletions bgpd/bgp_updgrp_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,18 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
gnh_modified = 1;
}

if (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg)) {
if (peer->nexthop.v4.s_addr) {
ipv4_to_ipv4_mapped_ipv6(mod_v6nhg,
peer->nexthop.v4);
}
}

if (IS_MAPPED_IPV6(&peer->nexthop.v6_global)) {
mod_v6nhg = &peer->nexthop.v6_global;
gnh_modified = 1;
}

if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
|| nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
stream_get_from(&v6nhlocal, s, offset_nhlocal,
Expand Down
7 changes: 7 additions & 0 deletions lib/ipaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
return buf;
}

#define IS_MAPPED_IPV6(A) \
((A)->s6_addr32[0] == 0x00000000 \
? ((A)->s6_addr32[1] == 0x00000000 \
? (ntohl((A)->s6_addr32[2]) == 0xFFFF ? 1 : 0) \
: 0) \
: 0)

/*
* Convert IPv4 address to IPv4-mapped IPv6 address which is of the
* form ::FFFF:<IPv4 address> (RFC 4291). This IPv6 address can then
Expand Down
19 changes: 11 additions & 8 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,14 +1051,17 @@ static bool _netlink_route_add_gateway_info(uint8_t route_family,
bytelen + 2))
return false;
} else {
if (gw_family == AF_INET) {
if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv4, bytelen))
return false;
} else {
if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen))
return false;
if (!(nexthop->rparent
&& IS_MAPPED_IPV6(&nexthop->rparent->gate.ipv6))) {
if (gw_family == AF_INET) {
if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv4, bytelen))
return false;
} else {
if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen))
return false;
}
}
}

Expand Down
12 changes: 10 additions & 2 deletions zebra/zebra_fpm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
struct rtattr *nest, *inner_nest;
struct rtnexthop *rtnh;
struct vxlan_encap_info_t *vxlan;
struct in6_addr ipv6;

struct {
struct nlmsghdr n;
Expand Down Expand Up @@ -423,8 +424,15 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
nhi = &ri->nhs[0];

if (nhi->gateway) {
nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
nhi->gateway, bytelen);
if (nhi->type == NEXTHOP_TYPE_IPV4_IFINDEX
&& ri->af == AF_INET6) {
ipv4_to_ipv4_mapped_ipv6(&ipv6,
nhi->gateway->ipv4);
nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
&ipv6, bytelen);
} else
nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
nhi->gateway, bytelen);
}

if (nhi->if_index) {
Expand Down
13 changes: 12 additions & 1 deletion zebra/zebra_nhg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
struct interface *ifp;
rib_dest_t *dest;
struct zebra_vrf *zvrf;
struct in_addr ipv4;

if ((nexthop->type == NEXTHOP_TYPE_IPV4)
|| nexthop->type == NEXTHOP_TYPE_IPV6)
Expand Down Expand Up @@ -1835,13 +1836,23 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
return 0;
}

/* Validation for ipv4 mapped ipv6 nexthop. */
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
afi = AFI_IP;
}

/* Make lookup prefix. */
memset(&p, 0, sizeof(struct prefix));
switch (afi) {
case AFI_IP:
p.family = AF_INET;
p.prefixlen = IPV4_MAX_PREFIXLEN;
p.u.prefix4 = nexthop->gate.ipv4;
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
ipv4_mapped_ipv6_to_ipv4(&nexthop->gate.ipv6, &ipv4);
p.u.prefix4 = ipv4;
} else {
p.u.prefix4 = nexthop->gate.ipv4;
}
break;
case AFI_IP6:
p.family = AF_INET6;
Expand Down

0 comments on commit c117742

Please sign in to comment.