Network package receiving process

xiaoxiao2021-03-06  63

1) NIC device driver receives the data frame in the hardware interrupt into the SK_BUFF structure, then check the hardware frame header.

Identify frame type,

Put it in the receiving queue, activate the reception soft interrupt for further processing. Receive a soft interrupt (NET_RX_ACTION) to extract the received package,

According to it

The device and protocol type are passed to the respective package processors. The package processor is registered with dev_add_pack ().

If the registered device number is

Zero indicates that it receives the package of all devices. If the registered package type is (eth_p_all), it means that it receives all types of packages.

in case

The system registers the package processor with (Eth_P_all) type.

The system will copy each send package by dev_queue_xmit_nit ()

The copy is passed to them.

Struct packet_type

{

UNSIGNED SHORT TYPE; / * This is really htons (ether_type). * /

Struct Net_Device * dev; / * null is Wildcarded Here * /

INT (* func) (struct SK_Buff *, Struct Net_Device *,

Struct packet_type *);

Void * data; / * private to the packet type * /

Struct packet_type * next;

}

NET / CORE / dev.c:

Static struct packet_type * ptype_base [16];

16-fold index chain table, package processor for ordinary registration types

Static struct packet_type * ptype_all =

NULL; the head of the listeners, the package processor for registration type eth_p_all

Static void net_rx_action (Struct Softirq_Action * H)

{

INT this_cpu = SMP_PROCESSOR_ID ();

Struct SoftNet_Data * Queue = & SoftNet_Data [this_cpu];

Unsigned long start_time = jiffies;

INT bugdet = netdev_max_backlog; maximum receiving queue length

BR_READ_LOCK (BR_NETPROTO_LOCK);

For (;;) {

Struct SK_Buff * SKB;

Struct Net_Device * rx_dev;

Local_IRQ_DISABLE ();

SKB = __skb_dequeue (& queue-> Input_pkt_queue);

Local_irq_enable ();

IF (SKB == NULL)

Break;

SKB_BOND (SKB); Re-binding the package with (SKB-> MASTER)

RX_DEV = SKB-> dev;

#ifdef config_net_faSTroute

IF (SKB-> PKT_TYPE == Packet_faster) {

NetDev_rx_stat [this_cpu] .faster_deferred_out ;

DEV_QUEUE_XMIT (SKB);

DEV_PUT (RX_DEV);

CONTINUE;

}

#ENDIF

SKB-> H.RAW = SKB-> nh.raw = SKB-> DATA; this time (SKB-> DATA) points to the end of the frame, starting the header

{

Struct packet_type * ptype, * pt_prev;

Unsigned short type = SKB-> Protocol;

PT_PREV = NULL;

For (ptype = ptype_all; ptype; ptype = ptype-> next) {if (! ptype-> dev || ptype-> dev == SKB-> dev) {

IF (pt_prev) {

IF (! pt_prev-> data) {

Deliver_to_old_ones (pt_prev, skb, 0); passed to the old package processor

} else {

Atomic_inc (& SKB-> Uses);

PT_PREV-> FUNC (SKB,

SKB-> DEV,

PT_PREV);

}

}

PT_PREV = Ptype;

}

}

#ifdef config_net_divert

IF (SKB-> dev-> Divert && Skb-> dev-> Divert-> Divert)

Handle_diverter (SKB);

#ENDIF / * Config_Net_Divert * /

#if defined (config_bridge) || Defined (config_bridge_module)

IF (SKB-> dev-> br_port! = null&&

BR_HANDLE_FRAME_HOK! = NULL) {

Handle_bridge (SKB, PT_PREV);

DEV_PUT (RX_DEV);

CONTINUE;

}

#ENDIF

For (ptype = ptype_base [ntohs (type) & 15]; ptype; ptype = ptype-> next) {

IF (ptype-> type == Type &&

(! ptype-> dev || ptype-> dev == SKB-> dev) {

IF (pt_prev) {

IF (! pt_prev-> data)

DELIVER_TO_OLD_ONES (PT_PREV, SKB, 0);

Else {

Atomic_inc (& SKB-> Uses);

PT_PREV-> FUNC (SKB,

SKB-> DEV,

PT_PREV);

}

}

PT_PREV = Ptype;

}

}

IF (pt_prev) {

IF (! pt_prev-> data)

Deliver_to_old_ones (pt_prev, skb, 1);

Else

PT_PREV-> FUNC (SKB, SKB-> DEV, PT_PREV);

Else

Kfree_skb (SKB);

}

DEV_PUT (RX_DEV);

IF (BugDet - <0 || Jiffies - Start_time> 1)

Goto softnet_break;

#ifdef config_net_hw_flowcontrol

IF (Queue-> THROTTLE && Queue-> Input_PKT_QUE.QLEN

IF (Atomic_Dec_and_test (& NetDev_Dropping) {

Queue-> throttle = 0;

NetDev_wakeup ();

Goto softnet_break;

}

}

#ENDIF

} The receiving package has all been processed.

BR_READ_UNLOCK (BR_NETPROTO_LOCK);

Local_IRQ_DISABLE ();

IF (Queue-> THROTTLE) {

Queue-> throttle = 0;

#ifdef config_net_hw_flowcontrolif (Atomic_Dec_and_test (& NetDev_Dropping))

NetDev_wakeup ();

#ENDIF

}

Local_irq_enable ();

NET_PROFILE_LEVE (SoftNet_Process);

Return;

SoftNet_break: The receiving package failed to handle

BR_READ_UNLOCK (BR_NETPROTO_LOCK);

Local_IRQ_DISABLE ();

NetDev_rx_stat [this_cpu] .time_squeeze ;

__CPU_RAISE_SOFTIRQ (this_cpu, net_rx_softirq); activate the reception soft interrupt again in order to continue processing next time

Local_irq_enable ();

NET_PROFILE_LEVE (SoftNet_Process);

Return;

}

Static Int Deliver_to_old_ones (Struct Packet_Type * Pt, Struct Sk_buff * SKB, INT LAST)

{

Static Spinlock_t Net_BH_LOCK = Spin_lock_unlocked;

INT RET = NET_RX_DROP;

IF (! last) {

SKB = SKB_CLONE (SKB, GFP_ATOMIC); Copy Pack Descriptor, Share its data buffer

IF (SKB == NULL)

Return Ret;

}

/ * The assumption (Correct One) Is That Old Protocols

DID NOT Dep Partened On BHS Different of Net_BH and Timer_BH.

* /

/ * Emulate net_bh with special spinlock * /

Spin_lock (& ​​NET_BH_LOCK);

/ * Disable Timers and Wait for all Timers completion * /

Tasklet_disable (BH_TASK_VEC TIMER_BH);

RET = Pt-> Func (SKB, SKB-> DEV, PT);

Tasklet_enable (BH_TASK_VEC TIMER_BH);

Spin_unlock (& ​​NET_BH_LOCK);

Return Ret;

}

Void dev_add_pack (struct packet_type * pt) registration package processor

{

Int hash;

BR_WRITE_LOCK_BH (BR_NETPROTO_LOCK);

#ifdef config_net_faSTroute

/ * Hack to Detect Packet Socket * /

IF (Pt-> DATA) {

NetDev_faSTroute_obstacles ;

DEV_CLEAR_FASTROUTE (PT-> dev);

}

#ENDIF

IF (Pt-> Type == HTONS (Eth_P_all)) {

NetDev_nit ;

Pt-> next = ptype_all;

PTYPE_ALL = Pt;

} else {

Hash = NTOHS (Pt-> Type) & 15;

Pt-> Next = ptype_base [hash];

Ptype_base [hash] = pt;

}

BR_WRITE_UNLOCK_BH (Br_NetProto_lock);

}

Void dev_queue_xmit_nit (Struct Sk_buff * SKB, STRUCT NET_DEVICE * DEV) {

Struct packet_type * ptype;

GET_FAST_TIME (& SKB-> stamp);

BR_READ_LOCK (BR_NETPROTO_LOCK);

For (ptype = ptype_all; ptype! = null; ptype = ptype-> next)

{

/ * Never send packets back to the socket

* They Originated from - MVS (Miquels@drinkel.ow.org)

* /

IF ((ptype-> dev == dev ||! ptype-> dev) &&&&

(Struct Sock *) ptype-> data! = SKB-> SK))

{

Struct SK_Buff * SKB2;

IF ((SKB2 = SKB_CLONE (SKB, GFP_ATOMIC) == NULL)

Break;

/ * SKB-> NH SHOULD BE CORRECTLY

Set by sender, so that the second statement is

Just Protection Against Buggy Protocols.

* /

SKB2-> mac.raw = SKB2-> DATA;

IF (SKB2-> NH.RAW Data || SKB2-> NH.RAW> = SKB2-> Tail) {

IF (Net_RATELIMIT ())

Printk (kern_debug "protocol% 04x is buggy, def% s / n", SKB2-> protocol, dev-> name);

SKB2-> nh.raw = SKB2-> DATA;

IF (dev-> hard_header)

SKB2-> nh.raw = dev-> hard_header_len;

}

SKB2-> H.RAW = SKB2-> nh.raw;

SKB2-> PKT_TYPE = packet_outgoing; package will be transmitted outward

PTYPE-> FUNC (SKB2, SKB-> dev, ptype);

}

}

BR_READ_UNLOCK (BR_NETPROTO_LOCK);

}

Net / ethernet / eth.c:

Unsigned short eth_type_trans (struct SK_Buff * SKB, STRUCT NET_DEVICE * DEV)

Identify Ethernet hardware frame header

{

Struct Ethhdr * Eth;

UNSIGNED Char * RAWP;

SKB-> mac.raw = SKB-> DATA; point to the received data frame

SKB_PULL (SKB, Dev-> HARD_HEADER_LEN); Retained hardware head address area

Eth = SKB-> mac.ethernet;

if (* Eth-> H_Dest & 1) Test the highest bit of the target address (connected network bit sequence, the highest valid bits are transmitted first)

{

IF (Memcmp (Eth-> h_dest, dev-> Broadcast, Eth_alent) == 0)

SKB-> PKT_TYPE = Packet_Broadcast; Received Broadcast Package

Else

SKB-> pkt_type = packet_multicast; receive the same broadcaster package

}

/ *

* This allmulti check shop be redundant by 1.4 * SO Don't forget to remove it.

*

* Seems, you forgot to remove it. All silly devices

* Seems to set iff_promisc.

* /

Else IF (1 / * dev-> flags & iff_promisc * /)

{

IF (Memcmp (Eth-> H_Dest, dev-> dev_addr, eth_alent))

SKB-> PKT_TYPE = packet_otherhost; receive packages from other hosts

}

IF (ntoh-> h_proto> = 1536)

Return Eth-> h_proto;

Rawp = SKB-> DATA;

/ *

* This is a magic holppy to spot ipx packets. Older Novell Breaks

* The Protocol Design and Runs IPX over 802.3 without AN 802.2 LLC

* Layer. WE LOOK for FFFF Which isn't a used 802.2 SSAP / DSAP. THIS

* Won't work for fault tolerant NetWare But Does for the REST.

* /

IF (* (unsigned short *) Rawp == 0xffff)

Return HTONS (Eth_P_802_3);

/ *

* Real 802.2 LLC

* /

Return HTONS (Eth_P_802_2);

}

转载请注明原文地址:https://www.9cbs.com/read-112885.html

New Post(0)