These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / xfrm / xfrm_output.c
index fbcedbe..ff4a91f 100644 (file)
@@ -19,7 +19,7 @@
 #include <net/dst.h>
 #include <net/xfrm.h>
 
-static int xfrm_output2(struct sock *sk, struct sk_buff *skb);
+static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb);
 
 static int xfrm_skb_check_space(struct sk_buff *skb)
 {
@@ -38,6 +38,18 @@ static int xfrm_skb_check_space(struct sk_buff *skb)
        return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC);
 }
 
+/* Children define the path of the packet through the
+ * Linux networking.  Thus, destinations are stackable.
+ */
+
+static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
+{
+       struct dst_entry *child = dst_clone(skb_dst(skb)->child);
+
+       skb_dst_drop(skb);
+       return child;
+}
+
 static int xfrm_output_one(struct sk_buff *skb, int err)
 {
        struct dst_entry *dst = skb_dst(skb);
@@ -119,18 +131,20 @@ out:
 
 int xfrm_output_resume(struct sk_buff *skb, int err)
 {
+       struct net *net = xs_net(skb_dst(skb)->xfrm);
+
        while (likely((err = xfrm_output_one(skb, err)) == 0)) {
                nf_reset(skb);
 
-               err = skb_dst(skb)->ops->local_out(skb);
+               err = skb_dst(skb)->ops->local_out(net, skb->sk, skb);
                if (unlikely(err != 1))
                        goto out;
 
                if (!skb_dst(skb)->xfrm)
-                       return dst_output(skb);
+                       return dst_output(net, skb->sk, skb);
 
                err = nf_hook(skb_dst(skb)->ops->family,
-                             NF_INET_POST_ROUTING, skb->sk, skb,
+                             NF_INET_POST_ROUTING, net, skb->sk, skb,
                              NULL, skb_dst(skb)->dev, xfrm_output2);
                if (unlikely(err != 1))
                        goto out;
@@ -144,15 +158,17 @@ out:
 }
 EXPORT_SYMBOL_GPL(xfrm_output_resume);
 
-static int xfrm_output2(struct sock *sk, struct sk_buff *skb)
+static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
        return xfrm_output_resume(skb, 1);
 }
 
-static int xfrm_output_gso(struct sock *sk, struct sk_buff *skb)
+static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
        struct sk_buff *segs;
 
+       BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET);
+       BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_SGO_CB_OFFSET);
        segs = skb_gso_segment(skb, 0);
        kfree_skb(skb);
        if (IS_ERR(segs))
@@ -165,7 +181,7 @@ static int xfrm_output_gso(struct sock *sk, struct sk_buff *skb)
                int err;
 
                segs->next = NULL;
-               err = xfrm_output2(sk, segs);
+               err = xfrm_output2(net, sk, segs);
 
                if (unlikely(err)) {
                        kfree_skb_list(nskb);
@@ -184,7 +200,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
        int err;
 
        if (skb_is_gso(skb))
-               return xfrm_output_gso(sk, skb);
+               return xfrm_output_gso(net, sk, skb);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                err = skb_checksum_help(skb);
@@ -195,7 +211,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       return xfrm_output2(sk, skb);
+       return xfrm_output2(net, sk, skb);
 }
 EXPORT_SYMBOL_GPL(xfrm_output);