diff options
Diffstat (limited to 'drivers/net/veth.c')
-rw-r--r-- | drivers/net/veth.c | 73 |
1 files changed, 34 insertions, 39 deletions
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index ade5b344f75d..63099c58a6dd 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
@@ -155,8 +155,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
155 | struct veth_net_stats *stats, *rcv_stats; | 155 | struct veth_net_stats *stats, *rcv_stats; |
156 | int length, cpu; | 156 | int length, cpu; |
157 | 157 | ||
158 | skb_orphan(skb); | ||
159 | |||
160 | priv = netdev_priv(dev); | 158 | priv = netdev_priv(dev); |
161 | rcv = priv->peer; | 159 | rcv = priv->peer; |
162 | rcv_priv = netdev_priv(rcv); | 160 | rcv_priv = netdev_priv(rcv); |
@@ -168,20 +166,12 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
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 | ||
195 | tx_drop: | 184 | tx_drop: |
@@ -210,32 +199,29 @@ rx_drop: | |||
210 | static struct net_device_stats *veth_get_stats(struct net_device *dev) | 199 | static struct net_device_stats *veth_get_stats(struct net_device *dev) |
211 | { | 200 | { |
212 | struct veth_priv *priv; | 201 | struct veth_priv *priv; |
213 | struct net_device_stats *dev_stats; | ||
214 | int cpu; | 202 | int cpu; |
215 | struct veth_net_stats *stats; | 203 | struct veth_net_stats *stats, total = {0}; |
216 | 204 | ||
217 | priv = netdev_priv(dev); | 205 | priv = netdev_priv(dev); |
218 | dev_stats = &dev->stats; | ||
219 | 206 | ||
220 | dev_stats->rx_packets = 0; | 207 | for_each_possible_cpu(cpu) { |
221 | dev_stats->tx_packets = 0; | ||
222 | dev_stats->rx_bytes = 0; | ||
223 | dev_stats->tx_bytes = 0; | ||
224 | dev_stats->tx_dropped = 0; | ||
225 | dev_stats->rx_dropped = 0; | ||
226 | |||
227 | for_each_online_cpu(cpu) { | ||
228 | stats = per_cpu_ptr(priv->stats, cpu); | 208 | stats = per_cpu_ptr(priv->stats, cpu); |
229 | 209 | ||
230 | dev_stats->rx_packets += stats->rx_packets; | 210 | total.rx_packets += stats->rx_packets; |
231 | dev_stats->tx_packets += stats->tx_packets; | 211 | total.tx_packets += stats->tx_packets; |
232 | dev_stats->rx_bytes += stats->rx_bytes; | 212 | total.rx_bytes += stats->rx_bytes; |
233 | dev_stats->tx_bytes += stats->tx_bytes; | 213 | total.tx_bytes += stats->tx_bytes; |
234 | dev_stats->tx_dropped += stats->tx_dropped; | 214 | total.tx_dropped += stats->tx_dropped; |
235 | dev_stats->rx_dropped += stats->rx_dropped; | 215 | total.rx_dropped += stats->rx_dropped; |
236 | } | 216 | } |
237 | 217 | dev->stats.rx_packets = total.rx_packets; | |
238 | return dev_stats; | 218 | dev->stats.tx_packets = total.tx_packets; |
219 | dev->stats.rx_bytes = total.rx_bytes; | ||
220 | dev->stats.tx_bytes = total.tx_bytes; | ||
221 | dev->stats.tx_dropped = total.tx_dropped; | ||
222 | dev->stats.rx_dropped = total.rx_dropped; | ||
223 | |||
224 | return &dev->stats; | ||
239 | } | 225 | } |
240 | 226 | ||
241 | static int veth_open(struct net_device *dev) | 227 | static int veth_open(struct net_device *dev) |
@@ -340,7 +326,7 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
340 | 326 | ||
341 | static struct rtnl_link_ops veth_link_ops; | 327 | static struct rtnl_link_ops veth_link_ops; |
342 | 328 | ||
343 | static int veth_newlink(struct net_device *dev, | 329 | static int veth_newlink(struct net *src_net, struct net_device *dev, |
344 | struct nlattr *tb[], struct nlattr *data[]) | 330 | struct nlattr *tb[], struct nlattr *data[]) |
345 | { | 331 | { |
346 | int err; | 332 | int err; |
@@ -348,6 +334,7 @@ static int veth_newlink(struct net_device *dev, | |||
348 | struct veth_priv *priv; | 334 | struct veth_priv *priv; |
349 | char ifname[IFNAMSIZ]; | 335 | char ifname[IFNAMSIZ]; |
350 | struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; | 336 | struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; |
337 | struct net *net; | ||
351 | 338 | ||
352 | /* | 339 | /* |
353 | * create and register peer first | 340 | * create and register peer first |
@@ -380,14 +367,22 @@ static int veth_newlink(struct net_device *dev, | |||
380 | else | 367 | else |
381 | snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d"); | 368 | snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d"); |
382 | 369 | ||
383 | peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp); | 370 | net = rtnl_link_get_net(src_net, tbp); |
384 | if (IS_ERR(peer)) | 371 | if (IS_ERR(net)) |
372 | return PTR_ERR(net); | ||
373 | |||
374 | peer = rtnl_create_link(src_net, net, ifname, &veth_link_ops, tbp); | ||
375 | if (IS_ERR(peer)) { | ||
376 | put_net(net); | ||
385 | return PTR_ERR(peer); | 377 | return PTR_ERR(peer); |
378 | } | ||
386 | 379 | ||
387 | if (tbp[IFLA_ADDRESS] == NULL) | 380 | if (tbp[IFLA_ADDRESS] == NULL) |
388 | random_ether_addr(peer->dev_addr); | 381 | random_ether_addr(peer->dev_addr); |
389 | 382 | ||
390 | err = register_netdevice(peer); | 383 | err = register_netdevice(peer); |
384 | put_net(net); | ||
385 | net = NULL; | ||
391 | if (err < 0) | 386 | if (err < 0) |
392 | goto err_register_peer; | 387 | goto err_register_peer; |
393 | 388 | ||
@@ -442,7 +437,7 @@ err_register_peer: | |||
442 | return err; | 437 | return err; |
443 | } | 438 | } |
444 | 439 | ||
445 | static void veth_dellink(struct net_device *dev) | 440 | static void veth_dellink(struct net_device *dev, struct list_head *head) |
446 | { | 441 | { |
447 | struct veth_priv *priv; | 442 | struct veth_priv *priv; |
448 | struct net_device *peer; | 443 | struct net_device *peer; |
@@ -450,8 +445,8 @@ static void veth_dellink(struct net_device *dev) | |||
450 | priv = netdev_priv(dev); | 445 | priv = netdev_priv(dev); |
451 | peer = priv->peer; | 446 | peer = priv->peer; |
452 | 447 | ||
453 | unregister_netdevice(dev); | 448 | unregister_netdevice_queue(dev, head); |
454 | unregister_netdevice(peer); | 449 | unregister_netdevice_queue(peer, head); |
455 | } | 450 | } |
456 | 451 | ||
457 | static const struct nla_policy veth_policy[VETH_INFO_MAX + 1]; | 452 | static const struct nla_policy veth_policy[VETH_INFO_MAX + 1]; |