Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net ipsecif(4) can use fixed SP reqid based on ifindex, ...
details: https://anonhg.NetBSD.org/src/rev/de209010fe2b
branches: trunk
changeset: 371233:de209010fe2b
user: knakahara <knakahara%NetBSD.org@localhost>
date: Fri Sep 30 07:36:36 2022 +0000
description:
ipsecif(4) can use fixed SP reqid based on ifindex, that can reduce number of reqid.
If we want to use fixed SP reqid for ipsecif(4), set
net.ipsecif.use_fixed_reqid=1 Default(=0) is the same as before.
net.ipsecif.use_fixed_reqid can be changed only if there is no ipsecif(4) yet.
If we want to change the range of ipseif(4) SP reqid,
set net.ipsecif.reqid_base and net.ipsecif.reqid_last.
These can also be changed only if there is no ipsecif(4) yet.
diffstat:
sys/net/if_ipsec.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 193 insertions(+), 22 deletions(-)
diffs (truncated from 337 to 300 lines):
diff -r 5fff7358465b -r de209010fe2b sys/net/if_ipsec.c
--- a/sys/net/if_ipsec.c Fri Sep 30 06:39:54 2022 +0000
+++ b/sys/net/if_ipsec.c Fri Sep 30 07:36:36 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ipsec.c,v 1.31 2021/10/11 05:13:11 knakahara Exp $ */
+/* $NetBSD: if_ipsec.c,v 1.32 2022/09/30 07:36:36 knakahara Exp $ */
/*
* Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.31 2021/10/11 05:13:11 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.32 2022/09/30 07:36:36 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -110,7 +110,7 @@
struct sockaddr *, int);
static inline size_t if_ipsec_set_sadb_x_policy(struct sadb_x_policy *,
struct sadb_x_ipsecrequest *, uint16_t, uint8_t, uint32_t, uint8_t,
- struct sockaddr *, struct sockaddr *);
+ struct sockaddr *, struct sockaddr *, uint16_t);
static inline void if_ipsec_set_sadb_msg(struct sadb_msg *, uint16_t, uint8_t);
static inline void if_ipsec_set_sadb_msg_add(struct sadb_msg *, uint16_t);
static inline void if_ipsec_set_sadb_msg_del(struct sadb_msg *, uint16_t);
@@ -118,7 +118,7 @@
static int if_ipsec_share_sp(struct ipsec_variant *);
static int if_ipsec_unshare_sp(struct ipsec_variant *);
static inline struct secpolicy *if_ipsec_add_sp0(struct sockaddr *,
- in_port_t, struct sockaddr *, in_port_t, int, int, int, u_int);
+ in_port_t, struct sockaddr *, in_port_t, int, int, int, u_int, uint16_t);
static inline int if_ipsec_del_sp0(struct secpolicy *);
static int if_ipsec_add_sp(struct ipsec_variant *,
struct sockaddr *, in_port_t, struct sockaddr *, in_port_t);
@@ -140,8 +140,17 @@
/* This list is used in ioctl context only. */
static struct {
LIST_HEAD(ipsec_sclist, ipsec_softc) list;
+ bool use_fixed_reqid;
+#define REQID_BASE_DEFAULT 0x2000
+#define REQID_LAST_DEFAULT 0x2fff
+ u_int16_t reqid_base;
+ u_int16_t reqid_last;
kmutex_t lock;
-} ipsec_softcs __cacheline_aligned;
+} ipsec_softcs __cacheline_aligned = {
+ .use_fixed_reqid = false,
+ .reqid_base = REQID_BASE_DEFAULT,
+ .reqid_last = REQID_LAST_DEFAULT,
+};
struct psref_class *iv_psref_class __read_mostly;
@@ -153,6 +162,14 @@
static pktq_rps_hash_func_t if_ipsec_pktq_rps_hash_p;
+enum {
+ REQID_INDEX_IPV4IN = 0,
+ REQID_INDEX_IPV4OUT,
+ REQID_INDEX_IPV6IN,
+ REQID_INDEX_IPV6OUT,
+ REQID_INDEX_NUM,
+};
+
#ifdef INET6
static int
sysctl_if_ipsec_pmtu_global(SYSCTLFN_ARGS)
@@ -205,6 +222,84 @@
}
#endif
+static int
+sysctl_if_ipsec_use_fixed_reqid(SYSCTLFN_ARGS)
+{
+ bool fixed;
+ int error;
+ struct sysctlnode node = *rnode;
+
+ mutex_enter(&ipsec_softcs.lock);
+ fixed = ipsec_softcs.use_fixed_reqid;
+ node.sysctl_data = &fixed;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL) {
+ mutex_exit(&ipsec_softcs.lock);
+ return error;
+ }
+
+ if (!LIST_EMPTY(&ipsec_softcs.list)) {
+ mutex_exit(&ipsec_softcs.lock);
+ return EBUSY;
+ }
+ ipsec_softcs.use_fixed_reqid = fixed;
+ mutex_exit(&ipsec_softcs.lock);
+
+ return 0;
+}
+
+static int
+sysctl_if_ipsec_reqid_base(SYSCTLFN_ARGS)
+{
+ int base;
+ int error;
+ struct sysctlnode node = *rnode;
+
+ mutex_enter(&ipsec_softcs.lock);
+ base = ipsec_softcs.reqid_base;
+ node.sysctl_data = &base;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL) {
+ mutex_exit(&ipsec_softcs.lock);
+ return error;
+ }
+
+ if (!LIST_EMPTY(&ipsec_softcs.list)) {
+ mutex_exit(&ipsec_softcs.lock);
+ return EBUSY;
+ }
+ ipsec_softcs.reqid_base = base;
+ mutex_exit(&ipsec_softcs.lock);
+
+ return 0;
+}
+
+static int
+sysctl_if_ipsec_reqid_last(SYSCTLFN_ARGS)
+{
+ int last;
+ int error;
+ struct sysctlnode node = *rnode;
+
+ mutex_enter(&ipsec_softcs.lock);
+ last = ipsec_softcs.reqid_last;
+ node.sysctl_data = &last;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL) {
+ mutex_exit(&ipsec_softcs.lock);
+ return error;
+ }
+
+ if (!LIST_EMPTY(&ipsec_softcs.list)) {
+ mutex_exit(&ipsec_softcs.lock);
+ return EBUSY;
+ }
+ ipsec_softcs.reqid_last = last;
+ mutex_exit(&ipsec_softcs.lock);
+
+ return 0;
+}
+
static void
if_ipsec_sysctl_setup(void)
{
@@ -260,6 +355,26 @@
sysctl_pktq_rps_hash_handler, 0, (void *)&if_ipsec_pktq_rps_hash_p,
PKTQ_RPS_HASH_NAME_LEN,
CTL_CREATE, CTL_EOL);
+
+ sysctl_createv(&if_ipsec_sysctl, 0, &node, NULL,
+ CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+ CTLTYPE_BOOL, "use_fixed_reqid",
+ SYSCTL_DESCR("use fixed reqid for SP"),
+ sysctl_if_ipsec_use_fixed_reqid, 0, NULL, 0,
+ CTL_CREATE, CTL_EOL);
+ sysctl_createv(&if_ipsec_sysctl, 0, &node, NULL,
+ CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+ CTLTYPE_INT, "reqid_base",
+ SYSCTL_DESCR("base value of fixed reqid"),
+ sysctl_if_ipsec_reqid_base, 0, NULL, 0,
+ CTL_CREATE, CTL_EOL);
+ sysctl_createv(&if_ipsec_sysctl, 0, &node, NULL,
+ CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+ CTLTYPE_INT, "reqid_last",
+ SYSCTL_DESCR("last value of fixed reqid"),
+ sysctl_if_ipsec_reqid_last, 0, NULL, 0,
+ CTL_CREATE, CTL_EOL);
+
}
static void
@@ -1575,7 +1690,7 @@
static inline size_t
if_ipsec_set_sadb_x_policy(struct sadb_x_policy *xpl,
struct sadb_x_ipsecrequest *xisr, uint16_t policy, uint8_t dir, uint32_t id,
- uint8_t level, struct sockaddr *src, struct sockaddr *dst)
+ uint8_t level, struct sockaddr *src, struct sockaddr *dst, uint16_t reqid)
{
size_t size;
@@ -1604,7 +1719,7 @@
xisr->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
xisr->sadb_x_ipsecrequest_level = level;
if (level == IPSEC_LEVEL_UNIQUE)
- xisr->sadb_x_ipsecrequest_reqid = key_newreqid();
+ xisr->sadb_x_ipsecrequest_reqid = reqid;
else
xisr->sadb_x_ipsecrequest_reqid = 0;
}
@@ -1675,10 +1790,47 @@
return error;
}
+static int
+if_ipsec_get_reqids(struct ipsec_variant *var, u_int16_t reqids[REQID_INDEX_NUM])
+{
+ struct ipsec_softc *sc = var->iv_softc;
+ struct ifnet *ifp = &sc->ipsec_if;
+
+ mutex_enter(&ipsec_softcs.lock);
+ if (ipsec_softcs.use_fixed_reqid) {
+ u_int16_t reqid_base;
+
+ reqid_base = ipsec_softcs.reqid_base + ifp->if_index * 2;
+ if (reqid_base + 1 > ipsec_softcs.reqid_last) {
+ log(LOG_ERR,
+ "%s: invalid fixed reqid(%"PRIu16"), "
+ "current range %"PRIu16" <= reqid <= %"PRIu16"\n",
+ ifp->if_xname, reqid_base + 1,
+ ipsec_softcs.reqid_base, ipsec_softcs.reqid_last);
+ mutex_exit(&ipsec_softcs.lock);
+ return ENOSPC;
+ }
+
+ /*
+ * Use same reqid both inbound and outbound to reduce reqid.
+ */
+ reqids[REQID_INDEX_IPV4IN] = reqid_base;
+ reqids[REQID_INDEX_IPV4OUT] = reqid_base;
+ reqids[REQID_INDEX_IPV6IN] = reqid_base + 1;
+ reqids[REQID_INDEX_IPV6OUT] = reqid_base + 1;
+ } else {
+ for (int i = 0; i < REQID_INDEX_NUM; i++)
+ reqids[i] = key_newreqid();
+ }
+ mutex_exit(&ipsec_softcs.lock);
+
+ return 0;
+}
+
static struct secpolicy *
if_ipsec_add_sp0(struct sockaddr *src, in_port_t sport,
struct sockaddr *dst, in_port_t dport,
- int dir, int proto, int level, u_int policy)
+ int dir, int proto, int level, u_int policy, uint16_t reqid)
{
struct sadb_msg msg;
struct sadb_address xsrc, xdst;
@@ -1701,7 +1853,8 @@
ext_msg_len += PFKEY_UNIT64(size);
size = if_ipsec_set_sadb_dst(&xdst, dst, proto);
ext_msg_len += PFKEY_UNIT64(size);
- size = if_ipsec_set_sadb_x_policy(&xpl, &xisr, policy, dir, 0, level, NULL, NULL);
+ size = if_ipsec_set_sadb_x_policy(&xpl, &xisr, policy, dir, 0, level,
+ NULL, NULL, reqid);
ext_msg_len += PFKEY_UNIT64(size);
if_ipsec_set_sadb_msg_add(&msg, ext_msg_len);
@@ -1746,7 +1899,9 @@
{
struct ipsec_softc *sc = var->iv_softc;
int level;
+ int error;
u_int v6policy;
+ u_int16_t reqids[REQID_INDEX_NUM];
/*
* must delete sp before add it.
@@ -1772,22 +1927,38 @@
else
v6policy = IPSEC_POLICY_DISCARD;
- IV_SP_IN(var) = if_ipsec_add_sp0(dst, dport, src, sport,
- IPSEC_DIR_INBOUND, IPPROTO_IPIP, level, IPSEC_POLICY_IPSEC);
- if (IV_SP_IN(var) == NULL)
+ error = if_ipsec_get_reqids(var, reqids);
+ if (error)
goto fail;
- IV_SP_OUT(var) = if_ipsec_add_sp0(src, sport, dst, dport,
- IPSEC_DIR_OUTBOUND, IPPROTO_IPIP, level, IPSEC_POLICY_IPSEC);
- if (IV_SP_OUT(var) == NULL)
+
+ IV_SP_IN(var) = if_ipsec_add_sp0(dst, dport, src, sport,
+ IPSEC_DIR_INBOUND, IPPROTO_IPIP, level, IPSEC_POLICY_IPSEC,
+ reqids[REQID_INDEX_IPV4IN]);
+ if (IV_SP_IN(var) == NULL) {
+ error = EEXIST;
goto fail;
- IV_SP_IN6(var) = if_ipsec_add_sp0(dst, dport, src, sport,
- IPSEC_DIR_INBOUND, IPPROTO_IPV6, level, v6policy);
- if (IV_SP_IN6(var) == NULL)
+ }
+ IV_SP_OUT(var) = if_ipsec_add_sp0(src, sport, dst, dport,
+ IPSEC_DIR_OUTBOUND, IPPROTO_IPIP, level, IPSEC_POLICY_IPSEC,
+ reqids[REQID_INDEX_IPV4OUT]);
+ if (IV_SP_OUT(var) == NULL) {
+ error = EEXIST;
goto fail;
+ }
Home |
Main Index |
Thread Index |
Old Index