2.6.24.4 Kernel Network Received Packet Analysis

In 2.6.24.4, all network cards, whether they support napi or not, use the struct napi_struct structure. So let's talk about this structure first.

struct napi_struct{

   struct list_head poll_list;

   unsigned long state;

   int weight;

   int (*poll)(struct napi_struct *,int);

}

Corresponding to the network card that supports napi, fill in this structure by yourself; instead of the napi network card, use the softnet_data>backlog of per cpu, and the initialization of this structure is completed in net_dev_init().

Let's talk about the network card of the non-napi mechanism first:

    After the network card receives the data packet, DMA goes to the kernel space, and then calls netif_rx() to hook the data packet to softnet_data>input_pkt_queue. If the napi_struct of backlog is not scheduled, napi_schedule(&backlog).napi_schedule() will hang the poll_list of backlog Received on softnet_data->poll_list, and start soft interrupt NET_RX_SOFTIRQ at the same time. NET_RX_SOFTIRQ soft interrupt, call the corresponding function net_rx_action().

The network card corresponding to the napi mechanism:

     When the network card is initialized, it will initialize its own data packet receiving queue and put the receiving agent in the poll_list. When a data packet arrives, it will dma the data packet to its own data packet queue. NET_RX_SOFTIRQ soft interrupt, call the corresponding function net_rx_action().

 

net_rx_action():

    First get softnet_data->poll_list, traverse poll_list, get the napi_struct structure corresponding to each poll_list (container_of implementation), and then call the poll function according to the weight of napi_struct, if it is a non-napi network card, the napi_struct here is backlog, so the poll function is process_backlog; If it is a napi network card, it will make its own poll function.

The poll function of the napi network card is to dequeue a skb from its own packet queue, and then call netif_receive_skb().

The non-napi process_backlog will get softnet_data->input_pkt_queue, then dequeue the queue input_pkt_queue, get a skb, and then call netif_receive_skb(skb).

netif_receive_skb():

    Do some preparatory work for skb, such as setting mac_len, etc., call deliver_skb() to handle handles for all registered ptype_all types of protocols, then handle bridges and VLANs, and then give the handle of the registered ptype_base of the corresponding protocol. Assuming that the ip protocol is used here, the processing function ip_rcv of the corresponding ip protocol handle will be called.

ip_rcv():

    Do some checks on skb, if skb->users!=1, clone a skb, and then transfer to the hook point of NF_IP_PRE_ROUTING of netfilter, and call all hook functions registered at this point. For example, if conntrack is enabled, packet reassembly will be performed here. Then call ip_rcv_finish().

ip_rcv_finish():

    First call ip_route_input() to determine the route of the packet, initialize skb->dst, and call dst_input(skb).

dst_input():

    In fact, skb->dst->input(skb) is called, and the initialization of the corresponding input is in route.c. If it is a local packet dst->input=ip_local_deliver; if it is a forwarded packet dst->input=ip_forward;

Local process:

ip_local_deliver():

    The first is the reassembly of the fragmented data packets, which will be transferred to the hook point of NF_IP_LOCAL_IN of netfilter, and all hook functions registered at this point will be called. After that, ip_local_deliver_finish() will be called, and then it will go to the fourth layer.

Forwarding process:

ip_forward():

    After doing some source routing checks, it will transfer to the hook point of NF_IP_FORWARD of netfilter, and call all hook functions registered at this point. Then ip_forward_finish() will be called.

ip_forward_finish():

    Call dst_output().

dst_output():

    skb->dst->output(skb).一般output=ip_output.

ip_output():

    Set the dev of skb as the dev of the package, and set skb->protocol at the same time, it will transfer to the hook point of NF_IP_POST_ROUTING of netfilter, and call all hook functions registered at this point. Then ip_finish_output() will be called.

ip_finish_output():

    Check whether the packet needs fragmentation. If fragmentation is required, perform ip_fragement(), and then call ip_finish_output2().

ip_finish_output2():

    根据neighbour,调用dst->neighbour->output.

So far, the data packet will be put into the dev's qdisc through dev_queue_xmit. Then there is the flow control out of the queue.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326968751&siteId=291194637
Recommended