mac80211: probe unexercised mesh links
authorRajkumar Manoharan <rmanohar@codeaurora.org>
Thu, 11 Apr 2019 20:47:26 +0000 (13:47 -0700)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 26 Apr 2019 11:02:11 +0000 (13:02 +0200)
The requirement for mesh link metric refreshing, is that from one
mesh point we be able to send some data frames to other mesh points
which are not currently selected as a primary traffic path, but which
are only 1 hop away. The absence of the primary path to the chosen node
makes it necessary to apply some form of marking on a chosen packet
stream so that the packets can be properly steered to the selected node
for testing, and not by the regular mesh path lookup.

Tested-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mesh_hwmp.c
net/mac80211/tx.c

index d66fbfe8d55d0347598b1cba47b9a05e123401e4..76a443f32fc82ca65a9271bd8778a48f0aa4d5a7 100644 (file)
@@ -807,6 +807,7 @@ enum mac80211_tx_info_flags {
  * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
  * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
+ * @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
  *
  * These flags are used in tx_info->control.flags.
  */
@@ -816,6 +817,7 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_CTRL_RATE_INJECT           = BIT(2),
        IEEE80211_TX_CTRL_AMSDU                 = BIT(3),
        IEEE80211_TX_CTRL_FAST_XMIT             = BIT(4),
+       IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP     = BIT(5),
 };
 
 /*
index ba6e4080d63d1bc45a89aa453ddb6ad9af0ddb9d..52e6a091b7e40800a989fdb12fe6acfffb00124f 100644 (file)
@@ -4035,4 +4035,5 @@ const struct cfg80211_ops mac80211_config_ops = {
        .get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
        .start_pmsr = ieee80211_start_pmsr,
        .abort_pmsr = ieee80211_abort_pmsr,
+       .probe_mesh_link = ieee80211_probe_mesh_link,
 };
index 9b0190eaff1ebc5e07a037e805f4c22ca3ef8dd7..073a8235ae1bd8cfcd28640a31bbb66bb4d22f96 100644 (file)
@@ -1779,6 +1779,8 @@ void ieee80211_clear_fast_xmit(struct sta_info *sta);
 int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
                              const u8 *buf, size_t len,
                              const u8 *dest, __be16 proto, bool unencrypted);
+int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
+                             const u8 *buf, size_t len);
 
 /* HT */
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
index 2c5929c0fa622e2395ad3405fd778c13f63336bd..bf8e13cd5fd16f31fc7c059b64da456c3428db14 100644 (file)
@@ -1135,6 +1135,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
        if (ieee80211_is_qos_nullfunc(hdr->frame_control))
                return 0;
 
+       /* Allow injected packets to bypass mesh routing */
+       if (info->control.flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
+               return 0;
+
        if (!mesh_nexthop_lookup(sdata, skb))
                return 0;
 
index 9e3678675f3baacb7627b34dd8fa66dec65e1278..8037384fc06e07a4ea22b6c7877bfd03ec19b9af 100644 (file)
@@ -2607,6 +2607,13 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                        goto free;
                }
                band = chanctx_conf->def.chan->band;
+
+               /* For injected frames, fill RA right away as nexthop lookup
+                * will be skipped.
+                */
+               if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) &&
+                   is_zero_ether_addr(hdr.addr1))
+                       memcpy(hdr.addr1, skb->data, ETH_ALEN);
                break;
 #endif
        case NL80211_IFTYPE_STATION:
@@ -5091,3 +5098,32 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 
        return 0;
 }
+
+int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
+                             const u8 *buf, size_t len)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+       struct sk_buff *skb;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + len +
+                           30 + /* header size */
+                           18); /* 11s header size */
+       if (!skb)
+               return -ENOMEM;
+
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+       skb_put_data(skb, buf, len);
+
+       skb->dev = dev;
+       skb->protocol = htons(ETH_P_802_3);
+       skb_reset_network_header(skb);
+       skb_reset_mac_header(skb);
+
+       local_bh_disable();
+       __ieee80211_subif_start_xmit(skb, skb->dev, 0,
+                                    IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP);
+       local_bh_enable();
+
+       return 0;
+}