[systemd-devel] [PATCH v2] networkd: set route protocol

Dan Williams dcbw at redhat.com
Tue Jul 22 14:54:47 PDT 2014


All routes added by networkd are currently set RTPROT_BOOT, which according
to the kernel means "Route installed during boot" (rtnetlink.h).  But this
is not always the case as networkd changes routing after boot too.  Since
the kernel gives more detailed protocols, use them.

With this patch, user-configured static routes now use RTPROT_STATIC (which
they are) and DHCP routes use RTPROT_DHCP.  There is no define for IPv4LL
yet, so those are installed as RTPROT_STATIC (though perhaps RTPROT_RA is
better?).

Signed-off-by: Dan Williams <dcbw at redhat.com>
---
v2: rebase missed one case of RTPROT_DHCP; now fixed

 src/libsystemd/sd-rtnl/rtnl-message.c |  5 +++--
 src/libsystemd/sd-rtnl/test-rtnl.c    |  2 +-
 src/network/networkd-link.c           | 14 +++++++-------
 src/network/networkd-route.c          | 10 +++++++---
 src/network/networkd.h                |  3 ++-
 src/systemd/sd-rtnl.h                 |  2 +-
 6 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 7f2e398..c50d0ea 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -129,15 +129,16 @@ int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
 
         rtm->rtm_scope = scope;
 
         return 0;
 }
 
 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
-                              uint16_t nlmsg_type, int rtm_family) {
+                              uint16_t nlmsg_type, int rtm_family,
+                              unsigned char rtm_protocol) {
         struct rtmsg *rtm;
         int r;
 
         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
         assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
         assert_return(ret, -EINVAL);
 
@@ -150,15 +151,15 @@ int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
 
         rtm = NLMSG_DATA((*ret)->hdr);
 
         rtm->rtm_family = rtm_family;
         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
         rtm->rtm_type = RTN_UNICAST;
         rtm->rtm_table = RT_TABLE_MAIN;
-        rtm->rtm_protocol = RTPROT_BOOT;
+        rtm->rtm_protocol = rtm_protocol;
 
         return 0;
 }
 
 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
         struct ifinfomsg *ifi;
 
diff --git a/src/libsystemd/sd-rtnl/test-rtnl.c b/src/libsystemd/sd-rtnl/test-rtnl.c
index 082c9e4..4b6e533 100644
--- a/src/libsystemd/sd-rtnl/test-rtnl.c
+++ b/src/libsystemd/sd-rtnl/test-rtnl.c
@@ -128,15 +128,15 @@ static void test_address_get(sd_rtnl *rtnl, int ifindex) {
 
 static void test_route(void) {
         _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
         struct in_addr addr, addr_data;
         uint32_t index = 2, u32_data;
         int r;
 
-        r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
+        r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
         if (r < 0) {
                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
                 return;
         }
 
         addr.s_addr = htonl(INADDR_LOOPBACK);
 
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0a6f524..5b70578 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -411,15 +411,15 @@ static int link_set_dhcp_routes(Link *link) {
                         log_warning_link(link, "DHCP error: could not get routes: %s", strerror(-n));
                 return n;
         }
 
         for (i = 0; i < n; i++) {
                 _cleanup_route_free_ Route *route = NULL;
 
-                r = route_new_dynamic(&route);
+                r = route_new_dynamic(&route, RTPROT_DHCP);
                 if (r < 0) {
                         log_error_link(link, "Could not allocate route: %s",
                                        strerror(-r));
                         return r;
                 }
 
                 route->family = AF_INET;
@@ -477,15 +477,15 @@ static int link_enter_set_routes(Link *link) {
                 if (r < 0 && r != -ENOENT) {
                         log_warning_link(link, "IPV4LL error: no address: %s",
                                         strerror(-r));
                         return r;
                 }
 
                 if (r != -ENOENT) {
-                        r = route_new_dynamic(&route);
+                        r = route_new_dynamic(&route, RTPROT_STATIC);
                         if (r < 0) {
                                 log_error_link(link, "Could not allocate route: %s",
                                                strerror(-r));
                                 return r;
                         }
 
                         route->family = AF_INET;
@@ -513,22 +513,22 @@ static int link_enter_set_routes(Link *link) {
                 if (r < 0 && r != -ENOENT) {
                         log_warning_link(link, "DHCP error: could not get gateway: %s",
                                          strerror(-r));
                         return r;
                 }
 
                 if (r >= 0) {
-                        r = route_new_dynamic(&route);
+                        r = route_new_dynamic(&route, RTPROT_DHCP);
                         if (r < 0) {
                                 log_error_link(link, "Could not allocate route: %s",
                                                strerror(-r));
                                 return r;
                         }
 
-                        r = route_new_dynamic(&route_gw);
+                        r = route_new_dynamic(&route_gw, RTPROT_DHCP);
                         if (r < 0) {
                                 log_error_link(link, "Could not allocate route: %s",
                                                strerror(-r));
                                 return r;
                         }
 
                         /* The dhcp netmask may mask out the gateway. Add an explicit
@@ -985,25 +985,25 @@ static int dhcp_lease_lost(Link *link) {
         r = address_new_dynamic(&address);
         if (r >= 0) {
                 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
                 if (r >= 0) {
                         _cleanup_route_free_ Route *route_gw = NULL;
                         _cleanup_route_free_ Route *route = NULL;
 
-                        r = route_new_dynamic(&route_gw);
+                        r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
                         if (r >= 0) {
                                 route_gw->family = AF_INET;
                                 route_gw->dst_addr.in = gateway;
                                 route_gw->dst_prefixlen = 32;
                                 route_gw->scope = RT_SCOPE_LINK;
 
                                 route_drop(route_gw, link, &route_drop_handler);
                         }
 
-                        r = route_new_dynamic(&route);
+                        r = route_new_dynamic(&route, RTPROT_UNSPEC);
                         if (r >= 0) {
                                 route->family = AF_INET;
                                 route->in_addr.in = gateway;
 
                                 route_drop(route, link, &route_drop_handler);
                         }
                 }
@@ -1312,15 +1312,15 @@ static int ipv4ll_address_lost(Link *link) {
                 address->family = AF_INET;
                 address->in_addr.in = addr;
                 address->prefixlen = 16;
                 address->scope = RT_SCOPE_LINK;
 
                 address_drop(address, link, &address_drop_handler);
 
-                r = route_new_dynamic(&route);
+                r = route_new_dynamic(&route, RTPROT_UNSPEC);
                 if (r < 0) {
                         log_error_link(link, "Could not allocate route: %s",
                                        strerror(-r));
                         return r;
                 }
 
                 route->family = AF_INET;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 8949299..00fd952 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -45,14 +45,15 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
 
         route = new0(Route, 1);
         if (!route)
                 return -ENOMEM;
 
         route->family = AF_UNSPEC;
         route->scope = RT_SCOPE_UNIVERSE;
+        route->protocol = RTPROT_STATIC;
 
         route->network = network;
 
         LIST_PREPEND(routes, network->static_routes, route);
 
         if (section) {
                 route->section = section;
@@ -61,23 +62,24 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
 
         *ret = route;
         route = NULL;
 
         return 0;
 }
 
-int route_new_dynamic(Route **ret) {
+int route_new_dynamic(Route **ret, unsigned char rtm_protocol) {
         _cleanup_route_free_ Route *route = NULL;
 
         route = new0(Route, 1);
         if (!route)
                 return -ENOMEM;
 
         route->family = AF_UNSPEC;
         route->scope = RT_SCOPE_UNIVERSE;
+        route->protocol = rtm_protocol;
 
         *ret = route;
         route = NULL;
 
         return 0;
 }
 
@@ -104,15 +106,16 @@ int route_drop(Route *route, Link *link,
         assert(link);
         assert(link->manager);
         assert(link->manager->rtnl);
         assert(link->ifindex > 0);
         assert(route->family == AF_INET || route->family == AF_INET6);
 
         r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
-                                      RTM_DELROUTE, route->family);
+                                      RTM_DELROUTE, route->family,
+                                      route->protocol);
         if (r < 0) {
                 log_error("Could not create RTM_DELROUTE message: %s", strerror(-r));
                 return r;
         }
 
         if (route->family == AF_INET)
                 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
@@ -177,15 +180,16 @@ int route_configure(Route *route, Link *link,
         assert(link);
         assert(link->manager);
         assert(link->manager->rtnl);
         assert(link->ifindex > 0);
         assert(route->family == AF_INET || route->family == AF_INET6);
 
         r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
-                                      RTM_NEWROUTE, route->family);
+                                      RTM_NEWROUTE, route->family,
+                                      route->protocol);
         if (r < 0) {
                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
                 return r;
         }
 
         if (route->family == AF_INET)
                 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
diff --git a/src/network/networkd.h b/src/network/networkd.h
index f1c7f20..7d291e5 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -133,14 +133,15 @@ struct Route {
         Network *network;
         uint64_t section;
 
         int family;
         unsigned char dst_prefixlen;
         unsigned char scope;
         uint32_t metrics;
+        unsigned char protocol;  /* RTPROT_* */
 
         union in_addr_union in_addr;
         union in_addr_union dst_addr;
 
         LIST_FIELDS(Route, routes);
 };
 
@@ -301,15 +302,15 @@ int config_parse_tunnel_address(const char *unit,
                                 void *userdata);
 
 /* gperf */
 const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
 
 /* Route */
 int route_new_static(Network *network, unsigned section, Route **ret);
-int route_new_dynamic(Route **ret);
+int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
 void route_free(Route *route);
 int route_configure(Route *route, Link *link, sd_rtnl_message_handler_t callback);
 int route_drop(Route *route, Link *link, sd_rtnl_message_handler_t callback);
 
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
 #define _cleanup_route_free_ _cleanup_(route_freep)
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 5cd26d9..47bb232 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -68,15 +68,15 @@ int sd_rtnl_detach_event(sd_rtnl *nl);
 
 /* messages */
 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t msg_type, int index);
 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret, int index, int family);
 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t msg_type, int index,
                              int family);
 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type,
-                              int rtm_family);
+                              int rtm_family, unsigned char rtm_protocol);
 
 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m);
 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m);
 
 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump);
 int sd_rtnl_message_get_errno(sd_rtnl_message *m);
 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type);
-- 
1.9.3




More information about the systemd-devel mailing list