/*更新整個lro skb的相關數據*/
static void lro_add_common(struct net_lro_desc *lro_desc, struct iphdr *iph,
struct tcphdr *tcph, int tcp_data_len)
{
struct sk_buff *parent = lro_desc->parent;
__be32 *topt;
lro_desc->pkt_aggr_cnt++;
lro_desc->ip_tot_len += tcp_data_len;
lro_desc->tcp_next_seq += tcp_data_len;
lro_desc->tcp_window = tcph->window;
lro_desc->tcp_ack = tcph->ack_seq;
/* don't update tcp_rcv_tsval, would not work with PAWS */
if (lro_desc->tcp_saw_tstamp) {
topt = (__be32 *) (tcph + 1);
lro_desc->tcp_rcv_tsecr = *(topt + 2);
}
lro_desc->data_csum = csum_block_add(lro_desc->data_csum,
lro_tcp_data_csum(iph, tcph,
tcp_data_len),
parent->len);
parent->len += tcp_data_len;
parent->data_len += tcp_data_len;
if (tcp_data_len > lro_desc->mss)
lro_desc->mss = tcp_data_len;
}
/*向LRO skb中添加一個新的skb*/
static void lro_add_packet(struct net_lro_desc *lro_desc, struct sk_buff *skb,
struct iphdr *iph, struct tcphdr *tcph)
{
struct sk_buff *parent = lro_desc->parent;
int tcp_data_len = TCP_PAYLOAD_LENGTH(iph, tcph);
lro_add_common(lro_desc, iph, tcph, tcp_data_len);
/*更新該skb的data 長度,需要除去header部分長度*/
skb_pull(skb, (skb->len - tcp_data_len));
/*更新整個lro skb的總長度*/
parent->truesize += skb->truesize;
/*將skb掛接在lro skb的 frag_list上面。*/
if (lro_desc->last_skb)
lro_desc->last_skb->next = skb;
else
skb_shinfo(parent)->frag_list = skb;
lro_desc->last_skb = skb;
}
/*向一個skb添加帶frags的數據包; 支持分散、聚合的dma, 一個數據可能由多個skb_frags組成。*/
static void lro_add_frags(struct net_lro_desc *lro_desc,
int len, int hlen, int truesize,
struct skb_frag_struct *skb_frags,
struct iphdr *iph, struct tcphdr *tcph)
{
struct sk_buff *skb = lro_desc->parent;
int tcp_data_len = TCP_PAYLOAD_LENGTH(iph, tcph);
lro_add_common(lro_desc, iph, tcph, tcp_data_len);
skb->truesize += truesize;
/*去掉該skb包的header部分, 而該header應該保存在第一個frags數據中。*/
skb_frags[0].page_offset += hlen;
skb_frags[0].size -= hlen;
/*將page部分的數據,直接保存到skb的frags中*/
while (tcp_data_len > 0) {
*(lro_desc->next_frag) = *skb_frags;
tcp_data_len -= skb_frags->size;
lro_desc->next_frag++;
skb_frags++;
skb_shinfo(skb)->nr_frags++;
}
}