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

psp: base PSP device support

Add a netlink family for PSP and allow drivers to register support.

The "PSP device" is its own object. This allows us to perform more
flexible reference counting / lifetime control than if PSP information
was part of net_device. In the future we should also be able
to "delegate" PSP access to software devices, such as *vlan, veth
or netkit more easily.

Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250917000954.859376-3-daniel.zahka@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Jakub Kicinski and committed by
Paolo Abeni
00c94ca2 a9266275

+777
+96
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 + operations: 43 + list: 44 + - 45 + name: dev-get 46 + doc: Get / dump information about PSP capable devices on the system. 47 + attribute-set: dev 48 + do: 49 + request: 50 + attributes: 51 + - id 52 + reply: &dev-all 53 + attributes: 54 + - id 55 + - ifindex 56 + - psp-versions-cap 57 + - psp-versions-ena 58 + pre: psp-device-get-locked 59 + post: psp-device-unlock 60 + dump: 61 + reply: *dev-all 62 + - 63 + name: dev-add-ntf 64 + doc: Notification about device appearing. 65 + notify: dev-get 66 + mcgrp: mgmt 67 + - 68 + name: dev-del-ntf 69 + doc: Notification about device disappearing. 70 + notify: dev-get 71 + mcgrp: mgmt 72 + - 73 + name: dev-set 74 + doc: Set the configuration of a PSP device. 75 + attribute-set: dev 76 + do: 77 + request: 78 + attributes: 79 + - id 80 + - psp-versions-ena 81 + reply: 82 + attributes: [] 83 + pre: psp-device-get-locked 84 + post: psp-device-unlock 85 + - 86 + name: dev-change-ntf 87 + doc: Notification about device configuration being changed. 88 + notify: dev-get 89 + mcgrp: mgmt 90 + 91 + mcast-groups: 92 + list: 93 + - 94 + name: mgmt 95 + 96 + ...
+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 /*
+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 */
+14
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 <net/psp/types.h> 7 + 8 + /* Driver-facing API */ 9 + struct psp_dev * 10 + psp_dev_create(struct net_device *netdev, struct psp_dev_ops *psd_ops, 11 + struct psp_dev_caps *psd_caps, void *priv_ptr); 12 + void psp_dev_unregister(struct psp_dev *psd); 13 + 14 + #endif /* __NET_PSP_HELPERS_H */
+100
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_SPI_KEY_ID GENMASK(30, 0) 24 + #define PSP_SPI_KEY_PHASE BIT(31) 25 + 26 + #define PSPHDR_CRYPT_OFFSET GENMASK(5, 0) 27 + 28 + #define PSPHDR_VERFL_SAMPLE BIT(7) 29 + #define PSPHDR_VERFL_DROP BIT(6) 30 + #define PSPHDR_VERFL_VERSION GENMASK(5, 2) 31 + #define PSPHDR_VERFL_VIRT BIT(1) 32 + #define PSPHDR_VERFL_ONE BIT(0) 33 + 34 + #define PSP_HDRLEN_NOOPT ((sizeof(struct psphdr) - 8) / 8) 35 + 36 + /** 37 + * struct psp_dev_config - PSP device configuration 38 + * @versions: PSP versions enabled on the device 39 + */ 40 + struct psp_dev_config { 41 + u32 versions; 42 + }; 43 + 44 + /** 45 + * struct psp_dev - PSP device struct 46 + * @main_netdev: original netdevice of this PSP device 47 + * @ops: driver callbacks 48 + * @caps: device capabilities 49 + * @drv_priv: driver priv pointer 50 + * @lock: instance lock, protects all fields 51 + * @refcnt: reference count for the instance 52 + * @id: instance id 53 + * @config: current device configuration 54 + * 55 + * @rcu: RCU head for freeing the structure 56 + */ 57 + struct psp_dev { 58 + struct net_device *main_netdev; 59 + 60 + struct psp_dev_ops *ops; 61 + struct psp_dev_caps *caps; 62 + void *drv_priv; 63 + 64 + struct mutex lock; 65 + refcount_t refcnt; 66 + 67 + u32 id; 68 + 69 + struct psp_dev_config config; 70 + 71 + struct rcu_head rcu; 72 + }; 73 + 74 + /** 75 + * struct psp_dev_caps - PSP device capabilities 76 + */ 77 + struct psp_dev_caps { 78 + /** 79 + * @versions: mask of supported PSP versions 80 + * Set this field to 0 to indicate PSP is not supported at all. 81 + */ 82 + u32 versions; 83 + }; 84 + 85 + #define PSP_MAX_KEY 32 86 + 87 + /** 88 + * struct psp_dev_ops - netdev driver facing PSP callbacks 89 + */ 90 + struct psp_dev_ops { 91 + /** 92 + * @set_config: set configuration of a PSP device 93 + * Driver can inspect @psd->config for the previous configuration. 94 + * Core will update @psd->config with @config on success. 95 + */ 96 + int (*set_config)(struct psp_dev *psd, struct psp_dev_config *conf, 97 + struct netlink_ext_ack *extack); 98 + }; 99 + 100 + #endif /* __NET_PSP_H */
+42
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_CMD_DEV_GET = 1, 31 + PSP_CMD_DEV_ADD_NTF, 32 + PSP_CMD_DEV_DEL_NTF, 33 + PSP_CMD_DEV_SET, 34 + PSP_CMD_DEV_CHANGE_NTF, 35 + 36 + __PSP_CMD_MAX, 37 + PSP_CMD_MAX = (__PSP_CMD_MAX - 1) 38 + }; 39 + 40 + #define PSP_MCGRP_MGMT "mgmt" 41 + 42 + #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/
+13
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 + help 9 + Enable kernel support for the PSP protocol. 10 + For more information see: 11 + https://raw.githubusercontent.com/google/psp/main/doc/PSP_Arch_Spec.pdf 12 + 13 + 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-nl-gen.o
+65
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 + /* PSP_CMD_DEV_GET - do */ 14 + static const struct nla_policy psp_dev_get_nl_policy[PSP_A_DEV_ID + 1] = { 15 + [PSP_A_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 16 + }; 17 + 18 + /* PSP_CMD_DEV_SET - do */ 19 + static const struct nla_policy psp_dev_set_nl_policy[PSP_A_DEV_PSP_VERSIONS_ENA + 1] = { 20 + [PSP_A_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), 21 + [PSP_A_DEV_PSP_VERSIONS_ENA] = NLA_POLICY_MASK(NLA_U32, 0xf), 22 + }; 23 + 24 + /* Ops table for psp */ 25 + static const struct genl_split_ops psp_nl_ops[] = { 26 + { 27 + .cmd = PSP_CMD_DEV_GET, 28 + .pre_doit = psp_device_get_locked, 29 + .doit = psp_nl_dev_get_doit, 30 + .post_doit = psp_device_unlock, 31 + .policy = psp_dev_get_nl_policy, 32 + .maxattr = PSP_A_DEV_ID, 33 + .flags = GENL_CMD_CAP_DO, 34 + }, 35 + { 36 + .cmd = PSP_CMD_DEV_GET, 37 + .dumpit = psp_nl_dev_get_dumpit, 38 + .flags = GENL_CMD_CAP_DUMP, 39 + }, 40 + { 41 + .cmd = PSP_CMD_DEV_SET, 42 + .pre_doit = psp_device_get_locked, 43 + .doit = psp_nl_dev_set_doit, 44 + .post_doit = psp_device_unlock, 45 + .policy = psp_dev_set_nl_policy, 46 + .maxattr = PSP_A_DEV_PSP_VERSIONS_ENA, 47 + .flags = GENL_CMD_CAP_DO, 48 + }, 49 + }; 50 + 51 + static const struct genl_multicast_group psp_nl_mcgrps[] = { 52 + [PSP_NLGRP_MGMT] = { "mgmt", }, 53 + }; 54 + 55 + struct genl_family psp_nl_family __ro_after_init = { 56 + .name = PSP_FAMILY_NAME, 57 + .version = PSP_FAMILY_VERSION, 58 + .netnsok = true, 59 + .parallel_ops = true, 60 + .module = THIS_MODULE, 61 + .split_ops = psp_nl_ops, 62 + .n_split_ops = ARRAY_SIZE(psp_nl_ops), 63 + .mcgrps = psp_nl_mcgrps, 64 + .n_mcgrps = ARRAY_SIZE(psp_nl_mcgrps), 65 + };
+30
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 + int psp_device_get_locked(const struct genl_split_ops *ops, 15 + struct sk_buff *skb, struct genl_info *info); 16 + void 17 + psp_device_unlock(const struct genl_split_ops *ops, struct sk_buff *skb, 18 + struct genl_info *info); 19 + 20 + int psp_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info); 21 + int psp_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb); 22 + int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info); 23 + 24 + enum { 25 + PSP_NLGRP_MGMT, 26 + }; 27 + 28 + extern struct genl_family psp_nl_family; 29 + 30 + #endif /* _LINUX_PSP_GEN_H */
+31
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/mutex.h> 8 + #include <net/netns/generic.h> 9 + #include <net/psp.h> 10 + #include <net/sock.h> 11 + 12 + extern struct xarray psp_devs; 13 + extern struct mutex psp_devs_lock; 14 + 15 + void psp_dev_destroy(struct psp_dev *psd); 16 + int psp_dev_check_access(struct psp_dev *psd, struct net *net); 17 + 18 + void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd); 19 + 20 + static inline void psp_dev_get(struct psp_dev *psd) 21 + { 22 + refcount_inc(&psd->refcnt); 23 + } 24 + 25 + static inline void psp_dev_put(struct psp_dev *psd) 26 + { 27 + if (refcount_dec_and_test(&psd->refcnt)) 28 + psp_dev_destroy(psd); 29 + } 30 + 31 + #endif /* __PSP_PSP_H */
+139
net/psp/psp_main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/list.h> 4 + #include <linux/netdevice.h> 5 + #include <linux/xarray.h> 6 + #include <net/net_namespace.h> 7 + #include <net/psp.h> 8 + 9 + #include "psp.h" 10 + #include "psp-nl-gen.h" 11 + 12 + DEFINE_XARRAY_ALLOC1(psp_devs); 13 + struct mutex psp_devs_lock; 14 + 15 + /** 16 + * DOC: PSP locking 17 + * 18 + * psp_devs_lock protects the psp_devs xarray. 19 + * Ordering is take the psp_devs_lock and then the instance lock. 20 + * Each instance is protected by RCU, and has a refcount. 21 + * When driver unregisters the instance gets flushed, but struct sticks around. 22 + */ 23 + 24 + /** 25 + * psp_dev_check_access() - check if user in a given net ns can access PSP dev 26 + * @psd: PSP device structure user is trying to access 27 + * @net: net namespace user is in 28 + * 29 + * Return: 0 if PSP device should be visible in @net, errno otherwise. 30 + */ 31 + int psp_dev_check_access(struct psp_dev *psd, struct net *net) 32 + { 33 + if (dev_net(psd->main_netdev) == net) 34 + return 0; 35 + return -ENOENT; 36 + } 37 + 38 + /** 39 + * psp_dev_create() - create and register PSP device 40 + * @netdev: main netdevice 41 + * @psd_ops: driver callbacks 42 + * @psd_caps: device capabilities 43 + * @priv_ptr: back-pointer to driver private data 44 + * 45 + * Return: pointer to allocated PSP device, or ERR_PTR. 46 + */ 47 + struct psp_dev * 48 + psp_dev_create(struct net_device *netdev, 49 + struct psp_dev_ops *psd_ops, struct psp_dev_caps *psd_caps, 50 + void *priv_ptr) 51 + { 52 + struct psp_dev *psd; 53 + static u32 last_id; 54 + int err; 55 + 56 + if (WARN_ON(!psd_caps->versions || 57 + !psd_ops->set_config)) 58 + return ERR_PTR(-EINVAL); 59 + 60 + psd = kzalloc(sizeof(*psd), GFP_KERNEL); 61 + if (!psd) 62 + return ERR_PTR(-ENOMEM); 63 + 64 + psd->main_netdev = netdev; 65 + psd->ops = psd_ops; 66 + psd->caps = psd_caps; 67 + psd->drv_priv = priv_ptr; 68 + 69 + mutex_init(&psd->lock); 70 + refcount_set(&psd->refcnt, 1); 71 + 72 + mutex_lock(&psp_devs_lock); 73 + err = xa_alloc_cyclic(&psp_devs, &psd->id, psd, xa_limit_16b, 74 + &last_id, GFP_KERNEL); 75 + if (err) { 76 + mutex_unlock(&psp_devs_lock); 77 + kfree(psd); 78 + return ERR_PTR(err); 79 + } 80 + mutex_lock(&psd->lock); 81 + mutex_unlock(&psp_devs_lock); 82 + 83 + psp_nl_notify_dev(psd, PSP_CMD_DEV_ADD_NTF); 84 + 85 + rcu_assign_pointer(netdev->psp_dev, psd); 86 + 87 + mutex_unlock(&psd->lock); 88 + 89 + return psd; 90 + } 91 + EXPORT_SYMBOL(psp_dev_create); 92 + 93 + void psp_dev_destroy(struct psp_dev *psd) 94 + { 95 + mutex_lock(&psp_devs_lock); 96 + xa_erase(&psp_devs, psd->id); 97 + mutex_unlock(&psp_devs_lock); 98 + 99 + mutex_destroy(&psd->lock); 100 + kfree_rcu(psd, rcu); 101 + } 102 + 103 + /** 104 + * psp_dev_unregister() - unregister PSP device 105 + * @psd: PSP device structure 106 + */ 107 + void psp_dev_unregister(struct psp_dev *psd) 108 + { 109 + mutex_lock(&psp_devs_lock); 110 + mutex_lock(&psd->lock); 111 + 112 + psp_nl_notify_dev(psd, PSP_CMD_DEV_DEL_NTF); 113 + 114 + /* Wait until psp_dev_destroy() to call xa_erase() to prevent a 115 + * different psd from being added to the xarray with this id, while 116 + * there are still references to this psd being held. 117 + */ 118 + xa_store(&psp_devs, psd->id, NULL, GFP_KERNEL); 119 + mutex_unlock(&psp_devs_lock); 120 + 121 + rcu_assign_pointer(psd->main_netdev->psp_dev, NULL); 122 + 123 + psd->ops = NULL; 124 + psd->drv_priv = NULL; 125 + 126 + mutex_unlock(&psd->lock); 127 + 128 + psp_dev_put(psd); 129 + } 130 + EXPORT_SYMBOL(psp_dev_unregister); 131 + 132 + static int __init psp_init(void) 133 + { 134 + mutex_init(&psp_devs_lock); 135 + 136 + return genl_register_family(&psp_nl_family); 137 + } 138 + 139 + subsys_initcall(psp_init);
+223
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 psp_dev *psd = info->user_ptr[0]; 83 + 84 + mutex_unlock(&psd->lock); 85 + } 86 + 87 + static int 88 + psp_nl_dev_fill(struct psp_dev *psd, struct sk_buff *rsp, 89 + const struct genl_info *info) 90 + { 91 + void *hdr; 92 + 93 + hdr = genlmsg_iput(rsp, info); 94 + if (!hdr) 95 + return -EMSGSIZE; 96 + 97 + if (nla_put_u32(rsp, PSP_A_DEV_ID, psd->id) || 98 + nla_put_u32(rsp, PSP_A_DEV_IFINDEX, psd->main_netdev->ifindex) || 99 + nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_CAP, psd->caps->versions) || 100 + nla_put_u32(rsp, PSP_A_DEV_PSP_VERSIONS_ENA, psd->config.versions)) 101 + goto err_cancel_msg; 102 + 103 + genlmsg_end(rsp, hdr); 104 + return 0; 105 + 106 + err_cancel_msg: 107 + genlmsg_cancel(rsp, hdr); 108 + return -EMSGSIZE; 109 + } 110 + 111 + void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd) 112 + { 113 + struct genl_info info; 114 + struct sk_buff *ntf; 115 + 116 + if (!genl_has_listeners(&psp_nl_family, dev_net(psd->main_netdev), 117 + PSP_NLGRP_MGMT)) 118 + return; 119 + 120 + ntf = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 121 + if (!ntf) 122 + return; 123 + 124 + genl_info_init_ntf(&info, &psp_nl_family, cmd); 125 + if (psp_nl_dev_fill(psd, ntf, &info)) { 126 + nlmsg_free(ntf); 127 + return; 128 + } 129 + 130 + genlmsg_multicast_netns(&psp_nl_family, dev_net(psd->main_netdev), ntf, 131 + 0, PSP_NLGRP_MGMT, GFP_KERNEL); 132 + } 133 + 134 + int psp_nl_dev_get_doit(struct sk_buff *req, struct genl_info *info) 135 + { 136 + struct psp_dev *psd = info->user_ptr[0]; 137 + struct sk_buff *rsp; 138 + int err; 139 + 140 + rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 141 + if (!rsp) 142 + return -ENOMEM; 143 + 144 + err = psp_nl_dev_fill(psd, rsp, info); 145 + if (err) 146 + goto err_free_msg; 147 + 148 + return genlmsg_reply(rsp, info); 149 + 150 + err_free_msg: 151 + nlmsg_free(rsp); 152 + return err; 153 + } 154 + 155 + static int 156 + psp_nl_dev_get_dumpit_one(struct sk_buff *rsp, struct netlink_callback *cb, 157 + struct psp_dev *psd) 158 + { 159 + if (psp_dev_check_access(psd, sock_net(rsp->sk))) 160 + return 0; 161 + 162 + return psp_nl_dev_fill(psd, rsp, genl_info_dump(cb)); 163 + } 164 + 165 + int psp_nl_dev_get_dumpit(struct sk_buff *rsp, struct netlink_callback *cb) 166 + { 167 + struct psp_dev *psd; 168 + int err = 0; 169 + 170 + mutex_lock(&psp_devs_lock); 171 + xa_for_each_start(&psp_devs, cb->args[0], psd, cb->args[0]) { 172 + mutex_lock(&psd->lock); 173 + err = psp_nl_dev_get_dumpit_one(rsp, cb, psd); 174 + mutex_unlock(&psd->lock); 175 + if (err) 176 + break; 177 + } 178 + mutex_unlock(&psp_devs_lock); 179 + 180 + return err; 181 + } 182 + 183 + int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info) 184 + { 185 + struct psp_dev *psd = info->user_ptr[0]; 186 + struct psp_dev_config new_config; 187 + struct sk_buff *rsp; 188 + int err; 189 + 190 + memcpy(&new_config, &psd->config, sizeof(new_config)); 191 + 192 + if (info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA]) { 193 + new_config.versions = 194 + nla_get_u32(info->attrs[PSP_A_DEV_PSP_VERSIONS_ENA]); 195 + if (new_config.versions & ~psd->caps->versions) { 196 + NL_SET_ERR_MSG(info->extack, "Requested PSP versions not supported by the device"); 197 + return -EINVAL; 198 + } 199 + } else { 200 + NL_SET_ERR_MSG(info->extack, "No settings present"); 201 + return -EINVAL; 202 + } 203 + 204 + rsp = psp_nl_reply_new(info); 205 + if (!rsp) 206 + return -ENOMEM; 207 + 208 + if (memcmp(&new_config, &psd->config, sizeof(new_config))) { 209 + err = psd->ops->set_config(psd, &new_config, info->extack); 210 + if (err) 211 + goto err_free_rsp; 212 + 213 + memcpy(&psd->config, &new_config, sizeof(new_config)); 214 + } 215 + 216 + psp_nl_notify_dev(psd, PSP_CMD_DEV_CHANGE_NTF); 217 + 218 + return psp_nl_reply_send(rsp, info); 219 + 220 + err_free_rsp: 221 + nlmsg_free(rsp); 222 + return err; 223 + }
+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) \