Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thomas Pedersen and committed by
John W. Linville
0cfda851 dca7e943

+79 -77
+2
net/mac80211/mesh.h
··· 233 233 /* Mesh paths */ 234 234 int mesh_nexthop_lookup(struct sk_buff *skb, 235 235 struct ieee80211_sub_if_data *sdata); 236 + int mesh_nexthop_resolve(struct sk_buff *skb, 237 + struct ieee80211_sub_if_data *sdata); 236 238 void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); 237 239 struct mesh_path *mesh_path_lookup(u8 *dst, 238 240 struct ieee80211_sub_if_data *sdata);
+68 -43
net/mac80211/mesh_hwmp.c
··· 982 982 kfree(preq_node); 983 983 } 984 984 985 - /** 986 - * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame 985 + /* mesh_nexthop_resolve - lookup next hop for given skb and start path 986 + * discovery if no forwarding information is found. 987 987 * 988 988 * @skb: 802.11 frame to be sent 989 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 992 - * found, the function will start a path discovery and queue the frame so it is 993 - * sent when the path is resolved. This means the caller must not free the skb 994 - * in this case. 991 + * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. 992 + * skb is freeed here if no mpath could be allocated. 995 993 */ 996 - int mesh_nexthop_lookup(struct sk_buff *skb, 997 - struct ieee80211_sub_if_data *sdata) 994 + int mesh_nexthop_resolve(struct sk_buff *skb, 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 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 1001 u8 *target_addr = hdr->addr3; 1004 1002 int err = 0; 1005 1003 1006 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 1011 if (!mpath) { 1010 1012 mesh_path_add(target_addr, sdata); 1011 1013 mpath = mesh_path_lookup(target_addr, sdata); 1012 1014 if (!mpath) { 1013 - sdata->u.mesh.mshstats.dropped_frames_no_route++; 1015 + mesh_path_discard_frame(skb, sdata); 1014 1016 err = -ENOSPC; 1015 1017 goto endlookup; 1016 1018 } 1017 1019 } 1018 1020 1019 - if (mpath->flags & MESH_PATH_ACTIVE) { 1020 - if (time_after(jiffies, 1021 - mpath->exp_time - 1022 - msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && 1023 - !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && 1024 - !(mpath->flags & MESH_PATH_RESOLVING) && 1025 - !(mpath->flags & MESH_PATH_FIXED)) { 1026 - mesh_queue_preq(mpath, 1027 - PREQ_Q_F_START | PREQ_Q_F_REFRESH); 1028 - } 1029 - next_hop = rcu_dereference(mpath->next_hop); 1030 - if (next_hop) { 1031 - memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); 1032 - memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 1033 - } else 1034 - err = -ENOENT; 1035 - } else { 1036 - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1037 - if (!(mpath->flags & MESH_PATH_RESOLVING)) { 1038 - /* Start discovery only if it is not running yet */ 1039 - mesh_queue_preq(mpath, PREQ_Q_F_START); 1040 - } 1021 + if (!(mpath->flags & MESH_PATH_RESOLVING)) 1022 + mesh_queue_preq(mpath, PREQ_Q_F_START); 1041 1023 1042 - if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) 1043 - skb_to_free = skb_dequeue(&mpath->frame_queue); 1024 + if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) 1025 + skb_to_free = skb_dequeue(&mpath->frame_queue); 1044 1026 1045 - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 1046 - ieee80211_set_qos_hdr(sdata, skb); 1047 - skb_queue_tail(&mpath->frame_queue, skb); 1048 - if (skb_to_free) 1049 - mesh_path_discard_frame(skb_to_free, sdata); 1050 - err = -ENOENT; 1027 + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 1028 + ieee80211_set_qos_hdr(sdata, skb); 1029 + skb_queue_tail(&mpath->frame_queue, skb); 1030 + err = -ENOENT; 1031 + if (skb_to_free) 1032 + mesh_path_discard_frame(skb_to_free, sdata); 1033 + 1034 + endlookup: 1035 + rcu_read_unlock(); 1036 + return err; 1037 + } 1038 + /** 1039 + * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling 1040 + * this function is considered "using" the associated mpath, so preempt a path 1041 + * refresh if this mpath expires soon. 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; 1056 + 1057 + rcu_read_lock(); 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); 1070 + 1071 + next_hop = rcu_dereference(mpath->next_hop); 1072 + if (next_hop) { 1073 + memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); 1074 + memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 1075 + err = 0; 1051 1076 } 1052 1077 1053 1078 endlookup:
-27
net/mac80211/mesh_pathtbl.c
··· 973 973 * @skb: frame to discard 974 974 * @sdata: network subif the frame was to be sent through 975 975 * 976 - * If the frame was being forwarded from another MP, a PERR frame will be sent 977 - * to the precursor. The precursor's address (i.e. the previous hop) was saved 978 - * in addr1 of the frame-to-be-forwarded, and would only be overwritten once 979 - * the destination is successfully resolved. 980 - * 981 976 * Locking: the function must me called within a rcu_read_lock region 982 977 */ 983 978 void mesh_path_discard_frame(struct sk_buff *skb, 984 979 struct ieee80211_sub_if_data *sdata) 985 980 { 986 - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 987 - struct mesh_path *mpath; 988 - u32 sn = 0; 989 - __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); 990 - 991 - if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { 992 - u8 *ra, *da; 993 - 994 - da = hdr->addr3; 995 - ra = hdr->addr2; 996 - rcu_read_lock(); 997 - mpath = mesh_path_lookup(da, sdata); 998 - if (mpath) { 999 - spin_lock_bh(&mpath->state_lock); 1000 - sn = ++mpath->sn; 1001 - spin_unlock_bh(&mpath->state_lock); 1002 - } 1003 - rcu_read_unlock(); 1004 - mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, da, 1005 - cpu_to_le32(sn), reason, ra, sdata); 1006 - } 1007 - 1008 981 kfree_skb(skb); 1009 982 sdata->u.mesh.mshstats.dropped_frames_no_route++; 1010 983 }
+8 -6
net/mac80211/rx.c
··· 1899 1899 struct ieee80211_local *local = rx->local; 1900 1900 struct ieee80211_sub_if_data *sdata = rx->sdata; 1901 1901 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 1902 + __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); 1902 1903 u16 q; 1903 1904 1904 1905 hdr = (struct ieee80211_hdr *) skb->data; ··· 1986 1985 fwded_mcast); 1987 1986 memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); 1988 1987 } else { 1989 - int err; 1990 - err = mesh_nexthop_lookup(fwd_skb, sdata); 1991 - /* Failed to immediately resolve next hop: 1992 - * fwded frame was dropped or will be added 1993 - * later to the pending skb queue. */ 1994 - if (err) 1988 + if (mesh_nexthop_lookup(fwd_skb, sdata)) { 1989 + /* can't resolve next hop, send a PERR */ 1990 + mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, 1991 + fwd_hdr->addr3, 0, reason, 1992 + fwd_hdr->addr2, sdata); 1993 + sdata->u.mesh.mshstats.dropped_frames_no_route++; 1995 1994 return RX_DROP_MONITOR; 1995 + } 1996 1996 1997 1997 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, 1998 1998 fwded_unicast);
+1 -1
net/mac80211/tx.c
··· 1464 1464 if (ieee80211_vif_is_mesh(&sdata->vif) && 1465 1465 ieee80211_is_data(hdr->frame_control) && 1466 1466 !is_multicast_ether_addr(hdr->addr1)) 1467 - if (mesh_nexthop_lookup(skb, sdata)) { 1467 + if (mesh_nexthop_resolve(skb, sdata)) { 1468 1468 /* skb queued: don't free */ 1469 1469 rcu_read_unlock(); 1470 1470 return;