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 }
行胜于言,自强不息。

浙公网安备 33010602011771号