Receiving matching function _ napi_gro_receive (napi, skb) of The Link Layer ):
This function matches messages and does not merge messages.
The matching rule must meet both of the following conditions ):
1. The received dev packets must be the same.
2. The two packets must have the same Ethernet header.
Static int _ napi_gro_receive (struct napi_struct * napi, struct sk_buff * skb) {struct sk_buff * p;/* traverses the skb mounted on the gro_list on the napi instance, set the same field */for (p = napi-> gro_list; p = p-> next) {NAPI_GRO_CB (p) -> same_flow = (p-> dev = skb-> dev )&&! Compare_ether_header (skb_mac_header (p), skb_gro_mac_header (skb); NAPI_GRO_CB (p)-> flush = 0;} return dev_gro_receive (napi, skb );}
Int dev_gro_receive (struct napi_struct * napi, struct sk_buff * skb) {struct sk_buff ** pp = NULL; struct packet_type * ptype; _ be16 type = skb-> protocol; struct list_head * head = & ptype_base [ntohs (type) & PTYPE_HASH_MASK]; int same_flow; int mac_len; int ret;/* If the receiving network device is set to not support GRO, no GRO merge processing */if (! (Skb-> dev-> features & NETIF_F_GRO) {goto normal;}/* If the ip address is a multipart packet, GRO is not processed, * In the ip layer, the ip segment packets are merged */if (skb_is_gso (skb) | skb_has_frags (skb) {goto normal ;} /* Add the RCU read lock to protect the ptype_base hahs linked list */rcu_read_lock ();/* The traversal chain table to find the ptype that processes this type of packets, * This type of ptype implements the gro processing function */list_for_each_entry_rcu (ptype, head, list) {if (ptype-> type! = Type | ptype-> dev |! Ptype-> gro_receive) continue;/* If found, initialize the packet header pointer, * and reset the private field used by GRO in skb, * These fields will be set in the GRO handler implemented by the corresponding protocol */skb_set_network_header (skb, skb_gro_offset (skb); mac_len = skb-> network> _header-skb-> mac_header; skb-> mac_len = mac_len; NAPI_GRO_CB (skb)-> same_flow = 0; NAPI_GRO_CB (skb)-> flush = 0; NAPI_GRO_CB (skb)-> free = 0; /* call the GRO processing function registered for this protocol type to process packets */pp = ptype-> gro_receive (& napi-> gro_list, skb); break;} rcu _ Read_unlock ();/* if the GRO for processing the protocol type message is not found, GRO operations are not performed */if (& ptype-> list = head) {goto normal;} same_flow = NAPI_GRO_CB (skb)-> same_flow; ret = NAPI_GRO_CB (skb)-> free? GRO_MERGED_FREE: GRO_MERGED;/* if the GRO processing function of the Protocol returns the merged packet, * Call napi_gro_complete to send the packet to the protocol stack for processing */if (pp) {struct sk_buff * nskb = * pp; * pp = nskb-> next; nskb-> next = NULL; napi_gro_complete (nskb); napi-> gro_count --;} /* if the same is set, it indicates that a matched message is found on the linked list. * The message has been merged and no longer needs to be cached */if (same_flow) {goto OK;}/* If the matched message is not found, it must be cached. * Determine whether the queue is full or whether the message should be cached */if (NAPI_GRO_CB (skb)-> flush | napi-> gro_count> = MAX_GRO_SKBS) {goto normal ;} /* No matched packets are cached to gro_list, and the returned value is GRO_HELD */napi-> gro_count ++; NAPI_GRO_CB (skb)-> count = 1; skb_shinfo (skb) -> gso_size = skb_gro_len (skb); skb-> next = napi-> gro_list; napi-> gro_list = skb; ret = GRO_HELD; pull: /* after GRO receive processing of this protocol stack, * the NAPI_GRO_CB (skb)-> data_offset field has been set. * If the data to be processed by GRO is not in the skb linear zone, * copy the required data to the linear zone to facilitate subsequent operations */if (skb_headlen (skb) <skb_gro_offset (skb )) {int grow = skb_gro_offset (skb)-skb_headlen (skb); BUG_ON (skb-> end-skb-> tail <group); memcpy (skb_tail_pointer (skb), NAPI_GRO_CB (skb) -> frag0, grow); skb-> tail + = grow; skb-> data_len-= grow; skb_shinfo (skb)-> frags [0]. page_offset + = grow; skb_shinfo (skb)-> frags [0]. size-= grow;/* if the data is moved to the linear zone, the first page is blank. * release null. Page and move the subsequent pages forward in turn */if (unlikely (! Skb_shinfo (skb)-> frags [0]. size) {put_page (skb_shinfo (skb)-> frags [0]. page); memmove (skb_shinfo (skb)-> frags, skb_shinfo (skb)-> frags + 1, (-- skb_shinfo (skb) -> nr_frags * sizeof (skb_frag_t);} OK: return ret; normal: ret = GRO_NORMAL; goto pull ;}
GRO completion function of Link Layer:
The merged packets call this function to send messages to the protocol stack.
Static int napi_gro_complete (struct sk_buff * skb) {struct packet_type * ptype; _ be16 type = skb-> protocol; struct list_head * head = & ptype_base [ntohs (type) & PTYPE_HASH_MASK]; int err =-ENOENT;/* if it has not been merged with other packets, * the protocol stack can be directly sent for processing */if (NAPI_GRO_CB (skb) -> count = 1) {skb_shinfo (skb)-> gso_size = 0; goto out ;} /* Find the grp_complete function for sending packets to the Protocol */rcu_read_lock (); list_for_each_entry_rcu (ptype, head, lis T) {if (ptype-> type! = Type | ptype-> dev |! Ptype-> gro_complete) continue; err = ptype-> gro_complete (skb); break;} rcu_read_unlock (); if (err) {WARN_ON (& ptype-> list = head); kfree_skb (skb); return NET_RX_SUCCESS;}/* Send the layer-Layer Protocol to the Protocol Stack for processing */out: return netif_receive_skb (skb );}
This article is from the "Yao Yang blog" blog, please be sure to keep this source http://yaoyang.blog.51cto.com/7657153/1303144