[PATCH] Allow setting the default route.
Bushman, Jeff
JBushman at ciena.com
Wed May 16 15:14:05 EDT 2012
Below is a patch which allows setting the default route, which is a route with no destination.
It also fixes a bug with setting the table attribute of a route. It only puts the table
attribute in the header if it is less than 256, and if it is greater
than 255, sets it as a U32 attribute.
It changes the scope guessing algorithm to match the one used by iproute2
when setting a route.
It uses the algorithm from iproute2 for setting the table ID for a route if
it is not specified by the caller.
With this patch, I was able to create a default route entry that was identical (or nearly so)
to the one created by using iproute2 from the command line.
Jeff
---
lib/route/route_obj.c | 70 +++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c
index ac634ae..da8b595 100644
--- a/lib/route/route_obj.c
+++ b/lib/route/route_obj.c
@@ -779,6 +779,26 @@ int rtnl_route_guess_scope(struct rtnl_route *route)
/** @} */
+static void adjust_scope(struct rtmsg *rtmsg, uint16_t cmd, int nexthop)
+{
+ if (rtmsg->rtm_type == RTN_LOCAL ||
+ rtmsg->rtm_type == RTN_NAT)
+ rtmsg->rtm_scope = RT_SCOPE_HOST;
+
+ else if (rtmsg->rtm_type == RTN_BROADCAST ||
+ rtmsg->rtm_type == RTN_MULTICAST ||
+ rtmsg->rtm_type == RTN_ANYCAST)
+ rtmsg->rtm_scope = RT_SCOPE_LINK;
+
+ else if (rtmsg->rtm_type == RTN_UNICAST ||
+ rtmsg->rtm_type == RTN_UNSPEC) {
+ if (cmd == RTM_DELROUTE)
+ rtmsg->rtm_scope = RT_SCOPE_NOWHERE;
+ else if (!nexthop)
+ rtmsg->rtm_scope = RT_SCOPE_LINK;
+ }
+}
+
static struct nla_policy route_policy[RTA_MAX+1] = {
[RTA_IIF] = { .type = NLA_U32 },
[RTA_OIF] = { .type = NLA_U32 },
@@ -1028,34 +1048,62 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route)
struct rtmsg rtmsg = {
.rtm_family = route->rt_family,
.rtm_tos = route->rt_tos,
- .rtm_table = route->rt_table,
.rtm_protocol = route->rt_protocol,
.rtm_scope = route->rt_scope,
.rtm_type = route->rt_type,
.rtm_flags = route->rt_flags,
};
- if (route->rt_dst == NULL)
- return -NLE_MISSING_ATTR;
+ int table_as_attr = 0;
+ uint16_t cmd = msg->nm_nlh->nlmsg_type;
+
+ /* Adjust defaults if necessary */
+ if (cmd != RTM_DELROUTE) {
+ if (!(route->ce_mask & ROUTE_ATTR_SCOPE))
+ rtmsg.rtm_scope = RT_SCOPE_UNIVERSE;
+ }
+
+ /* An empty destination is the "default" route */
+ if (route->rt_dst)
+ rtmsg.rtm_dst_len = nl_addr_get_prefixlen(route->rt_dst);
- rtmsg.rtm_dst_len = nl_addr_get_prefixlen(route->rt_dst);
if (route->rt_src)
rtmsg.rtm_src_len = nl_addr_get_prefixlen(route->rt_src);
+ /* If scope not explicitly set, adjust based on route type, command and
+ * nexthop or gateway */
+ if (!(route->ce_mask & ROUTE_ATTR_SCOPE))
+ adjust_scope(&rtmsg, cmd, rtnl_route_get_nnexthops(route));
+
+ /* If table ID won't fit in 8-bit value of header, add 32-bit
+ * attribute below. Is required to allow more than 256 tables. */
+ if (route->rt_table < 256)
+ rtmsg.rtm_table = route->rt_table;
+ else {
+ rtmsg.rtm_table = RT_TABLE_UNSPEC;
+ table_as_attr = 1;
+ }
- if (rtmsg.rtm_scope == RT_SCOPE_NOWHERE)
- rtmsg.rtm_scope = rtnl_route_guess_scope(route);
+ /* If table not explicitly set, adjust from MAIN to LOCAL for these
+ * special cases */
+ if (!(route->ce_mask & ROUTE_ATTR_TABLE))
+ if (route->rt_type == RTN_LOCAL ||
+ route->rt_type == RTN_BROADCAST ||
+ route->rt_type == RTN_NAT ||
+ route->rt_type == RTN_ANYCAST)
+ rtmsg.rtm_table = RT_TABLE_LOCAL;
if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
- /* Additional table attribute replacing the 8bit in the header, was
- * required to allow more than 256 tables. */
- NLA_PUT_U32(msg, RTA_TABLE, route->rt_table);
+ if (table_as_attr)
+ NLA_PUT_U32(msg, RTA_TABLE, route->rt_table);
- if (nl_addr_get_len(route->rt_dst))
+ if (route->rt_dst && nl_addr_get_len(route->rt_dst))
NLA_PUT_ADDR(msg, RTA_DST, route->rt_dst);
- NLA_PUT_U32(msg, RTA_PRIORITY, route->rt_prio);
+
+ if (route->ce_mask & ROUTE_ATTR_PRIO)
+ NLA_PUT_U32(msg, RTA_PRIORITY, route->rt_prio);
if (route->ce_mask & ROUTE_ATTR_SRC)
NLA_PUT_ADDR(msg, RTA_SRC, route->rt_src);
--
1.6.2.5
Jeffrey M. Bushman | Software Engineer 4
jbushman at ciena.com<mailto:jbushman at ciena.com> | 1185 Sanctuary Pkwy, Ste 300 | Alpharetta, GA 30009 USA
Direct +1.678.867.3572 | Fax +1.678.867.5101
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20120516/cf879d51/attachment-0001.html>
More information about the libnl
mailing list