root/net/core/tso.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tso_count_descs
  2. tso_build_hdr
  3. tso_build_data
  4. tso_start

   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(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(struct sk_buff *skb, char *hdr, struct tso_t *tso,
  17                    int size, bool is_last)
  18 {
  19         struct tcphdr *tcph;
  20         int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
  21         int mac_hdr_len = skb_network_offset(skb);
  22 
  23         memcpy(hdr, skb->data, hdr_len);
  24         if (!tso->ipv6) {
  25                 struct iphdr *iph = (void *)(hdr + mac_hdr_len);
  26 
  27                 iph->id = htons(tso->ip_id);
  28                 iph->tot_len = htons(size + hdr_len - mac_hdr_len);
  29                 tso->ip_id++;
  30         } else {
  31                 struct ipv6hdr *iph = (void *)(hdr + mac_hdr_len);
  32 
  33                 iph->payload_len = htons(size + tcp_hdrlen(skb));
  34         }
  35         tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb));
  36         put_unaligned_be32(tso->tcp_seq, &tcph->seq);
  37 
  38         if (!is_last) {
  39                 /* Clear all special flags for not last packet */
  40                 tcph->psh = 0;
  41                 tcph->fin = 0;
  42                 tcph->rst = 0;
  43         }
  44 }
  45 EXPORT_SYMBOL(tso_build_hdr);
  46 
  47 void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size)
  48 {
  49         tso->tcp_seq += size;
  50         tso->size -= size;
  51         tso->data += size;
  52 
  53         if ((tso->size == 0) &&
  54             (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
  55                 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
  56 
  57                 /* Move to next segment */
  58                 tso->size = skb_frag_size(frag);
  59                 tso->data = skb_frag_address(frag);
  60                 tso->next_frag_idx++;
  61         }
  62 }
  63 EXPORT_SYMBOL(tso_build_data);
  64 
  65 void tso_start(struct sk_buff *skb, struct tso_t *tso)
  66 {
  67         int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
  68 
  69         tso->ip_id = ntohs(ip_hdr(skb)->id);
  70         tso->tcp_seq = ntohl(tcp_hdr(skb)->seq);
  71         tso->next_frag_idx = 0;
  72         tso->ipv6 = vlan_get_protocol(skb) == htons(ETH_P_IPV6);
  73 
  74         /* Build first data */
  75         tso->size = skb_headlen(skb) - hdr_len;
  76         tso->data = skb->data + hdr_len;
  77         if ((tso->size == 0) &&
  78             (tso->next_frag_idx < skb_shinfo(skb)->nr_frags)) {
  79                 skb_frag_t *frag = &skb_shinfo(skb)->frags[tso->next_frag_idx];
  80 
  81                 /* Move to next segment */
  82                 tso->size = skb_frag_size(frag);
  83                 tso->data = skb_frag_address(frag);
  84                 tso->next_frag_idx++;
  85         }
  86 }
  87 EXPORT_SYMBOL(tso_start);

/* [<][>][^][v][top][bottom][index][help] */