2 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <crypto/aead.h>
37 #include "accel/ipsec_offload.h"
38 #include "en_accel/ipsec_rxtx.h"
39 #include "en_accel/ipsec.h"
40 #include "accel/accel.h"
44 MLX5E_IPSEC_RX_SYNDROME_DECRYPTED = 0x11,
45 MLX5E_IPSEC_RX_SYNDROME_AUTH_FAILED = 0x12,
46 MLX5E_IPSEC_RX_SYNDROME_BAD_PROTO = 0x17,
49 struct mlx5e_ipsec_rx_metadata {
50 unsigned char nexthdr;
55 MLX5E_IPSEC_TX_SYNDROME_OFFLOAD = 0x8,
56 MLX5E_IPSEC_TX_SYNDROME_OFFLOAD_WITH_LSO_TCP = 0x9,
59 struct mlx5e_ipsec_tx_metadata {
60 __be16 mss_inv; /* 1/MSS in 16bit fixed point, only for LSO */
61 __be16 seq; /* LSBs of the first TCP seq, only for LSO */
62 u8 esp_next_proto; /* Next protocol of ESP */
65 struct mlx5e_ipsec_metadata {
66 unsigned char syndrome;
69 /* from FPGA to host, on successful decrypt */
70 struct mlx5e_ipsec_rx_metadata rx;
71 /* from host to FPGA */
72 struct mlx5e_ipsec_tx_metadata tx;
74 /* packet type ID field */
78 #define MAX_LSO_MSS 2048
80 /* Pre-calculated (Q0.16) fixed-point inverse 1/x function */
81 static __be16 mlx5e_ipsec_inverse_table[MAX_LSO_MSS];
83 static inline __be16 mlx5e_ipsec_mss_inv(struct sk_buff *skb)
85 return mlx5e_ipsec_inverse_table[skb_shinfo(skb)->gso_size];
88 static struct mlx5e_ipsec_metadata *mlx5e_ipsec_add_metadata(struct sk_buff *skb)
90 struct mlx5e_ipsec_metadata *mdata;
93 if (unlikely(skb_cow_head(skb, sizeof(*mdata))))
94 return ERR_PTR(-ENOMEM);
96 eth = (struct ethhdr *)skb_push(skb, sizeof(*mdata));
97 skb->mac_header -= sizeof(*mdata);
98 mdata = (struct mlx5e_ipsec_metadata *)(eth + 1);
100 memmove(skb->data, skb->data + sizeof(*mdata),
103 eth->h_proto = cpu_to_be16(MLX5E_METADATA_ETHER_TYPE);
105 memset(mdata->content.raw, 0, sizeof(mdata->content.raw));
109 static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x)
111 unsigned int alen = crypto_aead_authsize(x->data);
112 struct ipv6hdr *ipv6hdr = ipv6_hdr(skb);
113 struct iphdr *ipv4hdr = ip_hdr(skb);
114 unsigned int trailer_len;
118 ret = skb_copy_bits(skb, skb->len - alen - 2, &plen, 1);
122 trailer_len = alen + plen + 2;
124 pskb_trim(skb, skb->len - trailer_len);
125 if (skb->protocol == htons(ETH_P_IP)) {
126 ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len);
127 ip_send_check(ipv4hdr);
129 ipv6hdr->payload_len = htons(ntohs(ipv6hdr->payload_len) -
135 static void mlx5e_ipsec_set_swp(struct sk_buff *skb,
136 struct mlx5_wqe_eth_seg *eseg, u8 mode,
137 struct xfrm_offload *xo)
140 * SWP: OutL3 InL3 InL4
141 * Pkt: MAC IP ESP IP L4
147 * Tunnel(VXLAN TCP/UDP) over Transport Mode
148 * SWP: OutL3 InL3 InL4
149 * Pkt: MAC IP ESP UDP VXLAN IP L4
152 /* Shared settings */
153 eseg->swp_outer_l3_offset = skb_network_offset(skb) / 2;
154 if (skb->protocol == htons(ETH_P_IPV6))
155 eseg->swp_flags |= MLX5_ETH_WQE_SWP_OUTER_L3_IPV6;
158 if (mode == XFRM_MODE_TUNNEL) {
159 eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2;
160 if (xo->proto == IPPROTO_IPV6)
161 eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6;
163 switch (xo->inner_ipproto) {
165 eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L4_UDP;
168 /* IP | ESP | IP | [TCP | UDP] */
169 eseg->swp_inner_l4_offset = skb_inner_transport_offset(skb) / 2;
178 if (mode != XFRM_MODE_TRANSPORT)
181 if (!xo->inner_ipproto) {
184 eseg->swp_flags |= MLX5_ETH_WQE_SWP_OUTER_L4_UDP;
188 eseg->swp_outer_l4_offset = skb_inner_transport_offset(skb) / 2;
194 /* Tunnel(VXLAN TCP/UDP) over Transport Mode */
195 switch (xo->inner_ipproto) {
197 eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L4_UDP;
200 eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2;
201 eseg->swp_inner_l4_offset =
202 (skb->csum_start + skb->head - skb->data) / 2;
203 if (inner_ip_hdr(skb)->version == 6)
204 eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6;
213 void mlx5e_ipsec_set_iv_esn(struct sk_buff *skb, struct xfrm_state *x,
214 struct xfrm_offload *xo)
216 struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
217 __u32 oseq = replay_esn->oseq;
222 if (unlikely(skb_is_gso(skb) && oseq < MLX5E_IPSEC_ESN_SCOPE_MID &&
223 MLX5E_IPSEC_ESN_SCOPE_MID < (oseq - skb_shinfo(skb)->gso_segs))) {
224 seq_hi = xo->seq.hi - 1;
229 /* Place the SN in the IV field */
230 seqno = cpu_to_be64(xo->seq.low + ((u64)seq_hi << 32));
231 iv_offset = skb_transport_offset(skb) + sizeof(struct ip_esp_hdr);
232 skb_store_bits(skb, iv_offset, &seqno, 8);
235 void mlx5e_ipsec_set_iv(struct sk_buff *skb, struct xfrm_state *x,
236 struct xfrm_offload *xo)
241 /* Place the SN in the IV field */
242 seqno = cpu_to_be64(xo->seq.low + ((u64)xo->seq.hi << 32));
243 iv_offset = skb_transport_offset(skb) + sizeof(struct ip_esp_hdr);
244 skb_store_bits(skb, iv_offset, &seqno, 8);
247 static void mlx5e_ipsec_set_metadata(struct sk_buff *skb,
248 struct mlx5e_ipsec_metadata *mdata,
249 struct xfrm_offload *xo)
251 struct ip_esp_hdr *esph;
254 if (skb_is_gso(skb)) {
255 /* Add LSO metadata indication */
256 esph = ip_esp_hdr(skb);
257 tcph = inner_tcp_hdr(skb);
258 netdev_dbg(skb->dev, " Offloading GSO packet outer L3 %u; L4 %u; Inner L3 %u; L4 %u\n",
260 skb->transport_header,
261 skb->inner_network_header,
262 skb->inner_transport_header);
263 netdev_dbg(skb->dev, " Offloading GSO packet of len %u; mss %u; TCP sp %u dp %u seq 0x%x ESP seq 0x%x\n",
264 skb->len, skb_shinfo(skb)->gso_size,
265 ntohs(tcph->source), ntohs(tcph->dest),
266 ntohl(tcph->seq), ntohl(esph->seq_no));
267 mdata->syndrome = MLX5E_IPSEC_TX_SYNDROME_OFFLOAD_WITH_LSO_TCP;
268 mdata->content.tx.mss_inv = mlx5e_ipsec_mss_inv(skb);
269 mdata->content.tx.seq = htons(ntohl(tcph->seq) & 0xFFFF);
271 mdata->syndrome = MLX5E_IPSEC_TX_SYNDROME_OFFLOAD;
273 mdata->content.tx.esp_next_proto = xo->proto;
275 netdev_dbg(skb->dev, " TX metadata syndrome %u proto %u mss_inv %04x seq %04x\n",
276 mdata->syndrome, mdata->content.tx.esp_next_proto,
277 ntohs(mdata->content.tx.mss_inv),
278 ntohs(mdata->content.tx.seq));
281 void mlx5e_ipsec_handle_tx_wqe(struct mlx5e_tx_wqe *wqe,
282 struct mlx5e_accel_tx_ipsec_state *ipsec_st,
283 struct mlx5_wqe_inline_seg *inlseg)
285 inlseg->byte_count = cpu_to_be32(ipsec_st->tailen | MLX5_INLINE_SEG);
286 esp_output_fill_trailer((u8 *)inlseg->data, 0, ipsec_st->plen, ipsec_st->xo->proto);
289 static int mlx5e_ipsec_set_state(struct mlx5e_priv *priv,
291 struct xfrm_state *x,
292 struct xfrm_offload *xo,
293 struct mlx5e_accel_tx_ipsec_state *ipsec_st)
295 unsigned int blksize, clen, alen, plen;
296 struct crypto_aead *aead;
301 if (mlx5_is_ipsec_device(priv->mdev)) {
303 alen = crypto_aead_authsize(aead);
304 blksize = ALIGN(crypto_aead_blocksize(aead), 4);
305 clen = ALIGN(skb->len + 2, blksize);
306 plen = max_t(u32, clen - skb->len, 4);
307 tailen = plen + alen;
308 ipsec_st->plen = plen;
309 ipsec_st->tailen = tailen;
315 void mlx5e_ipsec_tx_build_eseg(struct mlx5e_priv *priv, struct sk_buff *skb,
316 struct mlx5_wqe_eth_seg *eseg)
318 struct xfrm_offload *xo = xfrm_offload(skb);
319 struct xfrm_encap_tmpl *encap;
320 struct xfrm_state *x;
324 sp = skb_sec_path(skb);
325 if (unlikely(sp->len != 1))
328 x = xfrm_input_state(skb);
332 if (unlikely(!x->xso.offload_handle ||
333 (skb->protocol != htons(ETH_P_IP) &&
334 skb->protocol != htons(ETH_P_IPV6))))
337 mlx5e_ipsec_set_swp(skb, eseg, x->props.mode, xo);
339 l3_proto = (x->props.family == AF_INET) ?
340 ((struct iphdr *)skb_network_header(skb))->protocol :
341 ((struct ipv6hdr *)skb_network_header(skb))->nexthdr;
343 if (mlx5_is_ipsec_device(priv->mdev)) {
344 eseg->flow_table_metadata |= cpu_to_be32(MLX5_ETH_WQE_FT_META_IPSEC);
345 eseg->trailer |= cpu_to_be32(MLX5_ETH_WQE_INSERT_TRAILER);
348 eseg->trailer |= (l3_proto == IPPROTO_ESP) ?
349 cpu_to_be32(MLX5_ETH_WQE_TRAILER_HDR_OUTER_IP_ASSOC) :
350 cpu_to_be32(MLX5_ETH_WQE_TRAILER_HDR_OUTER_L4_ASSOC);
351 } else if (encap->encap_type == UDP_ENCAP_ESPINUDP) {
352 eseg->trailer |= (l3_proto == IPPROTO_ESP) ?
353 cpu_to_be32(MLX5_ETH_WQE_TRAILER_HDR_INNER_IP_ASSOC) :
354 cpu_to_be32(MLX5_ETH_WQE_TRAILER_HDR_INNER_L4_ASSOC);
359 bool mlx5e_ipsec_handle_tx_skb(struct net_device *netdev,
361 struct mlx5e_accel_tx_ipsec_state *ipsec_st)
363 struct mlx5e_priv *priv = netdev_priv(netdev);
364 struct xfrm_offload *xo = xfrm_offload(skb);
365 struct mlx5e_ipsec_sa_entry *sa_entry;
366 struct mlx5e_ipsec_metadata *mdata;
367 struct xfrm_state *x;
370 sp = skb_sec_path(skb);
371 if (unlikely(sp->len != 1)) {
372 atomic64_inc(&priv->ipsec->sw_stats.ipsec_tx_drop_bundle);
376 x = xfrm_input_state(skb);
378 atomic64_inc(&priv->ipsec->sw_stats.ipsec_tx_drop_no_state);
382 if (unlikely(!x->xso.offload_handle ||
383 (skb->protocol != htons(ETH_P_IP) &&
384 skb->protocol != htons(ETH_P_IPV6)))) {
385 atomic64_inc(&priv->ipsec->sw_stats.ipsec_tx_drop_not_ip);
389 if (!skb_is_gso(skb))
390 if (unlikely(mlx5e_ipsec_remove_trailer(skb, x))) {
391 atomic64_inc(&priv->ipsec->sw_stats.ipsec_tx_drop_trailer);
395 if (MLX5_CAP_GEN(priv->mdev, fpga)) {
396 mdata = mlx5e_ipsec_add_metadata(skb);
398 atomic64_inc(&priv->ipsec->sw_stats.ipsec_tx_drop_metadata);
403 sa_entry = (struct mlx5e_ipsec_sa_entry *)x->xso.offload_handle;
404 sa_entry->set_iv_op(skb, x, xo);
405 if (MLX5_CAP_GEN(priv->mdev, fpga))
406 mlx5e_ipsec_set_metadata(skb, mdata, xo);
408 mlx5e_ipsec_set_state(priv, skb, x, xo, ipsec_st);
417 static inline struct xfrm_state *
418 mlx5e_ipsec_build_sp(struct net_device *netdev, struct sk_buff *skb,
419 struct mlx5e_ipsec_metadata *mdata)
421 struct mlx5e_priv *priv = netdev_priv(netdev);
422 struct xfrm_offload *xo;
423 struct xfrm_state *xs;
427 sp = secpath_set(skb);
429 atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sp_alloc);
433 sa_handle = be32_to_cpu(mdata->content.rx.sa_handle);
434 xs = mlx5e_ipsec_sadb_rx_lookup(priv->ipsec, sa_handle);
436 atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sadb_miss);
440 sp = skb_sec_path(skb);
441 sp->xvec[sp->len++] = xs;
444 xo = xfrm_offload(skb);
445 xo->flags = CRYPTO_DONE;
446 switch (mdata->syndrome) {
447 case MLX5E_IPSEC_RX_SYNDROME_DECRYPTED:
448 xo->status = CRYPTO_SUCCESS;
449 if (likely(priv->ipsec->no_trailer)) {
450 xo->flags |= XFRM_ESP_NO_TRAILER;
451 xo->proto = mdata->content.rx.nexthdr;
454 case MLX5E_IPSEC_RX_SYNDROME_AUTH_FAILED:
455 xo->status = CRYPTO_TUNNEL_ESP_AUTH_FAILED;
457 case MLX5E_IPSEC_RX_SYNDROME_BAD_PROTO:
458 xo->status = CRYPTO_INVALID_PROTOCOL;
461 atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_syndrome);
467 struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
468 struct sk_buff *skb, u32 *cqe_bcnt)
470 struct mlx5e_ipsec_metadata *mdata;
471 struct xfrm_state *xs;
473 if (!is_metadata_hdr_valid(skb))
476 /* Use the metadata */
477 mdata = (struct mlx5e_ipsec_metadata *)(skb->data + ETH_HLEN);
478 xs = mlx5e_ipsec_build_sp(netdev, skb, mdata);
484 remove_metadata_hdr(skb);
485 *cqe_bcnt -= MLX5E_METADATA_ETHER_LEN;
491 MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_DECRYPTED,
492 MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_AUTH_FAILED,
493 MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_BAD_TRAILER,
496 void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev,
498 struct mlx5_cqe64 *cqe)
500 u32 ipsec_meta_data = be32_to_cpu(cqe->ft_metadata);
501 struct mlx5e_priv *priv;
502 struct xfrm_offload *xo;
503 struct xfrm_state *xs;
507 sa_handle = MLX5_IPSEC_METADATA_HANDLE(ipsec_meta_data);
508 priv = netdev_priv(netdev);
509 sp = secpath_set(skb);
511 atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sp_alloc);
515 xs = mlx5e_ipsec_sadb_rx_lookup(priv->ipsec, sa_handle);
517 atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sadb_miss);
521 sp = skb_sec_path(skb);
522 sp->xvec[sp->len++] = xs;
525 xo = xfrm_offload(skb);
526 xo->flags = CRYPTO_DONE;
528 switch (MLX5_IPSEC_METADATA_SYNDROM(ipsec_meta_data)) {
529 case MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_DECRYPTED:
530 xo->status = CRYPTO_SUCCESS;
531 if (WARN_ON_ONCE(priv->ipsec->no_trailer))
532 xo->flags |= XFRM_ESP_NO_TRAILER;
534 case MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_AUTH_FAILED:
535 xo->status = CRYPTO_TUNNEL_ESP_AUTH_FAILED;
537 case MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_BAD_TRAILER:
538 xo->status = CRYPTO_INVALID_PACKET_SYNTAX;
541 atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_syndrome);
545 void mlx5e_ipsec_build_inverse_table(void)
550 /* Calculate 1/x inverse table for use in GSO data path.
551 * Using this table, we provide the IPSec accelerator with the value of
552 * 1/gso_size so that it can infer the position of each segment inside
553 * the GSO, and increment the ESP sequence number, and generate the IV.
554 * The HW needs this value in Q0.16 fixed-point number format
556 mlx5e_ipsec_inverse_table[1] = htons(0xFFFF);
557 for (mss = 2; mss < MAX_LSO_MSS; mss++) {
558 mss_inv = div_u64(1ULL << 32, mss) >> 16;
559 mlx5e_ipsec_inverse_table[mss] = htons(mss_inv);