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

mac80211: add TDLS channel-switch Rx flow

When receiving a TDLS channel switch request or response, parse the frame
and call a new tdls_recv_channel_switch op in the low level driver with
the parsed data.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Arik Nemtsov and committed by
Johannes Berg
8a4d32f3 a7a6bdd0

+449 -2
+36 -1
include/net/mac80211.h
··· 1827 1827 }; 1828 1828 1829 1829 /** 1830 + * struct ieee80211_tdls_ch_sw_params - TDLS channel switch parameters 1831 + * 1832 + * @sta: peer this TDLS channel-switch request/response came from 1833 + * @chandef: channel referenced in a TDLS channel-switch request 1834 + * @action_code: see &enum ieee80211_tdls_actioncode 1835 + * @status: channel-switch response status 1836 + * @timestamp: time at which the frame was received 1837 + * @switch_time: switch-timing parameter received in the frame 1838 + * @switch_timeout: switch-timing parameter received in the frame 1839 + * @tmpl_skb: TDLS switch-channel response template 1840 + * @ch_sw_tm_ie: offset of the channel-switch timing IE inside @tmpl_skb 1841 + */ 1842 + struct ieee80211_tdls_ch_sw_params { 1843 + struct ieee80211_sta *sta; 1844 + struct cfg80211_chan_def *chandef; 1845 + u8 action_code; 1846 + u32 status; 1847 + u32 timestamp; 1848 + u16 switch_time; 1849 + u16 switch_timeout; 1850 + struct sk_buff *tmpl_skb; 1851 + u32 ch_sw_tm_ie; 1852 + }; 1853 + 1854 + /** 1830 1855 * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy 1831 1856 * 1832 1857 * @wiphy: the &struct wiphy which we want to query ··· 2950 2925 * optionally copy the skb for further re-use. 2951 2926 * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both 2952 2927 * peers must be on the base channel when the call completes. 2928 + * @tdls_recv_channel_switch: a TDLS channel-switch related frame (request or 2929 + * response) has been received from a remote peer. The driver gets 2930 + * parameters parsed from the incoming frame and may use them to continue 2931 + * an ongoing channel-switch operation. In addition, a channel-switch 2932 + * response template is provided, together with the location of the 2933 + * switch-timing IE within the template. The skb can only be used within 2934 + * the function call. 2953 2935 */ 2954 2936 struct ieee80211_ops { 2955 2937 void (*tx)(struct ieee80211_hw *hw, ··· 3173 3141 struct ieee80211_vif *vif, 3174 3142 struct ieee80211_sta *sta, u8 oper_class, 3175 3143 struct cfg80211_chan_def *chandef, 3176 - struct sk_buff *skb, u32 ch_sw_tm_ie); 3144 + struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie); 3177 3145 void (*tdls_cancel_channel_switch)(struct ieee80211_hw *hw, 3178 3146 struct ieee80211_vif *vif, 3179 3147 struct ieee80211_sta *sta); 3148 + void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw, 3149 + struct ieee80211_vif *vif, 3150 + struct ieee80211_tdls_ch_sw_params *params); 3180 3151 }; 3181 3152 3182 3153 /**
+12
net/mac80211/driver-ops.h
··· 1337 1337 trace_drv_return_void(local); 1338 1338 } 1339 1339 1340 + static inline void 1341 + drv_tdls_recv_channel_switch(struct ieee80211_local *local, 1342 + struct ieee80211_sub_if_data *sdata, 1343 + struct ieee80211_tdls_ch_sw_params *params) 1344 + { 1345 + trace_drv_tdls_recv_channel_switch(local, sdata, params); 1346 + if (local->ops->tdls_recv_channel_switch) 1347 + local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif, 1348 + params); 1349 + trace_drv_return_void(local); 1350 + } 1351 + 1340 1352 #endif /* __MAC80211_DRIVER_OPS */
+3
net/mac80211/ieee80211_i.h
··· 993 993 IEEE80211_SDATA_QUEUE_AGG_STOP = 2, 994 994 IEEE80211_SDATA_QUEUE_RX_AGG_START = 3, 995 995 IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4, 996 + IEEE80211_SDATA_QUEUE_TDLS_CHSW = 5, 996 997 }; 997 998 998 999 enum { ··· 2014 2013 void ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy, 2015 2014 struct net_device *dev, 2016 2015 const u8 *addr); 2016 + void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata, 2017 + struct sk_buff *skb); 2017 2018 2018 2019 extern const struct ethtool_ops ieee80211_ethtool_ops; 2019 2020
+2
net/mac80211/iface.c
··· 1202 1202 WLAN_BACK_RECIPIENT, 0, 1203 1203 false); 1204 1204 mutex_unlock(&local->sta_mtx); 1205 + } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_TDLS_CHSW) { 1206 + ieee80211_process_tdls_channel_switch(sdata, skb); 1205 1207 } else if (ieee80211_is_action(mgmt->frame_control) && 1206 1208 mgmt->u.action.category == WLAN_CATEGORY_BACK) { 1207 1209 int len = skb->len;
+2 -1
net/mac80211/main.c
··· 766 766 767 767 if ((hw->wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) && 768 768 (!local->ops->tdls_channel_switch || 769 - !local->ops->tdls_cancel_channel_switch)) 769 + !local->ops->tdls_cancel_channel_switch || 770 + !local->ops->tdls_recv_channel_switch)) 770 771 return -EOPNOTSUPP; 771 772 772 773 #ifdef CONFIG_PM
+21
net/mac80211/rx.c
··· 2333 2333 if (!ieee80211_frame_allowed(rx, fc)) 2334 2334 return RX_DROP_MONITOR; 2335 2335 2336 + /* directly handle TDLS channel switch requests/responses */ 2337 + if (unlikely(((struct ethhdr *)rx->skb->data)->h_proto == 2338 + cpu_to_be16(ETH_P_TDLS))) { 2339 + struct ieee80211_tdls_data *tf = (void *)rx->skb->data; 2340 + 2341 + if (pskb_may_pull(rx->skb, 2342 + offsetof(struct ieee80211_tdls_data, u)) && 2343 + tf->payload_type == WLAN_TDLS_SNAP_RFTYPE && 2344 + tf->category == WLAN_CATEGORY_TDLS && 2345 + (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST || 2346 + tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) { 2347 + rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TDLS_CHSW; 2348 + skb_queue_tail(&sdata->skb_queue, rx->skb); 2349 + ieee80211_queue_work(&rx->local->hw, &sdata->work); 2350 + if (rx->sta) 2351 + rx->sta->rx_packets++; 2352 + 2353 + return RX_QUEUED; 2354 + } 2355 + } 2356 + 2336 2357 if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && 2337 2358 unlikely(port_control) && sdata->bss) { 2338 2359 sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+328
net/mac80211/tdls.c
··· 491 491 } 492 492 } 493 493 494 + static void 495 + ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_sub_if_data *sdata, 496 + struct sk_buff *skb, const u8 *peer, 497 + u16 status_code, bool initiator, 498 + const u8 *extra_ies, 499 + size_t extra_ies_len) 500 + { 501 + if (status_code == 0) 502 + ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); 503 + 504 + if (extra_ies_len) 505 + memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); 506 + } 507 + 494 508 static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata, 495 509 struct sk_buff *skb, const u8 *peer, 496 510 u8 action_code, u16 status_code, ··· 542 528 initiator, extra_ies, 543 529 extra_ies_len, 544 530 oper_class, chandef); 531 + break; 532 + case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE: 533 + ieee80211_tdls_add_chan_switch_resp_ies(sdata, skb, peer, 534 + status_code, 535 + initiator, extra_ies, 536 + extra_ies_len); 545 537 break; 546 538 } 547 539 ··· 620 600 tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST; 621 601 622 602 skb_put(skb, sizeof(tf->u.chan_switch_req)); 603 + break; 604 + case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE: 605 + tf->category = WLAN_CATEGORY_TDLS; 606 + tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE; 607 + 608 + skb_put(skb, sizeof(tf->u.chan_switch_resp)); 609 + tf->u.chan_switch_resp.status_code = cpu_to_le16(status_code); 623 610 break; 624 611 default: 625 612 return -EINVAL; ··· 708 681 case WLAN_TDLS_TEARDOWN: 709 682 case WLAN_TDLS_DISCOVERY_REQUEST: 710 683 case WLAN_TDLS_CHANNEL_SWITCH_REQUEST: 684 + case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE: 711 685 ret = ieee80211_prep_tdls_encap_data(local->hw.wiphy, 712 686 sdata->dev, peer, 713 687 action_code, dialog_token, ··· 783 755 break; 784 756 case WLAN_TDLS_TEARDOWN: 785 757 case WLAN_TDLS_CHANNEL_SWITCH_REQUEST: 758 + case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE: 786 759 /* any value is ok */ 787 760 break; 788 761 default: ··· 1308 1279 1309 1280 out: 1310 1281 mutex_unlock(&local->sta_mtx); 1282 + } 1283 + 1284 + static struct sk_buff * 1285 + ieee80211_tdls_ch_sw_resp_tmpl_get(struct sta_info *sta, 1286 + u32 *ch_sw_tm_ie_offset) 1287 + { 1288 + struct ieee80211_sub_if_data *sdata = sta->sdata; 1289 + struct sk_buff *skb; 1290 + u8 extra_ies[2 + sizeof(struct ieee80211_ch_switch_timing)]; 1291 + 1292 + /* initial timing are always zero in the template */ 1293 + iee80211_tdls_add_ch_switch_timing(extra_ies, 0, 0); 1294 + 1295 + skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr, 1296 + WLAN_TDLS_CHANNEL_SWITCH_RESPONSE, 1297 + 0, 0, !sta->sta.tdls_initiator, 1298 + extra_ies, sizeof(extra_ies), 0, NULL); 1299 + if (!skb) 1300 + return NULL; 1301 + 1302 + skb = ieee80211_build_data_template(sdata, skb, 0); 1303 + if (IS_ERR(skb)) { 1304 + tdls_dbg(sdata, 1305 + "Failed building TDLS channel switch resp frame\n"); 1306 + return NULL; 1307 + } 1308 + 1309 + if (ch_sw_tm_ie_offset) { 1310 + const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb); 1311 + 1312 + if (!tm_ie) { 1313 + tdls_dbg(sdata, 1314 + "No switch timing IE in TDLS switch resp\n"); 1315 + dev_kfree_skb_any(skb); 1316 + return NULL; 1317 + } 1318 + 1319 + *ch_sw_tm_ie_offset = tm_ie - skb->data; 1320 + } 1321 + 1322 + tdls_dbg(sdata, "TDLS get channel switch response template for %pM\n", 1323 + sta->sta.addr); 1324 + return skb; 1325 + } 1326 + 1327 + static int 1328 + ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata, 1329 + struct sk_buff *skb) 1330 + { 1331 + struct ieee80211_local *local = sdata->local; 1332 + struct ieee802_11_elems elems; 1333 + struct sta_info *sta; 1334 + struct ieee80211_tdls_data *tf = (void *)skb->data; 1335 + bool local_initiator; 1336 + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); 1337 + int baselen = offsetof(typeof(*tf), u.chan_switch_resp.variable); 1338 + struct ieee80211_tdls_ch_sw_params params = {}; 1339 + int ret; 1340 + 1341 + params.action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE; 1342 + params.timestamp = rx_status->device_timestamp; 1343 + 1344 + if (skb->len < baselen) { 1345 + tdls_dbg(sdata, "TDLS channel switch resp too short: %d\n", 1346 + skb->len); 1347 + return -EINVAL; 1348 + } 1349 + 1350 + mutex_lock(&local->sta_mtx); 1351 + sta = sta_info_get(sdata, tf->sa); 1352 + if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) { 1353 + tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n", 1354 + tf->sa); 1355 + ret = -EINVAL; 1356 + goto out; 1357 + } 1358 + 1359 + params.sta = &sta->sta; 1360 + params.status = le16_to_cpu(tf->u.chan_switch_resp.status_code); 1361 + if (params.status != 0) { 1362 + ret = 0; 1363 + goto call_drv; 1364 + } 1365 + 1366 + ieee802_11_parse_elems(tf->u.chan_switch_resp.variable, 1367 + skb->len - baselen, false, &elems); 1368 + if (elems.parse_error) { 1369 + tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n"); 1370 + ret = -EINVAL; 1371 + goto out; 1372 + } 1373 + 1374 + if (!elems.ch_sw_timing || !elems.lnk_id) { 1375 + tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n"); 1376 + ret = -EINVAL; 1377 + goto out; 1378 + } 1379 + 1380 + /* validate the initiator is set correctly */ 1381 + local_initiator = 1382 + !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); 1383 + if (local_initiator == sta->sta.tdls_initiator) { 1384 + tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n"); 1385 + ret = -EINVAL; 1386 + goto out; 1387 + } 1388 + 1389 + params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time); 1390 + params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout); 1391 + 1392 + params.tmpl_skb = 1393 + ieee80211_tdls_ch_sw_resp_tmpl_get(sta, &params.ch_sw_tm_ie); 1394 + if (!params.tmpl_skb) { 1395 + ret = -ENOENT; 1396 + goto out; 1397 + } 1398 + 1399 + call_drv: 1400 + drv_tdls_recv_channel_switch(sdata->local, sdata, &params); 1401 + 1402 + tdls_dbg(sdata, 1403 + "TDLS channel switch response received from %pM status %d\n", 1404 + tf->sa, params.status); 1405 + 1406 + out: 1407 + mutex_unlock(&local->sta_mtx); 1408 + dev_kfree_skb_any(params.tmpl_skb); 1409 + return ret; 1410 + } 1411 + 1412 + static int 1413 + ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, 1414 + struct sk_buff *skb) 1415 + { 1416 + struct ieee80211_local *local = sdata->local; 1417 + struct ieee802_11_elems elems; 1418 + struct cfg80211_chan_def chandef; 1419 + struct ieee80211_channel *chan; 1420 + enum nl80211_channel_type chan_type; 1421 + int freq; 1422 + u8 target_channel, oper_class; 1423 + bool local_initiator; 1424 + struct sta_info *sta; 1425 + enum ieee80211_band band; 1426 + struct ieee80211_tdls_data *tf = (void *)skb->data; 1427 + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); 1428 + int baselen = offsetof(typeof(*tf), u.chan_switch_req.variable); 1429 + struct ieee80211_tdls_ch_sw_params params = {}; 1430 + int ret = 0; 1431 + 1432 + params.action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST; 1433 + params.timestamp = rx_status->device_timestamp; 1434 + 1435 + if (skb->len < baselen) { 1436 + tdls_dbg(sdata, "TDLS channel switch req too short: %d\n", 1437 + skb->len); 1438 + return -EINVAL; 1439 + } 1440 + 1441 + target_channel = tf->u.chan_switch_req.target_channel; 1442 + oper_class = tf->u.chan_switch_req.oper_class; 1443 + 1444 + /* 1445 + * We can't easily infer the channel band. The operating class is 1446 + * ambiguous - there are multiple tables (US/Europe/JP/Global). The 1447 + * solution here is to treat channels with number >14 as 5GHz ones, 1448 + * and specifically check for the (oper_class, channel) combinations 1449 + * where this doesn't hold. These are thankfully unique according to 1450 + * IEEE802.11-2012. 1451 + * We consider only the 2GHz and 5GHz bands and 20MHz+ channels as 1452 + * valid here. 1453 + */ 1454 + if ((oper_class == 112 || oper_class == 2 || oper_class == 3 || 1455 + oper_class == 4 || oper_class == 5 || oper_class == 6) && 1456 + target_channel < 14) 1457 + band = IEEE80211_BAND_5GHZ; 1458 + else 1459 + band = target_channel < 14 ? IEEE80211_BAND_2GHZ : 1460 + IEEE80211_BAND_5GHZ; 1461 + 1462 + freq = ieee80211_channel_to_frequency(target_channel, band); 1463 + if (freq == 0) { 1464 + tdls_dbg(sdata, "Invalid channel in TDLS chan switch: %d\n", 1465 + target_channel); 1466 + return -EINVAL; 1467 + } 1468 + 1469 + chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq); 1470 + if (!chan) { 1471 + tdls_dbg(sdata, 1472 + "Unsupported channel for TDLS chan switch: %d\n", 1473 + target_channel); 1474 + return -EINVAL; 1475 + } 1476 + 1477 + ieee802_11_parse_elems(tf->u.chan_switch_req.variable, 1478 + skb->len - baselen, false, &elems); 1479 + if (elems.parse_error) { 1480 + tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n"); 1481 + return -EINVAL; 1482 + } 1483 + 1484 + if (!elems.ch_sw_timing || !elems.lnk_id) { 1485 + tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n"); 1486 + return -EINVAL; 1487 + } 1488 + 1489 + mutex_lock(&local->sta_mtx); 1490 + sta = sta_info_get(sdata, tf->sa); 1491 + if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) { 1492 + tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n", 1493 + tf->sa); 1494 + ret = -EINVAL; 1495 + goto out; 1496 + } 1497 + 1498 + params.sta = &sta->sta; 1499 + 1500 + /* validate the initiator is set correctly */ 1501 + local_initiator = 1502 + !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); 1503 + if (local_initiator == sta->sta.tdls_initiator) { 1504 + tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n"); 1505 + ret = -EINVAL; 1506 + goto out; 1507 + } 1508 + 1509 + if (!sta->sta.ht_cap.ht_supported) { 1510 + chan_type = NL80211_CHAN_NO_HT; 1511 + } else if (!elems.sec_chan_offs) { 1512 + chan_type = NL80211_CHAN_HT20; 1513 + } else { 1514 + switch (elems.sec_chan_offs->sec_chan_offs) { 1515 + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 1516 + chan_type = NL80211_CHAN_HT40PLUS; 1517 + break; 1518 + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 1519 + chan_type = NL80211_CHAN_HT40MINUS; 1520 + break; 1521 + default: 1522 + chan_type = NL80211_CHAN_HT20; 1523 + break; 1524 + } 1525 + } 1526 + 1527 + cfg80211_chandef_create(&chandef, chan, chan_type); 1528 + params.chandef = &chandef; 1529 + 1530 + params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time); 1531 + params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout); 1532 + 1533 + params.tmpl_skb = 1534 + ieee80211_tdls_ch_sw_resp_tmpl_get(sta, 1535 + &params.ch_sw_tm_ie); 1536 + if (!params.tmpl_skb) { 1537 + ret = -ENOENT; 1538 + goto out; 1539 + } 1540 + 1541 + drv_tdls_recv_channel_switch(sdata->local, sdata, &params); 1542 + 1543 + tdls_dbg(sdata, 1544 + "TDLS ch switch request received from %pM ch %d width %d\n", 1545 + tf->sa, params.chandef->chan->center_freq, 1546 + params.chandef->width); 1547 + out: 1548 + mutex_unlock(&local->sta_mtx); 1549 + dev_kfree_skb_any(params.tmpl_skb); 1550 + return ret; 1551 + } 1552 + 1553 + void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata, 1554 + struct sk_buff *skb) 1555 + { 1556 + struct ieee80211_tdls_data *tf = (void *)skb->data; 1557 + struct wiphy *wiphy = sdata->local->hw.wiphy; 1558 + 1559 + /* make sure the driver supports it */ 1560 + if (!(wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH)) 1561 + return; 1562 + 1563 + /* we want to access the entire packet */ 1564 + if (skb_linearize(skb)) 1565 + return; 1566 + /* 1567 + * The packet/size was already validated by mac80211 Rx path, only look 1568 + * at the action type. 1569 + */ 1570 + switch (tf->action_code) { 1571 + case WLAN_TDLS_CHANNEL_SWITCH_REQUEST: 1572 + ieee80211_process_tdls_channel_switch_req(sdata, skb); 1573 + break; 1574 + case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE: 1575 + ieee80211_process_tdls_channel_switch_resp(sdata, skb); 1576 + break; 1577 + default: 1578 + WARN_ON_ONCE(1); 1579 + return; 1580 + } 1311 1581 }
+45
net/mac80211/trace.h
··· 16 16 17 17 #define STA_ENTRY __array(char, sta_addr, ETH_ALEN) 18 18 #define STA_ASSIGN (sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN)) 19 + #define STA_NAMED_ASSIGN(s) memcpy(__entry->sta_addr, (s)->addr, ETH_ALEN) 19 20 #define STA_PR_FMT " sta:%pM" 20 21 #define STA_PR_ARG __entry->sta_addr 21 22 ··· 2252 2251 LOCAL_PR_FMT VIF_PR_FMT 2253 2252 " tdls cancel channel switch with " STA_PR_FMT, 2254 2253 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG 2254 + ) 2255 + ); 2256 + 2257 + TRACE_EVENT(drv_tdls_recv_channel_switch, 2258 + TP_PROTO(struct ieee80211_local *local, 2259 + struct ieee80211_sub_if_data *sdata, 2260 + struct ieee80211_tdls_ch_sw_params *params), 2261 + 2262 + TP_ARGS(local, sdata, params), 2263 + 2264 + TP_STRUCT__entry( 2265 + LOCAL_ENTRY 2266 + VIF_ENTRY 2267 + __field(u8, action_code) 2268 + STA_ENTRY 2269 + CHANDEF_ENTRY 2270 + __field(u32, status) 2271 + __field(bool, peer_initiator) 2272 + __field(u32, timestamp) 2273 + __field(u16, switch_time) 2274 + __field(u16, switch_timeout) 2275 + ), 2276 + 2277 + TP_fast_assign( 2278 + LOCAL_ASSIGN; 2279 + VIF_ASSIGN; 2280 + STA_NAMED_ASSIGN(params->sta); 2281 + CHANDEF_ASSIGN(params->chandef) 2282 + __entry->peer_initiator = params->sta->tdls_initiator; 2283 + __entry->action_code = params->action_code; 2284 + __entry->status = params->status; 2285 + __entry->timestamp = params->timestamp; 2286 + __entry->switch_time = params->switch_time; 2287 + __entry->switch_timeout = params->switch_timeout; 2288 + ), 2289 + 2290 + TP_printk( 2291 + LOCAL_PR_FMT VIF_PR_FMT " received tdls channel switch packet" 2292 + " action:%d status:%d time:%d switch time:%d switch" 2293 + " timeout:%d initiator: %d chan:" CHANDEF_PR_FMT STA_PR_FMT, 2294 + LOCAL_PR_ARG, VIF_PR_ARG, __entry->action_code, __entry->status, 2295 + __entry->timestamp, __entry->switch_time, 2296 + __entry->switch_timeout, __entry->peer_initiator, 2297 + CHANDEF_PR_ARG, STA_PR_ARG 2255 2298 ) 2256 2299 ); 2257 2300