2021-11-12 11:22:29

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH] mac80211: add support for .ndo_fill_forward_path

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 <[email protected]>
---
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(-)

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



2021-11-15 13:35:18

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH] mac80211: add support for .ndo_fill_forward_path

> 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 <[email protected]>
> ---
> 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 <[email protected]>

>
> 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
>


Attachments:
(No filename) (5.73 kB)
signature.asc (228.00 B)
Download all attachments