net: Add a software TSO helper API
[deliverable/linux.git] / net / core / tso.c
CommitLineData
e876f208
EG
1#include <net/ip.h>
2#include <net/tso.h>
3
4/* Calculate expected number of TX descriptors */
5int tso_count_descs(struct sk_buff *skb)
6{
7 /* The Marvell Way */
8 return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags;
9}
10
11void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
12 int size, bool is_last)
13{
14 struct iphdr *iph;
15 struct tcphdr *tcph;
16 int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
17 int mac_hdr_len = skb_network_offset(skb);
18
19 memcpy(hdr, skb->data, hdr_len);
20 iph = (struct iphdr *)(hdr + mac_hdr_len);
21 iph->id = htons(tso->ip_id);
22 iph->tot_len = htons(size + hdr_len - mac_hdr_len);
23 tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb));
24 tcph->seq = htonl(tso->tcp_seq);
25 tso->ip_id++;
26
27 if (!is_last) {
28 /* Clear all special flags for not last packet */
29 tcph->psh = 0;
30 tcph->fin = 0;
31 tcph->rst = 0;
32 }
33}
34
35void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size)
36{
37 tso->tcp_seq += size;
38 tso->size -= size;
39 tso->data += size;
40
41 if ((tso->size == 0) &&
42 (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
43 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
44
45 /* Move to next segment */
46 tso->size = frag->size;
47 tso->data = page_address(frag->page.p) + frag->page_offset;
48 tso->next_frag_idx++;
49 }
50}
51
52void tso_start(struct sk_buff *skb, struct tso_t *tso)
53{
54 int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
55
56 tso->ip_id = ntohs(ip_hdr(skb)->id);
57 tso->tcp_seq = ntohl(tcp_hdr(skb)->seq);
58 tso->next_frag_idx = 0;
59
60 /* Build first data */
61 tso->size = skb_headlen(skb) - hdr_len;
62 tso->data = skb->data + hdr_len;
63 if ((tso->size == 0) &&
64 (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
65 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
66
67 /* Move to next segment */
68 tso->size = frag->size;
69 tso->data = page_address(frag->page.p) + frag->page_offset;
70 tso->next_frag_idx++;
71 }
72}
This page took 0.0385 seconds and 5 git commands to generate.