Netdev List
 help / color / mirror / Atom feed
* [PATCH iproute2-next 0/3] tc: add the psp action and flower psp matches
@ 2026-11-12  0:15 Todd Freed
  2026-11-12  0:15 ` [PATCH iproute2-next 1/3] uapi: add the tc psp action and flower psp keys Todd Freed
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Todd Freed @ 2026-11-12  0:15 UTC (permalink / raw)
  To: netdev, toddfreed
  Cc: David Ahern, Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko,
	Daniel Zahka, Willem de Bruijn, Jakub Kicinski, linux-kselftest

this adds tc support for socket-less psp associations, from the net-next
series:

  https://lore.kernel.org/netdev/20261111005533.6436-1-toddfreed@meta.com

 - the psp action: attach a psp tx association to a packet, for the psp
   device to encrypt on transmit (encap), or remove the psp rx state of a
   packet the device decrypted (decap).
 - flower matches on that rx state: psp_spi, psp_ver and psp_dev.

the selftests in the kernel series, drivers/net psp.py and tc-testing
psp.json, use them.

the kernel series isn't merged yet. patch 1 copies its uapi headers, so
that this builds and can be tested with it; it can be replaced by the
regular header sync once the kernel series is merged.

testing: with the kernel series on netdevsim, drivers/net psp.py (57
tests) and tc-testing psp.json (17 tests) pass with this tc.

Todd Freed (3):
  uapi: add the tc psp action and flower psp keys
  tc: add the psp action
  tc: flower: add matches psp_spi, psp_ver and psp_dev

 include/uapi/linux/pkt_cls.h       |   6 ++
 include/uapi/linux/tc_act/tc_psp.h |  28 +++++
 man/man8/tc-flower.8               |  29 +++++
 man/man8/tc-psp.8                  |  90 ++++++++++++++++
 tc/Makefile                        |   1 +
 tc/f_flower.c                      |  71 ++++++++++++
 tc/m_psp.c                         | 166 +++++++++++++++++++++++++++++
 7 files changed, 391 insertions(+)
 create mode 100644 include/uapi/linux/tc_act/tc_psp.h
 create mode 100644 man/man8/tc-psp.8
 create mode 100644 tc/m_psp.c


base-commit: 204a721033556114c81c47d00375f2d52e98e463
--
2.53.0-Meta


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH iproute2-next 1/3] uapi: add the tc psp action and flower psp keys
  2026-11-12  0:15 [PATCH iproute2-next 0/3] tc: add the psp action and flower psp matches Todd Freed
@ 2026-11-12  0:15 ` Todd Freed
  2026-11-12  0:15 ` [PATCH iproute2-next 2/3] tc: add the psp action Todd Freed
  2026-11-12  0:15 ` [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev Todd Freed
  2 siblings, 0 replies; 8+ messages in thread
From: Todd Freed @ 2026-11-12  0:15 UTC (permalink / raw)
  To: netdev, toddfreed
  Cc: David Ahern, Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko,
	Daniel Zahka, Willem de Bruijn, Jakub Kicinski, linux-kselftest

The tc psp action (TCA_ID_PSP, tc_act/tc_psp.h) and the flower psp
matches (TCA_FLOWER_KEY_PSP_SPI, _SPI_MASK, _VERSION, _DEV), as added by
the net-next socket-less psp series.

To be replaced by the regular header sync once that is merged.

Signed-off-by: Todd Freed <toddfreed@meta.com>
---
 include/uapi/linux/pkt_cls.h       |  6 ++++++
 include/uapi/linux/tc_act/tc_psp.h | 28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 include/uapi/linux/tc_act/tc_psp.h

diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 3c24e8e2880b..b98d9aaebc31 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -139,6 +139,7 @@ enum tca_id {
 	TCA_ID_MPLS,
 	TCA_ID_CT,
 	TCA_ID_GATE,
+	TCA_ID_PSP,
 	/* other actions go here */
 	__TCA_ID_MAX = 255
 };
@@ -560,6 +561,11 @@ enum {
 	TCA_FLOWER_KEY_ENC_FLAGS,	/* be32 */
 	TCA_FLOWER_KEY_ENC_FLAGS_MASK,	/* be32 */
 
+	TCA_FLOWER_KEY_PSP_SPI,		/* be32 */
+	TCA_FLOWER_KEY_PSP_SPI_MASK,	/* be32 */
+	TCA_FLOWER_KEY_PSP_VERSION,	/* u8, enum psp_version */
+	TCA_FLOWER_KEY_PSP_DEV,		/* u32, PSP device ID */
+
 	__TCA_FLOWER_MAX,
 };
 
diff --git a/include/uapi/linux/tc_act/tc_psp.h b/include/uapi/linux/tc_act/tc_psp.h
new file mode 100644
index 000000000000..e58ebcae77be
--- /dev/null
+++ b/include/uapi/linux/tc_act/tc_psp.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_TC_PSP_H
+#define __LINUX_TC_PSP_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_PSP_ACT_ENCAP	1	/* attach a PSP association */
+#define TCA_PSP_ACT_DECAP	2	/* drop PSP Rx state */
+
+struct tc_psp {
+	tc_gen;
+};
+
+enum {
+	TCA_PSP_UNSPEC,
+	TCA_PSP_TM,
+	TCA_PSP_PARMS,
+	TCA_PSP_PAD,
+	TCA_PSP_ACTION,		/* u32, TCA_PSP_ACT_* */
+	TCA_PSP_ASSOC_ID,	/* u32, encap only: Tx association ID from
+				 * the PSP netlink family (assoc-add)
+				 */
+	__TCA_PSP_MAX,
+};
+
+#define TCA_PSP_MAX (__TCA_PSP_MAX - 1)
+
+#endif
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH iproute2-next 2/3] tc: add the psp action
  2026-11-12  0:15 [PATCH iproute2-next 0/3] tc: add the psp action and flower psp matches Todd Freed
  2026-11-12  0:15 ` [PATCH iproute2-next 1/3] uapi: add the tc psp action and flower psp keys Todd Freed
@ 2026-11-12  0:15 ` Todd Freed
  2026-11-12  1:05   ` Stephen Hemminger
  2026-11-12  0:15 ` [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev Todd Freed
  2 siblings, 1 reply; 8+ messages in thread
From: Todd Freed @ 2026-11-12  0:15 UTC (permalink / raw)
  To: netdev, toddfreed
  Cc: David Ahern, Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko,
	Daniel Zahka, Willem de Bruijn, Jakub Kicinski, linux-kselftest

The psp action applies PSP (PSP Security Protocol) encap and encryption
to packets, separately from psp socket offload:

  psp encap assoc ASSOC_ID   attach a PSP Tx association, created with
                             assoc-add over the PSP netlink family; the
                             association's device encrypts the packet
                             on transmit
  psp decap                  remove the PSP Rx state of a packet the
                             PSP device decrypted

decap takes no association. To take only those packets which belong to a
single rx-spi-alloc call, a rule applies the corresponding flower psp_spi,
psp_ver and psp_dev matches.

In JSON, the verb is psp_action. The action is documented in tc-psp(8).

Signed-off-by: Todd Freed <toddfreed@meta.com>
---
 man/man8/tc-psp.8 |  90 +++++++++++++++++++++++++
 tc/Makefile       |   1 +
 tc/m_psp.c        | 166 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 257 insertions(+)
 create mode 100644 man/man8/tc-psp.8
 create mode 100644 tc/m_psp.c

diff --git a/man/man8/tc-psp.8 b/man/man8/tc-psp.8
new file mode 100644
index 000000000000..4973bbbe05fa
--- /dev/null
+++ b/man/man8/tc-psp.8
@@ -0,0 +1,90 @@
+.TH "PSP action in tc" 8 "9 Nov 2026" "iproute2" "Linux"
+
+.SH NAME
+psp - PSP transport mode action
+.SH SYNOPSIS
+.in +8
+.ti -8
+.BR tc " ... " "action psp" " { "
+.BI "encap assoc" " ASSOC_ID"
+.RB " | " decap " } [ "
+.IR CONTROL " ] [ "
+.BI index " INDEX"
+.RB " ]"
+
+.ti -8
+.IR CONTROL " := { "
+.BR reclassify " | " pipe " | " drop " | " continue " | " pass " | " goto " " chain " " CHAIN_INDEX " }"
+.SH DESCRIPTION
+The
+.B psp
+action applies PSP (PSP Security Protocol) encapsulation to packets using keys from the PSP netlink
+family: Rx SPIs and their keys from rx-spi-alloc, and Tx associations from assoc-add (assoc-get,
+assoc-del). The PSP device encrypts and decrypts the packets.
+.SH OPTIONS
+.TP
+.BI "encap assoc" " ASSOC_ID"
+Attach the Tx association
+.IR ASSOC_ID ,
+created with the PSP netlink
+.B assoc-add
+command, to the packet. The packet must then be transmitted on the netdev of
+the association's PSP device, which encrypts it: encap on that netdev's egress,
+or on another netdev's egress followed by a redirect to it
+.RB ( "mirred egress redirect" ).
+If it reaches another device the packet is dropped. In software, encap runs on
+egress only: encap on ingress is hardware offload only
+.RB ( skip_sw ),
+and in software the action drops the packet.
+.TP
+.B decap
+Remove the PSP Rx state of a packet which the PSP device decrypted, so that
+it can be forwarded. It takes no association. To take only the packets
+corresponding to one rx-spi-alloc, match packets with the
+.BR flower " keys " psp_spi ", " psp_ver " and " psp_dev .
+.IP
+An SPI from
+.B rx-spi-alloc
+is valid until the PSP device's key has been rotated twice. After that, the
+device can allocate the same SPI value again, and a rule which still matches it
+takes the packets of the new allocation. Delete such rules before the second
+key rotation after the allocation; the PSP netlink family notifies each key
+rotation
+.RB ( key-rotate-ntf ).
+.TP
+.I CONTROL
+How to continue after this action, see
+.BR tc-actions (8).
+The default is
+.BR pipe .
+.TP
+.BI index " INDEX"
+Use the action of index
+.IR INDEX ,
+to create it, or to reference an existing one.
+.SH EXAMPLES
+Encrypt the packets to 2001:db8::2 with Tx association 3, of the PSP device
+of eth0:
+
+.RS
+.EX
+tc filter add dev eth0 egress protocol ipv6 flower dst_ip 2001:db8::2 \\
+	action psp encap assoc 3
+.EE
+.RE
+
+Take the packets which eth0's PSP device (ID 1) decrypted with an SPI from
+rx-spi-alloc, and remove their PSP state:
+
+.RS
+.EX
+tc filter add dev eth0 ingress protocol ipv6 flower \\
+	psp_spi 0x80000001 psp_ver 0 psp_dev 1 \\
+	action psp decap
+.EE
+.RE
+.SH SEE ALSO
+.BR tc (8),
+.BR tc-actions (8),
+.BR tc-flower (8),
+.BR tc-mirred (8)
diff --git a/tc/Makefile b/tc/Makefile
index 6264a772e686..f0b3ddb10155 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -49,6 +49,7 @@ TCMODULES += m_ctinfo.o
 TCMODULES += m_bpf.o
 TCMODULES += m_tunnel_key.o
 TCMODULES += m_sample.o
+TCMODULES += m_psp.o
 TCMODULES += m_ct.o
 TCMODULES += m_gate.o
 TCMODULES += p_ip.o
diff --git a/tc/m_psp.c b/tc/m_psp.c
new file mode 100644
index 000000000000..37ddff25ed14
--- /dev/null
+++ b/tc/m_psp.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * m_psp.c		PSP encryption action
+ */
+
+#include <stdio.h>
+#include "utils.h"
+#include "tc_util.h"
+#include "tc_common.h"
+#include <linux/tc_act/tc_psp.h>
+
+static void explain(void)
+{
+	fprintf(stderr,
+		"Usage: psp encap assoc ASSOC_ID [CONTROL] [index INDEX]\n"
+		"       psp decap [CONTROL] [index INDEX]\n"
+		"where:\n"
+		"\tASSOC_ID := ID of a Tx association, from PSP netlink assoc-add\n"
+		"\tdecap takes no association: match the packets with flower\n"
+		"\tpsp_spi, psp_ver and psp_dev\n"
+		"\tCONTROL := reclassify | pipe | drop | continue | pass |\n"
+		"\t           goto chain <CHAIN_INDEX>\n");
+}
+
+static void usage(void)
+{
+	explain();
+	exit(-1);
+}
+
+static int psp_set_action(__u32 *action, __u32 a)
+{
+	if (*action && *action != a) {
+		fprintf(stderr, "psp: only one of \"encap\" and \"decap\"\n");
+		return -1;
+	}
+	*action = a;
+	return 0;
+}
+
+static int parse_psp(const struct action_util *a, int *argc_p, char ***argv_p,
+		     int tca_id, struct nlmsghdr *n)
+{
+	struct tc_psp p = { 0 };
+	bool assoc_set = false;
+	__u32 action = 0;
+	char **argv = *argv_p;
+	struct rtattr *tail;
+	int argc = *argc_p;
+	__u32 assoc;
+
+	if (matches(*argv, "psp") != 0)
+		return -1;
+	NEXT_ARG();
+
+	while (argc > 0) {
+		if (matches(*argv, "encap") == 0) {
+			if (psp_set_action(&action, TCA_PSP_ACT_ENCAP))
+				return -1;
+		} else if (matches(*argv, "decap") == 0) {
+			if (psp_set_action(&action, TCA_PSP_ACT_DECAP))
+				return -1;
+		} else if (matches(*argv, "assoc") == 0) {
+			NEXT_ARG();
+			if (get_u32(&assoc, *argv, 0)) {
+				fprintf(stderr, "psp: Illegal \"assoc\"\n");
+				return -1;
+			}
+			assoc_set = true;
+		} else if (matches(*argv, "help") == 0) {
+			usage();
+		} else {
+			break;
+		}
+		NEXT_ARG_FWD();
+	}
+
+	parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
+
+	if (argc && matches(*argv, "index") == 0) {
+		NEXT_ARG();
+		if (get_u32(&p.index, *argv, 10)) {
+			fprintf(stderr, "psp: Illegal \"index\"\n");
+			return -1;
+		}
+		NEXT_ARG_FWD();
+	}
+
+	if (!p.index) {
+		if (!action) {
+			fprintf(stderr, "psp: \"encap\" or \"decap\" required\n");
+			usage();
+		}
+		if (action == TCA_PSP_ACT_ENCAP && !assoc_set) {
+			fprintf(stderr, "psp: \"encap\" requires \"assoc\"\n");
+			usage();
+		}
+	}
+
+	tail = addattr_nest(n, MAX_MSG, tca_id);
+	addattr_l(n, MAX_MSG, TCA_PSP_PARMS, &p, sizeof(p));
+	if (action)
+		addattr32(n, MAX_MSG, TCA_PSP_ACTION, action);
+	if (assoc_set)
+		addattr32(n, MAX_MSG, TCA_PSP_ASSOC_ID, assoc);
+	addattr_nest_end(n, tail);
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+}
+
+static int print_psp(const struct action_util *au, FILE *f, struct rtattr *arg)
+{
+	struct rtattr *tb[TCA_PSP_MAX + 1];
+	struct tc_psp *p;
+	__u32 action = 0;
+
+	print_string(PRINT_ANY, "kind", "%s ", "psp");
+	if (!arg)
+		return 0;
+
+	parse_rtattr_nested(tb, TCA_PSP_MAX, arg);
+	if (!tb[TCA_PSP_PARMS]) {
+		fprintf(stderr, "Missing psp parameters\n");
+		return -1;
+	}
+	p = RTA_DATA(tb[TCA_PSP_PARMS]);
+	if (tb[TCA_PSP_ACTION])
+		action = rta_getattr_u32(tb[TCA_PSP_ACTION]);
+
+	switch (action) {
+	case TCA_PSP_ACT_ENCAP:
+		print_string(PRINT_ANY, "psp_action", "%s", "encap");
+		break;
+	case TCA_PSP_ACT_DECAP:
+		print_string(PRINT_ANY, "psp_action", "%s", "decap");
+		break;
+	default:
+		print_uint(PRINT_ANY, "psp_action", "action %u", action);
+	}
+	if (tb[TCA_PSP_ASSOC_ID])
+		print_uint(PRINT_ANY, "assoc", " assoc %u",
+			   rta_getattr_u32(tb[TCA_PSP_ASSOC_ID]));
+
+	print_action_control(" ", p->action, "");
+
+	print_nl();
+	print_uint(PRINT_ANY, "index", "\t index %u", p->index);
+	print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
+	print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
+
+	if (show_stats && tb[TCA_PSP_TM]) {
+		struct tcf_t *tm = RTA_DATA(tb[TCA_PSP_TM]);
+
+		print_tm(tm);
+	}
+	print_nl();
+	return 0;
+}
+
+struct action_util psp_action_util = {
+	.id = "psp",
+	.parse_aopt = parse_psp,
+	.print_aopt = print_psp,
+};
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev
  2026-11-12  0:15 [PATCH iproute2-next 0/3] tc: add the psp action and flower psp matches Todd Freed
  2026-11-12  0:15 ` [PATCH iproute2-next 1/3] uapi: add the tc psp action and flower psp keys Todd Freed
  2026-11-12  0:15 ` [PATCH iproute2-next 2/3] tc: add the psp action Todd Freed
@ 2026-11-12  0:15 ` Todd Freed
  2026-11-12  1:06   ` Stephen Hemminger
  2 siblings, 1 reply; 8+ messages in thread
From: Todd Freed @ 2026-11-12  0:15 UTC (permalink / raw)
  To: netdev, toddfreed
  Cc: David Ahern, Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko,
	Daniel Zahka, Willem de Bruijn, Jakub Kicinski, linux-kselftest

Match on the PSP Rx state of a packet the device decrypted: the SPI it
was decrypted with (psp_spi, with an optional mask), the PSP version
(psp_ver), and the ID of the PSP device which decrypted it (psp_dev).

For example, to take the packets decrypted with one Rx SPI, from
rx-spi-alloc, and remove their PSP state:

  tc filter add dev eth0 ingress protocol ipv6 flower
      psp_spi 0x80000001 psp_ver 0 psp_dev 1
      action psp decap

These keys only match decrypted packets, even with a zero mask, so
"psp_spi 0/0" matches any decrypted PSP packet.

psp_spi and its mask are hexadecimal, like spi. tc-flower(8) documents
the keys.

Signed-off-by: Todd Freed <toddfreed@meta.com>
---
 man/man8/tc-flower.8 | 29 ++++++++++++++++++
 tc/f_flower.c        | 71 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+)

diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
index 3f8ba4656ef4..88881671c693 100644
--- a/man/man8/tc-flower.8
+++ b/man/man8/tc-flower.8
@@ -56,6 +56,12 @@ flower \- flow based traffic control filter
 .IR TTL " | "
 .B l2tpv3_sid
 .IR LSID " | "
+.B psp_spi
+.IR SPI "[/" MASK "] | "
+.B psp_ver
+.IR VERSION " | "
+.B psp_dev
+.IR PSP_DEV_ID " | "
 .BR ip_proto " { " tcp " | " udp " | " sctp " | " icmp " | " icmpv6 " | " l2tp " | "
 .IR IP_PROTO " } | "
 .B ip_tos
@@ -323,6 +329,29 @@ Match on L2TPv3 session id field transported over IPv4 or IPv6.
 .I LSID
 is an unsigned 32 bit value in decimal format.
 .TP
+.BI psp_spi " SPI[/MASK]"
+Match on the SPI which a PSP device decrypted the packet with.
+.I SPI
+and
+.I MASK
+are unsigned 32 bit values in hexadecimal format.
+.TP
+.BI psp_ver " VERSION"
+Match on the PSP version which the packet was decrypted with, as numbered
+by the PSP netlink family (0 for hdr0-aes-gcm-128, 1 for hdr0-aes-gcm-256,
+2 for hdr0-aes-gmac-128, 3 for hdr0-aes-gmac-256).
+.TP
+.BI psp_dev " PSP_DEV_ID"
+Match on the ID of the PSP device which decrypted the packet, from the PSP
+netlink family.
+.IP
+The PSP keys only ever match packets which a PSP device decrypted, even with
+a zero mask:
+.B psp_spi 0/0
+matches any packet decrypted with PSP. See
+.BR tc-psp (8)
+for an example.
+.TP
 .BI ip_proto " IP_PROTO"
 Match on layer four protocol.
 .I IP_PROTO
diff --git a/tc/f_flower.c b/tc/f_flower.c
index 6fc2c6a1ccc6..27244733e03a 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -73,6 +73,9 @@ static void explain(void)
 		"			mpls_bos BOS |\n"
 		"			mpls_ttl TTL |\n"
 		"			spi SPI-INDEX  |\n"
+		"			psp_spi SPI[/MASK] |\n"
+		"			psp_ver VERSION |\n"
+		"			psp_dev PSP-DEV-ID |\n"
 		"			l2tpv3_sid LSID |\n"
 		"			dst_ip PREFIX |\n"
 		"			src_ip PREFIX |\n"
@@ -678,6 +681,25 @@ static int flower_parse_icmp(char *str, __u16 eth_type, __u8 ip_proto,
 	return flower_parse_u8(str, value_type, mask_type, NULL, NULL, n);
 }
 
+static int flower_parse_psp_spi(char *str, struct nlmsghdr *n)
+{
+	__u32 spi, mask = UINT32_MAX;
+	char *slash;
+
+	slash = strchr(str, '/');
+	if (slash) {
+		*slash = '\0';
+		if (get_u32(&mask, slash + 1, 16))
+			return -1;
+	}
+	if (get_u32(&spi, str, 16))
+		return -1;
+
+	addattr32(n, MAX_MSG, TCA_FLOWER_KEY_PSP_SPI, htonl(spi));
+	addattr32(n, MAX_MSG, TCA_FLOWER_KEY_PSP_SPI_MASK, htonl(mask));
+	return 0;
+}
+
 static int flower_parse_spi(char *str, __u8 ip_proto, struct nlmsghdr *n)
 {
 	__be32 spi;
@@ -2074,6 +2096,31 @@ static int flower_parse_opt(const struct filter_util *qu, char *handle,
 			ret = flower_parse_l2tpv3(*argv, ip_proto, n);
 			if (ret < 0)
 				return -1;
+		} else if (!strcmp(*argv, "psp_spi")) {
+			NEXT_ARG();
+			ret = flower_parse_psp_spi(*argv, n);
+			if (ret < 0) {
+				fprintf(stderr, "Illegal \"psp_spi\"\n");
+				return -1;
+			}
+		} else if (!strcmp(*argv, "psp_ver")) {
+			__u8 ver;
+
+			NEXT_ARG();
+			if (get_u8(&ver, *argv, 0)) {
+				fprintf(stderr, "Illegal \"psp_ver\"\n");
+				return -1;
+			}
+			addattr8(n, MAX_MSG, TCA_FLOWER_KEY_PSP_VERSION, ver);
+		} else if (!strcmp(*argv, "psp_dev")) {
+			__u32 dev;
+
+			NEXT_ARG();
+			if (get_u32(&dev, *argv, 0)) {
+				fprintf(stderr, "Illegal \"psp_dev\"\n");
+				return -1;
+			}
+			addattr32(n, MAX_MSG, TCA_FLOWER_KEY_PSP_DEV, dev);
 		} else if (!strcmp(*argv, "spi")) {
 			NEXT_ARG();
 			ret = flower_parse_spi(*argv, ip_proto, n);
@@ -3236,6 +3283,30 @@ static int flower_print_opt(const struct filter_util *qu, FILE *f,
 			   rta_getattr_be32(attr));
 	}
 
+	if (tb[TCA_FLOWER_KEY_PSP_SPI]) {
+		__u32 mask = UINT32_MAX;
+
+		if (tb[TCA_FLOWER_KEY_PSP_SPI_MASK])
+			mask = rta_getattr_be32(tb[TCA_FLOWER_KEY_PSP_SPI_MASK]);
+		print_nl();
+		print_hex(PRINT_ANY, "psp_spi", "  psp_spi 0x%x",
+			  rta_getattr_be32(tb[TCA_FLOWER_KEY_PSP_SPI]));
+		if (mask != UINT32_MAX)
+			print_hex(PRINT_ANY, "psp_spi_mask", "/0x%x", mask);
+	}
+
+	if (tb[TCA_FLOWER_KEY_PSP_VERSION]) {
+		print_nl();
+		print_uint(PRINT_ANY, "psp_ver", "  psp_ver %u",
+			   rta_getattr_u8(tb[TCA_FLOWER_KEY_PSP_VERSION]));
+	}
+
+	if (tb[TCA_FLOWER_KEY_PSP_DEV]) {
+		print_nl();
+		print_uint(PRINT_ANY, "psp_dev", "  psp_dev %u",
+			   rta_getattr_u32(tb[TCA_FLOWER_KEY_PSP_DEV]));
+	}
+
 	flower_print_ip4_addr("arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
 			     tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
 	flower_print_ip4_addr("arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP],
-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH iproute2-next 2/3] tc: add the psp action
  2026-11-12  0:15 ` [PATCH iproute2-next 2/3] tc: add the psp action Todd Freed
@ 2026-11-12  1:05   ` Stephen Hemminger
  2026-11-12 19:22     ` Todd Bert Freed
  0 siblings, 1 reply; 8+ messages in thread
From: Stephen Hemminger @ 2026-11-12  1:05 UTC (permalink / raw)
  To: Todd Freed
  Cc: netdev, David Ahern, Jamal Hadi Salim, Jiri Pirko, Daniel Zahka,
	Willem de Bruijn, Jakub Kicinski, linux-kselftest

On Wed, 11 Nov 2026 16:15:11 -0800
Todd Freed <toddfreed@meta.com> wrote:

> The psp action applies PSP (PSP Security Protocol) encap and encryption
> to packets, separately from psp socket offload:
> 
>   psp encap assoc ASSOC_ID   attach a PSP Tx association, created with
>                              assoc-add over the PSP netlink family; the
>                              association's device encrypts the packet
>                              on transmit
>   psp decap                  remove the PSP Rx state of a packet the
>                              PSP device decrypted
> 
> decap takes no association. To take only those packets which belong to a
> single rx-spi-alloc call, a rule applies the corresponding flower psp_spi,
> psp_ver and psp_dev matches.
> 
> In JSON, the verb is psp_action. The action is documented in tc-psp(8).
> 
> Signed-off-by: Todd Freed <toddfreed@meta.com>
> ---

I saw several things that need fixing here, but AI review saw more:

New code must use strcmp(), not matches().  Six sites: "psp", "encap",
"decap", "assoc", "help", and the "index" test.  matches() does prefix
matching, so "e", "d", "a", "h", "i" all become valid keywords and are
de-facto ABI once released -- any keyword added later that shares a
prefix either changes the meaning of an existing one or can't be added.
Your own 3/3 uses strcmp(), so this is just making 2/3 match.

"psp decap assoc 3" is accepted silently and sends both
TCA_PSP_ACT_DECAP and TCA_PSP_ASSOC_ID.  Your changelog, the man page,
and your uapi comment ("u32, encap only") all say this is meaningless.
You already reject encap without assoc; please reject this too.  The
check has to go outside the "if (!p.index)" guard, since the attribute
is added unconditionally.  A repeated "assoc" is also silently
last-one-wins -- duparg() is the usual way to flag that.

print_psp() emits "psp_action" as a JSON string for encap/decap and as
a number in the default case.  Which type a script sees depends on the
kernel it's talking to.  Keep the key one type.  The default case also
fires when TCA_PSP_ACTION is absent entirely, printing "action 0".

explain() and the man page both omit "jump" from the CONTROL list,
though parse_action_control_dflt() accepts it.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev
  2026-11-12  0:15 ` [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev Todd Freed
@ 2026-11-12  1:06   ` Stephen Hemminger
  2026-11-12 19:21     ` Todd Bert Freed
  0 siblings, 1 reply; 8+ messages in thread
From: Stephen Hemminger @ 2026-11-12  1:06 UTC (permalink / raw)
  To: Todd Freed
  Cc: netdev, David Ahern, Jamal Hadi Salim, Jiri Pirko, Daniel Zahka,
	Willem de Bruijn, Jakub Kicinski, linux-kselftest

On Wed, 11 Nov 2026 16:15:12 -0800
Todd Freed <toddfreed@meta.com> wrote:

> Match on the PSP Rx state of a packet the device decrypted: the SPI it
> was decrypted with (psp_spi, with an optional mask), the PSP version
> (psp_ver), and the ID of the PSP device which decrypted it (psp_dev).
> 
> For example, to take the packets decrypted with one Rx SPI, from
> rx-spi-alloc, and remove their PSP state:
> 
>   tc filter add dev eth0 ingress protocol ipv6 flower
>       psp_spi 0x80000001 psp_ver 0 psp_dev 1
>       action psp decap
> 
> These keys only match decrypted packets, even with a zero mask, so
> "psp_spi 0/0" matches any decrypted PSP packet.
> 
> psp_spi and its mask are hexadecimal, like spi. tc-flower(8) documents
> the keys.
> 
> Signed-off-by: Todd Freed <toddfreed@meta.com>
> ---

AI review feedback on this


get_u8/get_u32 use base 0 for psp_ver and psp_dev, so "psp_ver 010" is
octal.  The man page documents plain numbers; base 10 would match.
Otherwise this one looks fine.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev
  2026-11-12  1:06   ` Stephen Hemminger
@ 2026-11-12 19:21     ` Todd Bert Freed
  0 siblings, 0 replies; 8+ messages in thread
From: Todd Bert Freed @ 2026-11-12 19:21 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev, David Ahern, Jamal Hadi Salim, Jiri Pirko, Daniel Zahka,
	Willem de Bruijn, Jakub Kicinski, linux-kselftest

> get_u8/get_u32 use base 0 for psp_ver and psp_dev, so "psp_ver 010" is
> octal.  The man page documents plain numbers; base 10 would match.
> Otherwise this one looks fine.

I will fix this

-Todd

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH iproute2-next 2/3] tc: add the psp action
  2026-11-12  1:05   ` Stephen Hemminger
@ 2026-11-12 19:22     ` Todd Bert Freed
  0 siblings, 0 replies; 8+ messages in thread
From: Todd Bert Freed @ 2026-11-12 19:22 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev, David Ahern, Jamal Hadi Salim, Jiri Pirko, Daniel Zahka,
	Willem de Bruijn, Jakub Kicinski, linux-kselftest

> I saw several things that need fixing here, but AI review saw more:

Fixed all of these. (I also re-ran Sashiko myself).

-Todd

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-11-12 19:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12  0:15 [PATCH iproute2-next 0/3] tc: add the psp action and flower psp matches Todd Freed
2026-11-12  0:15 ` [PATCH iproute2-next 1/3] uapi: add the tc psp action and flower psp keys Todd Freed
2026-11-12  0:15 ` [PATCH iproute2-next 2/3] tc: add the psp action Todd Freed
2026-11-12  1:05   ` Stephen Hemminger
2026-11-12 19:22     ` Todd Bert Freed
2026-11-12  0:15 ` [PATCH iproute2-next 3/3] tc: flower: add matches psp_spi, psp_ver and psp_dev Todd Freed
2026-11-12  1:06   ` Stephen Hemminger
2026-11-12 19:21     ` Todd Bert Freed

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox