Packet offload drivers can currently program state and validate whether an skb can be offloaded, but they cannot take ownership of a packet that needs driver-specific TX preparation before the regular XFRM output path continues. Add an optional xdo_dev_packet_xmit() callback. Drivers that implement it consume the skb and return the final TX status; all other drivers keep the existing XFRM output path. Signed-off-by: Jihong Min --- include/linux/netdevice.h | 8 ++++++++ net/xfrm/xfrm_output.c | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7f4f0837c09f..1552eb81ddf0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1048,6 +1048,14 @@ struct xfrmdev_ops { int (*xdo_dev_policy_add) (struct xfrm_policy *x, struct netlink_ext_ack *extack); void (*xdo_dev_policy_delete) (struct xfrm_policy *x); void (*xdo_dev_policy_free) (struct xfrm_policy *x); + /* Optional packet-offload TX path for devices that need + * driver-specific transmit preparation instead of continuing through + * the regular XFRM output path, such as adding offload metadata or + * steering the packet to a private transmit queue. The driver consumes + * skb and returns the final transmit status. + */ + int (*xdo_dev_packet_xmit)(struct sk_buff *skb, + struct xfrm_state *x); }; #endif diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index cc35c2fcbbe0..9f11559b0221 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -770,6 +770,17 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) } if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) { +#ifdef CONFIG_XFRM_OFFLOAD + const struct xfrmdev_ops *ops; +#endif + +#ifdef CONFIG_XFRM_OFFLOAD + ops = x->xso.dev->xfrmdev_ops; + /* Callback validates, consumes skb and returns final TX status. */ + if (ops && ops->xdo_dev_packet_xmit) + return ops->xdo_dev_packet_xmit(skb, x); +#endif + if (!xfrm_dev_offload_ok(skb, x)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); kfree_skb(skb); -- 2.53.0