> This allows drivers to provide a destination device + info for flow offload > Only supported in combination with 802.3 encap offload > > Signed-off-by: Felix Fietkau > --- > include/net/mac80211.h | 7 +++++ > net/mac80211/driver-ops.h | 22 ++++++++++++++ > net/mac80211/ieee80211_i.h | 2 +- > net/mac80211/iface.c | 61 ++++++++++++++++++++++++++++++++++++++ > net/mac80211/trace.h | 7 +++++ > 5 files changed, 98 insertions(+), 1 deletion(-) Tested-by: Lorenzo Bianconi > > diff --git a/include/net/mac80211.h b/include/net/mac80211.h > index 775dbb982654..10e6fe215f0f 100644 > --- a/include/net/mac80211.h > +++ b/include/net/mac80211.h > @@ -3952,6 +3952,8 @@ struct ieee80211_prep_tx_info { > * radar channel. > * The caller is expected to set chandef pointer to NULL in order to > * disable offchannel CAC/radar detection. > + * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to > + * resolve a path for hardware flow offloading > */ > struct ieee80211_ops { > void (*tx)(struct ieee80211_hw *hw, > @@ -4282,6 +4284,11 @@ struct ieee80211_ops { > struct ieee80211_sta *sta, u8 flowid); > int (*set_radar_offchan)(struct ieee80211_hw *hw, > struct cfg80211_chan_def *chandef); > + int (*net_fill_forward_path)(struct ieee80211_hw *hw, > + struct ieee80211_vif *vif, > + struct ieee80211_sta *sta, > + struct net_device_path_ctx *ctx, > + struct net_device_path *path); > }; > > /** > diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h > index cd3731cbf6c6..50a0cdadceec 100644 > --- a/net/mac80211/driver-ops.h > +++ b/net/mac80211/driver-ops.h > @@ -1483,4 +1483,26 @@ static inline void drv_twt_teardown_request(struct ieee80211_local *local, > trace_drv_return_void(local); > } > > +static inline int drv_net_fill_forward_path(struct ieee80211_local *local, > + struct ieee80211_sub_if_data *sdata, > + struct ieee80211_sta *sta, > + struct net_device_path_ctx *ctx, > + struct net_device_path *path) > +{ > + int ret = -EOPNOTSUPP; > + > + sdata = get_bss_sdata(sdata); > + if (!check_sdata_in_driver(sdata)) > + return -EIO; > + > + trace_drv_net_fill_forward_path(local, sdata, sta); > + if (local->ops->net_fill_forward_path) > + ret = local->ops->net_fill_forward_path(&local->hw, > + &sdata->vif, sta, > + ctx, path); > + trace_drv_return_int(local, ret); > + > + return ret; > +} > + > #endif /* __MAC80211_DRIVER_OPS */ > diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h > index 5666bbb8860b..08c0542c93a3 100644 > --- a/net/mac80211/ieee80211_i.h > +++ b/net/mac80211/ieee80211_i.h > @@ -1463,7 +1463,7 @@ struct ieee80211_local { > }; > > static inline struct ieee80211_sub_if_data * > -IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) > +IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev) > { > return netdev_priv(dev); > } > diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c > index 9a2145c8192b..6012442cd0d6 100644 > --- a/net/mac80211/iface.c > +++ b/net/mac80211/iface.c > @@ -789,6 +789,66 @@ static const struct net_device_ops ieee80211_monitorif_ops = { > .ndo_get_stats64 = ieee80211_get_stats64, > }; > > + > +static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx, > + struct net_device_path *path) > +{ > + struct ieee80211_sub_if_data *sdata; > + struct ieee80211_local *local; > + struct sta_info *sta; > + int ret = -ENOENT; > + > + sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev); > + local = sdata->local; > + > + if (!local->ops->net_fill_forward_path) > + return -EOPNOTSUPP; > + > + rcu_read_lock(); > + switch (sdata->vif.type) { > + case NL80211_IFTYPE_AP_VLAN: > + sta = rcu_dereference(sdata->u.vlan.sta); > + if (sta) > + break; > + if (sdata->wdev.use_4addr) > + goto out; > + if (is_multicast_ether_addr(ctx->daddr)) > + goto out; > + sta = sta_info_get_bss(sdata, ctx->daddr); > + break; > + case NL80211_IFTYPE_AP: > + if (is_multicast_ether_addr(ctx->daddr)) > + goto out; > + sta = sta_info_get(sdata, ctx->daddr); > + break; > + case NL80211_IFTYPE_STATION: > + if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { > + sta = sta_info_get(sdata, ctx->daddr); > + if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { > + if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) > + goto out; > + > + break; > + } > + } > + > + sta = sta_info_get(sdata, sdata->u.mgd.bssid); > + break; > + default: > + goto out; > + } > + > + if (!sta) > + goto out; > + > + ret = drv_net_fill_forward_path(local, sdata, &sta->sta, ctx, path); > +out: > + rcu_read_unlock(); > + > + return ret; > +} > + > + > static const struct net_device_ops ieee80211_dataif_8023_ops = { > .ndo_open = ieee80211_open, > .ndo_stop = ieee80211_stop, > @@ -798,6 +858,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = { > .ndo_set_mac_address = ieee80211_change_mac, > .ndo_select_queue = ieee80211_netdev_select_queue, > .ndo_get_stats64 = ieee80211_get_stats64, > + .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path, > }; > > static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype) > diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h > index 9e8381bef7ed..d91498f77796 100644 > --- a/net/mac80211/trace.h > +++ b/net/mac80211/trace.h > @@ -2892,6 +2892,13 @@ TRACE_EVENT(drv_twt_teardown_request, > ) > ); > > +DEFINE_EVENT(sta_event, drv_net_fill_forward_path, > + TP_PROTO(struct ieee80211_local *local, > + struct ieee80211_sub_if_data *sdata, > + struct ieee80211_sta *sta), > + TP_ARGS(local, sdata, sta) > +); > + > #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ > > #undef TRACE_INCLUDE_PATH > -- > 2.30.1 >