Skip to content

Commit 0ce8df6

Browse files
ecree-solarflaredavem330
authored andcommitted
sfc: implement encapsulated TSO on EF10
>From the 8000 series onwards, EF10 NICs with suitable firmware are able to perform TSO within VXLAN or NVGRE encapsulation. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1679c72 commit 0ce8df6

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,10 +2179,11 @@ int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
21792179
bool *data_mapped)
21802180
{
21812181
struct efx_tx_buffer *buffer;
2182+
u16 inner_ipv4_id = 0;
2183+
u16 outer_ipv4_id = 0;
21822184
struct tcphdr *tcp;
21832185
struct iphdr *ip;
2184-
2185-
u16 ipv4_id;
2186+
u16 ip_tot_len;
21862187
u32 seqnum;
21872188
u32 mss;
21882189

@@ -2195,21 +2196,43 @@ int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
21952196
return -EINVAL;
21962197
}
21972198

2198-
ip = ip_hdr(skb);
2199+
if (skb->encapsulation) {
2200+
if (!tx_queue->tso_encap)
2201+
return -EINVAL;
2202+
ip = ip_hdr(skb);
2203+
if (ip->version == 4)
2204+
outer_ipv4_id = ntohs(ip->id);
2205+
2206+
ip = inner_ip_hdr(skb);
2207+
tcp = inner_tcp_hdr(skb);
2208+
} else {
2209+
ip = ip_hdr(skb);
2210+
tcp = tcp_hdr(skb);
2211+
}
2212+
2213+
/* 8000-series EF10 hardware requires that IP Total Length be
2214+
* greater than or equal to the value it will have in each segment
2215+
* (which is at most mss + 208 + TCP header length), but also less
2216+
* than (0x10000 - inner_network_header). Otherwise the TCP
2217+
* checksum calculation will be broken for encapsulated packets.
2218+
* We fill in ip->tot_len with 0xff30, which should satisfy the
2219+
* first requirement unless the MSS is ridiculously large (which
2220+
* should be impossible as the driver max MTU is 9216); it is
2221+
* guaranteed to satisfy the second as we only attempt TSO if
2222+
* inner_network_header <= 208.
2223+
*/
2224+
ip_tot_len = -EFX_TSO2_MAX_HDRLEN;
2225+
EFX_WARN_ON_ONCE_PARANOID(mss + EFX_TSO2_MAX_HDRLEN +
2226+
(tcp->doff << 2u) > ip_tot_len);
2227+
21992228
if (ip->version == 4) {
2200-
/* Modify IPv4 header if needed. */
2201-
ip->tot_len = 0;
2229+
ip->tot_len = htons(ip_tot_len);
22022230
ip->check = 0;
2203-
ipv4_id = ntohs(ip->id);
2231+
inner_ipv4_id = ntohs(ip->id);
22042232
} else {
2205-
/* Modify IPv6 header if needed. */
2206-
struct ipv6hdr *ipv6 = ipv6_hdr(skb);
2207-
2208-
ipv6->payload_len = 0;
2209-
ipv4_id = 0;
2233+
((struct ipv6hdr *)ip)->payload_len = htons(ip_tot_len);
22102234
}
22112235

2212-
tcp = tcp_hdr(skb);
22132236
seqnum = ntohl(tcp->seq);
22142237

22152238
buffer = efx_tx_queue_get_insert_buffer(tx_queue);
@@ -2222,7 +2245,7 @@ int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
22222245
ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_TSO,
22232246
ESF_DZ_TX_TSO_OPTION_TYPE,
22242247
ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
2225-
ESF_DZ_TX_TSO_IP_ID, ipv4_id,
2248+
ESF_DZ_TX_TSO_IP_ID, inner_ipv4_id,
22262249
ESF_DZ_TX_TSO_TCP_SEQNO, seqnum
22272250
);
22282251
++tx_queue->insert_count;
@@ -2232,11 +2255,12 @@ int efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
22322255
buffer->flags = EFX_TX_BUF_OPTION;
22332256
buffer->len = 0;
22342257
buffer->unmap_len = 0;
2235-
EFX_POPULATE_QWORD_4(buffer->option,
2258+
EFX_POPULATE_QWORD_5(buffer->option,
22362259
ESF_DZ_TX_DESC_IS_OPT, 1,
22372260
ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_TSO,
22382261
ESF_DZ_TX_TSO_OPTION_TYPE,
22392262
ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
2263+
ESF_DZ_TX_TSO_OUTER_IPID, outer_ipv4_id,
22402264
ESF_DZ_TX_TSO_TCP_MSS, mss
22412265
);
22422266
++tx_queue->insert_count;
@@ -2322,6 +2346,9 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
23222346
ESF_DZ_TX_TIMESTAMP, tx_queue->timestamping);
23232347
tx_queue->write_count = 1;
23242348

2349+
if (tx_queue->tso_version == 2 && efx_has_cap(efx, TX_TSO_V2_ENCAP))
2350+
tx_queue->tso_encap = true;
2351+
23252352
wmb();
23262353
efx_ef10_push_tx_desc(tx_queue, txd);
23272354

drivers/net/ethernet/sfc/net_driver.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
/* Minimum MTU, from RFC791 (IP) */
7878
#define EFX_MIN_MTU 68
7979

80+
/* Maximum total header length for TSOv2 */
81+
#define EFX_TSO2_MAX_HDRLEN 208
82+
8083
/* Size of an RX scatter buffer. Small enough to pack 2 into a 4K page,
8184
* and should be a multiple of the cache line size.
8285
*/
@@ -195,6 +198,7 @@ struct efx_tx_buffer {
195198
* Is our index within @channel->tx_queue array.
196199
* @type: configuration type of this TX queue. A bitmask of %EFX_TXQ_TYPE_* flags.
197200
* @tso_version: Version of TSO in use for this queue.
201+
* @tso_encap: Is encapsulated TSO supported? Supported in TSOv2 on 8000 series.
198202
* @channel: The associated channel
199203
* @core_txq: The networking core TX queue structure
200204
* @buffer: The software buffer ring
@@ -258,6 +262,7 @@ struct efx_tx_queue {
258262
unsigned int label;
259263
unsigned int type;
260264
unsigned int tso_version;
265+
bool tso_encap;
261266
struct efx_channel *channel;
262267
struct netdev_queue *core_txq;
263268
struct efx_tx_buffer *buffer;

0 commit comments

Comments
 (0)