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

Dave Taht dave.taht at gmail.com
Mon Apr 6 06:43:01 UTC 2015


Is there anywhere a good reference to netlink?

On Mon, Mar 16, 2015 at 11:32 AM, Henning Rogge <hrogge at gmail.com> wrote:
> On Mon, Mar 16, 2015 at 7:25 PM, Dave Taht <dave.taht at gmail.com> wrote:
>> got code?
>
> I just used the same code I use for IPv4 (which has been working for
> atomic replacement for ages).
>
> I got confused when someone reported "multiple IPv6 routes" which I
> could not reproduce.
>
> http://olsr.org/git/?p=oonf.git;a=blob;f=src-plugins/subsystems/os_linux/os_routing_linux.c;h=4194fd04f8f259b686a1343cc906fc8649c6a7b6;hb=master
>
> If I understand it correctly you just need to set the routes with
> NLM_F_CREATE | NLM_F_REPLACE to get the atomic replacement.

Well, I tried a naive approach to that for babel after looking over
the olsr code and did not succeed at this level. I am curious as to
whether this sequence of events works for olsr, in the first place.

start it up on two machines
add an ipv6 address on machine A)
wait for it to show up in the routing table for B)
delete the ipv6 address on machine A)
See if it is unreachable, then gone on B)

What happens with the patch below (and variants), is that babel thinks
it has modified
the route but it is not gone. I dont understand how the operation
could work in the first place
actually... don´t you have to feed both the old route and the new into
the netmsg?

I am going to go read the iproute2 code for bedtime sleepies. and git
clone a fresh tree
from git://github.com/jech/babeld.git

root at ranger:/sys/class/net/eth0# ip -6 addr add 2601:9:4e01:9200::4/128 dev eth3
root at ranger:/sys/class/net/eth0# ip -6 addr del 2601:9:4e01:9200::4/128 dev eth3

on nuc:

2601:9:4e01:9200::4/128 from ::/0 metric 65535 (65535) refmetric 65535
id 02:25:90:ff:fe:f4:a5:c2 seqno 62322 chan (255) age 58 via eth0
neigh fe80::2ac6:8eff:febb:9ff1 (installed)

but not gone in the FIB. I am running linux-3.18. The too simple babel patch:

diff --git a/Makefile b/Makefile
index 1bbb100..81f77cb 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ VERSION := $(shell ./get-version)

 CDEBUGFLAGS = -Os -g -Wall

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

 CFLAGS = $(CDEBUGFLAGS) $(DEFINES) $(EXTRA_DEFINES)

diff --git a/kernel_netlink.c b/kernel_netlink.c
index eb2e801..47a9c56 100644
--- a/kernel_netlink.c
+++ b/kernel_netlink.c
@@ -966,6 +966,9 @@ kernel_route(int operation, const unsigned char
*dest, unsigned short plen,
         if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
            newifindex == ifindex)
             return 0;
+ /* If a kernel is new enough to do IPV6_SUBTREES it can do
+   atomic updates if only I knew how */
+#ifndef IPV6_SUBTREES
         /* It would be better to add the new route before removing the
            old one, to avoid losing packets.  However, this causes
            problems with non-multipath kernels, which sometimes
@@ -987,6 +990,7 @@ kernel_route(int operation, const unsigned char
*dest, unsigned short plen,
                Error handling is hard. */
         }
         return rc;
+#endif
     }


@@ -1006,7 +1010,8 @@ kernel_route(int operation, const unsigned char
*dest, unsigned short plen,
     kdebugf("kernel_route: %s %s from %s "
             "table %d metric %d dev %d nexthop %s\n",
             operation == ROUTE_ADD ? "add" :
-            operation == ROUTE_FLUSH ? "flush" : "???",
+            operation == ROUTE_FLUSH ? "flush" :
+    operation == ROUTE_MODIFY ? "modify" : "???",
             format_prefix(dest, plen), format_prefix(src, src_plen),
             table, metric, ifindex, format_address(gate));

@@ -1016,14 +1021,20 @@ kernel_route(int operation, const unsigned
char *dest, unsigned short plen,
         return 0;

     memset(buf.raw, 0, sizeof(buf.raw));
-    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;
         buf.nh.nlmsg_type = RTM_NEWROUTE;
-    } else {
+ break;
+    case ROUTE_FLUSH:
         buf.nh.nlmsg_flags = NLM_F_REQUEST;
         buf.nh.nlmsg_type = RTM_DELROUTE;
-    }
-
+ break;
+    case ROUTE_MODIFY:
+        buf.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
+        buf.nh.nlmsg_type = RTM_NEWROUTE;
+ break;
+    }
     rtm = NLMSG_DATA(&buf.nh);
     rtm->rtm_family = ipv4 ? AF_INET : AF_INET6;
     rtm->rtm_dst_len = ipv4 ? plen - 96 : plen;
@@ -1031,6 +1042,9 @@ kernel_route(int operation, const unsigned char
*dest, unsigned short plen,
         rtm->rtm_src_len = src_plen;
     rtm->rtm_table = table;
     rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+    if(operation == ROUTE_FLUSH) {
+     rtm->rtm_scope = RT_SCOPE_NOWHERE;
+    }
     if(metric < KERNEL_INFINITY)
         rtm->rtm_type = RTN_UNICAST;
     else
@@ -1067,8 +1081,11 @@ kernel_route(int operation, const unsigned char
*dest, unsigned short plen,
         rta = RTA_NEXT(rta, len);
         rta->rta_len = RTA_LENGTH(sizeof(int));
         rta->rta_type = RTA_OIF;
+    if(operation == ROUTE_FLUSH) {
+        *(int*)RTA_DATA(rta) = 0;
+    } else {
         *(int*)RTA_DATA(rta) = ifindex;
-
+ }
         if(ipv4) {
             rta = RTA_NEXT(rta, len);
             rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
-- 
Dave Täht
Let's make wifi fast, less jittery and reliable again!

https://plus.google.com/u/0/107942175615993706558/posts/TVX3o84jjmb



More information about the Babel-users mailing list