]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations
authorPeddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
Mon, 20 Apr 2026 09:08:46 +0000 (14:38 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 5 May 2026 11:28:57 +0000 (13:28 +0200)
Add a new wdev-only interface type NL80211_IFTYPE_PD to support
Proximity Detection (PD) operations such as PASN and peer measurement
operations. This interface type operates without a netdev, similar to
P2P_DEVICE and NAN interfaces.

Implement support across cfg80211 and mac80211 layers with PD-specific
checks gated by the NL80211_EXT_FEATURE_SECURE_RTT feature flag,
management frame registration and transmission capabilities, and proper
channel context handling where PD interfaces are excluded from bandwidth
calculations. Update mac80211 to recognize the new interface type in the
relevant paths for this management-only interface.

PD discovery can be performed on any available interface, such as
NL80211_IFTYPE_STATION.

If PD/PMSR uses the MAC address of an existing interface type, such as
NL80211_IFTYPE_STATION, then pairing and measurement shall use that
same interface. If PD/PMSR uses a different MAC address, such as a
random MAC address, then pairing and measurement can be performed on a
new NL80211_IFTYPE_PD interface created with that random MAC address.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
Link: https://patch.msgid.link/20260420090856.2152905-4-peddolla.reddy@oss.qualcomm.com
[fix comment style]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
13 files changed:
include/uapi/linux/nl80211.h
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/iface.c
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/util.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/util.c

index 8103f2912abc50d7124afc93908499d9df01b6f7..69e13cd7978a1618f628d39d2bc9ed02813e0130 100644 (file)
@@ -3842,6 +3842,7 @@ enum nl80211_attrs {
  * @NL80211_IFTYPE_NAN_DATA: NAN data interface type (netdev); NAN data
  *     interfaces can only be brought up (IFF_UP) when a NAN interface
  *     already exists and NAN has been started (using %NL80211_CMD_START_NAN).
+ * @NL80211_IFTYPE_PD: PD device interface type (not a netdev)
  * @NL80211_IFTYPE_MAX: highest interface type number currently defined
  * @NUM_NL80211_IFTYPES: number of defined interface types
  *
@@ -3864,6 +3865,7 @@ enum nl80211_iftype {
        NL80211_IFTYPE_OCB,
        NL80211_IFTYPE_NAN,
        NL80211_IFTYPE_NAN_DATA,
+       NL80211_IFTYPE_PD,
 
        /* keep last */
        NUM_NL80211_IFTYPES,
index c71af8878562ccac03e7090bde21639f4aa5ae74..413dd73e8815952eee16ce37141a00e09c05eeac 100644 (file)
@@ -716,6 +716,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
        case NL80211_IFTYPE_WDS:
        case NL80211_IFTYPE_MONITOR:
        case NL80211_IFTYPE_P2P_DEVICE:
+       case NL80211_IFTYPE_PD:
        case NL80211_IFTYPE_UNSPECIFIED:
        case NUM_NL80211_IFTYPES:
        case NL80211_IFTYPE_P2P_CLIENT:
@@ -3459,6 +3460,7 @@ static int ieee80211_scan(struct wiphy *wiphy,
                }
                break;
        case NL80211_IFTYPE_NAN:
+       case NL80211_IFTYPE_PD:
        default:
                return -EOPNOTSUPP;
        }
index 9683d3e6e1d2a40e9d2d7a8cb0f499285ccc96c5..16ee79566e50e38004929b03a872ffbb13d8a69d 100644 (file)
@@ -535,6 +535,7 @@ ieee80211_get_width_of_link(struct ieee80211_link_data *link)
        case NL80211_IFTYPE_P2P_GO:
        case NL80211_IFTYPE_NAN:
        case NL80211_IFTYPE_NAN_DATA:
+       case NL80211_IFTYPE_PD:
                WARN_ON_ONCE(1);
                break;
        }
@@ -1532,6 +1533,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
        case NL80211_IFTYPE_P2P_DEVICE:
        case NL80211_IFTYPE_NAN:
        case NL80211_IFTYPE_NAN_DATA:
+       case NL80211_IFTYPE_PD:
        case NUM_NL80211_IFTYPES:
                WARN_ON(1);
                break;
index 683d8db4da1432e035ed2e98348216650dda25eb..84e8e78d157366d637c143c988e7d6c55552aa8a 100644 (file)
@@ -1400,6 +1400,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
        case NL80211_IFTYPE_P2P_DEVICE:
        case NL80211_IFTYPE_OCB:
        case NL80211_IFTYPE_NAN:
+       case NL80211_IFTYPE_PD:
                /* no special treatment */
                break;
        case NL80211_IFTYPE_NAN_DATA:
@@ -1532,7 +1533,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                                                FIF_PROBE_REQ);
 
                if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
-                   sdata->vif.type != NL80211_IFTYPE_NAN)
+                   sdata->vif.type != NL80211_IFTYPE_NAN &&
+                   sdata->vif.type != NL80211_IFTYPE_PD)
                        changed |= ieee80211_reset_erp_info(sdata);
                ieee80211_link_info_change_notify(sdata, &sdata->deflink,
                                                  changed);
@@ -1548,6 +1550,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                        break;
                case NL80211_IFTYPE_P2P_DEVICE:
                case NL80211_IFTYPE_NAN:
+               case NL80211_IFTYPE_PD:
                        break;
                default:
                        /* not reached */
@@ -1988,6 +1991,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.bssid = sdata->vif.addr;
                break;
        case NL80211_IFTYPE_NAN_DATA:
+       case NL80211_IFTYPE_PD:
                break;
        case NL80211_IFTYPE_UNSPECIFIED:
        case NL80211_IFTYPE_WDS:
index 83e4be06039e30ee2a0acd5492733babe523ef99..8bec39b099a09dee737bffdaef82246735aff5db 100644 (file)
@@ -895,6 +895,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                }
                break;
        case NL80211_IFTYPE_P2P_DEVICE:
+       case NL80211_IFTYPE_PD:
                need_offchan = true;
                break;
        case NL80211_IFTYPE_NAN:
index e1f376e0620c348ff4fdd3538a4bc594235501b7..4c788328c8205350d847122792faceadac2dac51 100644 (file)
@@ -4672,6 +4672,13 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
                /* Unicast secure management frames */
                return ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
                       ieee80211_is_unicast_robust_mgmt_frame(skb);
+       case NL80211_IFTYPE_PD:
+               /*
+                * Accept only authentication frames (PASN) addressed to
+                * this interface.
+                */
+               return ieee80211_is_auth(hdr->frame_control) &&
+                      ether_addr_equal(sdata->vif.addr, hdr->addr1);
        default:
                break;
        }
index 89e82d34ae48389ff370c774d8152a50920d05e5..61ec2116fab23e2104dfd3dfb0caf6ba37183e27 100644 (file)
@@ -2210,6 +2210,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                case NL80211_IFTYPE_AP_VLAN:
                case NL80211_IFTYPE_MONITOR:
                case NL80211_IFTYPE_P2P_DEVICE:
+               case NL80211_IFTYPE_PD:
                        /* nothing to do */
                        break;
                case NL80211_IFTYPE_UNSPECIFIED:
index 8b94c0de80adea26af901c58beab1781bfa7a62d..8954ac1659c172f8587387050f29a7a3d501900f 100644 (file)
@@ -817,6 +817,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
        case NL80211_IFTYPE_AP_VLAN:
        case NL80211_IFTYPE_P2P_DEVICE:
        case NL80211_IFTYPE_NAN_DATA:
+       case NL80211_IFTYPE_PD:
                break;
        case NL80211_IFTYPE_WDS:
        case NL80211_IFTYPE_UNSPECIFIED:
@@ -941,6 +942,7 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
        /* Can NAN type be considered as beaconing interface? */
        case NL80211_IFTYPE_NAN:
        case NL80211_IFTYPE_NAN_DATA:
+       case NL80211_IFTYPE_PD:
                break;
        case NL80211_IFTYPE_UNSPECIFIED:
        case NL80211_IFTYPE_WDS:
index 345a83fe428fe6794b51b4b00dabf3aaa42c0d9e..9a6f8ffe7ba9dc2b93c7a20662ecb4a2d00d060d 100644 (file)
@@ -1519,6 +1519,7 @@ void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
        case NL80211_IFTYPE_AP_VLAN:
        case NL80211_IFTYPE_MONITOR:
        case NL80211_IFTYPE_NAN_DATA:
+       case NL80211_IFTYPE_PD:
                /* nothing to do */
                break;
        case NL80211_IFTYPE_UNSPECIFIED:
index d196b5c086ccc7f200ac93e9fa737ed62803158d..50ee462e5eac43272e92ac6b9ff7be118032e44a 100644 (file)
@@ -945,6 +945,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                         * fall through, P2P device only supports
                         * public action frames
                         */
+               case NL80211_IFTYPE_PD:
                default:
                        err = -EOPNOTSUPP;
                        break;
index c5879056e6940e77e957f5557ffe58a5eadf6d1d..85096c8964ff03d19bf9962b0dc7f8752f59357e 100644 (file)
@@ -1842,6 +1842,11 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
                                            NL80211_EXT_FEATURE_SECURE_NAN))
                        return 0;
                return -EINVAL;
+       case NL80211_IFTYPE_PD:
+               if (wiphy_ext_feature_isset(wdev->wiphy,
+                                           NL80211_EXT_FEATURE_SECURE_RTT))
+                       return 0;
+               return -EINVAL;
        case NL80211_IFTYPE_UNSPECIFIED:
        case NL80211_IFTYPE_OCB:
        case NL80211_IFTYPE_MONITOR:
@@ -4938,6 +4943,7 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                return -EOPNOTSUPP;
 
        if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
+            type == NL80211_IFTYPE_PD ||
             rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
            info->attrs[NL80211_ATTR_MAC]) {
                nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
@@ -4994,8 +5000,9 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                break;
        case NL80211_IFTYPE_NAN:
        case NL80211_IFTYPE_P2P_DEVICE:
+       case NL80211_IFTYPE_PD:
                /*
-                * P2P Device and NAN do not have a netdev, so don't go
+                * P2P Device, NAN and PD do not have a netdev, so don't go
                 * through the netdev notifier and must be added here
                 */
                cfg80211_init_wdev(wdev);
@@ -10869,7 +10876,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 
        wiphy = &rdev->wiphy;
 
-       if (wdev->iftype == NL80211_IFTYPE_NAN)
+       if (wdev->iftype == NL80211_IFTYPE_NAN ||
+           wdev->iftype == NL80211_IFTYPE_PD)
                return -EOPNOTSUPP;
 
        if (!rdev->ops->scan)
@@ -14290,6 +14298,11 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
                      WIPHY_NAN_FLAGS_USERSPACE_DE))
                        return -EOPNOTSUPP;
                break;
+       case NL80211_IFTYPE_PD:
+               if (!wiphy_ext_feature_isset(wdev->wiphy,
+                                            NL80211_EXT_FEATURE_SECURE_RTT))
+                       return -EOPNOTSUPP;
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -14354,6 +14367,11 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                      WIPHY_NAN_FLAGS_USERSPACE_DE))
                        return -EOPNOTSUPP;
                break;
+       case NL80211_IFTYPE_PD:
+               if (!wiphy_ext_feature_isset(wdev->wiphy,
+                                            NL80211_EXT_FEATURE_SECURE_RTT))
+                       return -EOPNOTSUPP;
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -14479,6 +14497,11 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
                                             NL80211_EXT_FEATURE_SECURE_NAN))
                        return -EOPNOTSUPP;
                break;
+       case NL80211_IFTYPE_PD:
+               if (!wiphy_ext_feature_isset(wdev->wiphy,
+                                            NL80211_EXT_FEATURE_SECURE_RTT))
+                       return -EOPNOTSUPP;
+               break;
        default:
                return -EOPNOTSUPP;
        }
index 5db2121c0b570b7a1efb510c700c6f8aded5c4e7..1e8214d6b6d8818eb47f70f00c10c963f3546441 100644 (file)
@@ -2412,6 +2412,9 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
                case NL80211_IFTYPE_NAN_DATA:
                        /* NAN channels are checked in NL80211_IFTYPE_NAN interface */
                        break;
+               case NL80211_IFTYPE_PD:
+                       /* we have no info, but PD is also pretty universal */
+                       continue;
                default:
                        /* others not implemented for now */
                        WARN_ON_ONCE(1);
index 95ae06e94f10c6effca20e37c0f105b8fccf3b06..b638e205c71eaa9994e9c312eda9645fcab5bb53 100644 (file)
@@ -1211,7 +1211,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
 
        /* cannot change into P2P device or NAN */
        if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
-           ntype == NL80211_IFTYPE_NAN)
+           ntype == NL80211_IFTYPE_NAN ||
+           ntype == NL80211_IFTYPE_PD)
                return -EOPNOTSUPP;
 
        if (!rdev->ops->change_virtual_intf ||
@@ -1276,6 +1277,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
                case NL80211_IFTYPE_P2P_DEVICE:
                case NL80211_IFTYPE_WDS:
                case NL80211_IFTYPE_NAN:
+               case NL80211_IFTYPE_PD:
                        WARN_ON(1);
                        break;
                }