[quagga-dev 8377] Removal of interfaces doesn't delete routes

Daniel Fahlgren fahlgren at tutus.se
Tue Nov 30 16:35:58 GMT 2010


Hi,

I have discovered that Quagga isn't removing routes that are connected
to an interface when the interface is removed. If you have a usb network
card and have an extra route via that will that route be left in Quagga
if the card is removed. I have a usb network card that is recognized as
eth1. If I run

        ifconfig eth1 192.168.0.2 netmask 255.255.255.0 up
        route add -net 192.168.10.0 netmask 255.255.255.0 gw 192.168.0.1

will I have the following route in Quagga after I unplug the network
card (without first removing the routes and the interface):

        K * 192.168.10.0/24 via 192.168.0.1, unknown inactive

This is tested with Ubuntu 10.10 and Quagga from a git checkout.

This can also be tested with tun devices if you don't have access to a
network card that you can unplug.
        
        tunctl -t tun0
        ifconfig tun0 192.168.0.2 netmask 255.255.255.0 up
        route add -net 192.168.10.0 netmask 255.255.255.0 gw 192.168.0.1
        tunctl -d tun0

It doesn't seems like it get a notification that the kernel is removing
this route. The attached patch tries to fix it by iterating over any
route that is connected to this interface, but it doesn't handle ipv6
etc.

How and where should these routes be removed?

Cheers,
Daniel Fahlgren
-------------- next part --------------
diff --git a/zebra/interface.c b/zebra/interface.c
index 03e7ff7..ec7abec 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -381,6 +381,7 @@ if_delete_update (struct interface *ifp)
   struct prefix *p;
   struct route_node *rn;
   struct zebra_if *zebra_if;
+  struct route_table *table;
 
   zebra_if = ifp->info;
 
@@ -483,6 +484,28 @@ if_delete_update (struct interface *ifp)
 	    }
 	}
     }
+
+  /* Delete routes that are via this interface */
+  if ((table = vrf_table (AFI_IP, SAFI_UNICAST, 0)) != NULL)
+    {
+      struct route_node *rn;
+      for (rn = route_top (table); rn; rn = route_next (rn))
+	{
+	  struct rib *rib;
+	  for (rib = rn->info; rib; rib = rib->next)
+	    {
+	      if (rib->nexthop && rib->nexthop->ifindex == ifp->ifindex)
+		{
+		  struct prefix_ipv4 p;
+		  p.family = AF_INET;
+		  p.prefix = rn->p.u.prefix4;
+		  p.prefixlen = rn->p.prefixlen;
+		  rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, NULL,
+				   ifp->ifindex, 0);
+		}
+	    }
+	}
+    }
   zebra_interface_delete_update (ifp);
 
   /* Update ifindex after distributing the delete message.  This is in


More information about the Quagga-dev mailing list