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 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); 215 216 /* Mesh paths */ 217 - int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, 218 - struct net_device *dev); 219 void mesh_path_start_discovery(struct net_device *dev); 220 struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); 221 struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); ··· 284 #else 285 #define mesh_allocated 0 286 #endif 287 - 288 - #define MESH_PREQ(skb) (skb->cb + 30) 289 290 #endif /* IEEE80211S_H */
··· 214 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); 215 216 /* Mesh paths */ 217 + int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); 218 void mesh_path_start_discovery(struct net_device *dev); 219 struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); 220 struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); ··· 285 #else 286 #define mesh_allocated 0 287 #endif 288 289 #endif /* IEEE80211S_H */
+10 -9
net/mac80211/mesh_hwmp.c
··· 758 /** 759 * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame 760 * 761 - * @next_hop: output argument for next hop address 762 - * @skb: frame to be sent 763 * @dev: network device the frame will be sent through 764 * 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 767 * sent when the path is resolved. This means the caller must not free the skb 768 * in this case. 769 */ 770 - int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, 771 - struct net_device *dev) 772 { 773 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 774 struct sk_buff *skb_to_free = NULL; 775 struct mesh_path *mpath; 776 int err = 0; 777 778 rcu_read_lock(); 779 - mpath = mesh_path_lookup(skb->data, dev); 780 781 if (!mpath) { 782 - mesh_path_add(skb->data, dev); 783 - mpath = mesh_path_lookup(skb->data, dev); 784 if (!mpath) { 785 dev_kfree_skb(skb); 786 sdata->u.sta.mshstats.dropped_frames_no_route++; ··· 793 if (mpath->flags & MESH_PATH_ACTIVE) { 794 if (time_after(jiffies, mpath->exp_time - 795 msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) 796 - && skb->pkt_type != PACKET_OTHERHOST 797 && !(mpath->flags & MESH_PATH_RESOLVING) 798 && !(mpath->flags & MESH_PATH_FIXED)) { 799 mesh_queue_preq(mpath, 800 PREQ_Q_F_START | PREQ_Q_F_REFRESH); 801 } 802 - memcpy(next_hop, mpath->next_hop->addr, 803 ETH_ALEN); 804 } else { 805 if (!(mpath->flags & MESH_PATH_RESOLVING)) {
··· 758 /** 759 * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame 760 * 761 + * @skb: 802.11 frame to be sent 762 * @dev: network device the frame will be sent through 763 + * @fwd_frame: true if this frame was originally from a different host 764 * 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 767 * sent when the path is resolved. This means the caller must not free the skb 768 * in this case. 769 */ 770 + int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) 771 { 772 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 773 struct sk_buff *skb_to_free = NULL; 774 struct mesh_path *mpath; 775 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 776 + u8 *dst_addr = hdr->addr3; 777 int err = 0; 778 779 rcu_read_lock(); 780 + mpath = mesh_path_lookup(dst_addr, dev); 781 782 if (!mpath) { 783 + mesh_path_add(dst_addr, dev); 784 + mpath = mesh_path_lookup(dst_addr, dev); 785 if (!mpath) { 786 dev_kfree_skb(skb); 787 sdata->u.sta.mshstats.dropped_frames_no_route++; ··· 792 if (mpath->flags & MESH_PATH_ACTIVE) { 793 if (time_after(jiffies, mpath->exp_time - 794 msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) 795 + && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) 796 && !(mpath->flags & MESH_PATH_RESOLVING) 797 && !(mpath->flags & MESH_PATH_FIXED)) { 798 mesh_queue_preq(mpath, 799 PREQ_Q_F_START | PREQ_Q_F_REFRESH); 800 } 801 + memcpy(hdr->addr1, mpath->next_hop->addr, 802 ETH_ALEN); 803 } else { 804 if (!(mpath->flags & MESH_PATH_RESOLVING)) {
+4 -7
net/mac80211/mesh_pathtbl.c
··· 388 void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) 389 { 390 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 391 struct mesh_path *mpath; 392 u32 dsn = 0; 393 394 - if (skb->pkt_type == PACKET_OTHERHOST) { 395 - struct ieee80211s_hdr *prev_meshhdr; 396 - int mshhdrlen; 397 u8 *ra, *da; 398 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); 403 mpath = mesh_path_lookup(da, dev); 404 if (mpath) 405 dsn = ++mpath->dsn;
··· 388 void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) 389 { 390 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 391 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 392 struct mesh_path *mpath; 393 u32 dsn = 0; 394 395 + if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { 396 u8 *ra, *da; 397 398 + da = hdr->addr3; 399 + ra = hdr->addr2; 400 mpath = mesh_path_lookup(da, dev); 401 if (mpath) 402 dsn = ++mpath->dsn;
+67 -49
net/mac80211/rx.c
··· 1109 1110 hdrlen = ieee80211_get_hdrlen(fc); 1111 1112 - if (ieee80211_vif_is_mesh(&sdata->vif)) { 1113 - int meshhdrlen = ieee80211_get_mesh_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 1127 /* convert IEEE 802.11 header + possible LLC headers into Ethernet 1128 * header ··· 1258 } 1259 } 1260 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 if (skb) { 1294 /* deliver to local stack */ 1295 skb->protocol = eth_type_trans(skb, dev); ··· 1386 1387 return RX_QUEUED; 1388 } 1389 1390 static ieee80211_rx_result debug_noinline 1391 ieee80211_rx_h_data(struct ieee80211_rx_data *rx) ··· 1677 rx->sdata = sdata; 1678 rx->dev = sdata->dev; 1679 1680 - #define CALL_RXH(rxh) \ 1681 - res = rxh(rx); \ 1682 - if (res != RX_CONTINUE) \ 1683 - goto rxh_done; 1684 1685 CALL_RXH(ieee80211_rx_h_passive_scan) 1686 CALL_RXH(ieee80211_rx_h_check) ··· 1694 /* must be after MMIC verify so header is counted in MPDU mic */ 1695 CALL_RXH(ieee80211_rx_h_remove_qos_control) 1696 CALL_RXH(ieee80211_rx_h_amsdu) 1697 CALL_RXH(ieee80211_rx_h_data) 1698 CALL_RXH(ieee80211_rx_h_ctrl) 1699 CALL_RXH(ieee80211_rx_h_mgmt)
··· 1109 1110 hdrlen = ieee80211_get_hdrlen(fc); 1111 1112 + if (ieee80211_vif_is_mesh(&sdata->vif)) 1113 + hdrlen += ieee80211_get_mesh_hdrlen( 1114 (struct ieee80211s_hdr *) (skb->data + hdrlen)); 1115 1116 /* convert IEEE 802.11 header + possible LLC headers into Ethernet 1117 * header ··· 1269 } 1270 } 1271 1272 if (skb) { 1273 /* deliver to local stack */ 1274 skb->protocol = eth_type_trans(skb, dev); ··· 1429 1430 return RX_QUEUED; 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 + 1489 1490 static ieee80211_rx_result debug_noinline 1491 ieee80211_rx_h_data(struct ieee80211_rx_data *rx) ··· 1663 rx->sdata = sdata; 1664 rx->dev = sdata->dev; 1665 1666 + #define CALL_RXH(rxh) \ 1667 + do { \ 1668 + res = rxh(rx); \ 1669 + if (res != RX_CONTINUE) \ 1670 + goto rxh_done; \ 1671 + } while (0); 1672 1673 CALL_RXH(ieee80211_rx_h_passive_scan) 1674 CALL_RXH(ieee80211_rx_h_check) ··· 1678 /* must be after MMIC verify so header is counted in MPDU mic */ 1679 CALL_RXH(ieee80211_rx_h_remove_qos_control) 1680 CALL_RXH(ieee80211_rx_h_amsdu) 1681 + if (ieee80211_vif_is_mesh(&sdata->vif)) 1682 + CALL_RXH(ieee80211_rx_h_mesh_fwding); 1683 CALL_RXH(ieee80211_rx_h_data) 1684 CALL_RXH(ieee80211_rx_h_ctrl) 1685 CALL_RXH(ieee80211_rx_h_mgmt)
+24 -21
net/mac80211/tx.c
··· 1301 struct net_device *dev) 1302 { 1303 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1304 struct net_device *odev = NULL; 1305 struct ieee80211_sub_if_data *osdata; 1306 int headroom; ··· 1328 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 1329 1330 osdata = IEEE80211_DEV_TO_SUB_IF(odev); 1331 1332 may_encrypt = !skb->do_not_encrypt; 1333 ··· 1487 case IEEE80211_IF_TYPE_MESH_POINT: 1488 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1489 /* 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; 1494 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1495 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1496 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); 1513 } 1514 hdrlen = 30; 1515 break; 1516 #endif ··· 1545 * Drop unicast frames to unauthorised stations unless they are 1546 * EAPOL frames from the local station. 1547 */ 1548 - if (unlikely(!is_multicast_ether_addr(hdr.addr1) && 1549 !(sta_flags & WLAN_STA_AUTHORIZED) && 1550 !(ethertype == ETH_P_PAE && 1551 compare_ether_addr(dev->dev_addr,
··· 1301 struct net_device *dev) 1302 { 1303 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1304 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1305 struct net_device *odev = NULL; 1306 struct ieee80211_sub_if_data *osdata; 1307 int headroom; ··· 1327 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 1328 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 + } 1344 1345 may_encrypt = !skb->do_not_encrypt; 1346 ··· 1472 case IEEE80211_IF_TYPE_MESH_POINT: 1473 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1474 /* RA TA DA SA */ 1475 + memset(hdr.addr1, 0, ETH_ALEN); 1476 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1477 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1478 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 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; 1484 } 1485 + meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); 1486 hdrlen = 30; 1487 break; 1488 #endif ··· 1543 * Drop unicast frames to unauthorised stations unless they are 1544 * EAPOL frames from the local station. 1545 */ 1546 + if (!ieee80211_vif_is_mesh(&sdata->vif) && 1547 + unlikely(!is_multicast_ether_addr(hdr.addr1) && 1548 !(sta_flags & WLAN_STA_AUTHORIZED) && 1549 !(ethertype == ETH_P_PAE && 1550 compare_ether_addr(dev->dev_addr,