Introduce xdp_set_features_flag utility routine in order to update dynamically xdp_features according to the dynamic hw configuration via ethtool (e.g. changing number of hw rx/tx queues). Add xdp_clear_features_flag() in order to clear all xdp_feature flag. Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- Documentation/netlink/specs/netdev.yaml | 1 + include/net/xdp.h | 11 +++++++++++ include/uapi/linux/netdev.h | 2 ++ net/core/xdp.c | 26 ++++++++++++++++++------- tools/include/uapi/linux/netdev.h | 2 ++ tools/net/ynl/ynl-gen-c.py | 2 +- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml index cffef09729f1..7e4a5b4e7162 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -7,6 +7,7 @@ definitions: - type: flags name: xdp-act + render-max: true entries: - name: basic diff --git a/include/net/xdp.h b/include/net/xdp.h index d517bfac937b..41c57b8b1671 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -428,12 +428,18 @@ MAX_XDP_METADATA_KFUNC, #ifdef CONFIG_NET u32 bpf_xdp_metadata_kfunc_id(int id); bool bpf_dev_bound_kfunc_id(u32 btf_id); +void xdp_set_features_flag(struct net_device *dev, xdp_features_t val); void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg); void xdp_features_clear_redirect_target(struct net_device *dev); #else static inline u32 bpf_xdp_metadata_kfunc_id(int id) { return 0; } static inline bool bpf_dev_bound_kfunc_id(u32 btf_id) { return false; } +static inline void +xdp_set_features_flag(struct net_device *dev, xdp_features_t val) +{ +} + static inline void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg) { @@ -445,4 +451,9 @@ xdp_features_clear_redirect_target(struct net_device *dev) } #endif +static inline void xdp_clear_features_flag(struct net_device *dev) +{ + xdp_set_features_flag(dev, 0); +} + #endif /* __LINUX_NET_XDP_H__ */ diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h index 588391447bfb..497cfc93f2e3 100644 --- a/include/uapi/linux/netdev.h +++ b/include/uapi/linux/netdev.h @@ -33,6 +33,8 @@ enum netdev_xdp_act { NETDEV_XDP_ACT_HW_OFFLOAD = 16, NETDEV_XDP_ACT_RX_SG = 32, NETDEV_XDP_ACT_NDO_XMIT_SG = 64, + + NETDEV_XDP_ACT_MASK = 127, }; enum { diff --git a/net/core/xdp.c b/net/core/xdp.c index 8c92fc553317..87e654b7d06c 100644 --- a/net/core/xdp.c +++ b/net/core/xdp.c @@ -774,20 +774,32 @@ static int __init xdp_metadata_init(void) } late_initcall(xdp_metadata_init); -void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg) +void xdp_set_features_flag(struct net_device *dev, xdp_features_t val) { - dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT; - if (support_sg) - dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT_SG; + val &= NETDEV_XDP_ACT_MASK; + if (dev->xdp_features == val) + return; + dev->xdp_features = val; call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev); } +EXPORT_SYMBOL_GPL(xdp_set_features_flag); + +void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg) +{ + xdp_features_t val = (dev->xdp_features | NETDEV_XDP_ACT_NDO_XMIT); + + if (support_sg) + val |= NETDEV_XDP_ACT_NDO_XMIT_SG; + xdp_set_features_flag(dev, val); +} EXPORT_SYMBOL_GPL(xdp_features_set_redirect_target); void xdp_features_clear_redirect_target(struct net_device *dev) { - dev->xdp_features &= ~(NETDEV_XDP_ACT_NDO_XMIT | - NETDEV_XDP_ACT_NDO_XMIT_SG); - call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev); + xdp_features_t val = dev->xdp_features; + + val &= ~(NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_NDO_XMIT_SG); + xdp_set_features_flag(dev, val); } EXPORT_SYMBOL_GPL(xdp_features_clear_redirect_target); diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h index 588391447bfb..497cfc93f2e3 100644 --- a/tools/include/uapi/linux/netdev.h +++ b/tools/include/uapi/linux/netdev.h @@ -33,6 +33,8 @@ enum netdev_xdp_act { NETDEV_XDP_ACT_HW_OFFLOAD = 16, NETDEV_XDP_ACT_RX_SG = 32, NETDEV_XDP_ACT_NDO_XMIT_SG = 64, + + NETDEV_XDP_ACT_MASK = 127, }; enum { diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index 0d6df9414aa9..feb86f043e3b 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -1995,7 +1995,7 @@ def render_uapi(family, cw): cw.nl() if const['type'] == 'flags': max_name = c_upper(name_pfx + 'mask') - max_val = f' = {(entry.user_value() << 1) - 1},' + max_val = f' = {enum.get_mask()},' cw.p(max_name + max_val) else: max_name = c_upper(name_pfx + 'max') -- 2.39.2