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. 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/wpa_supplicant.conf | 10 ++-- 10 files changed, 152 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/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