Base on EasyMesh spec and traffic separation we have: "If a Multi-AP Agent configures a Primary VLAN ID, the Multi-AP Agent shall send EtherType 0x888E frames on a Wi-Fi link in a Multi-AP Profile-2 Network Segment with an 802.1Q C-Tag with VLAN ID equal to the Primary VLAN ID." Add option that extend current control port implementation when NL80211_ATTR_CONTROL_PORT_OVER_NL80211_VLAN used and allow to setup VLAN id for control port frames for both TX/RX direction. When set for RX direction: - lower layer should check vlan id and strip 8021Q header before pass it to usermode When set for TX direction: - lower layer should add proper 8021Q header Signed-off-by: Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx> --- include/net/cfg80211.h | 8 +++++++- include/uapi/linux/nl80211.h | 8 +++++++- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/tx.c | 2 +- net/wireless/nl80211.c | 20 +++++++++++++++++++- net/wireless/rdev-ops.h | 7 ++++--- net/wireless/trace.h | 12 ++++++++---- 7 files changed, 47 insertions(+), 12 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4072a67c9cc9..ad0bee7e6813 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1485,6 +1485,11 @@ struct cfg80211_s1g_short_beacon { * @mbssid_config: AP settings for multiple bssid * @s1g_long_beacon_period: S1G long beacon period * @s1g_short_beacon: S1G short beacon data + * @control_port_vlan_id: if set (nonzero) userspace expect to receive also + * 8021Q tagged control port protocol frames. Verification of VLAN id + * should be done in lower layer. Also 8021Q header should be stripped. + * For tx path userspace expect lower layer will add proper 8021Q header + * and setup VLAN id. */ struct cfg80211_ap_settings { struct cfg80211_chan_def chandef; @@ -1520,6 +1525,7 @@ struct cfg80211_ap_settings { struct cfg80211_mbssid_config mbssid_config; u8 s1g_long_beacon_period; struct cfg80211_s1g_short_beacon s1g_short_beacon; + u16 control_port_vlan_id; }; @@ -5091,7 +5097,7 @@ struct cfg80211_ops { const u8 *buf, size_t len, const u8 *dest, const __be16 proto, const bool noencrypt, int link_id, - u64 *cookie); + u64 *cookie, u16 vlan_id); int (*get_ftm_responder_stats)(struct wiphy *wiphy, struct net_device *dev, diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index aed0b4c5d5e8..19f6d69ac7d0 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2680,7 +2680,8 @@ enum nl80211_commands { * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. * * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key - * (u16). + * (u16). For %NL80211_ATTR_CONTROL_PORT_OVER_NL80211_VLAN allow to + * receive and send tagged (8021Q) control port packets. * * @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings. * @@ -6692,6 +6693,10 @@ enum nl80211_feature_flags { * * @NL80211_EXT_FEATURE_BEACON_RATE_EHT: Driver supports beacon rate * configuration (AP/mesh) with EHT rates. + * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_VLAN: Driver supports + * sending and receiving control port frames over nl80211 with VLAN + * support. Userspace can provide a VLAN ID in the control port request + * to send packets on that VLAN. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -6769,6 +6774,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_DFS_CONCURRENT, NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT, NL80211_EXT_FEATURE_BEACON_RATE_EHT, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_VLAN, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8a666faeb1ec..2c785ecf70f0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2165,7 +2165,7 @@ void ieee80211_clear_fast_xmit(struct sta_info *sta); int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len, const u8 *dest, __be16 proto, bool unencrypted, - int link_id, u64 *cookie); + int link_id, u64 *cookie, u16 vlan_id); int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len); void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a27e2af5d569..8e0221f68fa7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -6312,7 +6312,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len, const u8 *dest, __be16 proto, bool unencrypted, - int link_id, u64 *cookie) + int link_id, u64 *cookie, u16 vlan_id) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b7bc7e5e81dd..2247cb5c75e3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6607,6 +6607,16 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) if (err) goto out; + if (info->attrs[NL80211_ATTR_VLAN_ID]) { + if (!wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_VLAN)) { + err = -EOPNOTSUPP; + goto out; + } + params->control_port_vlan_id = + nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]); + } + if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) { if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) { err = -EOPNOTSUPP; @@ -16745,6 +16755,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) u8 *dest; u16 proto; bool noencrypt; + u16 vlan_id = 0; u64 cookie = 0; int link_id; int err; @@ -16790,9 +16801,16 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) link_id = nl80211_link_id_or_invalid(info->attrs); + if (info->attrs[NL80211_ATTR_VLAN_ID]) { + if (!wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_VLAN)) + return -EOPNOTSUPP; + vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]); + } + err = rdev_tx_control_port(rdev, dev, buf, len, dest, cpu_to_be16(proto), noencrypt, link_id, - dont_wait_for_ack ? NULL : &cookie); + dont_wait_for_ack ? NULL : &cookie, vlan_id); if (!err && !dont_wait_for_ack) nl_set_extack_cookie_u64(info->extack, cookie); return err; diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index ac6884bacf3f..5b1e629ee3e8 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -774,13 +774,14 @@ static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev, const void *buf, size_t len, const u8 *dest, __be16 proto, const bool noencrypt, int link, - u64 *cookie) + u64 *cookie, u16 vlan_id) { int ret; trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len, - dest, proto, noencrypt, link); + dest, proto, noencrypt, link, vlan_id); ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len, - dest, proto, noencrypt, link, cookie); + dest, proto, noencrypt, link, + cookie, vlan_id); if (cookie) trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); else diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 9b6074155d59..16367fee8fec 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2202,8 +2202,8 @@ TRACE_EVENT(rdev_mgmt_tx, TRACE_EVENT(rdev_tx_control_port, TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *buf, size_t len, const u8 *dest, __be16 proto, - bool unencrypted, int link_id), - TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted, link_id), + bool unencrypted, int link_id, u16 vlan_id), + TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted, link_id, vlan_id), TP_STRUCT__entry( WIPHY_ENTRY NETDEV_ENTRY @@ -2211,6 +2211,7 @@ TRACE_EVENT(rdev_tx_control_port, __field(__be16, proto) __field(bool, unencrypted) __field(int, link_id) + __field(u16, vlan_id) ), TP_fast_assign( WIPHY_ASSIGN; @@ -2219,13 +2220,16 @@ TRACE_EVENT(rdev_tx_control_port, __entry->proto = proto; __entry->unencrypted = unencrypted; __entry->link_id = link_id; + __entry->vlan_id = vlan_id; ), TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM," - " proto: 0x%x, unencrypted: %s, link: %d", + " proto: 0x%x, unencrypted: %s, link: %d," + " vlan_id: %hu", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->dest, be16_to_cpu(__entry->proto), BOOL_TO_STR(__entry->unencrypted), - __entry->link_id) + __entry->link_id, + __entry->vlan_id) ); TRACE_EVENT(rdev_set_noack_map, -- 2.43.0