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

Merge branch 'add-basic-psp-encryption-for-tcp-connections'

Daniel Zahka says:

==================
add basic PSP encryption for TCP connections

This is v13 of the PSP RFC [1] posted by Jakub Kicinski one year
ago. General developments since v1 include a fork of packetdrill [2]
with support for PSP added, as well as some test cases, and an
implementation of PSP key exchange and connection upgrade [3]
integrated into the fbthrift RPC library. Both [2] and [3] have been
tested on server platforms with PSP-capable CX7 NICs. Below is the
cover letter from the original RFC:

Add support for PSP encryption of TCP connections.

PSP is a protocol out of Google:
https://github.com/google/psp/blob/main/doc/PSP_Arch_Spec.pdf
which shares some similarities with IPsec. I added some more info
in the first patch so I'll keep it short here.

The protocol can work in multiple modes including tunneling.
But I'm mostly interested in using it as TLS replacement because
of its superior offload characteristics. So this patch does three
things:

- it adds "core" PSP code
PSP is offload-centric, and requires some additional care and
feeding, so first chunk of the code exposes device info.
This part can be reused by PSP implementations in xfrm, tunneling etc.

- TCP integration TLS style
Reuse some of the existing concepts from TLS offload, such as
attaching crypto state to a socket, marking skbs as "decrypted",
egress validation. PSP does not prescribe key exchange protocols.
To use PSP as a more efficient TLS offload we intend to perform
a TLS handshake ("inline" in the same TCP connection) and negotiate
switching to PSP based on capabilities of both endpoints.
This is also why I'm not including a software implementation.
Nobody would use it in production, software TLS is faster,
it has larger crypto records.

- mlx5 implementation
That's mostly other people's work, not 100% sure those folks
consider it ready hence the RFC in the title. But it works :)

Not posted, queued a branch [4] are follow up pieces:
- standard stats
- netdevsim implementation and tests

[1] https://lore.kernel.org/netdev/20240510030435.120935-1-kuba@kernel.org/
[2] https://github.com/danieldzahka/packetdrill
[3] https://github.com/danieldzahka/fbthrift/tree/dzahka/psp
[4] https://github.com/kuba-moo/linux/tree/psp

Comments we intend to defer to future series:
- we prefer to keep the version field in the tx-assoc netlink
request, because it makes parsing keys require less state early
on, but we are willing to change in the next version of this
series.
- using a static branch to wrap psp_enqueue_set_decrypted() and
other functions called from tcp.
- using INDIRECT_CALL for tls/psp in sk_validate_xmit_skb(). We
prefer to address this in a dedicated patch series, so that this
series does not need to modify the way tls_validate_xmit_skb() is
declared and stubbed out.

v12: https://lore.kernel.org/netdev/20250916000559.1320151-1-kuba@kernel.org/
v11: https://lore.kernel.org/20250911014735.118695-1-daniel.zahka@gmail.com
v10: https://lore.kernel.org/netdev/20250828162953.2707727-1-daniel.zahka@gmail.com/
v9: https://lore.kernel.org/netdev/20250827155340.2738246-1-daniel.zahka@gmail.com/
v8: https://lore.kernel.org/netdev/20250825200112.1750547-1-daniel.zahka@gmail.com/
v7: https://lore.kernel.org/netdev/20250820113120.992829-1-daniel.zahka@gmail.com/
v6: https://lore.kernel.org/netdev/20250812003009.2455540-1-daniel.zahka@gmail.com/
v5: https://lore.kernel.org/netdev/20250723203454.519540-1-daniel.zahka@gmail.com/
v4: https://lore.kernel.org/netdev/20250716144551.3646755-1-daniel.zahka@gmail.com/
v3: https://lore.kernel.org/netdev/20250702171326.3265825-1-daniel.zahka@gmail.com/
v2: https://lore.kernel.org/netdev/20250625135210.2975231-1-daniel.zahka@gmail.com/
v1: https://lore.kernel.org/netdev/20240510030435.120935-1-kuba@kernel.org/
==================

Links: https://patch.msgid.link/20250917000954.859376-1-daniel.zahka@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
* add-basic-psp-encryption-for-tcp-connections:
net/mlx5e: Implement PSP key_rotate operation
net/mlx5e: Add Rx data path offload
psp: provide decapsulation and receive helper for drivers
net/mlx5e: Configure PSP Rx flow steering rules
net/mlx5e: Add PSP steering in local NIC RX
net/mlx5e: Implement PSP Tx data path
psp: provide encapsulation helper for drivers
net/mlx5e: Implement PSP operations .assoc_add and .assoc_del
net/mlx5e: Support PSP offload functionality
psp: track generations of device key
net: psp: update the TCP MSS to reflect PSP packet overhead
net: psp: add socket security association code
net: tcp: allow tcp_timewait_sock to validate skbs before handing to device
net: move sk_validate_xmit_skb() to net/core/dev.c
psp: add op for rotation of device key
tcp: add datapath logic for PSP with inline key exchange
net: modify core data structures for PSP datapath support
psp: base PSP device support
psp: add documentation

+3801 -55
+187
Documentation/netlink/specs/psp.yaml
··· 1 + # SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 2 + --- 3 + name: psp 4 + 5 + doc: 6 + PSP Security Protocol Generic Netlink family. 7 + 8 + definitions: 9 + - 10 + type: enum 11 + name: version 12 + entries: [hdr0-aes-gcm-128, hdr0-aes-gcm-256, 13 + hdr0-aes-gmac-128, hdr0-aes-gmac-256] 14 + 15 + attribute-sets: 16 + - 17 + name: dev 18 + attributes: 19 + - 20 + name: id 21 + doc: PSP device ID. 22 + type: u32 23 + checks: 24 + min: 1 25 + - 26 + name: ifindex 27 + doc: ifindex of the main netdevice linked to the PSP device. 28 + type: u32 29 + - 30 + name: psp-versions-cap 31 + doc: Bitmask of PSP versions supported by the device. 32 + type: u32 33 + enum: version 34 + enum-as-flags: true 35 + - 36 + name: psp-versions-ena 37 + doc: Bitmask of currently enabled (accepted on Rx) PSP versions. 38 + type: u32 39 + enum: version 40 + enum-as-flags: true 41 + - 42 + name: assoc 43 + attributes: 44 + - 45 + name: dev-id 46 + doc: PSP device ID. 47 + type: u32 48 + checks: 49 + min: 1 50 + - 51 + name: version 52 + doc: | 53 + PSP versions (AEAD and protocol version) used by this association, 54 + dictates the size of the key. 55 + type: u32 56 + enum: version 57 + - 58 + name: rx-key 59 + type: nest 60 + nested-attributes: keys 61 + - 62 + name: tx-key 63 + type: nest 64 + nested-attributes: keys 65 + - 66 + name: sock-fd 67 + doc: Sockets which should be bound to the association immediately. 68 + type: u32 69 + - 70 + name: keys 71 + attributes: 72 + - 73 + name: key 74 + type: binary 75 + - 76 + name: spi 77 + doc: Security Parameters Index (SPI) of the association. 78 + type: u32 79 + 80 + operations: 81 + list: 82 + - 83 + name: dev-get 84 + doc: Get / dump information about PSP capable devices on the system. 85 + attribute-set: dev 86 + do: 87 + request: 88 + attributes: 89 + - id 90 + reply: &dev-all 91 + attributes: 92 + - id 93 + - ifindex 94 + - psp-versions-cap 95 + - psp-versions-ena 96 + pre: psp-device-get-locked 97 + post: psp-device-unlock 98 + dump: 99 + reply: *dev-all 100 + - 101 + name: dev-add-ntf 102 + doc: Notification about device appearing. 103 + notify: dev-get 104 + mcgrp: mgmt 105 + - 106 + name: dev-del-ntf 107 + doc: Notification about device disappearing. 108 + notify: dev-get 109 + mcgrp: mgmt 110 + - 111 + name: dev-set 112 + doc: Set the configuration of a PSP device. 113 + attribute-set: dev 114 + do: 115 + request: 116 + attributes: 117 + - id 118 + - psp-versions-ena 119 + reply: 120 + attributes: [] 121 + pre: psp-device-get-locked 122 + post: psp-device-unlock 123 + - 124 + name: dev-change-ntf 125 + doc: Notification about device configuration being changed. 126 + notify: dev-get 127 + mcgrp: mgmt 128 + 129 + - 130 + name: key-rotate 131 + doc: Rotate the device key. 132 + attribute-set: dev 133 + do: 134 + request: 135 + attributes: 136 + - id 137 + reply: 138 + attributes: 139 + - id 140 + pre: psp-device-get-locked 141 + post: psp-device-unlock 142 + - 143 + name: key-rotate-ntf 144 + doc: Notification about device key getting rotated. 145 + notify: key-rotate 146 + mcgrp: use 147 + 148 + - 149 + name: rx-assoc 150 + doc: Allocate a new Rx key + SPI pair, associate it with a socket. 151 + attribute-set: assoc 152 + do: 153 + request: 154 + attributes: 155 + - dev-id 156 + - version 157 + - sock-fd 158 + reply: 159 + attributes: 160 + - dev-id 161 + - rx-key 162 + pre: psp-assoc-device-get-locked 163 + post: psp-device-unlock 164 + - 165 + name: tx-assoc 166 + doc: Add a PSP Tx association. 167 + attribute-set: assoc 168 + do: 169 + request: 170 + attributes: 171 + - dev-id 172 + - version 173 + - tx-key 174 + - sock-fd 175 + reply: 176 + attributes: [] 177 + pre: psp-assoc-device-get-locked 178 + post: psp-device-unlock 179 + 180 + mcast-groups: 181 + list: 182 + - 183 + name: mgmt 184 + - 185 + name: use 186 + 187 + ...
+1
Documentation/networking/index.rst
··· 101 101 ppp_generic 102 102 proc_net_tcp 103 103 pse-pd/index 104 + psp 104 105 radiotap-headers 105 106 rds 106 107 regulatory
+183
Documentation/networking/psp.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-only 2 + 3 + ===================== 4 + PSP Security Protocol 5 + ===================== 6 + 7 + Protocol 8 + ======== 9 + 10 + PSP Security Protocol (PSP) was defined at Google and published in: 11 + 12 + https://raw.githubusercontent.com/google/psp/main/doc/PSP_Arch_Spec.pdf 13 + 14 + This section briefly covers protocol aspects crucial for understanding 15 + the kernel API. Refer to the protocol specification for further details. 16 + 17 + Note that the kernel implementation and documentation uses the term 18 + "device key" in place of "master key", it is both less confusing 19 + to an average developer and is less likely to run afoul any naming 20 + guidelines. 21 + 22 + Derived Rx keys 23 + --------------- 24 + 25 + PSP borrows some terms and mechanisms from IPsec. PSP was designed 26 + with HW offloads in mind. The key feature of PSP is that Rx keys for every 27 + connection do not have to be stored by the receiver but can be derived 28 + from device key and information present in packet headers. 29 + This makes it possible to implement receivers which require a constant 30 + amount of memory regardless of the number of connections (``O(1)`` scaling). 31 + 32 + Tx keys have to be stored like with any other protocol, but Tx is much 33 + less latency sensitive than Rx, and delays in fetching keys from slow 34 + memory is less likely to cause packet drops. Preferably, the Tx keys 35 + should be provided with the packet (e.g. as part of the descriptors). 36 + 37 + Key rotation 38 + ------------ 39 + 40 + The device key known only to the receiver is fundamental to the design. 41 + Per specification this state cannot be directly accessible (it must be 42 + impossible to read it out of the hardware of the receiver NIC). 43 + Moreover, it has to be "rotated" periodically (usually daily). Rotation 44 + means that new device key gets generated (by a random number generator 45 + of the device), and used for all new connections. To avoid disrupting 46 + old connections the old device key remains in the NIC. A phase bit 47 + carried in the packet headers indicates which generation of device key 48 + the packet has been encrypted with. 49 + 50 + User facing API 51 + =============== 52 + 53 + PSP is designed primarily for hardware offloads. There is currently 54 + no software fallback for systems which do not have PSP capable NICs. 55 + There is also no standard (or otherwise defined) way of establishing 56 + a PSP-secured connection or exchanging the symmetric keys. 57 + 58 + The expectation is that higher layer protocols will take care of 59 + protocol and key negotiation. For example one may use TLS key exchange, 60 + announce the PSP capability, and switch to PSP if both endpoints 61 + are PSP-capable. 62 + 63 + All configuration of PSP is performed via the PSP netlink family. 64 + 65 + Device discovery 66 + ---------------- 67 + 68 + The PSP netlink family defines operations to retrieve information 69 + about the PSP devices available on the system, configure them and 70 + access PSP related statistics. 71 + 72 + Securing a connection 73 + --------------------- 74 + 75 + PSP encryption is currently only supported for TCP connections. 76 + Rx and Tx keys are allocated separately. First the ``rx-assoc`` 77 + Netlink command needs to be issued, specifying a target TCP socket. 78 + Kernel will allocate a new PSP Rx key from the NIC and associate it 79 + with given socket. At this stage socket will accept both PSP-secured 80 + and plain text TCP packets. 81 + 82 + Tx keys are installed using the ``tx-assoc`` Netlink command. 83 + Once the Tx keys are installed, all data read from the socket will 84 + be PSP-secured. In other words act of installing Tx keys has a secondary 85 + effect on the Rx direction. 86 + 87 + There is an intermediate period after ``tx-assoc`` successfully 88 + returns and before the TCP socket encounters it's first PSP 89 + authenticated packet, where the TCP stack will allow certain nondata 90 + packets, i.e. ACKs, FINs, and RSTs, to enter TCP receive processing 91 + even if not PSP authenticated. During the ``tx-assoc`` call, the TCP 92 + socket's ``rcv_nxt`` field is recorded. At this point, ACKs and RSTs 93 + will be accepted with any sequence number, while FINs will only be 94 + accepted at the latched value of ``rcv_nxt``. Once the TCP stack 95 + encounters the first TCP packet containing PSP authenticated data, the 96 + other end of the connection must have executed the ``tx-assoc`` 97 + command, so any TCP packet, including those without data, will be 98 + dropped before receive processing if it is not successfully 99 + authenticated. This is summarized in the table below. The 100 + aforementioned state of rejecting all non-PSP packets is labeled "PSP 101 + Full". 102 + 103 + +----------------+------------+------------+-------------+-------------+ 104 + | Event | Normal TCP | Rx PSP | Tx PSP | PSP Full | 105 + +================+============+============+=============+=============+ 106 + | Rx plain | accept | accept | drop | drop | 107 + | (data) | | | | | 108 + +----------------+------------+------------+-------------+-------------+ 109 + | Rx plain | accept | accept | accept | drop | 110 + | (ACK|FIN|RST) | | | | | 111 + +----------------+------------+------------+-------------+-------------+ 112 + | Rx PSP (good) | drop | accept | accept | accept | 113 + +----------------+------------+------------+-------------+-------------+ 114 + | Rx PSP (bad | drop | drop | drop | drop | 115 + | crypt, !=SPI) | | | | | 116 + +----------------+------------+------------+-------------+-------------+ 117 + | Tx | plain text | plain text | encrypted | encrypted | 118 + | | | | (excl. rtx) | (excl. rtx) | 119 + +----------------+------------+------------+-------------+-------------+ 120 + 121 + To ensure that any data read from the socket after the ``tx-assoc`` 122 + call returns success has been authenticated, the kernel will scan the 123 + receive and ofo queues of the socket at ``tx-assoc`` time. If any 124 + enqueued packet was received in clear text, the Tx association will 125 + fail, and the application should retry installing the Tx key after 126 + draining the socket (this should not be necessary if both endpoints 127 + are well behaved). 128 + 129 + Because TCP sequence numbers are not integrity protected prior to 130 + upgrading to PSP, it is possible that a MITM could offset sequence 131 + numbers in a way that deletes a prefix of the PSP protected part of 132 + the TCP stream. If userspace cares to mitigate this type of attack, a 133 + special "start of PSP" message should be exchanged after ``tx-assoc``. 134 + 135 + Rotation notifications 136 + ---------------------- 137 + 138 + The rotations of device key happen asynchronously and are usually 139 + performed by management daemons, not under application control. 140 + The PSP netlink family will generate a notification whenever keys 141 + are rotated. The applications are expected to re-establish connections 142 + before keys are rotated again. 143 + 144 + Kernel implementation 145 + ===================== 146 + 147 + Driver notes 148 + ------------ 149 + 150 + Drivers are expected to start with no PSP enabled (``psp-versions-ena`` 151 + in ``dev-get`` set to ``0``) whenever possible. The user space should 152 + not depend on this behavior, as future extension may necessitate creation 153 + of devices with PSP already enabled, nonetheless drivers should not enable 154 + PSP by default. Enabling PSP should be the responsibility of the system 155 + component which also takes care of key rotation. 156 + 157 + Note that ``psp-versions-ena`` is expected to be used only for enabling 158 + receive processing. The device is not expected to reject transmit requests 159 + after ``psp-versions-ena`` has been disabled. User may also disable 160 + ``psp-versions-ena`` while there are active associations, which will 161 + break all PSP Rx processing. 162 + 163 + Drivers are expected to ensure that a device key is usable and secure 164 + upon init, without explicit key rotation by the user space. It must be 165 + possible to allocate working keys, and that no duplicate keys must be 166 + generated. If the device allows the host to request the key for an 167 + arbitrary SPI - driver should discard both device keys (rotate the 168 + device key twice), to avoid potentially using a SPI+key which previous 169 + OS instance already had access to. 170 + 171 + Drivers must use ``psp_skb_get_assoc_rcu()`` to check if PSP Tx offload 172 + was requested for given skb. On Rx drivers should allocate and populate 173 + the ``SKB_EXT_PSP`` skb extension, and set the skb->decrypted bit to 1. 174 + 175 + Kernel implementation notes 176 + --------------------------- 177 + 178 + PSP implementation follows the TLS offload more closely than the IPsec 179 + offload, with per-socket state, and the use of skb->decrypted to prevent 180 + clear text leaks. 181 + 182 + PSP device is separate from netdev, to make it possible to "delegate" 183 + PSP offload capabilities to software devices (e.g. ``veth``).
+11
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
··· 207 207 help 208 208 DPLL support in Mellanox Technologies ConnectX NICs. 209 209 210 + config MLX5_EN_PSP 211 + bool "Mellanox Technologies support for PSP cryptography-offload acceleration" 212 + depends on INET_PSP 213 + depends on MLX5_CORE_EN 214 + default y 215 + help 216 + mlx5 device offload support for Google PSP Security Protocol offload. 217 + Adds support for PSP encryption offload and for SPI and key generation 218 + interfaces to PSP Stack which supports PSP crypto offload. 219 + 220 + If unsure, say Y.
+2
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 112 112 en_accel/fs_tcp.o en_accel/ktls.o en_accel/ktls_txrx.o \ 113 113 en_accel/ktls_tx.o en_accel/ktls_rx.o 114 114 115 + mlx5_core-$(CONFIG_MLX5_EN_PSP) += en_accel/psp.o en_accel/psp_rxtx.o 116 + 115 117 # 116 118 # SW Steering 117 119 #
+5 -1
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 47 47 #include <linux/rhashtable.h> 48 48 #include <net/udp_tunnel.h> 49 49 #include <net/switchdev.h> 50 + #include <net/psp/types.h> 50 51 #include <net/xdp.h> 51 52 #include <linux/dim.h> 52 53 #include <linux/bits.h> ··· 69 68 #define MLX5E_METADATA_ETHER_TYPE (0x8CE4) 70 69 #define MLX5E_METADATA_ETHER_LEN 8 71 70 72 - #define MLX5E_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) 71 + #define MLX5E_ETH_HARD_MTU (ETH_HLEN + PSP_ENCAP_HLEN + PSP_TRL_SIZE + VLAN_HLEN + ETH_FCS_LEN) 73 72 74 73 #define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu)) 75 74 #define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu)) ··· 938 937 #endif 939 938 #ifdef CONFIG_MLX5_EN_IPSEC 940 939 struct mlx5e_ipsec *ipsec; 940 + #endif 941 + #ifdef CONFIG_MLX5_EN_PSP 942 + struct mlx5e_psp *psp; 941 943 #endif 942 944 #ifdef CONFIG_MLX5_EN_TLS 943 945 struct mlx5e_tls *tls;
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
··· 88 88 #ifdef CONFIG_MLX5_EN_ARFS 89 89 MLX5E_ARFS_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, 90 90 #endif 91 - #ifdef CONFIG_MLX5_EN_IPSEC 91 + #if defined(CONFIG_MLX5_EN_IPSEC) || defined(CONFIG_MLX5_EN_PSP) 92 92 MLX5E_ACCEL_FS_ESP_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, 93 93 MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, 94 94 MLX5E_ACCEL_FS_POL_FT_LEVEL,
+3 -1
drivers/net/ethernet/mellanox/mlx5/core/en/params.c
··· 6 6 #include "en/port.h" 7 7 #include "en_accel/en_accel.h" 8 8 #include "en_accel/ipsec.h" 9 + #include "en_accel/psp.h" 9 10 #include <linux/dim.h> 10 11 #include <net/page_pool/types.h> 11 12 #include <net/xdp_sock_drv.h> ··· 1005 1004 bool allow_swp; 1006 1005 1007 1006 allow_swp = mlx5_geneve_tx_allowed(mdev) || 1008 - (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_CRYPTO); 1007 + (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_CRYPTO) || 1008 + mlx5_is_psp_device(mdev); 1009 1009 mlx5e_build_sq_param_common(mdev, param); 1010 1010 MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size); 1011 1011 MLX5_SET(sqc, sqc, allow_swp, allow_swp);
+49 -1
drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
··· 42 42 #include <en_accel/macsec.h> 43 43 #include "en.h" 44 44 #include "en/txrx.h" 45 + #include "en_accel/psp.h" 46 + #include "en_accel/psp_rxtx.h" 45 47 46 48 #if IS_ENABLED(CONFIG_GENEVE) 47 49 #include <net/geneve.h> ··· 121 119 #ifdef CONFIG_MLX5_EN_IPSEC 122 120 struct mlx5e_accel_tx_ipsec_state ipsec; 123 121 #endif 122 + #ifdef CONFIG_MLX5_EN_PSP 123 + struct mlx5e_accel_tx_psp_state psp_st; 124 + #endif 124 125 }; 125 126 126 127 static inline bool mlx5e_accel_tx_begin(struct net_device *dev, ··· 140 135 if (unlikely(!mlx5e_ktls_handle_tx_skb(dev, sq, skb, 141 136 &state->tls))) 142 137 return false; 138 + #endif 139 + 140 + #ifdef CONFIG_MLX5_EN_PSP 141 + if (mlx5e_psp_is_offload(skb, dev)) { 142 + if (unlikely(!mlx5e_psp_handle_tx_skb(dev, skb, &state->psp_st))) 143 + return false; 144 + } 143 145 #endif 144 146 145 147 #ifdef CONFIG_MLX5_EN_IPSEC ··· 169 157 } 170 158 171 159 static inline unsigned int mlx5e_accel_tx_ids_len(struct mlx5e_txqsq *sq, 160 + struct sk_buff *skb, 172 161 struct mlx5e_accel_tx_state *state) 173 162 { 163 + #ifdef CONFIG_MLX5_EN_PSP 164 + if (mlx5e_psp_is_offload_state(&state->psp_st)) 165 + return mlx5e_psp_tx_ids_len(&state->psp_st); 166 + #endif 167 + 174 168 #ifdef CONFIG_MLX5_EN_IPSEC 175 169 if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state)) 176 170 return mlx5e_ipsec_tx_ids_len(&state->ipsec); ··· 190 172 191 173 static inline void mlx5e_accel_tx_eseg(struct mlx5e_priv *priv, 192 174 struct sk_buff *skb, 175 + struct mlx5e_accel_tx_state *accel, 193 176 struct mlx5_wqe_eth_seg *eseg, u16 ihs) 194 177 { 178 + #ifdef CONFIG_MLX5_EN_PSP 179 + if (mlx5e_psp_is_offload_state(&accel->psp_st)) 180 + mlx5e_psp_tx_build_eseg(priv, skb, &accel->psp_st, eseg); 181 + #endif 182 + 195 183 #ifdef CONFIG_MLX5_EN_IPSEC 196 184 if (xfrm_offload(skb)) 197 185 mlx5e_ipsec_tx_build_eseg(priv, skb, eseg); ··· 223 199 mlx5e_ktls_handle_tx_wqe(&wqe->ctrl, &state->tls); 224 200 #endif 225 201 202 + #ifdef CONFIG_MLX5_EN_PSP 203 + if (mlx5e_psp_is_offload_state(&state->psp_st)) 204 + mlx5e_psp_handle_tx_wqe(wqe, &state->psp_st, inlseg); 205 + #endif 206 + 226 207 #ifdef CONFIG_MLX5_EN_IPSEC 227 208 if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state) && 228 209 state->ipsec.xo && state->ipsec.tailen) ··· 237 208 238 209 static inline int mlx5e_accel_init_rx(struct mlx5e_priv *priv) 239 210 { 240 - return mlx5e_ktls_init_rx(priv); 211 + int err; 212 + 213 + err = mlx5_accel_psp_fs_init_rx_tables(priv); 214 + if (err) 215 + goto out; 216 + 217 + err = mlx5e_ktls_init_rx(priv); 218 + if (err) 219 + mlx5_accel_psp_fs_cleanup_rx_tables(priv); 220 + 221 + out: 222 + return err; 241 223 } 242 224 243 225 static inline void mlx5e_accel_cleanup_rx(struct mlx5e_priv *priv) 244 226 { 245 227 mlx5e_ktls_cleanup_rx(priv); 228 + mlx5_accel_psp_fs_cleanup_rx_tables(priv); 246 229 } 247 230 248 231 static inline int mlx5e_accel_init_tx(struct mlx5e_priv *priv) 249 232 { 233 + int err; 234 + 235 + err = mlx5_accel_psp_fs_init_tx_tables(priv); 236 + if (err) 237 + return err; 238 + 250 239 return mlx5e_ktls_init_tx(priv); 251 240 } 252 241 253 242 static inline void mlx5e_accel_cleanup_tx(struct mlx5e_priv *priv) 254 243 { 255 244 mlx5e_ktls_cleanup_tx(priv); 245 + mlx5_accel_psp_fs_cleanup_tx_tables(priv); 256 246 } 257 247 #endif /* __MLX5E_EN_ACCEL_H__ */
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
··· 40 40 #include "en/txrx.h" 41 41 42 42 /* Bit31: IPsec marker, Bit30: reserved, Bit29-24: IPsec syndrome, Bit23-0: IPsec obj id */ 43 - #define MLX5_IPSEC_METADATA_MARKER(metadata) (((metadata) >> 31) & 0x1) 43 + #define MLX5_IPSEC_METADATA_MARKER(metadata) ((((metadata) >> 30) & 0x3) == 0x2) 44 44 #define MLX5_IPSEC_METADATA_SYNDROM(metadata) (((metadata) >> 24) & GENMASK(5, 0)) 45 45 #define MLX5_IPSEC_METADATA_HANDLE(metadata) ((metadata) & GENMASK(23, 0)) 46 46
+952
drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + #include <linux/mlx5/device.h> 4 + #include <net/psp.h> 5 + #include <linux/psp.h> 6 + #include "mlx5_core.h" 7 + #include "psp.h" 8 + #include "lib/crypto.h" 9 + #include "en_accel/psp.h" 10 + #include "fs_core.h" 11 + 12 + enum accel_fs_psp_type { 13 + ACCEL_FS_PSP4, 14 + ACCEL_FS_PSP6, 15 + ACCEL_FS_PSP_NUM_TYPES, 16 + }; 17 + 18 + enum accel_psp_syndrome { 19 + PSP_OK = 0, 20 + PSP_ICV_FAIL, 21 + PSP_BAD_TRAILER, 22 + }; 23 + 24 + struct mlx5e_psp_tx { 25 + struct mlx5_flow_namespace *ns; 26 + struct mlx5_flow_table *ft; 27 + struct mlx5_flow_group *fg; 28 + struct mlx5_flow_handle *rule; 29 + struct mutex mutex; /* Protect PSP TX steering */ 30 + u32 refcnt; 31 + }; 32 + 33 + struct mlx5e_psp_rx_err { 34 + struct mlx5_flow_table *ft; 35 + struct mlx5_flow_handle *rule; 36 + struct mlx5_flow_handle *drop_rule; 37 + struct mlx5_modify_hdr *copy_modify_hdr; 38 + }; 39 + 40 + struct mlx5e_accel_fs_psp_prot { 41 + struct mlx5_flow_table *ft; 42 + struct mlx5_flow_group *miss_group; 43 + struct mlx5_flow_handle *miss_rule; 44 + struct mlx5_flow_destination default_dest; 45 + struct mlx5e_psp_rx_err rx_err; 46 + u32 refcnt; 47 + struct mutex prot_mutex; /* protect ESP4/ESP6 protocol */ 48 + struct mlx5_flow_handle *def_rule; 49 + }; 50 + 51 + struct mlx5e_accel_fs_psp { 52 + struct mlx5e_accel_fs_psp_prot fs_prot[ACCEL_FS_PSP_NUM_TYPES]; 53 + }; 54 + 55 + struct mlx5e_psp_fs { 56 + struct mlx5_core_dev *mdev; 57 + struct mlx5e_psp_tx *tx_fs; 58 + /* Rx manage */ 59 + struct mlx5e_flow_steering *fs; 60 + struct mlx5e_accel_fs_psp *rx_fs; 61 + }; 62 + 63 + /* PSP RX flow steering */ 64 + static enum mlx5_traffic_types fs_psp2tt(enum accel_fs_psp_type i) 65 + { 66 + if (i == ACCEL_FS_PSP4) 67 + return MLX5_TT_IPV4_UDP; 68 + 69 + return MLX5_TT_IPV6_UDP; 70 + } 71 + 72 + static void accel_psp_fs_rx_err_del_rules(struct mlx5e_psp_fs *fs, 73 + struct mlx5e_psp_rx_err *rx_err) 74 + { 75 + if (rx_err->drop_rule) { 76 + mlx5_del_flow_rules(rx_err->drop_rule); 77 + rx_err->drop_rule = NULL; 78 + } 79 + 80 + if (rx_err->rule) { 81 + mlx5_del_flow_rules(rx_err->rule); 82 + rx_err->rule = NULL; 83 + } 84 + 85 + if (rx_err->copy_modify_hdr) { 86 + mlx5_modify_header_dealloc(fs->mdev, rx_err->copy_modify_hdr); 87 + rx_err->copy_modify_hdr = NULL; 88 + } 89 + } 90 + 91 + static void accel_psp_fs_rx_err_destroy_ft(struct mlx5e_psp_fs *fs, 92 + struct mlx5e_psp_rx_err *rx_err) 93 + { 94 + accel_psp_fs_rx_err_del_rules(fs, rx_err); 95 + 96 + if (rx_err->ft) { 97 + mlx5_destroy_flow_table(rx_err->ft); 98 + rx_err->ft = NULL; 99 + } 100 + } 101 + 102 + static void accel_psp_setup_syndrome_match(struct mlx5_flow_spec *spec, 103 + enum accel_psp_syndrome syndrome) 104 + { 105 + void *misc_params_2; 106 + 107 + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; 108 + misc_params_2 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2); 109 + MLX5_SET_TO_ONES(fte_match_set_misc2, misc_params_2, psp_syndrome); 110 + misc_params_2 = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2); 111 + MLX5_SET(fte_match_set_misc2, misc_params_2, psp_syndrome, syndrome); 112 + } 113 + 114 + static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs, 115 + struct mlx5e_accel_fs_psp_prot *fs_prot, 116 + struct mlx5e_psp_rx_err *rx_err) 117 + { 118 + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 119 + struct mlx5_core_dev *mdev = fs->mdev; 120 + struct mlx5_flow_act flow_act = {}; 121 + struct mlx5_modify_hdr *modify_hdr; 122 + struct mlx5_flow_handle *fte; 123 + struct mlx5_flow_spec *spec; 124 + int err = 0; 125 + 126 + spec = kzalloc(sizeof(*spec), GFP_KERNEL); 127 + if (!spec) 128 + return -ENOMEM; 129 + 130 + /* Action to copy 7 bit psp_syndrome to regB[23:29] */ 131 + MLX5_SET(copy_action_in, action, action_type, MLX5_ACTION_TYPE_COPY); 132 + MLX5_SET(copy_action_in, action, src_field, MLX5_ACTION_IN_FIELD_PSP_SYNDROME); 133 + MLX5_SET(copy_action_in, action, src_offset, 0); 134 + MLX5_SET(copy_action_in, action, length, 7); 135 + MLX5_SET(copy_action_in, action, dst_field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); 136 + MLX5_SET(copy_action_in, action, dst_offset, 23); 137 + 138 + modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_KERNEL, 139 + 1, action); 140 + if (IS_ERR(modify_hdr)) { 141 + err = PTR_ERR(modify_hdr); 142 + mlx5_core_err(mdev, 143 + "fail to alloc psp copy modify_header_id err=%d\n", err); 144 + goto out_spec; 145 + } 146 + 147 + accel_psp_setup_syndrome_match(spec, PSP_OK); 148 + /* create fte */ 149 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | 150 + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 151 + flow_act.modify_hdr = modify_hdr; 152 + fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, 153 + &fs_prot->default_dest, 1); 154 + if (IS_ERR(fte)) { 155 + err = PTR_ERR(fte); 156 + mlx5_core_err(mdev, "fail to add psp rx err copy rule err=%d\n", err); 157 + goto out; 158 + } 159 + rx_err->rule = fte; 160 + 161 + /* add default drop rule */ 162 + memset(spec, 0, sizeof(*spec)); 163 + memset(&flow_act, 0, sizeof(flow_act)); 164 + /* create fte */ 165 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; 166 + fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, NULL, 0); 167 + if (IS_ERR(fte)) { 168 + err = PTR_ERR(fte); 169 + mlx5_core_err(mdev, "fail to add psp rx err drop rule err=%d\n", err); 170 + goto out_drop_rule; 171 + } 172 + rx_err->drop_rule = fte; 173 + rx_err->copy_modify_hdr = modify_hdr; 174 + 175 + goto out_spec; 176 + 177 + out_drop_rule: 178 + mlx5_del_flow_rules(rx_err->rule); 179 + rx_err->rule = NULL; 180 + out: 181 + mlx5_modify_header_dealloc(mdev, modify_hdr); 182 + out_spec: 183 + kfree(spec); 184 + return err; 185 + } 186 + 187 + static int accel_psp_fs_rx_err_create_ft(struct mlx5e_psp_fs *fs, 188 + struct mlx5e_accel_fs_psp_prot *fs_prot, 189 + struct mlx5e_psp_rx_err *rx_err) 190 + { 191 + struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs->fs, false); 192 + struct mlx5_flow_table_attr ft_attr = {}; 193 + struct mlx5_flow_table *ft; 194 + int err; 195 + 196 + ft_attr.max_fte = 2; 197 + ft_attr.autogroup.max_num_groups = 2; 198 + ft_attr.level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; // MLX5E_ACCEL_FS_TCP_FT_LEVEL 199 + ft_attr.prio = MLX5E_NIC_PRIO; 200 + ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 201 + if (IS_ERR(ft)) { 202 + err = PTR_ERR(ft); 203 + mlx5_core_err(fs->mdev, "fail to create psp rx inline ft err=%d\n", err); 204 + return err; 205 + } 206 + 207 + rx_err->ft = ft; 208 + err = accel_psp_fs_rx_err_add_rule(fs, fs_prot, rx_err); 209 + if (err) 210 + goto out_err; 211 + 212 + return 0; 213 + 214 + out_err: 215 + mlx5_destroy_flow_table(ft); 216 + rx_err->ft = NULL; 217 + return err; 218 + } 219 + 220 + static void accel_psp_fs_rx_fs_destroy(struct mlx5e_accel_fs_psp_prot *fs_prot) 221 + { 222 + if (fs_prot->def_rule) { 223 + mlx5_del_flow_rules(fs_prot->def_rule); 224 + fs_prot->def_rule = NULL; 225 + } 226 + 227 + if (fs_prot->miss_rule) { 228 + mlx5_del_flow_rules(fs_prot->miss_rule); 229 + fs_prot->miss_rule = NULL; 230 + } 231 + 232 + if (fs_prot->miss_group) { 233 + mlx5_destroy_flow_group(fs_prot->miss_group); 234 + fs_prot->miss_group = NULL; 235 + } 236 + 237 + if (fs_prot->ft) { 238 + mlx5_destroy_flow_table(fs_prot->ft); 239 + fs_prot->ft = NULL; 240 + } 241 + } 242 + 243 + static void setup_fte_udp_psp(struct mlx5_flow_spec *spec, u16 udp_port) 244 + { 245 + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 246 + MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport, 0xffff); 247 + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, udp_port); 248 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, spec->match_criteria, ip_protocol); 249 + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, ip_protocol, IPPROTO_UDP); 250 + } 251 + 252 + static int accel_psp_fs_rx_create_ft(struct mlx5e_psp_fs *fs, 253 + struct mlx5e_accel_fs_psp_prot *fs_prot) 254 + { 255 + struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs->fs, false); 256 + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 257 + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 258 + struct mlx5_modify_hdr *modify_hdr = NULL; 259 + struct mlx5_flow_table_attr ft_attr = {}; 260 + struct mlx5_flow_destination dest = {}; 261 + struct mlx5_core_dev *mdev = fs->mdev; 262 + struct mlx5_flow_group *miss_group; 263 + MLX5_DECLARE_FLOW_ACT(flow_act); 264 + struct mlx5_flow_handle *rule; 265 + struct mlx5_flow_spec *spec; 266 + struct mlx5_flow_table *ft; 267 + u32 *flow_group_in; 268 + int err = 0; 269 + 270 + flow_group_in = kvzalloc(inlen, GFP_KERNEL); 271 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 272 + if (!flow_group_in || !spec) { 273 + err = -ENOMEM; 274 + goto out; 275 + } 276 + 277 + /* Create FT */ 278 + ft_attr.max_fte = 2; 279 + ft_attr.level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; 280 + ft_attr.prio = MLX5E_NIC_PRIO; 281 + ft_attr.autogroup.num_reserved_entries = 1; 282 + ft_attr.autogroup.max_num_groups = 1; 283 + ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 284 + if (IS_ERR(ft)) { 285 + err = PTR_ERR(ft); 286 + mlx5_core_err(mdev, "fail to create psp rx ft err=%d\n", err); 287 + goto out_err; 288 + } 289 + fs_prot->ft = ft; 290 + 291 + /* Create miss_group */ 292 + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ft->max_fte - 1); 293 + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ft->max_fte - 1); 294 + miss_group = mlx5_create_flow_group(ft, flow_group_in); 295 + if (IS_ERR(miss_group)) { 296 + err = PTR_ERR(miss_group); 297 + mlx5_core_err(mdev, "fail to create psp rx miss_group err=%d\n", err); 298 + goto out_err; 299 + } 300 + fs_prot->miss_group = miss_group; 301 + 302 + /* Create miss rule */ 303 + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &fs_prot->default_dest, 1); 304 + if (IS_ERR(rule)) { 305 + err = PTR_ERR(rule); 306 + mlx5_core_err(mdev, "fail to create psp rx miss_rule err=%d\n", err); 307 + goto out_err; 308 + } 309 + fs_prot->miss_rule = rule; 310 + 311 + /* Add default Rx psp rule */ 312 + setup_fte_udp_psp(spec, PSP_DEFAULT_UDP_PORT); 313 + flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_PSP; 314 + /* Set bit[31, 30] PSP marker */ 315 + /* Set bit[29-23] psp_syndrome is set in error FT */ 316 + #define MLX5E_PSP_MARKER_BIT (BIT(30) | BIT(31)) 317 + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); 318 + MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); 319 + MLX5_SET(set_action_in, action, data, MLX5E_PSP_MARKER_BIT); 320 + MLX5_SET(set_action_in, action, offset, 0); 321 + MLX5_SET(set_action_in, action, length, 32); 322 + 323 + modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_KERNEL, 1, action); 324 + if (IS_ERR(modify_hdr)) { 325 + err = PTR_ERR(modify_hdr); 326 + mlx5_core_err(mdev, "fail to alloc psp set modify_header_id err=%d\n", err); 327 + modify_hdr = NULL; 328 + goto out_err; 329 + } 330 + 331 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 332 + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT | 333 + MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 334 + flow_act.modify_hdr = modify_hdr; 335 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 336 + dest.ft = fs_prot->rx_err.ft; 337 + rule = mlx5_add_flow_rules(fs_prot->ft, spec, &flow_act, &dest, 1); 338 + if (IS_ERR(rule)) { 339 + err = PTR_ERR(rule); 340 + mlx5_core_err(mdev, 341 + "fail to add psp rule Rx decryption, err=%d, flow_act.action = %#04X\n", 342 + err, flow_act.action); 343 + goto out_err; 344 + } 345 + 346 + fs_prot->def_rule = rule; 347 + goto out; 348 + 349 + out_err: 350 + accel_psp_fs_rx_fs_destroy(fs_prot); 351 + out: 352 + kvfree(flow_group_in); 353 + kvfree(spec); 354 + return err; 355 + } 356 + 357 + static int accel_psp_fs_rx_destroy(struct mlx5e_psp_fs *fs, enum accel_fs_psp_type type) 358 + { 359 + struct mlx5e_accel_fs_psp_prot *fs_prot; 360 + struct mlx5e_accel_fs_psp *accel_psp; 361 + 362 + accel_psp = fs->rx_fs; 363 + 364 + /* The netdev unreg already happened, so all offloaded rule are already removed */ 365 + fs_prot = &accel_psp->fs_prot[type]; 366 + 367 + accel_psp_fs_rx_fs_destroy(fs_prot); 368 + 369 + accel_psp_fs_rx_err_destroy_ft(fs, &fs_prot->rx_err); 370 + 371 + return 0; 372 + } 373 + 374 + static int accel_psp_fs_rx_create(struct mlx5e_psp_fs *fs, enum accel_fs_psp_type type) 375 + { 376 + struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs->fs, false); 377 + struct mlx5e_accel_fs_psp_prot *fs_prot; 378 + struct mlx5e_accel_fs_psp *accel_psp; 379 + int err; 380 + 381 + accel_psp = fs->rx_fs; 382 + fs_prot = &accel_psp->fs_prot[type]; 383 + 384 + fs_prot->default_dest = mlx5_ttc_get_default_dest(ttc, fs_psp2tt(type)); 385 + 386 + err = accel_psp_fs_rx_err_create_ft(fs, fs_prot, &fs_prot->rx_err); 387 + if (err) 388 + return err; 389 + 390 + err = accel_psp_fs_rx_create_ft(fs, fs_prot); 391 + if (err) 392 + accel_psp_fs_rx_err_destroy_ft(fs, &fs_prot->rx_err); 393 + 394 + return err; 395 + } 396 + 397 + static int accel_psp_fs_rx_ft_get(struct mlx5e_psp_fs *fs, enum accel_fs_psp_type type) 398 + { 399 + struct mlx5e_accel_fs_psp_prot *fs_prot; 400 + struct mlx5_flow_destination dest = {}; 401 + struct mlx5e_accel_fs_psp *accel_psp; 402 + struct mlx5_ttc_table *ttc; 403 + int err = 0; 404 + 405 + if (!fs || !fs->rx_fs) 406 + return -EINVAL; 407 + 408 + ttc = mlx5e_fs_get_ttc(fs->fs, false); 409 + accel_psp = fs->rx_fs; 410 + fs_prot = &accel_psp->fs_prot[type]; 411 + mutex_lock(&fs_prot->prot_mutex); 412 + if (fs_prot->refcnt++) 413 + goto out; 414 + 415 + /* create FT */ 416 + err = accel_psp_fs_rx_create(fs, type); 417 + if (err) { 418 + fs_prot->refcnt--; 419 + goto out; 420 + } 421 + 422 + /* connect */ 423 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 424 + dest.ft = fs_prot->ft; 425 + mlx5_ttc_fwd_dest(ttc, fs_psp2tt(type), &dest); 426 + 427 + out: 428 + mutex_unlock(&fs_prot->prot_mutex); 429 + return err; 430 + } 431 + 432 + static void accel_psp_fs_rx_ft_put(struct mlx5e_psp_fs *fs, enum accel_fs_psp_type type) 433 + { 434 + struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs->fs, false); 435 + struct mlx5e_accel_fs_psp_prot *fs_prot; 436 + struct mlx5e_accel_fs_psp *accel_psp; 437 + 438 + accel_psp = fs->rx_fs; 439 + fs_prot = &accel_psp->fs_prot[type]; 440 + mutex_lock(&fs_prot->prot_mutex); 441 + if (--fs_prot->refcnt) 442 + goto out; 443 + 444 + /* disconnect */ 445 + mlx5_ttc_fwd_default_dest(ttc, fs_psp2tt(type)); 446 + 447 + /* remove FT */ 448 + accel_psp_fs_rx_destroy(fs, type); 449 + 450 + out: 451 + mutex_unlock(&fs_prot->prot_mutex); 452 + } 453 + 454 + static void accel_psp_fs_cleanup_rx(struct mlx5e_psp_fs *fs) 455 + { 456 + struct mlx5e_accel_fs_psp_prot *fs_prot; 457 + struct mlx5e_accel_fs_psp *accel_psp; 458 + enum accel_fs_psp_type i; 459 + 460 + if (!fs->rx_fs) 461 + return; 462 + 463 + accel_psp = fs->rx_fs; 464 + for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) { 465 + fs_prot = &accel_psp->fs_prot[i]; 466 + mutex_destroy(&fs_prot->prot_mutex); 467 + WARN_ON(fs_prot->refcnt); 468 + } 469 + kfree(fs->rx_fs); 470 + fs->rx_fs = NULL; 471 + } 472 + 473 + static int accel_psp_fs_init_rx(struct mlx5e_psp_fs *fs) 474 + { 475 + struct mlx5e_accel_fs_psp_prot *fs_prot; 476 + struct mlx5e_accel_fs_psp *accel_psp; 477 + enum accel_fs_psp_type i; 478 + 479 + accel_psp = kzalloc(sizeof(*accel_psp), GFP_KERNEL); 480 + if (!accel_psp) 481 + return -ENOMEM; 482 + 483 + for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) { 484 + fs_prot = &accel_psp->fs_prot[i]; 485 + mutex_init(&fs_prot->prot_mutex); 486 + } 487 + 488 + fs->rx_fs = accel_psp; 489 + 490 + return 0; 491 + } 492 + 493 + void mlx5_accel_psp_fs_cleanup_rx_tables(struct mlx5e_priv *priv) 494 + { 495 + int i; 496 + 497 + if (!priv->psp) 498 + return; 499 + 500 + for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) 501 + accel_psp_fs_rx_ft_put(priv->psp->fs, i); 502 + } 503 + 504 + int mlx5_accel_psp_fs_init_rx_tables(struct mlx5e_priv *priv) 505 + { 506 + struct mlx5e_psp_fs *fs; 507 + int err, i; 508 + 509 + if (!priv->psp) 510 + return 0; 511 + 512 + fs = priv->psp->fs; 513 + for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) { 514 + err = accel_psp_fs_rx_ft_get(fs, i); 515 + if (err) 516 + goto out_err; 517 + } 518 + 519 + return 0; 520 + 521 + out_err: 522 + i--; 523 + while (i >= 0) { 524 + accel_psp_fs_rx_ft_put(fs, i); 525 + --i; 526 + } 527 + 528 + return err; 529 + } 530 + 531 + static int accel_psp_fs_tx_create_ft_table(struct mlx5e_psp_fs *fs) 532 + { 533 + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 534 + struct mlx5_flow_table_attr ft_attr = {}; 535 + struct mlx5_core_dev *mdev = fs->mdev; 536 + struct mlx5_flow_act flow_act = {}; 537 + u32 *in, *mc, *outer_headers_c; 538 + struct mlx5_flow_handle *rule; 539 + struct mlx5_flow_spec *spec; 540 + struct mlx5e_psp_tx *tx_fs; 541 + struct mlx5_flow_table *ft; 542 + struct mlx5_flow_group *fg; 543 + int err = 0; 544 + 545 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 546 + in = kvzalloc(inlen, GFP_KERNEL); 547 + if (!spec || !in) { 548 + err = -ENOMEM; 549 + goto out; 550 + } 551 + 552 + ft_attr.max_fte = 1; 553 + #define MLX5E_PSP_PRIO 0 554 + ft_attr.prio = MLX5E_PSP_PRIO; 555 + #define MLX5E_PSP_LEVEL 0 556 + ft_attr.level = MLX5E_PSP_LEVEL; 557 + ft_attr.autogroup.max_num_groups = 1; 558 + 559 + tx_fs = fs->tx_fs; 560 + ft = mlx5_create_flow_table(tx_fs->ns, &ft_attr); 561 + if (IS_ERR(ft)) { 562 + err = PTR_ERR(ft); 563 + mlx5_core_err(mdev, "PSP: fail to add psp tx flow table, err = %d\n", err); 564 + goto out; 565 + } 566 + 567 + mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 568 + outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers); 569 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol); 570 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, udp_dport); 571 + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 572 + fg = mlx5_create_flow_group(ft, in); 573 + if (IS_ERR(fg)) { 574 + err = PTR_ERR(fg); 575 + mlx5_core_err(mdev, "PSP: fail to add psp tx flow group, err = %d\n", err); 576 + goto err_create_fg; 577 + } 578 + 579 + setup_fte_udp_psp(spec, PSP_DEFAULT_UDP_PORT); 580 + flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_PSP; 581 + flow_act.flags |= FLOW_ACT_NO_APPEND; 582 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | 583 + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT; 584 + rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0); 585 + if (IS_ERR(rule)) { 586 + err = PTR_ERR(rule); 587 + mlx5_core_err(mdev, "PSP: fail to add psp tx flow rule, err = %d\n", err); 588 + goto err_add_flow_rule; 589 + } 590 + 591 + tx_fs->ft = ft; 592 + tx_fs->fg = fg; 593 + tx_fs->rule = rule; 594 + goto out; 595 + 596 + err_add_flow_rule: 597 + mlx5_destroy_flow_group(fg); 598 + err_create_fg: 599 + mlx5_destroy_flow_table(ft); 600 + out: 601 + kvfree(in); 602 + kvfree(spec); 603 + return err; 604 + } 605 + 606 + static void accel_psp_fs_tx_destroy(struct mlx5e_psp_tx *tx_fs) 607 + { 608 + if (!tx_fs->ft) 609 + return; 610 + 611 + mlx5_del_flow_rules(tx_fs->rule); 612 + mlx5_destroy_flow_group(tx_fs->fg); 613 + mlx5_destroy_flow_table(tx_fs->ft); 614 + } 615 + 616 + static int accel_psp_fs_tx_ft_get(struct mlx5e_psp_fs *fs) 617 + { 618 + struct mlx5e_psp_tx *tx_fs = fs->tx_fs; 619 + int err = 0; 620 + 621 + mutex_lock(&tx_fs->mutex); 622 + if (tx_fs->refcnt++) 623 + goto out; 624 + 625 + err = accel_psp_fs_tx_create_ft_table(fs); 626 + if (err) 627 + tx_fs->refcnt--; 628 + out: 629 + mutex_unlock(&tx_fs->mutex); 630 + return err; 631 + } 632 + 633 + static void accel_psp_fs_tx_ft_put(struct mlx5e_psp_fs *fs) 634 + { 635 + struct mlx5e_psp_tx *tx_fs = fs->tx_fs; 636 + 637 + mutex_lock(&tx_fs->mutex); 638 + if (--tx_fs->refcnt) 639 + goto out; 640 + 641 + accel_psp_fs_tx_destroy(tx_fs); 642 + out: 643 + mutex_unlock(&tx_fs->mutex); 644 + } 645 + 646 + static void accel_psp_fs_cleanup_tx(struct mlx5e_psp_fs *fs) 647 + { 648 + struct mlx5e_psp_tx *tx_fs = fs->tx_fs; 649 + 650 + if (!tx_fs) 651 + return; 652 + 653 + mutex_destroy(&tx_fs->mutex); 654 + WARN_ON(tx_fs->refcnt); 655 + kfree(tx_fs); 656 + fs->tx_fs = NULL; 657 + } 658 + 659 + static int accel_psp_fs_init_tx(struct mlx5e_psp_fs *fs) 660 + { 661 + struct mlx5_flow_namespace *ns; 662 + struct mlx5e_psp_tx *tx_fs; 663 + 664 + ns = mlx5_get_flow_namespace(fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC); 665 + if (!ns) 666 + return -EOPNOTSUPP; 667 + 668 + tx_fs = kzalloc(sizeof(*tx_fs), GFP_KERNEL); 669 + if (!tx_fs) 670 + return -ENOMEM; 671 + 672 + mutex_init(&tx_fs->mutex); 673 + tx_fs->ns = ns; 674 + fs->tx_fs = tx_fs; 675 + return 0; 676 + } 677 + 678 + void mlx5_accel_psp_fs_cleanup_tx_tables(struct mlx5e_priv *priv) 679 + { 680 + if (!priv->psp) 681 + return; 682 + 683 + accel_psp_fs_tx_ft_put(priv->psp->fs); 684 + } 685 + 686 + int mlx5_accel_psp_fs_init_tx_tables(struct mlx5e_priv *priv) 687 + { 688 + if (!priv->psp) 689 + return 0; 690 + 691 + return accel_psp_fs_tx_ft_get(priv->psp->fs); 692 + } 693 + 694 + static void mlx5e_accel_psp_fs_cleanup(struct mlx5e_psp_fs *fs) 695 + { 696 + accel_psp_fs_cleanup_rx(fs); 697 + accel_psp_fs_cleanup_tx(fs); 698 + kfree(fs); 699 + } 700 + 701 + static struct mlx5e_psp_fs *mlx5e_accel_psp_fs_init(struct mlx5e_priv *priv) 702 + { 703 + struct mlx5e_psp_fs *fs; 704 + int err = 0; 705 + 706 + fs = kzalloc(sizeof(*fs), GFP_KERNEL); 707 + if (!fs) 708 + return ERR_PTR(-ENOMEM); 709 + 710 + fs->mdev = priv->mdev; 711 + err = accel_psp_fs_init_tx(fs); 712 + if (err) 713 + goto err_tx; 714 + 715 + fs->fs = priv->fs; 716 + err = accel_psp_fs_init_rx(fs); 717 + if (err) 718 + goto err_rx; 719 + 720 + return fs; 721 + 722 + err_rx: 723 + accel_psp_fs_cleanup_tx(fs); 724 + err_tx: 725 + kfree(fs); 726 + return ERR_PTR(err); 727 + } 728 + 729 + static int 730 + mlx5e_psp_set_config(struct psp_dev *psd, struct psp_dev_config *conf, 731 + struct netlink_ext_ack *extack) 732 + { 733 + return 0; /* TODO: this should actually do things to the device */ 734 + } 735 + 736 + static int 737 + mlx5e_psp_generate_key_spi(struct mlx5_core_dev *mdev, 738 + enum mlx5_psp_gen_spi_in_key_size keysz, 739 + unsigned int keysz_bytes, 740 + struct psp_key_parsed *key) 741 + { 742 + u32 out[MLX5_ST_SZ_DW(psp_gen_spi_out) + MLX5_ST_SZ_DW(key_spi)] = {}; 743 + u32 in[MLX5_ST_SZ_DW(psp_gen_spi_in)] = {}; 744 + void *outkey; 745 + int err; 746 + 747 + WARN_ON_ONCE(keysz_bytes > PSP_MAX_KEY); 748 + 749 + MLX5_SET(psp_gen_spi_in, in, opcode, MLX5_CMD_OP_PSP_GEN_SPI); 750 + MLX5_SET(psp_gen_spi_in, in, key_size, keysz); 751 + MLX5_SET(psp_gen_spi_in, in, num_of_spi, 1); 752 + err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 753 + if (err) 754 + return err; 755 + 756 + outkey = MLX5_ADDR_OF(psp_gen_spi_out, out, key_spi); 757 + key->spi = cpu_to_be32(MLX5_GET(key_spi, outkey, spi)); 758 + memcpy(key->key, MLX5_ADDR_OF(key_spi, outkey, key) + 32 - keysz_bytes, 759 + keysz_bytes); 760 + 761 + return 0; 762 + } 763 + 764 + static int 765 + mlx5e_psp_rx_spi_alloc(struct psp_dev *psd, u32 version, 766 + struct psp_key_parsed *assoc, 767 + struct netlink_ext_ack *extack) 768 + { 769 + struct mlx5e_priv *priv = netdev_priv(psd->main_netdev); 770 + enum mlx5_psp_gen_spi_in_key_size keysz; 771 + u8 keysz_bytes; 772 + 773 + switch (version) { 774 + case PSP_VERSION_HDR0_AES_GCM_128: 775 + keysz = MLX5_PSP_GEN_SPI_IN_KEY_SIZE_128; 776 + keysz_bytes = 16; 777 + break; 778 + case PSP_VERSION_HDR0_AES_GCM_256: 779 + keysz = MLX5_PSP_GEN_SPI_IN_KEY_SIZE_256; 780 + keysz_bytes = 32; 781 + break; 782 + default: 783 + return -EINVAL; 784 + } 785 + 786 + return mlx5e_psp_generate_key_spi(priv->mdev, keysz, keysz_bytes, assoc); 787 + } 788 + 789 + struct psp_key { 790 + u32 id; 791 + }; 792 + 793 + static int mlx5e_psp_assoc_add(struct psp_dev *psd, struct psp_assoc *pas, 794 + struct netlink_ext_ack *extack) 795 + { 796 + struct mlx5e_priv *priv = netdev_priv(psd->main_netdev); 797 + struct mlx5_core_dev *mdev = priv->mdev; 798 + struct psp_key_parsed *tx = &pas->tx; 799 + struct mlx5e_psp *psp = priv->psp; 800 + struct psp_key *nkey; 801 + int err; 802 + 803 + mdev = priv->mdev; 804 + nkey = (struct psp_key *)pas->drv_data; 805 + 806 + err = mlx5_create_encryption_key(mdev, tx->key, 807 + psp_key_size(pas->version), 808 + MLX5_ACCEL_OBJ_PSP_KEY, 809 + &nkey->id); 810 + if (err) { 811 + mlx5_core_err(mdev, "Failed to create encryption key (err = %d)\n", err); 812 + return err; 813 + } 814 + 815 + atomic_inc(&psp->tx_key_cnt); 816 + return 0; 817 + } 818 + 819 + static void mlx5e_psp_assoc_del(struct psp_dev *psd, struct psp_assoc *pas) 820 + { 821 + struct mlx5e_priv *priv = netdev_priv(psd->main_netdev); 822 + struct mlx5e_psp *psp = priv->psp; 823 + struct psp_key *nkey; 824 + 825 + nkey = (struct psp_key *)pas->drv_data; 826 + mlx5_destroy_encryption_key(priv->mdev, nkey->id); 827 + atomic_dec(&psp->tx_key_cnt); 828 + } 829 + 830 + static int mlx5e_psp_rotate_key(struct mlx5_core_dev *mdev) 831 + { 832 + u32 in[MLX5_ST_SZ_DW(psp_rotate_key_in)] = {}; 833 + u32 out[MLX5_ST_SZ_DW(psp_rotate_key_out)]; 834 + 835 + MLX5_SET(psp_rotate_key_in, in, opcode, 836 + MLX5_CMD_OP_PSP_ROTATE_KEY); 837 + 838 + return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 839 + } 840 + 841 + static int 842 + mlx5e_psp_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *exack) 843 + { 844 + struct mlx5e_priv *priv = netdev_priv(psd->main_netdev); 845 + 846 + /* no support for protecting against external rotations */ 847 + psd->generation = 0; 848 + 849 + return mlx5e_psp_rotate_key(priv->mdev); 850 + } 851 + 852 + static struct psp_dev_ops mlx5_psp_ops = { 853 + .set_config = mlx5e_psp_set_config, 854 + .rx_spi_alloc = mlx5e_psp_rx_spi_alloc, 855 + .tx_key_add = mlx5e_psp_assoc_add, 856 + .tx_key_del = mlx5e_psp_assoc_del, 857 + .key_rotate = mlx5e_psp_key_rotate, 858 + }; 859 + 860 + void mlx5e_psp_unregister(struct mlx5e_priv *priv) 861 + { 862 + if (!priv->psp || !priv->psp->psp) 863 + return; 864 + 865 + psp_dev_unregister(priv->psp->psp); 866 + } 867 + 868 + void mlx5e_psp_register(struct mlx5e_priv *priv) 869 + { 870 + /* FW Caps missing */ 871 + if (!priv->psp) 872 + return; 873 + 874 + priv->psp->caps.assoc_drv_spc = sizeof(u32); 875 + priv->psp->caps.versions = 1 << PSP_VERSION_HDR0_AES_GCM_128; 876 + if (MLX5_CAP_PSP(priv->mdev, psp_crypto_esp_aes_gcm_256_encrypt) && 877 + MLX5_CAP_PSP(priv->mdev, psp_crypto_esp_aes_gcm_256_decrypt)) 878 + priv->psp->caps.versions |= 1 << PSP_VERSION_HDR0_AES_GCM_256; 879 + 880 + priv->psp->psp = psp_dev_create(priv->netdev, &mlx5_psp_ops, 881 + &priv->psp->caps, NULL); 882 + if (IS_ERR(priv->psp->psp)) 883 + mlx5_core_err(priv->mdev, "PSP failed to register due to %pe\n", 884 + priv->psp->psp); 885 + } 886 + 887 + int mlx5e_psp_init(struct mlx5e_priv *priv) 888 + { 889 + struct mlx5_core_dev *mdev = priv->mdev; 890 + struct mlx5e_psp_fs *fs; 891 + struct mlx5e_psp *psp; 892 + int err; 893 + 894 + if (!mlx5_is_psp_device(mdev)) { 895 + mlx5_core_dbg(mdev, "PSP offload not supported\n"); 896 + return -EOPNOTSUPP; 897 + } 898 + 899 + if (!MLX5_CAP_ETH(mdev, swp)) { 900 + mlx5_core_dbg(mdev, "SWP not supported\n"); 901 + return -EOPNOTSUPP; 902 + } 903 + 904 + if (!MLX5_CAP_ETH(mdev, swp_csum)) { 905 + mlx5_core_dbg(mdev, "SWP checksum not supported\n"); 906 + return -EOPNOTSUPP; 907 + } 908 + 909 + if (!MLX5_CAP_ETH(mdev, swp_csum_l4_partial)) { 910 + mlx5_core_dbg(mdev, "SWP L4 partial checksum not supported\n"); 911 + return -EOPNOTSUPP; 912 + } 913 + 914 + if (!MLX5_CAP_ETH(mdev, swp_lso)) { 915 + mlx5_core_dbg(mdev, "PSP LSO not supported\n"); 916 + return -EOPNOTSUPP; 917 + } 918 + 919 + psp = kzalloc(sizeof(*psp), GFP_KERNEL); 920 + if (!psp) 921 + return -ENOMEM; 922 + 923 + priv->psp = psp; 924 + fs = mlx5e_accel_psp_fs_init(priv); 925 + if (IS_ERR(fs)) { 926 + err = PTR_ERR(fs); 927 + goto out_err; 928 + } 929 + 930 + psp->fs = fs; 931 + 932 + mlx5_core_dbg(priv->mdev, "PSP attached to netdevice\n"); 933 + return 0; 934 + 935 + out_err: 936 + priv->psp = NULL; 937 + kfree(psp); 938 + return err; 939 + } 940 + 941 + void mlx5e_psp_cleanup(struct mlx5e_priv *priv) 942 + { 943 + struct mlx5e_psp *psp = priv->psp; 944 + 945 + if (!psp) 946 + return; 947 + 948 + WARN_ON(atomic_read(&psp->tx_key_cnt)); 949 + mlx5e_accel_psp_fs_cleanup(psp->fs); 950 + priv->psp = NULL; 951 + kfree(psp); 952 + }
+61
drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5E_ACCEL_PSP_H__ 5 + #define __MLX5E_ACCEL_PSP_H__ 6 + #if IS_ENABLED(CONFIG_MLX5_EN_PSP) 7 + #include <net/psp/types.h> 8 + #include "en.h" 9 + 10 + struct mlx5e_psp { 11 + struct psp_dev *psp; 12 + struct psp_dev_caps caps; 13 + struct mlx5e_psp_fs *fs; 14 + atomic_t tx_key_cnt; 15 + }; 16 + 17 + static inline bool mlx5_is_psp_device(struct mlx5_core_dev *mdev) 18 + { 19 + if (!MLX5_CAP_GEN(mdev, psp)) 20 + return false; 21 + 22 + if (!MLX5_CAP_PSP(mdev, psp_crypto_offload) || 23 + !MLX5_CAP_PSP(mdev, psp_crypto_esp_aes_gcm_128_encrypt) || 24 + !MLX5_CAP_PSP(mdev, psp_crypto_esp_aes_gcm_128_decrypt)) 25 + return false; 26 + 27 + return true; 28 + } 29 + 30 + int mlx5_accel_psp_fs_init_rx_tables(struct mlx5e_priv *priv); 31 + void mlx5_accel_psp_fs_cleanup_rx_tables(struct mlx5e_priv *priv); 32 + int mlx5_accel_psp_fs_init_tx_tables(struct mlx5e_priv *priv); 33 + void mlx5_accel_psp_fs_cleanup_tx_tables(struct mlx5e_priv *priv); 34 + void mlx5e_psp_register(struct mlx5e_priv *priv); 35 + void mlx5e_psp_unregister(struct mlx5e_priv *priv); 36 + int mlx5e_psp_init(struct mlx5e_priv *priv); 37 + void mlx5e_psp_cleanup(struct mlx5e_priv *priv); 38 + #else 39 + static inline int mlx5_accel_psp_fs_init_rx_tables(struct mlx5e_priv *priv) 40 + { 41 + return 0; 42 + } 43 + 44 + static inline void mlx5_accel_psp_fs_cleanup_rx_tables(struct mlx5e_priv *priv) { } 45 + static inline int mlx5_accel_psp_fs_init_tx_tables(struct mlx5e_priv *priv) 46 + { 47 + return 0; 48 + } 49 + 50 + static inline void mlx5_accel_psp_fs_cleanup_tx_tables(struct mlx5e_priv *priv) { } 51 + static inline bool mlx5_is_psp_device(struct mlx5_core_dev *mdev) 52 + { 53 + return false; 54 + } 55 + 56 + static inline void mlx5e_psp_register(struct mlx5e_priv *priv) { } 57 + static inline void mlx5e_psp_unregister(struct mlx5e_priv *priv) { } 58 + static inline int mlx5e_psp_init(struct mlx5e_priv *priv) { return 0; } 59 + static inline void mlx5e_psp_cleanup(struct mlx5e_priv *priv) { } 60 + #endif /* CONFIG_MLX5_EN_PSP */ 61 + #endif /* __MLX5E_ACCEL_PSP_H__ */
+200
drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #include <linux/skbuff.h> 5 + #include <linux/ip.h> 6 + #include <linux/udp.h> 7 + #include <net/protocol.h> 8 + #include <net/udp.h> 9 + #include <net/ip6_checksum.h> 10 + #include <net/psp/types.h> 11 + 12 + #include "en.h" 13 + #include "psp.h" 14 + #include "en_accel/psp_rxtx.h" 15 + #include "en_accel/psp.h" 16 + 17 + enum { 18 + MLX5E_PSP_OFFLOAD_RX_SYNDROME_DECRYPTED, 19 + MLX5E_PSP_OFFLOAD_RX_SYNDROME_AUTH_FAILED, 20 + MLX5E_PSP_OFFLOAD_RX_SYNDROME_BAD_TRAILER, 21 + }; 22 + 23 + static void mlx5e_psp_set_swp(struct sk_buff *skb, 24 + struct mlx5e_accel_tx_psp_state *psp_st, 25 + struct mlx5_wqe_eth_seg *eseg) 26 + { 27 + /* Tunnel Mode: 28 + * SWP: OutL3 InL3 InL4 29 + * Pkt: MAC IP ESP IP L4 30 + * 31 + * Transport Mode: 32 + * SWP: OutL3 OutL4 33 + * Pkt: MAC IP ESP L4 34 + * 35 + * Tunnel(VXLAN TCP/UDP) over Transport Mode 36 + * SWP: OutL3 InL3 InL4 37 + * Pkt: MAC IP ESP UDP VXLAN IP L4 38 + */ 39 + u8 inner_ipproto = 0; 40 + struct ethhdr *eth; 41 + 42 + /* Shared settings */ 43 + eseg->swp_outer_l3_offset = skb_network_offset(skb) / 2; 44 + if (skb->protocol == htons(ETH_P_IPV6)) 45 + eseg->swp_flags |= MLX5_ETH_WQE_SWP_OUTER_L3_IPV6; 46 + 47 + if (skb->inner_protocol_type == ENCAP_TYPE_IPPROTO) { 48 + inner_ipproto = skb->inner_ipproto; 49 + /* Set SWP additional flags for packet of type IP|UDP|PSP|[ TCP | UDP ] */ 50 + switch (inner_ipproto) { 51 + case IPPROTO_UDP: 52 + eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L4_UDP; 53 + fallthrough; 54 + case IPPROTO_TCP: 55 + eseg->swp_inner_l4_offset = skb_inner_transport_offset(skb) / 2; 56 + break; 57 + default: 58 + break; 59 + } 60 + } else { 61 + /* IP in IP tunneling like vxlan*/ 62 + if (skb->inner_protocol_type != ENCAP_TYPE_ETHER) 63 + return; 64 + 65 + eth = (struct ethhdr *)skb_inner_mac_header(skb); 66 + switch (ntohs(eth->h_proto)) { 67 + case ETH_P_IP: 68 + inner_ipproto = ((struct iphdr *)((char *)skb->data + 69 + skb_inner_network_offset(skb)))->protocol; 70 + break; 71 + case ETH_P_IPV6: 72 + inner_ipproto = ((struct ipv6hdr *)((char *)skb->data + 73 + skb_inner_network_offset(skb)))->nexthdr; 74 + break; 75 + default: 76 + break; 77 + } 78 + 79 + /* Tunnel(VXLAN TCP/UDP) over Transport Mode PSP i.e. PSP payload is vxlan tunnel */ 80 + switch (inner_ipproto) { 81 + case IPPROTO_UDP: 82 + eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L4_UDP; 83 + fallthrough; 84 + case IPPROTO_TCP: 85 + eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2; 86 + eseg->swp_inner_l4_offset = 87 + (skb->csum_start + skb->head - skb->data) / 2; 88 + if (skb->protocol == htons(ETH_P_IPV6)) 89 + eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6; 90 + break; 91 + default: 92 + break; 93 + } 94 + 95 + psp_st->inner_ipproto = inner_ipproto; 96 + } 97 + } 98 + 99 + static bool mlx5e_psp_set_state(struct mlx5e_priv *priv, 100 + struct sk_buff *skb, 101 + struct mlx5e_accel_tx_psp_state *psp_st) 102 + { 103 + struct psp_assoc *pas; 104 + bool ret = false; 105 + 106 + rcu_read_lock(); 107 + pas = psp_skb_get_assoc_rcu(skb); 108 + if (!pas) 109 + goto out; 110 + 111 + ret = true; 112 + psp_st->tailen = PSP_TRL_SIZE; 113 + psp_st->spi = pas->tx.spi; 114 + psp_st->ver = pas->version; 115 + psp_st->keyid = *(u32 *)pas->drv_data; 116 + 117 + out: 118 + rcu_read_unlock(); 119 + return ret; 120 + } 121 + 122 + bool mlx5e_psp_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, 123 + struct mlx5_cqe64 *cqe) 124 + { 125 + u32 psp_meta_data = be32_to_cpu(cqe->ft_metadata); 126 + struct mlx5e_priv *priv = netdev_priv(netdev); 127 + u16 dev_id = priv->psp->psp->id; 128 + bool strip_icv = true; 129 + u8 generation = 0; 130 + 131 + /* TBD: report errors as SW counters to ethtool, any further handling ? */ 132 + if (MLX5_PSP_METADATA_SYNDROME(psp_meta_data) != MLX5E_PSP_OFFLOAD_RX_SYNDROME_DECRYPTED) 133 + goto drop; 134 + 135 + if (psp_dev_rcv(skb, dev_id, generation, strip_icv)) 136 + goto drop; 137 + 138 + skb->decrypted = 1; 139 + return false; 140 + 141 + drop: 142 + kfree_skb(skb); 143 + return true; 144 + } 145 + 146 + void mlx5e_psp_tx_build_eseg(struct mlx5e_priv *priv, struct sk_buff *skb, 147 + struct mlx5e_accel_tx_psp_state *psp_st, 148 + struct mlx5_wqe_eth_seg *eseg) 149 + { 150 + if (!mlx5_is_psp_device(priv->mdev)) 151 + return; 152 + 153 + if (unlikely(skb->protocol != htons(ETH_P_IP) && 154 + skb->protocol != htons(ETH_P_IPV6))) 155 + return; 156 + 157 + mlx5e_psp_set_swp(skb, psp_st, eseg); 158 + /* Special WA for PSP LSO in ConnectX7 */ 159 + eseg->swp_outer_l3_offset = 0; 160 + eseg->swp_inner_l3_offset = 0; 161 + 162 + eseg->flow_table_metadata |= cpu_to_be32(psp_st->keyid); 163 + eseg->trailer |= cpu_to_be32(MLX5_ETH_WQE_INSERT_TRAILER) | 164 + cpu_to_be32(MLX5_ETH_WQE_TRAILER_HDR_OUTER_L4_ASSOC); 165 + } 166 + 167 + void mlx5e_psp_handle_tx_wqe(struct mlx5e_tx_wqe *wqe, 168 + struct mlx5e_accel_tx_psp_state *psp_st, 169 + struct mlx5_wqe_inline_seg *inlseg) 170 + { 171 + inlseg->byte_count = cpu_to_be32(psp_st->tailen | MLX5_INLINE_SEG); 172 + } 173 + 174 + bool mlx5e_psp_handle_tx_skb(struct net_device *netdev, 175 + struct sk_buff *skb, 176 + struct mlx5e_accel_tx_psp_state *psp_st) 177 + { 178 + struct mlx5e_priv *priv = netdev_priv(netdev); 179 + struct net *net = sock_net(skb->sk); 180 + const struct ipv6hdr *ip6; 181 + struct tcphdr *th; 182 + 183 + if (!mlx5e_psp_set_state(priv, skb, psp_st)) 184 + return true; 185 + 186 + /* psp_encap of the packet */ 187 + if (!psp_dev_encapsulate(net, skb, psp_st->spi, psp_st->ver, 0)) { 188 + kfree_skb_reason(skb, SKB_DROP_REASON_PSP_OUTPUT); 189 + return false; 190 + } 191 + if (skb_is_gso(skb)) { 192 + ip6 = ipv6_hdr(skb); 193 + th = inner_tcp_hdr(skb); 194 + 195 + th->check = ~tcp_v6_check(skb_shinfo(skb)->gso_size + inner_tcp_hdrlen(skb), &ip6->saddr, 196 + &ip6->daddr, 0); 197 + } 198 + 199 + return true; 200 + }
+121
drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5E_PSP_RXTX_H__ 5 + #define __MLX5E_PSP_RXTX_H__ 6 + 7 + #include <linux/skbuff.h> 8 + #include <net/xfrm.h> 9 + #include <net/psp.h> 10 + #include "en.h" 11 + #include "en/txrx.h" 12 + 13 + /* Bit30: PSP marker, Bit29-23: PSP syndrome, Bit22-0: PSP obj id */ 14 + #define MLX5_PSP_METADATA_MARKER(metadata) ((((metadata) >> 30) & 0x3) == 0x3) 15 + #define MLX5_PSP_METADATA_SYNDROME(metadata) (((metadata) >> 23) & GENMASK(6, 0)) 16 + #define MLX5_PSP_METADATA_HANDLE(metadata) ((metadata) & GENMASK(22, 0)) 17 + 18 + struct mlx5e_accel_tx_psp_state { 19 + u32 tailen; 20 + u32 keyid; 21 + __be32 spi; 22 + u8 inner_ipproto; 23 + u8 ver; 24 + }; 25 + 26 + #ifdef CONFIG_MLX5_EN_PSP 27 + static inline bool mlx5e_psp_is_offload_state(struct mlx5e_accel_tx_psp_state *psp_state) 28 + { 29 + return (psp_state->tailen != 0); 30 + } 31 + 32 + static inline bool mlx5e_psp_is_offload(struct sk_buff *skb, struct net_device *netdev) 33 + { 34 + bool ret; 35 + 36 + rcu_read_lock(); 37 + ret = !!psp_skb_get_assoc_rcu(skb); 38 + rcu_read_unlock(); 39 + return ret; 40 + } 41 + 42 + bool mlx5e_psp_handle_tx_skb(struct net_device *netdev, 43 + struct sk_buff *skb, 44 + struct mlx5e_accel_tx_psp_state *psp_st); 45 + 46 + void mlx5e_psp_tx_build_eseg(struct mlx5e_priv *priv, struct sk_buff *skb, 47 + struct mlx5e_accel_tx_psp_state *psp_st, 48 + struct mlx5_wqe_eth_seg *eseg); 49 + 50 + void mlx5e_psp_handle_tx_wqe(struct mlx5e_tx_wqe *wqe, 51 + struct mlx5e_accel_tx_psp_state *psp_st, 52 + struct mlx5_wqe_inline_seg *inlseg); 53 + 54 + static inline bool mlx5e_psp_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, 55 + struct mlx5e_accel_tx_psp_state *psp_st, 56 + struct mlx5_wqe_eth_seg *eseg) 57 + { 58 + u8 inner_ipproto; 59 + 60 + if (!mlx5e_psp_is_offload_state(psp_st)) 61 + return false; 62 + 63 + inner_ipproto = psp_st->inner_ipproto; 64 + eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM; 65 + if (inner_ipproto) { 66 + eseg->cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM; 67 + if (inner_ipproto == IPPROTO_TCP || inner_ipproto == IPPROTO_UDP) 68 + eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM; 69 + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) 70 + sq->stats->csum_partial_inner++; 71 + } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { 72 + eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM; 73 + sq->stats->csum_partial_inner++; 74 + } 75 + 76 + return true; 77 + } 78 + 79 + static inline unsigned int mlx5e_psp_tx_ids_len(struct mlx5e_accel_tx_psp_state *psp_st) 80 + { 81 + return psp_st->tailen; 82 + } 83 + 84 + static inline bool mlx5e_psp_is_rx_flow(struct mlx5_cqe64 *cqe) 85 + { 86 + return MLX5_PSP_METADATA_MARKER(be32_to_cpu(cqe->ft_metadata)); 87 + } 88 + 89 + bool mlx5e_psp_offload_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb, 90 + struct mlx5_cqe64 *cqe); 91 + #else 92 + static inline bool mlx5e_psp_is_offload_state(struct mlx5e_accel_tx_psp_state *psp_state) 93 + { 94 + return false; 95 + } 96 + 97 + static inline bool mlx5e_psp_is_offload(struct sk_buff *skb, struct net_device *netdev) 98 + { 99 + return false; 100 + } 101 + 102 + static inline bool mlx5e_psp_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, 103 + struct mlx5e_accel_tx_psp_state *psp_st, 104 + struct mlx5_wqe_eth_seg *eseg) 105 + { 106 + return false; 107 + } 108 + 109 + static inline bool mlx5e_psp_is_rx_flow(struct mlx5_cqe64 *cqe) 110 + { 111 + return false; 112 + } 113 + 114 + static inline bool mlx5e_psp_offload_handle_rx_skb(struct net_device *netdev, 115 + struct sk_buff *skb, 116 + struct mlx5_cqe64 *cqe) 117 + { 118 + return false; 119 + } 120 + #endif /* CONFIG_MLX5_EN_PSP */ 121 + #endif /* __MLX5E_PSP_RXTX_H__ */
+9
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 53 53 #include "en_tc.h" 54 54 #include "en_rep.h" 55 55 #include "en_accel/ipsec.h" 56 + #include "en_accel/psp.h" 56 57 #include "en_accel/macsec.h" 57 58 #include "en_accel/en_accel.h" 58 59 #include "en_accel/ktls.h" ··· 5920 5919 } 5921 5920 priv->fs = fs; 5922 5921 5922 + err = mlx5e_psp_init(priv); 5923 + if (err) 5924 + mlx5_core_err(mdev, "PSP initialization failed, %d\n", err); 5925 + 5923 5926 err = mlx5e_ktls_init(priv); 5924 5927 if (err) 5925 5928 mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); ··· 5936 5931 if (take_rtnl) 5937 5932 rtnl_lock(); 5938 5933 5934 + mlx5e_psp_register(priv); 5939 5935 /* update XDP supported features */ 5940 5936 mlx5e_set_xdp_feature(netdev); 5941 5937 ··· 5949 5943 static void mlx5e_nic_cleanup(struct mlx5e_priv *priv) 5950 5944 { 5951 5945 mlx5e_health_destroy_reporters(priv); 5946 + mlx5e_psp_unregister(priv); 5952 5947 mlx5e_ktls_cleanup(priv); 5948 + mlx5e_psp_cleanup(priv); 5953 5949 mlx5e_fs_cleanup(priv->fs); 5954 5950 debugfs_remove_recursive(priv->dfs_root); 5955 5951 priv->fs = NULL; ··· 6799 6791 * is already unregistered before changing to NIC profile. 6800 6792 */ 6801 6793 if (priv->netdev->reg_state == NETREG_REGISTERED) { 6794 + mlx5e_psp_unregister(priv); 6802 6795 unregister_netdev(priv->netdev); 6803 6796 _mlx5e_suspend(adev, false); 6804 6797 } else {
+37 -12
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
··· 51 51 #include "ipoib/ipoib.h" 52 52 #include "en_accel/ipsec.h" 53 53 #include "en_accel/macsec.h" 54 + #include "en_accel/psp_rxtx.h" 54 55 #include "en_accel/ipsec_rxtx.h" 55 56 #include "en_accel/ktls_txrx.h" 56 57 #include "en/xdp.h" ··· 1522 1521 skb->ip_summed = CHECKSUM_COMPLETE; 1523 1522 skb->csum = csum_unfold((__force __sum16)cqe->check_sum); 1524 1523 1524 + if (unlikely(mlx5e_psp_is_rx_flow(cqe))) { 1525 + /* TBD: PSP csum complete corrections for now chose csum_unnecessary path */ 1526 + goto csum_unnecessary; 1527 + } 1528 + 1525 1529 if (test_bit(MLX5E_RQ_STATE_CSUM_FULL, &rq->state)) 1526 1530 return; /* CQE csum covers all received bytes */ 1527 1531 ··· 1555 1549 1556 1550 #define MLX5E_CE_BIT_MASK 0x80 1557 1551 1558 - static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, 1552 + static inline bool mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, 1559 1553 u32 cqe_bcnt, 1560 1554 struct mlx5e_rq *rq, 1561 1555 struct sk_buff *skb) ··· 1568 1562 1569 1563 if (unlikely(get_cqe_tls_offload(cqe))) 1570 1564 mlx5e_ktls_handle_rx_skb(rq, skb, cqe, &cqe_bcnt); 1565 + 1566 + if (unlikely(mlx5e_psp_is_rx_flow(cqe))) { 1567 + if (mlx5e_psp_offload_handle_rx_skb(netdev, skb, cqe)) 1568 + return true; 1569 + } 1571 1570 1572 1571 if (unlikely(mlx5_ipsec_is_rx_flow(cqe))) 1573 1572 mlx5e_ipsec_offload_handle_rx_skb(netdev, skb, ··· 1619 1608 1620 1609 if (unlikely(mlx5e_skb_is_multicast(skb))) 1621 1610 stats->mcast_packets++; 1611 + 1612 + return false; 1622 1613 } 1623 1614 1624 - static void mlx5e_shampo_complete_rx_cqe(struct mlx5e_rq *rq, 1615 + static bool mlx5e_shampo_complete_rx_cqe(struct mlx5e_rq *rq, 1625 1616 struct mlx5_cqe64 *cqe, 1626 1617 u32 cqe_bcnt, 1627 1618 struct sk_buff *skb) ··· 1633 1620 stats->packets++; 1634 1621 stats->bytes += cqe_bcnt; 1635 1622 if (NAPI_GRO_CB(skb)->count != 1) 1636 - return; 1637 - mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb); 1623 + return false; 1624 + 1625 + if (mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb)) 1626 + return true; 1627 + 1638 1628 skb_reset_network_header(skb); 1639 1629 if (!skb_flow_dissect_flow_keys(skb, &rq->hw_gro_data->fk, 0)) { 1640 1630 napi_gro_receive(rq->cq.napi, skb); 1641 1631 rq->hw_gro_data->skb = NULL; 1642 1632 } 1633 + return false; 1643 1634 } 1644 1635 1645 - static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq, 1636 + static inline bool mlx5e_complete_rx_cqe(struct mlx5e_rq *rq, 1646 1637 struct mlx5_cqe64 *cqe, 1647 1638 u32 cqe_bcnt, 1648 1639 struct sk_buff *skb) ··· 1655 1638 1656 1639 stats->packets++; 1657 1640 stats->bytes += cqe_bcnt; 1658 - mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb); 1641 + return mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb); 1659 1642 } 1660 1643 1661 1644 static inline ··· 1871 1854 goto wq_cyc_pop; 1872 1855 } 1873 1856 1874 - mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); 1857 + if (mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb)) 1858 + goto wq_cyc_pop; 1875 1859 1876 1860 if (mlx5e_cqe_regb_chain(cqe)) 1877 1861 if (!mlx5e_tc_update_skb_nic(cqe, skb)) { ··· 1919 1901 goto wq_cyc_pop; 1920 1902 } 1921 1903 1922 - mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); 1904 + if (mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb)) 1905 + goto wq_cyc_pop; 1923 1906 1924 1907 if (rep->vlan && skb_vlan_tag_present(skb)) 1925 1908 skb_vlan_pop(skb); ··· 1969 1950 if (!skb) 1970 1951 goto mpwrq_cqe_out; 1971 1952 1972 - mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); 1953 + if (mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb)) 1954 + goto mpwrq_cqe_out; 1973 1955 1974 1956 mlx5e_rep_tc_receive(cqe, rq, skb); 1975 1957 ··· 2407 2387 stats->hds_nosplit_bytes += data_bcnt; 2408 2388 } 2409 2389 2410 - mlx5e_shampo_complete_rx_cqe(rq, cqe, cqe_bcnt, *skb); 2390 + if (mlx5e_shampo_complete_rx_cqe(rq, cqe, cqe_bcnt, *skb)) { 2391 + *skb = NULL; 2392 + goto free_hd_entry; 2393 + } 2411 2394 if (flush && rq->hw_gro_data->skb) 2412 2395 mlx5e_shampo_flush_skb(rq, cqe, match); 2413 2396 free_hd_entry: ··· 2468 2445 if (!skb) 2469 2446 goto mpwrq_cqe_out; 2470 2447 2471 - mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); 2448 + if (mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb)) 2449 + goto mpwrq_cqe_out; 2472 2450 2473 2451 if (mlx5e_cqe_regb_chain(cqe)) 2474 2452 if (!mlx5e_tc_update_skb_nic(cqe, skb)) { ··· 2802 2778 if (!skb) 2803 2779 goto wq_cyc_pop; 2804 2780 2805 - mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); 2781 + if (mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb)) 2782 + goto wq_cyc_pop; 2806 2783 skb_push(skb, ETH_HLEN); 2807 2784 2808 2785 mlx5_devlink_trap_report(rq->mdev, trap_id, skb,
+8 -2
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
··· 39 39 #include "ipoib/ipoib.h" 40 40 #include "en_accel/en_accel.h" 41 41 #include "en_accel/ipsec_rxtx.h" 42 + #include "en_accel/psp_rxtx.h" 42 43 #include "en_accel/macsec.h" 43 44 #include "en/ptp.h" 44 45 #include <net/ipv6.h> ··· 121 120 struct mlx5e_accel_tx_state *accel, 122 121 struct mlx5_wqe_eth_seg *eseg) 123 122 { 123 + #ifdef CONFIG_MLX5_EN_PSP 124 + if (unlikely(mlx5e_psp_txwqe_build_eseg_csum(sq, skb, &accel->psp_st, eseg))) 125 + return; 126 + #endif 127 + 124 128 if (unlikely(mlx5e_ipsec_txwqe_build_eseg_csum(sq, skb, eseg))) 125 129 return; 126 130 ··· 303 297 stats->packets++; 304 298 } 305 299 306 - attr->insz = mlx5e_accel_tx_ids_len(sq, accel); 300 + attr->insz = mlx5e_accel_tx_ids_len(sq, skb, accel); 307 301 stats->bytes += attr->num_bytes; 308 302 } 309 303 ··· 667 661 struct sk_buff *skb, struct mlx5e_accel_tx_state *accel, 668 662 struct mlx5_wqe_eth_seg *eseg, u16 ihs) 669 663 { 670 - mlx5e_accel_tx_eseg(priv, skb, eseg, ihs); 664 + mlx5e_accel_tx_eseg(priv, skb, accel, eseg, ihs); 671 665 mlx5e_txwqe_build_eseg_csum(sq, skb, accel, eseg); 672 666 if (unlikely(sq->ptpsq)) 673 667 mlx5e_cqe_ts_id_eseg(sq->ptpsq, skb, eseg);
+1
drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.h
··· 8 8 MLX5_ACCEL_OBJ_TLS_KEY = MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_PURPOSE_TLS, 9 9 MLX5_ACCEL_OBJ_IPSEC_KEY = MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_PURPOSE_IPSEC, 10 10 MLX5_ACCEL_OBJ_MACSEC_KEY = MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_PURPOSE_MACSEC, 11 + MLX5_ACCEL_OBJ_PSP_KEY = MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_PURPOSE_PSP, 11 12 MLX5_ACCEL_OBJ_TYPE_KEY_NUM, 12 13 }; 13 14
+4
include/linux/netdevice.h
··· 1906 1906 * device struct 1907 1907 * @mpls_ptr: mpls_dev struct pointer 1908 1908 * @mctp_ptr: MCTP specific data 1909 + * @psp_dev: PSP crypto device registered for this netdev 1909 1910 * 1910 1911 * @dev_addr: Hw address (before bcast, 1911 1912 * because most packets are unicast) ··· 2310 2309 #endif 2311 2310 #if IS_ENABLED(CONFIG_MCTP) 2312 2311 struct mctp_dev __rcu *mctp_ptr; 2312 + #endif 2313 + #if IS_ENABLED(CONFIG_INET_PSP) 2314 + struct psp_dev __rcu *psp_dev; 2313 2315 #endif 2314 2316 2315 2317 /*
+3
include/linux/skbuff.h
··· 4902 4902 #if IS_ENABLED(CONFIG_MCTP_FLOWS) 4903 4903 SKB_EXT_MCTP, 4904 4904 #endif 4905 + #if IS_ENABLED(CONFIG_INET_PSP) 4906 + SKB_EXT_PSP, 4907 + #endif 4905 4908 SKB_EXT_NUM, /* must be last */ 4906 4909 }; 4907 4910
+6
include/net/dropreason-core.h
··· 127 127 FN(CANXL_RX_INVALID_FRAME) \ 128 128 FN(PFMEMALLOC) \ 129 129 FN(DUALPI2_STEP_DROP) \ 130 + FN(PSP_INPUT) \ 131 + FN(PSP_OUTPUT) \ 130 132 FNe(MAX) 131 133 132 134 /** ··· 612 610 * threshold of DualPI2 qdisc. 613 611 */ 614 612 SKB_DROP_REASON_DUALPI2_STEP_DROP, 613 + /** @SKB_DROP_REASON_PSP_INPUT: PSP input checks failed */ 614 + SKB_DROP_REASON_PSP_INPUT, 615 + /** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */ 616 + SKB_DROP_REASON_PSP_OUTPUT, 615 617 /** 616 618 * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which 617 619 * shouldn't be used as a real 'reason' - only for tracing code gen
+8
include/net/inet_timewait_sock.h
··· 81 81 struct timer_list tw_timer; 82 82 struct inet_bind_bucket *tw_tb; 83 83 struct inet_bind2_bucket *tw_tb2; 84 + #if IS_ENABLED(CONFIG_INET_PSP) 85 + struct psp_assoc __rcu *psp_assoc; 86 + #endif 87 + #ifdef CONFIG_SOCK_VALIDATE_XMIT 88 + struct sk_buff* (*tw_validate_xmit_skb)(struct sock *sk, 89 + struct net_device *dev, 90 + struct sk_buff *skb); 91 + #endif 84 92 }; 85 93 #define tw_tclass tw_tos 86 94
+12
include/net/psp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __NET_PSP_ALL_H 4 + #define __NET_PSP_ALL_H 5 + 6 + #include <uapi/linux/psp.h> 7 + #include <net/psp/functions.h> 8 + #include <net/psp/types.h> 9 + 10 + /* Do not add any code here. Put it in the sub-headers instead. */ 11 + 12 + #endif /* __NET_PSP_ALL_H */
+210
include/net/psp/functions.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __NET_PSP_HELPERS_H 4 + #define __NET_PSP_HELPERS_H 5 + 6 + #include <linux/skbuff.h> 7 + #include <linux/rcupdate.h> 8 + #include <linux/udp.h> 9 + #include <net/sock.h> 10 + #include <net/tcp.h> 11 + #include <net/psp/types.h> 12 + 13 + struct inet_timewait_sock; 14 + 15 + /* Driver-facing API */ 16 + struct psp_dev * 17 + psp_dev_create(struct net_device *netdev, struct psp_dev_ops *psd_ops, 18 + struct psp_dev_caps *psd_caps, void *priv_ptr); 19 + void psp_dev_unregister(struct psp_dev *psd); 20 + bool psp_dev_encapsulate(struct net *net, struct sk_buff *skb, __be32 spi, 21 + u8 ver, __be16 sport); 22 + int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv); 23 + 24 + /* Kernel-facing API */ 25 + void psp_assoc_put(struct psp_assoc *pas); 26 + 27 + static inline void *psp_assoc_drv_data(struct psp_assoc *pas) 28 + { 29 + return pas->drv_data; 30 + } 31 + 32 + #if IS_ENABLED(CONFIG_INET_PSP) 33 + unsigned int psp_key_size(u32 version); 34 + void psp_sk_assoc_free(struct sock *sk); 35 + void psp_twsk_init(struct inet_timewait_sock *tw, const struct sock *sk); 36 + void psp_twsk_assoc_free(struct inet_timewait_sock *tw); 37 + void psp_reply_set_decrypted(struct sk_buff *skb); 38 + 39 + static inline struct psp_assoc *psp_sk_assoc(const struct sock *sk) 40 + { 41 + return rcu_dereference_check(sk->psp_assoc, lockdep_sock_is_held(sk)); 42 + } 43 + 44 + static inline void 45 + psp_enqueue_set_decrypted(struct sock *sk, struct sk_buff *skb) 46 + { 47 + struct psp_assoc *pas; 48 + 49 + pas = psp_sk_assoc(sk); 50 + if (pas && pas->tx.spi) 51 + skb->decrypted = 1; 52 + } 53 + 54 + static inline unsigned long 55 + __psp_skb_coalesce_diff(const struct sk_buff *one, const struct sk_buff *two, 56 + unsigned long diffs) 57 + { 58 + struct psp_skb_ext *a, *b; 59 + 60 + a = skb_ext_find(one, SKB_EXT_PSP); 61 + b = skb_ext_find(two, SKB_EXT_PSP); 62 + 63 + diffs |= (!!a) ^ (!!b); 64 + if (!diffs && unlikely(a)) 65 + diffs |= memcmp(a, b, sizeof(*a)); 66 + return diffs; 67 + } 68 + 69 + static inline bool 70 + psp_is_allowed_nondata(struct sk_buff *skb, struct psp_assoc *pas) 71 + { 72 + bool fin = !!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN); 73 + u32 end_seq = TCP_SKB_CB(skb)->end_seq; 74 + u32 seq = TCP_SKB_CB(skb)->seq; 75 + bool pure_fin; 76 + 77 + pure_fin = fin && end_seq - seq == 1; 78 + 79 + return seq == end_seq || (pure_fin && seq == pas->upgrade_seq); 80 + } 81 + 82 + static inline bool 83 + psp_pse_matches_pas(struct psp_skb_ext *pse, struct psp_assoc *pas) 84 + { 85 + return pse && pas->rx.spi == pse->spi && 86 + pas->generation == pse->generation && 87 + pas->version == pse->version && 88 + pas->dev_id == pse->dev_id; 89 + } 90 + 91 + static inline enum skb_drop_reason 92 + __psp_sk_rx_policy_check(struct sk_buff *skb, struct psp_assoc *pas) 93 + { 94 + struct psp_skb_ext *pse = skb_ext_find(skb, SKB_EXT_PSP); 95 + 96 + if (!pas) 97 + return pse ? SKB_DROP_REASON_PSP_INPUT : 0; 98 + 99 + if (likely(psp_pse_matches_pas(pse, pas))) { 100 + if (unlikely(!pas->peer_tx)) 101 + pas->peer_tx = 1; 102 + 103 + return 0; 104 + } 105 + 106 + if (!pse) { 107 + if (!pas->tx.spi || 108 + (!pas->peer_tx && psp_is_allowed_nondata(skb, pas))) 109 + return 0; 110 + } 111 + 112 + return SKB_DROP_REASON_PSP_INPUT; 113 + } 114 + 115 + static inline enum skb_drop_reason 116 + psp_sk_rx_policy_check(struct sock *sk, struct sk_buff *skb) 117 + { 118 + return __psp_sk_rx_policy_check(skb, psp_sk_assoc(sk)); 119 + } 120 + 121 + static inline enum skb_drop_reason 122 + psp_twsk_rx_policy_check(struct inet_timewait_sock *tw, struct sk_buff *skb) 123 + { 124 + return __psp_sk_rx_policy_check(skb, rcu_dereference(tw->psp_assoc)); 125 + } 126 + 127 + static inline struct psp_assoc *psp_sk_get_assoc_rcu(struct sock *sk) 128 + { 129 + struct inet_timewait_sock *tw; 130 + struct psp_assoc *pas; 131 + int state; 132 + 133 + state = 1 << READ_ONCE(sk->sk_state); 134 + if (!sk_is_inet(sk) || state & TCPF_NEW_SYN_RECV) 135 + return NULL; 136 + 137 + tw = inet_twsk(sk); 138 + pas = state & TCPF_TIME_WAIT ? rcu_dereference(tw->psp_assoc) : 139 + rcu_dereference(sk->psp_assoc); 140 + return pas; 141 + } 142 + 143 + static inline struct psp_assoc *psp_skb_get_assoc_rcu(struct sk_buff *skb) 144 + { 145 + if (!skb->decrypted || !skb->sk) 146 + return NULL; 147 + 148 + return psp_sk_get_assoc_rcu(skb->sk); 149 + } 150 + 151 + static inline unsigned int psp_sk_overhead(const struct sock *sk) 152 + { 153 + int psp_encap = sizeof(struct udphdr) + PSP_HDR_SIZE + PSP_TRL_SIZE; 154 + bool has_psp = rcu_access_pointer(sk->psp_assoc); 155 + 156 + return has_psp ? psp_encap : 0; 157 + } 158 + #else 159 + static inline void psp_sk_assoc_free(struct sock *sk) { } 160 + static inline void 161 + psp_twsk_init(struct inet_timewait_sock *tw, const struct sock *sk) { } 162 + static inline void psp_twsk_assoc_free(struct inet_timewait_sock *tw) { } 163 + static inline void 164 + psp_reply_set_decrypted(struct sk_buff *skb) { } 165 + 166 + static inline struct psp_assoc *psp_sk_assoc(const struct sock *sk) 167 + { 168 + return NULL; 169 + } 170 + 171 + static inline void 172 + psp_enqueue_set_decrypted(struct sock *sk, struct sk_buff *skb) { } 173 + 174 + static inline unsigned long 175 + __psp_skb_coalesce_diff(const struct sk_buff *one, const struct sk_buff *two, 176 + unsigned long diffs) 177 + { 178 + return diffs; 179 + } 180 + 181 + static inline enum skb_drop_reason 182 + psp_sk_rx_policy_check(struct sock *sk, struct sk_buff *skb) 183 + { 184 + return 0; 185 + } 186 + 187 + static inline enum skb_drop_reason 188 + psp_twsk_rx_policy_check(struct inet_timewait_sock *tw, struct sk_buff *skb) 189 + { 190 + return 0; 191 + } 192 + 193 + static inline struct psp_assoc *psp_skb_get_assoc_rcu(struct sk_buff *skb) 194 + { 195 + return NULL; 196 + } 197 + 198 + static inline unsigned int psp_sk_overhead(const struct sock *sk) 199 + { 200 + return 0; 201 + } 202 + #endif 203 + 204 + static inline unsigned long 205 + psp_skb_coalesce_diff(const struct sk_buff *one, const struct sk_buff *two) 206 + { 207 + return __psp_skb_coalesce_diff(one, two, 0); 208 + } 209 + 210 + #endif /* __NET_PSP_HELPERS_H */
+184
include/net/psp/types.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __NET_PSP_H 4 + #define __NET_PSP_H 5 + 6 + #include <linux/mutex.h> 7 + #include <linux/refcount.h> 8 + 9 + struct netlink_ext_ack; 10 + 11 + #define PSP_DEFAULT_UDP_PORT 1000 12 + 13 + struct psphdr { 14 + u8 nexthdr; 15 + u8 hdrlen; 16 + u8 crypt_offset; 17 + u8 verfl; 18 + __be32 spi; 19 + __be64 iv; 20 + __be64 vc[]; /* optional */ 21 + }; 22 + 23 + #define PSP_ENCAP_HLEN (sizeof(struct udphdr) + sizeof(struct psphdr)) 24 + 25 + #define PSP_SPI_KEY_ID GENMASK(30, 0) 26 + #define PSP_SPI_KEY_PHASE BIT(31) 27 + 28 + #define PSPHDR_CRYPT_OFFSET GENMASK(5, 0) 29 + 30 + #define PSPHDR_VERFL_SAMPLE BIT(7) 31 + #define PSPHDR_VERFL_DROP BIT(6) 32 + #define PSPHDR_VERFL_VERSION GENMASK(5, 2) 33 + #define PSPHDR_VERFL_VIRT BIT(1) 34 + #define PSPHDR_VERFL_ONE BIT(0) 35 + 36 + #define PSP_HDRLEN_NOOPT ((sizeof(struct psphdr) - 8) / 8) 37 + 38 + /** 39 + * struct psp_dev_config - PSP device configuration 40 + * @versions: PSP versions enabled on the device 41 + */ 42 + struct psp_dev_config { 43 + u32 versions; 44 + }; 45 + 46 + /** 47 + * struct psp_dev - PSP device struct 48 + * @main_netdev: original netdevice of this PSP device 49 + * @ops: driver callbacks 50 + * @caps: device capabilities 51 + * @drv_priv: driver priv pointer 52 + * @lock: instance lock, protects all fields 53 + * @refcnt: reference count for the instance 54 + * @id: instance id 55 + * @generation: current generation of the device key 56 + * @config: current device configuration 57 + * @active_assocs: list of registered associations 58 + * @prev_assocs: associations which use old (but still usable) 59 + * device key 60 + * @stale_assocs: associations which use a rotated out key 61 + * 62 + * @rcu: RCU head for freeing the structure 63 + */ 64 + struct psp_dev { 65 + struct net_device *main_netdev; 66 + 67 + struct psp_dev_ops *ops; 68 + struct psp_dev_caps *caps; 69 + void *drv_priv; 70 + 71 + struct mutex lock; 72 + refcount_t refcnt; 73 + 74 + u32 id; 75 + 76 + u8 generation; 77 + 78 + struct psp_dev_config config; 79 + 80 + struct list_head active_assocs; 81 + struct list_head prev_assocs; 82 + struct list_head stale_assocs; 83 + 84 + struct rcu_head rcu; 85 + }; 86 + 87 + #define PSP_GEN_VALID_MASK 0x7f 88 + 89 + /** 90 + * struct psp_dev_caps - PSP device capabilities 91 + */ 92 + struct psp_dev_caps { 93 + /** 94 + * @versions: mask of supported PSP versions 95 + * Set this field to 0 to indicate PSP is not supported at all. 96 + */ 97 + u32 versions; 98 + 99 + /** 100 + * @assoc_drv_spc: size of driver-specific state in Tx assoc 101 + * Determines the size of struct psp_assoc::drv_spc 102 + */ 103 + u32 assoc_drv_spc; 104 + }; 105 + 106 + #define PSP_MAX_KEY 32 107 + 108 + #define PSP_HDR_SIZE 16 /* We don't support optional fields, yet */ 109 + #define PSP_TRL_SIZE 16 /* AES-GCM/GMAC trailer size */ 110 + 111 + struct psp_skb_ext { 112 + __be32 spi; 113 + u16 dev_id; 114 + u8 generation; 115 + u8 version; 116 + }; 117 + 118 + struct psp_key_parsed { 119 + __be32 spi; 120 + u8 key[PSP_MAX_KEY]; 121 + }; 122 + 123 + struct psp_assoc { 124 + struct psp_dev *psd; 125 + 126 + u16 dev_id; 127 + u8 generation; 128 + u8 version; 129 + u8 peer_tx; 130 + 131 + u32 upgrade_seq; 132 + 133 + struct psp_key_parsed tx; 134 + struct psp_key_parsed rx; 135 + 136 + refcount_t refcnt; 137 + struct rcu_head rcu; 138 + struct work_struct work; 139 + struct list_head assocs_list; 140 + 141 + u8 drv_data[] __aligned(8); 142 + }; 143 + 144 + /** 145 + * struct psp_dev_ops - netdev driver facing PSP callbacks 146 + */ 147 + struct psp_dev_ops { 148 + /** 149 + * @set_config: set configuration of a PSP device 150 + * Driver can inspect @psd->config for the previous configuration. 151 + * Core will update @psd->config with @config on success. 152 + */ 153 + int (*set_config)(struct psp_dev *psd, struct psp_dev_config *conf, 154 + struct netlink_ext_ack *extack); 155 + 156 + /** 157 + * @key_rotate: rotate the device key 158 + */ 159 + int (*key_rotate)(struct psp_dev *psd, struct netlink_ext_ack *extack); 160 + 161 + /** 162 + * @rx_spi_alloc: allocate an Rx SPI+key pair 163 + * Allocate an Rx SPI and resulting derived key. 164 + * This key should remain valid until key rotation. 165 + */ 166 + int (*rx_spi_alloc)(struct psp_dev *psd, u32 version, 167 + struct psp_key_parsed *assoc, 168 + struct netlink_ext_ack *extack); 169 + 170 + /** 171 + * @tx_key_add: add a Tx key to the device 172 + * Install an association in the device. Core will allocate space 173 + * for the driver to use at drv_data. 174 + */ 175 + int (*tx_key_add)(struct psp_dev *psd, struct psp_assoc *pas, 176 + struct netlink_ext_ack *extack); 177 + /** 178 + * @tx_key_del: remove a Tx key from the device 179 + * Remove an association from the device. 180 + */ 181 + void (*tx_key_del)(struct psp_dev *psd, struct psp_assoc *pas); 182 + }; 183 + 184 + #endif /* __NET_PSP_H */
+4 -22
include/net/sock.h
··· 249 249 * @sk_dst_cache: destination cache 250 250 * @sk_dst_pending_confirm: need to confirm neighbour 251 251 * @sk_policy: flow policy 252 + * @psp_assoc: PSP association, if socket is PSP-secured 252 253 * @sk_receive_queue: incoming packets 253 254 * @sk_wmem_alloc: transmit queue bytes committed 254 255 * @sk_tsq_flags: TCP Small Queues flags ··· 451 450 #endif 452 451 #ifdef CONFIG_XFRM 453 452 struct xfrm_policy __rcu *sk_policy[2]; 453 + #endif 454 + #if IS_ENABLED(CONFIG_INET_PSP) 455 + struct psp_assoc __rcu *psp_assoc; 454 456 #endif 455 457 __cacheline_group_end(sock_read_rxtx); 456 458 ··· 2958 2954 sk_requests_wifi_status(struct sock *sk) 2959 2955 { 2960 2956 return sk && sk_fullsock(sk) && sock_flag(sk, SOCK_WIFI_STATUS); 2961 - } 2962 - 2963 - /* Checks if this SKB belongs to an HW offloaded socket 2964 - * and whether any SW fallbacks are required based on dev. 2965 - * Check decrypted mark in case skb_orphan() cleared socket. 2966 - */ 2967 - static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb, 2968 - struct net_device *dev) 2969 - { 2970 - #ifdef CONFIG_SOCK_VALIDATE_XMIT 2971 - struct sock *sk = skb->sk; 2972 - 2973 - if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) { 2974 - skb = sk->sk_validate_xmit_skb(sk, dev, skb); 2975 - } else if (unlikely(skb_is_decrypted(skb))) { 2976 - pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n"); 2977 - kfree_skb(skb); 2978 - skb = NULL; 2979 - } 2980 - #endif 2981 - 2982 - return skb; 2983 2957 } 2984 2958 2985 2959 /* This helper checks if a socket is a LISTEN or NEW_SYN_RECV
+66
include/uapi/linux/psp.h
··· 1 + /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ 2 + /* Do not edit directly, auto-generated from: */ 3 + /* Documentation/netlink/specs/psp.yaml */ 4 + /* YNL-GEN uapi header */ 5 + 6 + #ifndef _UAPI_LINUX_PSP_H 7 + #define _UAPI_LINUX_PSP_H 8 + 9 + #define PSP_FAMILY_NAME "psp" 10 + #define PSP_FAMILY_VERSION 1 11 + 12 + enum psp_version { 13 + PSP_VERSION_HDR0_AES_GCM_128, 14 + PSP_VERSION_HDR0_AES_GCM_256, 15 + PSP_VERSION_HDR0_AES_GMAC_128, 16 + PSP_VERSION_HDR0_AES_GMAC_256, 17 + }; 18 + 19 + enum { 20 + PSP_A_DEV_ID = 1, 21 + PSP_A_DEV_IFINDEX, 22 + PSP_A_DEV_PSP_VERSIONS_CAP, 23 + PSP_A_DEV_PSP_VERSIONS_ENA, 24 + 25 + __PSP_A_DEV_MAX, 26 + PSP_A_DEV_MAX = (__PSP_A_DEV_MAX - 1) 27 + }; 28 + 29 + enum { 30 + PSP_A_ASSOC_DEV_ID = 1, 31 + PSP_A_ASSOC_VERSION, 32 + PSP_A_ASSOC_RX_KEY, 33 + PSP_A_ASSOC_TX_KEY, 34 + PSP_A_ASSOC_SOCK_FD, 35 + 36 + __PSP_A_ASSOC_MAX, 37 + PSP_A_ASSOC_MAX = (__PSP_A_ASSOC_MAX - 1) 38 + }; 39 + 40 + enum { 41 + PSP_A_KEYS_KEY = 1, 42 + PSP_A_KEYS_SPI, 43 + 44 + __PSP_A_KEYS_MAX, 45 + PSP_A_KEYS_MAX = (__PSP_A_KEYS_MAX - 1) 46 + }; 47 + 48 + enum { 49 + PSP_CMD_DEV_GET = 1, 50 + PSP_CMD_DEV_ADD_NTF, 51 + PSP_CMD_DEV_DEL_NTF, 52 + PSP_CMD_DEV_SET, 53 + PSP_CMD_DEV_CHANGE_NTF, 54 + PSP_CMD_KEY_ROTATE, 55 + PSP_CMD_KEY_ROTATE_NTF, 56 + PSP_CMD_RX_ASSOC, 57 + PSP_CMD_TX_ASSOC, 58 + 59 + __PSP_CMD_MAX, 60 + PSP_CMD_MAX = (__PSP_CMD_MAX - 1) 61 + }; 62 + 63 + #define PSP_MCGRP_MGMT "mgmt" 64 + #define PSP_MCGRP_USE "use" 65 + 66 + #endif /* _UAPI_LINUX_PSP_H */
+1
net/Kconfig
··· 82 82 menu "Networking options" 83 83 84 84 source "net/packet/Kconfig" 85 + source "net/psp/Kconfig" 85 86 source "net/unix/Kconfig" 86 87 source "net/tls/Kconfig" 87 88 source "net/xfrm/Kconfig"
+1
net/Makefile
··· 18 18 obj-$(CONFIG_TLS) += tls/ 19 19 obj-$(CONFIG_XFRM) += xfrm/ 20 20 obj-$(CONFIG_UNIX) += unix/ 21 + obj-$(CONFIG_INET_PSP) += psp/ 21 22 obj-y += ipv6/ 22 23 obj-$(CONFIG_PACKET) += packet/ 23 24 obj-$(CONFIG_NET_KEY) += key/
+32
net/core/dev.c
··· 3907 3907 } 3908 3908 EXPORT_SYMBOL(skb_csum_hwoffload_help); 3909 3909 3910 + /* Checks if this SKB belongs to an HW offloaded socket 3911 + * and whether any SW fallbacks are required based on dev. 3912 + * Check decrypted mark in case skb_orphan() cleared socket. 3913 + */ 3914 + static struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb, 3915 + struct net_device *dev) 3916 + { 3917 + #ifdef CONFIG_SOCK_VALIDATE_XMIT 3918 + struct sk_buff *(*sk_validate)(struct sock *sk, struct net_device *dev, 3919 + struct sk_buff *skb); 3920 + struct sock *sk = skb->sk; 3921 + 3922 + sk_validate = NULL; 3923 + if (sk) { 3924 + if (sk_fullsock(sk)) 3925 + sk_validate = sk->sk_validate_xmit_skb; 3926 + else if (sk_is_inet(sk) && sk->sk_state == TCP_TIME_WAIT) 3927 + sk_validate = inet_twsk(sk)->tw_validate_xmit_skb; 3928 + } 3929 + 3930 + if (sk_validate) { 3931 + skb = sk_validate(sk, dev, skb); 3932 + } else if (unlikely(skb_is_decrypted(skb))) { 3933 + pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n"); 3934 + kfree_skb(skb); 3935 + skb = NULL; 3936 + } 3937 + #endif 3938 + 3939 + return skb; 3940 + } 3941 + 3910 3942 static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb, 3911 3943 struct net_device *dev) 3912 3944 {
+2
net/core/gro.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 + #include <net/psp.h> 2 3 #include <net/gro.h> 3 4 #include <net/dst_metadata.h> 4 5 #include <net/busy_poll.h> ··· 377 376 diffs |= skb_get_nfct(p) ^ skb_get_nfct(skb); 378 377 379 378 diffs |= gro_list_prepare_tc_ext(skb, p, diffs); 379 + diffs |= __psp_skb_coalesce_diff(skb, p, diffs); 380 380 } 381 381 382 382 NAPI_GRO_CB(p)->same_flow = !diffs;
+4
net/core/skbuff.c
··· 79 79 #include <net/mptcp.h> 80 80 #include <net/mctp.h> 81 81 #include <net/page_pool/helpers.h> 82 + #include <net/psp/types.h> 82 83 #include <net/dropreason.h> 83 84 84 85 #include <linux/uaccess.h> ··· 5062 5061 #endif 5063 5062 #if IS_ENABLED(CONFIG_MCTP_FLOWS) 5064 5063 [SKB_EXT_MCTP] = SKB_EXT_CHUNKSIZEOF(struct mctp_flow), 5064 + #endif 5065 + #if IS_ENABLED(CONFIG_INET_PSP) 5066 + [SKB_EXT_PSP] = SKB_EXT_CHUNKSIZEOF(struct psp_skb_ext), 5065 5067 #endif 5066 5068 }; 5067 5069
+2
net/ipv4/af_inet.c
··· 102 102 #include <net/gro.h> 103 103 #include <net/gso.h> 104 104 #include <net/tcp.h> 105 + #include <net/psp.h> 105 106 #include <net/udp.h> 106 107 #include <net/udplite.h> 107 108 #include <net/ping.h> ··· 159 158 kfree(rcu_dereference_protected(inet->inet_opt, 1)); 160 159 dst_release(rcu_dereference_protected(sk->sk_dst_cache, 1)); 161 160 dst_release(rcu_dereference_protected(sk->sk_rx_dst, 1)); 161 + psp_sk_assoc_free(sk); 162 162 } 163 163 EXPORT_SYMBOL(inet_sock_destruct); 164 164
+5
net/ipv4/inet_timewait_sock.c
··· 16 16 #include <net/inet_timewait_sock.h> 17 17 #include <net/ip.h> 18 18 #include <net/tcp.h> 19 + #include <net/psp.h> 19 20 20 21 /** 21 22 * inet_twsk_bind_unhash - unhash a timewait socket from bind hash ··· 212 211 atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie)); 213 212 twsk_net_set(tw, sock_net(sk)); 214 213 timer_setup(&tw->tw_timer, tw_timer_handler, 0); 214 + #ifdef CONFIG_SOCK_VALIDATE_XMIT 215 + tw->tw_validate_xmit_skb = NULL; 216 + #endif 215 217 /* 216 218 * Because we use RCU lookups, we should not set tw_refcnt 217 219 * to a non null value before everything is setup for this ··· 223 219 refcount_set(&tw->tw_refcnt, 0); 224 220 225 221 __module_get(tw->tw_prot->owner); 222 + psp_twsk_init(tw, sk); 226 223 } 227 224 228 225 return tw;
+4 -1
net/ipv4/ip_output.c
··· 84 84 #include <linux/netfilter_bridge.h> 85 85 #include <linux/netlink.h> 86 86 #include <linux/tcp.h> 87 + #include <net/psp.h> 87 88 88 89 static int 89 90 ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ··· 1666 1665 arg->csumoffset) = csum_fold(csum_add(nskb->csum, 1667 1666 arg->csum)); 1668 1667 nskb->ip_summed = CHECKSUM_NONE; 1669 - if (orig_sk) 1668 + if (orig_sk) { 1670 1669 skb_set_owner_edemux(nskb, (struct sock *)orig_sk); 1670 + psp_reply_set_decrypted(nskb); 1671 + } 1671 1672 if (transmit_time) 1672 1673 nskb->tstamp_type = SKB_CLOCK_MONOTONIC; 1673 1674 if (txhash)
+2
net/ipv4/tcp.c
··· 277 277 #include <net/proto_memory.h> 278 278 #include <net/xfrm.h> 279 279 #include <net/ip.h> 280 + #include <net/psp.h> 280 281 #include <net/sock.h> 281 282 #include <net/rstreason.h> 282 283 ··· 706 705 tcb->seq = tcb->end_seq = tp->write_seq; 707 706 tcb->tcp_flags = TCPHDR_ACK; 708 707 __skb_header_release(skb); 708 + psp_enqueue_set_decrypted(sk, skb); 709 709 tcp_add_write_queue_tail(sk, skb); 710 710 sk_wmem_queued_add(sk, skb->truesize); 711 711 sk_mem_charge(sk, skb->truesize);
+15 -3
net/ipv4/tcp_ipv4.c
··· 75 75 #include <net/secure_seq.h> 76 76 #include <net/busy_poll.h> 77 77 #include <net/rstreason.h> 78 + #include <net/psp.h> 78 79 79 80 #include <linux/inet.h> 80 81 #include <linux/ipv6.h> ··· 294 293 inet->inet_dport = usin->sin_port; 295 294 sk_daddr_set(sk, daddr); 296 295 297 - inet_csk(sk)->icsk_ext_hdr_len = 0; 296 + inet_csk(sk)->icsk_ext_hdr_len = psp_sk_overhead(sk); 298 297 if (inet_opt) 299 - inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; 298 + inet_csk(sk)->icsk_ext_hdr_len += inet_opt->opt.optlen; 300 299 301 300 tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT; 302 301 ··· 1908 1907 enum skb_drop_reason reason; 1909 1908 struct sock *rsk; 1910 1909 1910 + reason = psp_sk_rx_policy_check(sk, skb); 1911 + if (reason) 1912 + goto err_discard; 1913 + 1911 1914 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ 1912 1915 struct dst_entry *dst; 1913 1916 ··· 1973 1968 reason = SKB_DROP_REASON_TCP_CSUM; 1974 1969 trace_tcp_bad_csum(skb); 1975 1970 TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); 1971 + err_discard: 1976 1972 TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); 1977 1973 goto discard; 1978 1974 } ··· 2075 2069 (TCPHDR_ECE | TCPHDR_CWR | TCPHDR_AE)) || 2076 2070 !tcp_skb_can_collapse_rx(tail, skb) || 2077 2071 thtail->doff != th->doff || 2078 - memcmp(thtail + 1, th + 1, hdrlen - sizeof(*th))) 2072 + memcmp(thtail + 1, th + 1, hdrlen - sizeof(*th)) || 2073 + /* prior to PSP Rx policy check, retain exact PSP metadata */ 2074 + psp_skb_coalesce_diff(tail, skb)) 2079 2075 goto no_coalesce; 2080 2076 2081 2077 __skb_pull(skb, hdrlen); ··· 2445 2437 __this_cpu_write(tcp_tw_isn, isn); 2446 2438 goto process; 2447 2439 } 2440 + 2441 + drop_reason = psp_twsk_rx_policy_check(inet_twsk(sk), skb); 2442 + if (drop_reason) 2443 + break; 2448 2444 } 2449 2445 /* to ACK */ 2450 2446 fallthrough;
+20
net/ipv4/tcp_minisocks.c
··· 24 24 #include <net/xfrm.h> 25 25 #include <net/busy_poll.h> 26 26 #include <net/rstreason.h> 27 + #include <net/psp.h> 27 28 28 29 static bool tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win) 29 30 { ··· 105 104 struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); 106 105 u32 rcv_nxt = READ_ONCE(tcptw->tw_rcv_nxt); 107 106 struct tcp_options_received tmp_opt; 107 + enum skb_drop_reason psp_drop; 108 108 bool paws_reject = false; 109 109 int ts_recent_stamp; 110 + 111 + /* Instead of dropping immediately, wait to see what value is 112 + * returned. We will accept a non psp-encapsulated syn in the 113 + * case where TCP_TW_SYN is returned. 114 + */ 115 + psp_drop = psp_twsk_rx_policy_check(tw, skb); 110 116 111 117 tmp_opt.saw_tstamp = 0; 112 118 ts_recent_stamp = READ_ONCE(tcptw->tw_ts_recent_stamp); ··· 131 123 132 124 if (READ_ONCE(tw->tw_substate) == TCP_FIN_WAIT2) { 133 125 /* Just repeat all the checks of tcp_rcv_state_process() */ 126 + 127 + if (psp_drop) 128 + goto out_put; 134 129 135 130 /* Out of window, send ACK */ 136 131 if (paws_reject || ··· 205 194 (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq || th->rst))) { 206 195 /* In window segment, it may be only reset or bare ack. */ 207 196 197 + if (psp_drop) 198 + goto out_put; 199 + 208 200 if (th->rst) { 209 201 /* This is TIME_WAIT assassination, in two flavors. 210 202 * Oh well... nobody has a sufficient solution to this ··· 261 247 return TCP_TW_SYN; 262 248 } 263 249 250 + if (psp_drop) 251 + goto out_put; 252 + 264 253 if (paws_reject) { 265 254 *drop_reason = SKB_DROP_REASON_TCP_RFC7323_TW_PAWS; 266 255 __NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWS_TW_REJECTED); ··· 282 265 return tcp_timewait_check_oow_rate_limit( 283 266 tw, skb, LINUX_MIB_TCPACKSKIPPEDTIMEWAIT); 284 267 } 268 + 269 + out_put: 285 270 inet_twsk_put(tw); 286 271 return TCP_TW_SUCCESS; 287 272 } ··· 411 392 } 412 393 #endif 413 394 tcp_ao_destroy_sock(sk, true); 395 + psp_twsk_assoc_free(inet_twsk(sk)); 414 396 } 415 397 416 398 void tcp_twsk_purge(struct list_head *net_exit_list)
+11 -6
net/ipv4/tcp_output.c
··· 41 41 #include <net/tcp_ecn.h> 42 42 #include <net/mptcp.h> 43 43 #include <net/proto_memory.h> 44 + #include <net/psp.h> 44 45 45 46 #include <linux/compiler.h> 46 47 #include <linux/gfp.h> ··· 359 358 /* Constructs common control bits of non-data skb. If SYN/FIN is present, 360 359 * auto increment end seqno. 361 360 */ 362 - static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u16 flags) 361 + static void tcp_init_nondata_skb(struct sk_buff *skb, struct sock *sk, 362 + u32 seq, u16 flags) 363 363 { 364 364 skb->ip_summed = CHECKSUM_PARTIAL; 365 365 366 366 TCP_SKB_CB(skb)->tcp_flags = flags; 367 367 368 368 tcp_skb_pcount_set(skb, 1); 369 + psp_enqueue_set_decrypted(sk, skb); 369 370 370 371 TCP_SKB_CB(skb)->seq = seq; 371 372 if (flags & (TCPHDR_SYN | TCPHDR_FIN)) ··· 1659 1656 /* Advance write_seq and place onto the write_queue. */ 1660 1657 WRITE_ONCE(tp->write_seq, TCP_SKB_CB(skb)->end_seq); 1661 1658 __skb_header_release(skb); 1659 + psp_enqueue_set_decrypted(sk, skb); 1662 1660 tcp_add_write_queue_tail(sk, skb); 1663 1661 sk_wmem_queued_add(sk, skb->truesize); 1664 1662 sk_mem_charge(sk, skb->truesize); ··· 3782 3778 skb_reserve(skb, MAX_TCP_HEADER); 3783 3779 sk_forced_mem_schedule(sk, skb->truesize); 3784 3780 /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ 3785 - tcp_init_nondata_skb(skb, tp->write_seq, 3781 + tcp_init_nondata_skb(skb, sk, tp->write_seq, 3786 3782 TCPHDR_ACK | TCPHDR_FIN); 3787 3783 tcp_queue_skb(sk, skb); 3788 3784 } ··· 3810 3806 3811 3807 /* Reserve space for headers and prepare control bits. */ 3812 3808 skb_reserve(skb, MAX_TCP_HEADER); 3813 - tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk), 3809 + tcp_init_nondata_skb(skb, sk, tcp_acceptable_seq(sk), 3814 3810 TCPHDR_ACK | TCPHDR_RST); 3815 3811 tcp_mstamp_refresh(tcp_sk(sk)); 3816 3812 /* Send it off. */ ··· 4307 4303 /* SYN eats a sequence byte, write_seq updated by 4308 4304 * tcp_connect_queue_skb(). 4309 4305 */ 4310 - tcp_init_nondata_skb(buff, tp->write_seq, TCPHDR_SYN); 4306 + tcp_init_nondata_skb(buff, sk, tp->write_seq, TCPHDR_SYN); 4311 4307 tcp_mstamp_refresh(tp); 4312 4308 tp->retrans_stamp = tcp_time_stamp_ts(tp); 4313 4309 tcp_connect_queue_skb(sk, buff); ··· 4432 4428 4433 4429 /* Reserve space for headers and prepare control bits. */ 4434 4430 skb_reserve(buff, MAX_TCP_HEADER); 4435 - tcp_init_nondata_skb(buff, tcp_acceptable_seq(sk), TCPHDR_ACK | flags); 4431 + tcp_init_nondata_skb(buff, sk, 4432 + tcp_acceptable_seq(sk), TCPHDR_ACK | flags); 4436 4433 4437 4434 /* We do not want pure acks influencing TCP Small Queues or fq/pacing 4438 4435 * too much. ··· 4479 4474 * end to send an ack. Don't queue or clone SKB, just 4480 4475 * send it. 4481 4476 */ 4482 - tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK); 4477 + tcp_init_nondata_skb(skb, sk, tp->snd_una - !urgent, TCPHDR_ACK); 4483 4478 NET_INC_STATS(sock_net(sk), mib); 4484 4479 return tcp_transmit_skb(sk, skb, 0, (__force gfp_t)0); 4485 4480 }
+5 -1
net/ipv6/ipv6_sockglue.c
··· 49 49 #include <net/xfrm.h> 50 50 #include <net/compat.h> 51 51 #include <net/seg6.h> 52 + #include <net/psp.h> 52 53 53 54 #include <linux/uaccess.h> 54 55 ··· 108 107 !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && 109 108 inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) { 110 109 struct inet_connection_sock *icsk = inet_csk(sk); 111 - icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; 110 + 111 + icsk->icsk_ext_hdr_len = 112 + psp_sk_overhead(sk) + 113 + opt->opt_flen + opt->opt_nflen; 112 114 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 113 115 } 114 116 }
+14 -3
net/ipv6/tcp_ipv6.c
··· 62 62 #include <net/hotdata.h> 63 63 #include <net/busy_poll.h> 64 64 #include <net/rstreason.h> 65 + #include <net/psp.h> 65 66 66 67 #include <linux/proc_fs.h> 67 68 #include <linux/seq_file.h> ··· 302 301 sk->sk_gso_type = SKB_GSO_TCPV6; 303 302 ip6_dst_store(sk, dst, false, false); 304 303 305 - icsk->icsk_ext_hdr_len = 0; 304 + icsk->icsk_ext_hdr_len = psp_sk_overhead(sk); 306 305 if (opt) 307 - icsk->icsk_ext_hdr_len = opt->opt_flen + 308 - opt->opt_nflen; 306 + icsk->icsk_ext_hdr_len += opt->opt_flen + 307 + opt->opt_nflen; 309 308 310 309 tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); 311 310 ··· 974 973 if (sk) { 975 974 /* unconstify the socket only to attach it to buff with care. */ 976 975 skb_set_owner_edemux(buff, (struct sock *)sk); 976 + psp_reply_set_decrypted(buff); 977 977 978 978 if (sk->sk_state == TCP_TIME_WAIT) 979 979 mark = inet_twsk(sk)->tw_mark; ··· 1607 1605 if (skb->protocol == htons(ETH_P_IP)) 1608 1606 return tcp_v4_do_rcv(sk, skb); 1609 1607 1608 + reason = psp_sk_rx_policy_check(sk, skb); 1609 + if (reason) 1610 + goto err_discard; 1611 + 1610 1612 /* 1611 1613 * socket locking is here for SMP purposes as backlog rcv 1612 1614 * is currently called with bh processing disabled. ··· 1690 1684 reason = SKB_DROP_REASON_TCP_CSUM; 1691 1685 trace_tcp_bad_csum(skb); 1692 1686 TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); 1687 + err_discard: 1693 1688 TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); 1694 1689 goto discard; 1695 1690 ··· 1995 1988 __this_cpu_write(tcp_tw_isn, isn); 1996 1989 goto process; 1997 1990 } 1991 + 1992 + drop_reason = psp_twsk_rx_policy_check(inet_twsk(sk), skb); 1993 + if (drop_reason) 1994 + break; 1998 1995 } 1999 1996 /* to ACK */ 2000 1997 fallthrough;
+15
net/psp/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # 3 + # PSP configuration 4 + # 5 + config INET_PSP 6 + bool "PSP Security Protocol support" 7 + depends on INET 8 + select SKB_DECRYPTED 9 + select SOCK_VALIDATE_XMIT 10 + help 11 + Enable kernel support for the PSP protocol. 12 + For more information see: 13 + https://raw.githubusercontent.com/google/psp/main/doc/PSP_Arch_Spec.pdf 14 + 15 + If unsure, say N.
+5
net/psp/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + obj-$(CONFIG_INET_PSP) += psp.o 4 + 5 + psp-y := psp_main.o psp_nl.o psp_sock.o psp-nl-gen.o
+119
net/psp/psp-nl-gen.c
··· 1 + // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 2 + /* Do not edit directly, auto-generated from: */ 3 + /* Documentation/netlink/specs/psp.yaml */ 4 + /* YNL-GEN kernel source */ 5 + 6 + #include <net/netlink.h> 7 + #include <net/genetlink.h> 8 + 9 + #include "psp-nl-gen.h" 10 + 11 + #include <uapi/linux/psp.h> 12 + 13 + /* Common nested types */ 14 + const struct nla_policy psp_keys_nl_policy[PSP_A_KEYS_SPI + 1] = { 15 + [PSP_A_KEYS_KEY] = { .type = NLA_BINARY, }, 16 + [PSP_A_KEYS_SPI] = { .type = NLA_U32, }, 17 + }; 18 + 19 + /* PSP_CMD_DEV_GET - do */ 20 + static const struct nla_policy psp_dev_get_nl_policy[PSP_A_DEV_ID + 1] = { 21 + [PSP_A_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 22 + }; 23 + 24 + /* PSP_CMD_DEV_SET - do */ 25 + static const struct nla_policy psp_dev_set_nl_policy[PSP_A_DEV_PSP_VERSIONS_ENA + 1] = { 26 + [PSP_A_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 27 + [PSP_A_DEV_PSP_VERSIONS_ENA] = NLA_POLICY_MASK(NLA_U32, 0xf), 28 + }; 29 + 30 + /* PSP_CMD_KEY_ROTATE - do */ 31 + static const struct nla_policy psp_key_rotate_nl_policy[PSP_A_DEV_ID + 1] = { 32 + [PSP_A_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 33 + }; 34 + 35 + /* PSP_CMD_RX_ASSOC - do */ 36 + static const struct nla_policy psp_rx_assoc_nl_policy[PSP_A_ASSOC_SOCK_FD + 1] = { 37 + [PSP_A_ASSOC_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 38 + [PSP_A_ASSOC_VERSION] = NLA_POLICY_MAX(NLA_U32, 3), 39 + [PSP_A_ASSOC_SOCK_FD] = { .type = NLA_U32, }, 40 + }; 41 + 42 + /* PSP_CMD_TX_ASSOC - do */ 43 + static const struct nla_policy psp_tx_assoc_nl_policy[PSP_A_ASSOC_SOCK_FD + 1] = { 44 + [PSP_A_ASSOC_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 45 + [PSP_A_ASSOC_VERSION] = NLA_POLICY_MAX(NLA_U32, 3), 46 + [PSP_A_ASSOC_TX_KEY] = NLA_POLICY_NESTED(psp_keys_nl_policy), 47 + [PSP_A_ASSOC_SOCK_FD] = { .type = NLA_U32, }, 48 + }; 49 + 50 + /* Ops table for psp */ 51 + static const struct genl_split_ops psp_nl_ops[] = { 52 + { 53 + .cmd = PSP_CMD_DEV_GET, 54 + .pre_doit = psp_device_get_locked, 55 + .doit = psp_nl_dev_get_doit, 56 + .post_doit = psp_device_unlock, 57 + .policy = psp_dev_get_nl_policy, 58 + .maxattr = PSP_A_DEV_ID, 59 + .flags = GENL_CMD_CAP_DO, 60 + }, 61 + { 62 + .cmd = PSP_CMD_DEV_GET, 63 + .dumpit = psp_nl_dev_get_dumpit, 64 + .flags = GENL_CMD_CAP_DUMP, 65 + }, 66 + { 67 + .cmd = PSP_CMD_DEV_SET, 68 + .pre_doit = psp_device_get_locked, 69 + .doit = psp_nl_dev_set_doit, 70 + .post_doit = psp_device_unlock, 71 + .policy = psp_dev_set_nl_policy, 72 + .maxattr = PSP_A_DEV_PSP_VERSIONS_ENA, 73 + .flags = GENL_CMD_CAP_DO, 74 + }, 75 + { 76 + .cmd = PSP_CMD_KEY_ROTATE, 77 + .pre_doit = psp_device_get_locked, 78 + .doit = psp_nl_key_rotate_doit, 79 + .post_doit = psp_device_unlock, 80 + .policy = psp_key_rotate_nl_policy, 81 + .maxattr = PSP_A_DEV_ID, 82 + .flags = GENL_CMD_CAP_DO, 83 + }, 84 + { 85 + .cmd = PSP_CMD_RX_ASSOC, 86 + .pre_doit = psp_assoc_device_get_locked, 87 + .doit = psp_nl_rx_assoc_doit, 88 + .post_doit = psp_device_unlock, 89 + .policy = psp_rx_assoc_nl_policy, 90 + .maxattr = PSP_A_ASSOC_SOCK_FD, 91 + .flags = GENL_CMD_CAP_DO, 92 + }, 93 + { 94 + .cmd = PSP_CMD_TX_ASSOC, 95 + .pre_doit = psp_assoc_device_get_locked, 96 + .doit = psp_nl_tx_assoc_doit, 97 + .post_doit = psp_device_unlock, 98 + .policy = psp_tx_assoc_nl_policy, 99 + .maxattr = PSP_A_ASSOC_SOCK_FD, 100 + .flags = GENL_CMD_CAP_DO, 101 + }, 102 + }; 103 + 104 + static const struct genl_multicast_group psp_nl_mcgrps[] = { 105 + [PSP_NLGRP_MGMT] = { "mgmt", }, 106 + [PSP_NLGRP_USE] = { "use", }, 107 + }; 108 + 109 + struct genl_family psp_nl_family __ro_after_init = { 110 + .name = PSP_FAMILY_NAME, 111 + .version = PSP_FAMILY_VERSION, 112 + .netnsok = true, 113 + .parallel_ops = true, 114 + .module = THIS_MODULE, 115 + .split_ops = psp_nl_ops, 116 + .n_split_ops = ARRAY_SIZE(psp_nl_ops), 117 + .mcgrps = psp_nl_mcgrps, 118 + .n_mcgrps = ARRAY_SIZE(psp_nl_mcgrps), 119 + };
+39
net/psp/psp-nl-gen.h
··· 1 + /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ 2 + /* Do not edit directly, auto-generated from: */ 3 + /* Documentation/netlink/specs/psp.yaml */ 4 + /* YNL-GEN kernel header */ 5 + 6 + #ifndef _LINUX_PSP_GEN_H 7 + #define _LINUX_PSP_GEN_H 8 + 9 + #include <net/netlink.h> 10 + #include <net/genetlink.h> 11 + 12 + #include <uapi/linux/psp.h> 13 + 14 + /* Common nested types */ 15 + extern const struct nla_policy psp_keys_nl_policy[PSP_A_KEYS_SPI + 1]; 16 + 17 + int psp_device_get_locked(const struct genl_split_ops *ops, 18 + struct sk_buff *skb, struct genl_info *info); 19 + int psp_assoc_device_get_locked(const struct genl_split_ops *ops, 20 + struct sk_buff *skb, struct genl_info *info); 21 + void 22 + psp_device_unlock(const struct genl_split_ops *ops, struct sk_buff *skb, 23 + struct genl_info *info); 24 + 25 + int psp_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info); 26 + int psp_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb); 27 + int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info); 28 + int psp_nl_key_rotate_doit(struct sk_buff *skb, struct genl_info *info); 29 + int psp_nl_rx_assoc_doit(struct sk_buff *skb, struct genl_info *info); 30 + int psp_nl_tx_assoc_doit(struct sk_buff *skb, struct genl_info *info); 31 + 32 + enum { 33 + PSP_NLGRP_MGMT, 34 + PSP_NLGRP_USE, 35 + }; 36 + 37 + extern struct genl_family psp_nl_family; 38 + 39 + #endif /* _LINUX_PSP_GEN_H */
+54
net/psp/psp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __PSP_PSP_H 4 + #define __PSP_PSP_H 5 + 6 + #include <linux/list.h> 7 + #include <linux/lockdep.h> 8 + #include <linux/mutex.h> 9 + #include <net/netns/generic.h> 10 + #include <net/psp.h> 11 + #include <net/sock.h> 12 + 13 + extern struct xarray psp_devs; 14 + extern struct mutex psp_devs_lock; 15 + 16 + void psp_dev_destroy(struct psp_dev *psd); 17 + int psp_dev_check_access(struct psp_dev *psd, struct net *net); 18 + 19 + void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd); 20 + 21 + struct psp_assoc *psp_assoc_create(struct psp_dev *psd); 22 + struct psp_dev *psp_dev_get_for_sock(struct sock *sk); 23 + void psp_dev_tx_key_del(struct psp_dev *psd, struct psp_assoc *pas); 24 + int psp_sock_assoc_set_rx(struct sock *sk, struct psp_assoc *pas, 25 + struct psp_key_parsed *key, 26 + struct netlink_ext_ack *extack); 27 + int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, 28 + u32 version, struct psp_key_parsed *key, 29 + struct netlink_ext_ack *extack); 30 + void psp_assocs_key_rotated(struct psp_dev *psd); 31 + 32 + static inline void psp_dev_get(struct psp_dev *psd) 33 + { 34 + refcount_inc(&psd->refcnt); 35 + } 36 + 37 + static inline bool psp_dev_tryget(struct psp_dev *psd) 38 + { 39 + return refcount_inc_not_zero(&psd->refcnt); 40 + } 41 + 42 + static inline void psp_dev_put(struct psp_dev *psd) 43 + { 44 + if (refcount_dec_and_test(&psd->refcnt)) 45 + psp_dev_destroy(psd); 46 + } 47 + 48 + static inline bool psp_dev_is_registered(struct psp_dev *psd) 49 + { 50 + lockdep_assert_held(&psd->lock); 51 + return !!psd->ops; 52 + } 53 + 54 + #endif /* __PSP_PSP_H */
+321
net/psp/psp_main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/bitfield.h> 4 + #include <linux/list.h> 5 + #include <linux/netdevice.h> 6 + #include <linux/xarray.h> 7 + #include <net/net_namespace.h> 8 + #include <net/psp.h> 9 + #include <net/udp.h> 10 + 11 + #include "psp.h" 12 + #include "psp-nl-gen.h" 13 + 14 + DEFINE_XARRAY_ALLOC1(psp_devs); 15 + struct mutex psp_devs_lock; 16 + 17 + /** 18 + * DOC: PSP locking 19 + * 20 + * psp_devs_lock protects the psp_devs xarray. 21 + * Ordering is take the psp_devs_lock and then the instance lock. 22 + * Each instance is protected by RCU, and has a refcount. 23 + * When driver unregisters the instance gets flushed, but struct sticks around. 24 + */ 25 + 26 + /** 27 + * psp_dev_check_access() - check if user in a given net ns can access PSP dev 28 + * @psd: PSP device structure user is trying to access 29 + * @net: net namespace user is in 30 + * 31 + * Return: 0 if PSP device should be visible in @net, errno otherwise. 32 + */ 33 + int psp_dev_check_access(struct psp_dev *psd, struct net *net) 34 + { 35 + if (dev_net(psd->main_netdev) == net) 36 + return 0; 37 + return -ENOENT; 38 + } 39 + 40 + /** 41 + * psp_dev_create() - create and register PSP device 42 + * @netdev: main netdevice 43 + * @psd_ops: driver callbacks 44 + * @psd_caps: device capabilities 45 + * @priv_ptr: back-pointer to driver private data 46 + * 47 + * Return: pointer to allocated PSP device, or ERR_PTR. 48 + */ 49 + struct psp_dev * 50 + psp_dev_create(struct net_device *netdev, 51 + struct psp_dev_ops *psd_ops, struct psp_dev_caps *psd_caps, 52 + void *priv_ptr) 53 + { 54 + struct psp_dev *psd; 55 + static u32 last_id; 56 + int err; 57 + 58 + if (WARN_ON(!psd_caps->versions || 59 + !psd_ops->set_config || 60 + !psd_ops->key_rotate || 61 + !psd_ops->rx_spi_alloc || 62 + !psd_ops->tx_key_add || 63 + !psd_ops->tx_key_del)) 64 + return ERR_PTR(-EINVAL); 65 + 66 + psd = kzalloc(sizeof(*psd), GFP_KERNEL); 67 + if (!psd) 68 + return ERR_PTR(-ENOMEM); 69 + 70 + psd->main_netdev = netdev; 71 + psd->ops = psd_ops; 72 + psd->caps = psd_caps; 73 + psd->drv_priv = priv_ptr; 74 + 75 + mutex_init(&psd->lock); 76 + INIT_LIST_HEAD(&psd->active_assocs); 77 + INIT_LIST_HEAD(&psd->prev_assocs); 78 + INIT_LIST_HEAD(&psd->stale_assocs); 79 + refcount_set(&psd->refcnt, 1); 80 + 81 + mutex_lock(&psp_devs_lock); 82 + err = xa_alloc_cyclic(&psp_devs, &psd->id, psd, xa_limit_16b, 83 + &last_id, GFP_KERNEL); 84 + if (err) { 85 + mutex_unlock(&psp_devs_lock); 86 + kfree(psd); 87 + return ERR_PTR(err); 88 + } 89 + mutex_lock(&psd->lock); 90 + mutex_unlock(&psp_devs_lock); 91 + 92 + psp_nl_notify_dev(psd, PSP_CMD_DEV_ADD_NTF); 93 + 94 + rcu_assign_pointer(netdev->psp_dev, psd); 95 + 96 + mutex_unlock(&psd->lock); 97 + 98 + return psd; 99 + } 100 + EXPORT_SYMBOL(psp_dev_create); 101 + 102 + void psp_dev_destroy(struct psp_dev *psd) 103 + { 104 + mutex_lock(&psp_devs_lock); 105 + xa_erase(&psp_devs, psd->id); 106 + mutex_unlock(&psp_devs_lock); 107 + 108 + mutex_destroy(&psd->lock); 109 + kfree_rcu(psd, rcu); 110 + } 111 + 112 + /** 113 + * psp_dev_unregister() - unregister PSP device 114 + * @psd: PSP device structure 115 + */ 116 + void psp_dev_unregister(struct psp_dev *psd) 117 + { 118 + struct psp_assoc *pas, *next; 119 + 120 + mutex_lock(&psp_devs_lock); 121 + mutex_lock(&psd->lock); 122 + 123 + psp_nl_notify_dev(psd, PSP_CMD_DEV_DEL_NTF); 124 + 125 + /* Wait until psp_dev_destroy() to call xa_erase() to prevent a 126 + * different psd from being added to the xarray with this id, while 127 + * there are still references to this psd being held. 128 + */ 129 + xa_store(&psp_devs, psd->id, NULL, GFP_KERNEL); 130 + mutex_unlock(&psp_devs_lock); 131 + 132 + list_splice_init(&psd->active_assocs, &psd->prev_assocs); 133 + list_splice_init(&psd->prev_assocs, &psd->stale_assocs); 134 + list_for_each_entry_safe(pas, next, &psd->stale_assocs, assocs_list) 135 + psp_dev_tx_key_del(psd, pas); 136 + 137 + rcu_assign_pointer(psd->main_netdev->psp_dev, NULL); 138 + 139 + psd->ops = NULL; 140 + psd->drv_priv = NULL; 141 + 142 + mutex_unlock(&psd->lock); 143 + 144 + psp_dev_put(psd); 145 + } 146 + EXPORT_SYMBOL(psp_dev_unregister); 147 + 148 + unsigned int psp_key_size(u32 version) 149 + { 150 + switch (version) { 151 + case PSP_VERSION_HDR0_AES_GCM_128: 152 + case PSP_VERSION_HDR0_AES_GMAC_128: 153 + return 16; 154 + case PSP_VERSION_HDR0_AES_GCM_256: 155 + case PSP_VERSION_HDR0_AES_GMAC_256: 156 + return 32; 157 + default: 158 + return 0; 159 + } 160 + } 161 + EXPORT_SYMBOL(psp_key_size); 162 + 163 + static void psp_write_headers(struct net *net, struct sk_buff *skb, __be32 spi, 164 + u8 ver, unsigned int udp_len, __be16 sport) 165 + { 166 + struct udphdr *uh = udp_hdr(skb); 167 + struct psphdr *psph = (struct psphdr *)(uh + 1); 168 + 169 + uh->dest = htons(PSP_DEFAULT_UDP_PORT); 170 + uh->source = udp_flow_src_port(net, skb, 0, 0, false); 171 + uh->check = 0; 172 + uh->len = htons(udp_len); 173 + 174 + psph->nexthdr = IPPROTO_TCP; 175 + psph->hdrlen = PSP_HDRLEN_NOOPT; 176 + psph->crypt_offset = 0; 177 + psph->verfl = FIELD_PREP(PSPHDR_VERFL_VERSION, ver) | 178 + FIELD_PREP(PSPHDR_VERFL_ONE, 1); 179 + psph->spi = spi; 180 + memset(&psph->iv, 0, sizeof(psph->iv)); 181 + } 182 + 183 + /* Encapsulate a TCP packet with PSP by adding the UDP+PSP headers and filling 184 + * them in. 185 + */ 186 + bool psp_dev_encapsulate(struct net *net, struct sk_buff *skb, __be32 spi, 187 + u8 ver, __be16 sport) 188 + { 189 + u32 network_len = skb_network_header_len(skb); 190 + u32 ethr_len = skb_mac_header_len(skb); 191 + u32 bufflen = ethr_len + network_len; 192 + 193 + if (skb_cow_head(skb, PSP_ENCAP_HLEN)) 194 + return false; 195 + 196 + skb_push(skb, PSP_ENCAP_HLEN); 197 + skb->mac_header -= PSP_ENCAP_HLEN; 198 + skb->network_header -= PSP_ENCAP_HLEN; 199 + skb->transport_header -= PSP_ENCAP_HLEN; 200 + memmove(skb->data, skb->data + PSP_ENCAP_HLEN, bufflen); 201 + 202 + if (skb->protocol == htons(ETH_P_IP)) { 203 + ip_hdr(skb)->protocol = IPPROTO_UDP; 204 + be16_add_cpu(&ip_hdr(skb)->tot_len, PSP_ENCAP_HLEN); 205 + ip_hdr(skb)->check = 0; 206 + ip_hdr(skb)->check = 207 + ip_fast_csum((u8 *)ip_hdr(skb), ip_hdr(skb)->ihl); 208 + } else if (skb->protocol == htons(ETH_P_IPV6)) { 209 + ipv6_hdr(skb)->nexthdr = IPPROTO_UDP; 210 + be16_add_cpu(&ipv6_hdr(skb)->payload_len, PSP_ENCAP_HLEN); 211 + } else { 212 + return false; 213 + } 214 + 215 + skb_set_inner_ipproto(skb, IPPROTO_TCP); 216 + skb_set_inner_transport_header(skb, skb_transport_offset(skb) + 217 + PSP_ENCAP_HLEN); 218 + skb->encapsulation = 1; 219 + psp_write_headers(net, skb, spi, ver, 220 + skb->len - skb_transport_offset(skb), sport); 221 + 222 + return true; 223 + } 224 + EXPORT_SYMBOL(psp_dev_encapsulate); 225 + 226 + /* Receive handler for PSP packets. 227 + * 228 + * Presently it accepts only already-authenticated packets and does not 229 + * support optional fields, such as virtualization cookies. The caller should 230 + * ensure that skb->data is pointing to the mac header, and that skb->mac_len 231 + * is set. 232 + */ 233 + int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv) 234 + { 235 + int l2_hlen = 0, l3_hlen, encap; 236 + struct psp_skb_ext *pse; 237 + struct psphdr *psph; 238 + struct ethhdr *eth; 239 + struct udphdr *uh; 240 + __be16 proto; 241 + bool is_udp; 242 + 243 + eth = (struct ethhdr *)skb->data; 244 + proto = __vlan_get_protocol(skb, eth->h_proto, &l2_hlen); 245 + if (proto == htons(ETH_P_IP)) 246 + l3_hlen = sizeof(struct iphdr); 247 + else if (proto == htons(ETH_P_IPV6)) 248 + l3_hlen = sizeof(struct ipv6hdr); 249 + else 250 + return -EINVAL; 251 + 252 + if (unlikely(!pskb_may_pull(skb, l2_hlen + l3_hlen + PSP_ENCAP_HLEN))) 253 + return -EINVAL; 254 + 255 + if (proto == htons(ETH_P_IP)) { 256 + struct iphdr *iph = (struct iphdr *)(skb->data + l2_hlen); 257 + 258 + is_udp = iph->protocol == IPPROTO_UDP; 259 + l3_hlen = iph->ihl * 4; 260 + if (l3_hlen != sizeof(struct iphdr) && 261 + !pskb_may_pull(skb, l2_hlen + l3_hlen + PSP_ENCAP_HLEN)) 262 + return -EINVAL; 263 + } else { 264 + struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + l2_hlen); 265 + 266 + is_udp = ipv6h->nexthdr == IPPROTO_UDP; 267 + } 268 + 269 + if (unlikely(!is_udp)) 270 + return -EINVAL; 271 + 272 + uh = (struct udphdr *)(skb->data + l2_hlen + l3_hlen); 273 + if (unlikely(uh->dest != htons(PSP_DEFAULT_UDP_PORT))) 274 + return -EINVAL; 275 + 276 + pse = skb_ext_add(skb, SKB_EXT_PSP); 277 + if (!pse) 278 + return -EINVAL; 279 + 280 + psph = (struct psphdr *)(skb->data + l2_hlen + l3_hlen + 281 + sizeof(struct udphdr)); 282 + pse->spi = psph->spi; 283 + pse->dev_id = dev_id; 284 + pse->generation = generation; 285 + pse->version = FIELD_GET(PSPHDR_VERFL_VERSION, psph->verfl); 286 + 287 + encap = PSP_ENCAP_HLEN; 288 + encap += strip_icv ? PSP_TRL_SIZE : 0; 289 + 290 + if (proto == htons(ETH_P_IP)) { 291 + struct iphdr *iph = (struct iphdr *)(skb->data + l2_hlen); 292 + 293 + iph->protocol = psph->nexthdr; 294 + iph->tot_len = htons(ntohs(iph->tot_len) - encap); 295 + iph->check = 0; 296 + iph->check = ip_fast_csum((u8 *)iph, iph->ihl); 297 + } else { 298 + struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + l2_hlen); 299 + 300 + ipv6h->nexthdr = psph->nexthdr; 301 + ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) - encap); 302 + } 303 + 304 + memmove(skb->data + PSP_ENCAP_HLEN, skb->data, l2_hlen + l3_hlen); 305 + skb_pull(skb, PSP_ENCAP_HLEN); 306 + 307 + if (strip_icv) 308 + pskb_trim(skb, skb->len - PSP_TRL_SIZE); 309 + 310 + return 0; 311 + } 312 + EXPORT_SYMBOL(psp_dev_rcv); 313 + 314 + static int __init psp_init(void) 315 + { 316 + mutex_init(&psp_devs_lock); 317 + 318 + return genl_register_family(&psp_nl_family); 319 + } 320 + 321 + subsys_initcall(psp_init);
+505
net/psp/psp_nl.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/skbuff.h> 4 + #include <linux/xarray.h> 5 + #include <net/genetlink.h> 6 + #include <net/psp.h> 7 + #include <net/sock.h> 8 + 9 + #include "psp-nl-gen.h" 10 + #include "psp.h" 11 + 12 + /* Netlink helpers */ 13 + 14 + static struct sk_buff *psp_nl_reply_new(struct genl_info *info) 15 + { 16 + struct sk_buff *rsp; 17 + void *hdr; 18 + 19 + rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 20 + if (!rsp) 21 + return NULL; 22 + 23 + hdr = genlmsg_iput(rsp, info); 24 + if (!hdr) { 25 + nlmsg_free(rsp); 26 + return NULL; 27 + } 28 + 29 + return rsp; 30 + } 31 + 32 + static int psp_nl_reply_send(struct sk_buff *rsp, struct genl_info *info) 33 + { 34 + /* Note that this *only* works with a single message per skb! */ 35 + nlmsg_end(rsp, (struct nlmsghdr *)rsp->data); 36 + 37 + return genlmsg_reply(rsp, info); 38 + } 39 + 40 + /* Device stuff */ 41 + 42 + static struct psp_dev * 43 + psp_device_get_and_lock(struct net *net, struct nlattr *dev_id) 44 + { 45 + struct psp_dev *psd; 46 + int err; 47 + 48 + mutex_lock(&psp_devs_lock); 49 + psd = xa_load(&psp_devs, nla_get_u32(dev_id)); 50 + if (!psd) { 51 + mutex_unlock(&psp_devs_lock); 52 + return ERR_PTR(-ENODEV); 53 + } 54 + 55 + mutex_lock(&psd->lock); 56 + mutex_unlock(&psp_devs_lock); 57 + 58 + err = psp_dev_check_access(psd, net); 59 + if (err) { 60 + mutex_unlock(&psd->lock); 61 + return ERR_PTR(err); 62 + } 63 + 64 + return psd; 65 + } 66 + 67 + int psp_device_get_locked(const struct genl_split_ops *ops, 68 + struct sk_buff *skb, struct genl_info *info) 69 + { 70 + if (GENL_REQ_ATTR_CHECK(info, PSP_A_DEV_ID)) 71 + return -EINVAL; 72 + 73 + info->user_ptr[0] = psp_device_get_and_lock(genl_info_net(info), 74 + info->attrs[PSP_A_DEV_ID]); 75 + return PTR_ERR_OR_ZERO(info->user_ptr[0]); 76 + } 77 + 78 + void 79 + psp_device_unlock(const struct genl_split_ops *ops, struct sk_buff *skb, 80 + struct genl_info *info) 81 + { 82 + struct socket *socket = info->user_ptr[1]; 83 + struct psp_dev *psd = info->user_ptr[0]; 84 + 85 + mutex_unlock(&psd->lock); 86 + if (socket) 87 + sockfd_put(socket); 88 + } 89 + 90 + static int 91 + psp_nl_dev_fill(struct psp_dev *psd, struct sk_buff *rsp, 92 + const struct genl_info *info) 93 + { 94 + void *hdr; 95 + 96 + hdr = genlmsg_iput(rsp, info); 97 + if (!hdr) 98 + return -EMSGSIZE; 99 + 100 + if (nla_put_u32(rsp, PSP_A_DEV_ID, psd->id) || 101 + nla_put_u32(rsp, PSP_A_DEV_IFINDEX, psd->main_netdev->ifindex) || 102 + nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_CAP, psd->caps->versions) || 103 + nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_ENA, psd->config.versions)) 104 + goto err_cancel_msg; 105 + 106 + genlmsg_end(rsp, hdr); 107 + return 0; 108 + 109 + err_cancel_msg: 110 + genlmsg_cancel(rsp, hdr); 111 + return -EMSGSIZE; 112 + } 113 + 114 + void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd) 115 + { 116 + struct genl_info info; 117 + struct sk_buff *ntf; 118 + 119 + if (!genl_has_listeners(&psp_nl_family, dev_net(psd->main_netdev), 120 + PSP_NLGRP_MGMT)) 121 + return; 122 + 123 + ntf = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 124 + if (!ntf) 125 + return; 126 + 127 + genl_info_init_ntf(&info, &psp_nl_family, cmd); 128 + if (psp_nl_dev_fill(psd, ntf, &info)) { 129 + nlmsg_free(ntf); 130 + return; 131 + } 132 + 133 + genlmsg_multicast_netns(&psp_nl_family, dev_net(psd->main_netdev), ntf, 134 + 0, PSP_NLGRP_MGMT, GFP_KERNEL); 135 + } 136 + 137 + int psp_nl_dev_get_doit(struct sk_buff *req, struct genl_info *info) 138 + { 139 + struct psp_dev *psd = info->user_ptr[0]; 140 + struct sk_buff *rsp; 141 + int err; 142 + 143 + rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 144 + if (!rsp) 145 + return -ENOMEM; 146 + 147 + err = psp_nl_dev_fill(psd, rsp, info); 148 + if (err) 149 + goto err_free_msg; 150 + 151 + return genlmsg_reply(rsp, info); 152 + 153 + err_free_msg: 154 + nlmsg_free(rsp); 155 + return err; 156 + } 157 + 158 + static int 159 + psp_nl_dev_get_dumpit_one(struct sk_buff *rsp, struct netlink_callback *cb, 160 + struct psp_dev *psd) 161 + { 162 + if (psp_dev_check_access(psd, sock_net(rsp->sk))) 163 + return 0; 164 + 165 + return psp_nl_dev_fill(psd, rsp, genl_info_dump(cb)); 166 + } 167 + 168 + int psp_nl_dev_get_dumpit(struct sk_buff *rsp, struct netlink_callback *cb) 169 + { 170 + struct psp_dev *psd; 171 + int err = 0; 172 + 173 + mutex_lock(&psp_devs_lock); 174 + xa_for_each_start(&psp_devs, cb->args[0], psd, cb->args[0]) { 175 + mutex_lock(&psd->lock); 176 + err = psp_nl_dev_get_dumpit_one(rsp, cb, psd); 177 + mutex_unlock(&psd->lock); 178 + if (err) 179 + break; 180 + } 181 + mutex_unlock(&psp_devs_lock); 182 + 183 + return err; 184 + } 185 + 186 + int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info) 187 + { 188 + struct psp_dev *psd = info->user_ptr[0]; 189 + struct psp_dev_config new_config; 190 + struct sk_buff *rsp; 191 + int err; 192 + 193 + memcpy(&new_config, &psd->config, sizeof(new_config)); 194 + 195 + if (info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA]) { 196 + new_config.versions = 197 + nla_get_u32(info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA]); 198 + if (new_config.versions & ~psd->caps->versions) { 199 + NL_SET_ERR_MSG(info->extack, "Requested PSP versions not supported by the device"); 200 + return -EINVAL; 201 + } 202 + } else { 203 + NL_SET_ERR_MSG(info->extack, "No settings present"); 204 + return -EINVAL; 205 + } 206 + 207 + rsp = psp_nl_reply_new(info); 208 + if (!rsp) 209 + return -ENOMEM; 210 + 211 + if (memcmp(&new_config, &psd->config, sizeof(new_config))) { 212 + err = psd->ops->set_config(psd, &new_config, info->extack); 213 + if (err) 214 + goto err_free_rsp; 215 + 216 + memcpy(&psd->config, &new_config, sizeof(new_config)); 217 + } 218 + 219 + psp_nl_notify_dev(psd, PSP_CMD_DEV_CHANGE_NTF); 220 + 221 + return psp_nl_reply_send(rsp, info); 222 + 223 + err_free_rsp: 224 + nlmsg_free(rsp); 225 + return err; 226 + } 227 + 228 + int psp_nl_key_rotate_doit(struct sk_buff *skb, struct genl_info *info) 229 + { 230 + struct psp_dev *psd = info->user_ptr[0]; 231 + struct genl_info ntf_info; 232 + struct sk_buff *ntf, *rsp; 233 + u8 prev_gen; 234 + int err; 235 + 236 + rsp = psp_nl_reply_new(info); 237 + if (!rsp) 238 + return -ENOMEM; 239 + 240 + genl_info_init_ntf(&ntf_info, &psp_nl_family, PSP_CMD_KEY_ROTATE_NTF); 241 + ntf = psp_nl_reply_new(&ntf_info); 242 + if (!ntf) { 243 + err = -ENOMEM; 244 + goto err_free_rsp; 245 + } 246 + 247 + if (nla_put_u32(rsp, PSP_A_DEV_ID, psd->id) || 248 + nla_put_u32(ntf, PSP_A_DEV_ID, psd->id)) { 249 + err = -EMSGSIZE; 250 + goto err_free_ntf; 251 + } 252 + 253 + /* suggest the next gen number, driver can override */ 254 + prev_gen = psd->generation; 255 + psd->generation = (prev_gen + 1) & PSP_GEN_VALID_MASK; 256 + 257 + err = psd->ops->key_rotate(psd, info->extack); 258 + if (err) 259 + goto err_free_ntf; 260 + 261 + WARN_ON_ONCE((psd->generation && psd->generation == prev_gen) || 262 + psd->generation & ~PSP_GEN_VALID_MASK); 263 + 264 + psp_assocs_key_rotated(psd); 265 + 266 + nlmsg_end(ntf, (struct nlmsghdr *)ntf->data); 267 + genlmsg_multicast_netns(&psp_nl_family, dev_net(psd->main_netdev), ntf, 268 + 0, PSP_NLGRP_USE, GFP_KERNEL); 269 + return psp_nl_reply_send(rsp, info); 270 + 271 + err_free_ntf: 272 + nlmsg_free(ntf); 273 + err_free_rsp: 274 + nlmsg_free(rsp); 275 + return err; 276 + } 277 + 278 + /* Key etc. */ 279 + 280 + int psp_assoc_device_get_locked(const struct genl_split_ops *ops, 281 + struct sk_buff *skb, struct genl_info *info) 282 + { 283 + struct socket *socket; 284 + struct psp_dev *psd; 285 + struct nlattr *id; 286 + int fd, err; 287 + 288 + if (GENL_REQ_ATTR_CHECK(info, PSP_A_ASSOC_SOCK_FD)) 289 + return -EINVAL; 290 + 291 + fd = nla_get_u32(info->attrs[PSP_A_ASSOC_SOCK_FD]); 292 + socket = sockfd_lookup(fd, &err); 293 + if (!socket) 294 + return err; 295 + 296 + if (!sk_is_tcp(socket->sk)) { 297 + NL_SET_ERR_MSG_ATTR(info->extack, 298 + info->attrs[PSP_A_ASSOC_SOCK_FD], 299 + "Unsupported socket family and type"); 300 + err = -EOPNOTSUPP; 301 + goto err_sock_put; 302 + } 303 + 304 + psd = psp_dev_get_for_sock(socket->sk); 305 + if (psd) { 306 + err = psp_dev_check_access(psd, genl_info_net(info)); 307 + if (err) { 308 + psp_dev_put(psd); 309 + psd = NULL; 310 + } 311 + } 312 + 313 + if (!psd && GENL_REQ_ATTR_CHECK(info, PSP_A_ASSOC_DEV_ID)) { 314 + err = -EINVAL; 315 + goto err_sock_put; 316 + } 317 + 318 + id = info->attrs[PSP_A_ASSOC_DEV_ID]; 319 + if (psd) { 320 + mutex_lock(&psd->lock); 321 + if (id && psd->id != nla_get_u32(id)) { 322 + mutex_unlock(&psd->lock); 323 + NL_SET_ERR_MSG_ATTR(info->extack, id, 324 + "Device id vs socket mismatch"); 325 + err = -EINVAL; 326 + goto err_psd_put; 327 + } 328 + 329 + psp_dev_put(psd); 330 + } else { 331 + psd = psp_device_get_and_lock(genl_info_net(info), id); 332 + if (IS_ERR(psd)) { 333 + err = PTR_ERR(psd); 334 + goto err_sock_put; 335 + } 336 + } 337 + 338 + info->user_ptr[0] = psd; 339 + info->user_ptr[1] = socket; 340 + 341 + return 0; 342 + 343 + err_psd_put: 344 + psp_dev_put(psd); 345 + err_sock_put: 346 + sockfd_put(socket); 347 + return err; 348 + } 349 + 350 + static int 351 + psp_nl_parse_key(struct genl_info *info, u32 attr, struct psp_key_parsed *key, 352 + unsigned int key_sz) 353 + { 354 + struct nlattr *nest = info->attrs[attr]; 355 + struct nlattr *tb[PSP_A_KEYS_SPI + 1]; 356 + u32 spi; 357 + int err; 358 + 359 + err = nla_parse_nested(tb, ARRAY_SIZE(tb) - 1, nest, 360 + psp_keys_nl_policy, info->extack); 361 + if (err) 362 + return err; 363 + 364 + if (NL_REQ_ATTR_CHECK(info->extack, nest, tb, PSP_A_KEYS_KEY) || 365 + NL_REQ_ATTR_CHECK(info->extack, nest, tb, PSP_A_KEYS_SPI)) 366 + return -EINVAL; 367 + 368 + if (nla_len(tb[PSP_A_KEYS_KEY]) != key_sz) { 369 + NL_SET_ERR_MSG_ATTR(info->extack, tb[PSP_A_KEYS_KEY], 370 + "incorrect key length"); 371 + return -EINVAL; 372 + } 373 + 374 + spi = nla_get_u32(tb[PSP_A_KEYS_SPI]); 375 + if (!(spi & PSP_SPI_KEY_ID)) { 376 + NL_SET_ERR_MSG_ATTR(info->extack, tb[PSP_A_KEYS_KEY], 377 + "invalid SPI: lower 31b must be non-zero"); 378 + return -EINVAL; 379 + } 380 + 381 + key->spi = cpu_to_be32(spi); 382 + memcpy(key->key, nla_data(tb[PSP_A_KEYS_KEY]), key_sz); 383 + 384 + return 0; 385 + } 386 + 387 + static int 388 + psp_nl_put_key(struct sk_buff *skb, u32 attr, u32 version, 389 + struct psp_key_parsed *key) 390 + { 391 + int key_sz = psp_key_size(version); 392 + void *nest; 393 + 394 + nest = nla_nest_start(skb, attr); 395 + 396 + if (nla_put_u32(skb, PSP_A_KEYS_SPI, be32_to_cpu(key->spi)) || 397 + nla_put(skb, PSP_A_KEYS_KEY, key_sz, key->key)) { 398 + nla_nest_cancel(skb, nest); 399 + return -EMSGSIZE; 400 + } 401 + 402 + nla_nest_end(skb, nest); 403 + 404 + return 0; 405 + } 406 + 407 + int psp_nl_rx_assoc_doit(struct sk_buff *skb, struct genl_info *info) 408 + { 409 + struct socket *socket = info->user_ptr[1]; 410 + struct psp_dev *psd = info->user_ptr[0]; 411 + struct psp_key_parsed key; 412 + struct psp_assoc *pas; 413 + struct sk_buff *rsp; 414 + u32 version; 415 + int err; 416 + 417 + if (GENL_REQ_ATTR_CHECK(info, PSP_A_ASSOC_VERSION)) 418 + return -EINVAL; 419 + 420 + version = nla_get_u32(info->attrs[PSP_A_ASSOC_VERSION]); 421 + if (!(psd->caps->versions & (1 << version))) { 422 + NL_SET_BAD_ATTR(info->extack, info->attrs[PSP_A_ASSOC_VERSION]); 423 + return -EOPNOTSUPP; 424 + } 425 + 426 + rsp = psp_nl_reply_new(info); 427 + if (!rsp) 428 + return -ENOMEM; 429 + 430 + pas = psp_assoc_create(psd); 431 + if (!pas) { 432 + err = -ENOMEM; 433 + goto err_free_rsp; 434 + } 435 + pas->version = version; 436 + 437 + err = psd->ops->rx_spi_alloc(psd, version, &key, info->extack); 438 + if (err) 439 + goto err_free_pas; 440 + 441 + if (nla_put_u32(rsp, PSP_A_ASSOC_DEV_ID, psd->id) || 442 + psp_nl_put_key(rsp, PSP_A_ASSOC_RX_KEY, version, &key)) { 443 + err = -EMSGSIZE; 444 + goto err_free_pas; 445 + } 446 + 447 + err = psp_sock_assoc_set_rx(socket->sk, pas, &key, info->extack); 448 + if (err) { 449 + NL_SET_BAD_ATTR(info->extack, info->attrs[PSP_A_ASSOC_SOCK_FD]); 450 + goto err_free_pas; 451 + } 452 + psp_assoc_put(pas); 453 + 454 + return psp_nl_reply_send(rsp, info); 455 + 456 + err_free_pas: 457 + psp_assoc_put(pas); 458 + err_free_rsp: 459 + nlmsg_free(rsp); 460 + return err; 461 + } 462 + 463 + int psp_nl_tx_assoc_doit(struct sk_buff *skb, struct genl_info *info) 464 + { 465 + struct socket *socket = info->user_ptr[1]; 466 + struct psp_dev *psd = info->user_ptr[0]; 467 + struct psp_key_parsed key; 468 + struct sk_buff *rsp; 469 + unsigned int key_sz; 470 + u32 version; 471 + int err; 472 + 473 + if (GENL_REQ_ATTR_CHECK(info, PSP_A_ASSOC_VERSION) || 474 + GENL_REQ_ATTR_CHECK(info, PSP_A_ASSOC_TX_KEY)) 475 + return -EINVAL; 476 + 477 + version = nla_get_u32(info->attrs[PSP_A_ASSOC_VERSION]); 478 + if (!(psd->caps->versions & (1 << version))) { 479 + NL_SET_BAD_ATTR(info->extack, info->attrs[PSP_A_ASSOC_VERSION]); 480 + return -EOPNOTSUPP; 481 + } 482 + 483 + key_sz = psp_key_size(version); 484 + if (!key_sz) 485 + return -EINVAL; 486 + 487 + err = psp_nl_parse_key(info, PSP_A_ASSOC_TX_KEY, &key, key_sz); 488 + if (err < 0) 489 + return err; 490 + 491 + rsp = psp_nl_reply_new(info); 492 + if (!rsp) 493 + return -ENOMEM; 494 + 495 + err = psp_sock_assoc_set_tx(socket->sk, psd, version, &key, 496 + info->extack); 497 + if (err) 498 + goto err_free_msg; 499 + 500 + return psp_nl_reply_send(rsp, info); 501 + 502 + err_free_msg: 503 + nlmsg_free(rsp); 504 + return err; 505 + }
+295
net/psp/psp_sock.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/file.h> 4 + #include <linux/net.h> 5 + #include <linux/rcupdate.h> 6 + #include <linux/tcp.h> 7 + 8 + #include <net/ip.h> 9 + #include <net/psp.h> 10 + #include "psp.h" 11 + 12 + struct psp_dev *psp_dev_get_for_sock(struct sock *sk) 13 + { 14 + struct dst_entry *dst; 15 + struct psp_dev *psd; 16 + 17 + dst = sk_dst_get(sk); 18 + if (!dst) 19 + return NULL; 20 + 21 + rcu_read_lock(); 22 + psd = rcu_dereference(dst->dev->psp_dev); 23 + if (psd && !psp_dev_tryget(psd)) 24 + psd = NULL; 25 + rcu_read_unlock(); 26 + 27 + dst_release(dst); 28 + 29 + return psd; 30 + } 31 + 32 + static struct sk_buff * 33 + psp_validate_xmit(struct sock *sk, struct net_device *dev, struct sk_buff *skb) 34 + { 35 + struct psp_assoc *pas; 36 + bool good; 37 + 38 + rcu_read_lock(); 39 + pas = psp_skb_get_assoc_rcu(skb); 40 + good = !pas || rcu_access_pointer(dev->psp_dev) == pas->psd; 41 + rcu_read_unlock(); 42 + if (!good) { 43 + kfree_skb_reason(skb, SKB_DROP_REASON_PSP_OUTPUT); 44 + return NULL; 45 + } 46 + 47 + return skb; 48 + } 49 + 50 + struct psp_assoc *psp_assoc_create(struct psp_dev *psd) 51 + { 52 + struct psp_assoc *pas; 53 + 54 + lockdep_assert_held(&psd->lock); 55 + 56 + pas = kzalloc(struct_size(pas, drv_data, psd->caps->assoc_drv_spc), 57 + GFP_KERNEL_ACCOUNT); 58 + if (!pas) 59 + return NULL; 60 + 61 + pas->psd = psd; 62 + pas->dev_id = psd->id; 63 + pas->generation = psd->generation; 64 + psp_dev_get(psd); 65 + refcount_set(&pas->refcnt, 1); 66 + 67 + list_add_tail(&pas->assocs_list, &psd->active_assocs); 68 + 69 + return pas; 70 + } 71 + 72 + static struct psp_assoc *psp_assoc_dummy(struct psp_assoc *pas) 73 + { 74 + struct psp_dev *psd = pas->psd; 75 + size_t sz; 76 + 77 + lockdep_assert_held(&psd->lock); 78 + 79 + sz = struct_size(pas, drv_data, psd->caps->assoc_drv_spc); 80 + return kmemdup(pas, sz, GFP_KERNEL); 81 + } 82 + 83 + static int psp_dev_tx_key_add(struct psp_dev *psd, struct psp_assoc *pas, 84 + struct netlink_ext_ack *extack) 85 + { 86 + return psd->ops->tx_key_add(psd, pas, extack); 87 + } 88 + 89 + void psp_dev_tx_key_del(struct psp_dev *psd, struct psp_assoc *pas) 90 + { 91 + if (pas->tx.spi) 92 + psd->ops->tx_key_del(psd, pas); 93 + list_del(&pas->assocs_list); 94 + } 95 + 96 + static void psp_assoc_free(struct work_struct *work) 97 + { 98 + struct psp_assoc *pas = container_of(work, struct psp_assoc, work); 99 + struct psp_dev *psd = pas->psd; 100 + 101 + mutex_lock(&psd->lock); 102 + if (psd->ops) 103 + psp_dev_tx_key_del(psd, pas); 104 + mutex_unlock(&psd->lock); 105 + psp_dev_put(psd); 106 + kfree(pas); 107 + } 108 + 109 + static void psp_assoc_free_queue(struct rcu_head *head) 110 + { 111 + struct psp_assoc *pas = container_of(head, struct psp_assoc, rcu); 112 + 113 + INIT_WORK(&pas->work, psp_assoc_free); 114 + schedule_work(&pas->work); 115 + } 116 + 117 + /** 118 + * psp_assoc_put() - release a reference on a PSP association 119 + * @pas: association to release 120 + */ 121 + void psp_assoc_put(struct psp_assoc *pas) 122 + { 123 + if (pas && refcount_dec_and_test(&pas->refcnt)) 124 + call_rcu(&pas->rcu, psp_assoc_free_queue); 125 + } 126 + 127 + void psp_sk_assoc_free(struct sock *sk) 128 + { 129 + struct psp_assoc *pas = rcu_dereference_protected(sk->psp_assoc, 1); 130 + 131 + rcu_assign_pointer(sk->psp_assoc, NULL); 132 + psp_assoc_put(pas); 133 + } 134 + 135 + int psp_sock_assoc_set_rx(struct sock *sk, struct psp_assoc *pas, 136 + struct psp_key_parsed *key, 137 + struct netlink_ext_ack *extack) 138 + { 139 + int err; 140 + 141 + memcpy(&pas->rx, key, sizeof(*key)); 142 + 143 + lock_sock(sk); 144 + 145 + if (psp_sk_assoc(sk)) { 146 + NL_SET_ERR_MSG(extack, "Socket already has PSP state"); 147 + err = -EBUSY; 148 + goto exit_unlock; 149 + } 150 + 151 + refcount_inc(&pas->refcnt); 152 + rcu_assign_pointer(sk->psp_assoc, pas); 153 + err = 0; 154 + 155 + exit_unlock: 156 + release_sock(sk); 157 + 158 + return err; 159 + } 160 + 161 + static int psp_sock_recv_queue_check(struct sock *sk, struct psp_assoc *pas) 162 + { 163 + struct psp_skb_ext *pse; 164 + struct sk_buff *skb; 165 + 166 + skb_rbtree_walk(skb, &tcp_sk(sk)->out_of_order_queue) { 167 + pse = skb_ext_find(skb, SKB_EXT_PSP); 168 + if (!psp_pse_matches_pas(pse, pas)) 169 + return -EBUSY; 170 + } 171 + 172 + skb_queue_walk(&sk->sk_receive_queue, skb) { 173 + pse = skb_ext_find(skb, SKB_EXT_PSP); 174 + if (!psp_pse_matches_pas(pse, pas)) 175 + return -EBUSY; 176 + } 177 + return 0; 178 + } 179 + 180 + int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, 181 + u32 version, struct psp_key_parsed *key, 182 + struct netlink_ext_ack *extack) 183 + { 184 + struct inet_connection_sock *icsk; 185 + struct psp_assoc *pas, *dummy; 186 + int err; 187 + 188 + lock_sock(sk); 189 + 190 + pas = psp_sk_assoc(sk); 191 + if (!pas) { 192 + NL_SET_ERR_MSG(extack, "Socket has no Rx key"); 193 + err = -EINVAL; 194 + goto exit_unlock; 195 + } 196 + if (pas->psd != psd) { 197 + NL_SET_ERR_MSG(extack, "Rx key from different device"); 198 + err = -EINVAL; 199 + goto exit_unlock; 200 + } 201 + if (pas->version != version) { 202 + NL_SET_ERR_MSG(extack, 203 + "PSP version mismatch with existing state"); 204 + err = -EINVAL; 205 + goto exit_unlock; 206 + } 207 + if (pas->tx.spi) { 208 + NL_SET_ERR_MSG(extack, "Tx key already set"); 209 + err = -EBUSY; 210 + goto exit_unlock; 211 + } 212 + 213 + err = psp_sock_recv_queue_check(sk, pas); 214 + if (err) { 215 + NL_SET_ERR_MSG(extack, "Socket has incompatible segments already in the recv queue"); 216 + goto exit_unlock; 217 + } 218 + 219 + /* Pass a fake association to drivers to make sure they don't 220 + * try to store pointers to it. For re-keying we'll need to 221 + * re-allocate the assoc structures. 222 + */ 223 + dummy = psp_assoc_dummy(pas); 224 + if (!dummy) { 225 + err = -ENOMEM; 226 + goto exit_unlock; 227 + } 228 + 229 + memcpy(&dummy->tx, key, sizeof(*key)); 230 + err = psp_dev_tx_key_add(psd, dummy, extack); 231 + if (err) 232 + goto exit_free_dummy; 233 + 234 + memcpy(pas->drv_data, dummy->drv_data, psd->caps->assoc_drv_spc); 235 + memcpy(&pas->tx, key, sizeof(*key)); 236 + 237 + WRITE_ONCE(sk->sk_validate_xmit_skb, psp_validate_xmit); 238 + tcp_write_collapse_fence(sk); 239 + pas->upgrade_seq = tcp_sk(sk)->rcv_nxt; 240 + 241 + icsk = inet_csk(sk); 242 + icsk->icsk_ext_hdr_len += psp_sk_overhead(sk); 243 + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 244 + 245 + exit_free_dummy: 246 + kfree(dummy); 247 + exit_unlock: 248 + release_sock(sk); 249 + return err; 250 + } 251 + 252 + void psp_assocs_key_rotated(struct psp_dev *psd) 253 + { 254 + struct psp_assoc *pas, *next; 255 + 256 + /* Mark the stale associations as invalid, they will no longer 257 + * be able to Rx any traffic. 258 + */ 259 + list_for_each_entry_safe(pas, next, &psd->prev_assocs, assocs_list) 260 + pas->generation |= ~PSP_GEN_VALID_MASK; 261 + list_splice_init(&psd->prev_assocs, &psd->stale_assocs); 262 + list_splice_init(&psd->active_assocs, &psd->prev_assocs); 263 + 264 + /* TODO: we should inform the sockets that got shut down */ 265 + } 266 + 267 + void psp_twsk_init(struct inet_timewait_sock *tw, const struct sock *sk) 268 + { 269 + struct psp_assoc *pas = psp_sk_assoc(sk); 270 + 271 + if (pas) 272 + refcount_inc(&pas->refcnt); 273 + rcu_assign_pointer(tw->psp_assoc, pas); 274 + tw->tw_validate_xmit_skb = psp_validate_xmit; 275 + } 276 + 277 + void psp_twsk_assoc_free(struct inet_timewait_sock *tw) 278 + { 279 + struct psp_assoc *pas = rcu_dereference_protected(tw->psp_assoc, 1); 280 + 281 + rcu_assign_pointer(tw->psp_assoc, NULL); 282 + psp_assoc_put(pas); 283 + } 284 + 285 + void psp_reply_set_decrypted(struct sk_buff *skb) 286 + { 287 + struct psp_assoc *pas; 288 + 289 + rcu_read_lock(); 290 + pas = psp_sk_get_assoc_rcu(skb->sk); 291 + if (pas && pas->tx.spi) 292 + skb->decrypted = 1; 293 + rcu_read_unlock(); 294 + } 295 + EXPORT_IPV6_MOD_GPL(psp_reply_set_decrypted);
+1
tools/net/ynl/Makefile.deps
··· 31 31 CFLAGS_ovs_datapath:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h) 32 32 CFLAGS_ovs_flow:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h) 33 33 CFLAGS_ovs_vport:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h) 34 + CFLAGS_psp:=$(call get_hdr_inc,_LINUX_PSP_H,psp.h) 34 35 CFLAGS_rt-addr:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ 35 36 $(call get_hdr_inc,__LINUX_IF_ADDR_H,if_addr.h) 36 37 CFLAGS_rt-link:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \