diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7f33f775c5df..66c797cc85ce 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1479,10 +1479,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1479 | unsigned int hdrlen; | 1479 | unsigned int hdrlen; |
1480 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1480 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1481 | struct ieee80211_local *local = rx->local; | 1481 | struct ieee80211_local *local = rx->local; |
1482 | struct ieee80211_sub_if_data *sdata; | ||
1482 | 1483 | ||
1483 | hdr = (struct ieee80211_hdr *) skb->data; | 1484 | hdr = (struct ieee80211_hdr *) skb->data; |
1484 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1485 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1485 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1486 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1487 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1486 | 1488 | ||
1487 | if (!ieee80211_is_data(hdr->frame_control)) | 1489 | if (!ieee80211_is_data(hdr->frame_control)) |
1488 | return RX_CONTINUE; | 1490 | return RX_CONTINUE; |
@@ -1492,10 +1494,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1492 | return RX_DROP_MONITOR; | 1494 | return RX_DROP_MONITOR; |
1493 | 1495 | ||
1494 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | 1496 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ |
1495 | struct ieee80211_sub_if_data *sdata; | ||
1496 | struct mesh_path *mppath; | 1497 | struct mesh_path *mppath; |
1497 | 1498 | ||
1498 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1499 | rcu_read_lock(); | 1499 | rcu_read_lock(); |
1500 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | 1500 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); |
1501 | if (!mppath) { | 1501 | if (!mppath) { |
@@ -1541,6 +1541,19 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1541 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1541 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1542 | fwd_skb->iif = rx->dev->ifindex; | 1542 | fwd_skb->iif = rx->dev->ifindex; |
1543 | ieee80211_select_queue(local, fwd_skb); | 1543 | ieee80211_select_queue(local, fwd_skb); |
1544 | if (is_multicast_ether_addr(fwd_hdr->addr3)) | ||
1545 | memcpy(fwd_hdr->addr1, fwd_hdr->addr3, | ||
1546 | ETH_ALEN); | ||
1547 | else { | ||
1548 | int err = mesh_nexthop_lookup(fwd_skb, sdata); | ||
1549 | /* Failed to immediately resolve next hop: | ||
1550 | * fwded frame was dropped or will be added | ||
1551 | * later to the pending skb queue. */ | ||
1552 | if (err) | ||
1553 | return RX_DROP_MONITOR; | ||
1554 | } | ||
1555 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1556 | fwded_frames); | ||
1544 | ieee80211_add_pending_skb(local, fwd_skb); | 1557 | ieee80211_add_pending_skb(local, fwd_skb); |
1545 | } | 1558 | } |
1546 | } | 1559 | } |