aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis Carlos Cobo <luisca@cozybit.com>2008-08-05 13:34:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-07 09:49:04 -0400
commite32f85f7b917456265d4c30d15f734c4912cfa6a (patch)
tree14d48a5e3d4b279966f2c15b0a3e5f909bc71d58
parenteda0c003d1ff14c99d8476b482377ccfaf967b6c (diff)
mac80211: fix use of skb->cb for mesh forwarding
Now we deal with mesh forwarding before the 802.11->802.3 conversion, thus eliminating a few unnecessary steps. The next hop lookup is called from ieee80211_master_start_xmit() instead of subif_start_xmit(). Until the next hop is found, RA in the frame will be all zeroes for frames originating from the device. For forwarded frames, RA will contain the TA of the received frame, which will be necessary to send a path error if a next hop is not found. Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/mesh.h5
-rw-r--r--net/mac80211/mesh_hwmp.c19
-rw-r--r--net/mac80211/mesh_pathtbl.c11
-rw-r--r--net/mac80211/rx.c116
-rw-r--r--net/mac80211/tx.c45
5 files changed, 106 insertions, 90 deletions
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 669eafafe497..7495fbb0d211 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -214,8 +214,7 @@ void ieee80211s_stop(void);
214void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); 214void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
215 215
216/* Mesh paths */ 216/* Mesh paths */
217int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, 217int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev);
218 struct net_device *dev);
219void mesh_path_start_discovery(struct net_device *dev); 218void mesh_path_start_discovery(struct net_device *dev);
220struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); 219struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev);
221struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); 220struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev);
@@ -286,6 +285,4 @@ static inline void mesh_path_activate(struct mesh_path *mpath)
286#define mesh_allocated 0 285#define mesh_allocated 0
287#endif 286#endif
288 287
289#define MESH_PREQ(skb) (skb->cb + 30)
290
291#endif /* IEEE80211S_H */ 288#endif /* IEEE80211S_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 7fa149e230e6..08aca446ca01 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -758,29 +758,30 @@ enddiscovery:
758/** 758/**
759 * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame 759 * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame
760 * 760 *
761 * @next_hop: output argument for next hop address 761 * @skb: 802.11 frame to be sent
762 * @skb: frame to be sent
763 * @dev: network device the frame will be sent through 762 * @dev: network device the frame will be sent through
763 * @fwd_frame: true if this frame was originally from a different host
764 * 764 *
765 * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is 765 * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is
766 * found, the function will start a path discovery and queue the frame so it is 766 * found, the function will start a path discovery and queue the frame so it is
767 * sent when the path is resolved. This means the caller must not free the skb 767 * sent when the path is resolved. This means the caller must not free the skb
768 * in this case. 768 * in this case.
769 */ 769 */
770int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, 770int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev)
771 struct net_device *dev)
772{ 771{
773 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 772 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
774 struct sk_buff *skb_to_free = NULL; 773 struct sk_buff *skb_to_free = NULL;
775 struct mesh_path *mpath; 774 struct mesh_path *mpath;
775 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
776 u8 *dst_addr = hdr->addr3;
776 int err = 0; 777 int err = 0;
777 778
778 rcu_read_lock(); 779 rcu_read_lock();
779 mpath = mesh_path_lookup(skb->data, dev); 780 mpath = mesh_path_lookup(dst_addr, dev);
780 781
781 if (!mpath) { 782 if (!mpath) {
782 mesh_path_add(skb->data, dev); 783 mesh_path_add(dst_addr, dev);
783 mpath = mesh_path_lookup(skb->data, dev); 784 mpath = mesh_path_lookup(dst_addr, dev);
784 if (!mpath) { 785 if (!mpath) {
785 dev_kfree_skb(skb); 786 dev_kfree_skb(skb);
786 sdata->u.sta.mshstats.dropped_frames_no_route++; 787 sdata->u.sta.mshstats.dropped_frames_no_route++;
@@ -792,13 +793,13 @@ int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
792 if (mpath->flags & MESH_PATH_ACTIVE) { 793 if (mpath->flags & MESH_PATH_ACTIVE) {
793 if (time_after(jiffies, mpath->exp_time - 794 if (time_after(jiffies, mpath->exp_time -
794 msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) 795 msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time))
795 && skb->pkt_type != PACKET_OTHERHOST 796 && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN)
796 && !(mpath->flags & MESH_PATH_RESOLVING) 797 && !(mpath->flags & MESH_PATH_RESOLVING)
797 && !(mpath->flags & MESH_PATH_FIXED)) { 798 && !(mpath->flags & MESH_PATH_FIXED)) {
798 mesh_queue_preq(mpath, 799 mesh_queue_preq(mpath,
799 PREQ_Q_F_START | PREQ_Q_F_REFRESH); 800 PREQ_Q_F_START | PREQ_Q_F_REFRESH);
800 } 801 }
801 memcpy(next_hop, mpath->next_hop->addr, 802 memcpy(hdr->addr1, mpath->next_hop->addr,
802 ETH_ALEN); 803 ETH_ALEN);
803 } else { 804 } else {
804 if (!(mpath->flags & MESH_PATH_RESOLVING)) { 805 if (!(mpath->flags & MESH_PATH_RESOLVING)) {
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 5f88a2e6ee50..838ee60492ad 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -388,18 +388,15 @@ void mesh_path_tx_pending(struct mesh_path *mpath)
388void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) 388void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev)
389{ 389{
390 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 390 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
391 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
391 struct mesh_path *mpath; 392 struct mesh_path *mpath;
392 u32 dsn = 0; 393 u32 dsn = 0;
393 394
394 if (skb->pkt_type == PACKET_OTHERHOST) { 395 if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) {
395 struct ieee80211s_hdr *prev_meshhdr;
396 int mshhdrlen;
397 u8 *ra, *da; 396 u8 *ra, *da;
398 397
399 prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); 398 da = hdr->addr3;
400 mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); 399 ra = hdr->addr2;
401 da = skb->data;
402 ra = MESH_PREQ(skb);
403 mpath = mesh_path_lookup(da, dev); 400 mpath = mesh_path_lookup(da, dev);
404 if (mpath) 401 if (mpath)
405 dsn = ++mpath->dsn; 402 dsn = ++mpath->dsn;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6d9ae67c27ca..6db854505193 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1109,20 +1109,9 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1109 1109
1110 hdrlen = ieee80211_get_hdrlen(fc); 1110 hdrlen = ieee80211_get_hdrlen(fc);
1111 1111
1112 if (ieee80211_vif_is_mesh(&sdata->vif)) { 1112 if (ieee80211_vif_is_mesh(&sdata->vif))
1113 int meshhdrlen = ieee80211_get_mesh_hdrlen( 1113 hdrlen += ieee80211_get_mesh_hdrlen(
1114 (struct ieee80211s_hdr *) (skb->data + hdrlen)); 1114 (struct ieee80211s_hdr *) (skb->data + hdrlen));
1115 /* Copy on cb:
1116 * - mesh header: to be used for mesh forwarding
1117 * decision. It will also be used as mesh header template at
1118 * tx.c:ieee80211_subif_start_xmit() if interface
1119 * type is mesh and skb->pkt_type == PACKET_OTHERHOST
1120 * - ta: to be used if a RERR needs to be sent.
1121 */
1122 memcpy(skb->cb, skb->data + hdrlen, meshhdrlen);
1123 memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN);
1124 hdrlen += meshhdrlen;
1125 }
1126 1115
1127 /* convert IEEE 802.11 header + possible LLC headers into Ethernet 1116 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
1128 * header 1117 * header
@@ -1269,38 +1258,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1269 } 1258 }
1270 } 1259 }
1271 1260
1272 /* Mesh forwarding */
1273 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1274 u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl;
1275 (*mesh_ttl)--;
1276
1277 if (is_multicast_ether_addr(skb->data)) {
1278 if (*mesh_ttl > 0) {
1279 xmit_skb = skb_copy(skb, GFP_ATOMIC);
1280 if (xmit_skb)
1281 xmit_skb->pkt_type = PACKET_OTHERHOST;
1282 else if (net_ratelimit())
1283 printk(KERN_DEBUG "%s: failed to clone "
1284 "multicast frame\n", dev->name);
1285 } else
1286 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
1287 dropped_frames_ttl);
1288 } else if (skb->pkt_type != PACKET_OTHERHOST &&
1289 compare_ether_addr(dev->dev_addr, skb->data) != 0) {
1290 if (*mesh_ttl == 0) {
1291 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
1292 dropped_frames_ttl);
1293 dev_kfree_skb(skb);
1294 skb = NULL;
1295 } else {
1296 xmit_skb = skb;
1297 xmit_skb->pkt_type = PACKET_OTHERHOST;
1298 if (!(dev->flags & IFF_PROMISC))
1299 skb = NULL;
1300 }
1301 }
1302 }
1303
1304 if (skb) { 1261 if (skb) {
1305 /* deliver to local stack */ 1262 /* deliver to local stack */
1306 skb->protocol = eth_type_trans(skb, dev); 1263 skb->protocol = eth_type_trans(skb, dev);
@@ -1431,6 +1388,63 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
1431} 1388}
1432 1389
1433static ieee80211_rx_result debug_noinline 1390static ieee80211_rx_result debug_noinline
1391ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1392{
1393 struct ieee80211_hdr *hdr;
1394 struct ieee80211s_hdr *mesh_hdr;
1395 unsigned int hdrlen;
1396 struct sk_buff *skb = rx->skb, *fwd_skb;
1397
1398 hdr = (struct ieee80211_hdr *) skb->data;
1399 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1400 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1401
1402 if (!ieee80211_is_data(hdr->frame_control))
1403 return RX_CONTINUE;
1404
1405 if (!mesh_hdr->ttl)
1406 /* illegal frame */
1407 return RX_DROP_MONITOR;
1408
1409 if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
1410 return RX_CONTINUE;
1411
1412 mesh_hdr->ttl--;
1413
1414 if (rx->flags & IEEE80211_RX_RA_MATCH) {
1415 if (!mesh_hdr->ttl)
1416 IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta,
1417 dropped_frames_ttl);
1418 else {
1419 struct ieee80211_hdr *fwd_hdr;
1420 fwd_skb = skb_copy(skb, GFP_ATOMIC);
1421
1422 if (!fwd_skb && net_ratelimit())
1423 printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
1424 rx->dev->name);
1425
1426 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
1427 /*
1428 * Save TA to addr1 to send TA a path error if a
1429 * suitable next hop is not found
1430 */
1431 memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
1432 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
1433 fwd_skb->dev = rx->local->mdev;
1434 fwd_skb->iif = rx->dev->ifindex;
1435 dev_queue_xmit(fwd_skb);
1436 }
1437 }
1438
1439 if (is_multicast_ether_addr(hdr->addr3) ||
1440 rx->dev->flags & IFF_PROMISC)
1441 return RX_CONTINUE;
1442 else
1443 return RX_DROP_MONITOR;
1444}
1445
1446
1447static ieee80211_rx_result debug_noinline
1434ieee80211_rx_h_data(struct ieee80211_rx_data *rx) 1448ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1435{ 1449{
1436 struct net_device *dev = rx->dev; 1450 struct net_device *dev = rx->dev;
@@ -1663,10 +1677,12 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
1663 rx->sdata = sdata; 1677 rx->sdata = sdata;
1664 rx->dev = sdata->dev; 1678 rx->dev = sdata->dev;
1665 1679
1666#define CALL_RXH(rxh) \ 1680#define CALL_RXH(rxh) \
1667 res = rxh(rx); \ 1681 do { \
1668 if (res != RX_CONTINUE) \ 1682 res = rxh(rx); \
1669 goto rxh_done; 1683 if (res != RX_CONTINUE) \
1684 goto rxh_done; \
1685 } while (0);
1670 1686
1671 CALL_RXH(ieee80211_rx_h_passive_scan) 1687 CALL_RXH(ieee80211_rx_h_passive_scan)
1672 CALL_RXH(ieee80211_rx_h_check) 1688 CALL_RXH(ieee80211_rx_h_check)
@@ -1678,6 +1694,8 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
1678 /* must be after MMIC verify so header is counted in MPDU mic */ 1694 /* must be after MMIC verify so header is counted in MPDU mic */
1679 CALL_RXH(ieee80211_rx_h_remove_qos_control) 1695 CALL_RXH(ieee80211_rx_h_remove_qos_control)
1680 CALL_RXH(ieee80211_rx_h_amsdu) 1696 CALL_RXH(ieee80211_rx_h_amsdu)
1697 if (ieee80211_vif_is_mesh(&sdata->vif))
1698 CALL_RXH(ieee80211_rx_h_mesh_fwding);
1681 CALL_RXH(ieee80211_rx_h_data) 1699 CALL_RXH(ieee80211_rx_h_data)
1682 CALL_RXH(ieee80211_rx_h_ctrl) 1700 CALL_RXH(ieee80211_rx_h_ctrl)
1683 CALL_RXH(ieee80211_rx_h_mgmt) 1701 CALL_RXH(ieee80211_rx_h_mgmt)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 771ec68b848d..4788f7b91f49 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1301,6 +1301,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1301 struct net_device *dev) 1301 struct net_device *dev)
1302{ 1302{
1303 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1303 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1304 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1304 struct net_device *odev = NULL; 1305 struct net_device *odev = NULL;
1305 struct ieee80211_sub_if_data *osdata; 1306 struct ieee80211_sub_if_data *osdata;
1306 int headroom; 1307 int headroom;
@@ -1328,6 +1329,20 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1328 1329
1329 osdata = IEEE80211_DEV_TO_SUB_IF(odev); 1330 osdata = IEEE80211_DEV_TO_SUB_IF(odev);
1330 1331
1332 if (ieee80211_vif_is_mesh(&osdata->vif) &&
1333 ieee80211_is_data(hdr->frame_control)) {
1334 if (ieee80211_is_data(hdr->frame_control)) {
1335 if (is_multicast_ether_addr(hdr->addr3))
1336 memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
1337 else
1338 if (mesh_nexthop_lookup(skb, odev))
1339 return 0;
1340 if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
1341 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta,
1342 fwded_frames);
1343 }
1344 }
1345
1331 may_encrypt = !skb->do_not_encrypt; 1346 may_encrypt = !skb->do_not_encrypt;
1332 1347
1333 headroom = osdata->local->tx_headroom; 1348 headroom = osdata->local->tx_headroom;
@@ -1472,30 +1487,17 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
1472 case IEEE80211_IF_TYPE_MESH_POINT: 1487 case IEEE80211_IF_TYPE_MESH_POINT:
1473 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1488 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1474 /* RA TA DA SA */ 1489 /* RA TA DA SA */
1475 if (is_multicast_ether_addr(skb->data)) 1490 memset(hdr.addr1, 0, ETH_ALEN);
1476 memcpy(hdr.addr1, skb->data, ETH_ALEN);
1477 else if (mesh_nexthop_lookup(hdr.addr1, skb, dev))
1478 return 0;
1479 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1491 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1480 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1492 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1481 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 1493 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1482 if (skb->pkt_type == PACKET_OTHERHOST) { 1494 if (!sdata->u.sta.mshcfg.dot11MeshTTL) {
1483 /* Forwarded frame, keep mesh ttl and seqnum */ 1495 /* Do not send frames with mesh_ttl == 0 */
1484 struct ieee80211s_hdr *prev_meshhdr; 1496 sdata->u.sta.mshstats.dropped_frames_ttl++;
1485 prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); 1497 ret = 0;
1486 meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); 1498 goto fail;
1487 memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen);
1488 sdata->u.sta.mshstats.fwded_frames++;
1489 } else {
1490 if (!sdata->u.sta.mshcfg.dot11MeshTTL) {
1491 /* Do not send frames with mesh_ttl == 0 */
1492 sdata->u.sta.mshstats.dropped_frames_ttl++;
1493 ret = 0;
1494 goto fail;
1495 }
1496 meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
1497 sdata);
1498 } 1499 }
1500 meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
1499 hdrlen = 30; 1501 hdrlen = 30;
1500 break; 1502 break;
1501#endif 1503#endif
@@ -1543,7 +1545,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
1543 * Drop unicast frames to unauthorised stations unless they are 1545 * Drop unicast frames to unauthorised stations unless they are
1544 * EAPOL frames from the local station. 1546 * EAPOL frames from the local station.
1545 */ 1547 */
1546 if (unlikely(!is_multicast_ether_addr(hdr.addr1) && 1548 if (!ieee80211_vif_is_mesh(&sdata->vif) &&
1549 unlikely(!is_multicast_ether_addr(hdr.addr1) &&
1547 !(sta_flags & WLAN_STA_AUTHORIZED) && 1550 !(sta_flags & WLAN_STA_AUTHORIZED) &&
1548 !(ethertype == ETH_P_PAE && 1551 !(ethertype == ETH_P_PAE &&
1549 compare_ether_addr(dev->dev_addr, 1552 compare_ether_addr(dev->dev_addr,