forked from Mirror/frr
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:
parent
89a9069abb
commit
a2ca67d1d2
|
@ -241,92 +241,8 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||||
p.family = AF_INET;
|
p.family = AF_INET;
|
||||||
memcpy (&p.u.prefix4, dest, 4);
|
memcpy (&p.u.prefix4, dest, 4);
|
||||||
p.prefixlen = rtm->rtm_dst_len;
|
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;
|
p.family = AF_INET6;
|
||||||
memcpy (&p.u.prefix6, dest, 16);
|
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;
|
src_p.family = AF_INET6;
|
||||||
memcpy (&src_p.prefix, src, 16);
|
memcpy (&src_p.prefix, src, 16);
|
||||||
src_p.prefixlen = rtm->rtm_src_len;
|
src_p.prefixlen = rtm->rtm_src_len;
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
if (rtm->rtm_src_len != 0)
|
||||||
{
|
{
|
||||||
char buf[PREFIX_STRLEN];
|
char buf[PREFIX_STRLEN];
|
||||||
char buf2[PREFIX_STRLEN];
|
zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
|
||||||
zlog_debug ("%s %s%s%s vrf %u",
|
prefix2str (&p, buf, sizeof(buf)), vrf_id);
|
||||||
nl_msg_type_to_str (h->nlmsg_type),
|
return 0;
|
||||||
prefix2str (&p, buf, sizeof(buf)),
|
}
|
||||||
src_p.prefixlen ? " from " : "",
|
|
||||||
src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
|
|
||||||
vrf_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h->nlmsg_type == RTM_NEWROUTE)
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
|
{
|
||||||
0, flags, &p, &src_p, gate, prefsrc, index,
|
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);
|
table, metric, mtu, 0);
|
||||||
else
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue