~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/core/tso.c

Version: ~ [ linux-5.18 ] ~ [ linux-5.17.9 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.41 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.117 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.195 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.244 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.280 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.315 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <linux/export.h>
  3 #include <linux/if_vlan.h>
  4 #include <net/ip.h>
  5 #include <net/tso.h>
  6 #include <asm/unaligned.h>
  7 
  8 /* Calculate expected number of TX descriptors */
  9 int tso_count_descs(const struct sk_buff *skb)
 10 {
 11         /* The Marvell Way */
 12         return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags;
 13 }
 14 EXPORT_SYMBOL(tso_count_descs);
 15 
 16 void tso_build_hdr(const struct sk_buff *skb, char *hdr, struct tso_t *tso,
 17                    int size, bool is_last)
 18 {
 19         int hdr_len = skb_transport_offset(skb) + tso->tlen;
 20         int mac_hdr_len = skb_network_offset(skb);
 21 
 22         memcpy(hdr, skb->data, hdr_len);
 23         if (!tso->ipv6) {
 24                 struct iphdr *iph = (void *)(hdr + mac_hdr_len);
 25 
 26                 iph->id = htons(tso->ip_id);
 27                 iph->tot_len = htons(size + hdr_len - mac_hdr_len);
 28                 tso->ip_id++;
 29         } else {
 30                 struct ipv6hdr *iph = (void *)(hdr + mac_hdr_len);
 31 
 32                 iph->payload_len = htons(size + tso->tlen);
 33         }
 34         hdr += skb_transport_offset(skb);
 35         if (tso->tlen != sizeof(struct udphdr)) {
 36                 struct tcphdr *tcph = (struct tcphdr *)hdr;
 37 
 38                 put_unaligned_be32(tso->tcp_seq, &tcph->seq);
 39 
 40                 if (!is_last) {
 41                         /* Clear all special flags for not last packet */
 42                         tcph->psh = 0;
 43                         tcph->fin = 0;
 44                         tcph->rst = 0;
 45                 }
 46         } else {
 47                 struct udphdr *uh = (struct udphdr *)hdr;
 48 
 49                 uh->len = htons(sizeof(*uh) + size);
 50         }
 51 }
 52 EXPORT_SYMBOL(tso_build_hdr);
 53 
 54 void tso_build_data(const struct sk_buff *skb, struct tso_t *tso, int size)
 55 {
 56         tso->tcp_seq += size; /* not worth avoiding this operation for UDP */
 57         tso->size -= size;
 58         tso->data += size;
 59 
 60         if ((tso->size == 0) &&
 61             (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
 62                 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
 63 
 64                 /* Move to next segment */
 65                 tso->size = skb_frag_size(frag);
 66                 tso->data = skb_frag_address(frag);
 67                 tso->next_frag_idx++;
 68         }
 69 }
 70 EXPORT_SYMBOL(tso_build_data);
 71 
 72 int tso_start(struct sk_buff *skb, struct tso_t *tso)
 73 {
 74         int tlen = skb_is_gso_tcp(skb) ? tcp_hdrlen(skb) : sizeof(struct udphdr);
 75         int hdr_len = skb_transport_offset(skb) + tlen;
 76 
 77         tso->tlen = tlen;
 78         tso->ip_id = ntohs(ip_hdr(skb)->id);
 79         tso->tcp_seq = (tlen != sizeof(struct udphdr)) ? ntohl(tcp_hdr(skb)->seq) : 0;
 80         tso->next_frag_idx = 0;
 81         tso->ipv6 = vlan_get_protocol(skb) == htons(ETH_P_IPV6);
 82 
 83         /* Build first data */
 84         tso->size = skb_headlen(skb) - hdr_len;
 85         tso->data = skb->data + hdr_len;
 86         if ((tso->size == 0) &&
 87             (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
 88                 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
 89 
 90                 /* Move to next segment */
 91                 tso->size = skb_frag_size(frag);
 92                 tso->data = skb_frag_address(frag);
 93                 tso->next_frag_idx++;
 94         }
 95         return hdr_len;
 96 }
 97 EXPORT_SYMBOL(tso_start);
 98 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp