Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211_hwsim: notify wmediumd of used MAC addresses

Currently, wmediumd requires each used MAC address to be configured
as a station in the virtual air, but that doesn't make sense as any
station could have multiple MAC addresses, and even have randomized
ones in scanning, etc.

Add some code here to tell wmediumd of used MAC addresses, binding
them to the hardware address. Combined with a wmediumd patch that
makes it track the addresses this allows configuring just the radio
address (42:00:00:00:nn:00 unless the radio was manually created)
in wmediumd as a station, and all addresses that the station uses
are added/removed dynamically.

Tested with random scan, which without this and the corresponding
wmediumd change doesn't get anything through as the sender doesn't
exist as far as wmediumd is concerned (it's random).

Link: https://lore.kernel.org/r/20200323162358.b397b1a1acef.Ice0536e34e5d96c51f97c374ea8af9551347c7e8@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+59
+51
drivers/net/wireless/mac80211_hwsim.c
··· 1068 1068 return res; 1069 1069 } 1070 1070 1071 + static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw, 1072 + const u8 *addr, bool add) 1073 + { 1074 + struct mac80211_hwsim_data *data = hw->priv; 1075 + u32 _portid = READ_ONCE(data->wmediumd); 1076 + struct sk_buff *skb; 1077 + void *msg_head; 1078 + 1079 + if (!_portid && !hwsim_virtio_enabled) 1080 + return; 1081 + 1082 + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1083 + if (!skb) 1084 + return; 1085 + 1086 + msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, 1087 + add ? HWSIM_CMD_ADD_MAC_ADDR : 1088 + HWSIM_CMD_DEL_MAC_ADDR); 1089 + if (!msg_head) { 1090 + pr_debug("mac80211_hwsim: problem with msg_head\n"); 1091 + goto nla_put_failure; 1092 + } 1093 + 1094 + if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, 1095 + ETH_ALEN, data->addresses[1].addr)) 1096 + goto nla_put_failure; 1097 + 1098 + if (nla_put(skb, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN, addr)) 1099 + goto nla_put_failure; 1100 + 1101 + genlmsg_end(skb, msg_head); 1102 + 1103 + if (hwsim_virtio_enabled) 1104 + hwsim_tx_virtio(data, skb); 1105 + else 1106 + hwsim_unicast_netgroup(data, skb, _portid); 1107 + return; 1108 + nla_put_failure: 1109 + nlmsg_free(skb); 1110 + } 1111 + 1071 1112 static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate) 1072 1113 { 1073 1114 u16 result = 0; ··· 1586 1545 vif->addr); 1587 1546 hwsim_set_magic(vif); 1588 1547 1548 + if (vif->type != NL80211_IFTYPE_MONITOR) 1549 + mac80211_hwsim_config_mac_nl(hw, vif->addr, true); 1550 + 1589 1551 vif->cab_queue = 0; 1590 1552 vif->hw_queue[IEEE80211_AC_VO] = 0; 1591 1553 vif->hw_queue[IEEE80211_AC_VI] = 1; ··· 1628 1584 vif->addr); 1629 1585 hwsim_check_magic(vif); 1630 1586 hwsim_clear_magic(vif); 1587 + if (vif->type != NL80211_IFTYPE_MONITOR) 1588 + mac80211_hwsim_config_mac_nl(hw, vif->addr, false); 1631 1589 } 1632 1590 1633 1591 static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, ··· 2150 2104 hwsim->hw_scan_vif = NULL; 2151 2105 hwsim->tmp_chan = NULL; 2152 2106 mutex_unlock(&hwsim->mutex); 2107 + mac80211_hwsim_config_mac_nl(hwsim->hw, hwsim->scan_addr, 2108 + false); 2153 2109 return; 2154 2110 } 2155 2111 ··· 2225 2177 memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); 2226 2178 mutex_unlock(&hwsim->mutex); 2227 2179 2180 + mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true); 2228 2181 wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n"); 2229 2182 2230 2183 ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); ··· 2269 2220 pr_debug("hwsim sw_scan request, prepping stuff\n"); 2270 2221 2271 2222 memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); 2223 + mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true); 2272 2224 hwsim->scanning = true; 2273 2225 memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); 2274 2226 ··· 2286 2236 2287 2237 pr_debug("hwsim sw_scan_complete\n"); 2288 2238 hwsim->scanning = false; 2239 + mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, false); 2289 2240 eth_zero_addr(hwsim->scan_addr); 2290 2241 2291 2242 mutex_unlock(&hwsim->mutex);
+8
drivers/net/wireless/mac80211_hwsim.h
··· 75 75 * @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted 76 76 * @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses: 77 77 * %HWSIM_ATTR_RADIO_ID 78 + * @HWSIM_CMD_ADD_MAC_ADDR: add a receive MAC address (given in the 79 + * %HWSIM_ATTR_ADDR_RECEIVER attribute) to a device identified by 80 + * %HWSIM_ATTR_ADDR_TRANSMITTER. This lets wmediumd forward frames 81 + * to this receiver address for a given station. 82 + * @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes 83 + * are the same as to @HWSIM_CMD_ADD_MAC_ADDR. 78 84 * @__HWSIM_CMD_MAX: enum limit 79 85 */ 80 86 enum { ··· 91 85 HWSIM_CMD_NEW_RADIO, 92 86 HWSIM_CMD_DEL_RADIO, 93 87 HWSIM_CMD_GET_RADIO, 88 + HWSIM_CMD_ADD_MAC_ADDR, 89 + HWSIM_CMD_DEL_MAC_ADDR, 94 90 __HWSIM_CMD_MAX, 95 91 }; 96 92 #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)