net: reduce structures when XFRM=n
[safe/jmp/linux-2.6] / net / ipv6 / ip6_output.c
index 0e844c2..7d92fd9 100644 (file)
@@ -103,7 +103,8 @@ static int ip6_output_finish(struct sk_buff *skb)
        else if (dst->neighbour)
                return dst->neighbour->output(skb);
 
-       IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
+       IP6_INC_STATS_BH(dev_net(dst->dev),
+                        ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
        kfree_skb(skb);
        return -EINVAL;
 
@@ -150,13 +151,14 @@ static int ip6_output2(struct sk_buff *skb)
                                        ip6_dev_loopback_xmit);
 
                        if (ipv6_hdr(skb)->hop_limit == 0) {
-                               IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
+                               IP6_INC_STATS(dev_net(dev), idev,
+                                             IPSTATS_MIB_OUTDISCARDS);
                                kfree_skb(skb);
                                return 0;
                        }
                }
 
-               IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
+               IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
        }
 
        return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
@@ -175,7 +177,8 @@ int ip6_output(struct sk_buff *skb)
 {
        struct inet6_dev *idev = ip6_dst_idev(skb->dst);
        if (unlikely(idev->cnf.disable_ipv6)) {
-               IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
+               IP6_INC_STATS(dev_net(skb->dst->dev), idev,
+                             IPSTATS_MIB_OUTDISCARDS);
                kfree_skb(skb);
                return 0;
        }
@@ -194,6 +197,7 @@ int ip6_output(struct sk_buff *skb)
 int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
             struct ipv6_txoptions *opt, int ipfragok)
 {
+       struct net *net = sock_net(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct in6_addr *first_hop = &fl->fl6_dst;
        struct dst_entry *dst = skb->dst;
@@ -216,7 +220,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
                if (skb_headroom(skb) < head_room) {
                        struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
                        if (skb2 == NULL) {
-                               IP6_INC_STATS(ip6_dst_idev(skb->dst),
+                               IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
                                              IPSTATS_MIB_OUTDISCARDS);
                                kfree_skb(skb);
                                return -ENOBUFS;
@@ -270,7 +274,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 
        mtu = dst_mtu(dst);
        if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
-               IP6_INC_STATS(ip6_dst_idev(skb->dst),
+               IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
                              IPSTATS_MIB_OUTREQUESTS);
                return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
                                dst_output);
@@ -280,7 +284,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
                printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
        skb->dev = dst->dev;
        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
-       IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
+       IP6_INC_STATS(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
        kfree_skb(skb);
        return -EMSGSIZE;
 }
@@ -422,7 +426,7 @@ int ip6_forward(struct sk_buff *skb)
                goto drop;
 
        if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
-               IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
+               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
                goto drop;
        }
 
@@ -455,7 +459,8 @@ int ip6_forward(struct sk_buff *skb)
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
                            0, skb->dev);
-               IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(net,
+                                ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
 
                kfree_skb(skb);
                return -ETIMEDOUT;
@@ -468,13 +473,14 @@ int ip6_forward(struct sk_buff *skb)
                if (proxied > 0)
                        return ip6_input(skb);
                else if (proxied < 0) {
-                       IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
+                       IP6_INC_STATS(net, ip6_dst_idev(dst),
+                                     IPSTATS_MIB_INDISCARDS);
                        goto drop;
                }
        }
 
        if (!xfrm6_route_forward(skb)) {
-               IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
+               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
                goto drop;
        }
        dst = skb->dst;
@@ -484,7 +490,7 @@ int ip6_forward(struct sk_buff *skb)
           We don't send redirects to frames decapsulated from IPsec.
         */
        if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
-           !skb->sp) {
+           !skb_sec_path(skb)) {
                struct in6_addr *target = NULL;
                struct rt6_info *rt;
                struct neighbour *n = dst->neighbour;
@@ -523,14 +529,16 @@ int ip6_forward(struct sk_buff *skb)
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev);
-               IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS);
-               IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS);
+               IP6_INC_STATS_BH(net,
+                                ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS);
+               IP6_INC_STATS_BH(net,
+                                ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS);
                kfree_skb(skb);
                return -EMSGSIZE;
        }
 
        if (skb_cow(skb, dst->dev->hard_header_len)) {
-               IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
+               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
                goto drop;
        }
 
@@ -540,12 +548,12 @@ int ip6_forward(struct sk_buff *skb)
 
        hdr->hop_limit--;
 
-       IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
+       IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
        return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev,
                       ip6_forward_finish);
 
 error:
-       IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
+       IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
 drop:
        kfree_skb(skb);
        return -EINVAL;
@@ -613,7 +621,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 
 static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
-       struct net_device *dev;
        struct sk_buff *frag;
        struct rt6_info *rt = (struct rt6_info*)skb->dst;
        struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
@@ -623,8 +630,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
        __be32 frag_id = 0;
        int ptr, offset = 0, err=0;
        u8 *prevhdr, nexthdr = 0;
+       struct net *net = dev_net(skb->dst->dev);
 
-       dev = rt->u.dst.dev;
        hlen = ip6_find_1stfragopt(skb, &prevhdr);
        nexthdr = *prevhdr;
 
@@ -637,7 +644,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
        if (!skb->local_df) {
                skb->dev = skb->dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
-               IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
+               IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
+                             IPSTATS_MIB_FRAGFAILS);
                kfree_skb(skb);
                return -EMSGSIZE;
        }
@@ -686,7 +694,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                *prevhdr = NEXTHDR_FRAGMENT;
                tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC);
                if (!tmp_hdr) {
-                       IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
+                       IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
+                                     IPSTATS_MIB_FRAGFAILS);
                        return -ENOMEM;
                }
 
@@ -737,7 +746,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
                        err = output(skb);
                        if(!err)
-                               IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES);
+                               IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
+                                             IPSTATS_MIB_FRAGCREATES);
 
                        if (err || !frag)
                                break;
@@ -750,7 +760,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                kfree(tmp_hdr);
 
                if (err == 0) {
-                       IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS);
+                       IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
+                                     IPSTATS_MIB_FRAGOKS);
                        dst_release(&rt->u.dst);
                        return 0;
                }
@@ -761,7 +772,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                        frag = skb;
                }
 
-               IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS);
+               IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
+                             IPSTATS_MIB_FRAGFAILS);
                dst_release(&rt->u.dst);
                return err;
        }
@@ -795,7 +807,7 @@ slow_path:
 
                if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
                        NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
-                       IP6_INC_STATS(ip6_dst_idev(skb->dst),
+                       IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
                                      IPSTATS_MIB_FRAGFAILS);
                        err = -ENOMEM;
                        goto fail;
@@ -859,15 +871,16 @@ slow_path:
                if (err)
                        goto fail;
 
-               IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES);
+               IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
+                             IPSTATS_MIB_FRAGCREATES);
        }
-       IP6_INC_STATS(ip6_dst_idev(skb->dst),
+       IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
                      IPSTATS_MIB_FRAGOKS);
        kfree_skb(skb);
        return err;
 
 fail:
-       IP6_INC_STATS(ip6_dst_idev(skb->dst),
+       IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
                      IPSTATS_MIB_FRAGFAILS);
        kfree_skb(skb);
        return err;
@@ -943,46 +956,46 @@ static int ip6_dst_lookup_tail(struct sock *sk,
        }
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
-               /*
-                * Here if the dst entry we've looked up
-                * has a neighbour entry that is in the INCOMPLETE
-                * state and the src address from the flow is
-                * marked as OPTIMISTIC, we release the found
-                * dst entry and replace it instead with the
-                * dst entry of the nexthop router
-                */
-               if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
-                       struct inet6_ifaddr *ifp;
-                       struct flowi fl_gw;
-                       int redirect;
-
-                       ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
-                                             (*dst)->dev, 1);
-
-                       redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
-                       if (ifp)
-                               in6_ifa_put(ifp);
-
-                       if (redirect) {
-                               /*
-                                * We need to get the dst entry for the
-                                * default router instead
-                                */
-                               dst_release(*dst);
-                               memcpy(&fl_gw, fl, sizeof(struct flowi));
-                               memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
-                               *dst = ip6_route_output(net, sk, &fl_gw);
-                               if ((err = (*dst)->error))
-                                       goto out_err_release;
-                       }
+       /*
+        * Here if the dst entry we've looked up
+        * has a neighbour entry that is in the INCOMPLETE
+        * state and the src address from the flow is
+        * marked as OPTIMISTIC, we release the found
+        * dst entry and replace it instead with the
+        * dst entry of the nexthop router
+        */
+       if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
+               struct inet6_ifaddr *ifp;
+               struct flowi fl_gw;
+               int redirect;
+
+               ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+                                     (*dst)->dev, 1);
+
+               redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
+               if (ifp)
+                       in6_ifa_put(ifp);
+
+               if (redirect) {
+                       /*
+                        * We need to get the dst entry for the
+                        * default router instead
+                        */
+                       dst_release(*dst);
+                       memcpy(&fl_gw, fl, sizeof(struct flowi));
+                       memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
+                       *dst = ip6_route_output(net, sk, &fl_gw);
+                       if ((err = (*dst)->error))
+                               goto out_err_release;
                }
+       }
 #endif
 
        return 0;
 
 out_err_release:
        if (err == -ENETUNREACH)
-               IP6_INC_STATS_BH(NULL, IPSTATS_MIB_OUTNOROUTES);
+               IP6_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
        dst_release(*dst);
        *dst = NULL;
        return err;
@@ -1387,7 +1400,7 @@ alloc_new_skb:
        return 0;
 error:
        inet->cork.length -= length;
-       IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
+       IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
        return err;
 }
 
@@ -1411,6 +1424,7 @@ int ip6_push_pending_frames(struct sock *sk)
        struct in6_addr final_dst_buf, *final_dst = &final_dst_buf;
        struct inet_sock *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
+       struct net *net = sock_net(sk);
        struct ipv6hdr *hdr;
        struct ipv6_txoptions *opt = np->cork.opt;
        struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
@@ -1464,12 +1478,12 @@ int ip6_push_pending_frames(struct sock *sk)
        skb->mark = sk->sk_mark;
 
        skb->dst = dst_clone(&rt->u.dst);
-       IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+       IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
        if (proto == IPPROTO_ICMPV6) {
                struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
-               ICMP6MSGOUT_INC_STATS_BH(idev, icmp6_hdr(skb)->icmp6_type);
-               ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
+               ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type);
+               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
        }
 
        err = ip6_local_out(skb);
@@ -1493,7 +1507,7 @@ void ip6_flush_pending_frames(struct sock *sk)
 
        while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
                if (skb->dst)
-                       IP6_INC_STATS(ip6_dst_idev(skb->dst),
+                       IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb->dst),
                                      IPSTATS_MIB_OUTDISCARDS);
                kfree_skb(skb);
        }