diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-01-30 20:50:06 +0100 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-03-01 14:30:50 +0100 |
commit | a2ca67d1d21ee8fdf33906e12815663584634e94 (patch) | |
tree | d7b257d6c9ba755d127b54661c3368dcc9f1eec2 /zebra/rt_netlink.c | |
parent | zebra: Refactor netlink_route_change and netlink_route_change_read_unicast (diff) | |
download | frr-a2ca67d1d21ee8fdf33906e12815663584634e94.tar.xz frr-a2ca67d1d21ee8fdf33906e12815663584634e94.zip |
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>
Diffstat (limited to '')
-rw-r--r-- | zebra/rt_netlink.c | 191 |
1 files changed, 95 insertions, 96 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4e5c16a33..0c3d17dbd 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -241,121 +241,120 @@ 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; + } + else if (rtm->rtm_family == AF_INET6) + { + p.family = AF_INET6; + memcpy (&p.u.prefix6, dest, 16); + 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; - } + 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]; - zlog_debug ("%s %s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - prefix2str (&p, buf, sizeof(buf)), 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 (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 (h->nlmsg_type == RTM_NEWROUTE) + 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 { - 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 (;;) { - /* 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; + 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]); - } + 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 (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 - rib_nexthop_ifindex_add (rib, index); - - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); + else if (rtm->rtm_family == AF_INET6) + { + if (index) + rib_nexthop_ipv6_ifindex_add (rib, gate, index); + else + rib_nexthop_ipv6_add (rib,gate); + } } - - 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) - { - p.family = AF_INET6; - memcpy (&p.u.prefix6, dest, 16); - p.prefixlen = rtm->rtm_dst_len; + rib_nexthop_ifindex_add (rib, index); - src_p.family = AF_INET6; - memcpy (&src_p.prefix, src, 16); - src_p.prefixlen = rtm->rtm_src_len; + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } - 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); + 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); } - - 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, - table, metric, mtu, 0); - else - rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, &src_p, gate, index, table); } + else + rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, + &p, NULL, gate, index, table); return 0; } |