aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
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 /net/mac80211/rx.c
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>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c116
1 files changed, 67 insertions, 49 deletions
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)