Added a macro to validate the v4 mapped v6 address.
Modified bgp receive & send updates for v4 mapped v6 address as
nexthop and installing it as recursive nexthop in RIB.
Minor change in fpm while sending the routes for nexthop as
v4 mapped v6 address.
Signed-off-by: Kaushik <kaushik@niralnetworks.com>
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)
: 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)
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:
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,
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
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;
+ }
}
}
struct rtattr *nest, *inner_nest;
struct rtnexthop *rtnh;
struct vxlan_encap_info_t *vxlan;
+ struct in6_addr ipv6;
struct {
struct nlmsghdr n;
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) {
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)
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;