本文共 2445 字,大约阅读时间需要 8 分钟。
以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/79185800Linux内核--网络栈实现分析(二)--数据包的传递过程(上)
https://blog.csdn.net/geekcome/article/details/7492423