[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