1 #include <linux/export.h>
4 #include <asm/unaligned.h>
6 /* Calculate expected number of TX descriptors */
7 int tso_count_descs(struct sk_buff
*skb
)
10 return skb_shinfo(skb
)->gso_segs
* 2 + skb_shinfo(skb
)->nr_frags
;
12 EXPORT_SYMBOL(tso_count_descs
);
14 void tso_build_hdr(struct sk_buff
*skb
, char *hdr
, struct tso_t
*tso
,
15 int size
, bool is_last
)
19 int hdr_len
= skb_transport_offset(skb
) + tcp_hdrlen(skb
);
20 int mac_hdr_len
= skb_network_offset(skb
);
22 memcpy(hdr
, skb
->data
, hdr_len
);
23 iph
= (struct iphdr
*)(hdr
+ mac_hdr_len
);
24 iph
->id
= htons(tso
->ip_id
);
25 iph
->tot_len
= htons(size
+ hdr_len
- mac_hdr_len
);
26 tcph
= (struct tcphdr
*)(hdr
+ skb_transport_offset(skb
));
27 put_unaligned_be32(tso
->tcp_seq
, &tcph
->seq
);
31 /* Clear all special flags for not last packet */
37 EXPORT_SYMBOL(tso_build_hdr
);
39 void tso_build_data(struct sk_buff
*skb
, struct tso_t
*tso
, int size
)
45 if ((tso
->size
== 0) &&
46 (tso
->next_frag_idx
< skb_shinfo(skb
)->nr_frags
)) {
47 skb_frag_t
*frag
= &skb_shinfo(skb
)->frags
[tso
->next_frag_idx
];
49 /* Move to next segment */
50 tso
->size
= frag
->size
;
51 tso
->data
= page_address(frag
->page
.p
) + frag
->page_offset
;
55 EXPORT_SYMBOL(tso_build_data
);
57 void tso_start(struct sk_buff
*skb
, struct tso_t
*tso
)
59 int hdr_len
= skb_transport_offset(skb
) + tcp_hdrlen(skb
);
61 tso
->ip_id
= ntohs(ip_hdr(skb
)->id
);
62 tso
->tcp_seq
= ntohl(tcp_hdr(skb
)->seq
);
63 tso
->next_frag_idx
= 0;
65 /* Build first data */
66 tso
->size
= skb_headlen(skb
) - hdr_len
;
67 tso
->data
= skb
->data
+ hdr_len
;
68 if ((tso
->size
== 0) &&
69 (tso
->next_frag_idx
< skb_shinfo(skb
)->nr_frags
)) {
70 skb_frag_t
*frag
= &skb_shinfo(skb
)->frags
[tso
->next_frag_idx
];
72 /* Move to next segment */
73 tso
->size
= frag
->size
;
74 tso
->data
= page_address(frag
->page
.p
) + frag
->page_offset
;
78 EXPORT_SYMBOL(tso_start
);