Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'ipsec-next-2022-12-09' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next

Steffen Klassert says:

====================
ipsec-next 2022-12-09

1) Add xfrm packet offload core API.
From Leon Romanovsky.

2) Add xfrm packet offload support for mlx5.
From Leon Romanovsky and Raed Salem.

3) Fix a typto in a error message.
From Colin Ian King.

* tag 'ipsec-next-2022-12-09' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next: (38 commits)
xfrm: Fix spelling mistake "oflload" -> "offload"
net/mlx5e: Open mlx5 driver to accept IPsec packet offload
net/mlx5e: Handle ESN update events
net/mlx5e: Handle hardware IPsec limits events
net/mlx5e: Update IPsec soft and hard limits
net/mlx5e: Store all XFRM SAs in Xarray
net/mlx5e: Provide intermediate pointer to access IPsec struct
net/mlx5e: Skip IPsec encryption for TX path without matching policy
net/mlx5e: Add statistics for Rx/Tx IPsec offloaded flows
net/mlx5e: Improve IPsec flow steering autogroup
net/mlx5e: Configure IPsec packet offload flow steering
net/mlx5e: Use same coding pattern for Rx and Tx flows
net/mlx5e: Add XFRM policy offload logic
net/mlx5e: Create IPsec policy offload tables
net/mlx5e: Generalize creation of default IPsec miss group and rule
net/mlx5e: Group IPsec miss handles into separate struct
net/mlx5e: Make clear what IPsec rx_err does
net/mlx5e: Flatten the IPsec RX add rule path
net/mlx5e: Refactor FTE setup code to be more clear
net/mlx5e: Move IPsec flow table creation to separate function
...
====================

Link: https://lore.kernel.org/r/20221209093310.4018731-1-steffen.klassert@secunet.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+2161 -532
+53 -9
Documentation/networking/xfrm_device.rst
··· 5 5 =============================================== 6 6 7 7 Shannon Nelson <shannon.nelson@oracle.com> 8 + Leon Romanovsky <leonro@nvidia.com> 8 9 9 10 10 11 Overview ··· 19 18 Device interface allows NIC drivers to offer to the stack access to the 20 19 hardware offload. 21 20 21 + Right now, there are two types of hardware offload that kernel supports. 22 + * IPsec crypto offload: 23 + * NIC performs encrypt/decrypt 24 + * Kernel does everything else 25 + * IPsec packet offload: 26 + * NIC performs encrypt/decrypt 27 + * NIC does encapsulation 28 + * Kernel and NIC have SA and policy in-sync 29 + * NIC handles the SA and policies states 30 + * The Kernel talks to the keymanager 31 + 22 32 Userland access to the offload is typically through a system such as 23 33 libreswan or KAME/raccoon, but the iproute2 'ip xfrm' command set can 24 34 be handy when experimenting. An example command might look something 25 - like this:: 35 + like this for crypto offload: 26 36 27 37 ip x s add proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode transport \ 28 38 reqid 0x07 replay-window 32 \ 29 39 aead 'rfc4106(gcm(aes))' 0x44434241343332312423222114131211f4f3f2f1 128 \ 30 40 sel src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp \ 31 41 offload dev eth4 dir in 42 + 43 + and for packet offload 44 + 45 + ip x s add proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode transport \ 46 + reqid 0x07 replay-window 32 \ 47 + aead 'rfc4106(gcm(aes))' 0x44434241343332312423222114131211f4f3f2f1 128 \ 48 + sel src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp \ 49 + offload packet dev eth4 dir in 50 + 51 + ip x p add src 14.0.0.70 dst 14.0.0.52 offload packet dev eth4 dir in 52 + tmpl src 14.0.0.70 dst 14.0.0.52 proto esp reqid 10000 mode transport 32 53 33 54 Yes, that's ugly, but that's what shell scripts and/or libreswan are for. 34 55 ··· 63 40 64 41 /* from include/linux/netdevice.h */ 65 42 struct xfrmdev_ops { 43 + /* Crypto and Packet offload callbacks */ 66 44 int (*xdo_dev_state_add) (struct xfrm_state *x); 67 45 void (*xdo_dev_state_delete) (struct xfrm_state *x); 68 46 void (*xdo_dev_state_free) (struct xfrm_state *x); 69 47 bool (*xdo_dev_offload_ok) (struct sk_buff *skb, 70 48 struct xfrm_state *x); 71 49 void (*xdo_dev_state_advance_esn) (struct xfrm_state *x); 50 + 51 + /* Solely packet offload callbacks */ 52 + void (*xdo_dev_state_update_curlft) (struct xfrm_state *x); 53 + int (*xdo_dev_policy_add) (struct xfrm_policy *x); 54 + void (*xdo_dev_policy_delete) (struct xfrm_policy *x); 55 + void (*xdo_dev_policy_free) (struct xfrm_policy *x); 72 56 }; 73 57 74 - The NIC driver offering ipsec offload will need to implement these 75 - callbacks to make the offload available to the network stack's 76 - XFRM subsystem. Additionally, the feature bits NETIF_F_HW_ESP and 58 + The NIC driver offering ipsec offload will need to implement callbacks 59 + relevant to supported offload to make the offload available to the network 60 + stack's XFRM subsystem. Additionally, the feature bits NETIF_F_HW_ESP and 77 61 NETIF_F_HW_ESP_TX_CSUM will signal the availability of the offload. 78 62 79 63 ··· 109 79 110 80 =========== =================================== 111 81 0 success 112 - -EOPNETSUPP offload not supported, try SW IPsec 82 + -EOPNETSUPP offload not supported, try SW IPsec, 83 + not applicable for packet offload mode 113 84 other fail the request 114 85 =========== =================================== 115 86 ··· 127 96 offload can be supported (e.g. IPv4 or IPv6, no IPv4 options, etc) and 128 97 return true of false to signify its support. 129 98 99 + Crypto offload mode: 130 100 When ready to send, the driver needs to inspect the Tx packet for the 131 101 offload information, including the opaque context, and set up the packet 132 102 send accordingly:: ··· 171 139 In ESN mode, xdo_dev_state_advance_esn() is called from xfrm_replay_advance_esn(). 172 140 Driver will check packet seq number and update HW ESN state machine if needed. 173 141 142 + Packet offload mode: 143 + HW adds and deletes XFRM headers. So in RX path, XFRM stack is bypassed if HW 144 + reported success. In TX path, the packet lefts kernel without extra header 145 + and not encrypted, the HW is responsible to perform it. 146 + 174 147 When the SA is removed by the user, the driver's xdo_dev_state_delete() 175 - is asked to disable the offload. Later, xdo_dev_state_free() is called 176 - from a garbage collection routine after all reference counts to the state 148 + and xdo_dev_policy_delete() are asked to disable the offload. Later, 149 + xdo_dev_state_free() and xdo_dev_policy_free() are called from a garbage 150 + collection routine after all reference counts to the state and policy 177 151 have been removed and any remaining resources can be cleared for the 178 152 offload state. How these are used by the driver will depend on specific 179 153 hardware needs. 180 154 181 155 As a netdev is set to DOWN the XFRM stack's netdev listener will call 182 - xdo_dev_state_delete() and xdo_dev_state_free() on any remaining offloaded 183 - states. 156 + xdo_dev_state_delete(), xdo_dev_policy_delete(), xdo_dev_state_free() and 157 + xdo_dev_policy_free() on any remaining offloaded states. 158 + 159 + Outcome of HW handling packets, the XFRM core can't count hard, soft limits. 160 + The HW/driver are responsible to perform it and provide accurate data when 161 + xdo_dev_state_update_curlft() is called. In case of one of these limits 162 + occuried, the driver needs to call to xfrm_state_check_expire() to make sure 163 + that XFRM performs rekeying sequence.
+4
drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c
··· 283 283 pr_debug("Cannot offload xfrm states with geniv other than seqiv\n"); 284 284 return -EINVAL; 285 285 } 286 + if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) { 287 + pr_debug("Unsupported xfrm offload\n"); 288 + return -EINVAL; 289 + } 286 290 287 291 sa_entry = kzalloc(sizeof(*sa_entry), GFP_KERNEL); 288 292 if (!sa_entry) {
+5
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
··· 585 585 return -EINVAL; 586 586 } 587 587 588 + if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) { 589 + netdev_err(dev, "Unsupported ipsec offload type\n"); 590 + return -EINVAL; 591 + } 592 + 588 593 if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) { 589 594 struct rx_sa rsa; 590 595
+5
drivers/net/ethernet/intel/ixgbevf/ipsec.c
··· 280 280 return -EINVAL; 281 281 } 282 282 283 + if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) { 284 + netdev_err(dev, "Unsupported ipsec offload type\n"); 285 + return -EINVAL; 286 + } 287 + 283 288 if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) { 284 289 struct rx_sa rsa; 285 290
+1
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 1245 1245 int mlx5e_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi); 1246 1246 int mlx5e_get_vf_stats(struct net_device *dev, int vf, struct ifla_vf_stats *vf_stats); 1247 1247 #endif 1248 + int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey); 1248 1249 #endif /* __MLX5_EN_H__ */
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
··· 84 84 MLX5E_ARFS_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, 85 85 #endif 86 86 #ifdef CONFIG_MLX5_EN_IPSEC 87 - MLX5E_ACCEL_FS_ESP_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, 87 + MLX5E_ACCEL_FS_POL_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, 88 + MLX5E_ACCEL_FS_ESP_FT_LEVEL, 88 89 MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, 89 90 #endif 90 91 };
-1
drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c
··· 162 162 MLX5_ACCESS_ASO_OPC_MOD_FLOW_METER); 163 163 164 164 aso_ctrl = &aso_wqe->aso_ctrl; 165 - memset(aso_ctrl, 0, sizeof(*aso_ctrl)); 166 165 aso_ctrl->data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BYTEWISE_64BYTE << 6; 167 166 aso_ctrl->condition_1_0_operand = MLX5_ASO_ALWAYS_TRUE | 168 167 MLX5_ASO_ALWAYS_TRUE << 4;
+270 -86
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
··· 45 45 return (struct mlx5e_ipsec_sa_entry *)x->xso.offload_handle; 46 46 } 47 47 48 - struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *ipsec, 49 - unsigned int handle) 48 + static struct mlx5e_ipsec_pol_entry *to_ipsec_pol_entry(struct xfrm_policy *x) 50 49 { 51 - struct mlx5e_ipsec_sa_entry *sa_entry; 52 - struct xfrm_state *ret = NULL; 53 - 54 - rcu_read_lock(); 55 - hash_for_each_possible_rcu(ipsec->sadb_rx, sa_entry, hlist, handle) 56 - if (sa_entry->handle == handle) { 57 - ret = sa_entry->x; 58 - xfrm_state_hold(ret); 59 - break; 60 - } 61 - rcu_read_unlock(); 62 - 63 - return ret; 64 - } 65 - 66 - static int mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry) 67 - { 68 - unsigned int handle = sa_entry->ipsec_obj_id; 69 - struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 70 - struct mlx5e_ipsec_sa_entry *_sa_entry; 71 - unsigned long flags; 72 - 73 - rcu_read_lock(); 74 - hash_for_each_possible_rcu(ipsec->sadb_rx, _sa_entry, hlist, handle) 75 - if (_sa_entry->handle == handle) { 76 - rcu_read_unlock(); 77 - return -EEXIST; 78 - } 79 - rcu_read_unlock(); 80 - 81 - spin_lock_irqsave(&ipsec->sadb_rx_lock, flags); 82 - sa_entry->handle = handle; 83 - hash_add_rcu(ipsec->sadb_rx, &sa_entry->hlist, sa_entry->handle); 84 - spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags); 85 - 86 - return 0; 87 - } 88 - 89 - static void mlx5e_ipsec_sadb_rx_del(struct mlx5e_ipsec_sa_entry *sa_entry) 90 - { 91 - struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 92 - unsigned long flags; 93 - 94 - spin_lock_irqsave(&ipsec->sadb_rx_lock, flags); 95 - hash_del_rcu(&sa_entry->hlist); 96 - spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags); 50 + return (struct mlx5e_ipsec_pol_entry *)x->xdo.offload_handle; 97 51 } 98 52 99 53 static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry) ··· 83 129 return false; 84 130 } 85 131 86 - static void 87 - mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, 88 - struct mlx5_accel_esp_xfrm_attrs *attrs) 132 + static void mlx5e_ipsec_init_limits(struct mlx5e_ipsec_sa_entry *sa_entry, 133 + struct mlx5_accel_esp_xfrm_attrs *attrs) 134 + { 135 + struct xfrm_state *x = sa_entry->x; 136 + 137 + attrs->hard_packet_limit = x->lft.hard_packet_limit; 138 + if (x->lft.soft_packet_limit == XFRM_INF) 139 + return; 140 + 141 + /* Hardware decrements hard_packet_limit counter through 142 + * the operation. While fires an event when soft_packet_limit 143 + * is reached. It emans that we need substitute the numbers 144 + * in order to properly count soft limit. 145 + * 146 + * As an example: 147 + * XFRM user sets soft limit is 2 and hard limit is 9 and 148 + * expects to see soft event after 2 packets and hard event 149 + * after 9 packets. In our case, the hard limit will be set 150 + * to 9 and soft limit is comparator to 7 so user gets the 151 + * soft event after 2 packeta 152 + */ 153 + attrs->soft_packet_limit = 154 + x->lft.hard_packet_limit - x->lft.soft_packet_limit; 155 + } 156 + 157 + void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, 158 + struct mlx5_accel_esp_xfrm_attrs *attrs) 89 159 { 90 160 struct xfrm_state *x = sa_entry->x; 91 161 struct aes_gcm_keymat *aes_gcm = &attrs->aes_gcm; ··· 135 157 memcpy(&aes_gcm->salt, x->aead->alg_key + key_len, 136 158 sizeof(aes_gcm->salt)); 137 159 160 + attrs->authsize = crypto_aead_authsize(aead) / 4; /* in dwords */ 161 + 138 162 /* iv len */ 139 163 aes_gcm->icv_len = x->aead->alg_icv_len; 140 164 141 165 /* esn */ 142 166 if (sa_entry->esn_state.trigger) { 143 - attrs->flags |= MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED; 167 + attrs->esn_trigger = true; 144 168 attrs->esn = sa_entry->esn_state.esn; 145 - if (sa_entry->esn_state.overlap) 146 - attrs->flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; 169 + attrs->esn_overlap = sa_entry->esn_state.overlap; 170 + attrs->replay_window = x->replay_esn->replay_window; 147 171 } 148 172 149 - /* action */ 150 - attrs->action = (x->xso.dir == XFRM_DEV_OFFLOAD_OUT) ? 151 - MLX5_ACCEL_ESP_ACTION_ENCRYPT : 152 - MLX5_ACCEL_ESP_ACTION_DECRYPT; 153 - /* flags */ 154 - attrs->flags |= (x->props.mode == XFRM_MODE_TRANSPORT) ? 155 - MLX5_ACCEL_ESP_FLAGS_TRANSPORT : 156 - MLX5_ACCEL_ESP_FLAGS_TUNNEL; 157 - 173 + attrs->dir = x->xso.dir; 158 174 /* spi */ 159 175 attrs->spi = be32_to_cpu(x->id.spi); 160 176 161 177 /* source , destination ips */ 162 178 memcpy(&attrs->saddr, x->props.saddr.a6, sizeof(attrs->saddr)); 163 179 memcpy(&attrs->daddr, x->id.daddr.a6, sizeof(attrs->daddr)); 164 - attrs->is_ipv6 = (x->props.family != AF_INET); 180 + attrs->family = x->props.family; 181 + attrs->type = x->xso.type; 182 + attrs->reqid = x->props.reqid; 183 + 184 + mlx5e_ipsec_init_limits(sa_entry, attrs); 165 185 } 166 186 167 187 static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x) ··· 189 213 if (x->props.family != AF_INET && 190 214 x->props.family != AF_INET6) { 191 215 netdev_info(netdev, "Only IPv4/6 xfrm states may be offloaded\n"); 192 - return -EINVAL; 193 - } 194 - if (x->props.mode != XFRM_MODE_TRANSPORT && 195 - x->props.mode != XFRM_MODE_TUNNEL) { 196 - dev_info(&netdev->dev, "Only transport and tunnel xfrm states may be offloaded\n"); 197 216 return -EINVAL; 198 217 } 199 218 if (x->id.proto != IPPROTO_ESP) { ··· 224 253 netdev_info(netdev, "Cannot offload xfrm states with geniv other than seqiv\n"); 225 254 return -EINVAL; 226 255 } 256 + switch (x->xso.type) { 257 + case XFRM_DEV_OFFLOAD_CRYPTO: 258 + if (!(mlx5_ipsec_device_caps(priv->mdev) & 259 + MLX5_IPSEC_CAP_CRYPTO)) { 260 + netdev_info(netdev, "Crypto offload is not supported\n"); 261 + return -EINVAL; 262 + } 263 + 264 + if (x->props.mode != XFRM_MODE_TRANSPORT && 265 + x->props.mode != XFRM_MODE_TUNNEL) { 266 + netdev_info(netdev, "Only transport and tunnel xfrm states may be offloaded\n"); 267 + return -EINVAL; 268 + } 269 + break; 270 + case XFRM_DEV_OFFLOAD_PACKET: 271 + if (!(mlx5_ipsec_device_caps(priv->mdev) & 272 + MLX5_IPSEC_CAP_PACKET_OFFLOAD)) { 273 + netdev_info(netdev, "Packet offload is not supported\n"); 274 + return -EINVAL; 275 + } 276 + 277 + if (x->props.mode != XFRM_MODE_TRANSPORT) { 278 + netdev_info(netdev, "Only transport xfrm states may be offloaded in packet mode\n"); 279 + return -EINVAL; 280 + } 281 + 282 + if (x->replay_esn && x->replay_esn->replay_window != 32 && 283 + x->replay_esn->replay_window != 64 && 284 + x->replay_esn->replay_window != 128 && 285 + x->replay_esn->replay_window != 256) { 286 + netdev_info(netdev, 287 + "Unsupported replay window size %u\n", 288 + x->replay_esn->replay_window); 289 + return -EINVAL; 290 + } 291 + 292 + if (!x->props.reqid) { 293 + netdev_info(netdev, "Cannot offload without reqid\n"); 294 + return -EINVAL; 295 + } 296 + 297 + if (x->lft.hard_byte_limit != XFRM_INF || 298 + x->lft.soft_byte_limit != XFRM_INF) { 299 + netdev_info(netdev, 300 + "Device doesn't support limits in bytes\n"); 301 + return -EINVAL; 302 + } 303 + 304 + if (x->lft.soft_packet_limit >= x->lft.hard_packet_limit && 305 + x->lft.hard_packet_limit != XFRM_INF) { 306 + /* XFRM stack doesn't prevent such configuration :(. */ 307 + netdev_info(netdev, 308 + "Hard packet limit must be greater than soft one\n"); 309 + return -EINVAL; 310 + } 311 + break; 312 + default: 313 + netdev_info(netdev, "Unsupported xfrm offload type %d\n", 314 + x->xso.type); 315 + return -EINVAL; 316 + } 227 317 return 0; 228 318 } 229 319 ··· 302 270 { 303 271 struct mlx5e_ipsec_sa_entry *sa_entry = NULL; 304 272 struct net_device *netdev = x->xso.real_dev; 273 + struct mlx5e_ipsec *ipsec; 305 274 struct mlx5e_priv *priv; 306 275 int err; 307 276 ··· 310 277 if (!priv->ipsec) 311 278 return -EOPNOTSUPP; 312 279 280 + ipsec = priv->ipsec; 313 281 err = mlx5e_xfrm_validate_state(x); 314 282 if (err) 315 283 return err; ··· 322 288 } 323 289 324 290 sa_entry->x = x; 325 - sa_entry->ipsec = priv->ipsec; 291 + sa_entry->ipsec = ipsec; 326 292 327 293 /* check esn */ 328 294 mlx5e_ipsec_update_esn_state(sa_entry); ··· 333 299 if (err) 334 300 goto err_xfrm; 335 301 336 - err = mlx5e_accel_ipsec_fs_add_rule(priv, sa_entry); 302 + err = mlx5e_accel_ipsec_fs_add_rule(sa_entry); 337 303 if (err) 338 304 goto err_hw_ctx; 339 305 340 - if (x->xso.dir == XFRM_DEV_OFFLOAD_IN) { 341 - err = mlx5e_ipsec_sadb_rx_add(sa_entry); 342 - if (err) 343 - goto err_add_rule; 344 - } else { 306 + /* We use *_bh() variant because xfrm_timer_handler(), which runs 307 + * in softirq context, can reach our state delete logic and we need 308 + * xa_erase_bh() there. 309 + */ 310 + err = xa_insert_bh(&ipsec->sadb, sa_entry->ipsec_obj_id, sa_entry, 311 + GFP_KERNEL); 312 + if (err) 313 + goto err_add_rule; 314 + 315 + if (x->xso.dir == XFRM_DEV_OFFLOAD_OUT) 345 316 sa_entry->set_iv_op = (x->props.flags & XFRM_STATE_ESN) ? 346 317 mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv; 347 - } 348 318 349 319 INIT_WORK(&sa_entry->modify_work.work, _update_xfrm_state); 350 320 x->xso.offload_handle = (unsigned long)sa_entry; 351 - goto out; 321 + return 0; 352 322 353 323 err_add_rule: 354 - mlx5e_accel_ipsec_fs_del_rule(priv, sa_entry); 324 + mlx5e_accel_ipsec_fs_del_rule(sa_entry); 355 325 err_hw_ctx: 356 326 mlx5_ipsec_free_sa_ctx(sa_entry); 357 327 err_xfrm: ··· 367 329 static void mlx5e_xfrm_del_state(struct xfrm_state *x) 368 330 { 369 331 struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); 332 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 333 + struct mlx5e_ipsec_sa_entry *old; 370 334 371 - if (x->xso.dir == XFRM_DEV_OFFLOAD_IN) 372 - mlx5e_ipsec_sadb_rx_del(sa_entry); 335 + old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id); 336 + WARN_ON(old != sa_entry); 373 337 } 374 338 375 339 static void mlx5e_xfrm_free_state(struct xfrm_state *x) 376 340 { 377 341 struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); 378 - struct mlx5e_priv *priv = netdev_priv(x->xso.dev); 379 342 380 343 cancel_work_sync(&sa_entry->modify_work.work); 381 - mlx5e_accel_ipsec_fs_del_rule(priv, sa_entry); 344 + mlx5e_accel_ipsec_fs_del_rule(sa_entry); 382 345 mlx5_ipsec_free_sa_ctx(sa_entry); 383 346 kfree(sa_entry); 384 347 } ··· 398 359 if (!ipsec) 399 360 return; 400 361 401 - hash_init(ipsec->sadb_rx); 402 - spin_lock_init(&ipsec->sadb_rx_lock); 362 + xa_init_flags(&ipsec->sadb, XA_FLAGS_ALLOC); 403 363 ipsec->mdev = priv->mdev; 404 364 ipsec->wq = alloc_ordered_workqueue("mlx5e_ipsec: %s", 0, 405 365 priv->netdev->name); 406 366 if (!ipsec->wq) 407 367 goto err_wq; 408 368 369 + if (mlx5_ipsec_device_caps(priv->mdev) & 370 + MLX5_IPSEC_CAP_PACKET_OFFLOAD) { 371 + ret = mlx5e_ipsec_aso_init(ipsec); 372 + if (ret) 373 + goto err_aso; 374 + } 375 + 409 376 ret = mlx5e_accel_ipsec_fs_init(ipsec); 410 377 if (ret) 411 378 goto err_fs_init; 412 379 380 + ipsec->fs = priv->fs; 413 381 priv->ipsec = ipsec; 414 382 netdev_dbg(priv->netdev, "IPSec attached to netdevice\n"); 415 383 return; 416 384 417 385 err_fs_init: 386 + if (mlx5_ipsec_device_caps(priv->mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD) 387 + mlx5e_ipsec_aso_cleanup(ipsec); 388 + err_aso: 418 389 destroy_workqueue(ipsec->wq); 419 390 err_wq: 420 391 kfree(ipsec); ··· 440 391 return; 441 392 442 393 mlx5e_accel_ipsec_fs_cleanup(ipsec); 394 + if (mlx5_ipsec_device_caps(priv->mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD) 395 + mlx5e_ipsec_aso_cleanup(ipsec); 443 396 destroy_workqueue(ipsec->wq); 444 397 kfree(ipsec); 445 398 priv->ipsec = NULL; ··· 477 426 queue_work(sa_entry->ipsec->wq, &modify_work->work); 478 427 } 479 428 429 + static void mlx5e_xfrm_update_curlft(struct xfrm_state *x) 430 + { 431 + struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); 432 + int err; 433 + 434 + lockdep_assert_held(&x->lock); 435 + 436 + if (sa_entry->attrs.soft_packet_limit == XFRM_INF) 437 + /* Limits are not configured, as soft limit 438 + * must be lowever than hard limit. 439 + */ 440 + return; 441 + 442 + err = mlx5e_ipsec_aso_query(sa_entry, NULL); 443 + if (err) 444 + return; 445 + 446 + mlx5e_ipsec_aso_update_curlft(sa_entry, &x->curlft.packets); 447 + } 448 + 449 + static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x) 450 + { 451 + struct net_device *netdev = x->xdo.real_dev; 452 + 453 + if (x->type != XFRM_POLICY_TYPE_MAIN) { 454 + netdev_info(netdev, "Cannot offload non-main policy types\n"); 455 + return -EINVAL; 456 + } 457 + 458 + /* Please pay attention that we support only one template */ 459 + if (x->xfrm_nr > 1) { 460 + netdev_info(netdev, "Cannot offload more than one template\n"); 461 + return -EINVAL; 462 + } 463 + 464 + if (x->xdo.dir != XFRM_DEV_OFFLOAD_IN && 465 + x->xdo.dir != XFRM_DEV_OFFLOAD_OUT) { 466 + netdev_info(netdev, "Cannot offload forward policy\n"); 467 + return -EINVAL; 468 + } 469 + 470 + if (!x->xfrm_vec[0].reqid) { 471 + netdev_info(netdev, "Cannot offload policy without reqid\n"); 472 + return -EINVAL; 473 + } 474 + 475 + if (x->xdo.type != XFRM_DEV_OFFLOAD_PACKET) { 476 + netdev_info(netdev, "Unsupported xfrm offload type\n"); 477 + return -EINVAL; 478 + } 479 + 480 + return 0; 481 + } 482 + 483 + static void 484 + mlx5e_ipsec_build_accel_pol_attrs(struct mlx5e_ipsec_pol_entry *pol_entry, 485 + struct mlx5_accel_pol_xfrm_attrs *attrs) 486 + { 487 + struct xfrm_policy *x = pol_entry->x; 488 + struct xfrm_selector *sel; 489 + 490 + sel = &x->selector; 491 + memset(attrs, 0, sizeof(*attrs)); 492 + 493 + memcpy(&attrs->saddr, sel->saddr.a6, sizeof(attrs->saddr)); 494 + memcpy(&attrs->daddr, sel->daddr.a6, sizeof(attrs->daddr)); 495 + attrs->family = sel->family; 496 + attrs->dir = x->xdo.dir; 497 + attrs->action = x->action; 498 + attrs->type = XFRM_DEV_OFFLOAD_PACKET; 499 + attrs->reqid = x->xfrm_vec[0].reqid; 500 + } 501 + 502 + static int mlx5e_xfrm_add_policy(struct xfrm_policy *x) 503 + { 504 + struct net_device *netdev = x->xdo.real_dev; 505 + struct mlx5e_ipsec_pol_entry *pol_entry; 506 + struct mlx5e_priv *priv; 507 + int err; 508 + 509 + priv = netdev_priv(netdev); 510 + if (!priv->ipsec) 511 + return -EOPNOTSUPP; 512 + 513 + err = mlx5e_xfrm_validate_policy(x); 514 + if (err) 515 + return err; 516 + 517 + pol_entry = kzalloc(sizeof(*pol_entry), GFP_KERNEL); 518 + if (!pol_entry) 519 + return -ENOMEM; 520 + 521 + pol_entry->x = x; 522 + pol_entry->ipsec = priv->ipsec; 523 + 524 + mlx5e_ipsec_build_accel_pol_attrs(pol_entry, &pol_entry->attrs); 525 + err = mlx5e_accel_ipsec_fs_add_pol(pol_entry); 526 + if (err) 527 + goto err_fs; 528 + 529 + x->xdo.offload_handle = (unsigned long)pol_entry; 530 + return 0; 531 + 532 + err_fs: 533 + kfree(pol_entry); 534 + return err; 535 + } 536 + 537 + static void mlx5e_xfrm_free_policy(struct xfrm_policy *x) 538 + { 539 + struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x); 540 + 541 + mlx5e_accel_ipsec_fs_del_pol(pol_entry); 542 + kfree(pol_entry); 543 + } 544 + 480 545 static const struct xfrmdev_ops mlx5e_ipsec_xfrmdev_ops = { 481 546 .xdo_dev_state_add = mlx5e_xfrm_add_state, 482 547 .xdo_dev_state_delete = mlx5e_xfrm_del_state, 483 548 .xdo_dev_state_free = mlx5e_xfrm_free_state, 484 549 .xdo_dev_offload_ok = mlx5e_ipsec_offload_ok, 485 550 .xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state, 551 + }; 552 + 553 + static const struct xfrmdev_ops mlx5e_ipsec_packet_xfrmdev_ops = { 554 + .xdo_dev_state_add = mlx5e_xfrm_add_state, 555 + .xdo_dev_state_delete = mlx5e_xfrm_del_state, 556 + .xdo_dev_state_free = mlx5e_xfrm_free_state, 557 + .xdo_dev_offload_ok = mlx5e_ipsec_offload_ok, 558 + .xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state, 559 + 560 + .xdo_dev_state_update_curlft = mlx5e_xfrm_update_curlft, 561 + .xdo_dev_policy_add = mlx5e_xfrm_add_policy, 562 + .xdo_dev_policy_free = mlx5e_xfrm_free_policy, 486 563 }; 487 564 488 565 void mlx5e_ipsec_build_netdev(struct mlx5e_priv *priv) ··· 622 443 return; 623 444 624 445 mlx5_core_info(mdev, "mlx5e: IPSec ESP acceleration enabled\n"); 625 - netdev->xfrmdev_ops = &mlx5e_ipsec_xfrmdev_ops; 446 + 447 + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD) 448 + netdev->xfrmdev_ops = &mlx5e_ipsec_packet_xfrmdev_ops; 449 + else 450 + netdev->xfrmdev_ops = &mlx5e_ipsec_xfrmdev_ops; 451 + 626 452 netdev->features |= NETIF_F_HW_ESP; 627 453 netdev->hw_enc_features |= NETIF_F_HW_ESP; 628 454
+101 -31
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
··· 34 34 #ifndef __MLX5E_IPSEC_H__ 35 35 #define __MLX5E_IPSEC_H__ 36 36 37 - #ifdef CONFIG_MLX5_EN_IPSEC 38 - 39 37 #include <linux/mlx5/device.h> 40 38 #include <net/xfrm.h> 41 39 #include <linux/idr.h> 40 + #include "lib/aso.h" 42 41 43 42 #define MLX5E_IPSEC_SADB_RX_BITS 10 44 43 #define MLX5E_IPSEC_ESN_SCOPE_MID 0x80000000L 45 - 46 - enum mlx5_accel_esp_flags { 47 - MLX5_ACCEL_ESP_FLAGS_TUNNEL = 0, /* Default */ 48 - MLX5_ACCEL_ESP_FLAGS_TRANSPORT = 1UL << 0, 49 - MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED = 1UL << 1, 50 - MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP = 1UL << 2, 51 - }; 52 - 53 - enum mlx5_accel_esp_action { 54 - MLX5_ACCEL_ESP_ACTION_DECRYPT, 55 - MLX5_ACCEL_ESP_ACTION_ENCRYPT, 56 - }; 57 44 58 45 struct aes_gcm_keymat { 59 46 u64 seq_iv; ··· 53 66 }; 54 67 55 68 struct mlx5_accel_esp_xfrm_attrs { 56 - enum mlx5_accel_esp_action action; 57 69 u32 esn; 58 70 u32 spi; 59 71 u32 flags; ··· 68 82 __be32 a6[4]; 69 83 } daddr; 70 84 71 - u8 is_ipv6; 85 + u8 dir : 2; 86 + u8 esn_overlap : 1; 87 + u8 esn_trigger : 1; 88 + u8 type : 2; 89 + u8 family; 90 + u32 replay_window; 91 + u32 authsize; 92 + u32 reqid; 93 + u64 hard_packet_limit; 94 + u64 soft_packet_limit; 72 95 }; 73 96 74 97 enum mlx5_ipsec_cap { 75 98 MLX5_IPSEC_CAP_CRYPTO = 1 << 0, 76 99 MLX5_IPSEC_CAP_ESN = 1 << 1, 100 + MLX5_IPSEC_CAP_PACKET_OFFLOAD = 1 << 2, 77 101 }; 78 102 79 103 struct mlx5e_priv; 104 + 105 + struct mlx5e_ipsec_hw_stats { 106 + u64 ipsec_rx_pkts; 107 + u64 ipsec_rx_bytes; 108 + u64 ipsec_rx_drop_pkts; 109 + u64 ipsec_rx_drop_bytes; 110 + u64 ipsec_tx_pkts; 111 + u64 ipsec_tx_bytes; 112 + u64 ipsec_tx_drop_pkts; 113 + u64 ipsec_tx_drop_bytes; 114 + }; 80 115 81 116 struct mlx5e_ipsec_sw_stats { 82 117 atomic64_t ipsec_rx_drop_sp_alloc; ··· 109 102 atomic64_t ipsec_tx_drop_trailer; 110 103 }; 111 104 112 - struct mlx5e_accel_fs_esp; 105 + struct mlx5e_ipsec_rx; 113 106 struct mlx5e_ipsec_tx; 107 + 108 + struct mlx5e_ipsec_work { 109 + struct work_struct work; 110 + struct mlx5e_ipsec *ipsec; 111 + u32 id; 112 + }; 113 + 114 + struct mlx5e_ipsec_aso { 115 + u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)]; 116 + dma_addr_t dma_addr; 117 + struct mlx5_aso *aso; 118 + /* IPsec ASO caches data on every query call, 119 + * so in nested calls, we can use this boolean to save 120 + * recursive calls to mlx5e_ipsec_aso_query() 121 + */ 122 + u8 use_cache : 1; 123 + }; 114 124 115 125 struct mlx5e_ipsec { 116 126 struct mlx5_core_dev *mdev; 117 - DECLARE_HASHTABLE(sadb_rx, MLX5E_IPSEC_SADB_RX_BITS); 118 - spinlock_t sadb_rx_lock; /* Protects sadb_rx */ 127 + struct xarray sadb; 119 128 struct mlx5e_ipsec_sw_stats sw_stats; 129 + struct mlx5e_ipsec_hw_stats hw_stats; 120 130 struct workqueue_struct *wq; 121 - struct mlx5e_accel_fs_esp *rx_fs; 122 - struct mlx5e_ipsec_tx *tx_fs; 131 + struct mlx5e_flow_steering *fs; 132 + struct mlx5e_ipsec_rx *rx_ipv4; 133 + struct mlx5e_ipsec_rx *rx_ipv6; 134 + struct mlx5e_ipsec_tx *tx; 135 + struct mlx5e_ipsec_aso *aso; 136 + struct notifier_block nb; 123 137 }; 124 138 125 139 struct mlx5e_ipsec_esn_state { ··· 151 123 152 124 struct mlx5e_ipsec_rule { 153 125 struct mlx5_flow_handle *rule; 154 - struct mlx5_modify_hdr *set_modify_hdr; 126 + struct mlx5_modify_hdr *modify_hdr; 127 + struct mlx5_pkt_reformat *pkt_reformat; 155 128 }; 156 129 157 130 struct mlx5e_ipsec_modify_state_work { ··· 161 132 }; 162 133 163 134 struct mlx5e_ipsec_sa_entry { 164 - struct hlist_node hlist; /* Item in SADB_RX hashtable */ 165 135 struct mlx5e_ipsec_esn_state esn_state; 166 - unsigned int handle; /* Handle in SADB_RX */ 167 136 struct xfrm_state *x; 168 137 struct mlx5e_ipsec *ipsec; 169 138 struct mlx5_accel_esp_xfrm_attrs attrs; ··· 173 146 struct mlx5e_ipsec_modify_state_work modify_work; 174 147 }; 175 148 149 + struct mlx5_accel_pol_xfrm_attrs { 150 + union { 151 + __be32 a4; 152 + __be32 a6[4]; 153 + } saddr; 154 + 155 + union { 156 + __be32 a4; 157 + __be32 a6[4]; 158 + } daddr; 159 + 160 + u8 family; 161 + u8 action; 162 + u8 type : 2; 163 + u8 dir : 2; 164 + u32 reqid; 165 + }; 166 + 167 + struct mlx5e_ipsec_pol_entry { 168 + struct xfrm_policy *x; 169 + struct mlx5e_ipsec *ipsec; 170 + struct mlx5e_ipsec_rule ipsec_rule; 171 + struct mlx5_accel_pol_xfrm_attrs attrs; 172 + }; 173 + 174 + #ifdef CONFIG_MLX5_EN_IPSEC 175 + 176 176 void mlx5e_ipsec_init(struct mlx5e_priv *priv); 177 177 void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv); 178 178 void mlx5e_ipsec_build_netdev(struct mlx5e_priv *priv); 179 179 180 - struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *dev, 181 - unsigned int handle); 182 - 183 180 void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec); 184 181 int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec); 185 - int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_priv *priv, 186 - struct mlx5e_ipsec_sa_entry *sa_entry); 187 - void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_priv *priv, 188 - struct mlx5e_ipsec_sa_entry *sa_entry); 182 + int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry); 183 + void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry); 184 + int mlx5e_accel_ipsec_fs_add_pol(struct mlx5e_ipsec_pol_entry *pol_entry); 185 + void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry); 189 186 190 187 int mlx5_ipsec_create_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry); 191 188 void mlx5_ipsec_free_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry); ··· 219 168 void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry, 220 169 const struct mlx5_accel_esp_xfrm_attrs *attrs); 221 170 171 + int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec); 172 + void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec); 173 + 174 + int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, 175 + struct mlx5_wqe_aso_ctrl_seg *data); 176 + void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry, 177 + u64 *packets); 178 + 179 + void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv, 180 + void *ipsec_stats); 181 + 182 + void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, 183 + struct mlx5_accel_esp_xfrm_attrs *attrs); 222 184 static inline struct mlx5_core_dev * 223 185 mlx5e_ipsec_sa2dev(struct mlx5e_ipsec_sa_entry *sa_entry) 224 186 { 225 187 return sa_entry->ipsec->mdev; 188 + } 189 + 190 + static inline struct mlx5_core_dev * 191 + mlx5e_ipsec_pol2dev(struct mlx5e_ipsec_pol_entry *pol_entry) 192 + { 193 + return pol_entry->ipsec->mdev; 226 194 } 227 195 #else 228 196 static inline void mlx5e_ipsec_init(struct mlx5e_priv *priv)
+786 -327
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
··· 9 9 10 10 #define NUM_IPSEC_FTE BIT(15) 11 11 12 - enum accel_fs_esp_type { 13 - ACCEL_FS_ESP4, 14 - ACCEL_FS_ESP6, 15 - ACCEL_FS_ESP_NUM_TYPES, 12 + struct mlx5e_ipsec_fc { 13 + struct mlx5_fc *cnt; 14 + struct mlx5_fc *drop; 16 15 }; 17 16 18 - struct mlx5e_ipsec_rx_err { 19 - struct mlx5_flow_table *ft; 20 - struct mlx5_flow_handle *rule; 21 - struct mlx5_modify_hdr *copy_modify_hdr; 22 - }; 23 - 24 - struct mlx5e_accel_fs_esp_prot { 25 - struct mlx5_flow_table *ft; 26 - struct mlx5_flow_group *miss_group; 27 - struct mlx5_flow_handle *miss_rule; 28 - struct mlx5_flow_destination default_dest; 29 - struct mlx5e_ipsec_rx_err rx_err; 17 + struct mlx5e_ipsec_ft { 18 + struct mutex mutex; /* Protect changes to this struct */ 19 + struct mlx5_flow_table *pol; 20 + struct mlx5_flow_table *sa; 21 + struct mlx5_flow_table *status; 30 22 u32 refcnt; 31 - struct mutex prot_mutex; /* protect ESP4/ESP6 protocol */ 32 23 }; 33 24 34 - struct mlx5e_accel_fs_esp { 35 - struct mlx5e_accel_fs_esp_prot fs_prot[ACCEL_FS_ESP_NUM_TYPES]; 25 + struct mlx5e_ipsec_miss { 26 + struct mlx5_flow_group *group; 27 + struct mlx5_flow_handle *rule; 28 + }; 29 + 30 + struct mlx5e_ipsec_rx { 31 + struct mlx5e_ipsec_ft ft; 32 + struct mlx5e_ipsec_miss pol; 33 + struct mlx5e_ipsec_miss sa; 34 + struct mlx5e_ipsec_rule status; 35 + struct mlx5e_ipsec_fc *fc; 36 36 }; 37 37 38 38 struct mlx5e_ipsec_tx { 39 + struct mlx5e_ipsec_ft ft; 40 + struct mlx5e_ipsec_miss pol; 39 41 struct mlx5_flow_namespace *ns; 40 - struct mlx5_flow_table *ft; 41 - struct mutex mutex; /* Protect IPsec TX steering */ 42 - u32 refcnt; 42 + struct mlx5e_ipsec_fc *fc; 43 43 }; 44 44 45 45 /* IPsec RX flow steering */ 46 - static enum mlx5_traffic_types fs_esp2tt(enum accel_fs_esp_type i) 46 + static enum mlx5_traffic_types family2tt(u32 family) 47 47 { 48 - if (i == ACCEL_FS_ESP4) 48 + if (family == AF_INET) 49 49 return MLX5_TT_IPV4_IPSEC_ESP; 50 50 return MLX5_TT_IPV6_IPSEC_ESP; 51 51 } 52 52 53 - static int rx_err_add_rule(struct mlx5e_priv *priv, 54 - struct mlx5e_accel_fs_esp_prot *fs_prot, 55 - struct mlx5e_ipsec_rx_err *rx_err) 53 + static struct mlx5_flow_table *ipsec_ft_create(struct mlx5_flow_namespace *ns, 54 + int level, int prio, 55 + int max_num_groups) 56 + { 57 + struct mlx5_flow_table_attr ft_attr = {}; 58 + 59 + ft_attr.autogroup.num_reserved_entries = 1; 60 + ft_attr.autogroup.max_num_groups = max_num_groups; 61 + ft_attr.max_fte = NUM_IPSEC_FTE; 62 + ft_attr.level = level; 63 + ft_attr.prio = prio; 64 + 65 + return mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 66 + } 67 + 68 + static int ipsec_status_rule(struct mlx5_core_dev *mdev, 69 + struct mlx5e_ipsec_rx *rx, 70 + struct mlx5_flow_destination *dest) 56 71 { 57 72 u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 58 - struct mlx5_core_dev *mdev = priv->mdev; 59 73 struct mlx5_flow_act flow_act = {}; 60 74 struct mlx5_modify_hdr *modify_hdr; 61 75 struct mlx5_flow_handle *fte; ··· 93 79 94 80 if (IS_ERR(modify_hdr)) { 95 81 err = PTR_ERR(modify_hdr); 96 - netdev_err(priv->netdev, 97 - "fail to alloc ipsec copy modify_header_id err=%d\n", err); 82 + mlx5_core_err(mdev, 83 + "fail to alloc ipsec copy modify_header_id err=%d\n", err); 98 84 goto out_spec; 99 85 } 100 86 101 87 /* create fte */ 102 88 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | 103 - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 89 + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 90 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 104 91 flow_act.modify_hdr = modify_hdr; 105 - fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, 106 - &fs_prot->default_dest, 1); 92 + fte = mlx5_add_flow_rules(rx->ft.status, spec, &flow_act, dest, 2); 107 93 if (IS_ERR(fte)) { 108 94 err = PTR_ERR(fte); 109 - netdev_err(priv->netdev, "fail to add ipsec rx err copy rule err=%d\n", err); 95 + mlx5_core_err(mdev, "fail to add ipsec rx err copy rule err=%d\n", err); 110 96 goto out; 111 97 } 112 98 113 99 kvfree(spec); 114 - rx_err->rule = fte; 115 - rx_err->copy_modify_hdr = modify_hdr; 100 + rx->status.rule = fte; 101 + rx->status.modify_hdr = modify_hdr; 116 102 return 0; 117 103 118 104 out: ··· 122 108 return err; 123 109 } 124 110 125 - static int rx_fs_create(struct mlx5e_priv *priv, 126 - struct mlx5e_accel_fs_esp_prot *fs_prot) 111 + static int ipsec_miss_create(struct mlx5_core_dev *mdev, 112 + struct mlx5_flow_table *ft, 113 + struct mlx5e_ipsec_miss *miss, 114 + struct mlx5_flow_destination *dest) 127 115 { 128 116 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 129 - struct mlx5_flow_table *ft = fs_prot->ft; 130 - struct mlx5_flow_group *miss_group; 131 - struct mlx5_flow_handle *miss_rule; 132 117 MLX5_DECLARE_FLOW_ACT(flow_act); 133 118 struct mlx5_flow_spec *spec; 134 119 u32 *flow_group_in; ··· 143 130 /* Create miss_group */ 144 131 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ft->max_fte - 1); 145 132 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ft->max_fte - 1); 146 - miss_group = mlx5_create_flow_group(ft, flow_group_in); 147 - if (IS_ERR(miss_group)) { 148 - err = PTR_ERR(miss_group); 149 - netdev_err(priv->netdev, "fail to create ipsec rx miss_group err=%d\n", err); 133 + miss->group = mlx5_create_flow_group(ft, flow_group_in); 134 + if (IS_ERR(miss->group)) { 135 + err = PTR_ERR(miss->group); 136 + mlx5_core_err(mdev, "fail to create IPsec miss_group err=%d\n", 137 + err); 150 138 goto out; 151 139 } 152 - fs_prot->miss_group = miss_group; 153 140 154 141 /* Create miss rule */ 155 - miss_rule = mlx5_add_flow_rules(ft, spec, &flow_act, &fs_prot->default_dest, 1); 156 - if (IS_ERR(miss_rule)) { 157 - mlx5_destroy_flow_group(fs_prot->miss_group); 158 - err = PTR_ERR(miss_rule); 159 - netdev_err(priv->netdev, "fail to create ipsec rx miss_rule err=%d\n", err); 142 + miss->rule = mlx5_add_flow_rules(ft, spec, &flow_act, dest, 1); 143 + if (IS_ERR(miss->rule)) { 144 + mlx5_destroy_flow_group(miss->group); 145 + err = PTR_ERR(miss->rule); 146 + mlx5_core_err(mdev, "fail to create IPsec miss_rule err=%d\n", 147 + err); 160 148 goto out; 161 149 } 162 - fs_prot->miss_rule = miss_rule; 163 150 out: 164 151 kvfree(flow_group_in); 165 152 kvfree(spec); 166 153 return err; 167 154 } 168 155 169 - static void rx_destroy(struct mlx5e_priv *priv, enum accel_fs_esp_type type) 156 + static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_rx *rx) 170 157 { 171 - struct mlx5e_accel_fs_esp_prot *fs_prot; 172 - struct mlx5e_accel_fs_esp *accel_esp; 158 + mlx5_del_flow_rules(rx->pol.rule); 159 + mlx5_destroy_flow_group(rx->pol.group); 160 + mlx5_destroy_flow_table(rx->ft.pol); 173 161 174 - accel_esp = priv->ipsec->rx_fs; 162 + mlx5_del_flow_rules(rx->sa.rule); 163 + mlx5_destroy_flow_group(rx->sa.group); 164 + mlx5_destroy_flow_table(rx->ft.sa); 175 165 176 - /* The netdev unreg already happened, so all offloaded rule are already removed */ 177 - fs_prot = &accel_esp->fs_prot[type]; 178 - 179 - mlx5_del_flow_rules(fs_prot->miss_rule); 180 - mlx5_destroy_flow_group(fs_prot->miss_group); 181 - mlx5_destroy_flow_table(fs_prot->ft); 182 - 183 - mlx5_del_flow_rules(fs_prot->rx_err.rule); 184 - mlx5_modify_header_dealloc(priv->mdev, fs_prot->rx_err.copy_modify_hdr); 185 - mlx5_destroy_flow_table(fs_prot->rx_err.ft); 166 + mlx5_del_flow_rules(rx->status.rule); 167 + mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 168 + mlx5_destroy_flow_table(rx->ft.status); 186 169 } 187 170 188 - static int rx_create(struct mlx5e_priv *priv, enum accel_fs_esp_type type) 171 + static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, 172 + struct mlx5e_ipsec_rx *rx, u32 family) 189 173 { 190 - struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(priv->fs, false); 191 - struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(priv->fs, false); 192 - struct mlx5_flow_table_attr ft_attr = {}; 193 - struct mlx5e_accel_fs_esp_prot *fs_prot; 194 - struct mlx5e_accel_fs_esp *accel_esp; 174 + struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(ipsec->fs, false); 175 + struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 176 + struct mlx5_flow_destination dest[2]; 195 177 struct mlx5_flow_table *ft; 196 178 int err; 197 179 198 - accel_esp = priv->ipsec->rx_fs; 199 - fs_prot = &accel_esp->fs_prot[type]; 200 - fs_prot->default_dest = 201 - mlx5_ttc_get_default_dest(ttc, fs_esp2tt(type)); 202 - 203 - ft_attr.max_fte = 1; 204 - ft_attr.autogroup.max_num_groups = 1; 205 - ft_attr.level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; 206 - ft_attr.prio = MLX5E_NIC_PRIO; 207 - ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 180 + ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, 181 + MLX5E_NIC_PRIO, 1); 208 182 if (IS_ERR(ft)) 209 183 return PTR_ERR(ft); 210 184 211 - fs_prot->rx_err.ft = ft; 212 - err = rx_err_add_rule(priv, fs_prot, &fs_prot->rx_err); 185 + rx->ft.status = ft; 186 + 187 + dest[0] = mlx5_ttc_get_default_dest(ttc, family2tt(family)); 188 + dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 189 + dest[1].counter_id = mlx5_fc_id(rx->fc->cnt); 190 + err = ipsec_status_rule(mdev, rx, dest); 213 191 if (err) 214 192 goto err_add; 215 193 216 194 /* Create FT */ 217 - ft_attr.max_fte = NUM_IPSEC_FTE; 218 - ft_attr.level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; 219 - ft_attr.prio = MLX5E_NIC_PRIO; 220 - ft_attr.autogroup.num_reserved_entries = 1; 221 - ft_attr.autogroup.max_num_groups = 1; 222 - ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 195 + ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_LEVEL, MLX5E_NIC_PRIO, 196 + 2); 223 197 if (IS_ERR(ft)) { 224 198 err = PTR_ERR(ft); 225 199 goto err_fs_ft; 226 200 } 227 - fs_prot->ft = ft; 201 + rx->ft.sa = ft; 228 202 229 - err = rx_fs_create(priv, fs_prot); 203 + err = ipsec_miss_create(mdev, rx->ft.sa, &rx->sa, dest); 230 204 if (err) 231 205 goto err_fs; 232 206 207 + ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_POL_FT_LEVEL, MLX5E_NIC_PRIO, 208 + 2); 209 + if (IS_ERR(ft)) { 210 + err = PTR_ERR(ft); 211 + goto err_pol_ft; 212 + } 213 + rx->ft.pol = ft; 214 + memset(dest, 0x00, 2 * sizeof(*dest)); 215 + dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 216 + dest[0].ft = rx->ft.sa; 217 + err = ipsec_miss_create(mdev, rx->ft.pol, &rx->pol, dest); 218 + if (err) 219 + goto err_pol_miss; 220 + 233 221 return 0; 234 222 223 + err_pol_miss: 224 + mlx5_destroy_flow_table(rx->ft.pol); 225 + err_pol_ft: 226 + mlx5_del_flow_rules(rx->sa.rule); 227 + mlx5_destroy_flow_group(rx->sa.group); 235 228 err_fs: 236 - mlx5_destroy_flow_table(fs_prot->ft); 229 + mlx5_destroy_flow_table(rx->ft.sa); 237 230 err_fs_ft: 238 - mlx5_del_flow_rules(fs_prot->rx_err.rule); 239 - mlx5_modify_header_dealloc(priv->mdev, fs_prot->rx_err.copy_modify_hdr); 231 + mlx5_del_flow_rules(rx->status.rule); 232 + mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 240 233 err_add: 241 - mlx5_destroy_flow_table(fs_prot->rx_err.ft); 234 + mlx5_destroy_flow_table(rx->ft.status); 242 235 return err; 243 236 } 244 237 245 - static int rx_ft_get(struct mlx5e_priv *priv, enum accel_fs_esp_type type) 238 + static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, 239 + struct mlx5e_ipsec *ipsec, u32 family) 246 240 { 247 - struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(priv->fs, false); 248 - struct mlx5e_accel_fs_esp_prot *fs_prot; 241 + struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 249 242 struct mlx5_flow_destination dest = {}; 250 - struct mlx5e_accel_fs_esp *accel_esp; 243 + struct mlx5e_ipsec_rx *rx; 251 244 int err = 0; 252 245 253 - accel_esp = priv->ipsec->rx_fs; 254 - fs_prot = &accel_esp->fs_prot[type]; 255 - mutex_lock(&fs_prot->prot_mutex); 256 - if (fs_prot->refcnt) 246 + if (family == AF_INET) 247 + rx = ipsec->rx_ipv4; 248 + else 249 + rx = ipsec->rx_ipv6; 250 + 251 + mutex_lock(&rx->ft.mutex); 252 + if (rx->ft.refcnt) 257 253 goto skip; 258 254 259 255 /* create FT */ 260 - err = rx_create(priv, type); 256 + err = rx_create(mdev, ipsec, rx, family); 261 257 if (err) 262 258 goto out; 263 259 264 260 /* connect */ 265 261 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 266 - dest.ft = fs_prot->ft; 267 - mlx5_ttc_fwd_dest(ttc, fs_esp2tt(type), &dest); 262 + dest.ft = rx->ft.pol; 263 + mlx5_ttc_fwd_dest(ttc, family2tt(family), &dest); 268 264 269 265 skip: 270 - fs_prot->refcnt++; 266 + rx->ft.refcnt++; 271 267 out: 272 - mutex_unlock(&fs_prot->prot_mutex); 273 - return err; 268 + mutex_unlock(&rx->ft.mutex); 269 + if (err) 270 + return ERR_PTR(err); 271 + return rx; 274 272 } 275 273 276 - static void rx_ft_put(struct mlx5e_priv *priv, enum accel_fs_esp_type type) 274 + static void rx_ft_put(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, 275 + u32 family) 277 276 { 278 - struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(priv->fs, false); 279 - struct mlx5e_accel_fs_esp_prot *fs_prot; 280 - struct mlx5e_accel_fs_esp *accel_esp; 277 + struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 278 + struct mlx5e_ipsec_rx *rx; 281 279 282 - accel_esp = priv->ipsec->rx_fs; 283 - fs_prot = &accel_esp->fs_prot[type]; 284 - mutex_lock(&fs_prot->prot_mutex); 285 - fs_prot->refcnt--; 286 - if (fs_prot->refcnt) 280 + if (family == AF_INET) 281 + rx = ipsec->rx_ipv4; 282 + else 283 + rx = ipsec->rx_ipv6; 284 + 285 + mutex_lock(&rx->ft.mutex); 286 + rx->ft.refcnt--; 287 + if (rx->ft.refcnt) 287 288 goto out; 288 289 289 290 /* disconnect */ 290 - mlx5_ttc_fwd_default_dest(ttc, fs_esp2tt(type)); 291 + mlx5_ttc_fwd_default_dest(ttc, family2tt(family)); 291 292 292 293 /* remove FT */ 293 - rx_destroy(priv, type); 294 + rx_destroy(mdev, rx); 294 295 295 296 out: 296 - mutex_unlock(&fs_prot->prot_mutex); 297 + mutex_unlock(&rx->ft.mutex); 297 298 } 298 299 299 300 /* IPsec TX flow steering */ 300 - static int tx_create(struct mlx5e_priv *priv) 301 + static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx) 301 302 { 302 - struct mlx5_flow_table_attr ft_attr = {}; 303 - struct mlx5e_ipsec *ipsec = priv->ipsec; 303 + struct mlx5_flow_destination dest = {}; 304 304 struct mlx5_flow_table *ft; 305 305 int err; 306 306 307 - ft_attr.max_fte = NUM_IPSEC_FTE; 308 - ft_attr.autogroup.max_num_groups = 1; 309 - ft = mlx5_create_auto_grouped_flow_table(ipsec->tx_fs->ns, &ft_attr); 307 + ft = ipsec_ft_create(tx->ns, 1, 0, 4); 308 + if (IS_ERR(ft)) 309 + return PTR_ERR(ft); 310 + 311 + tx->ft.sa = ft; 312 + 313 + ft = ipsec_ft_create(tx->ns, 0, 0, 2); 310 314 if (IS_ERR(ft)) { 311 315 err = PTR_ERR(ft); 312 - netdev_err(priv->netdev, "fail to create ipsec tx ft err=%d\n", err); 313 - return err; 316 + goto err_pol_ft; 314 317 } 315 - ipsec->tx_fs->ft = ft; 318 + tx->ft.pol = ft; 319 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 320 + dest.ft = tx->ft.sa; 321 + err = ipsec_miss_create(mdev, tx->ft.pol, &tx->pol, &dest); 322 + if (err) 323 + goto err_pol_miss; 316 324 return 0; 325 + 326 + err_pol_miss: 327 + mlx5_destroy_flow_table(tx->ft.pol); 328 + err_pol_ft: 329 + mlx5_destroy_flow_table(tx->ft.sa); 330 + return err; 317 331 } 318 332 319 - static int tx_ft_get(struct mlx5e_priv *priv) 333 + static struct mlx5e_ipsec_tx *tx_ft_get(struct mlx5_core_dev *mdev, 334 + struct mlx5e_ipsec *ipsec) 320 335 { 321 - struct mlx5e_ipsec_tx *tx_fs = priv->ipsec->tx_fs; 336 + struct mlx5e_ipsec_tx *tx = ipsec->tx; 322 337 int err = 0; 323 338 324 - mutex_lock(&tx_fs->mutex); 325 - if (tx_fs->refcnt) 339 + mutex_lock(&tx->ft.mutex); 340 + if (tx->ft.refcnt) 326 341 goto skip; 327 342 328 - err = tx_create(priv); 343 + err = tx_create(mdev, tx); 329 344 if (err) 330 345 goto out; 331 346 skip: 332 - tx_fs->refcnt++; 347 + tx->ft.refcnt++; 333 348 out: 334 - mutex_unlock(&tx_fs->mutex); 335 - return err; 349 + mutex_unlock(&tx->ft.mutex); 350 + if (err) 351 + return ERR_PTR(err); 352 + return tx; 336 353 } 337 354 338 - static void tx_ft_put(struct mlx5e_priv *priv) 355 + static void tx_ft_put(struct mlx5e_ipsec *ipsec) 339 356 { 340 - struct mlx5e_ipsec_tx *tx_fs = priv->ipsec->tx_fs; 357 + struct mlx5e_ipsec_tx *tx = ipsec->tx; 341 358 342 - mutex_lock(&tx_fs->mutex); 343 - tx_fs->refcnt--; 344 - if (tx_fs->refcnt) 359 + mutex_lock(&tx->ft.mutex); 360 + tx->ft.refcnt--; 361 + if (tx->ft.refcnt) 345 362 goto out; 346 363 347 - mlx5_destroy_flow_table(tx_fs->ft); 364 + mlx5_del_flow_rules(tx->pol.rule); 365 + mlx5_destroy_flow_group(tx->pol.group); 366 + mlx5_destroy_flow_table(tx->ft.pol); 367 + mlx5_destroy_flow_table(tx->ft.sa); 348 368 out: 349 - mutex_unlock(&tx_fs->mutex); 369 + mutex_unlock(&tx->ft.mutex); 350 370 } 351 371 352 - static void setup_fte_common(struct mlx5_accel_esp_xfrm_attrs *attrs, 353 - u32 ipsec_obj_id, 354 - struct mlx5_flow_spec *spec, 355 - struct mlx5_flow_act *flow_act) 372 + static void setup_fte_addr4(struct mlx5_flow_spec *spec, __be32 *saddr, 373 + __be32 *daddr) 356 374 { 357 - u8 ip_version = attrs->is_ipv6 ? 6 : 4; 375 + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 358 376 359 - spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS; 360 - 361 - /* ip_version */ 362 377 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version); 363 - MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, ip_version); 378 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 4); 364 379 365 - /* Non fragmented */ 366 - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.frag); 367 - MLX5_SET(fte_match_param, spec->match_value, outer_headers.frag, 0); 380 + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 381 + outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4), saddr, 4); 382 + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 383 + outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4), daddr, 4); 384 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 385 + outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4); 386 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 387 + outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 388 + } 368 389 390 + static void setup_fte_addr6(struct mlx5_flow_spec *spec, __be32 *saddr, 391 + __be32 *daddr) 392 + { 393 + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 394 + 395 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version); 396 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 6); 397 + 398 + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 399 + outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), saddr, 16); 400 + memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 401 + outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), daddr, 16); 402 + memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 403 + outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), 0xff, 16); 404 + memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 405 + outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 0xff, 16); 406 + } 407 + 408 + static void setup_fte_esp(struct mlx5_flow_spec *spec) 409 + { 369 410 /* ESP header */ 411 + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; 412 + 370 413 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol); 371 414 MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_ESP); 372 - 373 - /* SPI number */ 374 - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters.outer_esp_spi); 375 - MLX5_SET(fte_match_param, spec->match_value, 376 - misc_parameters.outer_esp_spi, attrs->spi); 377 - 378 - if (ip_version == 4) { 379 - memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 380 - outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4), 381 - &attrs->saddr.a4, 4); 382 - memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 383 - outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4), 384 - &attrs->daddr.a4, 4); 385 - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 386 - outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4); 387 - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 388 - outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 389 - } else { 390 - memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 391 - outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), 392 - &attrs->saddr.a6, 16); 393 - memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, 394 - outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 395 - &attrs->daddr.a6, 16); 396 - memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 397 - outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6), 398 - 0xff, 16); 399 - memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 400 - outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 401 - 0xff, 16); 402 - } 403 - 404 - flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_IPSEC; 405 - flow_act->crypto.obj_id = ipsec_obj_id; 406 - flow_act->flags |= FLOW_ACT_NO_APPEND; 407 415 } 408 416 409 - static int rx_add_rule(struct mlx5e_priv *priv, 410 - struct mlx5e_ipsec_sa_entry *sa_entry) 417 + static void setup_fte_spi(struct mlx5_flow_spec *spec, u32 spi) 418 + { 419 + /* SPI number */ 420 + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; 421 + 422 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters.outer_esp_spi); 423 + MLX5_SET(fte_match_param, spec->match_value, misc_parameters.outer_esp_spi, spi); 424 + } 425 + 426 + static void setup_fte_no_frags(struct mlx5_flow_spec *spec) 427 + { 428 + /* Non fragmented */ 429 + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 430 + 431 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.frag); 432 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.frag, 0); 433 + } 434 + 435 + static void setup_fte_reg_a(struct mlx5_flow_spec *spec) 436 + { 437 + /* Add IPsec indicator in metadata_reg_a */ 438 + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; 439 + 440 + MLX5_SET(fte_match_param, spec->match_criteria, 441 + misc_parameters_2.metadata_reg_a, MLX5_ETH_WQE_FT_META_IPSEC); 442 + MLX5_SET(fte_match_param, spec->match_value, 443 + misc_parameters_2.metadata_reg_a, MLX5_ETH_WQE_FT_META_IPSEC); 444 + } 445 + 446 + static void setup_fte_reg_c0(struct mlx5_flow_spec *spec, u32 reqid) 447 + { 448 + /* Pass policy check before choosing this SA */ 449 + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; 450 + 451 + MLX5_SET(fte_match_param, spec->match_criteria, 452 + misc_parameters_2.metadata_reg_c_0, reqid); 453 + MLX5_SET(fte_match_param, spec->match_value, 454 + misc_parameters_2.metadata_reg_c_0, reqid); 455 + } 456 + 457 + static int setup_modify_header(struct mlx5_core_dev *mdev, u32 val, u8 dir, 458 + struct mlx5_flow_act *flow_act) 411 459 { 412 460 u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 413 - struct mlx5e_ipsec_rule *ipsec_rule = &sa_entry->ipsec_rule; 414 - struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; 415 - u32 ipsec_obj_id = sa_entry->ipsec_obj_id; 416 - struct mlx5_modify_hdr *modify_hdr = NULL; 417 - struct mlx5e_accel_fs_esp_prot *fs_prot; 418 - struct mlx5_flow_destination dest = {}; 419 - struct mlx5e_accel_fs_esp *accel_esp; 420 - struct mlx5_flow_act flow_act = {}; 421 - struct mlx5_flow_handle *rule; 422 - enum accel_fs_esp_type type; 423 - struct mlx5_flow_spec *spec; 424 - int err = 0; 461 + enum mlx5_flow_namespace_type ns_type; 462 + struct mlx5_modify_hdr *modify_hdr; 425 463 426 - accel_esp = priv->ipsec->rx_fs; 427 - type = attrs->is_ipv6 ? ACCEL_FS_ESP6 : ACCEL_FS_ESP4; 428 - fs_prot = &accel_esp->fs_prot[type]; 429 - 430 - err = rx_ft_get(priv, type); 431 - if (err) 432 - return err; 433 - 434 - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 435 - if (!spec) { 436 - err = -ENOMEM; 437 - goto out_err; 464 + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); 465 + switch (dir) { 466 + case XFRM_DEV_OFFLOAD_IN: 467 + MLX5_SET(set_action_in, action, field, 468 + MLX5_ACTION_IN_FIELD_METADATA_REG_B); 469 + ns_type = MLX5_FLOW_NAMESPACE_KERNEL; 470 + break; 471 + case XFRM_DEV_OFFLOAD_OUT: 472 + MLX5_SET(set_action_in, action, field, 473 + MLX5_ACTION_IN_FIELD_METADATA_REG_C_0); 474 + ns_type = MLX5_FLOW_NAMESPACE_EGRESS; 475 + break; 476 + default: 477 + return -EINVAL; 438 478 } 439 479 440 - setup_fte_common(attrs, ipsec_obj_id, spec, &flow_act); 441 - 442 - /* Set bit[31] ipsec marker */ 443 - /* Set bit[23-0] ipsec_obj_id */ 444 - MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); 445 - MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); 446 - MLX5_SET(set_action_in, action, data, (ipsec_obj_id | BIT(31))); 480 + MLX5_SET(set_action_in, action, data, val); 447 481 MLX5_SET(set_action_in, action, offset, 0); 448 482 MLX5_SET(set_action_in, action, length, 32); 449 483 450 - modify_hdr = mlx5_modify_header_alloc(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL, 451 - 1, action); 484 + modify_hdr = mlx5_modify_header_alloc(mdev, ns_type, 1, action); 452 485 if (IS_ERR(modify_hdr)) { 453 - err = PTR_ERR(modify_hdr); 454 - netdev_err(priv->netdev, 455 - "fail to alloc ipsec set modify_header_id err=%d\n", err); 456 - modify_hdr = NULL; 457 - goto out_err; 486 + mlx5_core_err(mdev, "Failed to allocate modify_header %ld\n", 487 + PTR_ERR(modify_hdr)); 488 + return PTR_ERR(modify_hdr); 458 489 } 459 490 460 - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 461 - MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | 462 - MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 463 - dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 464 - flow_act.modify_hdr = modify_hdr; 465 - dest.ft = fs_prot->rx_err.ft; 466 - rule = mlx5_add_flow_rules(fs_prot->ft, spec, &flow_act, &dest, 1); 467 - if (IS_ERR(rule)) { 468 - err = PTR_ERR(rule); 469 - netdev_err(priv->netdev, "fail to add ipsec rule attrs->action=0x%x, err=%d\n", 470 - attrs->action, err); 471 - goto out_err; 472 - } 473 - 474 - ipsec_rule->rule = rule; 475 - ipsec_rule->set_modify_hdr = modify_hdr; 476 - goto out; 477 - 478 - out_err: 479 - if (modify_hdr) 480 - mlx5_modify_header_dealloc(priv->mdev, modify_hdr); 481 - rx_ft_put(priv, type); 482 - 483 - out: 484 - kvfree(spec); 485 - return err; 491 + flow_act->modify_hdr = modify_hdr; 492 + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 493 + return 0; 486 494 } 487 495 488 - static int tx_add_rule(struct mlx5e_priv *priv, 489 - struct mlx5e_ipsec_sa_entry *sa_entry) 496 + static int setup_pkt_reformat(struct mlx5_core_dev *mdev, 497 + struct mlx5_accel_esp_xfrm_attrs *attrs, 498 + struct mlx5_flow_act *flow_act) 490 499 { 500 + enum mlx5_flow_namespace_type ns_type = MLX5_FLOW_NAMESPACE_EGRESS; 501 + struct mlx5_pkt_reformat_params reformat_params = {}; 502 + struct mlx5_pkt_reformat *pkt_reformat; 503 + u8 reformatbf[16] = {}; 504 + __be32 spi; 505 + 506 + if (attrs->dir == XFRM_DEV_OFFLOAD_IN) { 507 + reformat_params.type = MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT; 508 + ns_type = MLX5_FLOW_NAMESPACE_KERNEL; 509 + goto cmd; 510 + } 511 + 512 + if (attrs->family == AF_INET) 513 + reformat_params.type = 514 + MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4; 515 + else 516 + reformat_params.type = 517 + MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6; 518 + 519 + /* convert to network format */ 520 + spi = htonl(attrs->spi); 521 + memcpy(reformatbf, &spi, 4); 522 + 523 + reformat_params.param_0 = attrs->authsize; 524 + reformat_params.size = sizeof(reformatbf); 525 + reformat_params.data = &reformatbf; 526 + 527 + cmd: 528 + pkt_reformat = 529 + mlx5_packet_reformat_alloc(mdev, &reformat_params, ns_type); 530 + if (IS_ERR(pkt_reformat)) 531 + return PTR_ERR(pkt_reformat); 532 + 533 + flow_act->pkt_reformat = pkt_reformat; 534 + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 535 + return 0; 536 + } 537 + 538 + static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) 539 + { 540 + struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; 541 + struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry); 542 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 543 + struct mlx5_flow_destination dest = {}; 491 544 struct mlx5_flow_act flow_act = {}; 492 545 struct mlx5_flow_handle *rule; 493 546 struct mlx5_flow_spec *spec; 494 - int err = 0; 547 + struct mlx5e_ipsec_rx *rx; 548 + int err; 495 549 496 - err = tx_ft_get(priv); 497 - if (err) 498 - return err; 550 + rx = rx_ft_get(mdev, ipsec, attrs->family); 551 + if (IS_ERR(rx)) 552 + return PTR_ERR(rx); 499 553 500 554 spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 501 555 if (!spec) { 502 556 err = -ENOMEM; 503 - goto out; 557 + goto err_alloc; 504 558 } 505 559 506 - setup_fte_common(&sa_entry->attrs, sa_entry->ipsec_obj_id, spec, 507 - &flow_act); 560 + if (attrs->family == AF_INET) 561 + setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); 562 + else 563 + setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); 508 564 509 - /* Add IPsec indicator in metadata_reg_a */ 510 - spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; 511 - MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a, 512 - MLX5_ETH_WQE_FT_META_IPSEC); 513 - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a, 514 - MLX5_ETH_WQE_FT_META_IPSEC); 565 + setup_fte_spi(spec, attrs->spi); 566 + setup_fte_esp(spec); 567 + setup_fte_no_frags(spec); 515 568 516 - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | 517 - MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT; 518 - rule = mlx5_add_flow_rules(priv->ipsec->tx_fs->ft, spec, &flow_act, NULL, 0); 569 + err = setup_modify_header(mdev, sa_entry->ipsec_obj_id | BIT(31), 570 + XFRM_DEV_OFFLOAD_IN, &flow_act); 571 + if (err) 572 + goto err_mod_header; 573 + 574 + switch (attrs->type) { 575 + case XFRM_DEV_OFFLOAD_PACKET: 576 + err = setup_pkt_reformat(mdev, attrs, &flow_act); 577 + if (err) 578 + goto err_pkt_reformat; 579 + break; 580 + default: 581 + break; 582 + } 583 + 584 + flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_IPSEC; 585 + flow_act.crypto.obj_id = sa_entry->ipsec_obj_id; 586 + flow_act.flags |= FLOW_ACT_NO_APPEND; 587 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 588 + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT; 589 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 590 + dest.ft = rx->ft.status; 591 + rule = mlx5_add_flow_rules(rx->ft.sa, spec, &flow_act, &dest, 1); 519 592 if (IS_ERR(rule)) { 520 593 err = PTR_ERR(rule); 521 - netdev_err(priv->netdev, "fail to add ipsec rule attrs->action=0x%x, err=%d\n", 522 - sa_entry->attrs.action, err); 523 - goto out; 594 + mlx5_core_err(mdev, "fail to add RX ipsec rule err=%d\n", err); 595 + goto err_add_flow; 524 596 } 597 + kvfree(spec); 525 598 526 599 sa_entry->ipsec_rule.rule = rule; 600 + sa_entry->ipsec_rule.modify_hdr = flow_act.modify_hdr; 601 + sa_entry->ipsec_rule.pkt_reformat = flow_act.pkt_reformat; 602 + return 0; 527 603 528 - out: 604 + err_add_flow: 605 + if (flow_act.pkt_reformat) 606 + mlx5_packet_reformat_dealloc(mdev, flow_act.pkt_reformat); 607 + err_pkt_reformat: 608 + mlx5_modify_header_dealloc(mdev, flow_act.modify_hdr); 609 + err_mod_header: 529 610 kvfree(spec); 530 - if (err) 531 - tx_ft_put(priv); 611 + err_alloc: 612 + rx_ft_put(mdev, ipsec, attrs->family); 532 613 return err; 533 614 } 534 615 535 - int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_priv *priv, 536 - struct mlx5e_ipsec_sa_entry *sa_entry) 616 + static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) 537 617 { 538 - if (sa_entry->attrs.action == MLX5_ACCEL_ESP_ACTION_ENCRYPT) 539 - return tx_add_rule(priv, sa_entry); 618 + struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; 619 + struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry); 620 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 621 + struct mlx5_flow_destination dest = {}; 622 + struct mlx5_flow_act flow_act = {}; 623 + struct mlx5_flow_handle *rule; 624 + struct mlx5_flow_spec *spec; 625 + struct mlx5e_ipsec_tx *tx; 626 + int err = 0; 540 627 541 - return rx_add_rule(priv, sa_entry); 628 + tx = tx_ft_get(mdev, ipsec); 629 + if (IS_ERR(tx)) 630 + return PTR_ERR(tx); 631 + 632 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 633 + if (!spec) { 634 + err = -ENOMEM; 635 + goto err_alloc; 636 + } 637 + 638 + if (attrs->family == AF_INET) 639 + setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); 640 + else 641 + setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); 642 + 643 + setup_fte_no_frags(spec); 644 + 645 + switch (attrs->type) { 646 + case XFRM_DEV_OFFLOAD_CRYPTO: 647 + setup_fte_spi(spec, attrs->spi); 648 + setup_fte_esp(spec); 649 + setup_fte_reg_a(spec); 650 + break; 651 + case XFRM_DEV_OFFLOAD_PACKET: 652 + setup_fte_reg_c0(spec, attrs->reqid); 653 + err = setup_pkt_reformat(mdev, attrs, &flow_act); 654 + if (err) 655 + goto err_pkt_reformat; 656 + break; 657 + default: 658 + break; 659 + } 660 + 661 + flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_IPSEC; 662 + flow_act.crypto.obj_id = sa_entry->ipsec_obj_id; 663 + flow_act.flags |= FLOW_ACT_NO_APPEND; 664 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW | 665 + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT | 666 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 667 + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 668 + dest.counter_id = mlx5_fc_id(tx->fc->cnt); 669 + rule = mlx5_add_flow_rules(tx->ft.sa, spec, &flow_act, &dest, 1); 670 + if (IS_ERR(rule)) { 671 + err = PTR_ERR(rule); 672 + mlx5_core_err(mdev, "fail to add TX ipsec rule err=%d\n", err); 673 + goto err_add_flow; 674 + } 675 + 676 + kvfree(spec); 677 + sa_entry->ipsec_rule.rule = rule; 678 + sa_entry->ipsec_rule.pkt_reformat = flow_act.pkt_reformat; 679 + return 0; 680 + 681 + err_add_flow: 682 + if (flow_act.pkt_reformat) 683 + mlx5_packet_reformat_dealloc(mdev, flow_act.pkt_reformat); 684 + err_pkt_reformat: 685 + kvfree(spec); 686 + err_alloc: 687 + tx_ft_put(ipsec); 688 + return err; 542 689 } 543 690 544 - void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_priv *priv, 545 - struct mlx5e_ipsec_sa_entry *sa_entry) 691 + static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) 692 + { 693 + struct mlx5_accel_pol_xfrm_attrs *attrs = &pol_entry->attrs; 694 + struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); 695 + struct mlx5_flow_destination dest[2] = {}; 696 + struct mlx5_flow_act flow_act = {}; 697 + struct mlx5_flow_handle *rule; 698 + struct mlx5_flow_spec *spec; 699 + struct mlx5e_ipsec_tx *tx; 700 + int err, dstn = 0; 701 + 702 + tx = tx_ft_get(mdev, pol_entry->ipsec); 703 + if (IS_ERR(tx)) 704 + return PTR_ERR(tx); 705 + 706 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 707 + if (!spec) { 708 + err = -ENOMEM; 709 + goto err_alloc; 710 + } 711 + 712 + if (attrs->family == AF_INET) 713 + setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); 714 + else 715 + setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); 716 + 717 + setup_fte_no_frags(spec); 718 + 719 + err = setup_modify_header(mdev, attrs->reqid, XFRM_DEV_OFFLOAD_OUT, 720 + &flow_act); 721 + if (err) 722 + goto err_mod_header; 723 + 724 + switch (attrs->action) { 725 + case XFRM_POLICY_ALLOW: 726 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 727 + break; 728 + case XFRM_POLICY_BLOCK: 729 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP | 730 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 731 + dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 732 + dest[dstn].counter_id = mlx5_fc_id(tx->fc->drop); 733 + dstn++; 734 + break; 735 + default: 736 + WARN_ON(true); 737 + err = -EINVAL; 738 + goto err_action; 739 + } 740 + 741 + flow_act.flags |= FLOW_ACT_NO_APPEND; 742 + dest[dstn].ft = tx->ft.sa; 743 + dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 744 + dstn++; 745 + rule = mlx5_add_flow_rules(tx->ft.pol, spec, &flow_act, dest, dstn); 746 + if (IS_ERR(rule)) { 747 + err = PTR_ERR(rule); 748 + mlx5_core_err(mdev, "fail to add TX ipsec rule err=%d\n", err); 749 + goto err_action; 750 + } 751 + 752 + kvfree(spec); 753 + pol_entry->ipsec_rule.rule = rule; 754 + pol_entry->ipsec_rule.modify_hdr = flow_act.modify_hdr; 755 + return 0; 756 + 757 + err_action: 758 + mlx5_modify_header_dealloc(mdev, flow_act.modify_hdr); 759 + err_mod_header: 760 + kvfree(spec); 761 + err_alloc: 762 + tx_ft_put(pol_entry->ipsec); 763 + return err; 764 + } 765 + 766 + static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry) 767 + { 768 + struct mlx5_accel_pol_xfrm_attrs *attrs = &pol_entry->attrs; 769 + struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); 770 + struct mlx5_flow_destination dest[2]; 771 + struct mlx5_flow_act flow_act = {}; 772 + struct mlx5_flow_handle *rule; 773 + struct mlx5_flow_spec *spec; 774 + struct mlx5e_ipsec_rx *rx; 775 + int err, dstn = 0; 776 + 777 + rx = rx_ft_get(mdev, pol_entry->ipsec, attrs->family); 778 + if (IS_ERR(rx)) 779 + return PTR_ERR(rx); 780 + 781 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 782 + if (!spec) { 783 + err = -ENOMEM; 784 + goto err_alloc; 785 + } 786 + 787 + if (attrs->family == AF_INET) 788 + setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); 789 + else 790 + setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); 791 + 792 + setup_fte_no_frags(spec); 793 + 794 + switch (attrs->action) { 795 + case XFRM_POLICY_ALLOW: 796 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 797 + break; 798 + case XFRM_POLICY_BLOCK: 799 + flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; 800 + dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 801 + dest[dstn].counter_id = mlx5_fc_id(rx->fc->drop); 802 + dstn++; 803 + break; 804 + default: 805 + WARN_ON(true); 806 + err = -EINVAL; 807 + goto err_action; 808 + } 809 + 810 + flow_act.flags |= FLOW_ACT_NO_APPEND; 811 + dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 812 + dest[dstn].ft = rx->ft.sa; 813 + dstn++; 814 + rule = mlx5_add_flow_rules(rx->ft.pol, spec, &flow_act, dest, dstn); 815 + if (IS_ERR(rule)) { 816 + err = PTR_ERR(rule); 817 + mlx5_core_err(mdev, "Fail to add RX IPsec policy rule err=%d\n", err); 818 + goto err_action; 819 + } 820 + 821 + kvfree(spec); 822 + pol_entry->ipsec_rule.rule = rule; 823 + return 0; 824 + 825 + err_action: 826 + kvfree(spec); 827 + err_alloc: 828 + rx_ft_put(mdev, pol_entry->ipsec, attrs->family); 829 + return err; 830 + } 831 + 832 + static void ipsec_fs_destroy_counters(struct mlx5e_ipsec *ipsec) 833 + { 834 + struct mlx5e_ipsec_rx *rx_ipv4 = ipsec->rx_ipv4; 835 + struct mlx5_core_dev *mdev = ipsec->mdev; 836 + struct mlx5e_ipsec_tx *tx = ipsec->tx; 837 + 838 + mlx5_fc_destroy(mdev, tx->fc->drop); 839 + mlx5_fc_destroy(mdev, tx->fc->cnt); 840 + kfree(tx->fc); 841 + mlx5_fc_destroy(mdev, rx_ipv4->fc->drop); 842 + mlx5_fc_destroy(mdev, rx_ipv4->fc->cnt); 843 + kfree(rx_ipv4->fc); 844 + } 845 + 846 + static int ipsec_fs_init_counters(struct mlx5e_ipsec *ipsec) 847 + { 848 + struct mlx5e_ipsec_rx *rx_ipv4 = ipsec->rx_ipv4; 849 + struct mlx5e_ipsec_rx *rx_ipv6 = ipsec->rx_ipv6; 850 + struct mlx5_core_dev *mdev = ipsec->mdev; 851 + struct mlx5e_ipsec_tx *tx = ipsec->tx; 852 + struct mlx5e_ipsec_fc *fc; 853 + struct mlx5_fc *counter; 854 + int err; 855 + 856 + fc = kzalloc(sizeof(*rx_ipv4->fc), GFP_KERNEL); 857 + if (!fc) 858 + return -ENOMEM; 859 + 860 + /* Both IPv4 and IPv6 point to same flow counters struct. */ 861 + rx_ipv4->fc = fc; 862 + rx_ipv6->fc = fc; 863 + counter = mlx5_fc_create(mdev, false); 864 + if (IS_ERR(counter)) { 865 + err = PTR_ERR(counter); 866 + goto err_rx_cnt; 867 + } 868 + 869 + fc->cnt = counter; 870 + counter = mlx5_fc_create(mdev, false); 871 + if (IS_ERR(counter)) { 872 + err = PTR_ERR(counter); 873 + goto err_rx_drop; 874 + } 875 + 876 + fc->drop = counter; 877 + fc = kzalloc(sizeof(*tx->fc), GFP_KERNEL); 878 + if (!fc) { 879 + err = -ENOMEM; 880 + goto err_tx_fc; 881 + } 882 + 883 + tx->fc = fc; 884 + counter = mlx5_fc_create(mdev, false); 885 + if (IS_ERR(counter)) { 886 + err = PTR_ERR(counter); 887 + goto err_tx_cnt; 888 + } 889 + 890 + fc->cnt = counter; 891 + counter = mlx5_fc_create(mdev, false); 892 + if (IS_ERR(counter)) { 893 + err = PTR_ERR(counter); 894 + goto err_tx_drop; 895 + } 896 + 897 + fc->drop = counter; 898 + return 0; 899 + 900 + err_tx_drop: 901 + mlx5_fc_destroy(mdev, tx->fc->cnt); 902 + err_tx_cnt: 903 + kfree(tx->fc); 904 + err_tx_fc: 905 + mlx5_fc_destroy(mdev, rx_ipv4->fc->drop); 906 + err_rx_drop: 907 + mlx5_fc_destroy(mdev, rx_ipv4->fc->cnt); 908 + err_rx_cnt: 909 + kfree(rx_ipv4->fc); 910 + return err; 911 + } 912 + 913 + void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv, void *ipsec_stats) 914 + { 915 + struct mlx5_core_dev *mdev = priv->mdev; 916 + struct mlx5e_ipsec *ipsec = priv->ipsec; 917 + struct mlx5e_ipsec_hw_stats *stats; 918 + struct mlx5e_ipsec_fc *fc; 919 + 920 + stats = (struct mlx5e_ipsec_hw_stats *)ipsec_stats; 921 + 922 + stats->ipsec_rx_pkts = 0; 923 + stats->ipsec_rx_bytes = 0; 924 + stats->ipsec_rx_drop_pkts = 0; 925 + stats->ipsec_rx_drop_bytes = 0; 926 + stats->ipsec_tx_pkts = 0; 927 + stats->ipsec_tx_bytes = 0; 928 + stats->ipsec_tx_drop_pkts = 0; 929 + stats->ipsec_tx_drop_bytes = 0; 930 + 931 + fc = ipsec->rx_ipv4->fc; 932 + mlx5_fc_query(mdev, fc->cnt, &stats->ipsec_rx_pkts, &stats->ipsec_rx_bytes); 933 + mlx5_fc_query(mdev, fc->drop, &stats->ipsec_rx_drop_pkts, 934 + &stats->ipsec_rx_drop_bytes); 935 + 936 + fc = ipsec->tx->fc; 937 + mlx5_fc_query(mdev, fc->cnt, &stats->ipsec_tx_pkts, &stats->ipsec_tx_bytes); 938 + mlx5_fc_query(mdev, fc->drop, &stats->ipsec_tx_drop_pkts, 939 + &stats->ipsec_tx_drop_bytes); 940 + } 941 + 942 + int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) 943 + { 944 + if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 945 + return tx_add_rule(sa_entry); 946 + 947 + return rx_add_rule(sa_entry); 948 + } 949 + 950 + void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) 546 951 { 547 952 struct mlx5e_ipsec_rule *ipsec_rule = &sa_entry->ipsec_rule; 548 953 struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry); 549 954 550 955 mlx5_del_flow_rules(ipsec_rule->rule); 551 956 552 - if (sa_entry->attrs.action == MLX5_ACCEL_ESP_ACTION_ENCRYPT) { 553 - tx_ft_put(priv); 957 + if (ipsec_rule->pkt_reformat) 958 + mlx5_packet_reformat_dealloc(mdev, ipsec_rule->pkt_reformat); 959 + 960 + if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) { 961 + tx_ft_put(sa_entry->ipsec); 554 962 return; 555 963 } 556 964 557 - mlx5_modify_header_dealloc(mdev, ipsec_rule->set_modify_hdr); 558 - rx_ft_put(priv, 559 - sa_entry->attrs.is_ipv6 ? ACCEL_FS_ESP6 : ACCEL_FS_ESP4); 965 + mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); 966 + rx_ft_put(mdev, sa_entry->ipsec, sa_entry->attrs.family); 967 + } 968 + 969 + int mlx5e_accel_ipsec_fs_add_pol(struct mlx5e_ipsec_pol_entry *pol_entry) 970 + { 971 + if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 972 + return tx_add_policy(pol_entry); 973 + 974 + return rx_add_policy(pol_entry); 975 + } 976 + 977 + void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry) 978 + { 979 + struct mlx5e_ipsec_rule *ipsec_rule = &pol_entry->ipsec_rule; 980 + struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); 981 + 982 + mlx5_del_flow_rules(ipsec_rule->rule); 983 + 984 + if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) { 985 + rx_ft_put(mdev, pol_entry->ipsec, pol_entry->attrs.family); 986 + return; 987 + } 988 + 989 + mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); 990 + tx_ft_put(pol_entry->ipsec); 560 991 } 561 992 562 993 void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec) 563 994 { 564 - struct mlx5e_accel_fs_esp_prot *fs_prot; 565 - struct mlx5e_accel_fs_esp *accel_esp; 566 - enum accel_fs_esp_type i; 567 - 568 - if (!ipsec->rx_fs) 995 + if (!ipsec->tx) 569 996 return; 570 997 571 - mutex_destroy(&ipsec->tx_fs->mutex); 572 - WARN_ON(ipsec->tx_fs->refcnt); 573 - kfree(ipsec->tx_fs); 998 + ipsec_fs_destroy_counters(ipsec); 999 + mutex_destroy(&ipsec->tx->ft.mutex); 1000 + WARN_ON(ipsec->tx->ft.refcnt); 1001 + kfree(ipsec->tx); 574 1002 575 - accel_esp = ipsec->rx_fs; 576 - for (i = 0; i < ACCEL_FS_ESP_NUM_TYPES; i++) { 577 - fs_prot = &accel_esp->fs_prot[i]; 578 - mutex_destroy(&fs_prot->prot_mutex); 579 - WARN_ON(fs_prot->refcnt); 580 - } 581 - kfree(ipsec->rx_fs); 1003 + mutex_destroy(&ipsec->rx_ipv4->ft.mutex); 1004 + WARN_ON(ipsec->rx_ipv4->ft.refcnt); 1005 + kfree(ipsec->rx_ipv4); 1006 + 1007 + mutex_destroy(&ipsec->rx_ipv6->ft.mutex); 1008 + WARN_ON(ipsec->rx_ipv6->ft.refcnt); 1009 + kfree(ipsec->rx_ipv6); 582 1010 } 583 1011 584 1012 int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) 585 1013 { 586 - struct mlx5e_accel_fs_esp_prot *fs_prot; 587 - struct mlx5e_accel_fs_esp *accel_esp; 588 1014 struct mlx5_flow_namespace *ns; 589 - enum accel_fs_esp_type i; 590 1015 int err = -ENOMEM; 591 1016 592 1017 ns = mlx5_get_flow_namespace(ipsec->mdev, ··· 1032 581 if (!ns) 1033 582 return -EOPNOTSUPP; 1034 583 1035 - ipsec->tx_fs = kzalloc(sizeof(*ipsec->tx_fs), GFP_KERNEL); 1036 - if (!ipsec->tx_fs) 584 + ipsec->tx = kzalloc(sizeof(*ipsec->tx), GFP_KERNEL); 585 + if (!ipsec->tx) 1037 586 return -ENOMEM; 1038 587 1039 - ipsec->rx_fs = kzalloc(sizeof(*ipsec->rx_fs), GFP_KERNEL); 1040 - if (!ipsec->rx_fs) 1041 - goto err_rx; 588 + ipsec->rx_ipv4 = kzalloc(sizeof(*ipsec->rx_ipv4), GFP_KERNEL); 589 + if (!ipsec->rx_ipv4) 590 + goto err_rx_ipv4; 1042 591 1043 - mutex_init(&ipsec->tx_fs->mutex); 1044 - ipsec->tx_fs->ns = ns; 592 + ipsec->rx_ipv6 = kzalloc(sizeof(*ipsec->rx_ipv6), GFP_KERNEL); 593 + if (!ipsec->rx_ipv6) 594 + goto err_rx_ipv6; 1045 595 1046 - accel_esp = ipsec->rx_fs; 1047 - for (i = 0; i < ACCEL_FS_ESP_NUM_TYPES; i++) { 1048 - fs_prot = &accel_esp->fs_prot[i]; 1049 - mutex_init(&fs_prot->prot_mutex); 1050 - } 596 + err = ipsec_fs_init_counters(ipsec); 597 + if (err) 598 + goto err_counters; 599 + 600 + mutex_init(&ipsec->tx->ft.mutex); 601 + mutex_init(&ipsec->rx_ipv4->ft.mutex); 602 + mutex_init(&ipsec->rx_ipv6->ft.mutex); 603 + ipsec->tx->ns = ns; 1051 604 1052 605 return 0; 1053 606 1054 - err_rx: 1055 - kfree(ipsec->tx_fs); 607 + err_counters: 608 + kfree(ipsec->rx_ipv6); 609 + err_rx_ipv6: 610 + kfree(ipsec->rx_ipv4); 611 + err_rx_ipv4: 612 + kfree(ipsec->tx); 1056 613 return err; 1057 614 }
+297 -6
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
··· 2 2 /* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */ 3 3 4 4 #include "mlx5_core.h" 5 + #include "en.h" 5 6 #include "ipsec.h" 6 7 #include "lib/mlx5.h" 8 + 9 + enum { 10 + MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET, 11 + }; 7 12 8 13 u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) 9 14 { ··· 36 31 MLX5_CAP_ETH(mdev, insert_trailer) && MLX5_CAP_ETH(mdev, swp)) 37 32 caps |= MLX5_IPSEC_CAP_CRYPTO; 38 33 34 + if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload) && 35 + MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_esp_trasport) && 36 + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_del_esp_trasport) && 37 + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap)) 38 + caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD; 39 + 39 40 if (!caps) 40 41 return 0; 41 42 ··· 57 46 } 58 47 EXPORT_SYMBOL_GPL(mlx5_ipsec_device_caps); 59 48 49 + static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn, 50 + struct mlx5_accel_esp_xfrm_attrs *attrs) 51 + { 52 + void *aso_ctx; 53 + 54 + aso_ctx = MLX5_ADDR_OF(ipsec_obj, obj, ipsec_aso); 55 + if (attrs->esn_trigger) { 56 + MLX5_SET(ipsec_aso, aso_ctx, esn_event_arm, 1); 57 + 58 + if (attrs->dir == XFRM_DEV_OFFLOAD_IN) { 59 + MLX5_SET(ipsec_aso, aso_ctx, window_sz, 60 + attrs->replay_window / 64); 61 + MLX5_SET(ipsec_aso, aso_ctx, mode, 62 + MLX5_IPSEC_ASO_REPLAY_PROTECTION); 63 + } 64 + } 65 + 66 + /* ASO context */ 67 + MLX5_SET(ipsec_obj, obj, ipsec_aso_access_pd, pdn); 68 + MLX5_SET(ipsec_obj, obj, full_offload, 1); 69 + MLX5_SET(ipsec_aso, aso_ctx, valid, 1); 70 + /* MLX5_IPSEC_ASO_REG_C_4_5 is type C register that is used 71 + * in flow steering to perform matching against. Please be 72 + * aware that this register was chosen arbitrary and can't 73 + * be used in other places as long as IPsec packet offload 74 + * active. 75 + */ 76 + MLX5_SET(ipsec_obj, obj, aso_return_reg, MLX5_IPSEC_ASO_REG_C_4_5); 77 + if (attrs->dir == XFRM_DEV_OFFLOAD_OUT) 78 + MLX5_SET(ipsec_aso, aso_ctx, mode, MLX5_IPSEC_ASO_INC_SN); 79 + 80 + if (attrs->hard_packet_limit != XFRM_INF) { 81 + MLX5_SET(ipsec_aso, aso_ctx, remove_flow_pkt_cnt, 82 + lower_32_bits(attrs->hard_packet_limit)); 83 + MLX5_SET(ipsec_aso, aso_ctx, hard_lft_arm, 1); 84 + MLX5_SET(ipsec_aso, aso_ctx, remove_flow_enable, 1); 85 + } 86 + 87 + if (attrs->soft_packet_limit != XFRM_INF) { 88 + MLX5_SET(ipsec_aso, aso_ctx, remove_flow_soft_lft, 89 + lower_32_bits(attrs->soft_packet_limit)); 90 + 91 + MLX5_SET(ipsec_aso, aso_ctx, soft_lft_arm, 1); 92 + } 93 + } 94 + 60 95 static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry) 61 96 { 62 97 struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; ··· 111 54 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 112 55 u32 in[MLX5_ST_SZ_DW(create_ipsec_obj_in)] = {}; 113 56 void *obj, *salt_p, *salt_iv_p; 57 + struct mlx5e_hw_objs *res; 114 58 int err; 115 59 116 60 obj = MLX5_ADDR_OF(create_ipsec_obj_in, in, ipsec_object); ··· 124 66 salt_iv_p = MLX5_ADDR_OF(ipsec_obj, obj, implicit_iv); 125 67 memcpy(salt_iv_p, &aes_gcm->seq_iv, sizeof(aes_gcm->seq_iv)); 126 68 /* esn */ 127 - if (attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED) { 69 + if (attrs->esn_trigger) { 128 70 MLX5_SET(ipsec_obj, obj, esn_en, 1); 129 71 MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn); 130 - if (attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP) 131 - MLX5_SET(ipsec_obj, obj, esn_overlap, 1); 72 + MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap); 132 73 } 133 74 134 75 MLX5_SET(ipsec_obj, obj, dekn, sa_entry->enc_key_id); ··· 137 80 MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 138 81 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, 139 82 MLX5_GENERAL_OBJECT_TYPES_IPSEC); 83 + 84 + res = &mdev->mlx5e_res.hw_objs; 85 + if (attrs->type == XFRM_DEV_OFFLOAD_PACKET) 86 + mlx5e_ipsec_packet_setup(obj, res->pdn, attrs); 140 87 141 88 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 142 89 if (!err) ··· 213 152 void *obj; 214 153 int err; 215 154 216 - if (!(attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED)) 155 + if (!attrs->esn_trigger) 217 156 return 0; 218 157 219 158 general_obj_types = MLX5_CAP_GEN_64(mdev, general_obj_types); ··· 244 183 MLX5_MODIFY_IPSEC_BITMASK_ESN_OVERLAP | 245 184 MLX5_MODIFY_IPSEC_BITMASK_ESN_MSB); 246 185 MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn); 247 - if (attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP) 248 - MLX5_SET(ipsec_obj, obj, esn_overlap, 1); 186 + MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap); 249 187 250 188 /* general object fields set */ 251 189 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT); ··· 262 202 return; 263 203 264 204 memcpy(&sa_entry->attrs, attrs, sizeof(sa_entry->attrs)); 205 + } 206 + 207 + static void 208 + mlx5e_ipsec_aso_update_esn(struct mlx5e_ipsec_sa_entry *sa_entry, 209 + const struct mlx5_accel_esp_xfrm_attrs *attrs) 210 + { 211 + struct mlx5_wqe_aso_ctrl_seg data = {}; 212 + 213 + data.data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BITWISE_64BIT << 6; 214 + data.condition_1_0_operand = MLX5_ASO_ALWAYS_TRUE | MLX5_ASO_ALWAYS_TRUE 215 + << 4; 216 + data.data_offset_condition_operand = MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; 217 + data.bitwise_data = cpu_to_be64(BIT_ULL(54)); 218 + data.data_mask = data.bitwise_data; 219 + 220 + mlx5e_ipsec_aso_query(sa_entry, &data); 221 + } 222 + 223 + static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, 224 + u32 mode_param) 225 + { 226 + struct mlx5_accel_esp_xfrm_attrs attrs = {}; 227 + 228 + if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) { 229 + sa_entry->esn_state.esn++; 230 + sa_entry->esn_state.overlap = 0; 231 + } else { 232 + sa_entry->esn_state.overlap = 1; 233 + } 234 + 235 + mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs); 236 + mlx5_accel_esp_modify_xfrm(sa_entry, &attrs); 237 + mlx5e_ipsec_aso_update_esn(sa_entry, &attrs); 238 + } 239 + 240 + static void mlx5e_ipsec_handle_event(struct work_struct *_work) 241 + { 242 + struct mlx5e_ipsec_work *work = 243 + container_of(_work, struct mlx5e_ipsec_work, work); 244 + struct mlx5_accel_esp_xfrm_attrs *attrs; 245 + struct mlx5e_ipsec_sa_entry *sa_entry; 246 + struct mlx5e_ipsec_aso *aso; 247 + struct mlx5e_ipsec *ipsec; 248 + int ret; 249 + 250 + sa_entry = xa_load(&work->ipsec->sadb, work->id); 251 + if (!sa_entry) 252 + goto out; 253 + 254 + ipsec = sa_entry->ipsec; 255 + aso = ipsec->aso; 256 + attrs = &sa_entry->attrs; 257 + 258 + spin_lock(&sa_entry->x->lock); 259 + ret = mlx5e_ipsec_aso_query(sa_entry, NULL); 260 + if (ret) 261 + goto unlock; 262 + 263 + aso->use_cache = true; 264 + if (attrs->esn_trigger && 265 + !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) { 266 + u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter); 267 + 268 + mlx5e_ipsec_update_esn_state(sa_entry, mode_param); 269 + } 270 + 271 + if (attrs->soft_packet_limit != XFRM_INF) 272 + if (!MLX5_GET(ipsec_aso, aso->ctx, soft_lft_arm) || 273 + !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm) || 274 + !MLX5_GET(ipsec_aso, aso->ctx, remove_flow_enable)) 275 + xfrm_state_check_expire(sa_entry->x); 276 + aso->use_cache = false; 277 + 278 + unlock: 279 + spin_unlock(&sa_entry->x->lock); 280 + out: 281 + kfree(work); 282 + } 283 + 284 + static int mlx5e_ipsec_event(struct notifier_block *nb, unsigned long event, 285 + void *data) 286 + { 287 + struct mlx5e_ipsec *ipsec = container_of(nb, struct mlx5e_ipsec, nb); 288 + struct mlx5_eqe_obj_change *object; 289 + struct mlx5e_ipsec_work *work; 290 + struct mlx5_eqe *eqe = data; 291 + u16 type; 292 + 293 + if (event != MLX5_EVENT_TYPE_OBJECT_CHANGE) 294 + return NOTIFY_DONE; 295 + 296 + object = &eqe->data.obj_change; 297 + type = be16_to_cpu(object->obj_type); 298 + 299 + if (type != MLX5_GENERAL_OBJECT_TYPES_IPSEC) 300 + return NOTIFY_DONE; 301 + 302 + work = kmalloc(sizeof(*work), GFP_ATOMIC); 303 + if (!work) 304 + return NOTIFY_DONE; 305 + 306 + INIT_WORK(&work->work, mlx5e_ipsec_handle_event); 307 + work->ipsec = ipsec; 308 + work->id = be32_to_cpu(object->obj_id); 309 + 310 + queue_work(ipsec->wq, &work->work); 311 + return NOTIFY_OK; 312 + } 313 + 314 + int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec) 315 + { 316 + struct mlx5_core_dev *mdev = ipsec->mdev; 317 + struct mlx5e_ipsec_aso *aso; 318 + struct mlx5e_hw_objs *res; 319 + struct device *pdev; 320 + int err; 321 + 322 + aso = kzalloc(sizeof(*ipsec->aso), GFP_KERNEL); 323 + if (!aso) 324 + return -ENOMEM; 325 + 326 + res = &mdev->mlx5e_res.hw_objs; 327 + 328 + pdev = mlx5_core_dma_dev(mdev); 329 + aso->dma_addr = dma_map_single(pdev, aso->ctx, sizeof(aso->ctx), 330 + DMA_BIDIRECTIONAL); 331 + err = dma_mapping_error(pdev, aso->dma_addr); 332 + if (err) 333 + goto err_dma; 334 + 335 + aso->aso = mlx5_aso_create(mdev, res->pdn); 336 + if (IS_ERR(aso->aso)) { 337 + err = PTR_ERR(aso->aso); 338 + goto err_aso_create; 339 + } 340 + 341 + ipsec->nb.notifier_call = mlx5e_ipsec_event; 342 + mlx5_notifier_register(mdev, &ipsec->nb); 343 + 344 + ipsec->aso = aso; 345 + return 0; 346 + 347 + err_aso_create: 348 + dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx), 349 + DMA_BIDIRECTIONAL); 350 + err_dma: 351 + kfree(aso); 352 + return err; 353 + } 354 + 355 + void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec) 356 + { 357 + struct mlx5_core_dev *mdev = ipsec->mdev; 358 + struct mlx5e_ipsec_aso *aso; 359 + struct device *pdev; 360 + 361 + aso = ipsec->aso; 362 + pdev = mlx5_core_dma_dev(mdev); 363 + 364 + mlx5_notifier_unregister(mdev, &ipsec->nb); 365 + mlx5_aso_destroy(aso->aso); 366 + dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx), 367 + DMA_BIDIRECTIONAL); 368 + kfree(aso); 369 + } 370 + 371 + static void mlx5e_ipsec_aso_copy(struct mlx5_wqe_aso_ctrl_seg *ctrl, 372 + struct mlx5_wqe_aso_ctrl_seg *data) 373 + { 374 + if (!data) 375 + return; 376 + 377 + ctrl->data_mask_mode = data->data_mask_mode; 378 + ctrl->condition_1_0_operand = data->condition_1_0_operand; 379 + ctrl->condition_1_0_offset = data->condition_1_0_offset; 380 + ctrl->data_offset_condition_operand = data->data_offset_condition_operand; 381 + ctrl->condition_0_data = data->condition_0_data; 382 + ctrl->condition_0_mask = data->condition_0_mask; 383 + ctrl->condition_1_data = data->condition_1_data; 384 + ctrl->condition_1_mask = data->condition_1_mask; 385 + ctrl->bitwise_data = data->bitwise_data; 386 + ctrl->data_mask = data->data_mask; 387 + } 388 + 389 + int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, 390 + struct mlx5_wqe_aso_ctrl_seg *data) 391 + { 392 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 393 + struct mlx5e_ipsec_aso *aso = ipsec->aso; 394 + struct mlx5_core_dev *mdev = ipsec->mdev; 395 + struct mlx5_wqe_aso_ctrl_seg *ctrl; 396 + struct mlx5e_hw_objs *res; 397 + struct mlx5_aso_wqe *wqe; 398 + u8 ds_cnt; 399 + 400 + lockdep_assert_held(&sa_entry->x->lock); 401 + if (aso->use_cache) 402 + return 0; 403 + 404 + res = &mdev->mlx5e_res.hw_objs; 405 + 406 + memset(aso->ctx, 0, sizeof(aso->ctx)); 407 + wqe = mlx5_aso_get_wqe(aso->aso); 408 + ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); 409 + mlx5_aso_build_wqe(aso->aso, ds_cnt, wqe, sa_entry->ipsec_obj_id, 410 + MLX5_ACCESS_ASO_OPC_MOD_IPSEC); 411 + 412 + ctrl = &wqe->aso_ctrl; 413 + ctrl->va_l = 414 + cpu_to_be32(lower_32_bits(aso->dma_addr) | ASO_CTRL_READ_EN); 415 + ctrl->va_h = cpu_to_be32(upper_32_bits(aso->dma_addr)); 416 + ctrl->l_key = cpu_to_be32(res->mkey); 417 + mlx5e_ipsec_aso_copy(ctrl, data); 418 + 419 + mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl); 420 + return mlx5_aso_poll_cq(aso->aso, false); 421 + } 422 + 423 + void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry, 424 + u64 *packets) 425 + { 426 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 427 + struct mlx5e_ipsec_aso *aso = ipsec->aso; 428 + u64 hard_cnt; 429 + 430 + hard_cnt = MLX5_GET(ipsec_aso, aso->ctx, remove_flow_pkt_cnt); 431 + /* HW decresases the limit till it reaches zero to fire an avent. 432 + * We need to fix the calculations, so the returned count is a total 433 + * number of passed packets and not how much left. 434 + */ 435 + *packets = sa_entry->attrs.hard_packet_limit - hard_cnt; 265 436 }
+13 -9
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
··· 312 312 struct mlx5_cqe64 *cqe) 313 313 { 314 314 u32 ipsec_meta_data = be32_to_cpu(cqe->ft_metadata); 315 - struct mlx5e_priv *priv; 315 + struct mlx5e_priv *priv = netdev_priv(netdev); 316 + struct mlx5e_ipsec *ipsec = priv->ipsec; 317 + struct mlx5e_ipsec_sa_entry *sa_entry; 316 318 struct xfrm_offload *xo; 317 - struct xfrm_state *xs; 318 319 struct sec_path *sp; 319 320 u32 sa_handle; 320 321 321 322 sa_handle = MLX5_IPSEC_METADATA_HANDLE(ipsec_meta_data); 322 - priv = netdev_priv(netdev); 323 323 sp = secpath_set(skb); 324 324 if (unlikely(!sp)) { 325 - atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sp_alloc); 325 + atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_sp_alloc); 326 326 return; 327 327 } 328 328 329 - xs = mlx5e_ipsec_sadb_rx_lookup(priv->ipsec, sa_handle); 330 - if (unlikely(!xs)) { 331 - atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sadb_miss); 329 + rcu_read_lock(); 330 + sa_entry = xa_load(&ipsec->sadb, sa_handle); 331 + if (unlikely(!sa_entry)) { 332 + rcu_read_unlock(); 333 + atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_sadb_miss); 332 334 return; 333 335 } 336 + xfrm_state_hold(sa_entry->x); 337 + rcu_read_unlock(); 334 338 335 - sp->xvec[sp->len++] = xs; 339 + sp->xvec[sp->len++] = sa_entry->x; 336 340 sp->olen++; 337 341 338 342 xo = xfrm_offload(skb); ··· 353 349 xo->status = CRYPTO_INVALID_PACKET_SYNTAX; 354 350 break; 355 351 default: 356 - atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_syndrome); 352 + atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_syndrome); 357 353 } 358 354 }
+52
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_stats.c
··· 37 37 #include "en.h" 38 38 #include "ipsec.h" 39 39 40 + static const struct counter_desc mlx5e_ipsec_hw_stats_desc[] = { 41 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_rx_pkts) }, 42 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_rx_bytes) }, 43 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_rx_drop_pkts) }, 44 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_rx_drop_bytes) }, 45 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_tx_pkts) }, 46 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_tx_bytes) }, 47 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_tx_drop_pkts) }, 48 + { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_hw_stats, ipsec_tx_drop_bytes) }, 49 + }; 50 + 40 51 static const struct counter_desc mlx5e_ipsec_sw_stats_desc[] = { 41 52 { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_sw_stats, ipsec_rx_drop_sp_alloc) }, 42 53 { MLX5E_DECLARE_STAT(struct mlx5e_ipsec_sw_stats, ipsec_rx_drop_sadb_miss) }, ··· 61 50 #define MLX5E_READ_CTR_ATOMIC64(ptr, dsc, i) \ 62 51 atomic64_read((atomic64_t *)((char *)(ptr) + (dsc)[i].offset)) 63 52 53 + #define NUM_IPSEC_HW_COUNTERS ARRAY_SIZE(mlx5e_ipsec_hw_stats_desc) 64 54 #define NUM_IPSEC_SW_COUNTERS ARRAY_SIZE(mlx5e_ipsec_sw_stats_desc) 55 + 56 + static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(ipsec_hw) 57 + { 58 + if (!priv->ipsec) 59 + return 0; 60 + 61 + return NUM_IPSEC_HW_COUNTERS; 62 + } 63 + 64 + static inline MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(ipsec_hw) {} 65 + 66 + static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(ipsec_hw) 67 + { 68 + unsigned int i; 69 + 70 + if (!priv->ipsec) 71 + return idx; 72 + 73 + for (i = 0; i < NUM_IPSEC_HW_COUNTERS; i++) 74 + strcpy(data + (idx++) * ETH_GSTRING_LEN, 75 + mlx5e_ipsec_hw_stats_desc[i].format); 76 + 77 + return idx; 78 + } 79 + 80 + static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(ipsec_hw) 81 + { 82 + int i; 83 + 84 + if (!priv->ipsec) 85 + return idx; 86 + 87 + mlx5e_accel_ipsec_fs_read_stats(priv, &priv->ipsec->hw_stats); 88 + for (i = 0; i < NUM_IPSEC_HW_COUNTERS; i++) 89 + data[idx++] = MLX5E_READ_CTR_ATOMIC64(&priv->ipsec->hw_stats, 90 + mlx5e_ipsec_hw_stats_desc, i); 91 + 92 + return idx; 93 + } 65 94 66 95 static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(ipsec_sw) 67 96 { ··· 132 81 return idx; 133 82 } 134 83 84 + MLX5E_DEFINE_STATS_GRP(ipsec_hw, 0); 135 85 MLX5E_DEFINE_STATS_GRP(ipsec_sw, 0);
+1
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
··· 2480 2480 &MLX5E_STATS_GRP(per_prio), 2481 2481 &MLX5E_STATS_GRP(pme), 2482 2482 #ifdef CONFIG_MLX5_EN_IPSEC 2483 + &MLX5E_STATS_GRP(ipsec_hw), 2483 2484 &MLX5E_STATS_GRP(ipsec_sw), 2484 2485 #endif 2485 2486 &MLX5E_STATS_GRP(tls),
+1
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
··· 506 506 extern MLX5E_DECLARE_STATS_GRP(pme); 507 507 extern MLX5E_DECLARE_STATS_GRP(channels); 508 508 extern MLX5E_DECLARE_STATS_GRP(per_port_buff_congest); 509 + extern MLX5E_DECLARE_STATS_GRP(ipsec_hw); 509 510 extern MLX5E_DECLARE_STATS_GRP(ipsec_sw); 510 511 extern MLX5E_DECLARE_STATS_GRP(ptp); 511 512 extern MLX5E_DECLARE_STATS_GRP(macsec_hw);
+5
drivers/net/ethernet/mellanox/mlx5/core/eq.c
··· 19 19 #include "diag/fw_tracer.h" 20 20 #include "mlx5_irq.h" 21 21 #include "devlink.h" 22 + #include "en_accel/ipsec.h" 22 23 23 24 enum { 24 25 MLX5_EQE_OWNER_INIT_VAL = 0x1, ··· 578 577 579 578 if (MLX5_CAP_MACSEC(dev, log_max_macsec_offload)) 580 579 async_event_mask |= (1ull << MLX5_EVENT_TYPE_OBJECT_CHANGE); 580 + 581 + if (mlx5_ipsec_device_caps(dev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD) 582 + async_event_mask |= 583 + (1ull << MLX5_EVENT_TYPE_OBJECT_CHANGE); 581 584 582 585 mask[0] = async_event_mask; 583 586
+3 -3
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 111 111 #define ETHTOOL_PRIO_NUM_LEVELS 1 112 112 #define ETHTOOL_NUM_PRIOS 11 113 113 #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS) 114 - /* Promiscuous, Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}} */ 115 - #define KERNEL_NIC_PRIO_NUM_LEVELS 7 114 + /* Promiscuous, Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy */ 115 + #define KERNEL_NIC_PRIO_NUM_LEVELS 8 116 116 #define KERNEL_NIC_NUM_PRIOS 1 117 117 /* One more level for tc */ 118 118 #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1) ··· 133 133 #define LAG_MIN_LEVEL (OFFLOADS_MIN_LEVEL + KERNEL_RX_MACSEC_MIN_LEVEL + 1) 134 134 135 135 #define KERNEL_TX_IPSEC_NUM_PRIOS 1 136 - #define KERNEL_TX_IPSEC_NUM_LEVELS 1 136 + #define KERNEL_TX_IPSEC_NUM_LEVELS 2 137 137 #define KERNEL_TX_IPSEC_MIN_LEVEL (KERNEL_TX_IPSEC_NUM_LEVELS) 138 138 139 139 #define KERNEL_TX_MACSEC_NUM_PRIOS 1
+5 -2
drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c
··· 353 353 cseg->general_id = cpu_to_be32(obj_id); 354 354 } 355 355 356 - void *mlx5_aso_get_wqe(struct mlx5_aso *aso) 356 + struct mlx5_aso_wqe *mlx5_aso_get_wqe(struct mlx5_aso *aso) 357 357 { 358 + struct mlx5_aso_wqe *wqe; 358 359 u16 pi; 359 360 360 361 pi = mlx5_wq_cyc_ctr2ix(&aso->wq, aso->pc); 361 - return mlx5_wq_cyc_get_wqe(&aso->wq, pi); 362 + wqe = mlx5_wq_cyc_get_wqe(&aso->wq, pi); 363 + memset(wqe, 0, sizeof(*wqe)); 364 + return wqe; 362 365 } 363 366 364 367 void mlx5_aso_post_wqe(struct mlx5_aso *aso, bool with_data,
+3 -1
drivers/net/ethernet/mellanox/mlx5/core/lib/aso.h
··· 15 15 #define MLX5_WQE_CTRL_WQE_OPC_MOD_SHIFT 24 16 16 #define MLX5_MACSEC_ASO_DS_CNT (DIV_ROUND_UP(sizeof(struct mlx5_aso_wqe), MLX5_SEND_WQE_DS)) 17 17 18 + #define ASO_CTRL_READ_EN BIT(0) 18 19 struct mlx5_wqe_aso_ctrl_seg { 19 20 __be32 va_h; 20 21 __be32 va_l; /* include read_enable */ ··· 72 71 }; 73 72 74 73 enum { 74 + MLX5_ACCESS_ASO_OPC_MOD_IPSEC = 0x0, 75 75 MLX5_ACCESS_ASO_OPC_MOD_FLOW_METER = 0x2, 76 76 MLX5_ACCESS_ASO_OPC_MOD_MACSEC = 0x5, 77 77 }; 78 78 79 79 struct mlx5_aso; 80 80 81 - void *mlx5_aso_get_wqe(struct mlx5_aso *aso); 81 + struct mlx5_aso_wqe *mlx5_aso_get_wqe(struct mlx5_aso *aso); 82 82 void mlx5_aso_build_wqe(struct mlx5_aso *aso, u8 ds_cnt, 83 83 struct mlx5_aso_wqe *aso_wqe, 84 84 u32 obj_id, u32 opc_mode);
+5
drivers/net/ethernet/netronome/nfp/crypto/ipsec.c
··· 302 302 return -EINVAL; 303 303 } 304 304 305 + if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) { 306 + nn_err(nn, "Unsupported xfrm offload tyoe\n"); 307 + return -EINVAL; 308 + } 309 + 305 310 cfg->spi = ntohl(x->id.spi); 306 311 307 312 /* Hash/Authentication */
+5
drivers/net/netdevsim/ipsec.c
··· 149 149 return -EINVAL; 150 150 } 151 151 152 + if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) { 153 + netdev_err(dev, "Unsupported ipsec offload type\n"); 154 + return -EINVAL; 155 + } 156 + 152 157 /* find the first unused index */ 153 158 ret = nsim_ipsec_find_empty_idx(ipsec); 154 159 if (ret < 0) {
+50 -3
include/linux/mlx5/mlx5_ifc.h
··· 446 446 u8 max_modify_header_actions[0x8]; 447 447 u8 max_ft_level[0x8]; 448 448 449 - u8 reserved_at_40[0x6]; 449 + u8 reformat_add_esp_trasport[0x1]; 450 + u8 reserved_at_41[0x2]; 451 + u8 reformat_del_esp_trasport[0x1]; 452 + u8 reserved_at_44[0x2]; 450 453 u8 execute_aso[0x1]; 451 454 u8 reserved_at_47[0x19]; 452 455 ··· 642 639 u8 reserved_at_1a0[0x8]; 643 640 644 641 u8 macsec_syndrome[0x8]; 642 + u8 ipsec_syndrome[0x8]; 643 + u8 reserved_at_1b8[0x8]; 645 644 646 - u8 reserved_at_1b0[0x50]; 645 + u8 reserved_at_1c0[0x40]; 647 646 }; 648 647 649 648 struct mlx5_ifc_fte_match_set_misc3_bits { ··· 6457 6452 MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL = 0x2, 6458 6453 MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2 = 0x3, 6459 6454 MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL = 0x4, 6455 + MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4 = 0x5, 6456 + MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT = 0x8, 6457 + MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6 = 0xb, 6460 6458 MLX5_REFORMAT_TYPE_INSERT_HDR = 0xf, 6461 6459 MLX5_REFORMAT_TYPE_REMOVE_HDR = 0x10, 6462 6460 MLX5_REFORMAT_TYPE_ADD_MACSEC = 0x11, ··· 11639 11631 MLX5_IPSEC_OBJECT_ICV_LEN_16B, 11640 11632 }; 11641 11633 11634 + enum { 11635 + MLX5_IPSEC_ASO_REG_C_0_1 = 0x0, 11636 + MLX5_IPSEC_ASO_REG_C_2_3 = 0x1, 11637 + MLX5_IPSEC_ASO_REG_C_4_5 = 0x2, 11638 + MLX5_IPSEC_ASO_REG_C_6_7 = 0x3, 11639 + }; 11640 + 11641 + enum { 11642 + MLX5_IPSEC_ASO_MODE = 0x0, 11643 + MLX5_IPSEC_ASO_REPLAY_PROTECTION = 0x1, 11644 + MLX5_IPSEC_ASO_INC_SN = 0x2, 11645 + }; 11646 + 11647 + struct mlx5_ifc_ipsec_aso_bits { 11648 + u8 valid[0x1]; 11649 + u8 reserved_at_201[0x1]; 11650 + u8 mode[0x2]; 11651 + u8 window_sz[0x2]; 11652 + u8 soft_lft_arm[0x1]; 11653 + u8 hard_lft_arm[0x1]; 11654 + u8 remove_flow_enable[0x1]; 11655 + u8 esn_event_arm[0x1]; 11656 + u8 reserved_at_20a[0x16]; 11657 + 11658 + u8 remove_flow_pkt_cnt[0x20]; 11659 + 11660 + u8 remove_flow_soft_lft[0x20]; 11661 + 11662 + u8 reserved_at_260[0x80]; 11663 + 11664 + u8 mode_parameter[0x20]; 11665 + 11666 + u8 replay_protection_window[0x100]; 11667 + }; 11668 + 11642 11669 struct mlx5_ifc_ipsec_obj_bits { 11643 11670 u8 modify_field_select[0x40]; 11644 11671 u8 full_offload[0x1]; ··· 11695 11652 11696 11653 u8 implicit_iv[0x40]; 11697 11654 11698 - u8 reserved_at_100[0x700]; 11655 + u8 reserved_at_100[0x8]; 11656 + u8 ipsec_aso_access_pd[0x18]; 11657 + u8 reserved_at_120[0xe0]; 11658 + 11659 + struct mlx5_ifc_ipsec_aso_bits ipsec_aso; 11699 11660 }; 11700 11661 11701 11662 struct mlx5_ifc_create_ipsec_obj_in_bits {
+4
include/linux/netdevice.h
··· 1041 1041 bool (*xdo_dev_offload_ok) (struct sk_buff *skb, 1042 1042 struct xfrm_state *x); 1043 1043 void (*xdo_dev_state_advance_esn) (struct xfrm_state *x); 1044 + void (*xdo_dev_state_update_curlft) (struct xfrm_state *x); 1045 + int (*xdo_dev_policy_add) (struct xfrm_policy *x); 1046 + void (*xdo_dev_policy_delete) (struct xfrm_policy *x); 1047 + void (*xdo_dev_policy_free) (struct xfrm_policy *x); 1044 1048 }; 1045 1049 #endif 1046 1050
+101 -23
include/net/xfrm.h
··· 129 129 enum { 130 130 XFRM_DEV_OFFLOAD_IN = 1, 131 131 XFRM_DEV_OFFLOAD_OUT, 132 + XFRM_DEV_OFFLOAD_FWD, 133 + }; 134 + 135 + enum { 136 + XFRM_DEV_OFFLOAD_UNSPECIFIED, 137 + XFRM_DEV_OFFLOAD_CRYPTO, 138 + XFRM_DEV_OFFLOAD_PACKET, 132 139 }; 133 140 134 141 struct xfrm_dev_offload { ··· 144 137 struct net_device *real_dev; 145 138 unsigned long offload_handle; 146 139 u8 dir : 2; 140 + u8 type : 2; 147 141 }; 148 142 149 143 struct xfrm_mode { ··· 542 534 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; 543 535 struct hlist_node bydst_inexact_list; 544 536 struct rcu_head rcu; 537 + 538 + struct xfrm_dev_offload xdo; 545 539 }; 546 540 547 541 static inline struct net *xp_net(const struct xfrm_policy *xp) ··· 1103 1093 } 1104 1094 1105 1095 #ifdef CONFIG_XFRM 1096 + static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb) 1097 + { 1098 + struct sec_path *sp = skb_sec_path(skb); 1099 + 1100 + return sp->xvec[sp->len - 1]; 1101 + } 1102 + #endif 1103 + 1104 + static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb) 1105 + { 1106 + #ifdef CONFIG_XFRM 1107 + struct sec_path *sp = skb_sec_path(skb); 1108 + 1109 + if (!sp || !sp->olen || sp->len != sp->olen) 1110 + return NULL; 1111 + 1112 + return &sp->ovec[sp->olen - 1]; 1113 + #else 1114 + return NULL; 1115 + #endif 1116 + } 1117 + 1118 + #ifdef CONFIG_XFRM 1106 1119 int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, 1107 1120 unsigned short family); 1108 1121 ··· 1156 1123 { 1157 1124 struct net *net = dev_net(skb->dev); 1158 1125 int ndir = dir | (reverse ? XFRM_POLICY_MASK + 1 : 0); 1126 + struct xfrm_offload *xo = xfrm_offload(skb); 1127 + struct xfrm_state *x; 1159 1128 1160 1129 if (sk && sk->sk_policy[XFRM_POLICY_IN]) 1161 1130 return __xfrm_policy_check(sk, ndir, skb, family); 1131 + 1132 + if (xo) { 1133 + x = xfrm_input_state(skb); 1134 + if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) 1135 + return (xo->flags & CRYPTO_DONE) && 1136 + (xo->status & CRYPTO_SUCCESS); 1137 + } 1162 1138 1163 1139 return __xfrm_check_nopolicy(net, skb, dir) || 1164 1140 __xfrm_check_dev_nopolicy(skb, dir, family) || ··· 1571 1529 struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi, 1572 1530 unsigned short family); 1573 1531 int xfrm_state_check_expire(struct xfrm_state *x); 1532 + #ifdef CONFIG_XFRM_OFFLOAD 1533 + static inline void xfrm_dev_state_update_curlft(struct xfrm_state *x) 1534 + { 1535 + struct xfrm_dev_offload *xdo = &x->xso; 1536 + struct net_device *dev = xdo->dev; 1537 + 1538 + if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) 1539 + return; 1540 + 1541 + if (dev && dev->xfrmdev_ops && 1542 + dev->xfrmdev_ops->xdo_dev_state_update_curlft) 1543 + dev->xfrmdev_ops->xdo_dev_state_update_curlft(x); 1544 + 1545 + } 1546 + #else 1547 + static inline void xfrm_dev_state_update_curlft(struct xfrm_state *x) {} 1548 + #endif 1574 1549 void xfrm_state_insert(struct xfrm_state *x); 1575 1550 int xfrm_state_add(struct xfrm_state *x); 1576 1551 int xfrm_state_update(struct xfrm_state *x); ··· 1637 1578 int xfrm_state_delete(struct xfrm_state *x); 1638 1579 int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync); 1639 1580 int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid); 1581 + int xfrm_dev_policy_flush(struct net *net, struct net_device *dev, 1582 + bool task_valid); 1640 1583 void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); 1641 1584 void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); 1642 1585 u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); ··· 1921 1860 } 1922 1861 #endif 1923 1862 1924 - #ifdef CONFIG_XFRM 1925 - static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb) 1926 - { 1927 - struct sec_path *sp = skb_sec_path(skb); 1928 - 1929 - return sp->xvec[sp->len - 1]; 1930 - } 1931 - #endif 1932 - 1933 - static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb) 1934 - { 1935 - #ifdef CONFIG_XFRM 1936 - struct sec_path *sp = skb_sec_path(skb); 1937 - 1938 - if (!sp || !sp->olen || sp->len != sp->olen) 1939 - return NULL; 1940 - 1941 - return &sp->ovec[sp->olen - 1]; 1942 - #else 1943 - return NULL; 1944 - #endif 1945 - } 1946 - 1947 1863 void __init xfrm_dev_init(void); 1948 1864 1949 1865 #ifdef CONFIG_XFRM_OFFLOAD ··· 1930 1892 int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, 1931 1893 struct xfrm_user_offload *xuo, 1932 1894 struct netlink_ext_ack *extack); 1895 + int xfrm_dev_policy_add(struct net *net, struct xfrm_policy *xp, 1896 + struct xfrm_user_offload *xuo, u8 dir, 1897 + struct netlink_ext_ack *extack); 1933 1898 bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x); 1934 1899 1935 1900 static inline void xfrm_dev_state_advance_esn(struct xfrm_state *x) ··· 1981 1940 netdev_put(dev, &xso->dev_tracker); 1982 1941 } 1983 1942 } 1943 + 1944 + static inline void xfrm_dev_policy_delete(struct xfrm_policy *x) 1945 + { 1946 + struct xfrm_dev_offload *xdo = &x->xdo; 1947 + struct net_device *dev = xdo->dev; 1948 + 1949 + if (dev && dev->xfrmdev_ops && dev->xfrmdev_ops->xdo_dev_policy_delete) 1950 + dev->xfrmdev_ops->xdo_dev_policy_delete(x); 1951 + } 1952 + 1953 + static inline void xfrm_dev_policy_free(struct xfrm_policy *x) 1954 + { 1955 + struct xfrm_dev_offload *xdo = &x->xdo; 1956 + struct net_device *dev = xdo->dev; 1957 + 1958 + if (dev && dev->xfrmdev_ops) { 1959 + if (dev->xfrmdev_ops->xdo_dev_policy_free) 1960 + dev->xfrmdev_ops->xdo_dev_policy_free(x); 1961 + xdo->dev = NULL; 1962 + netdev_put(dev, &xdo->dev_tracker); 1963 + } 1964 + } 1984 1965 #else 1985 1966 static inline void xfrm_dev_resume(struct sk_buff *skb) 1986 1967 { ··· 2027 1964 } 2028 1965 2029 1966 static inline void xfrm_dev_state_free(struct xfrm_state *x) 1967 + { 1968 + } 1969 + 1970 + static inline int xfrm_dev_policy_add(struct net *net, struct xfrm_policy *xp, 1971 + struct xfrm_user_offload *xuo, u8 dir, 1972 + struct netlink_ext_ack *extack) 1973 + { 1974 + return 0; 1975 + } 1976 + 1977 + static inline void xfrm_dev_policy_delete(struct xfrm_policy *x) 1978 + { 1979 + } 1980 + 1981 + static inline void xfrm_dev_policy_free(struct xfrm_policy *x) 2030 1982 { 2031 1983 } 2032 1984
+6
include/uapi/linux/xfrm.h
··· 519 519 */ 520 520 #define XFRM_OFFLOAD_IPV6 1 521 521 #define XFRM_OFFLOAD_INBOUND 2 522 + /* Two bits above are relevant for state path only, while 523 + * offload is used for both policy and state flows. 524 + * 525 + * In policy offload mode, they are free and can be safely reused. 526 + */ 527 + #define XFRM_OFFLOAD_PACKET 4 522 528 523 529 struct xfrm_userpolicy_default { 524 530 #define XFRM_USERPOLICY_UNSPEC 0
+100 -7
net/xfrm/xfrm_device.c
··· 132 132 if (xo->flags & XFRM_GRO || x->xso.dir == XFRM_DEV_OFFLOAD_IN) 133 133 return skb; 134 134 135 + /* The packet was sent to HW IPsec packet offload engine, 136 + * but to wrong device. Drop the packet, so it won't skip 137 + * XFRM stack. 138 + */ 139 + if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET && x->xso.dev != dev) { 140 + kfree_skb(skb); 141 + dev_core_stats_tx_dropped_inc(dev); 142 + return NULL; 143 + } 144 + 135 145 /* This skb was already validated on the upper/virtual dev */ 136 146 if ((x->xso.dev != dev) && (x->xso.real_dev == dev)) 137 147 return skb; ··· 239 229 struct xfrm_dev_offload *xso = &x->xso; 240 230 xfrm_address_t *saddr; 241 231 xfrm_address_t *daddr; 232 + bool is_packet_offload; 242 233 243 234 if (!x->type_offload) { 244 235 NL_SET_ERR_MSG(extack, "Type doesn't support offload"); ··· 252 241 return -EINVAL; 253 242 } 254 243 255 - if (xuo->flags & ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND)) { 244 + if (xuo->flags & 245 + ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND | XFRM_OFFLOAD_PACKET)) { 256 246 NL_SET_ERR_MSG(extack, "Unrecognized flags in offload request"); 257 247 return -EINVAL; 258 248 } 259 249 250 + is_packet_offload = xuo->flags & XFRM_OFFLOAD_PACKET; 260 251 dev = dev_get_by_index(net, xuo->ifindex); 261 252 if (!dev) { 262 253 if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) { ··· 273 260 x->props.family, 274 261 xfrm_smark_get(0, x)); 275 262 if (IS_ERR(dst)) 276 - return 0; 263 + return (is_packet_offload) ? -EINVAL : 0; 277 264 278 265 dev = dst->dev; 279 266 ··· 284 271 if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_state_add) { 285 272 xso->dev = NULL; 286 273 dev_put(dev); 287 - return 0; 274 + return (is_packet_offload) ? -EINVAL : 0; 288 275 } 289 276 290 277 if (x->props.flags & XFRM_STATE_ESN && ··· 304 291 else 305 292 xso->dir = XFRM_DEV_OFFLOAD_OUT; 306 293 294 + if (is_packet_offload) 295 + xso->type = XFRM_DEV_OFFLOAD_PACKET; 296 + else 297 + xso->type = XFRM_DEV_OFFLOAD_CRYPTO; 298 + 307 299 err = dev->xfrmdev_ops->xdo_dev_state_add(x); 308 300 if (err) { 309 301 xso->dev = NULL; 310 302 xso->dir = 0; 311 303 xso->real_dev = NULL; 312 304 netdev_put(dev, &xso->dev_tracker); 305 + xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED; 313 306 314 - if (err != -EOPNOTSUPP) { 307 + /* User explicitly requested packet offload mode and configured 308 + * policy in addition to the XFRM state. So be civil to users, 309 + * and return an error instead of taking fallback path. 310 + * 311 + * This WARN_ON() can be seen as a documentation for driver 312 + * authors to do not return -EOPNOTSUPP in packet offload mode. 313 + */ 314 + WARN_ON(err == -EOPNOTSUPP && is_packet_offload); 315 + if (err != -EOPNOTSUPP || is_packet_offload) { 315 316 NL_SET_ERR_MSG(extack, "Device failed to offload this state"); 316 317 return err; 317 318 } ··· 334 307 return 0; 335 308 } 336 309 EXPORT_SYMBOL_GPL(xfrm_dev_state_add); 310 + 311 + int xfrm_dev_policy_add(struct net *net, struct xfrm_policy *xp, 312 + struct xfrm_user_offload *xuo, u8 dir, 313 + struct netlink_ext_ack *extack) 314 + { 315 + struct xfrm_dev_offload *xdo = &xp->xdo; 316 + struct net_device *dev; 317 + int err; 318 + 319 + if (!xuo->flags || xuo->flags & ~XFRM_OFFLOAD_PACKET) { 320 + /* We support only packet offload mode and it means 321 + * that user must set XFRM_OFFLOAD_PACKET bit. 322 + */ 323 + NL_SET_ERR_MSG(extack, "Unrecognized flags in offload request"); 324 + return -EINVAL; 325 + } 326 + 327 + dev = dev_get_by_index(net, xuo->ifindex); 328 + if (!dev) 329 + return -EINVAL; 330 + 331 + if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_policy_add) { 332 + xdo->dev = NULL; 333 + dev_put(dev); 334 + NL_SET_ERR_MSG(extack, "Policy offload is not supported"); 335 + return -EINVAL; 336 + } 337 + 338 + xdo->dev = dev; 339 + netdev_tracker_alloc(dev, &xdo->dev_tracker, GFP_ATOMIC); 340 + xdo->real_dev = dev; 341 + xdo->type = XFRM_DEV_OFFLOAD_PACKET; 342 + switch (dir) { 343 + case XFRM_POLICY_IN: 344 + xdo->dir = XFRM_DEV_OFFLOAD_IN; 345 + break; 346 + case XFRM_POLICY_OUT: 347 + xdo->dir = XFRM_DEV_OFFLOAD_OUT; 348 + break; 349 + case XFRM_POLICY_FWD: 350 + xdo->dir = XFRM_DEV_OFFLOAD_FWD; 351 + break; 352 + default: 353 + xdo->dev = NULL; 354 + dev_put(dev); 355 + NL_SET_ERR_MSG(extack, "Unrecognized offload direction"); 356 + return -EINVAL; 357 + } 358 + 359 + err = dev->xfrmdev_ops->xdo_dev_policy_add(xp); 360 + if (err) { 361 + xdo->dev = NULL; 362 + xdo->real_dev = NULL; 363 + xdo->type = XFRM_DEV_OFFLOAD_UNSPECIFIED; 364 + xdo->dir = 0; 365 + netdev_put(dev, &xdo->dev_tracker); 366 + NL_SET_ERR_MSG(extack, "Device failed to offload this policy"); 367 + return err; 368 + } 369 + 370 + return 0; 371 + } 372 + EXPORT_SYMBOL_GPL(xfrm_dev_policy_add); 337 373 338 374 bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x) 339 375 { ··· 408 318 if (!x->type_offload || x->encap) 409 319 return false; 410 320 411 - if ((!dev || (dev == xfrm_dst_path(dst)->dev)) && 412 - (!xdst->child->xfrm)) { 321 + if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET || 322 + ((!dev || (dev == xfrm_dst_path(dst)->dev)) && 323 + !xdst->child->xfrm)) { 413 324 mtu = xfrm_state_mtu(x, xdst->child_mtu_cached); 414 325 if (skb->len <= mtu) 415 326 goto ok; ··· 501 410 502 411 static int xfrm_dev_down(struct net_device *dev) 503 412 { 504 - if (dev->features & NETIF_F_HW_ESP) 413 + if (dev->features & NETIF_F_HW_ESP) { 505 414 xfrm_dev_state_flush(dev_net(dev), dev, true); 415 + xfrm_dev_policy_flush(dev_net(dev), dev, true); 416 + } 506 417 507 418 return NOTIFY_DONE; 508 419 }
+11 -1
net/xfrm/xfrm_output.c
··· 492 492 struct xfrm_state *x = dst->xfrm; 493 493 struct net *net = xs_net(x); 494 494 495 - if (err <= 0) 495 + if (err <= 0 || x->xso.type == XFRM_DEV_OFFLOAD_PACKET) 496 496 goto resume; 497 497 498 498 do { ··· 715 715 716 716 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 717 717 break; 718 + } 719 + 720 + if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) { 721 + if (!xfrm_dev_offload_ok(skb, x)) { 722 + XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); 723 + kfree_skb(skb); 724 + return -EHOSTUNREACH; 725 + } 726 + 727 + return xfrm_output_resume(sk, skb, 0); 718 728 } 719 729 720 730 secpath_reset(skb);
+80 -5
net/xfrm/xfrm_policy.c
··· 425 425 if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer)) 426 426 BUG(); 427 427 428 + xfrm_dev_policy_free(policy); 428 429 call_rcu(&policy->rcu, xfrm_policy_destroy_rcu); 429 430 } 430 431 EXPORT_SYMBOL(xfrm_policy_destroy); ··· 536 535 __get_hash_thresh(net, pol->family, dir, &dbits, &sbits); 537 536 h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr, 538 537 pol->family, nhashmask, dbits, sbits); 539 - if (!entry0) { 538 + if (!entry0 || pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) { 540 539 hlist_del_rcu(&pol->bydst); 541 540 hlist_add_head_rcu(&pol->bydst, ndsttable + h); 542 541 h0 = h; ··· 867 866 break; 868 867 } 869 868 870 - if (newpos) 869 + if (newpos && policy->xdo.type != XFRM_DEV_OFFLOAD_PACKET) 871 870 hlist_add_behind_rcu(&policy->bydst, newpos); 872 871 else 873 872 hlist_add_head_rcu(&policy->bydst, &n->hhead); ··· 1348 1347 else 1349 1348 break; 1350 1349 } 1351 - if (newpos) 1350 + if (newpos && policy->xdo.type != XFRM_DEV_OFFLOAD_PACKET) 1352 1351 hlist_add_behind_rcu(&policy->bydst, newpos); 1353 1352 else 1354 1353 hlist_add_head_rcu(&policy->bydst, chain); ··· 1525 1524 break; 1526 1525 } 1527 1526 1528 - if (newpos) 1527 + if (newpos && policy->xdo.type != XFRM_DEV_OFFLOAD_PACKET) 1529 1528 hlist_add_behind_rcu(&policy->bydst_inexact_list, newpos); 1530 1529 else 1531 1530 hlist_add_head_rcu(&policy->bydst_inexact_list, chain); ··· 1562 1561 break; 1563 1562 } 1564 1563 1565 - if (newpos) 1564 + if (newpos && policy->xdo.type != XFRM_DEV_OFFLOAD_PACKET) 1566 1565 hlist_add_behind_rcu(&policy->bydst, &newpos->bydst); 1567 1566 else 1567 + /* Packet offload policies enter to the head 1568 + * to speed-up lookups. 1569 + */ 1568 1570 hlist_add_head_rcu(&policy->bydst, chain); 1569 1571 1570 1572 return delpol; ··· 1773 1769 } 1774 1770 return err; 1775 1771 } 1772 + 1773 + static inline int xfrm_dev_policy_flush_secctx_check(struct net *net, 1774 + struct net_device *dev, 1775 + bool task_valid) 1776 + { 1777 + struct xfrm_policy *pol; 1778 + int err = 0; 1779 + 1780 + list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) { 1781 + if (pol->walk.dead || 1782 + xfrm_policy_id2dir(pol->index) >= XFRM_POLICY_MAX || 1783 + pol->xdo.dev != dev) 1784 + continue; 1785 + 1786 + err = security_xfrm_policy_delete(pol->security); 1787 + if (err) { 1788 + xfrm_audit_policy_delete(pol, 0, task_valid); 1789 + return err; 1790 + } 1791 + } 1792 + return err; 1793 + } 1776 1794 #else 1777 1795 static inline int 1778 1796 xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid) 1797 + { 1798 + return 0; 1799 + } 1800 + 1801 + static inline int xfrm_dev_policy_flush_secctx_check(struct net *net, 1802 + struct net_device *dev, 1803 + bool task_valid) 1779 1804 { 1780 1805 return 0; 1781 1806 } ··· 1846 1813 return err; 1847 1814 } 1848 1815 EXPORT_SYMBOL(xfrm_policy_flush); 1816 + 1817 + int xfrm_dev_policy_flush(struct net *net, struct net_device *dev, 1818 + bool task_valid) 1819 + { 1820 + int dir, err = 0, cnt = 0; 1821 + struct xfrm_policy *pol; 1822 + 1823 + spin_lock_bh(&net->xfrm.xfrm_policy_lock); 1824 + 1825 + err = xfrm_dev_policy_flush_secctx_check(net, dev, task_valid); 1826 + if (err) 1827 + goto out; 1828 + 1829 + again: 1830 + list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) { 1831 + dir = xfrm_policy_id2dir(pol->index); 1832 + if (pol->walk.dead || 1833 + dir >= XFRM_POLICY_MAX || 1834 + pol->xdo.dev != dev) 1835 + continue; 1836 + 1837 + __xfrm_policy_unlink(pol, dir); 1838 + spin_unlock_bh(&net->xfrm.xfrm_policy_lock); 1839 + cnt++; 1840 + xfrm_audit_policy_delete(pol, 1, task_valid); 1841 + xfrm_policy_kill(pol); 1842 + spin_lock_bh(&net->xfrm.xfrm_policy_lock); 1843 + goto again; 1844 + } 1845 + if (cnt) 1846 + __xfrm_policy_inexact_flush(net); 1847 + else 1848 + err = -ESRCH; 1849 + out: 1850 + spin_unlock_bh(&net->xfrm.xfrm_policy_lock); 1851 + return err; 1852 + } 1853 + EXPORT_SYMBOL(xfrm_dev_policy_flush); 1849 1854 1850 1855 int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, 1851 1856 int (*func)(struct xfrm_policy *, int, int, void*), ··· 2184 2113 break; 2185 2114 } 2186 2115 } 2116 + if (ret && ret->xdo.type == XFRM_DEV_OFFLOAD_PACKET) 2117 + goto skip_inexact; 2118 + 2187 2119 bin = xfrm_policy_inexact_lookup_rcu(net, type, family, dir, if_id); 2188 2120 if (!bin || !xfrm_policy_find_inexact_candidates(&cand, bin, saddr, 2189 2121 daddr)) ··· 2319 2245 pol = __xfrm_policy_unlink(pol, dir); 2320 2246 spin_unlock_bh(&net->xfrm.xfrm_policy_lock); 2321 2247 if (pol) { 2248 + xfrm_dev_policy_delete(pol); 2322 2249 xfrm_policy_kill(pol); 2323 2250 return 0; 2324 2251 }
+172 -17
net/xfrm/xfrm_state.c
··· 84 84 return __xfrm_seq_hash(seq, net->xfrm.state_hmask); 85 85 } 86 86 87 + #define XFRM_STATE_INSERT(by, _n, _h, _type) \ 88 + { \ 89 + struct xfrm_state *_x = NULL; \ 90 + \ 91 + if (_type != XFRM_DEV_OFFLOAD_PACKET) { \ 92 + hlist_for_each_entry_rcu(_x, _h, by) { \ 93 + if (_x->xso.type == XFRM_DEV_OFFLOAD_PACKET) \ 94 + continue; \ 95 + break; \ 96 + } \ 97 + } \ 98 + \ 99 + if (!_x || _x->xso.type == XFRM_DEV_OFFLOAD_PACKET) \ 100 + /* SAD is empty or consist from HW SAs only */ \ 101 + hlist_add_head_rcu(_n, _h); \ 102 + else \ 103 + hlist_add_before_rcu(_n, &_x->by); \ 104 + } 105 + 87 106 static void xfrm_hash_transfer(struct hlist_head *list, 88 107 struct hlist_head *ndsttable, 89 108 struct hlist_head *nsrctable, ··· 119 100 h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr, 120 101 x->props.reqid, x->props.family, 121 102 nhashmask); 122 - hlist_add_head_rcu(&x->bydst, ndsttable + h); 103 + XFRM_STATE_INSERT(bydst, &x->bydst, ndsttable + h, x->xso.type); 123 104 124 105 h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr, 125 106 x->props.family, 126 107 nhashmask); 127 - hlist_add_head_rcu(&x->bysrc, nsrctable + h); 108 + XFRM_STATE_INSERT(bysrc, &x->bysrc, nsrctable + h, x->xso.type); 128 109 129 110 if (x->id.spi) { 130 111 h = __xfrm_spi_hash(&x->id.daddr, x->id.spi, 131 112 x->id.proto, x->props.family, 132 113 nhashmask); 133 - hlist_add_head_rcu(&x->byspi, nspitable + h); 114 + XFRM_STATE_INSERT(byspi, &x->byspi, nspitable + h, 115 + x->xso.type); 134 116 } 135 117 136 118 if (x->km.seq) { 137 119 h = __xfrm_seq_hash(x->km.seq, nhashmask); 138 - hlist_add_head_rcu(&x->byseq, nseqtable + h); 120 + XFRM_STATE_INSERT(byseq, &x->byseq, nseqtable + h, 121 + x->xso.type); 139 122 } 140 123 } 141 124 } ··· 570 549 int err = 0; 571 550 572 551 spin_lock(&x->lock); 552 + xfrm_dev_state_update_curlft(x); 553 + 573 554 if (x->km.state == XFRM_STATE_DEAD) 574 555 goto out; 575 556 if (x->km.state == XFRM_STATE_EXPIRED) ··· 974 951 x->props.family = tmpl->encap_family; 975 952 } 976 953 954 + static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark, 955 + const xfrm_address_t *daddr, 956 + __be32 spi, u8 proto, 957 + unsigned short family, 958 + struct xfrm_dev_offload *xdo) 959 + { 960 + unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); 961 + struct xfrm_state *x; 962 + 963 + hlist_for_each_entry_rcu(x, net->xfrm.state_byspi + h, byspi) { 964 + #ifdef CONFIG_XFRM_OFFLOAD 965 + if (xdo->type == XFRM_DEV_OFFLOAD_PACKET) { 966 + if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) 967 + /* HW states are in the head of list, there is 968 + * no need to iterate further. 969 + */ 970 + break; 971 + 972 + /* Packet offload: both policy and SA should 973 + * have same device. 974 + */ 975 + if (xdo->dev != x->xso.dev) 976 + continue; 977 + } else if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) 978 + /* Skip HW policy for SW lookups */ 979 + continue; 980 + #endif 981 + if (x->props.family != family || 982 + x->id.spi != spi || 983 + x->id.proto != proto || 984 + !xfrm_addr_equal(&x->id.daddr, daddr, family)) 985 + continue; 986 + 987 + if ((mark & x->mark.m) != x->mark.v) 988 + continue; 989 + if (!xfrm_state_hold_rcu(x)) 990 + continue; 991 + return x; 992 + } 993 + 994 + return NULL; 995 + } 996 + 977 997 static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, 978 998 const xfrm_address_t *daddr, 979 999 __be32 spi, u8 proto, ··· 1158 1092 rcu_read_lock(); 1159 1093 h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); 1160 1094 hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h, bydst) { 1095 + #ifdef CONFIG_XFRM_OFFLOAD 1096 + if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) { 1097 + if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) 1098 + /* HW states are in the head of list, there is 1099 + * no need to iterate further. 1100 + */ 1101 + break; 1102 + 1103 + /* Packet offload: both policy and SA should 1104 + * have same device. 1105 + */ 1106 + if (pol->xdo.dev != x->xso.dev) 1107 + continue; 1108 + } else if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) 1109 + /* Skip HW policy for SW lookups */ 1110 + continue; 1111 + #endif 1161 1112 if (x->props.family == encap_family && 1162 1113 x->props.reqid == tmpl->reqid && 1163 1114 (mark & x->mark.m) == x->mark.v && ··· 1192 1109 1193 1110 h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family); 1194 1111 hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h_wildcard, bydst) { 1112 + #ifdef CONFIG_XFRM_OFFLOAD 1113 + if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) { 1114 + if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) 1115 + /* HW states are in the head of list, there is 1116 + * no need to iterate further. 1117 + */ 1118 + break; 1119 + 1120 + /* Packet offload: both policy and SA should 1121 + * have same device. 1122 + */ 1123 + if (pol->xdo.dev != x->xso.dev) 1124 + continue; 1125 + } else if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) 1126 + /* Skip HW policy for SW lookups */ 1127 + continue; 1128 + #endif 1195 1129 if (x->props.family == encap_family && 1196 1130 x->props.reqid == tmpl->reqid && 1197 1131 (mark & x->mark.m) == x->mark.v && ··· 1226 1126 x = best; 1227 1127 if (!x && !error && !acquire_in_progress) { 1228 1128 if (tmpl->id.spi && 1229 - (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi, 1230 - tmpl->id.proto, encap_family)) != NULL) { 1129 + (x0 = __xfrm_state_lookup_all(net, mark, daddr, 1130 + tmpl->id.spi, tmpl->id.proto, 1131 + encap_family, 1132 + &pol->xdo)) != NULL) { 1231 1133 to_put = x0; 1232 1134 error = -EEXIST; 1233 1135 goto out; ··· 1263 1161 x = NULL; 1264 1162 goto out; 1265 1163 } 1164 + #ifdef CONFIG_XFRM_OFFLOAD 1165 + if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) { 1166 + struct xfrm_dev_offload *xdo = &pol->xdo; 1167 + struct xfrm_dev_offload *xso = &x->xso; 1266 1168 1169 + xso->type = XFRM_DEV_OFFLOAD_PACKET; 1170 + xso->dir = xdo->dir; 1171 + xso->dev = xdo->dev; 1172 + xso->real_dev = xdo->real_dev; 1173 + netdev_tracker_alloc(xso->dev, &xso->dev_tracker, 1174 + GFP_ATOMIC); 1175 + error = xso->dev->xfrmdev_ops->xdo_dev_state_add(x); 1176 + if (error) { 1177 + xso->dir = 0; 1178 + netdev_put(xso->dev, &xso->dev_tracker); 1179 + xso->dev = NULL; 1180 + xso->real_dev = NULL; 1181 + xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED; 1182 + x->km.state = XFRM_STATE_DEAD; 1183 + to_put = x; 1184 + x = NULL; 1185 + goto out; 1186 + } 1187 + } 1188 + #endif 1267 1189 if (km_query(x, tmpl, pol) == 0) { 1268 1190 spin_lock_bh(&net->xfrm.xfrm_state_lock); 1269 1191 x->km.state = XFRM_STATE_ACQ; 1270 1192 list_add(&x->km.all, &net->xfrm.state_all); 1271 - hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h); 1193 + XFRM_STATE_INSERT(bydst, &x->bydst, 1194 + net->xfrm.state_bydst + h, 1195 + x->xso.type); 1272 1196 h = xfrm_src_hash(net, daddr, saddr, encap_family); 1273 - hlist_add_head_rcu(&x->bysrc, net->xfrm.state_bysrc + h); 1197 + XFRM_STATE_INSERT(bysrc, &x->bysrc, 1198 + net->xfrm.state_bysrc + h, 1199 + x->xso.type); 1274 1200 if (x->id.spi) { 1275 1201 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family); 1276 - hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h); 1202 + XFRM_STATE_INSERT(byspi, &x->byspi, 1203 + net->xfrm.state_byspi + h, 1204 + x->xso.type); 1277 1205 } 1278 1206 if (x->km.seq) { 1279 1207 h = xfrm_seq_hash(net, x->km.seq); 1280 - hlist_add_head_rcu(&x->byseq, net->xfrm.state_byseq + h); 1208 + XFRM_STATE_INSERT(byseq, &x->byseq, 1209 + net->xfrm.state_byseq + h, 1210 + x->xso.type); 1281 1211 } 1282 1212 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 1283 1213 hrtimer_start(&x->mtimer, ··· 1319 1185 xfrm_hash_grow_check(net, x->bydst.next != NULL); 1320 1186 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 1321 1187 } else { 1188 + #ifdef CONFIG_XFRM_OFFLOAD 1189 + struct xfrm_dev_offload *xso = &x->xso; 1190 + 1191 + if (xso->type == XFRM_DEV_OFFLOAD_PACKET) { 1192 + xso->dev->xfrmdev_ops->xdo_dev_state_delete(x); 1193 + xso->dir = 0; 1194 + netdev_put(xso->dev, &xso->dev_tracker); 1195 + xso->dev = NULL; 1196 + xso->real_dev = NULL; 1197 + xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED; 1198 + } 1199 + #endif 1322 1200 x->km.state = XFRM_STATE_DEAD; 1323 1201 to_put = x; 1324 1202 x = NULL; ··· 1426 1280 1427 1281 h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, 1428 1282 x->props.reqid, x->props.family); 1429 - hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h); 1283 + XFRM_STATE_INSERT(bydst, &x->bydst, net->xfrm.state_bydst + h, 1284 + x->xso.type); 1430 1285 1431 1286 h = xfrm_src_hash(net, &x->id.daddr, &x->props.saddr, x->props.family); 1432 - hlist_add_head_rcu(&x->bysrc, net->xfrm.state_bysrc + h); 1287 + XFRM_STATE_INSERT(bysrc, &x->bysrc, net->xfrm.state_bysrc + h, 1288 + x->xso.type); 1433 1289 1434 1290 if (x->id.spi) { 1435 1291 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, 1436 1292 x->props.family); 1437 1293 1438 - hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h); 1294 + XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, 1295 + x->xso.type); 1439 1296 } 1440 1297 1441 1298 if (x->km.seq) { 1442 1299 h = xfrm_seq_hash(net, x->km.seq); 1443 1300 1444 - hlist_add_head_rcu(&x->byseq, net->xfrm.state_byseq + h); 1301 + XFRM_STATE_INSERT(byseq, &x->byseq, net->xfrm.state_byseq + h, 1302 + x->xso.type); 1445 1303 } 1446 1304 1447 1305 hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT); ··· 1559 1409 ktime_set(net->xfrm.sysctl_acq_expires, 0), 1560 1410 HRTIMER_MODE_REL_SOFT); 1561 1411 list_add(&x->km.all, &net->xfrm.state_all); 1562 - hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h); 1412 + XFRM_STATE_INSERT(bydst, &x->bydst, net->xfrm.state_bydst + h, 1413 + x->xso.type); 1563 1414 h = xfrm_src_hash(net, daddr, saddr, family); 1564 - hlist_add_head_rcu(&x->bysrc, net->xfrm.state_bysrc + h); 1415 + XFRM_STATE_INSERT(bysrc, &x->bysrc, net->xfrm.state_bysrc + h, 1416 + x->xso.type); 1565 1417 1566 1418 net->xfrm.state_num++; 1567 1419 ··· 1938 1786 1939 1787 int xfrm_state_check_expire(struct xfrm_state *x) 1940 1788 { 1789 + xfrm_dev_state_update_curlft(x); 1790 + 1941 1791 if (!x->curlft.use_time) 1942 1792 x->curlft.use_time = ktime_get_real_seconds(); 1943 1793 ··· 2248 2094 spin_lock_bh(&net->xfrm.xfrm_state_lock); 2249 2095 x->id.spi = newspi; 2250 2096 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); 2251 - hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h); 2097 + XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, 2098 + x->xso.type); 2252 2099 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 2253 2100 2254 2101 err = 0;
+20
net/xfrm/xfrm_user.c
··· 956 956 xuo->ifindex = xso->dev->ifindex; 957 957 if (xso->dir == XFRM_DEV_OFFLOAD_IN) 958 958 xuo->flags = XFRM_OFFLOAD_INBOUND; 959 + if (xso->type == XFRM_DEV_OFFLOAD_PACKET) 960 + xuo->flags |= XFRM_OFFLOAD_PACKET; 959 961 960 962 return 0; 961 963 } ··· 1892 1890 if (attrs[XFRMA_IF_ID]) 1893 1891 xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); 1894 1892 1893 + /* configure the hardware if offload is requested */ 1894 + if (attrs[XFRMA_OFFLOAD_DEV]) { 1895 + err = xfrm_dev_policy_add(net, xp, 1896 + nla_data(attrs[XFRMA_OFFLOAD_DEV]), 1897 + p->dir, extack); 1898 + if (err) 1899 + goto error; 1900 + } 1901 + 1895 1902 return xp; 1896 1903 error: 1897 1904 *errp = err; ··· 1940 1929 xfrm_audit_policy_add(xp, err ? 0 : 1, true); 1941 1930 1942 1931 if (err) { 1932 + xfrm_dev_policy_delete(xp); 1943 1933 security_xfrm_policy_free(xp->security); 1944 1934 kfree(xp); 1945 1935 return err; ··· 2053 2041 err = xfrm_mark_put(skb, &xp->mark); 2054 2042 if (!err) 2055 2043 err = xfrm_if_id_put(skb, xp->if_id); 2044 + if (!err && xp->xdo.dev) 2045 + err = copy_user_offload(&xp->xdo, skb); 2056 2046 if (err) { 2057 2047 nlmsg_cancel(skb, nlh); 2058 2048 return err; ··· 3393 3379 err = xfrm_mark_put(skb, &xp->mark); 3394 3380 if (!err) 3395 3381 err = xfrm_if_id_put(skb, xp->if_id); 3382 + if (!err && xp->xdo.dev) 3383 + err = copy_user_offload(&xp->xdo, skb); 3396 3384 if (err) { 3397 3385 nlmsg_cancel(skb, nlh); 3398 3386 return err; ··· 3513 3497 err = xfrm_mark_put(skb, &xp->mark); 3514 3498 if (!err) 3515 3499 err = xfrm_if_id_put(skb, xp->if_id); 3500 + if (!err && xp->xdo.dev) 3501 + err = copy_user_offload(&xp->xdo, skb); 3516 3502 if (err) { 3517 3503 nlmsg_cancel(skb, nlh); 3518 3504 return err; ··· 3598 3580 err = xfrm_mark_put(skb, &xp->mark); 3599 3581 if (!err) 3600 3582 err = xfrm_if_id_put(skb, xp->if_id); 3583 + if (!err && xp->xdo.dev) 3584 + err = copy_user_offload(&xp->xdo, skb); 3601 3585 if (err) 3602 3586 goto out_free_skb; 3603 3587