* @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.
  */
        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),
 };
 
 /*
 
        .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,
 };
 
 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,
 
        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;
 
 
                        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:
 
        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;
+}