[Swan-dev] [PATCH libreswan] Add support for IPSec HW-offload on the NIC

ilant at mellanox.com ilant at mellanox.com
Tue Jun 27 15:48:26 UTC 2017


From: Ilan Tayari <ilant at mellanox.com>

Add per-connection configuration flag to enable HW offload.

For kernel_netlink, if flag is set and connection is oriented,
attempt to offload on the interface's device by adding the new
XFRMA_OFFLOAD_DEV netlink attribute.

Signed-off-by: Ilan Tayari <ilant at mellanox.com>
---
 include/ipsecconf/keywords.h    |  1 +
 include/whack.h                 |  1 +
 lib/libipsecconf/confread.c     |  1 +
 lib/libipsecconf/keywords.c     |  1 +
 lib/libipsecconf/starterwhack.c |  1 +
 programs/pluto/connections.c    |  1 +
 programs/pluto/connections.h    |  1 +
 programs/pluto/kernel.c         |  4 ++++
 programs/pluto/kernel.h         |  2 ++
 programs/pluto/kernel_netlink.c | 16 ++++++++++++++++
 programs/pluto/linux26/xfrm.h   | 12 ++++++++++++
 programs/whack/whack.c          |  1 +
 12 files changed, 42 insertions(+)

diff --git a/include/ipsecconf/keywords.h b/include/ipsecconf/keywords.h
index 36bf53529..0b00dcb25 100644
--- a/include/ipsecconf/keywords.h
+++ b/include/ipsecconf/keywords.h
@@ -156,6 +156,7 @@ enum keyword_numeric_config_field {
 	KBF_SECCOMP,		/* set SECCOMP mode */
 	KBF_VTI_ROUTING,	/* let updown do routing into VTI device */
 	KBF_VTI_SHARED,		/* VTI device is shared - enable checks and disable cleanup */
+	KBF_HW_OFFLOAD,		/* HW offload on network device */
 	KBF_MAX
 };
 
diff --git a/include/whack.h b/include/whack.h
index 077a05370..fd96053a0 100644
--- a/include/whack.h
+++ b/include/whack.h
@@ -155,6 +155,7 @@ struct whack_message {
 	unsigned long sa_replay_window;
 	deltatime_t r_timeout; /* in secs */
 	unsigned long  r_interval; /* in msec */
+	bool hw_offload;
 
 	/* For IKEv1 RFC 3706 - Dead Peer Detection */
 	deltatime_t dpd_delay;
diff --git a/lib/libipsecconf/confread.c b/lib/libipsecconf/confread.c
index bd4171c06..71ce2993c 100644
--- a/lib/libipsecconf/confread.c
+++ b/lib/libipsecconf/confread.c
@@ -147,6 +147,7 @@ void ipsecconf_default_values(struct starter_config *cfg)
 		POLICY_IKE_FRAG_ALLOW |      /* ike_frag=yes */
 		POLICY_ESN_NO;      /* esn=no */
 
+	cfg->conn_default.options[KBF_HW_OFFLOAD] = FALSE;
 	cfg->conn_default.options[KBF_IKELIFETIME] = IKE_SA_LIFETIME_DEFAULT;
 
 	cfg->conn_default.options[KBF_REPLAY_WINDOW] = IPSEC_SA_DEFAULT_REPLAY_WINDOW;
diff --git a/lib/libipsecconf/keywords.c b/lib/libipsecconf/keywords.c
index 09b7b04b5..9db752ccc 100644
--- a/lib/libipsecconf/keywords.c
+++ b/lib/libipsecconf/keywords.c
@@ -603,6 +603,7 @@ const struct keyword_def ipsec_conf_keywords_v2[] = {
   { "modecfgwins1",  kv_conn,  kt_obsolete,  KBF_WARNIGNORE,  NOT_ENUM },
   { "modecfgwins2",  kv_conn,  kt_obsolete,  KBF_WARNIGNORE,  NOT_ENUM },
 
+  { "hw_offload",  kv_conn,  kt_bool,  KBF_HW_OFFLOAD,  NOT_ENUM },
   { "encapsulation",  kv_conn,  kt_enum,  KBF_ENCAPS,  &kw_encaps_list },
   { "forceencaps",  kv_conn, kt_obsolete, KBF_WARNIGNORE, NOT_ENUM },
 
diff --git a/lib/libipsecconf/starterwhack.c b/lib/libipsecconf/starterwhack.c
index f244f9ce6..c667cec7f 100644
--- a/lib/libipsecconf/starterwhack.c
+++ b/lib/libipsecconf/starterwhack.c
@@ -530,6 +530,7 @@ static int starter_whack_basic_add_conn(struct starter_config *cfg,
 	if (conn->right.addrtype == KH_IPHOSTNAME)
 		msg.dnshostname = conn->right.strings[KSCF_IP];
 
+	msg.hw_offload = conn->options[KBF_HW_OFFLOAD];
 	msg.sa_ike_life_seconds = deltatime(conn->options[KBF_IKELIFETIME]);
 	msg.sa_ipsec_life_seconds = deltatime(conn->options[KBF_SALIFETIME]);
 	msg.sa_rekey_margin = deltatime(conn->options[KBF_REKEYMARGIN]);
diff --git a/programs/pluto/connections.c b/programs/pluto/connections.c
index 9d03f0f03..c47533353 100644
--- a/programs/pluto/connections.c
+++ b/programs/pluto/connections.c
@@ -1569,6 +1569,7 @@ void add_connection(const struct whack_message *wm)
 			}
 		}
 
+		c->hw_offload = wm->hw_offload;
 		c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
 		c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
 		c->sa_rekey_margin = wm->sa_rekey_margin;
diff --git a/programs/pluto/connections.h b/programs/pluto/connections.h
index b07539324..491f11434 100644
--- a/programs/pluto/connections.h
+++ b/programs/pluto/connections.h
@@ -242,6 +242,7 @@ struct connection {
 	deltatime_t r_timeout; /* max time (in secs) for one packet exchange attempt */
 	reqid_t sa_reqid;
 	int encapsulation;
+	bool hw_offload;
 
 	/* RFC 3706 DPD */
 	deltatime_t dpd_delay;		/* time between checks */
diff --git a/programs/pluto/kernel.c b/programs/pluto/kernel.c
index b400da7bf..c924e8181 100644
--- a/programs/pluto/kernel.c
+++ b/programs/pluto/kernel.c
@@ -1796,6 +1796,10 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
 	said_boilerplate.transport_proto = c->spd.this.protocol;
 	said_boilerplate.sa_lifetime = c->sa_ipsec_life_seconds;
 	said_boilerplate.outif = -1;
+	said_boilerplate.hw_offload = c->hw_offload;
+	if (c->hw_offload && c->interface)
+		said_boilerplate.hw_offload_ifindex = if_nametoindex(c->interface->ip_dev->id_rname);
+
 #ifdef HAVE_LABELED_IPSEC
 	said_boilerplate.sec_ctx = st->sec_ctx;
 #endif
diff --git a/programs/pluto/kernel.h b/programs/pluto/kernel.h
index 05ac8bf29..003b1d9b1 100644
--- a/programs/pluto/kernel.h
+++ b/programs/pluto/kernel.h
@@ -117,6 +117,8 @@ struct kernel_sa {
 #ifdef HAVE_LABELED_IPSEC
 	struct xfrm_user_sec_ctx_ike *sec_ctx;
 #endif
+	bool hw_offload;
+	int hw_offload_ifindex;
 
 	deltatime_t sa_lifetime; /* number of seconds until SA expires */
 	/* below two need to enabled and used, instead of getting passed */
diff --git a/programs/pluto/kernel_netlink.c b/programs/pluto/kernel_netlink.c
index 77b6010c0..bd16c2900 100644
--- a/programs/pluto/kernel_netlink.c
+++ b/programs/pluto/kernel_netlink.c
@@ -1235,6 +1235,22 @@ static bool netlink_add_sa(const struct kernel_sa *sa, bool replace)
 		attr = (struct rtattr *)((char *)attr + attr->rta_len);
 	}
 
+	if (sa->hw_offload) {
+		struct xfrm_user_offload xuo;
+
+		xuo.flags |= sa->inbound ? XFRM_OFFLOAD_INBOUND : 0;
+		if (sa->src->u.v4.sin_family == AF_INET6)
+			xuo.flags |= XFRM_OFFLOAD_IPV6;
+		xuo.ifindex = sa->hw_offload_ifindex;
+
+		attr->rta_type = XFRMA_OFFLOAD_DEV;
+		attr->rta_len = RTA_LENGTH(sizeof(xuo));
+
+		memcpy(RTA_DATA(attr), &xuo, sizeof(xuo));
+
+		req.n.nlmsg_len += attr->rta_len;
+		attr = (struct rtattr *)((char *)attr + attr->rta_len);
+	}
 
 #ifdef HAVE_LABELED_IPSEC
 	if (sa->sec_ctx != NULL) {
diff --git a/programs/pluto/linux26/xfrm.h b/programs/pluto/linux26/xfrm.h
index 22e61fdf7..104b770ea 100644
--- a/programs/pluto/linux26/xfrm.h
+++ b/programs/pluto/linux26/xfrm.h
@@ -295,6 +295,11 @@ enum xfrm_attr_type_t {
 	XFRMA_MARK,		/* struct xfrm_mark */
 	XFRMA_TFCPAD,		/* __u32 */
 	XFRMA_REPLAY_ESN_VAL,	/* struct xfrm_replay_esn */
+	XFRMA_SA_EXTRA_FLAGS,	/* __u32 */
+	XFRMA_PROTO,		/* __u8 */
+	XFRMA_ADDRESS_FILTER,	/* struct xfrm_address_filter */
+	XFRMA_PAD,
+	XFRMA_OFFLOAD_DEV,	/* struct xfrm_state_offload */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -469,6 +474,13 @@ struct xfrm_user_mapping {
 	__be16				new_sport;
 };
 
+struct xfrm_user_offload {
+	int				ifindex;
+	__u8				flags;
+};
+#define XFRM_OFFLOAD_IPV6	1
+#define XFRM_OFFLOAD_INBOUND	2
+
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
diff --git a/programs/whack/whack.c b/programs/whack/whack.c
index e2ede966e..8158b27d3 100644
--- a/programs/whack/whack.c
+++ b/programs/whack/whack.c
@@ -940,6 +940,7 @@ int main(int argc, char **argv)
 	msg.modecfg_domain = NULL;
 	msg.modecfg_banner = NULL;
 
+	msg.hw_offload = FALSE;
 	msg.sa_ike_life_seconds = deltatime(IKE_SA_LIFETIME_DEFAULT);
 	msg.sa_ipsec_life_seconds = deltatime(IPSEC_SA_LIFETIME_DEFAULT);
 	msg.sa_rekey_margin = deltatime(SA_REPLACEMENT_MARGIN_DEFAULT);
-- 
2.11.0



More information about the Swan-dev mailing list