aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/veth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/veth.c')
-rw-r--r--drivers/net/veth.c66
1 files changed, 34 insertions, 32 deletions
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 52af5017c46b..5ec542dd5b50 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/netdevice.h> 11#include <linux/netdevice.h>
12#include <linux/slab.h>
12#include <linux/ethtool.h> 13#include <linux/ethtool.h>
13#include <linux/etherdevice.h> 14#include <linux/etherdevice.h>
14 15
@@ -34,7 +35,7 @@ struct veth_net_stats {
34 35
35struct veth_priv { 36struct veth_priv {
36 struct net_device *peer; 37 struct net_device *peer;
37 struct veth_net_stats *stats; 38 struct veth_net_stats __percpu *stats;
38 unsigned ip_summed; 39 unsigned ip_summed;
39}; 40};
40 41
@@ -153,35 +154,24 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
153 struct net_device *rcv = NULL; 154 struct net_device *rcv = NULL;
154 struct veth_priv *priv, *rcv_priv; 155 struct veth_priv *priv, *rcv_priv;
155 struct veth_net_stats *stats, *rcv_stats; 156 struct veth_net_stats *stats, *rcv_stats;
156 int length, cpu; 157 int length;
157
158 skb_orphan(skb);
159 158
160 priv = netdev_priv(dev); 159 priv = netdev_priv(dev);
161 rcv = priv->peer; 160 rcv = priv->peer;
162 rcv_priv = netdev_priv(rcv); 161 rcv_priv = netdev_priv(rcv);
163 162
164 cpu = smp_processor_id(); 163 stats = this_cpu_ptr(priv->stats);
165 stats = per_cpu_ptr(priv->stats, cpu); 164 rcv_stats = this_cpu_ptr(rcv_priv->stats);
166 rcv_stats = per_cpu_ptr(rcv_priv->stats, cpu);
167 165
168 if (!(rcv->flags & IFF_UP)) 166 if (!(rcv->flags & IFF_UP))
169 goto tx_drop; 167 goto tx_drop;
170 168
171 if (skb->len > (rcv->mtu + MTU_PAD))
172 goto rx_drop;
173
174 skb->tstamp.tv64 = 0;
175 skb->pkt_type = PACKET_HOST;
176 skb->protocol = eth_type_trans(skb, rcv);
177 if (dev->features & NETIF_F_NO_CSUM) 169 if (dev->features & NETIF_F_NO_CSUM)
178 skb->ip_summed = rcv_priv->ip_summed; 170 skb->ip_summed = rcv_priv->ip_summed;
179 171
180 skb->mark = 0; 172 length = skb->len + ETH_HLEN;
181 secpath_reset(skb); 173 if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
182 nf_reset(skb); 174 goto rx_drop;
183
184 length = skb->len;
185 175
186 stats->tx_bytes += length; 176 stats->tx_bytes += length;
187 stats->tx_packets++; 177 stats->tx_packets++;
@@ -189,7 +179,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
189 rcv_stats->rx_bytes += length; 179 rcv_stats->rx_bytes += length;
190 rcv_stats->rx_packets++; 180 rcv_stats->rx_packets++;
191 181
192 netif_rx(skb);
193 return NETDEV_TX_OK; 182 return NETDEV_TX_OK;
194 183
195tx_drop: 184tx_drop:
@@ -198,7 +187,6 @@ tx_drop:
198 return NETDEV_TX_OK; 187 return NETDEV_TX_OK;
199 188
200rx_drop: 189rx_drop:
201 kfree_skb(skb);
202 rcv_stats->rx_dropped++; 190 rcv_stats->rx_dropped++;
203 return NETDEV_TX_OK; 191 return NETDEV_TX_OK;
204} 192}
@@ -275,7 +263,7 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu)
275 263
276static int veth_dev_init(struct net_device *dev) 264static int veth_dev_init(struct net_device *dev)
277{ 265{
278 struct veth_net_stats *stats; 266 struct veth_net_stats __percpu *stats;
279 struct veth_priv *priv; 267 struct veth_priv *priv;
280 268
281 stats = alloc_percpu(struct veth_net_stats); 269 stats = alloc_percpu(struct veth_net_stats);
@@ -337,7 +325,7 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[])
337 325
338static struct rtnl_link_ops veth_link_ops; 326static struct rtnl_link_ops veth_link_ops;
339 327
340static int veth_newlink(struct net_device *dev, 328static int veth_newlink(struct net *src_net, struct net_device *dev,
341 struct nlattr *tb[], struct nlattr *data[]) 329 struct nlattr *tb[], struct nlattr *data[])
342{ 330{
343 int err; 331 int err;
@@ -345,18 +333,17 @@ static int veth_newlink(struct net_device *dev,
345 struct veth_priv *priv; 333 struct veth_priv *priv;
346 char ifname[IFNAMSIZ]; 334 char ifname[IFNAMSIZ];
347 struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; 335 struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
336 struct ifinfomsg *ifmp;
337 struct net *net;
348 338
349 /* 339 /*
350 * create and register peer first 340 * create and register peer first
351 *
352 * struct ifinfomsg is at the head of VETH_INFO_PEER, but we
353 * skip it since no info from it is useful yet
354 */ 341 */
355
356 if (data != NULL && data[VETH_INFO_PEER] != NULL) { 342 if (data != NULL && data[VETH_INFO_PEER] != NULL) {
357 struct nlattr *nla_peer; 343 struct nlattr *nla_peer;
358 344
359 nla_peer = data[VETH_INFO_PEER]; 345 nla_peer = data[VETH_INFO_PEER];
346 ifmp = nla_data(nla_peer);
360 err = nla_parse(peer_tb, IFLA_MAX, 347 err = nla_parse(peer_tb, IFLA_MAX,
361 nla_data(nla_peer) + sizeof(struct ifinfomsg), 348 nla_data(nla_peer) + sizeof(struct ifinfomsg),
362 nla_len(nla_peer) - sizeof(struct ifinfomsg), 349 nla_len(nla_peer) - sizeof(struct ifinfomsg),
@@ -369,27 +356,41 @@ static int veth_newlink(struct net_device *dev,
369 return err; 356 return err;
370 357
371 tbp = peer_tb; 358 tbp = peer_tb;
372 } else 359 } else {
360 ifmp = NULL;
373 tbp = tb; 361 tbp = tb;
362 }
374 363
375 if (tbp[IFLA_IFNAME]) 364 if (tbp[IFLA_IFNAME])
376 nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ); 365 nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
377 else 366 else
378 snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d"); 367 snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
379 368
380 peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp); 369 net = rtnl_link_get_net(src_net, tbp);
381 if (IS_ERR(peer)) 370 if (IS_ERR(net))
371 return PTR_ERR(net);
372
373 peer = rtnl_create_link(src_net, net, ifname, &veth_link_ops, tbp);
374 if (IS_ERR(peer)) {
375 put_net(net);
382 return PTR_ERR(peer); 376 return PTR_ERR(peer);
377 }
383 378
384 if (tbp[IFLA_ADDRESS] == NULL) 379 if (tbp[IFLA_ADDRESS] == NULL)
385 random_ether_addr(peer->dev_addr); 380 random_ether_addr(peer->dev_addr);
386 381
387 err = register_netdevice(peer); 382 err = register_netdevice(peer);
383 put_net(net);
384 net = NULL;
388 if (err < 0) 385 if (err < 0)
389 goto err_register_peer; 386 goto err_register_peer;
390 387
391 netif_carrier_off(peer); 388 netif_carrier_off(peer);
392 389
390 err = rtnl_configure_link(peer, ifmp);
391 if (err < 0)
392 goto err_configure_peer;
393
393 /* 394 /*
394 * register dev last 395 * register dev last
395 * 396 *
@@ -431,6 +432,7 @@ static int veth_newlink(struct net_device *dev,
431err_register_dev: 432err_register_dev:
432 /* nothing to do */ 433 /* nothing to do */
433err_alloc_name: 434err_alloc_name:
435err_configure_peer:
434 unregister_netdevice(peer); 436 unregister_netdevice(peer);
435 return err; 437 return err;
436 438
@@ -439,7 +441,7 @@ err_register_peer:
439 return err; 441 return err;
440} 442}
441 443
442static void veth_dellink(struct net_device *dev) 444static void veth_dellink(struct net_device *dev, struct list_head *head)
443{ 445{
444 struct veth_priv *priv; 446 struct veth_priv *priv;
445 struct net_device *peer; 447 struct net_device *peer;
@@ -447,8 +449,8 @@ static void veth_dellink(struct net_device *dev)
447 priv = netdev_priv(dev); 449 priv = netdev_priv(dev);
448 peer = priv->peer; 450 peer = priv->peer;
449 451
450 unregister_netdevice(dev); 452 unregister_netdevice_queue(dev, head);
451 unregister_netdevice(peer); 453 unregister_netdevice_queue(peer, head);
452} 454}
453 455
454static const struct nla_policy veth_policy[VETH_INFO_MAX + 1]; 456static const struct nla_policy veth_policy[VETH_INFO_MAX + 1];