1 #include <linux/export.h>
2 #include <linux/if_vlan.h>
5 #include <asm/unaligned.h>
7 /* Calculate expected number of TX descriptors */
8 int tso_count_descs(struct sk_buff
*skb
)
11 return skb_shinfo(skb
)->gso_segs
* 2 + skb_shinfo(skb
)->nr_frags
;
13 EXPORT_SYMBOL(tso_count_descs
);
15 void tso_build_hdr(struct sk_buff
*skb
, char *hdr
, struct tso_t
*tso
,
16 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
);
24 struct iphdr
*iph
= (void *)(hdr
+ mac_hdr_len
);
26 iph
->id
= htons(tso
->ip_id
);
27 iph
->tot_len
= htons(size
+ hdr_len
- mac_hdr_len
);
30 struct ipv6hdr
*iph
= (void *)(hdr
+ mac_hdr_len
);
32 iph
->payload_len
= htons(size
+ tcp_hdrlen(skb
));
34 tcph
= (struct tcphdr
*)(hdr
+ skb_transport_offset(skb
));
35 put_unaligned_be32(tso
->tcp_seq
, &tcph
->seq
);
38 /* Clear all special flags for not last packet */
44 EXPORT_SYMBOL(tso_build_hdr
);
46 void tso_build_data(struct sk_buff
*skb
, struct tso_t
*tso
, int size
)
52 if ((tso
->size
== 0) &&
53 (tso
->next_frag_idx
< skb_shinfo(skb
)->nr_frags
)) {
54 skb_frag_t
*frag
= &skb_shinfo(skb
)->frags
[tso
->next_frag_idx
];
56 /* Move to next segment */
57 tso
->size
= frag
->size
;
58 tso
->data
= page_address(frag
->page
.p
) + frag
->page_offset
;
62 EXPORT_SYMBOL(tso_build_data
);
64 void tso_start(struct sk_buff
*skb
, struct tso_t
*tso
)
66 int hdr_len
= skb_transport_offset(skb
) + tcp_hdrlen(skb
);
68 tso
->ip_id
= ntohs(ip_hdr(skb
)->id
);
69 tso
->tcp_seq
= ntohl(tcp_hdr(skb
)->seq
);
70 tso
->next_frag_idx
= 0;
71 tso
->ipv6
= vlan_get_protocol(skb
) == htons(ETH_P_IPV6
);
73 /* Build first data */
74 tso
->size
= skb_headlen(skb
) - hdr_len
;
75 tso
->data
= skb
->data
+ hdr_len
;
76 if ((tso
->size
== 0) &&
77 (tso
->next_frag_idx
< skb_shinfo(skb
)->nr_frags
)) {
78 skb_frag_t
*frag
= &skb_shinfo(skb
)->frags
[tso
->next_frag_idx
];
80 /* Move to next segment */
81 tso
->size
= frag
->size
;
82 tso
->data
= page_address(frag
->page
.p
) + frag
->page_offset
;
86 EXPORT_SYMBOL(tso_start
);