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>

authored by Luis Carlos Cobo and committed by John W. Linville e32f85f7 eda0c003

+106 -90
+1 -4
net/mac80211/mesh.h
··· 214 214 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); 215 215 216 216 /* Mesh paths */ 217 - int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, 218 - struct net_device *dev); 217 + int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); 219 218 void mesh_path_start_discovery(struct net_device *dev); 220 219 struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); 221 220 struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); ··· 284 285 #else 285 286 #define mesh_allocated 0 286 287 #endif 287 - 288 - #define MESH_PREQ(skb) (skb->cb + 30) 289 288 290 289 #endif /* IEEE80211S_H */
+10 -9
net/mac80211/mesh_hwmp.c
··· 758 758 /** 759 759 * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame 760 760 * 761 - * @next_hop: output argument for next hop address 762 - * @skb: frame to be sent 761 + * @skb: 802.11 frame to be sent 763 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 765 * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is 766 766 * found, the function will start a path discovery and queue the frame so it is 767 767 * sent when the path is resolved. This means the caller must not free the skb 768 768 * in this case. 769 769 */ 770 - int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, 771 - struct net_device *dev) 770 + int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) 772 771 { 773 772 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 774 773 struct sk_buff *skb_to_free = NULL; 775 774 struct mesh_path *mpath; 775 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 776 + u8 *dst_addr = hdr->addr3; 776 777 int err = 0; 777 778 778 779 rcu_read_lock(); 779 - mpath = mesh_path_lookup(skb->data, dev); 780 + mpath = mesh_path_lookup(dst_addr, dev); 780 781 781 782 if (!mpath) { 782 - mesh_path_add(skb->data, dev); 783 - mpath = mesh_path_lookup(skb->data, dev); 783 + mesh_path_add(dst_addr, dev); 784 + mpath = mesh_path_lookup(dst_addr, dev); 784 785 if (!mpath) { 785 786 dev_kfree_skb(skb); 786 787 sdata->u.sta.mshstats.dropped_frames_no_route++; ··· 793 792 if (mpath->flags & MESH_PATH_ACTIVE) { 794 793 if (time_after(jiffies, mpath->exp_time - 795 794 msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) 796 - && skb->pkt_type != PACKET_OTHERHOST 795 + && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) 797 796 && !(mpath->flags & MESH_PATH_RESOLVING) 798 797 && !(mpath->flags & MESH_PATH_FIXED)) { 799 798 mesh_queue_preq(mpath, 800 799 PREQ_Q_F_START | PREQ_Q_F_REFRESH); 801 800 } 802 - memcpy(next_hop, mpath->next_hop->addr, 801 + memcpy(hdr->addr1, mpath->next_hop->addr, 803 802 ETH_ALEN); 804 803 } else { 805 804 if (!(mpath->flags & MESH_PATH_RESOLVING)) {
+4 -7
net/mac80211/mesh_pathtbl.c
··· 388 388 void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) 389 389 { 390 390 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 391 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 391 392 struct mesh_path *mpath; 392 393 u32 dsn = 0; 393 394 394 - if (skb->pkt_type == PACKET_OTHERHOST) { 395 - struct ieee80211s_hdr *prev_meshhdr; 396 - int mshhdrlen; 395 + if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { 397 396 u8 *ra, *da; 398 397 399 - prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); 400 - mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); 401 - da = skb->data; 402 - ra = MESH_PREQ(skb); 398 + da = hdr->addr3; 399 + ra = hdr->addr2; 403 400 mpath = mesh_path_lookup(da, dev); 404 401 if (mpath) 405 402 dsn = ++mpath->dsn;
+67 -49
net/mac80211/rx.c
··· 1109 1109 1110 1110 hdrlen = ieee80211_get_hdrlen(fc); 1111 1111 1112 - if (ieee80211_vif_is_mesh(&sdata->vif)) { 1113 - int meshhdrlen = ieee80211_get_mesh_hdrlen( 1112 + if (ieee80211_vif_is_mesh(&sdata->vif)) 1113 + hdrlen += ieee80211_get_mesh_hdrlen( 1114 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 1116 /* convert IEEE 802.11 header + possible LLC headers into Ethernet 1128 1117 * header ··· 1258 1269 } 1259 1270 } 1260 1271 1261 - /* Mesh forwarding */ 1262 - if (ieee80211_vif_is_mesh(&sdata->vif)) { 1263 - u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl; 1264 - (*mesh_ttl)--; 1265 - 1266 - if (is_multicast_ether_addr(skb->data)) { 1267 - if (*mesh_ttl > 0) { 1268 - xmit_skb = skb_copy(skb, GFP_ATOMIC); 1269 - if (xmit_skb) 1270 - xmit_skb->pkt_type = PACKET_OTHERHOST; 1271 - else if (net_ratelimit()) 1272 - printk(KERN_DEBUG "%s: failed to clone " 1273 - "multicast frame\n", dev->name); 1274 - } else 1275 - IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, 1276 - dropped_frames_ttl); 1277 - } else if (skb->pkt_type != PACKET_OTHERHOST && 1278 - compare_ether_addr(dev->dev_addr, skb->data) != 0) { 1279 - if (*mesh_ttl == 0) { 1280 - IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, 1281 - dropped_frames_ttl); 1282 - dev_kfree_skb(skb); 1283 - skb = NULL; 1284 - } else { 1285 - xmit_skb = skb; 1286 - xmit_skb->pkt_type = PACKET_OTHERHOST; 1287 - if (!(dev->flags & IFF_PROMISC)) 1288 - skb = NULL; 1289 - } 1290 - } 1291 - } 1292 - 1293 1272 if (skb) { 1294 1273 /* deliver to local stack */ 1295 1274 skb->protocol = eth_type_trans(skb, dev); ··· 1386 1429 1387 1430 return RX_QUEUED; 1388 1431 } 1432 + 1433 + static ieee80211_rx_result debug_noinline 1434 + ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) 1435 + { 1436 + struct ieee80211_hdr *hdr; 1437 + struct ieee80211s_hdr *mesh_hdr; 1438 + unsigned int hdrlen; 1439 + struct sk_buff *skb = rx->skb, *fwd_skb; 1440 + 1441 + hdr = (struct ieee80211_hdr *) skb->data; 1442 + hdrlen = ieee80211_hdrlen(hdr->frame_control); 1443 + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); 1444 + 1445 + if (!ieee80211_is_data(hdr->frame_control)) 1446 + return RX_CONTINUE; 1447 + 1448 + if (!mesh_hdr->ttl) 1449 + /* illegal frame */ 1450 + return RX_DROP_MONITOR; 1451 + 1452 + if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) 1453 + return RX_CONTINUE; 1454 + 1455 + mesh_hdr->ttl--; 1456 + 1457 + if (rx->flags & IEEE80211_RX_RA_MATCH) { 1458 + if (!mesh_hdr->ttl) 1459 + IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, 1460 + dropped_frames_ttl); 1461 + else { 1462 + struct ieee80211_hdr *fwd_hdr; 1463 + fwd_skb = skb_copy(skb, GFP_ATOMIC); 1464 + 1465 + if (!fwd_skb && net_ratelimit()) 1466 + printk(KERN_DEBUG "%s: failed to clone mesh frame\n", 1467 + rx->dev->name); 1468 + 1469 + fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; 1470 + /* 1471 + * Save TA to addr1 to send TA a path error if a 1472 + * suitable next hop is not found 1473 + */ 1474 + memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); 1475 + memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); 1476 + fwd_skb->dev = rx->local->mdev; 1477 + fwd_skb->iif = rx->dev->ifindex; 1478 + dev_queue_xmit(fwd_skb); 1479 + } 1480 + } 1481 + 1482 + if (is_multicast_ether_addr(hdr->addr3) || 1483 + rx->dev->flags & IFF_PROMISC) 1484 + return RX_CONTINUE; 1485 + else 1486 + return RX_DROP_MONITOR; 1487 + } 1488 + 1389 1489 1390 1490 static ieee80211_rx_result debug_noinline 1391 1491 ieee80211_rx_h_data(struct ieee80211_rx_data *rx) ··· 1677 1663 rx->sdata = sdata; 1678 1664 rx->dev = sdata->dev; 1679 1665 1680 - #define CALL_RXH(rxh) \ 1681 - res = rxh(rx); \ 1682 - if (res != RX_CONTINUE) \ 1683 - goto rxh_done; 1666 + #define CALL_RXH(rxh) \ 1667 + do { \ 1668 + res = rxh(rx); \ 1669 + if (res != RX_CONTINUE) \ 1670 + goto rxh_done; \ 1671 + } while (0); 1684 1672 1685 1673 CALL_RXH(ieee80211_rx_h_passive_scan) 1686 1674 CALL_RXH(ieee80211_rx_h_check) ··· 1694 1678 /* must be after MMIC verify so header is counted in MPDU mic */ 1695 1679 CALL_RXH(ieee80211_rx_h_remove_qos_control) 1696 1680 CALL_RXH(ieee80211_rx_h_amsdu) 1681 + if (ieee80211_vif_is_mesh(&sdata->vif)) 1682 + CALL_RXH(ieee80211_rx_h_mesh_fwding); 1697 1683 CALL_RXH(ieee80211_rx_h_data) 1698 1684 CALL_RXH(ieee80211_rx_h_ctrl) 1699 1685 CALL_RXH(ieee80211_rx_h_mgmt)
+24 -21
net/mac80211/tx.c
··· 1301 1301 struct net_device *dev) 1302 1302 { 1303 1303 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1304 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1304 1305 struct net_device *odev = NULL; 1305 1306 struct ieee80211_sub_if_data *osdata; 1306 1307 int headroom; ··· 1328 1327 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 1329 1328 1330 1329 osdata = IEEE80211_DEV_TO_SUB_IF(odev); 1330 + 1331 + if (ieee80211_vif_is_mesh(&osdata->vif) && 1332 + ieee80211_is_data(hdr->frame_control)) { 1333 + if (ieee80211_is_data(hdr->frame_control)) { 1334 + if (is_multicast_ether_addr(hdr->addr3)) 1335 + memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); 1336 + else 1337 + if (mesh_nexthop_lookup(skb, odev)) 1338 + return 0; 1339 + if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) 1340 + IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, 1341 + fwded_frames); 1342 + } 1343 + } 1331 1344 1332 1345 may_encrypt = !skb->do_not_encrypt; 1333 1346 ··· 1487 1472 case IEEE80211_IF_TYPE_MESH_POINT: 1488 1473 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1489 1474 /* RA TA DA SA */ 1490 - if (is_multicast_ether_addr(skb->data)) 1491 - memcpy(hdr.addr1, skb->data, ETH_ALEN); 1492 - else if (mesh_nexthop_lookup(hdr.addr1, skb, dev)) 1493 - return 0; 1475 + memset(hdr.addr1, 0, ETH_ALEN); 1494 1476 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1495 1477 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1496 1478 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 1497 - if (skb->pkt_type == PACKET_OTHERHOST) { 1498 - /* Forwarded frame, keep mesh ttl and seqnum */ 1499 - struct ieee80211s_hdr *prev_meshhdr; 1500 - prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); 1501 - meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); 1502 - memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen); 1503 - sdata->u.sta.mshstats.fwded_frames++; 1504 - } else { 1505 - if (!sdata->u.sta.mshcfg.dot11MeshTTL) { 1506 - /* Do not send frames with mesh_ttl == 0 */ 1507 - sdata->u.sta.mshstats.dropped_frames_ttl++; 1508 - ret = 0; 1509 - goto fail; 1510 - } 1511 - meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, 1512 - sdata); 1479 + if (!sdata->u.sta.mshcfg.dot11MeshTTL) { 1480 + /* Do not send frames with mesh_ttl == 0 */ 1481 + sdata->u.sta.mshstats.dropped_frames_ttl++; 1482 + ret = 0; 1483 + goto fail; 1513 1484 } 1485 + meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); 1514 1486 hdrlen = 30; 1515 1487 break; 1516 1488 #endif ··· 1545 1543 * Drop unicast frames to unauthorised stations unless they are 1546 1544 * EAPOL frames from the local station. 1547 1545 */ 1548 - if (unlikely(!is_multicast_ether_addr(hdr.addr1) && 1546 + if (!ieee80211_vif_is_mesh(&sdata->vif) && 1547 + unlikely(!is_multicast_ether_addr(hdr.addr1) && 1549 1548 !(sta_flags & WLAN_STA_AUTHORIZED) && 1550 1549 !(ethertype == ETH_P_PAE && 1551 1550 compare_ether_addr(dev->dev_addr,