diff options
author | Thomas Pedersen <thomas@cozybit.com> | 2011-11-24 20:15:25 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-28 14:44:07 -0500 |
commit | 0cfda8519c85eb279166fb55a8553ee66eac9b35 (patch) | |
tree | 55f917c9402c0164a76c80b4675ea173562a869f /net/mac80211/mesh_hwmp.c | |
parent | dca7e9430cb3e492437a5ce891b8b3e315c147ca (diff) |
mac80211: don't initiate path discovery when forwarding frame with unknown DA
We used to initiate a path discovery when receiving a frame for which
there is no forwarding information. To cut down on PREQ spam, just send
a (gated) PERR in response.
Also separate path discovery logic from nexthop querying. This patch
means we no longer queue frames when forwarding, so kill the PERR TX
stuff in discard_frame().
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 111 |
1 files changed, 68 insertions, 43 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index fe93386d6aa9..73abb7524b2c 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -982,72 +982,97 @@ enddiscovery: | |||
982 | kfree(preq_node); | 982 | kfree(preq_node); |
983 | } | 983 | } |
984 | 984 | ||
985 | /** | 985 | /* mesh_nexthop_resolve - lookup next hop for given skb and start path |
986 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame | 986 | * discovery if no forwarding information is found. |
987 | * | 987 | * |
988 | * @skb: 802.11 frame to be sent | 988 | * @skb: 802.11 frame to be sent |
989 | * @sdata: network subif the frame will be sent through | 989 | * @sdata: network subif the frame will be sent through |
990 | * | 990 | * |
991 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is | 991 | * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. |
992 | * found, the function will start a path discovery and queue the frame so it is | 992 | * skb is freeed here if no mpath could be allocated. |
993 | * sent when the path is resolved. This means the caller must not free the skb | ||
994 | * in this case. | ||
995 | */ | 993 | */ |
996 | int mesh_nexthop_lookup(struct sk_buff *skb, | 994 | int mesh_nexthop_resolve(struct sk_buff *skb, |
997 | struct ieee80211_sub_if_data *sdata) | 995 | struct ieee80211_sub_if_data *sdata) |
998 | { | 996 | { |
999 | struct sk_buff *skb_to_free = NULL; | ||
1000 | struct mesh_path *mpath; | ||
1001 | struct sta_info *next_hop; | ||
1002 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 997 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
998 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
999 | struct mesh_path *mpath; | ||
1000 | struct sk_buff *skb_to_free = NULL; | ||
1003 | u8 *target_addr = hdr->addr3; | 1001 | u8 *target_addr = hdr->addr3; |
1004 | int err = 0; | 1002 | int err = 0; |
1005 | 1003 | ||
1006 | rcu_read_lock(); | 1004 | rcu_read_lock(); |
1007 | mpath = mesh_path_lookup(target_addr, sdata); | 1005 | err = mesh_nexthop_lookup(skb, sdata); |
1006 | if (!err) | ||
1007 | goto endlookup; | ||
1008 | 1008 | ||
1009 | /* no nexthop found, start resolving */ | ||
1010 | mpath = mesh_path_lookup(target_addr, sdata); | ||
1009 | if (!mpath) { | 1011 | if (!mpath) { |
1010 | mesh_path_add(target_addr, sdata); | 1012 | mesh_path_add(target_addr, sdata); |
1011 | mpath = mesh_path_lookup(target_addr, sdata); | 1013 | mpath = mesh_path_lookup(target_addr, sdata); |
1012 | if (!mpath) { | 1014 | if (!mpath) { |
1013 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 1015 | mesh_path_discard_frame(skb, sdata); |
1014 | err = -ENOSPC; | 1016 | err = -ENOSPC; |
1015 | goto endlookup; | 1017 | goto endlookup; |
1016 | } | 1018 | } |
1017 | } | 1019 | } |
1018 | 1020 | ||
1019 | if (mpath->flags & MESH_PATH_ACTIVE) { | 1021 | if (!(mpath->flags & MESH_PATH_RESOLVING)) |
1020 | if (time_after(jiffies, | 1022 | mesh_queue_preq(mpath, PREQ_Q_F_START); |
1021 | mpath->exp_time - | 1023 | |
1022 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | 1024 | if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) |
1023 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && | 1025 | skb_to_free = skb_dequeue(&mpath->frame_queue); |
1024 | !(mpath->flags & MESH_PATH_RESOLVING) && | 1026 | |
1025 | !(mpath->flags & MESH_PATH_FIXED)) { | 1027 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1026 | mesh_queue_preq(mpath, | 1028 | ieee80211_set_qos_hdr(sdata, skb); |
1027 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 1029 | skb_queue_tail(&mpath->frame_queue, skb); |
1028 | } | 1030 | err = -ENOENT; |
1029 | next_hop = rcu_dereference(mpath->next_hop); | 1031 | if (skb_to_free) |
1030 | if (next_hop) { | 1032 | mesh_path_discard_frame(skb_to_free, sdata); |
1031 | memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); | 1033 | |
1032 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | 1034 | endlookup: |
1033 | } else | 1035 | rcu_read_unlock(); |
1034 | err = -ENOENT; | 1036 | return err; |
1035 | } else { | 1037 | } |
1036 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1038 | /** |
1037 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 1039 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling |
1038 | /* Start discovery only if it is not running yet */ | 1040 | * this function is considered "using" the associated mpath, so preempt a path |
1039 | mesh_queue_preq(mpath, PREQ_Q_F_START); | 1041 | * refresh if this mpath expires soon. |
1040 | } | 1042 | * |
1043 | * @skb: 802.11 frame to be sent | ||
1044 | * @sdata: network subif the frame will be sent through | ||
1045 | * | ||
1046 | * Returns: 0 if the next hop was found. Nonzero otherwise. | ||
1047 | */ | ||
1048 | int mesh_nexthop_lookup(struct sk_buff *skb, | ||
1049 | struct ieee80211_sub_if_data *sdata) | ||
1050 | { | ||
1051 | struct mesh_path *mpath; | ||
1052 | struct sta_info *next_hop; | ||
1053 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1054 | u8 *target_addr = hdr->addr3; | ||
1055 | int err = -ENOENT; | ||
1041 | 1056 | ||
1042 | if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) | 1057 | rcu_read_lock(); |
1043 | skb_to_free = skb_dequeue(&mpath->frame_queue); | 1058 | mpath = mesh_path_lookup(target_addr, sdata); |
1059 | |||
1060 | if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) | ||
1061 | goto endlookup; | ||
1062 | |||
1063 | if (time_after(jiffies, | ||
1064 | mpath->exp_time - | ||
1065 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | ||
1066 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && | ||
1067 | !(mpath->flags & MESH_PATH_RESOLVING) && | ||
1068 | !(mpath->flags & MESH_PATH_FIXED)) | ||
1069 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); | ||
1044 | 1070 | ||
1045 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1071 | next_hop = rcu_dereference(mpath->next_hop); |
1046 | ieee80211_set_qos_hdr(sdata, skb); | 1072 | if (next_hop) { |
1047 | skb_queue_tail(&mpath->frame_queue, skb); | 1073 | memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); |
1048 | if (skb_to_free) | 1074 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); |
1049 | mesh_path_discard_frame(skb_to_free, sdata); | 1075 | err = 0; |
1050 | err = -ENOENT; | ||
1051 | } | 1076 | } |
1052 | 1077 | ||
1053 | endlookup: | 1078 | endlookup: |