Skip to content

Commit

Permalink
BGP : Fix for nexthop as IPv4 mapped IPv6 address
Browse files Browse the repository at this point in the history
1. Added a macro to validate the IPv4 Mapped IPv6 address.
2. Modifications done for bgp receive and while sending updates
   for IPv4 Mapped IPv6 address as nexthop.
3. Modifications done for installing IPv4 Mapped IPv6 address as nexthop
   in RIB.
4. Minor correction done in fpm while sending the routes for
   nexthop as IPv4 Mapped IPv6 address.

Signed-off-by: Kaushik <kaushik@niralnetworks.com>
  • Loading branch information
KaushikNiral committed Jul 29, 2020
1 parent 93d0887 commit fb598ae
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 @@ -93,6 +93,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 fb598ae

Please sign in to comment.