[Openvpn-devel,RFC,net-next,v2,01/14] ovpn: prepare packet ID state for usage limits

Message ID 6c66a38af8ea53e4fbc587f087c594573fd8ee6a.1782986577.git.ralf@mandelbit.com
State Changes Requested
Headers
Series ovpn: add epoch data channel keys |

Commit Message

Ralf Lici July 2, 2026, 11:52 a.m. UTC
  OpenVPN needs packet-ID and cipher usage thresholds to decide when a
data-channel key should be renewed or stopped. The existing transmit
packet-ID helper only returns the next ID and has no way to request a
threshold notification.

Teach the transmit packet-ID helper to return 1 when the fixed OpenVPN
packet-ID soft threshold is crossed. The counter is monotonic, so the
exact crossing is naturally reported only once. The hard packet-ID wrap
check still stops TX; this only gives userspace a chance to rekey while
packet-ID space is still available.

Signed-off-by: Ralf Lici <ralf@mandelbit.com>
---
No changes since v1 https://lore.kernel.org/openvpn-devel/6c66a38af8ea53e4fbc587f087c594573fd8ee6a.1782919654.git.ralf@mandelbit.com/

 drivers/net/ovpn/crypto_aead.c |  3 +++
 drivers/net/ovpn/netlink.c     |  4 ++--
 drivers/net/ovpn/pktid.h       | 31 +++++++++++++++++++++++++------
 3 files changed, 30 insertions(+), 8 deletions(-)
  

Patch

diff --git a/drivers/net/ovpn/crypto_aead.c b/drivers/net/ovpn/crypto_aead.c
index 8f07c418622b..86b69aeddcf7 100644
--- a/drivers/net/ovpn/crypto_aead.c
+++ b/drivers/net/ovpn/crypto_aead.c
@@ -19,6 +19,7 @@ 
 #include "pktid.h"
 #include "crypto_aead.h"
 #include "crypto.h"
+#include "netlink.h"
 #include "peer.h"
 #include "proto.h"
 #include "skb.h"
@@ -207,6 +208,8 @@  int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	ret = ovpn_pktid_xmit_next(&ks->pid_xmit, &pktid);
 	if (unlikely(ret < 0))
 		return ret;
+	if (unlikely(ret > 0))
+		ovpn_nl_key_swap_notify(peer, ks->key_id);
 
 	/* concat 4 bytes packet id and 8 bytes nonce tail into 12 bytes
 	 * nonce
diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c
index 4c66c1ec497e..83d81a468b5a 100644
--- a/drivers/net/ovpn/netlink.c
+++ b/drivers/net/ovpn/netlink.c
@@ -1312,8 +1312,8 @@  int ovpn_nl_key_swap_notify(struct ovpn_peer *peer, u8 key_id)
 	int ret = -EMSGSIZE;
 	void *hdr;
 
-	netdev_info(peer->ovpn->dev, "peer with id %u must rekey - primary key unusable.\n",
-		    peer->id);
+	netdev_info(peer->ovpn->dev, "peer with id %u should rekey key %u\n",
+		    peer->id, key_id);
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
 	if (!msg)
diff --git a/drivers/net/ovpn/pktid.h b/drivers/net/ovpn/pktid.h
index 21845f353bc8..82f59256b4a3 100644
--- a/drivers/net/ovpn/pktid.h
+++ b/drivers/net/ovpn/pktid.h
@@ -17,6 +17,9 @@ 
  */
 #define PKTID_RECV_EXPIRE (30 * HZ)
 
+/* notify userspace when the packet ID space is close to wrapping */
+#define PKTID_XMIT_REKEY_NOTIFY 0xff000000U
+
 /* Packet-ID state for transmitter */
 struct ovpn_pktid_xmit {
 	atomic_t seq_num;
@@ -52,20 +55,36 @@  struct ovpn_pktid_recv {
 	spinlock_t lock;
 };
 
-/* Get the next packet ID for xmit */
+/**
+ * ovpn_pktid_xmit_next - allocate a transmit packet ID
+ * @pid: transmit packet ID state
+ * @pktid: location where the generated packet ID is stored
+ *
+ * The returned packet ID becomes part of the AEAD nonce, so the helper rejects
+ * the packet before the 32-bit packet-ID space wraps.
+ *
+ * The packet-ID soft threshold does not reject the packet. It returns 1 once
+ * so the caller can notify userspace to rekey while packet-ID space remains.
+ *
+ * Return: 1 if userspace should be notified, 0 if no notification is needed,
+ * or a negative error code otherwise.
+ */
 static inline int ovpn_pktid_xmit_next(struct ovpn_pktid_xmit *pid, u32 *pktid)
 {
 	const u32 seq_num = atomic_fetch_add_unless(&pid->seq_num, 1, 0);
-	/* when the 32bit space is over, we return an error because the packet
-	 * ID is used to create the cipher IV and we do not want to reuse the
-	 * same value more than once
-	 */
+	int ret = 0;
+
+	/* packet IDs are used to create cipher IVs and must not wrap */
 	if (unlikely(!seq_num))
 		return -ERANGE;
 
+	/* notify userspace before the packet ID space is close to wrapping */
+	if (unlikely(seq_num == PKTID_XMIT_REKEY_NOTIFY))
+		ret = 1;
+
 	*pktid = seq_num;
 
-	return 0;
+	return ret;
 }
 
 /* Write 12-byte AEAD IV to dest */