mac80211: Fix regression in mesh forwarding path.

The removal of the master netdev broke the mesh forwarding path.  This patch
fixes it by using the new internal 'pending' queue.

As a result of this change, mesh forwarding no longer does the inefficient
802.11 -> 802.3 -> 802.11 conversion that was done before.

[Changes since v1]
Suggested by Johannes:
 - Select queue before adding to mpath queue
 - ieee80211_add_pending_skb -> ieee80211_add_pending_skbs
 - Remove unnecessary header wme.h

Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Javier Cardona 2009-07-07 10:55:03 -07:00 committed by John W. Linville
parent 3d34deb673
commit 249b405cf8
4 changed files with 20 additions and 11 deletions

View File

@ -784,7 +784,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
mesh_path_add(dst_addr, sdata); mesh_path_add(dst_addr, sdata);
mpath = mesh_path_lookup(dst_addr, sdata); mpath = mesh_path_lookup(dst_addr, sdata);
if (!mpath) { if (!mpath) {
dev_kfree_skb(skb);
sdata->u.mesh.mshstats.dropped_frames_no_route++; sdata->u.mesh.mshstats.dropped_frames_no_route++;
err = -ENOSPC; err = -ENOSPC;
goto endlookup; goto endlookup;
@ -804,6 +803,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
memcpy(hdr->addr1, mpath->next_hop->sta.addr, memcpy(hdr->addr1, mpath->next_hop->sta.addr,
ETH_ALEN); ETH_ALEN);
} else { } else {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (!(mpath->flags & MESH_PATH_RESOLVING)) { if (!(mpath->flags & MESH_PATH_RESOLVING)) {
/* Start discovery only if it is not running yet */ /* Start discovery only if it is not running yet */
mesh_queue_preq(mpath, PREQ_Q_F_START); mesh_queue_preq(mpath, PREQ_Q_F_START);
@ -815,6 +815,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
skb_unlink(skb_to_free, &mpath->frame_queue); skb_unlink(skb_to_free, &mpath->frame_queue);
} }
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
skb_queue_tail(&mpath->frame_queue, skb); skb_queue_tail(&mpath->frame_queue, skb);
if (skb_to_free) if (skb_to_free)
mesh_path_discard_frame(skb_to_free, sdata); mesh_path_discard_frame(skb_to_free, sdata);

View File

@ -499,11 +499,9 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
*/ */
void mesh_path_tx_pending(struct mesh_path *mpath) void mesh_path_tx_pending(struct mesh_path *mpath)
{ {
struct sk_buff *skb; if (mpath->flags & MESH_PATH_ACTIVE)
ieee80211_add_pending_skbs(mpath->sdata->local,
while ((skb = skb_dequeue(&mpath->frame_queue)) && &mpath->frame_queue);
(mpath->flags & MESH_PATH_ACTIVE))
dev_queue_xmit(skb);
} }
/** /**

View File

@ -1479,10 +1479,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
unsigned int hdrlen; unsigned int hdrlen;
struct sk_buff *skb = rx->skb, *fwd_skb; struct sk_buff *skb = rx->skb, *fwd_skb;
struct ieee80211_local *local = rx->local; struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata;
hdr = (struct ieee80211_hdr *) skb->data; hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
if (!ieee80211_is_data(hdr->frame_control)) if (!ieee80211_is_data(hdr->frame_control))
return RX_CONTINUE; return RX_CONTINUE;
@ -1492,10 +1494,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mppath; struct mesh_path *mppath;
sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
rcu_read_lock(); rcu_read_lock();
mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata);
if (!mppath) { if (!mppath) {
@ -1541,6 +1541,19 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
fwd_skb->iif = rx->dev->ifindex; fwd_skb->iif = rx->dev->ifindex;
ieee80211_select_queue(local, fwd_skb); ieee80211_select_queue(local, fwd_skb);
if (is_multicast_ether_addr(fwd_hdr->addr3))
memcpy(fwd_hdr->addr1, fwd_hdr->addr3,
ETH_ALEN);
else {
int err = mesh_nexthop_lookup(fwd_skb, sdata);
/* Failed to immediately resolve next hop:
* fwded frame was dropped or will be added
* later to the pending skb queue. */
if (err)
return RX_DROP_MONITOR;
}
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
fwded_frames);
ieee80211_add_pending_skb(local, fwd_skb); ieee80211_add_pending_skb(local, fwd_skb);
} }
} }

View File

@ -1419,9 +1419,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
dev_put(sdata->dev); dev_put(sdata->dev);
return; return;
} }
if (memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
fwded_frames);
} else if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { } else if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
int hdrlen; int hdrlen;
u16 len_rthdr; u16 len_rthdr;