[PATCH v2] add new macsec offload modes to abstract device-level details

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, users have to guess which offload mode their hardware
provides, as the kernel doesn't expose this information.

Add an "on" mode which requires offload (either to mac or phy) and a
"prefer" mode which allows fallback to SW when offload (either to mac
or phy) is unavailable.

Also rename the existing modes to string values to make the config
file a bit clearer.

v2: add macsec_offload to the dont_quote list for dbus, as reported by
    Beniamino Galvani

Signed-off-by: Sabrina Dubroca <sd@xxxxxxxxxxxxxxx>
---
 hostapd/config_file.c                   | 32 +++++++++--
 hostapd/hostapd.conf                    |  8 ++-
 src/ap/ap_config.h                      |  4 +-
 src/common/ieee802_1x_defs.h            | 10 ++++
 src/drivers/driver.h                    |  4 +-
 src/drivers/driver_macsec_linux.c       | 73 +++++++++++++++++++++----
 wpa_supplicant/config.c                 | 36 +++++++++++-
 wpa_supplicant/config_file.c            |  8 ++-
 wpa_supplicant/config_ssid.h            |  4 +-
 wpa_supplicant/dbus/dbus_new_handlers.c |  3 +
 wpa_supplicant/wpa_supplicant.conf      | 10 ++--
 11 files changed, 155 insertions(+), 37 deletions(-)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 1af083917052..7c00398dcc01 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2435,6 +2435,29 @@ static int get_u16(const char *pos, int line, u16 *ret_val)
 }
 #endif /* CONFIG_IEEE80211BE */
 
+#ifdef CONFIG_MACSEC
+const char *macsec_offload_strings[NUM_CONFIG_MACSEC_OFFLOAD_MODES] = {
+	"off",
+	"on",
+	"mac",
+	"phy",
+	"prefer",
+};
+static int parse_macsec_offload(struct hostapd_bss_config *bss, const char *val)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(macsec_offload_strings); i++) {
+		if (os_strcmp(macsec_offload_strings[i], val) == 0) {
+			bss->macsec_offload = i;
+			return 0;
+		}
+	}
+
+	return 1;
+}
+#endif /* CONFIG_MACSEC */
+
 
 static int hostapd_config_fill(struct hostapd_config *conf,
 			       struct hostapd_bss_config *bss,
@@ -4816,15 +4839,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 	} else if (os_strcmp(buf, "macsec_replay_window") == 0) {
 		bss->macsec_replay_window = atoi(pos);
 	} else if (os_strcmp(buf, "macsec_offload") == 0) {
-		int macsec_offload = atoi(pos);
-
-		if (macsec_offload < 0 || macsec_offload > 2) {
+		if (parse_macsec_offload(bss, pos)) {
 			wpa_printf(MSG_ERROR,
-				   "Line %d: invalid macsec_offload (%d): '%s'.",
-				   line, macsec_offload, pos);
+				   "Line %d: invalid macsec_offload: '%s'.",
+				   line, pos);
 			return 1;
 		}
-		bss->macsec_offload = macsec_offload;
 	} else if (os_strcmp(buf, "macsec_port") == 0) {
 		int macsec_port = atoi(pos);
 
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 13576499a358..368e0c3622ed 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1174,9 +1174,11 @@ eapol_key_index_workaround=0
 # This setting applies only when MACsec is in use, i.e.,
 #  - macsec_policy is enabled
 #  - the key server has decided to enable MACsec
-# 0 = MACSEC_OFFLOAD_OFF (default)
-# 1 = MACSEC_OFFLOAD_PHY
-# 2 = MACSEC_OFFLOAD_MAC
+# off = don't offload (default)
+# mac = request offload to the MAC
+# phy = request offload to the PHY
+# on = request offload (to either MAC or PHY)
+# prefer = try to offload (to either MAC or PHY), fall back to software
 #
 # macsec_port: IEEE 802.1X/MACsec port
 # Port component of the SCI
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index de02ddafda77..5ce68b8d0b73 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -863,9 +863,7 @@ struct hostapd_bss_config {
 	 *  - macsec_policy is enabled
 	 *  - the key server has decided to enable MACsec
 	 *
-	 * 0 = MACSEC_OFFLOAD_OFF (default)
-	 * 1 = MACSEC_OFFLOAD_PHY
-	 * 2 = MACSEC_OFFLOAD_MAC
+	 * Values: enum macsec_offload_modes
 	 */
 	int macsec_offload;
 
diff --git a/src/common/ieee802_1x_defs.h b/src/common/ieee802_1x_defs.h
index e7acff108eb3..ea964e1dd338 100644
--- a/src/common/ieee802_1x_defs.h
+++ b/src/common/ieee802_1x_defs.h
@@ -83,4 +83,14 @@ enum confidentiality_offset {
 #define DEFAULT_PRIO_GROUP_CA_MEMBER   0x70
 #define DEFAULT_PRIO_NOT_KEY_SERVER    0xFF
 
+enum macsec_offload_modes {
+	CONFIG_MACSEC_OFFLOAD_OFF,
+	CONFIG_MACSEC_OFFLOAD_ON,
+	CONFIG_MACSEC_OFFLOAD_MAC,
+	CONFIG_MACSEC_OFFLOAD_PHY,
+	CONFIG_MACSEC_OFFLOAD_PREFER,
+	NUM_CONFIG_MACSEC_OFFLOAD_MODES,
+};
+extern const char *macsec_offload_strings[NUM_CONFIG_MACSEC_OFFLOAD_MODES];
+
 #endif /* IEEE802_1X_DEFS_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 4974bbdc8711..e018aabcf8ed 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -4662,9 +4662,7 @@ struct wpa_driver_ops {
 	/**
 	 * set_offload - Set MACsec hardware offload
 	 * @priv: Private driver interface data
-	 * @offload: 0 = MACSEC_OFFLOAD_OFF
-	 *           1 = MACSEC_OFFLOAD_PHY
-	 *           2 = MACSEC_OFFLOAD_MAC
+	 * @offload: enum macsec_offload_modes
 	 * Returns: 0 on success, -1 on failure (or if not supported)
 	 */
 	int (*set_offload)(void *priv, u8 offload);
diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c
index c867154981e9..3124104f4aad 100644
--- a/src/drivers/driver_macsec_linux.c
+++ b/src/drivers/driver_macsec_linux.c
@@ -78,7 +78,7 @@ struct macsec_drv_data {
 	bool replay_protect_set;
 
 #ifdef LIBNL_HAS_OFFLOAD
-	enum macsec_offload offload;
+	enum macsec_offload_modes offload;
 	bool offload_set;
 #endif /* LIBNL_HAS_OFFLOAD */
 
@@ -237,26 +237,77 @@ static int try_commit(struct macsec_drv_data *drv)
 						    drv->replay_window);
 	}
 
+	if (drv->encoding_sa_set) {
+		wpa_printf(MSG_DEBUG, DRV_PREFIX
+			   "%s: try_commit encoding_sa=%d",
+			   drv->ifname, drv->encoding_sa);
+		rtnl_link_macsec_set_encoding_sa(drv->link, drv->encoding_sa);
+	}
+
+	/* must be last */
 #ifdef LIBNL_HAS_OFFLOAD
 	if (drv->offload_set) {
+		int offload_value;
+
 		wpa_printf(MSG_DEBUG, DRV_PREFIX
 			   "%s: try_commit offload=%d",
 			   drv->ifname, drv->offload);
-		rtnl_link_macsec_set_offload(drv->link, drv->offload);
-	}
-#endif /* LIBNL_HAS_OFFLOAD */
+		if (drv->offload == CONFIG_MACSEC_OFFLOAD_PREFER ||
+		    drv->offload == CONFIG_MACSEC_OFFLOAD_ON) {
+			/* try MAC, then PHY, and also OFF (only for PREFER) */
+			wpa_printf(MSG_DEBUG, DRV_PREFIX
+				   "%s: attempting MACSEC_OFFLOAD_MAC",
+				   drv->ifname);
+			rtnl_link_macsec_set_offload(drv->link, MACSEC_OFFLOAD_MAC);
+			if (rtnl_link_add(drv->sk, drv->link, 0) >= 0)
+				goto end;
+
+			wpa_printf(MSG_DEBUG, DRV_PREFIX
+				   "%s: attempting MACSEC_OFFLOAD_PHY",
+				   drv->ifname);
+			rtnl_link_macsec_set_offload(drv->link, MACSEC_OFFLOAD_PHY);
+			if (rtnl_link_add(drv->sk, drv->link, 0) >= 0)
+				goto end;
+
+			if (drv->offload == CONFIG_MACSEC_OFFLOAD_ON) {
+				wpa_printf(MSG_DEBUG, DRV_PREFIX
+					   "%s: offload was requested but couldn't be set",
+					   drv->ifname);
+				return -1;
+			}
 
-	if (drv->encoding_sa_set) {
-		wpa_printf(MSG_DEBUG, DRV_PREFIX
-			   "%s: try_commit encoding_sa=%d",
-			   drv->ifname, drv->encoding_sa);
-		rtnl_link_macsec_set_encoding_sa(drv->link, drv->encoding_sa);
+			wpa_printf(MSG_DEBUG, DRV_PREFIX
+				   "%s: attempting MACSEC_OFFLOAD_OFF",
+				   drv->ifname);
+			rtnl_link_macsec_set_offload(drv->link, MACSEC_OFFLOAD_OFF);
+			if (rtnl_link_add(drv->sk, drv->link, 0) >= 0)
+				goto end;
+
+			return -1;
+		}
+
+		switch (drv->offload) {
+		case CONFIG_MACSEC_OFFLOAD_MAC:
+			offload_value = MACSEC_OFFLOAD_MAC;
+			break;
+		case CONFIG_MACSEC_OFFLOAD_PHY:
+			offload_value = MACSEC_OFFLOAD_PHY;
+			break;
+		default:
+			offload_value = MACSEC_OFFLOAD_OFF;
+			break;
+		}
+		rtnl_link_macsec_set_offload(drv->link, offload_value);
 	}
+#endif /* LIBNL_HAS_OFFLOAD */
 
 	err = rtnl_link_add(drv->sk, drv->link, 0);
 	if (err < 0)
 		return err;
 
+#ifdef LIBNL_HAS_OFFLOAD
+end:
+#endif /* LIBNL_HAS_OFFLOAD */
 	drv->protect_frames_set = false;
 	drv->encrypt_set = false;
 	drv->replay_protect_set = false;
@@ -476,9 +527,7 @@ static int macsec_drv_set_replay_protect(void *priv, bool enabled,
 /**
  * macsec_drv_set_offload - Set offload status
  * @priv: Private driver interface data
- * @offload: 0 = MACSEC_OFFLOAD_OFF
- *           1 = MACSEC_OFFLOAD_PHY
- *           2 = MACSEC_OFFLOAD_MAC
+ * @offload: see enum macsec_offload_modes
  * Returns: 0 on success, -1 on failure (or if not supported)
  */
 static int macsec_drv_set_offload(void *priv, u8 offload)
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index fca4320a19f2..e8dc14c4fa13 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2280,6 +2280,30 @@ static int wpa_config_parse_mka_ckn(const struct parse_data *data,
 	return 0;
 }
 
+const char *macsec_offload_strings[NUM_CONFIG_MACSEC_OFFLOAD_MODES] = {
+	"off",
+	"on",
+	"mac",
+	"phy",
+	"prefer",
+};
+static int wpa_config_parse_macsec_offload(const struct parse_data *data,
+					   struct wpa_ssid *ssid, int line,
+					   const char *value)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(macsec_offload_strings); i++) {
+		if (os_strcmp(macsec_offload_strings[i], value) == 0) {
+			ssid->macsec_offload = i;
+			return 0;
+		}
+	}
+
+	wpa_printf(MSG_ERROR, "Line %d: Invalid macsec_offload: '%s'.",
+		  line, value);
+	return -1;
+}
 
 #ifndef NO_CONFIG_WRITE
 
@@ -2301,6 +2325,16 @@ static char * wpa_config_write_mka_ckn(const struct parse_data *data,
 	return wpa_config_write_string_hex(ssid->mka_ckn, ssid->mka_ckn_len);
 }
 
+static char * wpa_config_write_macsec_offload(const struct parse_data *data,
+					      struct wpa_ssid *ssid)
+{
+	const char *str = macsec_offload_strings[ssid->macsec_offload];
+
+	if (ssid->macsec_offload >= ARRAY_SIZE(macsec_offload_strings))
+		return NULL;
+	return wpa_config_write_string_ascii((const u8 *)str, strlen(str));
+}
+
 #endif /* NO_CONFIG_WRITE */
 
 #endif /* CONFIG_MACSEC */
@@ -2694,7 +2728,7 @@ static const struct parse_data ssid_fields[] = {
 	{ INT_RANGE(macsec_integ_only, 0, 1) },
 	{ INT_RANGE(macsec_replay_protect, 0, 1) },
 	{ INT(macsec_replay_window) },
-	{ INT_RANGE(macsec_offload, 0, 2) },
+	{ FUNC_KEY(macsec_offload) },
 	{ INT_RANGE(macsec_port, 1, 65534) },
 	{ INT_RANGE(mka_priority, 0, 255) },
 	{ INT_RANGE(macsec_csindex, 0, 1) },
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 4db85f9c07e1..80e40e47c97e 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -663,6 +663,12 @@ static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid)
 	os_free(value);
 }
 
+static void write_macsec_offload(FILE *f, struct wpa_ssid *ssid)
+{
+	if (ssid->macsec_offload < ARRAY_SIZE(macsec_offload_strings))
+		fprintf(f, "\tmacsecoffload=%s\n", macsec_offload_strings[ssid->macsec_offload]);
+}
+
 #endif /* CONFIG_MACSEC */
 
 
@@ -814,7 +820,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 	INT(macsec_integ_only);
 	INT(macsec_replay_protect);
 	INT(macsec_replay_window);
-	INT(macsec_offload);
+	write_macsec_offload(f, ssid);
 	INT(macsec_port);
 	INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
 	INT(macsec_csindex);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index ff045380ec96..c9d0ea195eed 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -934,9 +934,7 @@ struct wpa_ssid {
 	 * This setting applies only when MACsec is in use, i.e.,
 	 *  - the key server has decided to enable MACsec
 	 *
-	 * 0 = MACSEC_OFFLOAD_OFF (default)
-	 * 1 = MACSEC_OFFLOAD_PHY
-	 * 2 = MACSEC_OFFLOAD_MAC
+	 * Values: macsec_offload_modes
 	 */
 	int macsec_offload;
 
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 6ad49a1360ef..b1fed41f4b32 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -152,6 +152,9 @@ static const char * const dont_quote[] = {
 #ifdef CONFIG_INTERWORKING
 	"roaming_consortium", "required_roaming_consortium",
 #endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_MACSEC
+	"macsec_offload",
+#endif /* CONFIG_MACSEC */
 	"mac_value", NULL
 };
 
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 743f2a323e0e..74a6002cc01b 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1150,13 +1150,13 @@ fast_reauth=1
 # 1..2^32-1: number of packets that could be misordered
 #
 # macsec_offload - Enable MACsec hardware offload
-#
 # This setting applies only when MACsec is in use, i.e.,
 #  - the key server has decided to enable MACsec
-#
-# 0 = MACSEC_OFFLOAD_OFF (default)
-# 1 = MACSEC_OFFLOAD_PHY
-# 2 = MACSEC_OFFLOAD_MAC
+# off = don't offload (default)
+# mac = request offload to the MAC
+# phy = request offload to the PHY
+# on = request offload (to either MAC or PHY)
+# prefer = try to offload (to either MAC or PHY), fall back to software
 #
 # macsec_port: IEEE 802.1X/MACsec port
 # Port component of the SCI
-- 
2.43.0


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux