1 | /* |
2 | * Copyright (c) 2018 Mellanox Technologies. All rights reserved. |
3 | * |
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: |
9 | * |
10 | * Redistribution and use in source and binary forms, with or |
11 | * without modification, are permitted provided that the following |
12 | * conditions are met: |
13 | * |
14 | * - Redistributions of source code must retain the above |
15 | * copyright notice, this list of conditions and the following |
16 | * disclaimer. |
17 | * |
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. |
22 | * |
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 |
30 | * SOFTWARE. |
31 | * |
32 | */ |
33 | |
34 | #ifndef __MLX5E_EN_ACCEL_H__ |
35 | #define __MLX5E_EN_ACCEL_H__ |
36 | |
37 | #include <linux/skbuff.h> |
38 | #include <linux/netdevice.h> |
39 | #include "en_accel/ipsec_rxtx.h" |
40 | #include "en_accel/ktls.h" |
41 | #include "en_accel/ktls_txrx.h" |
42 | #include <en_accel/macsec.h> |
43 | #include "en.h" |
44 | #include "en/txrx.h" |
45 | |
46 | #if IS_ENABLED(CONFIG_GENEVE) |
47 | #include <net/geneve.h> |
48 | |
49 | static inline bool mlx5_geneve_tx_allowed(struct mlx5_core_dev *mdev) |
50 | { |
51 | return mlx5_tx_swp_supported(mdev); |
52 | } |
53 | |
54 | static inline void |
55 | mlx5e_tx_tunnel_accel(struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg, u16 ihs) |
56 | { |
57 | struct mlx5e_swp_spec swp_spec = {}; |
58 | unsigned int offset = 0; |
59 | __be16 l3_proto; |
60 | u8 l4_proto; |
61 | |
62 | l3_proto = vlan_get_protocol(skb); |
63 | switch (l3_proto) { |
64 | case htons(ETH_P_IP): |
65 | l4_proto = ip_hdr(skb)->protocol; |
66 | break; |
67 | case htons(ETH_P_IPV6): |
68 | l4_proto = ipv6_find_hdr(skb, offset: &offset, target: -1, NULL, NULL); |
69 | break; |
70 | default: |
71 | return; |
72 | } |
73 | |
74 | if (l4_proto != IPPROTO_UDP || |
75 | udp_hdr(skb)->dest != cpu_to_be16(GENEVE_UDP_PORT)) |
76 | return; |
77 | swp_spec.l3_proto = l3_proto; |
78 | swp_spec.l4_proto = l4_proto; |
79 | swp_spec.is_tun = true; |
80 | if (inner_ip_hdr(skb)->version == 6) { |
81 | swp_spec.tun_l3_proto = htons(ETH_P_IPV6); |
82 | swp_spec.tun_l4_proto = inner_ipv6_hdr(skb)->nexthdr; |
83 | } else { |
84 | swp_spec.tun_l3_proto = htons(ETH_P_IP); |
85 | swp_spec.tun_l4_proto = inner_ip_hdr(skb)->protocol; |
86 | } |
87 | |
88 | mlx5e_set_eseg_swp(skb, eseg, swp_spec: &swp_spec); |
89 | if (skb_vlan_tag_present(skb) && ihs) |
90 | mlx5e_eseg_swp_offsets_add_vlan(eseg); |
91 | } |
92 | |
93 | #else |
94 | static inline bool mlx5_geneve_tx_allowed(struct mlx5_core_dev *mdev) |
95 | { |
96 | return false; |
97 | } |
98 | |
99 | #endif /* CONFIG_GENEVE */ |
100 | |
101 | static inline void |
102 | mlx5e_udp_gso_handle_tx_skb(struct sk_buff *skb) |
103 | { |
104 | int payload_len = skb_shinfo(skb)->gso_size + sizeof(struct udphdr); |
105 | |
106 | udp_hdr(skb)->len = htons(payload_len); |
107 | } |
108 | |
109 | struct mlx5e_accel_tx_state { |
110 | #ifdef CONFIG_MLX5_EN_TLS |
111 | struct mlx5e_accel_tx_tls_state tls; |
112 | #endif |
113 | #ifdef CONFIG_MLX5_EN_IPSEC |
114 | struct mlx5e_accel_tx_ipsec_state ipsec; |
115 | #endif |
116 | }; |
117 | |
118 | static inline bool mlx5e_accel_tx_begin(struct net_device *dev, |
119 | struct mlx5e_txqsq *sq, |
120 | struct sk_buff *skb, |
121 | struct mlx5e_accel_tx_state *state) |
122 | { |
123 | if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) |
124 | mlx5e_udp_gso_handle_tx_skb(skb); |
125 | |
126 | #ifdef CONFIG_MLX5_EN_TLS |
127 | /* May send WQEs. */ |
128 | if (tls_is_skb_tx_device_offloaded(skb)) |
129 | if (unlikely(!mlx5e_ktls_handle_tx_skb(dev, sq, skb, |
130 | &state->tls))) |
131 | return false; |
132 | #endif |
133 | |
134 | #ifdef CONFIG_MLX5_EN_IPSEC |
135 | if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state) && xfrm_offload(skb)) { |
136 | if (unlikely(!mlx5e_ipsec_handle_tx_skb(dev, skb, &state->ipsec))) |
137 | return false; |
138 | } |
139 | #endif |
140 | |
141 | #ifdef CONFIG_MLX5_MACSEC |
142 | if (unlikely(mlx5e_macsec_skb_is_offload(skb))) { |
143 | struct mlx5e_priv *priv = netdev_priv(dev); |
144 | |
145 | if (unlikely(!mlx5e_macsec_handle_tx_skb(priv->macsec, skb))) |
146 | return false; |
147 | } |
148 | #endif |
149 | |
150 | return true; |
151 | } |
152 | |
153 | static inline unsigned int mlx5e_accel_tx_ids_len(struct mlx5e_txqsq *sq, |
154 | struct mlx5e_accel_tx_state *state) |
155 | { |
156 | #ifdef CONFIG_MLX5_EN_IPSEC |
157 | if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state)) |
158 | return mlx5e_ipsec_tx_ids_len(ipsec_st: &state->ipsec); |
159 | #endif |
160 | |
161 | return 0; |
162 | } |
163 | |
164 | /* Part of the eseg touched by TX offloads */ |
165 | #define MLX5E_ACCEL_ESEG_LEN offsetof(struct mlx5_wqe_eth_seg, mss) |
166 | |
167 | static inline void mlx5e_accel_tx_eseg(struct mlx5e_priv *priv, |
168 | struct sk_buff *skb, |
169 | struct mlx5_wqe_eth_seg *eseg, u16 ihs) |
170 | { |
171 | #ifdef CONFIG_MLX5_EN_IPSEC |
172 | if (xfrm_offload(skb)) |
173 | mlx5e_ipsec_tx_build_eseg(priv, skb, eseg); |
174 | #endif |
175 | |
176 | #ifdef CONFIG_MLX5_MACSEC |
177 | if (unlikely(mlx5e_macsec_skb_is_offload(skb))) |
178 | mlx5e_macsec_tx_build_eseg(macsec: priv->macsec, skb, eseg); |
179 | #endif |
180 | |
181 | #if IS_ENABLED(CONFIG_GENEVE) |
182 | if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL) |
183 | mlx5e_tx_tunnel_accel(skb, eseg, ihs); |
184 | #endif |
185 | } |
186 | |
187 | static inline void mlx5e_accel_tx_finish(struct mlx5e_txqsq *sq, |
188 | struct mlx5e_tx_wqe *wqe, |
189 | struct mlx5e_accel_tx_state *state, |
190 | struct mlx5_wqe_inline_seg *inlseg) |
191 | { |
192 | #ifdef CONFIG_MLX5_EN_TLS |
193 | mlx5e_ktls_handle_tx_wqe(cseg: &wqe->ctrl, state: &state->tls); |
194 | #endif |
195 | |
196 | #ifdef CONFIG_MLX5_EN_IPSEC |
197 | if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state) && |
198 | state->ipsec.xo && state->ipsec.tailen) |
199 | mlx5e_ipsec_handle_tx_wqe(wqe, ipsec_st: &state->ipsec, inlseg); |
200 | #endif |
201 | } |
202 | |
203 | static inline int mlx5e_accel_init_rx(struct mlx5e_priv *priv) |
204 | { |
205 | return mlx5e_ktls_init_rx(priv); |
206 | } |
207 | |
208 | static inline void mlx5e_accel_cleanup_rx(struct mlx5e_priv *priv) |
209 | { |
210 | mlx5e_ktls_cleanup_rx(priv); |
211 | } |
212 | |
213 | static inline int mlx5e_accel_init_tx(struct mlx5e_priv *priv) |
214 | { |
215 | return mlx5e_ktls_init_tx(priv); |
216 | } |
217 | |
218 | static inline void mlx5e_accel_cleanup_tx(struct mlx5e_priv *priv) |
219 | { |
220 | mlx5e_ktls_cleanup_tx(priv); |
221 | } |
222 | #endif /* __MLX5E_EN_ACCEL_H__ */ |
223 | |