数据帧收发主要函数及netdevice 结构Word文件下载.docx

上传人:b****1 文档编号:5846620 上传时间:2023-05-05 格式:DOCX 页数:23 大小:22.26KB
下载 相关 举报
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第1页
第1页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第2页
第2页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第3页
第3页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第4页
第4页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第5页
第5页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第6页
第6页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第7页
第7页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第8页
第8页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第9页
第9页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第10页
第10页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第11页
第11页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第12页
第12页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第13页
第13页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第14页
第14页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第15页
第15页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第16页
第16页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第17页
第17页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第18页
第18页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第19页
第19页 / 共23页
数据帧收发主要函数及netdevice 结构Word文件下载.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

数据帧收发主要函数及netdevice 结构Word文件下载.docx

《数据帧收发主要函数及netdevice 结构Word文件下载.docx》由会员分享,可在线阅读,更多相关《数据帧收发主要函数及netdevice 结构Word文件下载.docx(23页珍藏版)》请在冰点文库上搜索。

数据帧收发主要函数及netdevice 结构Word文件下载.docx

local_irq_save(flags);

queue=&

__get_cpu_var(softnet_data);

//获取当前cpu的softnet_data数据

__get_cpu_var(netdev_rx_stat).total++;

//当前cpu接收的帧数+1

if(queue->

input_pkt_queue.qlen<

=netdev_max_backlog){

//监测设备是否还有空间来存储帧,如果空间已满,表示网络阻塞严重,则返回一个错误,此后cpu将丢掉再来的帧。

input_pkt_queue.qlen){

enqueue:

//将该帧加入到softnet_data队列

__skb_queue_tail(&

queue->

input_pkt_queue,skb);

local_irq_restore(flags);

returnnet_rx_success;

}

//当队列是空的时候,表明这个队列并没有被软中断所schedule,因此我们需要将此队列加入到软中断的处理链表中。

可以看到加入的正好是backlog,由于调用netif_rx的是非napi的驱动,因此backlog就是初始化时的process_backlog函数。

napi_schedule(&

backlog);

gotoenqueue;

__get_cpu_var(netdev_rx_stat).dropped++;

kfree_skb(skb);

}

//上面代码中用到一个关键的数据结构softnet_data,在网卡收发数据的时候,需要维护一个缓冲区队列,来缓存可能存在的突发数据,在协议栈中用一个队列层来表示该缓冲区,队列层位于数据链路层和网络层之间。

softnet_data就是数据链路层中的数据结构,它是一个per-cpu变量,每个cpu都有一个

/**

*netif_receive_skb-processreceivebufferfromnetwork

buffertoprocess

*netif_receive_skb()isthemainreceivedataprocessingfunction.

*italwayssucceeds.thebuffermaybedroppedduringprocessing

*forcongestioncontrolorbytheprotocollayers.

*thisfunctionmayonlybecalledfromsoftirqcontextandinterrupts

*shouldbeenabled.

*returnvalues(usuallyignored):

*net_rx_success:

nocongestion

*net_rx_drop:

packetwasdropped

//netif_receive_skb是对于netif_rx的napi对等函数;

它递交一个报文给内核.当一个napi兼容的驱动已耗尽接收报

文的供应,它应当重开中断,并且调用netif_rx_complete(现在是__napi_complete())来停止轮询.

intnetif_receive_skb(structsk_buff*skb)

structpacket_type*ptype,*pt_prev;

structnet_device*orig_dev;

structnet_device*master;

structnet_device*null_or_orig;

structnet_device*null_or_bond;

intret=net_rx_drop;

__be16type;

tstamp.tv64)

if(vlan_tx_tag_present(skb)&

&

vlan_hwaccel_do_receive(skb))

/*ifwe'

vegottenherethroughnapi,checknetpoll*/

if(netpoll_receive_skb(skb))

skb_iif)

skb->

skb_iif=skb->

dev->

ifindex;

//记录帧的入口

null_or_orig=null;

orig_dev=skb->

dev;

master=access_once(orig_dev->

master);

if(master){

if(skb_bond_should_drop(skb,master))

null_or_orig=orig_dev;

/*deliveronlyexactmatch*/

else

dev=master;

skb_reset_network_header(skb);

skb_reset_transport_header(skb);

mac_len=skb->

network_header-skb->

mac_header;

pt_prev=null;

rcu_read_lock();

#ifdefconfig_net_cls_act

if(skb->

tc_verd&

tc_ncls){

tc_verd=clr_tc_ncls(skb->

tc_verd);

gotoncls;

#endif

//处理ptype_all上所有的packet_type->

func(),这里先提一下linux是根据packet_type通过dev_add_pack()函数来注册相应的处理函数,后面会讲如何注册,每种包对应哪个处理函数

//staticstructlist_headptype_all__read_mostly;

list_for_each_entry_rcu(ptype,&

ptype_all,list){

if(ptype->

dev==null_or_orig||ptype->

dev==skb->

dev||

ptype->

dev==orig_dev){

if(pt_prev)

ret=deliver_skb(skb,pt_prev,orig_dev);

//调用相应的包处理函数

pt_prev=ptype;

skb=handle_ing(skb,&

pt_prev,&

ret,orig_dev);

skb)

gotoout;

ncls:

//若编译内核时选上bridge,下面会执行网桥模块

skb=handle_bridge(skb,&

//编译内核时选上mac_vlan模块,下面才会执行

skb=handle_macvlan(skb,&

*makesureframesreceivedonvlaninterfacesstackedon

*bondinginterfacesstillmaketheirwaytoanybasebonding

*devicethatmayhaveregisteredforaspecificptype.the

*handlermayhavetoadjustskb->

devandorig_dev.

null_or_bond=null;

if((skb->

priv_flags&

iff_802_1q_vlan)&

(vlan_dev_real_dev(skb->

dev)->

iff_bonding)){

null_or_bond=vlan_dev_real_dev(skb->

dev);

//最后type=skb->

protocol;

&

ptype_base[ntohs(type)&

15]处理ptype_base[ntohs(type)&

15]上的所有的packet_type->

func(),根据第二层不同协议来进入不同的钩子函数,重要的有:

ip_rcv(),arp_rcv()

type=skb->

protocol;

list_for_each_entry_rcu(ptype,

ptype_base[ntohs(type)&

ptype_hash_mask],list){

type==type&

(ptype->

dev==null_or_orig||

dev||ptype->

dev==orig_dev||

dev==null_or_bond)){

if(pt_prev){

ret=pt_prev->

func(skb,skb->

dev,pt_prev,orig_dev);

}else{

/*jamal,nowyouwillnotabletoescapeexplaining

*mehowyouweregoingtousethis.:

-)

ret=net_rx_drop;

out:

rcu_read_unlock();

returnret;

*dev_queue_xmit-transmitabuffer

buffertotransmit

*queueabufferfortransmissiontoanetworkdevice.thecallermust

*havesetthedeviceandpriorityandbuiltthebufferbeforecalling

*thisfunction.thefunctioncanbecalledfromaninterrupt.

*anegativeerrnocodeisreturnedonafailure.asuccessdoesnot

*guaranteetheframewillbetransmittedasitmaybedroppeddue

*tocongestionortrafficshaping.

*-----------------------------------------------------------------------------------

*inoticethismethodcanalsoreturnerrorsfromthequeuedisciplines,

*includingnet_xmit_drop,whichisapositivevalue.so,errorscanalso

*bepositive.

*regardlessofthereturnvalue,theskbisconsumed,soitiscurrently

*difficulttoretryasendtothismethod.(youcanbumptherefcount

*beforesendingtoholdareferenceforretryifyouarecareful.)

*whencallingthismethod,interruptsmustbeenabled.thisisbecause

*thebhenablecodemusthaveirqsenabledsothatitwillnotdeadlock.

*--blg

intdev_queue_xmit(structsk_buff*skb)

structnet_device*dev=skb->

structnetdev_queue*txq;

structqdisc*q;

intrc=-enomem;

/*gsowillhandlethefollowingemulationsdirectly.*/

if(netif_needs_gso(dev,skb))//如果是gso数据包,且设备支持gso数据包的处理

gotogso;

/*convertapagedskbtolinear,ifrequired*/

if(skb_needs_linearize(skb,dev)&

__skb_linearize(skb))

gotoout_kfree_skb;

/*ifpacketisnotchecksummedanddevicedoesnotsupport

*checksummingforthisprotocol,completechecksumminghere.

ip_summed==checksum_partial){

skb_set_transport_header(skb,skb->

csum_start-

skb_headroom(skb));

dev_can_checksum(dev,skb)&

skb_checksum_help(skb))

gso:

/*disablesoftirqsforvariouslocksbelow.also

*stopspreemptionforrcu.

rcu_read_lock_bh();

txq=dev_pick_tx(dev,skb);

q=rcu_dereference_bh(txq->

qdisc);

tc_verd=set_tc_at(skb->

tc_verd,at_egress);

if(q->

enqueue){

rc=__dev_xmit_skb(skb,q,dev,txq);

/*thedevicehasnoqueue.commoncaseforsoftwaredevices:

loopback,allthesortsoftunnels...

really,itisunlikelythatnetif_tx_lockprotectionisnecessary

here.(f.e.loopbackandiptunnelsarecleanignoringstatistics

counters.)

however,itispossible,thattheyrelyonprotection

madebyushere.

checkthisandshotthelock.itisnotpronefromdeadlocks.

eithershotnoqueueqdisc,itisevensimpler8)

if(dev->

flags&

iff_up){

intcpu=smp_processor_id();

/*okbecausebhsareoff*/

if(txq->

xmit_lock_owner!

=cpu){

hard_tx_lock(dev,txq,cpu);

netif_tx_queue_stopped(txq)){

rc=dev_hard_start_xmit(skb,dev,txq);

if(dev_xmit_complete(rc)){

hard_tx_unlock(dev,txq);

if(net_ratelimit())

printk(kern_crit"

virtualdevice%sasksto"

"

queuepacket!

\n"

dev->

name);

/*recursionisdetected!

itispossible,

*unfortunately*/

deadlooponvirtualdevice"

%s,fixiturgently!

rc=-enetdown;

rcu_read_unlock_bh();

out_kfree_skb:

returnrc;

数据链路层不得不谈到structnet_device相关结构,在2.6.29之后net_device结构进行了调整,操作函数被重构到了net_device_ops中。

下面简要分析一下:

structnet_device

/*

thisfirstfield,name,isthebeginningofthevisiblepartofthisstructure.itcontainsthestring

thatisthenameoftheinterface.byvisible,wemeanthatthispartofthedatastructureisgeneric

anddoesn’tcontainanyprivateareasspecifictoaparticulartypeofdevice.

*/

charname[ifnamsiz];

/*devicenamehashchain*/

structhlist_nodename_hlist;

/*snmpalias*/

char*ifalias;

*i/ospecificfields

*fixme:

mergetheseandstructifmapintoone

unsignedlongmem_end;

/*sharedmemend*/

unsignedlongmem_start;

/*sharedmemstart*/

unsignedlongbase_addr;

/*devicei/oaddress*/

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2