Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / ipv6 / ip6_fib.c
index 1816b81..2cb6149 100644 (file)
@@ -49,7 +49,7 @@
 
 struct rt6_statistics  rt6_stats;
 
-static kmem_cache_t * fib6_node_kmem;
+static kmem_cache_t * fib6_node_kmem __read_mostly;
 
 enum fib_walk_state_t
 {
@@ -69,7 +69,7 @@ struct fib6_cleaner_t
        void *arg;
 };
 
-rwlock_t fib6_walker_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(fib6_walker_lock);
 
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -92,7 +92,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
 
 static __u32 rt_sernum;
 
-static struct timer_list ip6_fib_timer = TIMER_INITIALIZER(fib6_run_gc, 0, 0);
+static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
 
 struct fib6_walker_t fib6_walker_list = {
        .prev   = &fib6_walker_list,
@@ -116,36 +116,6 @@ static __inline__ u32 fib6_new_sernum(void)
  *     64bit processors)
  */
 
-/*
- *     compare "prefix length" bits of an address
- */
-
-static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
-{
-       __u32 *a1 = token1;
-       __u32 *a2 = token2;
-       int pdw;
-       int pbi;
-
-       pdw = prefixlen >> 5;     /* num of whole __u32 in prefix */
-       pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
-
-       if (pdw)
-               if (memcmp(a1, a2, pdw << 2))
-                       return 0;
-
-       if (pbi) {
-               __u32 mask;
-
-               mask = htonl((0xffffffff) << (32 - pbi));
-
-               if ((a1[pdw] ^ a2[pdw]) & mask)
-                       return 0;
-       }
-
-       return 1;
-}
-
 /*
  *     test bit
  */
@@ -157,56 +127,6 @@ static __inline__ int addr_bit_set(void *token, int fn_bit)
        return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5];
 }
 
-/*
- *     find the first different bit between two addresses
- *     length of address must be a multiple of 32bits
- */
-
-static __inline__ int addr_diff(void *token1, void *token2, int addrlen)
-{
-       __u32 *a1 = token1;
-       __u32 *a2 = token2;
-       int i;
-
-       addrlen >>= 2;
-
-       for (i = 0; i < addrlen; i++) {
-               __u32 xb;
-
-               xb = a1[i] ^ a2[i];
-
-               if (xb) {
-                       int j = 31;
-
-                       xb = ntohl(xb);
-
-                       while ((xb & (1 << j)) == 0)
-                               j--;
-
-                       return (i * 32 + 31 - j);
-               }
-       }
-
-       /*
-        *      we should *never* get to this point since that 
-        *      would mean the addrs are equal
-        *
-        *      However, we do get to it 8) And exacly, when
-        *      addresses are equal 8)
-        *
-        *      ip route add 1111::/128 via ...
-        *      ip route add 1111::/64 via ...
-        *      and we are here.
-        *
-        *      Ideally, this function should stop comparison
-        *      at prefix length. It does not, but it is still OK,
-        *      if returned value is greater than prefix length.
-        *                                      --ANK (980803)
-        */
-
-       return addrlen<<5;
-}
-
 static __inline__ struct fib6_node * node_alloc(void)
 {
        struct fib6_node *fn;
@@ -261,7 +181,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
                 *      Prefix match
                 */
                if (plen < fn->fn_bit ||
-                   !addr_match(&key->addr, addr, fn->fn_bit))
+                   !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
                        goto insert_above;
                
                /*
@@ -326,11 +246,11 @@ insert_above:
 
        /* find 1st bit in difference between the 2 addrs.
 
-          See comment in addr_diff: bit may be an invalid value,
+          See comment in __ipv6_addr_diff: bit may be an invalid value,
           but if it is >= plen, the value is ignored in any case.
         */
        
-       bit = addr_diff(addr, &key->addr, addrlen);
+       bit = __ipv6_addr_diff(addr, &key->addr, addrlen);
 
        /* 
         *              (intermediate)[in]      
@@ -424,7 +344,7 @@ insert_above:
  */
 
 static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
-    struct nlmsghdr *nlh)
+               struct nlmsghdr *nlh,  struct netlink_skb_parms *req)
 {
        struct rt6_info *iter = NULL;
        struct rt6_info **ins;
@@ -433,7 +353,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 
        if (fn->fn_flags&RTN_TL_ROOT &&
            fn->leaf == &ip6_null_entry &&
-           !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF | RTF_ALLONLINK)) ){
+           !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
                fn->leaf = rt;
                rt->u.next = NULL;
                goto out;
@@ -451,8 +371,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 
                        if (iter->rt6i_dev == rt->rt6i_dev &&
                            iter->rt6i_idev == rt->rt6i_idev &&
-                           ipv6_addr_cmp(&iter->rt6i_gateway,
-                                          &rt->rt6i_gateway) == 0) {
+                           ipv6_addr_equal(&iter->rt6i_gateway,
+                                           &rt->rt6i_gateway)) {
                                if (!(iter->rt6i_flags&RTF_EXPIRES))
                                        return -EEXIST;
                                iter->rt6i_expires = rt->rt6i_expires;
@@ -479,7 +399,7 @@ out:
        *ins = rt;
        rt->rt6i_node = fn;
        atomic_inc(&rt->rt6i_ref);
-       inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
+       inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req);
        rt6_stats.fib_rt_entries++;
 
        if ((fn->fn_flags & RTN_RTINFO) == 0) {
@@ -509,7 +429,8 @@ void fib6_force_start_gc(void)
  *     with source addr info in sub-trees
  */
 
-int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int fib6_add(struct fib6_node *root, struct rt6_info *rt, 
+               struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
        struct fib6_node *fn;
        int err = -ENOMEM;
@@ -582,7 +503,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
        }
 #endif
 
-       err = fib6_add_rt2node(fn, rt, nlh);
+       err = fib6_add_rt2node(fn, rt, nlh, req);
 
        if (err == 0) {
                fib6_start_gc(rt);
@@ -667,7 +588,7 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
                        key = (struct rt6key *) ((u8 *) fn->leaf +
                                                 args->offset);
 
-                       if (addr_match(&key->addr, args->addr, key->plen))
+                       if (ipv6_prefix_equal(&key->addr, args->addr, key->plen))
                                return fn;
                }
 
@@ -718,7 +639,7 @@ static struct fib6_node * fib6_locate_1(struct fib6_node *root,
                 *      Prefix match
                 */
                if (plen < fn->fn_bit ||
-                   !addr_match(&key->addr, addr, fn->fn_bit))
+                   !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
                        return NULL;
 
                if (plen == fn->fn_bit)
@@ -889,7 +810,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
 }
 
 static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
-    struct nlmsghdr *nlh, void *_rtattr)
+    struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
        struct fib6_walker_t *w;
        struct rt6_info *rt = *rtp;
@@ -945,11 +866,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
                if (atomic_read(&rt->rt6i_ref) != 1) BUG();
        }
 
-       inet6_rt_notify(RTM_DELROUTE, rt, nlh);
+       inet6_rt_notify(RTM_DELROUTE, rt, nlh, req);
        rt6_release(rt);
 }
 
-int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
        struct fib6_node *fn = rt->rt6i_node;
        struct rt6_info **rtp;
@@ -974,7 +895,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
 
        for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
                if (*rtp == rt) {
-                       fib6_del_route(fn, rtp, nlh, _rtattr);
+                       fib6_del_route(fn, rtp, nlh, _rtattr, req);
                        return 0;
                }
        }
@@ -1103,7 +1024,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
                res = c->func(rt, c->arg);
                if (res < 0) {
                        w->leaf = rt;
-                       res = fib6_del(rt, NULL, NULL);
+                       res = fib6_del(rt, NULL, NULL, NULL);
                        if (res) {
 #if RT6_DEBUG >= 2
                                printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
@@ -1184,7 +1105,6 @@ static int fib6_age(struct rt6_info *rt, void *arg)
        if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
                if (time_after(now, rt->rt6i_expires)) {
                        RT6_TRACE("expiring %p\n", rt);
-                       rt6_reset_dflt_pointer(rt);
                        return -1;
                }
                gc_args.more++;
@@ -1205,13 +1125,13 @@ static int fib6_age(struct rt6_info *rt, void *arg)
        return 0;
 }
 
-static spinlock_t fib6_gc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(fib6_gc_lock);
 
 void fib6_run_gc(unsigned long dummy)
 {
        if (dummy != ~0UL) {
                spin_lock_bh(&fib6_gc_lock);
-               gc_args.timeout = (int)dummy;
+               gc_args.timeout = dummy ? (int)dummy : ip6_rt_gc_interval;
        } else {
                local_bh_disable();
                if (!spin_trylock(&fib6_gc_lock)) {
@@ -1248,7 +1168,7 @@ void __init fib6_init(void)
                panic("cannot create fib6_nodes cache");
 }
 
-void __exit fib6_gc_cleanup(void)
+void fib6_gc_cleanup(void)
 {
        del_timer(&ip6_fib_timer);
        kmem_cache_destroy(fib6_node_kmem);