Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[safe/jmp/linux-2.6] / drivers / net / veth.c
index 3a15de5..5ec542d 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 
@@ -34,7 +35,7 @@ struct veth_net_stats {
 
 struct veth_priv {
        struct net_device *peer;
-       struct veth_net_stats *stats;
+       struct veth_net_stats __percpu *stats;
        unsigned ip_summed;
 };
 
@@ -186,7 +187,6 @@ tx_drop:
        return NETDEV_TX_OK;
 
 rx_drop:
-       kfree_skb(skb);
        rcv_stats->rx_dropped++;
        return NETDEV_TX_OK;
 }
@@ -263,7 +263,7 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu)
 
 static int veth_dev_init(struct net_device *dev)
 {
-       struct veth_net_stats *stats;
+       struct veth_net_stats __percpu *stats;
        struct veth_priv *priv;
 
        stats = alloc_percpu(struct veth_net_stats);
@@ -333,19 +333,17 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
        struct veth_priv *priv;
        char ifname[IFNAMSIZ];
        struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
+       struct ifinfomsg *ifmp;
        struct net *net;
 
        /*
         * create and register peer first
-        *
-        * struct ifinfomsg is at the head of VETH_INFO_PEER, but we
-        * skip it since no info from it is useful yet
         */
-
        if (data != NULL && data[VETH_INFO_PEER] != NULL) {
                struct nlattr *nla_peer;
 
                nla_peer = data[VETH_INFO_PEER];
+               ifmp = nla_data(nla_peer);
                err = nla_parse(peer_tb, IFLA_MAX,
                                nla_data(nla_peer) + sizeof(struct ifinfomsg),
                                nla_len(nla_peer) - sizeof(struct ifinfomsg),
@@ -358,8 +356,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
                        return err;
 
                tbp = peer_tb;
-       } else
+       } else {
+               ifmp = NULL;
                tbp = tb;
+       }
 
        if (tbp[IFLA_IFNAME])
                nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
@@ -387,6 +387,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 
        netif_carrier_off(peer);
 
+       err = rtnl_configure_link(peer, ifmp);
+       if (err < 0)
+               goto err_configure_peer;
+
        /*
         * register dev last
         *
@@ -428,6 +432,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 err_register_dev:
        /* nothing to do */
 err_alloc_name:
+err_configure_peer:
        unregister_netdevice(peer);
        return err;