慢慢欣赏linux 网络协议栈四 sk_buff以及数据收发
以3c359x.c的网卡为例,因为这是《深入理解Linux网络技术内幕》里面的例子
irqreturn_t vortex_interrupt(int irq, void *dev_id)
vortex_rx(dev);
=>int vortex_rx(struct net_device *dev)
struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
short rx_status;
while ((rx_status = ioread16(ioaddr + RxStatus)) > 0)
int pkt_len = rx_status & 0x1fff;
struct sk_buff *skb = dev_alloc_skb(pkt_len + 5);
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
if (vp->bus_master && ! (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000))
dma_addr_t dma = pci_map_single(VORTEX_PCI(vp), skb_put(skb, pkt_len), pkt_len, PCI_DMA_FROMDEVICE);
iowrite32(dma, ioaddr + Wn7_MasterAddr);
iowrite16((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
iowrite16(StartDMAUp, ioaddr + EL3_CMD);
while (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)
;
pci_unmap_single(VORTEX_PCI(vp), dma, pkt_len, PCI_DMA_FROMDEVICE);
else
ioread32_rep(ioaddr + RX_FIFO, skb_put(skb, pkt_len), (pkt_len + 3) >> 2);
iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb)
=>int netif_rx(struct sk_buff *skb)
if (queue->input_pkt_queue.qlen <= netdev_max_backlog)
if (queue->input_pkt_queue.qlen)
enqueue:
__skb_queue_tail(&queue->input_pkt_queue, skb);
return NET_RX_SUCCESS;
napi_schedule(&queue->backlog);
=>inline void napi_schedule(struct napi_struct *n)
if (napi_schedule_prep(n))
__napi_schedule(n);
=>void __napi_schedule(struct napi_struct *n)
list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list);
__raise_softirq_irqoff(NET_RX_SOFTIRQ);//唤醒软中断
goto enqueue;
收包软中断入口函数
void net_rx_action(struct softirq_action *h)
struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
while (!list_empty(list))
n = list_first_entry(list, struct napi_struct, poll_list);
have = netpoll_poll_lock(n);
weight = n->weight;
n = list_first_entry(list, struct napi_struct, poll_list);
have = netpoll_poll_lock(n);
weight = n->weight;
work = 0;
if (test_bit(NAPI_STATE_SCHED, &n->state))
work = n->poll(n, weight);
=>int process_backlog(struct napi_struct *napi, int quota)
budget -= work;
Linux 网络协议栈开发代码分析篇之数据收发(一) —— netif_receive_skb()函数
https://blog.csdn.net/zqixiao_09/article/details/79185800
Linux内核--网络栈实现分析(二)--数据包的传递过程(上)
https://blog.csdn.net/geekcome/article/details/7492423
作者:天麓
来源:CSDN
原文:https://blog.csdn.net/shipinsky/article/details/88923786
版权声明:本文为博主原创文章,转载请附上博文链接!