|
29 | 29 | static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
30 | 30 | {
|
31 | 31 | struct netdevsim *ns = netdev_priv(dev);
|
| 32 | + unsigned int len = skb->len; |
| 33 | + struct netdevsim *peer_ns; |
32 | 34 |
|
| 35 | + rcu_read_lock(); |
33 | 36 | if (!nsim_ipsec_tx(ns, skb))
|
34 |
| - goto out; |
| 37 | + goto out_drop_free; |
35 | 38 |
|
| 39 | + peer_ns = rcu_dereference(ns->peer); |
| 40 | + if (!peer_ns) |
| 41 | + goto out_drop_free; |
| 42 | + |
| 43 | + skb_tx_timestamp(skb); |
| 44 | + if (unlikely(dev_forward_skb(peer_ns->netdev, skb) == NET_RX_DROP)) |
| 45 | + goto out_drop_cnt; |
| 46 | + |
| 47 | + rcu_read_unlock(); |
36 | 48 | u64_stats_update_begin(&ns->syncp);
|
37 | 49 | ns->tx_packets++;
|
38 |
| - ns->tx_bytes += skb->len; |
| 50 | + ns->tx_bytes += len; |
39 | 51 | u64_stats_update_end(&ns->syncp);
|
| 52 | + return NETDEV_TX_OK; |
40 | 53 |
|
41 |
| -out: |
| 54 | +out_drop_free: |
42 | 55 | dev_kfree_skb(skb);
|
43 |
| - |
| 56 | +out_drop_cnt: |
| 57 | + rcu_read_unlock(); |
| 58 | + u64_stats_update_begin(&ns->syncp); |
| 59 | + ns->tx_dropped++; |
| 60 | + u64_stats_update_end(&ns->syncp); |
44 | 61 | return NETDEV_TX_OK;
|
45 | 62 | }
|
46 | 63 |
|
@@ -70,6 +87,7 @@ nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
70 | 87 | start = u64_stats_fetch_begin(&ns->syncp);
|
71 | 88 | stats->tx_bytes = ns->tx_bytes;
|
72 | 89 | stats->tx_packets = ns->tx_packets;
|
| 90 | + stats->tx_dropped = ns->tx_dropped; |
73 | 91 | } while (u64_stats_fetch_retry(&ns->syncp, start));
|
74 | 92 | }
|
75 | 93 |
|
@@ -302,7 +320,6 @@ static void nsim_setup(struct net_device *dev)
|
302 | 320 | eth_hw_addr_random(dev);
|
303 | 321 |
|
304 | 322 | dev->tx_queue_len = 0;
|
305 |
| - dev->flags |= IFF_NOARP; |
306 | 323 | dev->flags &= ~IFF_MULTICAST;
|
307 | 324 | dev->priv_flags |= IFF_LIVE_ADDR_CHANGE |
|
308 | 325 | IFF_NO_QUEUE;
|
|
0 commit comments