summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c1
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mesh_hwmp.c4
-rw-r--r--net/mac80211/tx.c36
4 files changed, 43 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ba6e4080d63d..52e6a091b7e4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -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,
};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9b0190eaff1e..073a8235ae1b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -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,
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 2c5929c0fa62..bf8e13cd5fd1 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -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;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9e3678675f3b..8037384fc06e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -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;
+}