linux-network详解4数据包发送

1 数据链路层和接口层中网络数据包的发送

从函数dev_hard_start_xmit开始分析。

1.1 函数dev_hard_start_xmit

作用:它是将数据包交给网卡驱动进行发送的接口。定义位于:linux-4.9.73\net\core\dev.c

 1 struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *dev,
 2                     struct netdev_queue *txq, int *ret)
 3 {
 4     struct sk_buff *skb = first;
 5     int rc = NETDEV_TX_OK;
 6 
 7     while (skb) {
 8         struct sk_buff *next = skb->next;
 9 
10         skb->next = NULL;
11         rc = xmit_one(skb, dev, txq, next != NULL);//调用xmit_one来发送数据包
12         if (unlikely(!dev_xmit_complete(rc))) {
13             skb->next = next;
14             goto out;
15         }
16 
17         skb = next;
18         if (netif_xmit_stopped(txq) && skb) {
19             rc = NETDEV_TX_BUSY;
20             break;
21         }
22     }
23 
24 out:
25     *ret = rc;
26     return skb;
27 }

1.2 函数xmit_one

 1 static int xmit_one(struct sk_buff *skb, struct net_device *dev,
 2             struct netdev_queue *txq, bool more)
 3 {
 4     unsigned int len;
 5     int rc;
 6 
 7     if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
 8         dev_queue_xmit_nit(skb, dev);
 9 
10     len = skb->len;
11     trace_net_dev_start_xmit(skb, dev);
12     rc = netdev_start_xmit(skb, dev, txq, more);
13     trace_net_dev_xmit(skb, rc, dev, len);
14 
15     return rc;
16 }

1.3 函数netdev_start_xmit

定义位于:linux-4.9.73\include\linux\netdevice.h

 1 static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev,
 2                         struct netdev_queue *txq, bool more)
 3 {
 4     const struct net_device_ops *ops = dev->netdev_ops;
 5     int rc;
 6 
 7     rc = __netdev_start_xmit(ops, skb, dev, more);
 8     if (rc == NETDEV_TX_OK)
 9         txq_trans_update(txq);
10 
11     return rc;
12 }
13 
14 static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,
15                           struct sk_buff *skb, struct net_device *dev,
16                           bool more)
17 {
18     skb->xmit_more = more ? 1 : 0;
19     return ops->ndo_start_xmit(skb, dev);//调用驱动的发送函数
20 }

2 网卡驱动层数据的发送

具体以linux-4.9.73\drivers\net\wireless\ath\wil6210\为例

2.1 函数wil_start_xmit

接着1.3节中,对应驱动的发送函数,定义位于linux-4.9.73\drivers\net\wireless\ath\wil6210\netdev.c

网络设备操作结构体:

1 static const struct net_device_ops wil_netdev_ops = {
2     .ndo_open        = wil_open,
3     .ndo_stop        = wil_stop,
4     .ndo_start_xmit        = wil_start_xmit,
5     .ndo_set_mac_address    = eth_mac_addr,
6     .ndo_validate_addr    = eth_validate_addr,
7     .ndo_change_mtu        = wil_change_mtu,
8     .ndo_do_ioctl        = wil_do_ioctl,
9 };

调用函数wil_start_xmit,向网卡发送数据。

 1 netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 2 {
 3     struct wil6210_priv *wil = ndev_to_wil(ndev);
 4     struct ethhdr *eth = (void *)skb->data;
 5     bool bcast = is_multicast_ether_addr(eth->h_dest);
 6     struct vring *vring;
 7     static bool pr_once_fw;
 8     int rc;
 9 
10     wil_dbg_txrx(wil, "%s()\n", __func__);
11     if (unlikely(!test_bit(wil_status_fwready, wil->status))) {
12         if (!pr_once_fw) {
13             wil_err(wil, "FW not ready\n");
14             pr_once_fw = true;
15         }
16         goto drop;
17     }
18     if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) {
19         wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n");
20         goto drop;
21     }
22     if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) {
23         wil_err(wil, "Xmit in monitor mode not supported\n");
24         goto drop;
25     }
26     pr_once_fw = false;
27 
28     /* find vring */
29     if (wil->wdev->iftype == NL80211_IFTYPE_STATION) {
30         /* in STA mode (ESS), all to same VRING */
31         vring = wil_find_tx_vring_sta(wil, skb);
32     } else { /* direct communication, find matching VRING */
33         vring = bcast ? wil_find_tx_bcast(wil, skb) :
34                 wil_find_tx_ucast(wil, skb);
35     }
36     if (unlikely(!vring)) {
37         wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
38         goto drop;
39     }
40     /* set up vring entry */
41     rc = wil_tx_vring(wil, vring, skb);
42 
43     /* do we still have enough room in the vring? */
44     if (unlikely(wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))) {
45         netif_tx_stop_all_queues(wil_to_ndev(wil));
46         wil_dbg_txrx(wil, "netif_tx_stop : ring full\n");
47     }
48 
49     switch (rc) {
50     case 0:
51         /* statistics will be updated on the tx_complete */
52         dev_kfree_skb_any(skb);
53         return NETDEV_TX_OK;
54     case -ENOMEM:
55         return NETDEV_TX_BUSY;
56     default:
57         break; /* goto drop; */
58     }
59  drop:
60     ndev->stats.tx_dropped++;
61     dev_kfree_skb_any(skb);
62 
63     return NET_XMIT_DROP;
64 }

 

posted @ 2020-11-21 17:44  Action_er  阅读(1567)  评论(0)    收藏  举报