Linux网络数据包收发流程

4星(超过85%的资源)
所需积分/C币:50 2011-12-20 18:09:00 1.28MB PDF
187
收藏 收藏
举报

(一) 从驱动到协议栈 (二) 不配置NAPI (三) e1000 和 DMA (四) packet_type 从代码级详细讲述了Linux中网络设备和协议栈的衔接过程,以及底层的收发过程。
} int gfar probe(struct platform device*pdev) dev=allc_ etherdev( sizeof(ˆpri);∥创建 net device数据结构 dev->open =gfar_ enet open dev-shard start xmit- gfar start xmit; dev->tx timeout gfar timeout dev->watchdog timeo =TX TIMEOUT fifdef config gfar napl netif napi add(dev,&priy->napi, gfar poll, GFAR DEV WEIGHT);∥软中断里会调用pol钩子函数 tend #ifdef config net poll controller dev->poll controller gfar netpol fendi dev->stop= gfar close dev->change mtu gfar change mtu dev->mtu =1500 dev->set multicast list- gfar set multi dev->set mac address gfar set mac address: dev->ethtool ops =&gfar ethtool ops 五、启用网络设备 51用户调用 ifconfig等程序,然后通过ioct系统调用进入内核 socket的 ioctl系统调用 - sock ioctl -->dev ioctl )断S| OCSIFFLAGS > dev get by_name(net;ir-> ifr name)∥根据名字选 net device -- dev change flags ∥判断|FFUP dev open(net device) ∥调用open钩子函数 对于TSEC来说,挂的钩子函数是 gfar enet open( net device) 52在网络设备的open钩子函数里,分配接收bd,挂中断|sR(包括rx、tx、em),对于TSEC来说 gfar enet open 给 RX TX Bd分配一致性DMA内存 ∞>把RκBd的"EA地址'赋给数据结构,物理地址赋给TSEC寄存器 把TBd的EA地址”赋给数据结构,物理地址赋给TSEC寄存器 给 tx skbuff指针数组分配内存,并初始化为NULL >给 rx skbuff指针数组分配内存,并初始化为NUL >初始化TxBd 初始化RⅹBd,提前分配存储以太网包的skb,这里使用的是一次性dma映射 (注意:# define default rx buFFer size1536保证了skb能存一个以太网包) rxbdp= priv->rx bd base; for(i=0; i< priv->rx ring_ size; i++)t struct sk buff *skb null rxbdp-status =0; 这里真正分配skb,并且初始化 rxbpd-> bupt, rdpd-> length kb= gfar new skb(dev, rxbdp) priv->rx skbuff[= skb rxbdp++ rxbdp-; rxbdp-> status|= RXBD WRAP;∥给最后一个bd设置标记WRAP标记 >注册TSEC相关的中断 handler:错误,接收,发送 request irq(priv->interruptError, gfar error, 0, "enet error",dev) request irg(priy-> Interrupt Transmit, gfar transmit,0," enet tx",dev)∥何发送完 request irg(priy- >interruptReceive, gfar receive,o," enet rx";dev)∥包接收完 ->gfar start(net device ∥使能RX、TX ∥开启TSEC的DMA寄存器 ∥Mask掉我们不关心的中断 event 最终,TSEC相关的Bd等数据结构应该是下面这个样子的 内核使月的拦针数组 TSEC使甲的b数组 ( kmalloc普通内存) dma alloc coherent一致性DMA内存) dma map single 次性MA映射 Txbd的 全为0 len全 tx skbut.组 旦面全是NULL Ix skbuffll.数 Rxbd里 存放的是skb 存放的是skb->data 的EA逻辑地址 的物理地址 skb 六、中断里接收以太网包 TSEC的RX已经使能了,网络数据包进入内存的流程为: 网线->R45网口->MD|差分线 >bcm5461(PHY芯片进行数模转换)->M总线 >TSEC的 DMA Engine会自动检查下一个可用的Rxbd ->把网络数据包DMA到Rxbd所指向的内存,即skb->data 接收到一个完整的以太网数据包后,TSEC会根据 event mask触发一个Rx外部中断。 cpu保存现场,根据中断向量,开始执行外部中断处理函数do_|RQ0 do|RQ伪代码 上半部处理硬中断 查看中断源寄存器,得知是网络外设产生了外部中断 执行网络设备的x中断 handler(设备不同,函数不同,但流程类似,TSEC是 gfar receive) 1.mask掉 event,再来数据包就不会产生r中断 2.给 napl struct. state加上NAP| STATE SCHED状态 3.挂网络设备自己的 napl struct结构到cpu私有变量 get cpu var( softnet data., poll list 4.触发网络接收软中断 下半部处理软中断 依次执行所有软中断 handler,包括 timer, tasklet等等 执行网络接收的软中断 handler net rx action 1.遍历cpu私有变量 get cpu var( softnet data)po‖list 2.取出po‖list上面挂的 napl struct结构,执行钩子函数 napi struct. pol(Q 设备不同,钩子函数不同,流程类似,TSEC是 gfar poll 3.若po钩子函数处理完所有包,则打开 rx event mask,再来数据包的话会产生x中断 4.调用 napi complete(napi struct*n 把 napl struct结构从_ get cpu var(( softnet data) poll list上移走 同时去掉 napl struct state的NAP| STATE SCHED状态 61TSEc的接收中断处理函数 gfar receive #ifdef coNfig FAR NAPl test and set当前 net device的 napl struct state为NAP| STATE SCHED ∥在软中断里调用 net rx action会检查状态 napl struct state if (netif rx schedule _ prep(dev, &priv->napi)t tempval gfar read(&priv->regs->mask) tempoal&= MASK RX D| SABLED;/mask掉rx,不再产生rx中断 gfar write (&priv->regs->mask, tempval) ∥|将当前 net device的 napi struct poll list挂到 ∥CPU私有变量 get cpu var( softnet data) poll list上,并触发软中断 ∥/所以,在软中断中调用 net x action的时候,就会执行当前 net device的 ∥ napl struct:po(钩子函数即gfar_polO netif rx schedule(dev, &priv->napi) else gfar clean rx ring(dev, priv->rx ring_ size) tender 62网络接收软中断 net rx action net rx action struct list head *list = get cpu var (softnet data) poll list 通过 napi struct poll list,将N多个 napl struct链接到一条链上 通过CPU私有变量,我们找到了链头,然后开始遍历这个链 nt budget= netdev budget;∥这个值就是net.core. netdev max backlog,通过sysc来修改 while(list empty (ist))[ struct napl struct n int work, weight local irg enabled H)链上取一个 napl struct结构(接收中断处理函数里加到链表上的,如 gfar receive) n=list entry (list->next, struct napi struct, poll list) weight n->weight work=0 f( test bit(NAP| STATE SCHED,&n-> state)∥检查状态标记,此标记在接收中断里加上的 Work=n->po(n, weight;∥使用NAP的话,使用的是网络设备自己的 napi struct. pol /对于TSEC是,是 gfar poll WARN ON ONCE(work weight) budget-= work local irq disable 0: if (unlikely (work = weight))I if (unlikely (napi disable_ pending(n) napi_ complete(n);/操作 napl struct,把去掉NAP⊥ STATE_ SCHED状态,从链表中删去 se list move tail(&n->poll list, list) netpoll poll unlock(have) ou local irq enabled; static int gfar poll(struct napi struct *napi, int budget) struct gfar private *priv= container of(napi, struct gfar private, napi struct net device *dev=priv->dev;TSEC对应的网络设备 int howmany; ∥根据dev的rxbd,获取skb并送入协议栈,返回处理的skb的个数,即以太网包的个数 howmany =gfar clean rx ring(dev, budget) ∥下面这个判断比较有讲究的 ∥收到的包的个数小于 budget,代表我们在一个软中断里就全处理完了,所以打开rX中断 ∥要是收到的包的个数大于 budget,表示一个软中断里处理不完所有包,那就不打开rx中断, 待到下一个软中断里再接着处理,直到把所有包处理完(即 howmany< budget),再打开rx中断 if (howmany budget)i netit rx complete(dev, napi) gfar write(&priv->regs->rstat, RSTAT CLEAR RHALT !开rX中断,rX中断是在 gfar receive0中被关闭的 gfar write( &priv->regs->mask, IMASK DEFAULT) return howmany gfar clean rx ring(dev, budget) dp= priv->cur rx; while(((bdp->status RXBD EMPTY)ll(rx work limit < ot mbo skb=priy-> x skhuff[priv-> ikb curi:∥从 rx skbugg中获取skb howmany++ dev->stats. rx packets++ pkt len=bdp> ength-4;∥从 length中去掉以太网包的FCS长度 gfar process frame( dev, skb, pkt len) dev->stats. rx bytes + pkt len dev->last rx= jiffies bdp-> status&=- RXBD STATS;清rbd的状态 skb= gfar new skb(dev, bdp); / Add another skb for the future priv->rx skbufflpriv->skb currx= skb if(bdp-> status& RXBD WRAP)∥更新指向bd的指针 bdp=priy-> erx bd base;/bd有wARP标记,说明是最后一个bd了,需要“绕回来 else bdp++ -> skb curry=(prⅳ-> skb curry+1)&RⅩ RING MOD MASK(prⅳ> x ring sIze); priv->cur rx=bdp; / Update the current rxbd pointer to be the next one * return howmany gfar process frameD >RECEⅣVE(skb)∥调用 netif receive skb(skb)进入协议栈 #ifdef config gfar napl #define RECEIVE(x) netif receive skb(x) telse #define RECEIve(x ) netif_rx(x) #endif 网络数据包收发流程(二):不配置NAP的情况 2011-12-0420:17:08 标签:网络数据包收发流程(二):不配置NAP的情况 上一篇讲的是內核配置成NAP的情况,那也是绝大多数內核使用的配置 现在讲讲内核不配置成NAP时的情况 一、 no nap数据结构 CPU私有变量 softnet data poll napI struct alI lisl o list 不配置NAP的时候,网络设备不使用自己的 napl struct结构, 所有网络设备驱动都使用同一个 napl struct,即cpu私有变量 get cpu var(( softnet data). backlog 每当收到数据包时,网络设备驱动会把 get cpu var( softnet data. backlog挂到 get cpu var( softnet data). poll list上面。 所以软中断里 net rx action遍力cpu私有变量 get cpu var( softnet data), poll list时, 上面挂的 napl struct只有一个 内核启动时的准备工作 也是在 net dev init中,初始化了cpu私有变量的 napl struct,即所有网络设备驱动使用的 napl struct init net dev inito ∥每个CPU都有一个私有变量 get cpu var( softnet data ∥ get cpu var( softnet data) poll list很重要,软中断中需要遍历它的 for each possible cpu(t struct softnet_ data *queue data, D) queue =&per cpu(softnet da skb queue head init(& queue- Pinput pkt queue);l/不配置NAP时,才使用这个接收队列 queue->completion queue NULL INIT LIST HEAD(&queue->poll list) queue-> backlog. poll= process backlog;∥po钩子函数初始化 queue->backlog. weight = weight p open softing( NET TX SOFTIRQ, net tx action,NULL);∥在软中断上挂网络接收 handler open softing( NET RX SOFTIRQ, net rx action,NULL);∥在软中断上挂网络发送 handler 、中断里接受以太网包 TSEC的接收中断处理函数 gear receIve gfar write(&priv->regs->event, IEVENT RX MASK) fifdef config gfar nap ∥ test and set当前 net device的 napl struct state为NAP| STATE SCHED ∥在软中断里调用 net rx action会检查状态 napl structstate if (netif rx schedule prep(dev, &priv->napi))t tempval gfar read(&priv->regs->mask) tempval &=IMASK RX DISABLED gfar write (&priv->regs->mask, tempval) ∥.将当前 net device的 napl struct. poll list挂到 ∥CPU私有变量& get cpu var( softnet data) poll list上,并触发软中断 ∥/所以,在软中断中调用 net x action的时候,就会执行当前 net device的 ∥ napl struct.polO钩子函数,即 gfar poll0 netif rx schedule(dev, &priv->napi) felse gfar clean rx ring dev, priv->rx ring_ size) fendi gfar cleanrx_ ring >gfar process frame >初始化了skb->de,这样在软中断里才能判断这个数据包来自哪里 >RECEⅣE(skb)∥/调用 netif rx(skb) #ifdef config gfar napl #define RECEIVE(x) netif receive skb(x) #else #define RECEIVE(X) netif rx(x) #endif netif rx(skb queue = get cpu var(softnet data) skb queue tail(& queue- >input pkt queue,skb);∥将sKb放到接收队列(在 net dey init初始化) 中 napi schedule(& queue-> backlog);∥将cpu私有变量的的napi_ struct挂到cpu私有变量的po‖ist 上 //test and set napi struct state 2 NAPI STATE_ SCHED ∥触发网络接收软中断 软中断 net rx action中调用po钩子函数 虽说软中断里也邐历cpu私有变量的 poll list.,事实上 poll list现在只挂一个 napl struct结构 即cpu私有变量的 backlog成员(它在 net dev init中初始化),所以现在调用的po子函数就是 process backlog了 static int process backlog(struct napi struct *napl, int quota) struct softnet data *queue=& get cpu var(softnet data) napi->weight= weight p lo i struct sk buff *skb struct net device dev local irg disabled skb= skb dequeue(& queue-> input pkt queue);/从接收队列中取出skb, if (Iskb)[ ∥这些skb是在 netif rx中进入队列的 napi complete(napi) local irq enable break local irg enable: dev skb->dev netif receive skb(skb);∥进入协议协议栈 dev put(dev) I while(++work quota & jiffies = start time return work 网络数据包收发流程(三):e1000网卡和DMA 2011-12-0420:18:58 标签:网络数据包收发流程(三):e1000网卡和DMA 硬件布局 MPC8S DDR 内存条 DDR总线一 DDR Controller ore TSEC Engine PCI Controler M总线 PCL总线 bcm5461 inte182546 每个网卡(MAC)都有自己的专用 DMA Engine,如上图的TSEC和e1000网卡inte82546。 上图中的红色线就是以太网数据流,DMA与DDR打交道需要其他模块的协助,如TSEC,PCI controller 以太网数据在TSEc<-> DDR PCI Controller<->DDR之间的流动,CPU的core是不需要介入的 只有在数据流动结束时(接收完、发送完), DMA Engine才会以外部中断的方式告诉cPU的core 二、 DMA Engine tatus Control Length First BD DMA Engine Buffer pointer Fetch BD update BD 中 Mowe data between syst and FIFo Generate intermot to core Status Control(w) Last bd Len Buffer pointer R FIFO FIFO Date butt MAC System memor PHY 上面是 DMA Engine的框图,以接收为例: 1.在 System memory中为DMA开辟一端连续空间,用来BD数组(一致性dma内存)

...展开详情
试读 21P Linux网络数据包收发流程
立即下载 低至0.43元/次 身份认证VIP会员低至7折
一个资源只可评论一次,评论内容不能少于5个字
wensonsz 很好,代码有点难。 不过很好的资料了
2014-04-03
回复
f348235875 讲解很详细,代码级别初看比较艰难
2013-12-13
回复
warning310 材料不错,各个层次讲解都比较细致,推荐!
2013-09-11
回复
mft05045128 不错,对于新手学习很有用。
2013-09-10
回复
不想当程序猿的码农 不错,对学习很有用
2013-07-22
回复
您会向同学/朋友/同事推荐我们的CSDN下载吗?
谢谢参与!您的真实评价是我们改进的动力~
关注 私信
上传资源赚钱or赚积分
最新推荐
Linux网络数据包收发流程 50积分/C币 立即下载
1/21
Linux网络数据包收发流程第1页
Linux网络数据包收发流程第2页
Linux网络数据包收发流程第3页
Linux网络数据包收发流程第4页
Linux网络数据包收发流程第5页

试读结束, 可继续读2页

50积分/C币 立即下载 >