diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-10-07 08:01:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-11 16:41:19 -0400 |
commit | 73b9f03a813d66484105c4ed648a1aa66fa267aa (patch) | |
tree | 37a60a9c61f4537c898a5d863e93f1b445864d7d | |
parent | a26eb27ab430147a82e4a9f2f1ebfadf03d99550 (diff) |
mac80211: parse radiotap header earlier
We can now move the radiotap header parsing into
ieee80211_monitor_start_xmit(). This moves it out of
the hotpath, and also helps the code since now the
radiotap header will no longer be present in
ieee80211_xmit() etc. which is easier to understand.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | include/net/mac80211.h | 4 | ||||
-rw-r--r-- | net/mac80211/tx.c | 201 |
2 files changed, 89 insertions, 116 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 05f102197cfe..021317367d55 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -349,8 +349,6 @@ struct ieee80211_bss_conf { | |||
349 | * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted | 349 | * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted |
350 | * after TX status because the destination was asleep, it must not | 350 | * after TX status because the destination was asleep, it must not |
351 | * be modified again (no seqno assignment, crypto, etc.) | 351 | * be modified again (no seqno assignment, crypto, etc.) |
352 | * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still | ||
353 | * has a radiotap header at skb->data. | ||
354 | * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 | 352 | * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 |
355 | * MLME command (internal to mac80211 to figure out whether to send TX | 353 | * MLME command (internal to mac80211 to figure out whether to send TX |
356 | * status to user space) | 354 | * status to user space) |
@@ -402,7 +400,7 @@ enum mac80211_tx_control_flags { | |||
402 | IEEE80211_TX_CTL_POLL_RESPONSE = BIT(17), | 400 | IEEE80211_TX_CTL_POLL_RESPONSE = BIT(17), |
403 | IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), | 401 | IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), |
404 | IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), | 402 | IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), |
405 | IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), | 403 | /* hole at 20, use later */ |
406 | IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), | 404 | IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), |
407 | IEEE80211_TX_CTL_LDPC = BIT(22), | 405 | IEEE80211_TX_CTL_LDPC = BIT(22), |
408 | IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), | 406 | IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7f7d45cf77d1..3d2b6b2749f6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1035,103 +1035,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | |||
1035 | 1035 | ||
1036 | /* actual transmit path */ | 1036 | /* actual transmit path */ |
1037 | 1037 | ||
1038 | /* | ||
1039 | * deal with packet injection down monitor interface | ||
1040 | * with Radiotap Header -- only called for monitor mode interface | ||
1041 | */ | ||
1042 | static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | ||
1043 | struct sk_buff *skb) | ||
1044 | { | ||
1045 | /* | ||
1046 | * this is the moment to interpret and discard the radiotap header that | ||
1047 | * must be at the start of the packet injected in Monitor mode | ||
1048 | * | ||
1049 | * Need to take some care with endian-ness since radiotap | ||
1050 | * args are little-endian | ||
1051 | */ | ||
1052 | |||
1053 | struct ieee80211_radiotap_iterator iterator; | ||
1054 | struct ieee80211_radiotap_header *rthdr = | ||
1055 | (struct ieee80211_radiotap_header *) skb->data; | ||
1056 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1057 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | ||
1058 | NULL); | ||
1059 | u16 txflags; | ||
1060 | |||
1061 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | | ||
1062 | IEEE80211_TX_CTL_DONTFRAG; | ||
1063 | |||
1064 | /* | ||
1065 | * for every radiotap entry that is present | ||
1066 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1067 | * entries present, or -EINVAL on error) | ||
1068 | */ | ||
1069 | |||
1070 | while (!ret) { | ||
1071 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1072 | |||
1073 | if (ret) | ||
1074 | continue; | ||
1075 | |||
1076 | /* see if this argument is something we can use */ | ||
1077 | switch (iterator.this_arg_index) { | ||
1078 | /* | ||
1079 | * You must take care when dereferencing iterator.this_arg | ||
1080 | * for multibyte types... the pointer is not aligned. Use | ||
1081 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1082 | * iterator.this_arg for type "type" safely on all arches. | ||
1083 | */ | ||
1084 | case IEEE80211_RADIOTAP_FLAGS: | ||
1085 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1086 | /* | ||
1087 | * this indicates that the skb we have been | ||
1088 | * handed has the 32-bit FCS CRC at the end... | ||
1089 | * we should react to that by snipping it off | ||
1090 | * because it will be recomputed and added | ||
1091 | * on transmission | ||
1092 | */ | ||
1093 | if (skb->len < (iterator._max_length + FCS_LEN)) | ||
1094 | return false; | ||
1095 | |||
1096 | skb_trim(skb, skb->len - FCS_LEN); | ||
1097 | } | ||
1098 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | ||
1099 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1100 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | ||
1101 | info->flags &= ~IEEE80211_TX_CTL_DONTFRAG; | ||
1102 | break; | ||
1103 | |||
1104 | case IEEE80211_RADIOTAP_TX_FLAGS: | ||
1105 | txflags = le16_to_cpu(get_unaligned((__le16*) | ||
1106 | iterator.this_arg)); | ||
1107 | if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) | ||
1108 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1109 | break; | ||
1110 | |||
1111 | /* | ||
1112 | * Please update the file | ||
1113 | * Documentation/networking/mac80211-injection.txt | ||
1114 | * when parsing new fields here. | ||
1115 | */ | ||
1116 | |||
1117 | default: | ||
1118 | break; | ||
1119 | } | ||
1120 | } | ||
1121 | |||
1122 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1123 | return false; | ||
1124 | |||
1125 | /* | ||
1126 | * remove the radiotap header | ||
1127 | * iterator->_max_length was sanity-checked against | ||
1128 | * skb->len by iterator init | ||
1129 | */ | ||
1130 | skb_pull(skb, iterator._max_length); | ||
1131 | |||
1132 | return true; | ||
1133 | } | ||
1134 | |||
1135 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | 1038 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, |
1136 | struct sk_buff *skb, | 1039 | struct sk_buff *skb, |
1137 | struct ieee80211_tx_info *info, | 1040 | struct ieee80211_tx_info *info, |
@@ -1205,19 +1108,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1205 | tx->sdata = sdata; | 1108 | tx->sdata = sdata; |
1206 | tx->channel = local->hw.conf.channel; | 1109 | tx->channel = local->hw.conf.channel; |
1207 | 1110 | ||
1208 | /* process and remove the injection radiotap header */ | ||
1209 | if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { | ||
1210 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) | ||
1211 | return TX_DROP; | ||
1212 | |||
1213 | /* | ||
1214 | * __ieee80211_parse_tx_radiotap has now removed | ||
1215 | * the radiotap header that was present and pre-filled | ||
1216 | * 'tx' with tx control information. | ||
1217 | */ | ||
1218 | info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1219 | } | ||
1220 | |||
1221 | /* | 1111 | /* |
1222 | * If this flag is set to true anywhere, and we get here, | 1112 | * If this flag is set to true anywhere, and we get here, |
1223 | * we are doing the needed processing, so remove the flag | 1113 | * we are doing the needed processing, so remove the flag |
@@ -1559,6 +1449,89 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1559 | rcu_read_unlock(); | 1449 | rcu_read_unlock(); |
1560 | } | 1450 | } |
1561 | 1451 | ||
1452 | static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) | ||
1453 | { | ||
1454 | struct ieee80211_radiotap_iterator iterator; | ||
1455 | struct ieee80211_radiotap_header *rthdr = | ||
1456 | (struct ieee80211_radiotap_header *) skb->data; | ||
1457 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1458 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | ||
1459 | NULL); | ||
1460 | u16 txflags; | ||
1461 | |||
1462 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | | ||
1463 | IEEE80211_TX_CTL_DONTFRAG; | ||
1464 | |||
1465 | /* | ||
1466 | * for every radiotap entry that is present | ||
1467 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1468 | * entries present, or -EINVAL on error) | ||
1469 | */ | ||
1470 | |||
1471 | while (!ret) { | ||
1472 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1473 | |||
1474 | if (ret) | ||
1475 | continue; | ||
1476 | |||
1477 | /* see if this argument is something we can use */ | ||
1478 | switch (iterator.this_arg_index) { | ||
1479 | /* | ||
1480 | * You must take care when dereferencing iterator.this_arg | ||
1481 | * for multibyte types... the pointer is not aligned. Use | ||
1482 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1483 | * iterator.this_arg for type "type" safely on all arches. | ||
1484 | */ | ||
1485 | case IEEE80211_RADIOTAP_FLAGS: | ||
1486 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1487 | /* | ||
1488 | * this indicates that the skb we have been | ||
1489 | * handed has the 32-bit FCS CRC at the end... | ||
1490 | * we should react to that by snipping it off | ||
1491 | * because it will be recomputed and added | ||
1492 | * on transmission | ||
1493 | */ | ||
1494 | if (skb->len < (iterator._max_length + FCS_LEN)) | ||
1495 | return false; | ||
1496 | |||
1497 | skb_trim(skb, skb->len - FCS_LEN); | ||
1498 | } | ||
1499 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | ||
1500 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1501 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | ||
1502 | info->flags &= ~IEEE80211_TX_CTL_DONTFRAG; | ||
1503 | break; | ||
1504 | |||
1505 | case IEEE80211_RADIOTAP_TX_FLAGS: | ||
1506 | txflags = get_unaligned_le16(iterator.this_arg); | ||
1507 | if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) | ||
1508 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1509 | break; | ||
1510 | |||
1511 | /* | ||
1512 | * Please update the file | ||
1513 | * Documentation/networking/mac80211-injection.txt | ||
1514 | * when parsing new fields here. | ||
1515 | */ | ||
1516 | |||
1517 | default: | ||
1518 | break; | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1522 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1523 | return false; | ||
1524 | |||
1525 | /* | ||
1526 | * remove the radiotap header | ||
1527 | * iterator->_max_length was sanity-checked against | ||
1528 | * skb->len by iterator init | ||
1529 | */ | ||
1530 | skb_pull(skb, iterator._max_length); | ||
1531 | |||
1532 | return true; | ||
1533 | } | ||
1534 | |||
1562 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1535 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, |
1563 | struct net_device *dev) | 1536 | struct net_device *dev) |
1564 | { | 1537 | { |
@@ -1646,8 +1619,11 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1646 | memset(info, 0, sizeof(*info)); | 1619 | memset(info, 0, sizeof(*info)); |
1647 | 1620 | ||
1648 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | 1621 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | |
1649 | IEEE80211_TX_CTL_INJECTED | | 1622 | IEEE80211_TX_CTL_INJECTED; |
1650 | IEEE80211_TX_INTFL_HAS_RADIOTAP; | 1623 | |
1624 | /* process and remove the injection radiotap header */ | ||
1625 | if (!ieee80211_parse_tx_radiotap(skb)) | ||
1626 | goto fail; | ||
1651 | 1627 | ||
1652 | rcu_read_lock(); | 1628 | rcu_read_lock(); |
1653 | 1629 | ||
@@ -1674,7 +1650,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1674 | } | 1650 | } |
1675 | } | 1651 | } |
1676 | 1652 | ||
1677 | /* pass the radiotap header up to xmit */ | ||
1678 | ieee80211_xmit(sdata, skb); | 1653 | ieee80211_xmit(sdata, skb); |
1679 | rcu_read_unlock(); | 1654 | rcu_read_unlock(); |
1680 | 1655 | ||