]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - net/ipv6/ip6_output.c
net: Do delayed neigh confirmation.
[mirror_ubuntu-zesty-kernel.git] / net / ipv6 / ip6_output.c
index 17b8c67998bb80dc5e7052af210c7b64aa1471ee..c94e4aabe11bcf82d5235385105d9f4e6a213a95 100644 (file)
@@ -83,19 +83,6 @@ int ip6_local_out(struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(ip6_local_out);
 
-/* dev_loopback_xmit for use with netfilter. */
-static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
-{
-       skb_reset_mac_header(newskb);
-       __skb_pull(newskb, skb_network_offset(newskb));
-       newskb->pkt_type = PACKET_LOOPBACK;
-       newskb->ip_summed = CHECKSUM_UNNECESSARY;
-       WARN_ON(!skb_dst(newskb));
-
-       netif_rx_ni(newskb);
-       return 0;
-}
-
 static int ip6_finish_output2(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
@@ -121,7 +108,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
                        if (newskb)
                                NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING,
                                        newskb, NULL, newskb->dev,
-                                       ip6_dev_loopback_xmit);
+                                       dev_loopback_xmit);
 
                        if (ipv6_hdr(skb)->hop_limit == 0) {
                                IP6_INC_STATS(dev_net(dev), idev,
@@ -138,7 +125,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
        rcu_read_lock();
        neigh = dst_get_neighbour_noref(dst);
        if (neigh) {
-               int res = neigh_output(neigh, skb);
+               int res = dst_neigh_output(dst, neigh, skb);
 
                rcu_read_unlock();
                return res;
@@ -463,6 +450,7 @@ int ip6_forward(struct sk_buff *skb)
         */
        if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) {
                struct in6_addr *target = NULL;
+               struct inet_peer *peer;
                struct rt6_info *rt;
 
                /*
@@ -476,13 +464,12 @@ int ip6_forward(struct sk_buff *skb)
                else
                        target = &hdr->daddr;
 
-               if (!rt->rt6i_peer)
-                       rt6_bind_peer(rt, 1);
+               peer = rt6_get_peer_create(rt);
 
                /* Limit redirects both by destination (here)
                   and by source (inside ndisc_send_redirect)
                 */
-               if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
+               if (inet_peer_xrlim_allow(peer, 1*HZ))
                        ndisc_send_redirect(skb, target);
        } else {
                int addrtype = ipv6_addr_type(&hdr->saddr);
@@ -526,6 +513,7 @@ int ip6_forward(struct sk_buff *skb)
        hdr->hop_limit--;
 
        IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
+       IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len);
        return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev,
                       ip6_forward_finish);
 
@@ -602,11 +590,8 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
        int old, new;
 
        if (rt && !(rt->dst.flags & DST_NOPEER)) {
-               struct inet_peer *peer;
+               struct inet_peer *peer = rt6_get_peer_create(rt);
 
-               if (!rt->rt6i_peer)
-                       rt6_bind_peer(rt, 1);
-               peer = rt->rt6i_peer;
                if (peer) {
                        fhdr->identification = htonl(inet_getid(peer, 0));
                        return;