* [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