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 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); }