]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/route.c
net: use the macros defined for the members of flowi
[net-next-2.6.git] / net / ipv6 / route.c
index a275c6e1e25c23884d7d1859e46a2ee82c00acef..c346ccf66ae108cf5d36ef39f7f25c922ebc3388 100644 (file)
@@ -109,7 +109,6 @@ static struct dst_ops ip6_dst_ops_template = {
        .link_failure           =       ip6_link_failure,
        .update_pmtu            =       ip6_rt_update_pmtu,
        .local_out              =       __ip6_local_out,
-       .entries                =       ATOMIC_INIT(0),
 };
 
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -122,7 +121,6 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .destroy                =       ip6_dst_destroy,
        .check                  =       ip6_dst_check,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
-       .entries                =       ATOMIC_INIT(0),
 };
 
 static struct rt6_info ip6_null_entry_template = {
@@ -217,14 +215,14 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 
 static __inline__ int rt6_check_expired(const struct rt6_info *rt)
 {
-       return (rt->rt6i_flags & RTF_EXPIRES &&
-               time_after(jiffies, rt->rt6i_expires));
+       return (rt->rt6i_flags & RTF_EXPIRES) &&
+               time_after(jiffies, rt->rt6i_expires);
 }
 
 static inline int rt6_need_strict(struct in6_addr *daddr)
 {
-       return (ipv6_addr_type(daddr) &
-               (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK));
+       return ipv6_addr_type(daddr) &
+               (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
 }
 
 /*
@@ -440,7 +438,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
                  __func__, match);
 
        net = dev_net(rt0->rt6i_dev);
-       return (match ? match : net->ipv6.ip6_null_entry);
+       return match ? match : net->ipv6.ip6_null_entry;
 }
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
@@ -560,11 +558,7 @@ struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
 {
        struct flowi fl = {
                .oif = oif,
-               .nl_u = {
-                       .ip6_u = {
-                               .daddr = *daddr,
-                       },
-               },
+               .fl6_dst = *daddr,
        };
        struct dst_entry *dst;
        int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
@@ -780,13 +774,9 @@ void ip6_route_input(struct sk_buff *skb)
        int flags = RT6_LOOKUP_F_HAS_SADDR;
        struct flowi fl = {
                .iif = skb->dev->ifindex,
-               .nl_u = {
-                       .ip6_u = {
-                               .daddr = iph->daddr,
-                               .saddr = iph->saddr,
-                               .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
-                       },
-               },
+               .fl6_dst = iph->daddr,
+               .fl6_src = iph->saddr,
+               .fl6_flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
                .mark = skb->mark,
                .proto = iph->nexthdr,
        };
@@ -859,7 +849,7 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
 
        dst_release(*dstp);
        *dstp = new;
-       return (new ? 0 : -ENOMEM);
+       return new ? 0 : -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
 
@@ -1058,19 +1048,22 @@ static int ip6_dst_gc(struct dst_ops *ops)
        int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
        int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
        unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
+       int entries;
 
+       entries = dst_entries_get_fast(ops);
        if (time_after(rt_last_gc + rt_min_interval, now) &&
-           atomic_read(&ops->entries) <= rt_max_size)
+           entries <= rt_max_size)
                goto out;
 
        net->ipv6.ip6_rt_gc_expire++;
        fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
        net->ipv6.ip6_rt_last_gc = now;
-       if (atomic_read(&ops->entries) < ops->gc_thresh)
+       entries = dst_entries_get_slow(ops);
+       if (entries < ops->gc_thresh)
                net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
 out:
        net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
-       return (atomic_read(&ops->entries) > rt_max_size);
+       return entries > rt_max_size;
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,
@@ -1169,6 +1162,8 @@ int ip6_route_add(struct fib6_config *cfg)
 
        if (addr_type & IPV6_ADDR_MULTICAST)
                rt->dst.input = ip6_mc_input;
+       else if (cfg->fc_flags & RTF_LOCAL)
+               rt->dst.input = ip6_input;
        else
                rt->dst.input = ip6_forward;
 
@@ -1190,7 +1185,8 @@ int ip6_route_add(struct fib6_config *cfg)
           they would result in kernel looping; promote them to reject routes
         */
        if ((cfg->fc_flags & RTF_REJECT) ||
-           (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
+           (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK)
+                                             && !(cfg->fc_flags&RTF_LOCAL))) {
                /* hold loopback dev/idev if we haven't done so. */
                if (dev != net->loopback_dev) {
                        if (dev) {
@@ -1459,12 +1455,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
        struct ip6rd_flowi rdfl = {
                .fl = {
                        .oif = dev->ifindex,
-                       .nl_u = {
-                               .ip6_u = {
-                                       .daddr = *dest,
-                                       .saddr = *src,
-                               },
-                       },
+                       .fl6_dst = *dest,
+                       .fl6_src = *src,
                },
        };
 
@@ -1941,8 +1933,12 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
        struct neighbour *neigh;
 
-       if (rt == NULL)
+       if (rt == NULL) {
+               if (net_ratelimit())
+                       pr_warning("IPv6:  Maximum number of routes reached,"
+                                  " consider increasing route/max_size.\n");
                return ERR_PTR(-ENOMEM);
+       }
 
        dev_hold(net->loopback_dev);
        in6_dev_hold(idev);
@@ -2102,6 +2098,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (rtm->rtm_type == RTN_UNREACHABLE)
                cfg->fc_flags |= RTF_REJECT;
 
+       if (rtm->rtm_type == RTN_LOCAL)
+               cfg->fc_flags |= RTF_LOCAL;
+
        cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
        cfg->fc_nlinfo.nlh = nlh;
        cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
@@ -2222,6 +2221,8 @@ static int rt6_fill_node(struct net *net,
        NLA_PUT_U32(skb, RTA_TABLE, table);
        if (rt->rt6i_flags&RTF_REJECT)
                rtm->rtm_type = RTN_UNREACHABLE;
+       else if (rt->rt6i_flags&RTF_LOCAL)
+               rtm->rtm_type = RTN_LOCAL;
        else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
                rtm->rtm_type = RTN_LOCAL;
        else
@@ -2516,7 +2517,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v)
                   net->ipv6.rt6_stats->fib_rt_alloc,
                   net->ipv6.rt6_stats->fib_rt_entries,
                   net->ipv6.rt6_stats->fib_rt_cache,
-                  atomic_read(&net->ipv6.ip6_dst_ops.entries),
+                  dst_entries_get_slow(&net->ipv6.ip6_dst_ops),
                   net->ipv6.rt6_stats->fib_discarded_routes);
 
        return 0;
@@ -2658,11 +2659,14 @@ static int __net_init ip6_route_net_init(struct net *net)
        memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template,
               sizeof(net->ipv6.ip6_dst_ops));
 
+       if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
+               goto out_ip6_dst_ops;
+
        net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
                                           sizeof(*net->ipv6.ip6_null_entry),
                                           GFP_KERNEL);
        if (!net->ipv6.ip6_null_entry)
-               goto out_ip6_dst_ops;
+               goto out_ip6_dst_entries;
        net->ipv6.ip6_null_entry->dst.path =
                (struct dst_entry *)net->ipv6.ip6_null_entry;
        net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
@@ -2712,6 +2716,8 @@ out_ip6_prohibit_entry:
 out_ip6_null_entry:
        kfree(net->ipv6.ip6_null_entry);
 #endif
+out_ip6_dst_entries:
+       dst_entries_destroy(&net->ipv6.ip6_dst_ops);
 out_ip6_dst_ops:
        goto out;
 }
@@ -2727,6 +2733,7 @@ static void __net_exit ip6_route_net_exit(struct net *net)
        kfree(net->ipv6.ip6_prohibit_entry);
        kfree(net->ipv6.ip6_blk_hole_entry);
 #endif
+       dst_entries_destroy(&net->ipv6.ip6_dst_ops);
 }
 
 static struct pernet_operations ip6_route_net_ops = {
@@ -2750,10 +2757,14 @@ int __init ip6_route_init(void)
        if (!ip6_dst_ops_template.kmem_cachep)
                goto out;
 
-       ret = register_pernet_subsys(&ip6_route_net_ops);
+       ret = dst_entries_init(&ip6_dst_blackhole_ops);
        if (ret)
                goto out_kmem_cache;
 
+       ret = register_pernet_subsys(&ip6_route_net_ops);
+       if (ret)
+               goto out_dst_entries;
+
        ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
 
        /* Registering of the loopback is done before this portion of code,
@@ -2800,6 +2811,8 @@ out_fib6_init:
        fib6_gc_cleanup();
 out_register_subsys:
        unregister_pernet_subsys(&ip6_route_net_ops);
+out_dst_entries:
+       dst_entries_destroy(&ip6_dst_blackhole_ops);
 out_kmem_cache:
        kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
        goto out;
@@ -2812,5 +2825,6 @@ void ip6_route_cleanup(void)
        xfrm6_fini();
        fib6_gc_cleanup();
        unregister_pernet_subsys(&ip6_route_net_ops);
+       dst_entries_destroy(&ip6_dst_blackhole_ops);
        kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
 }