1.网卡驱动收数据包思路记录
来源:互联网 发布:开淘宝店进货渠道 编辑:程序博客网 时间:2024/06/09 16:45
http://www.cnblogs.com/lidp/archive/2009/05/13/1697981.html
根据这个思路走
网卡收到数据包的大概流程,目前只是大概理顺下思路,可能有的地方理解有误。
网卡的工作能力,接收到物理层面上的信号。
1.能够识别出来数据链路层的(L4)层的数据帧。
2.接收到多个数据帧的时候有一定的缓存能力。
3.能够在数据链路层计算收到的帧是否正确。
4.有帧的时候产生中断通知CPU。
驱动工作流程
1.注册中断函数
2.数据到了触发硬中断,硬中断只是将代表当前驱动的napi_struct连接到CPU的softnet_data,然后触发软中断。
3.软中断函数调用poll在一小段时间不断的读取数据帧存放到skb里面。
1.网卡启动
核心函数 request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev)
注册中断函数,当有数据包过来的时候会触发中断从而调用e100_intr,从而驱动知道有数据包过来。
static int e100_up(struct nic *nic)
{
int err;
if ((err = e100_rx_alloc_list(nic)))
return err;
if ((err = e100_alloc_cbs(nic)))
goto err_rx_clean_list;
if ((err = e100_hw_init(nic)))
goto err_clean_cbs;
e100_set_multicast_list(nic->netdev);
e100_start_receiver(nic, NULL);
mod_timer(&nic->watchdog, jiffies);
if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev)))
goto err_no_irq;
netif_wake_queue(nic->netdev);
napi_enable(&nic->napi);
/* enable ints _after_ enabling poll, preventing a race between
* disable ints+schedule */
e100_enable_irq(nic);
return 0;
err_no_irq:
del_timer_sync(&nic->watchdog);
err_clean_cbs:
e100_clean_cbs(nic);
err_rx_clean_list:
e100_rx_clean_list(nic);
return err;
}
2.中断里面只是告诉CPU有数据到了,将代表网卡的napi_struct通过链表添加在CPU的softnet_data上面,然后触发软中断,
软中断过程中调用注册过来的napi_struct上面的poll函数,在软中断中不断的读取和发送数据。
static irqreturn_t e100_intr(int irq, void *dev_id)
{
struct net_device *netdev = dev_id;
struct nic *nic = netdev_priv(netdev);
u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);
netif_printk(nic, intr, KERN_DEBUG, nic->netdev,
"stat_ack = 0x%02X\n", stat_ack);
if (stat_ack == stat_ack_not_ours ||/* Not our interrupt */
stat_ack == stat_ack_not_present)/* Hardware is ejected */
return IRQ_NONE;
/* Ack interrupt(s) */
iowrite8(stat_ack, &nic->csr->scb.stat_ack);
/* We hit Receive No Resource (RNR); restart RU after cleaning */
if (stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;
if (likely(napi_schedule_prep(&nic->napi))) {
e100_disable_irq(nic);
__napi_schedule(&nic->napi);
}
return IRQ_HANDLED;
}
3.poll函数
e100_poll函数在PCI网卡探测成功之后就注册在net_device里面
static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct nic *nic;
netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT);
}
注册完为
struct net_device {
struct list_headnapi_list;//这个链表上面链接这所有的napi_struct
}
struct napi_struct { //napi_struct 里面包含所有的poll函数
int (*poll)(struct napi_struct *, int);
}
static int e100_poll(struct napi_struct *napi, int budget)
{
struct nic *nic = container_of(napi, struct nic, napi);
unsigned int work_done = 0;
e100_rx_clean(nic, &work_done, budget);
e100_tx_clean(nic);
/* If budget not fully consumed, exit the polling mode */
if (work_done < budget) {
napi_complete(napi);
e100_enable_irq(nic);
}
return work_done;
}
4.接收数据的函数e100_rx_clean
e100_rx_clean -> e100_rx_indicate -> netif_receive_skb
根据这个思路走
网卡收到数据包的大概流程,目前只是大概理顺下思路,可能有的地方理解有误。
网卡的工作能力,接收到物理层面上的信号。
1.能够识别出来数据链路层的(L4)层的数据帧。
2.接收到多个数据帧的时候有一定的缓存能力。
3.能够在数据链路层计算收到的帧是否正确。
4.有帧的时候产生中断通知CPU。
驱动工作流程
1.注册中断函数
2.数据到了触发硬中断,硬中断只是将代表当前驱动的napi_struct连接到CPU的softnet_data,然后触发软中断。
3.软中断函数调用poll在一小段时间不断的读取数据帧存放到skb里面。
4.回调netif_receive_skb函数
1.网卡启动
核心函数 request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev)
注册中断函数,当有数据包过来的时候会触发中断从而调用e100_intr,从而驱动知道有数据包过来。
static int e100_up(struct nic *nic)
{
int err;
if ((err = e100_rx_alloc_list(nic)))
return err;
if ((err = e100_alloc_cbs(nic)))
goto err_rx_clean_list;
if ((err = e100_hw_init(nic)))
goto err_clean_cbs;
e100_set_multicast_list(nic->netdev);
e100_start_receiver(nic, NULL);
mod_timer(&nic->watchdog, jiffies);
if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev)))
goto err_no_irq;
netif_wake_queue(nic->netdev);
napi_enable(&nic->napi);
/* enable ints _after_ enabling poll, preventing a race between
* disable ints+schedule */
e100_enable_irq(nic);
return 0;
err_no_irq:
del_timer_sync(&nic->watchdog);
err_clean_cbs:
e100_clean_cbs(nic);
err_rx_clean_list:
e100_rx_clean_list(nic);
return err;
}
2.中断里面只是告诉CPU有数据到了,将代表网卡的napi_struct通过链表添加在CPU的softnet_data上面,然后触发软中断,
软中断过程中调用注册过来的napi_struct上面的poll函数,在软中断中不断的读取和发送数据。
static irqreturn_t e100_intr(int irq, void *dev_id)
{
struct net_device *netdev = dev_id;
struct nic *nic = netdev_priv(netdev);
u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);
netif_printk(nic, intr, KERN_DEBUG, nic->netdev,
"stat_ack = 0x%02X\n", stat_ack);
if (stat_ack == stat_ack_not_ours ||/* Not our interrupt */
stat_ack == stat_ack_not_present)/* Hardware is ejected */
return IRQ_NONE;
/* Ack interrupt(s) */
iowrite8(stat_ack, &nic->csr->scb.stat_ack);
/* We hit Receive No Resource (RNR); restart RU after cleaning */
if (stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;
if (likely(napi_schedule_prep(&nic->napi))) {
e100_disable_irq(nic);
__napi_schedule(&nic->napi);
}
return IRQ_HANDLED;
}
3.poll函数
e100_poll函数在PCI网卡探测成功之后就注册在net_device里面
static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
struct nic *nic;
netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT);
}
注册完为
struct net_device {
struct list_headnapi_list;//这个链表上面链接这所有的napi_struct
}
struct napi_struct { //napi_struct 里面包含所有的poll函数
int (*poll)(struct napi_struct *, int);
}
static int e100_poll(struct napi_struct *napi, int budget)
{
struct nic *nic = container_of(napi, struct nic, napi);
unsigned int work_done = 0;
e100_rx_clean(nic, &work_done, budget);
e100_tx_clean(nic);
/* If budget not fully consumed, exit the polling mode */
if (work_done < budget) {
napi_complete(napi);
e100_enable_irq(nic);
}
return work_done;
}
4.接收数据的函数e100_rx_clean
e100_rx_clean -> e100_rx_indicate -> netif_receive_skb
阅读全文
0 0
- 1.网卡驱动收数据包思路记录
- 网卡驱动的数据包发送接收
- 无线网卡收不到数据包
- 网卡驱动和队列层中的数据包接收
- 数据包接收系列 — 上半部实现(网卡驱动)
- 网卡驱动和队列层中的数据包接收
- 数据包接收系列 — 上半部实现(网卡驱动)
- 网卡驱动和队列层中的数据包接收
- centos 7, 安装网卡驱动过程记录
- 网卡驱动收包
- winpcap如何捕获多个网卡的数据包,一点小思路,欢迎讨论!
- winpcap如何捕获多个网卡的数据包,一点小思路,欢迎讨论!(续)
- 多网卡发送数据包
- 网卡如何接收数据包
- 网卡如何接收数据包
- 网卡如何发送数据包
- 网卡驱动:数据包发送的流控机制-netif_start_queue/netif_wake_queue/netif_stop_queue
- 网卡驱动:数据包发送的流控机制-netif_start_queue/netif_wake_queue/netif_stop_queue
- 习题8.14
- 人工神经网络之激活函数 -RELU函数
- 测试理论体系知识
- 工作总结10:毕业这一年的收获
- Zend Studio 13 +XDebug 调试
- 1.网卡驱动收数据包思路记录
- 如何解决failed to push some refs to git
- WEB开发中实现会话跟踪实现
- PAT甲级 1015. Reversible Primes (20)
- Fluent Python 笔记四
- linux之C编程学习——进程,进程,进程!
- c++ struct与class区别
- Map Serialization and Deserialization with Jackson
- TCP流量控制