zebra: Add multipath parsing to V6

In the near future it will be possible to recieve v6 multipath netlink
messages.  This code change is in prep for it.  In the meantime the
v6 code path will continue to work as per normal.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2017-01-30 14:50:06 -05:00
parent 89a9069abb
commit a2ca67d1d2

View file

@ -241,92 +241,8 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
p.family = AF_INET;
memcpy (&p.u.prefix4, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
if (rtm->rtm_src_len != 0)
{
zlog_warn ("unsupported IPv4 sourcedest route (dest %s/%d)",
inet_ntoa (p.u.prefix4), p.prefixlen);
return 0;
}
if (IS_ZEBRA_DEBUG_KERNEL)
{
char buf[PREFIX_STRLEN];
zlog_debug ("%s %s vrf %u",
nl_msg_type_to_str (h->nlmsg_type),
prefix2str (&p, buf, sizeof(buf)), vrf_id);
}
if (h->nlmsg_type == RTM_NEWROUTE)
{
if (!tb[RTA_MULTIPATH])
rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
0, flags, &p, NULL, gate, prefsrc, index,
table, metric, mtu, 0);
else
{
/* This is a multipath route */
struct rib *rib;
struct rtnexthop *rtnh =
(struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
rib->type = ZEBRA_ROUTE_KERNEL;
rib->distance = 0;
rib->flags = flags;
rib->metric = metric;
rib->mtu = mtu;
rib->vrf_id = vrf_id;
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
for (;;)
{
if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
break;
index = rtnh->rtnh_ifindex;
gate = 0;
if (rtnh->rtnh_len > sizeof (*rtnh))
{
memset (tb, 0, sizeof (tb));
netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
rtnh->rtnh_len - sizeof (*rtnh));
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
}
if (gate)
{
if (index)
rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
else
rib_nexthop_ipv4_add (rib, gate, prefsrc);
}
else
rib_nexthop_ifindex_add (rib, index);
len -= NLMSG_ALIGN(rtnh->rtnh_len);
rtnh = RTNH_NEXT(rtnh);
}
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
rib->nexthop_num);
if (rib->nexthop_num == 0)
XFREE (MTYPE_RIB, rib);
else
rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib);
}
}
else
rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
&p, NULL, gate, index, table);
}
if (rtm->rtm_family == AF_INET6)
else if (rtm->rtm_family == AF_INET6)
{
p.family = AF_INET6;
memcpy (&p.u.prefix6, dest, 16);
@ -335,27 +251,110 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
src_p.family = AF_INET6;
memcpy (&src_p.prefix, src, 16);
src_p.prefixlen = rtm->rtm_src_len;
}
if (IS_ZEBRA_DEBUG_KERNEL)
{
char buf[PREFIX_STRLEN];
char buf2[PREFIX_STRLEN];
zlog_debug ("%s %s%s%s vrf %u",
nl_msg_type_to_str (h->nlmsg_type),
prefix2str (&p, buf, sizeof(buf)),
src_p.prefixlen ? " from " : "",
src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
vrf_id);
}
if (rtm->rtm_src_len != 0)
{
char buf[PREFIX_STRLEN];
zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
prefix2str (&p, buf, sizeof(buf)), vrf_id);
return 0;
}
if (h->nlmsg_type == RTM_NEWROUTE)
rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
0, flags, &p, &src_p, gate, prefsrc, index,
if (IS_ZEBRA_DEBUG_KERNEL)
{
char buf[PREFIX_STRLEN];
char buf2[PREFIX_STRLEN];
zlog_debug ("%s %s%s%s vrf %u",
nl_msg_type_to_str (h->nlmsg_type),
prefix2str (&p, buf, sizeof(buf)),
src_p.prefixlen ? " from " : "",
src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
vrf_id);
}
afi_t afi = AFI_IP;
if (rtm->rtm_family == AF_INET6)
afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE)
{
if (!tb[RTA_MULTIPATH])
rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
0, flags, &p, NULL, gate, prefsrc, index,
table, metric, mtu, 0);
else
rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
0, flags, &p, &src_p, gate, index, table);
{
/* This is a multipath route */
struct rib *rib;
struct rtnexthop *rtnh =
(struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
rib->type = ZEBRA_ROUTE_KERNEL;
rib->distance = 0;
rib->flags = flags;
rib->metric = metric;
rib->mtu = mtu;
rib->vrf_id = vrf_id;
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
for (;;)
{
if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
break;
index = rtnh->rtnh_ifindex;
gate = 0;
if (rtnh->rtnh_len > sizeof (*rtnh))
{
memset (tb, 0, sizeof (tb));
netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
rtnh->rtnh_len - sizeof (*rtnh));
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
}
if (gate)
{
if (rtm->rtm_family == AF_INET)
{
if (index)
rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
else
rib_nexthop_ipv4_add (rib, gate, prefsrc);
}
else if (rtm->rtm_family == AF_INET6)
{
if (index)
rib_nexthop_ipv6_ifindex_add (rib, gate, index);
else
rib_nexthop_ipv6_add (rib,gate);
}
}
else
rib_nexthop_ifindex_add (rib, index);
len -= NLMSG_ALIGN(rtnh->rtnh_len);
rtnh = RTNH_NEXT(rtnh);
}
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
rib->nexthop_num);
if (rib->nexthop_num == 0)
XFREE (MTYPE_RIB, rib);
else
rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib);
}
}
else
rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
&p, NULL, gate, index, table);
return 0;
}