[quagga-dev 11783] [PATCH 09/13] zebra: netlink: add srcdest route support
David Lamparter
equinox at opensourcerouting.org
Sat Nov 22 06:42:49 GMT 2014
This implements processing the RTA_SRC attribute on routes received from
kernel, passing along the source prefix to the RIB functions, and adds
the attribute on updates to the kernel.
NB: "src" was in use as variable name for the "prefsrc" attribute on
routes, which indicates the preferred source address for IPv4. These
variables have been renamed to "prefsrc".
Signed-off-by: David Lamparter <equinox at opensourcerouting.org>
---
zebra/rt_netlink.c | 113 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 65 insertions(+), 48 deletions(-)
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 5805494..6f088c7 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -669,13 +669,14 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
char anyaddr[16] = { 0 };
- int index;
+ int index = 0;
int table;
- int metric;
+ int metric = 0;
- void *dest;
- void *gate;
- void *src;
+ void *dest = NULL;
+ void *gate = NULL;
+ void *prefsrc = NULL; /* IPv4 preferred source host address */
+ void *src = NULL; /* IPv6 srcdest source prefix */
rtm = NLMSG_DATA (h);
@@ -704,19 +705,10 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (rtm->rtm_protocol == RTPROT_KERNEL)
return 0;
- if (rtm->rtm_src_len != 0)
- return 0;
-
/* Route which inserted by Zebra. */
if (rtm->rtm_protocol == RTPROT_ZEBRA)
flags |= ZEBRA_FLAG_SELFROUTE;
- index = 0;
- metric = 0;
- dest = NULL;
- gate = NULL;
- src = NULL;
-
if (tb[RTA_OIF])
index = *(int *) RTA_DATA (tb[RTA_OIF]);
@@ -725,8 +717,13 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
else
dest = anyaddr;
+ if (tb[RTA_SRC])
+ src = RTA_DATA (tb[RTA_SRC]);
+ else
+ src = anyaddr;
+
if (tb[RTA_PREFSRC])
- src = RTA_DATA (tb[RTA_PREFSRC]);
+ prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
@@ -741,8 +738,11 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
memcpy (&p.prefix, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
+ if (rtm->rtm_src_len != 0)
+ return 0;
+
if (!tb[RTA_MULTIPATH])
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
+ rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, prefsrc, index,
table, metric, 0, SAFI_UNICAST);
else
{
@@ -803,12 +803,16 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
#ifdef HAVE_IPV6
if (rtm->rtm_family == AF_INET6)
{
- struct prefix_ipv6 p;
+ struct prefix_ipv6 p, src_p;
p.family = AF_INET6;
memcpy (&p.prefix, dest, 16);
p.prefixlen = rtm->rtm_dst_len;
- rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, NULL, gate, index, table,
+ src_p.family = AF_INET6;
+ memcpy (&src_p.prefix, src, 16);
+ src_p.prefixlen = rtm->rtm_src_len;
+
+ rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, &src_p, gate, index, table,
metric, 0, SAFI_UNICAST);
}
#endif /* HAVE_IPV6 */
@@ -841,13 +845,14 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
char anyaddr[16] = { 0 };
- int index;
+ int index = 0;
int table;
- int metric;
+ int metric = 0;
- void *dest;
- void *gate;
- void *src;
+ void *dest = NULL;
+ void *gate = NULL;
+ void *prefsrc = NULL; /* IPv4 preferred source host address */
+ void *src = NULL; /* IPv6 srcdest source prefix */
rtm = NLMSG_DATA (h);
@@ -895,18 +900,6 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
return 0;
- if (rtm->rtm_src_len != 0)
- {
- zlog_warn ("netlink_route_change(): no src len");
- return 0;
- }
-
- index = 0;
- metric = 0;
- dest = NULL;
- gate = NULL;
- src = NULL;
-
if (tb[RTA_OIF])
index = *(int *) RTA_DATA (tb[RTA_OIF]);
@@ -915,11 +908,16 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
else
dest = anyaddr;
+ if (tb[RTA_SRC])
+ src = RTA_DATA (tb[RTA_SRC]);
+ else
+ src = anyaddr;
+
if (tb[RTA_GATEWAY])
gate = RTA_DATA (tb[RTA_GATEWAY]);
if (tb[RTA_PREFSRC])
- src = RTA_DATA (tb[RTA_PREFSRC]);
+ prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
@@ -931,6 +929,13 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
memcpy (&p.prefix, 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.prefix), p.prefixlen);
+ return 0;
+ }
+
if (IS_ZEBRA_DEBUG_KERNEL)
{
if (h->nlmsg_type == RTM_NEWROUTE)
@@ -944,8 +949,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (h->nlmsg_type == RTM_NEWROUTE)
{
if (!tb[RTA_MULTIPATH])
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
- metric, 0, SAFI_UNICAST);
+ rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, prefsrc, index,
+ table, metric, 0, SAFI_UNICAST);
else
{
/* This is a multipath route */
@@ -985,9 +990,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (gate)
{
if (index)
- nexthop_ipv4_ifindex_add (rib, gate, src, index);
+ nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
else
- nexthop_ipv4_add (rib, gate, src);
+ nexthop_ipv4_add (rib, gate, prefsrc);
}
else
nexthop_ifindex_add (rib, index);
@@ -1009,30 +1014,39 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
#ifdef HAVE_IPV6
if (rtm->rtm_family == AF_INET6)
{
- struct prefix_ipv6 p;
- char buf[BUFSIZ];
+ struct prefix_ipv6 p, src_p;
+ char buf[BUFSIZ], src_info[BUFSIZ];
p.family = AF_INET6;
memcpy (&p.prefix, dest, 16);
p.prefixlen = rtm->rtm_dst_len;
+ src_p.family = AF_INET6;
+ memcpy (&src_p.prefix, src, 16);
+ src_p.prefixlen = rtm->rtm_src_len;
+
+ if (rtm->rtm_src_len)
+ snprintf (src_info, sizeof (src_info), " from %s/%d",
+ inet_ntop (AF_INET6, &src_p.prefix, buf, BUFSIZ),
+ src_p.prefixlen);
+
if (IS_ZEBRA_DEBUG_KERNEL)
{
if (h->nlmsg_type == RTM_NEWROUTE)
- zlog_debug ("RTM_NEWROUTE %s/%d",
+ zlog_debug ("RTM_NEWROUTE %s/%d%s",
inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
- p.prefixlen);
+ p.prefixlen, src_info);
else
- zlog_debug ("RTM_DELROUTE %s/%d",
+ zlog_debug ("RTM_DELROUTE %s/%d%s",
inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
- p.prefixlen);
+ p.prefixlen, src_info);
}
if (h->nlmsg_type == RTM_NEWROUTE)
- rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, NULL, gate, index, table,
+ rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, &src_p, gate, index, table,
metric, 0, SAFI_UNICAST);
else
- rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, NULL, gate, index, table,
+ rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, &src_p, gate, index, table,
SAFI_UNICAST);
}
#endif /* HAVE_IPV6 */
@@ -1682,6 +1696,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
req.r.rtm_family = family;
req.r.rtm_table = rib->table;
req.r.rtm_dst_len = p->prefixlen;
+ req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
req.r.rtm_protocol = RTPROT_ZEBRA;
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
@@ -1706,6 +1721,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
}
addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
+ if (src_p)
+ addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen);
/* Metric. */
addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
--
1.8.5.5
More information about the Quagga-dev
mailing list