[PATCH] Reg Review of changes flush all routing table entries in side kernel

2008-02-08 Thread dur...@it.iitb.ac.in phani
Problem :   Need to clean up routing table entries in side the Linux
kernel. But  kernel is not providing  single command to clear all
routing table entries at once.

Modified the kernel to take of the changesDefined new  net link
message under  NETLINK_ROUTE   family  RTM_FLUSHROUTE.   At the
receiving end in side kernel,  removed all routing table entries
related with each device.

  Changed the code so that only the corresponding device reference
will be incremented and perform the flush of entries related to that
device and reduce the reference count.   In side fib_sync_flush(This
function is same as fib_sync_down, except  that checking for protocol)
,  checking whether the route entry is installed by protocol,  and
marking them only as dead.


These are the changes . (2.6-18 linux kernel)

--- linux26/include/net/ip_fib.h 2008-01-04 04:41:45.326857000 -0800
+++ linux26/include/net/modified_ip_fib.h   2008-01-21 04:46:55.0 -0800
@@ -233,6 +233,9 @@ extern void ip_fib_init(void);

+extern int inet_rtm_flushroute(struct sk_buff *skb, struct nlmsghdr*
nlh, void *arg);

+extern int fib_sync_flush(u32 local, struct net_device *dev, int
force, int protocol);



--- linux26/include/linux/rtnetlink.h   2008-01-04 02:57:57.487754000 -0800
+++ linux26/include/linux/modified_rtnetlink.h  2008-01-21
04:46:56.0 -0800
@@ -35,7 +35,11 @@ enum {
 #define RTM_DELROUTE   RTM_DELROUTE
RTM_GETROUTE,
 #define RTM_GETROUTE   RTM_GETROUTE
-
+RTM_FLUSHROUTE,
+#define RTM_FLUSHROUTE RTM_FLUSHROUTE
+
RTM_NEWNEIGH= 28,
 #define RTM_NEWNEIGH   RTM_NEWNEIGH
RTM_DELNEIGH,
@@ -199,7 +203,9 @@ enum
~


--- linux26/net/ipv4/fib_frontend.c 2008-01-04 03:07:17.964607000 -0800
+++ linux26/net/ipv4/modified_fib_frontend.c2008-01-21
04:46:53.0 -0800
+/*
+ * Added For flushing all the routes when clear ip route is issued
from user space
+ */
+int inet_rtm_flushroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+{
+struct net_device *dev;
+struct in_device *in_dev;
+struct rtattr **rta = arg;
+struct rtmsg *r = NLMSG_DATA(nlh);
+
+if (inet_check_attr(r, rta))
+  return -EINVAL;
+
+for (dev = dev_base; dev; dev = dev->next) {
+in_dev = in_dev_get(dev);
+if (!in_dev)
+continue;
+if(fib_sync_flush(0, dev, 0, r->rtm_protocol)) {
+fib_flush();
+rt_cache_flush(0);
+}
+in_dev_put(in_dev);
+}
+
+return 0;
+}

This fib_sync_flush is same as fib_sync_down, except  for each entry
it compares the protocol type of the routing entry  to be  removed.

--- linux26/net/ipv4/fib_semantics.c2008-01-09 02:22:49.819492000 -0800
+++ linux26/net/ipv4/modified_fib_semantics.c1  2008-01-21
04:46:52.0 -0800
+/*
+ * FLUSH all  the routing table entries related to a
+ * device
+ */
+
+int fib_sync_flush(u32 local, struct net_device *dev, int force, int protocol)
+{
+int ret = 0;
+int scope = RT_SCOPE_NOWHERE;
+
+if (force)
+scope = -1;
+
+if (local && fib_info_laddrhash) {
+unsigned int hash = fib_laddr_hashfn(local);
+struct hlist_head *head = &fib_info_laddrhash[hash];
+struct hlist_node *node;
+struct fib_info *fi;
+hlist_for_each_entry(fi, node, head, fib_lhash) {
+if (fi->fib_prefsrc == local) {
+fi->fib_flags |= RTNH_F_DEAD;
+ret++;
+}
+}
+}
+
+if (dev) {
+struct fib_info *prev_fi = NULL;
+unsigned int hash = fib_devindex_hashfn(dev->ifindex);
+struct hlist_head *head = &fib_info_devhash[hash];
+struct hlist_node *node;
+struct fib_nh *nh;
+hlist_for_each_entry(nh, node, head, nh_hash) {
+struct fib_info *fi = nh->nh_parent;
+if(fi->fib_protocol == protocol) {
+int dead;
+BUG_ON(!fi->fib_nhs);
+if (nh->nh_dev != dev || fi == prev_fi)
+continue;
+prev_fi = fi;
+dead = 0;
+change_nexthops(fi) {
+if (nh->nh_flags&RTNH_F_DEAD)
+dead++;
+else if (nh->nh_dev == dev &&
+nh->nh_scope != scope) {
+nh->nh_flags |= RTNH_F_DEAD;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+spin_lock_bh(&fib_multipath_lock);
+fi->fib_power -= nh->nh_power;
+nh->nh_power = 0;
+spin_unlock_bh(&fib_multipath_lock);
+#endif
+dead++;
+}
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+if (force > 1 && nh->nh_dev == dev) {
+dead = fi->fib_nhs;
+break;
+}
+#endif
+} endfor_nexthops(fi)
+if (dead == fi->fib_nhs) {
+   fi->fib_flags 

[PATCH] changes required to flush all routing table entries in side kernel

2008-02-26 Thread dur...@it.iitb.ac.in phani
Problem :   Need to clean up routing table entries in side the Linux
 kernel. But  kernel is not providing  single command to clear all
 routing table entries at once.

 Modified the kernel to take of the changesDefined new  net link
 message under  NETLINK_ROUTE   family  RTM_FLUSHROUTE.   At the
 receiving end in side kernel,  removed all routing table entries
 related with each device.

  Changed the code so that only the corresponding device reference
 will be incremented and perform the flush of entries related to that
 device and reduce the reference count.   In side fib_sync_flush(This
 function is same as fib_sync_down, except  that checking for protocol)
 ,  checking whether the route entry is installed by protocol,  and
 marking them only as dead.


 These are the changes . (version  2.6.14.2 linux kernel)

 --- linux26/include/net/ip_fib.h 2008-01-04 04:41:45.326857000 -0800
 +++ linux26/include/net/modified_ip_fib.h   2008-01-21 04:46:55.0 -0800
 @@ -233,6 +233,9 @@ extern void ip_fib_init(void);

 +extern int inet_rtm_flushroute(struct sk_buff *skb, struct nlmsghdr*
 nlh, void *arg);

 +extern int fib_sync_flush(u32 local, struct net_device *dev, int
 force, int protocol);



 --- linux26/include/linux/rtnetlink.h   2008-01-04 02:57:57.487754000 -0800
 +++ linux26/include/linux/modified_rtnetlink.h  2008-01-21
 04:46:56.0 -0800
 @@ -35,7 +35,11 @@ enum {
  #define RTM_DELROUTE   RTM_DELROUTE
RTM_GETROUTE,
  #define RTM_GETROUTE   RTM_GETROUTE
 -
 +RTM_FLUSHROUTE,
 +#define RTM_FLUSHROUTE RTM_FLUSHROUTE
 +
RTM_NEWNEIGH= 28,
  #define RTM_NEWNEIGH   RTM_NEWNEIGH
RTM_DELNEIGH,
 @@ -199,7 +203,9 @@ enum
 ~


 --- linux26/net/ipv4/fib_frontend.c 2008-01-04 03:07:17.964607000 -0800
 +++ linux26/net/ipv4/modified_fib_frontend.c2008-01-21
 04:46:53.0 -0800
 +/*
 + * Added For flushing all the routes when clear ip route is issued
 from user space
 + */
 +int inet_rtm_flushroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 +{
 +struct net_device *dev;
 +struct in_device *in_dev;
 +struct rtattr **rta = arg;
 +struct rtmsg *r = NLMSG_DATA(nlh);
 +
 +if (inet_check_attr(r, rta))
 +  return -EINVAL;
 +
 +for (dev = dev_base; dev; dev = dev->next) {
 +in_dev = in_dev_get(dev);
 +if (!in_dev)
 +continue;
 +if(fib_sync_flush(0, dev, 0, r->rtm_protocol)) {
 +fib_flush();
 +rt_cache_flush(0);
 +}
 +in_dev_put(in_dev);
 +}
 +
 +return 0;
 +}

 This fib_sync_flush is same as fib_sync_down, except  for each entry
 it compares the protocol type of the routing entry  to be  removed.

 --- linux26/net/ipv4/fib_semantics.c2008-01-09 02:22:49.819492000 -0800
 +++ linux26/net/ipv4/modified_fib_semantics.c1  2008-01-21
 04:46:52.0 -0800
 +/*
 + * FLUSH all  the routing table entries related to a
 + * device
 + */
 +
 +int fib_sync_flush(u32 local, struct net_device *dev, int force, int protocol)
 +{
 +int ret = 0;
 +int scope = RT_SCOPE_NOWHERE;
 +
 +if (force)
 +scope = -1;
 +
 +if (local && fib_info_laddrhash) {
 +unsigned int hash = fib_laddr_hashfn(local);
 +struct hlist_head *head = &fib_info_laddrhash[hash];
 +struct hlist_node *node;
 +struct fib_info *fi;
 +hlist_for_each_entry(fi, node, head, fib_lhash) {
 +if (fi->fib_prefsrc == local) {
 +fi->fib_flags |= RTNH_F_DEAD;
 +ret++;
 +}
 +}
 +}
 +
 +if (dev) {
 +struct fib_info *prev_fi = NULL;
 +unsigned int hash = fib_devindex_hashfn(dev->ifindex);
 +struct hlist_head *head = &fib_info_devhash[hash];
 +struct hlist_node *node;
 +struct fib_nh *nh;
 +hlist_for_each_entry(nh, node, head, nh_hash) {
 +struct fib_info *fi = nh->nh_parent;
 +if(fi->fib_protocol == protocol) {
 +int dead;
 +BUG_ON(!fi->fib_nhs);
 +if (nh->nh_dev != dev || fi == prev_fi)
 +continue;
 +prev_fi = fi;
 +dead = 0;
 +change_nexthops(fi) {
 +if (nh->nh_flags&RTNH_F_DEAD)
 +dead++;
 +else if (nh->nh_dev == dev &&
 +nh->nh_scope != scope) {
 +nh->nh_flags |= RTNH_F_DEAD;
 +#ifdef CONFIG_IP_ROUTE_MULTIPATH
 +spin_lock_bh(&fib_multipath_lock);
 +fi->fib_power -= nh->nh_power;
 +nh->nh_power = 0;
 +spin_unlock_bh(&fib_multipath_lock);
 +#endif
 +dead++;
 +}
 +#ifdef CONFIG_IP_ROUTE_MULTIPATH
 +if (force > 1 && nh->nh_dev == dev) {
 +dead = fi->fib_nhs;
 +break;
 +