Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <nbd@nbd.name>
Tested-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://lore.kernel.org/r/20211112112223.1209-1-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Felix Fietkau and committed by
Johannes Berg
d787a3e3 71abf71e

+96 -1
+7
include/net/mac80211.h
··· 3952 3952 * radar channel. 3953 3953 * The caller is expected to set chandef pointer to NULL in order to 3954 3954 * disable offchannel CAC/radar detection. 3955 + * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to 3956 + * resolve a path for hardware flow offloading 3955 3957 */ 3956 3958 struct ieee80211_ops { 3957 3959 void (*tx)(struct ieee80211_hw *hw, ··· 4284 4282 struct ieee80211_sta *sta, u8 flowid); 4285 4283 int (*set_radar_offchan)(struct ieee80211_hw *hw, 4286 4284 struct cfg80211_chan_def *chandef); 4285 + int (*net_fill_forward_path)(struct ieee80211_hw *hw, 4286 + struct ieee80211_vif *vif, 4287 + struct ieee80211_sta *sta, 4288 + struct net_device_path_ctx *ctx, 4289 + struct net_device_path *path); 4287 4290 }; 4288 4291 4289 4292 /**
+22
net/mac80211/driver-ops.h
··· 1483 1483 trace_drv_return_void(local); 1484 1484 } 1485 1485 1486 + static inline int drv_net_fill_forward_path(struct ieee80211_local *local, 1487 + struct ieee80211_sub_if_data *sdata, 1488 + struct ieee80211_sta *sta, 1489 + struct net_device_path_ctx *ctx, 1490 + struct net_device_path *path) 1491 + { 1492 + int ret = -EOPNOTSUPP; 1493 + 1494 + sdata = get_bss_sdata(sdata); 1495 + if (!check_sdata_in_driver(sdata)) 1496 + return -EIO; 1497 + 1498 + trace_drv_net_fill_forward_path(local, sdata, sta); 1499 + if (local->ops->net_fill_forward_path) 1500 + ret = local->ops->net_fill_forward_path(&local->hw, 1501 + &sdata->vif, sta, 1502 + ctx, path); 1503 + trace_drv_return_int(local, ret); 1504 + 1505 + return ret; 1506 + } 1507 + 1486 1508 #endif /* __MAC80211_DRIVER_OPS */
+1 -1
net/mac80211/ieee80211_i.h
··· 1463 1463 }; 1464 1464 1465 1465 static inline struct ieee80211_sub_if_data * 1466 - IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) 1466 + IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev) 1467 1467 { 1468 1468 return netdev_priv(dev); 1469 1469 }
+59
net/mac80211/iface.c
··· 789 789 .ndo_get_stats64 = ieee80211_get_stats64, 790 790 }; 791 791 792 + static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx, 793 + struct net_device_path *path) 794 + { 795 + struct ieee80211_sub_if_data *sdata; 796 + struct ieee80211_local *local; 797 + struct sta_info *sta; 798 + int ret = -ENOENT; 799 + 800 + sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev); 801 + local = sdata->local; 802 + 803 + if (!local->ops->net_fill_forward_path) 804 + return -EOPNOTSUPP; 805 + 806 + rcu_read_lock(); 807 + switch (sdata->vif.type) { 808 + case NL80211_IFTYPE_AP_VLAN: 809 + sta = rcu_dereference(sdata->u.vlan.sta); 810 + if (sta) 811 + break; 812 + if (sdata->wdev.use_4addr) 813 + goto out; 814 + if (is_multicast_ether_addr(ctx->daddr)) 815 + goto out; 816 + sta = sta_info_get_bss(sdata, ctx->daddr); 817 + break; 818 + case NL80211_IFTYPE_AP: 819 + if (is_multicast_ether_addr(ctx->daddr)) 820 + goto out; 821 + sta = sta_info_get(sdata, ctx->daddr); 822 + break; 823 + case NL80211_IFTYPE_STATION: 824 + if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { 825 + sta = sta_info_get(sdata, ctx->daddr); 826 + if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { 827 + if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) 828 + goto out; 829 + 830 + break; 831 + } 832 + } 833 + 834 + sta = sta_info_get(sdata, sdata->u.mgd.bssid); 835 + break; 836 + default: 837 + goto out; 838 + } 839 + 840 + if (!sta) 841 + goto out; 842 + 843 + ret = drv_net_fill_forward_path(local, sdata, &sta->sta, ctx, path); 844 + out: 845 + rcu_read_unlock(); 846 + 847 + return ret; 848 + } 849 + 792 850 static const struct net_device_ops ieee80211_dataif_8023_ops = { 793 851 .ndo_open = ieee80211_open, 794 852 .ndo_stop = ieee80211_stop, ··· 856 798 .ndo_set_mac_address = ieee80211_change_mac, 857 799 .ndo_select_queue = ieee80211_netdev_select_queue, 858 800 .ndo_get_stats64 = ieee80211_get_stats64, 801 + .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path, 859 802 }; 860 803 861 804 static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
+7
net/mac80211/trace.h
··· 2892 2892 ) 2893 2893 ); 2894 2894 2895 + DEFINE_EVENT(sta_event, drv_net_fill_forward_path, 2896 + TP_PROTO(struct ieee80211_local *local, 2897 + struct ieee80211_sub_if_data *sdata, 2898 + struct ieee80211_sta *sta), 2899 + TP_ARGS(local, sdata, sta) 2900 + ); 2901 + 2895 2902 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ 2896 2903 2897 2904 #undef TRACE_INCLUDE_PATH