Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8941faa1 authored by emmanuel.grumbach@intel.com's avatar emmanuel.grumbach@intel.com Committed by David S. Miller
Browse files

net: tso: add support for IPv6



Adding IPv6 for the TSO helper API is trivial:
* Don't play with the id (which doesn't exist in IPv6)
* Correctly update the payload_len (don't include the
  length of the IP header itself)

Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 61b9da92
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -8,6 +8,7 @@ struct tso_t {
	void *data;
	void *data;
	size_t size;
	size_t size;
	u16 ip_id;
	u16 ip_id;
	bool ipv6;
	u32 tcp_seq;
	u32 tcp_seq;
};
};


+13 −5
Original line number Original line Diff line number Diff line
#include <linux/export.h>
#include <linux/export.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/ip.h>
#include <net/tso.h>
#include <net/tso.h>
#include <asm/unaligned.h>
#include <asm/unaligned.h>
@@ -14,18 +15,24 @@ EXPORT_SYMBOL(tso_count_descs);
void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
		   int size, bool is_last)
		   int size, bool is_last)
{
{
	struct iphdr *iph;
	struct tcphdr *tcph;
	struct tcphdr *tcph;
	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
	int mac_hdr_len = skb_network_offset(skb);
	int mac_hdr_len = skb_network_offset(skb);


	memcpy(hdr, skb->data, hdr_len);
	memcpy(hdr, skb->data, hdr_len);
	iph = (struct iphdr *)(hdr + mac_hdr_len);
	if (!tso->ipv6) {
		struct iphdr *iph = (void *)(hdr + mac_hdr_len);

		iph->id = htons(tso->ip_id);
		iph->id = htons(tso->ip_id);
		iph->tot_len = htons(size + hdr_len - mac_hdr_len);
		iph->tot_len = htons(size + hdr_len - mac_hdr_len);
		tso->ip_id++;
	} else {
		struct ipv6hdr *iph = (void *)(hdr + mac_hdr_len);

		iph->payload_len = htons(size + tcp_hdrlen(skb));
	}
	tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb));
	tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb));
	put_unaligned_be32(tso->tcp_seq, &tcph->seq);
	put_unaligned_be32(tso->tcp_seq, &tcph->seq);
	tso->ip_id++;


	if (!is_last) {
	if (!is_last) {
		/* Clear all special flags for not last packet */
		/* Clear all special flags for not last packet */
@@ -61,6 +68,7 @@ void tso_start(struct sk_buff *skb, struct tso_t *tso)
	tso->ip_id = ntohs(ip_hdr(skb)->id);
	tso->ip_id = ntohs(ip_hdr(skb)->id);
	tso->tcp_seq = ntohl(tcp_hdr(skb)->seq);
	tso->tcp_seq = ntohl(tcp_hdr(skb)->seq);
	tso->next_frag_idx = 0;
	tso->next_frag_idx = 0;
	tso->ipv6 = vlan_get_protocol(skb) == htons(ETH_P_IPV6);


	/* Build first data */
	/* Build first data */
	tso->size = skb_headlen(skb) - hdr_len;
	tso->size = skb_headlen(skb) - hdr_len;