netdev
[Top] [All Lists]

static routes and dead gateway detection

To: netdev@xxxxxxxxxxx
Subject: static routes and dead gateway detection
From: Julian Anastasov <ja@xxxxxx>
Date: Wed, 27 Jun 2001 15:03:52 +0300 (EEST)
Cc: kuznet@xxxxxxxxxxxxx
Sender: owner-netdev@xxxxxxxxxxx
        Hello,

        In the current kernels I see that all routes are deleted when
a device goes down (!IFF_UP -> NETDEV_DOWN). I can't find a place
where the proto static routes are used. So, I implemented a way to
make the proto static routes permanent. By this way devices that change
the device status will not delete these static routes. They are marked
dead and are not used (they are ignored). The current kernels already
have the ability to detect these dead routes and to ignore them. So,
I'm wondering whether such patch (appended) is useful for the mainstream
kernel(s). It is for 2.2 and can be ported to 2.4 too. How these RTPROT
codes are really used in the routing daemons and do they use static
routes too? The patch works as expected and I don't see problems for
now. The dead static routes as preserved until all nexthop devices
are deleted or until the pref source is deleted.

        What I see as problem even in the plain 2.2.19 kernel is that
when one device for one of the nexthops (when the prefsrc is not from
this device) is removed and added again it can receive another dev index
and the nexthop remains unused until the multipath route is recreated.
May be due to missing ref counter. I see ref counting in 2.4 but
I'm not sure whether the same problem exists there. But it seems such
problem can be solved only with a nh_ifname field or something similar.
This can be a 2.5 issue may be.

        I'm just not sure whether an 2.2 kernel oops can occur when
the nexthop uses a removed device and nh_dev points to "somewhere".
The patch contains a fix in fib_sync_up() about similar problem, i.e.
not to touch nh_dev for DEAD routes.

Comments?


Regards

--
Julian Anastasov <ja@xxxxxx>


--- v2.2.19/linux/include/net/ip_fib.h.orig     Mon Jun 25 15:56:49 2001
+++ linux/include/net/ip_fib.h  Wed Jun 27 12:02:23 2001
@@ -214,6 +214,7 @@
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                         u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, 
u8 tos,
                         struct fib_info *fi);
+extern int fib_num_down_nh_devs(struct fib_info *fi);
 extern int fib_sync_down(u32 local, struct device *dev, int force);
 extern int fib_sync_up(struct device *dev);
 extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
--- v2.2.19/linux/net/ipv4/fib_hash.c.orig      Mon Feb 19 13:44:54 2001
+++ linux/net/ipv4/fib_hash.c   Mon Jun 25 16:36:43 2001
@@ -349,7 +349,8 @@

                if ((f->fn_state&FN_S_ZOMBIE) ||
                    f->fn_scope != res->scope ||
-                   f->fn_type != RTN_UNICAST)
+                   f->fn_type != RTN_UNICAST ||
+                   next_fi->fib_flags&RTNH_F_DEAD)
                        continue;

                if (next_fi->fib_priority > res->fi->fib_priority)
@@ -686,7 +687,10 @@
        while ((f = *fp) != NULL) {
                struct fib_info *fi = FIB_INFO(f);

-               if (fi && ((f->fn_state&FN_S_ZOMBIE) || 
(fi->fib_flags&RTNH_F_DEAD))) {
+               if (fi && ((f->fn_state&FN_S_ZOMBIE) ||
+                   (fi->fib_flags&RTNH_F_DEAD &&
+                   (fi->fib_protocol != RTPROT_STATIC ||
+                   !fib_num_down_nh_devs(fi))))) {
                        *fp = f->fn_next;
                        synchronize_bh();

--- v2.2.19/linux/net/ipv4/fib_semantics.c.orig Mon Feb 19 13:44:44 2001
+++ linux/net/ipv4/fib_semantics.c      Wed Jun 27 14:19:00 2001
@@ -170,6 +170,30 @@
        return -1;
 }

+/*
+ * Return 0 only when we are sure that the preferred source is deleted
+ * or when all nexthop devices are removed
+ */
+
+int fib_num_down_nh_devs(struct fib_info *fi)
+{
+struct in_device *in_dev;
+struct device *dev;
+int dead = 0;
+
+       change_nexthops(fi) {
+               if (!(nh->nh_flags&RTNH_F_DEAD))
+                       return 0;
+               dev = dev_get_by_index(nh->nh_oif);
+               if (dev && !(dev->flags&IFF_UP) &&
+                   ((in_dev = dev->ip_ptr) != NULL) &&
+                   in_dev->ifa_list)
+                       dead ++;
+       } endfor_nexthops(fi)
+       /* dead>0: All are marked DEAD but there is one in DOWN state */
+       return dead;
+}
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH

 static u32 fib_get_attr32(struct rtattr *attr, int attrlen, int type)
@@ -880,9 +904,9 @@
                                alive++;
                                continue;
                        }
-                       if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
+                       if (nh->nh_oif != dev->ifindex || dev->ip_ptr == NULL)
                                continue;
-                       if (nh->nh_dev != dev || dev->ip_ptr == NULL)
+                       if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
                                continue;
                        alive++;
                        nh->nh_power = 0;


<Prev in Thread] Current Thread [Next in Thread>
  • static routes and dead gateway detection, Julian Anastasov <=