Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / core / dev.c
index c14748d051e7f58343768e920e52317154ef06fb..13f49f81ae13a3e3f07b3304b8f04bcb791d84b3 100644 (file)
@@ -2942,9 +2942,11 @@ EXPORT_SYMBOL(xmit_recursion);
 
 /**
  *     dev_loopback_xmit - loop back @skb
+ *     @net: network namespace this loopback is happening in
+ *     @sk:  sk needed to be a netfilter okfn
  *     @skb: buffer to transmit
  */
-int dev_loopback_xmit(struct sock *sk, struct sk_buff *skb)
+int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
        skb_reset_mac_header(skb);
        __skb_pull(skb, skb_network_offset(skb));
@@ -2999,6 +3001,7 @@ static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
                        new_index = skb_tx_hash(dev, skb);
 
                if (queue_index != new_index && sk &&
+                   sk_fullsock(sk) &&
                    rcu_access_pointer(sk->sk_dst_cache))
                        sk_tx_queue_set(sk, new_index);
 
@@ -3170,11 +3173,11 @@ out:
        return rc;
 }
 
-int dev_queue_xmit_sk(struct sock *sk, struct sk_buff *skb)
+int dev_queue_xmit(struct sk_buff *skb)
 {
        return __dev_queue_xmit(skb, NULL);
 }
-EXPORT_SYMBOL(dev_queue_xmit_sk);
+EXPORT_SYMBOL(dev_queue_xmit);
 
 int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
 {
@@ -3695,6 +3698,14 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb,
        case TC_ACT_QUEUED:
                kfree_skb(skb);
                return NULL;
+       case TC_ACT_REDIRECT:
+               /* skb_mac_header check was done by cls/act_bpf, so
+                * we can safely push the L2 header back before
+                * redirecting to another netdev
+                */
+               __skb_push(skb, skb->mac_len);
+               skb_do_redirect(skb);
+               return NULL;
        default:
                break;
        }
@@ -4009,13 +4020,13 @@ static int netif_receive_skb_internal(struct sk_buff *skb)
  *     NET_RX_SUCCESS: no congestion
  *     NET_RX_DROP: packet was dropped
  */
-int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb)
+int netif_receive_skb(struct sk_buff *skb)
 {
        trace_netif_receive_skb_entry(skb);
 
        return netif_receive_skb_internal(skb);
 }
-EXPORT_SYMBOL(netif_receive_skb_sk);
+EXPORT_SYMBOL(netif_receive_skb);
 
 /* Network device is going away, flush any packets still pending
  * Called with irqs disabled.
@@ -4884,8 +4895,7 @@ struct netdev_adjacent {
        struct rcu_head rcu;
 };
 
-static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
-                                                struct net_device *adj_dev,
+static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev,
                                                 struct list_head *adj_list)
 {
        struct netdev_adjacent *adj;
@@ -4911,7 +4921,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
 {
        ASSERT_RTNL();
 
-       return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper);
+       return __netdev_find_adj(upper_dev, &dev->all_adj_list.upper);
 }
 EXPORT_SYMBOL(netdev_has_upper_dev);
 
@@ -5173,7 +5183,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
        struct netdev_adjacent *adj;
        int ret;
 
-       adj = __netdev_find_adj(dev, adj_dev, dev_list);
+       adj = __netdev_find_adj(adj_dev, dev_list);
 
        if (adj) {
                adj->ref_nr++;
@@ -5229,7 +5239,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
 {
        struct netdev_adjacent *adj;
 
-       adj = __netdev_find_adj(dev, adj_dev, dev_list);
+       adj = __netdev_find_adj(adj_dev, dev_list);
 
        if (!adj) {
                pr_err("tried to remove device %s from %s\n",
@@ -5350,10 +5360,10 @@ static int __netdev_upper_dev_link(struct net_device *dev,
                return -EBUSY;
 
        /* To prevent loops, check if dev is not upper device to upper_dev. */
-       if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper))
+       if (__netdev_find_adj(dev, &upper_dev->all_adj_list.upper))
                return -EBUSY;
 
-       if (__netdev_find_adj(dev, upper_dev, &dev->adj_list.upper))
+       if (__netdev_find_adj(upper_dev, &dev->adj_list.upper))
                return -EEXIST;
 
        if (master && netdev_master_upper_dev_get(dev))
@@ -5363,6 +5373,12 @@ static int __netdev_upper_dev_link(struct net_device *dev,
        changeupper_info.master = master;
        changeupper_info.linking = true;
 
+       ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+                                           &changeupper_info.info);
+       ret = notifier_to_errno(ret);
+       if (ret)
+               return ret;
+
        ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private,
                                                   master);
        if (ret)
@@ -5505,6 +5521,9 @@ void netdev_upper_dev_unlink(struct net_device *dev,
        changeupper_info.master = netdev_master_upper_dev_get(dev) == upper_dev;
        changeupper_info.linking = false;
 
+       call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+                                     &changeupper_info.info);
+
        __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
 
        /* Here is the tricky part. We must remove all dev's lower
@@ -5631,7 +5650,7 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
 
        if (!lower_dev)
                return NULL;
-       lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower);
+       lower = __netdev_find_adj(lower_dev, &dev->adj_list.lower);
        if (!lower)
                return NULL;