[Babel-users] the routing atomic update wet paint - because *I* care

Matthieu Boutier boutier at pps.univ-paris-diderot.fr
Mon Apr 6 08:56:41 UTC 2015


> Is there anywhere a good reference to netlink?

iproute2, libnl, kernel sources ?


>> If I understand it correctly you just need to set the routes with
>> NLM_F_CREATE | NLM_F_REPLACE to get the atomic replacement.

> -DEFINES = $(PLATFORM_DEFINES) -DVERSION=\"$(VERSION)\"
> +DEFINES = $(PLATFORM_DEFINES) -DVERSION=\"$(VERSION)\" -DIPV6_SUBTREES

IPV6_SUBTREES macro is out-of-date now: we use dynamic configuration.

> -    if(operation == ROUTE_ADD) {
> -        buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
> +    switch(operation) {
> +    case ROUTE_ADD:
> +        buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;

Why did you remove EXCL? and why using REPLACE here?

> +    case ROUTE_MODIFY:
> +        buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
> +        buf.nh.nlmsg_type = RTM_NEWROUTE;

Seems reasonable (but I would keep EXCL).

> +    if(operation == ROUTE_FLUSH) {
> +     rtm->rtm_scope = RT_SCOPE_NOWHERE;
> +    }

This should be a separate patch: why this change?

> +    if(operation == ROUTE_FLUSH) {
> +        *(int*)RTA_DATA(rta) = 0;
> +    } else {
>         *(int*)RTA_DATA(rta) = ifindex;
> -
> + }

Same, why this change?

The main flaw is that you never use the "new*" arguments: no chances to work.

You can try this untested patch (and note I have no clue how REPLACE should work):

$ git diff kernel_netlink.c
diff --git a/kernel_netlink.c b/kernel_netlink.c
index eb2e801..f115003 100644
--- a/kernel_netlink.c
+++ b/kernel_netlink.c
@@ -929,6 +929,9 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
     struct rtattr *rta;
     int len = sizeof(buf.raw);
     int rc, ipv4, table, use_src = 0;
+    const int has_atomic_replacement = has_ipv6_subtrees; /* Dave says that if a
+        kernel is new enough to do IPV6_SUBTREES, then it can do atomic
+        updates */
 
     if(!nl_setup) {
         fprintf(stderr,"kernel_route: netlink not initialized.\n");
@@ -948,6 +951,12 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
         }
     }
 
+    if(has_atomic_replacement && operation == ROUTE_MODIFY) {
+        gate = newgate;
+        ifindex = newifindex;
+        metric = newmetric;
+    }
+
     /* Check that the protocol family is consistent. */
     if(plen >= 96 && v4mapped(dest)) {
         if(!v4mapped(gate) ||
@@ -962,6 +971,7 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
         }
     }
 
+    if(has_atomic_replacement) {
     if(operation == ROUTE_MODIFY) {
         if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
            newifindex == ifindex)
@@ -988,6 +998,7 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
         }
         return rc;
     }
+    }
 
 
     ipv4 = v4mapped(gate);
@@ -1019,9 +1030,16 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
     if(operation == ROUTE_ADD) {
         buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
         buf.nh.nlmsg_type = RTM_NEWROUTE;
-    } else {
+    } else if(operation == ROUTE_FLUSH) {
         buf.nh.nlmsg_flags = NLM_F_REQUEST;
         buf.nh.nlmsg_type = RTM_DELROUTE;
+    } else if(operation == ROUTE_MODIFY) {
+        buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL
+            | NLM_F_REPLACE;
+        buf.nh.nlmsg_type = RTM_NEWROUTE;
+    } else {
+        errno = EINVAL;
+        return -1;
     }
 
     rtm = NLMSG_DATA(&buf.nh);

Matthieu




More information about the Babel-users mailing list