can: j1939: j1939_sk_bind(): return failure if netdev is down
[linux-2.6-microblaze.git] / net / xfrm / xfrm_device.c
index 626096b..edf1189 100644 (file)
@@ -106,6 +106,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
        struct sk_buff *skb2, *nskb, *pskb = NULL;
        netdev_features_t esp_features = features;
        struct xfrm_offload *xo = xfrm_offload(skb);
+       struct net_device *dev = skb->dev;
        struct sec_path *sp;
 
        if (!xo || (xo->flags & XFRM_XMIT))
@@ -119,6 +120,10 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
        if (xo->flags & XFRM_GRO || x->xso.flags & XFRM_OFFLOAD_INBOUND)
                return skb;
 
+       /* This skb was already validated on the upper/virtual dev */
+       if ((x->xso.dev != dev) && (x->xso.real_dev == dev))
+               return skb;
+
        local_irq_save(flags);
        sd = this_cpu_ptr(&softnet_data);
        err = !skb_queue_empty(&sd->xfrm_backlog);
@@ -131,25 +136,20 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 
        xo->flags |= XFRM_XMIT;
 
-       if (skb_is_gso(skb)) {
-               struct net_device *dev = skb->dev;
-
-               if (unlikely(x->xso.dev != dev)) {
-                       struct sk_buff *segs;
+       if (skb_is_gso(skb) && unlikely(x->xso.dev != dev)) {
+               struct sk_buff *segs;
 
-                       /* Packet got rerouted, fixup features and segment it. */
-                       esp_features = esp_features & ~(NETIF_F_HW_ESP
-                                                       | NETIF_F_GSO_ESP);
+               /* Packet got rerouted, fixup features and segment it. */
+               esp_features = esp_features & ~(NETIF_F_HW_ESP | NETIF_F_GSO_ESP);
 
-                       segs = skb_gso_segment(skb, esp_features);
-                       if (IS_ERR(segs)) {
-                               kfree_skb(skb);
-                               atomic_long_inc(&dev->tx_dropped);
-                               return NULL;
-                       } else {
-                               consume_skb(skb);
-                               skb = segs;
-                       }
+               segs = skb_gso_segment(skb, esp_features);
+               if (IS_ERR(segs)) {
+                       kfree_skb(skb);
+                       atomic_long_inc(&dev->tx_dropped);
+                       return NULL;
+               } else {
+                       consume_skb(skb);
+                       skb = segs;
                }
        }
 
@@ -261,6 +261,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
        }
 
        xso->dev = dev;
+       xso->real_dev = dev;
        xso->num_exthdrs = 1;
        xso->flags = xuo->flags;