There are the following cases: 1. Packet ends before start marker: bypass offload. 2. Packet starts before start marker and ends after it: drop, not supported, breaks contract with kernel. 3. packet ends before tls record info starts: drop, this packet was already acknowledged and its record info was released. Add the above as comment in code. Mind possible wraparounds of the TCP seq, replace the simple comparison with a call to the TCP before() method. In addition, remove logic that handles negative sync_len values, as it became impossible.
Unified · Split
| @@ -180,7 +180,7 @@ mlx5e_ktls_tx_post_param_wqes(struct mlx5e_txqsq *sq, · 179 unmodified lines | ||
| 180 | 180 | |
| 181 | 181 | struct tx_sync_info { |
| 182 | 182 | u64 rcd_sn; |
| 183 | − s32 sync_len; | |
| 183 | + u32 sync_len; | |
| 184 | 184 | int nr_frags; |
| 185 | 185 | skb_frag_t frags[MAX_SKB_FRAGS]; |
| 186 | 186 | }; |
| @@ -193,13 +193,14 @@ enum mlx5e_ktls_sync_retval { · 6 unmodified lines | ||
| 193 | 193 | |
| 194 | 194 | static enum mlx5e_ktls_sync_retval |
| 195 | 195 | tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, |
| 196 | − u32 tcp_seq, struct tx_sync_info *info) | |
| 196 | + u32 tcp_seq, int datalen, struct tx_sync_info *info) | |
| 197 | 197 | { |
| 198 | 198 | struct tls_offload_context_tx *tx_ctx = priv_tx->tx_ctx; |
| 199 | 199 | enum mlx5e_ktls_sync_retval ret = MLX5E_KTLS_SYNC_DONE; |
| 200 | 200 | struct tls_record_info *record; |
| 201 | 201 | int remaining, i = 0; |
| 202 | 202 | unsigned long flags; |
| 203 | + bool ends_before; | |
| 203 | 204 | |
| 204 | 205 | spin_lock_irqsave(&tx_ctx->lock, flags); |
| 205 | 206 | record = tls_get_record(tx_ctx, tcp_seq, &info->rcd_sn); |
| @@ -209,9 +210,21 @@ tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, · 3 unmodified lines | ||
| 209 | 210 | goto out; |
| 210 | 211 | } |
| 211 | 212 | |
| 212 | − if (unlikely(tcp_seq < tls_record_start_seq(record))) { | |
| 213 | − ret = tls_record_is_start_marker(record) ? | |
| 214 | − MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL; | |
| 213 | + /* There are the following cases: | |
| 214 | + * 1. packet ends before start marker: bypass offload. | |
| 215 | + * 2. packet starts before start marker and ends after it: drop, | |
| 216 | + * not supported, breaks contract with kernel. | |
| 217 | + * 3. packet ends before tls record info starts: drop, | |
| 218 | + * this packet was already acknowledged and its record info | |
| 219 | + * was released. | |
| 220 | + */ | |
| 221 | + ends_before = before(tcp_seq + datalen, tls_record_start_seq(record)); | |
| 222 | + | |
| 223 | + if (unlikely(tls_record_is_start_marker(record))) { | |
| 224 | + ret = ends_before ? MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL; | |
| 225 | + goto out; | |
| 226 | + } else if (ends_before) { | |
| 227 | + ret = MLX5E_KTLS_SYNC_FAIL; | |
| 215 | 228 | goto out; |
| 216 | 229 | } |
| 217 | 230 | |
| @@ -337,7 +350,7 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, · 119 unmodified lines | ||
| 337 | 350 | u8 num_wqebbs; |
| 338 | 351 | int i = 0; |
| 339 | 352 | |
| 340 | − ret = tx_sync_info_get(priv_tx, seq, &info); | |
| 353 | + ret = tx_sync_info_get(priv_tx, seq, datalen, &info); | |
| 341 | 354 | if (unlikely(ret != MLX5E_KTLS_SYNC_DONE)) { |
| 342 | 355 | if (ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA) { |
| 343 | 356 | stats->tls_skip_no_sync_data++; |
| @@ -351,14 +364,6 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, · 7 unmodified lines | ||
| 351 | 364 | goto err_out; |
| 352 | 365 | } |
| 353 | 366 | |
| 354 | − if (unlikely(info.sync_len < 0)) { | |
| 355 | − if (likely(datalen <= -info.sync_len)) | |
| 356 | − return MLX5E_KTLS_SYNC_DONE; | |
| 357 | − | |
| 358 | − stats->tls_drop_bypass_req++; | |
| 359 | − goto err_out; | |
| 360 | − } | |
| 361 | − | |
| 362 | 367 | stats->tls_ooo++; |
| 363 | 368 | |
| 364 | 369 | tx_post_resync_params(sq, priv_tx, info.rcd_sn); |