DSA plays some tricks with overloading of a network device's netdev_ops in order to inject statistics, register dumps or various other operations. Because the pointer to the netdev_ops is not the same as the one the network driver registers, checks like theses:
dev->netdev_ops == &foo_ops will no longer work. In order to allow such tests to continue, introduce a ndo_equal() function pointer which can be specified by whomever assignes the net_device::netdev_ops, and in introduce a convenience function: netdev_ops_equal() which either calls that NDO, or defaults to a simple pointer comparison. A subsequent patch will do a tree wide conversion to the helper. Signed-off-by: Florian Fainelli <f.faine...@gmail.com> --- include/linux/netdevice.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ac2cd3f49aba..012033817a35 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1280,6 +1280,9 @@ struct netdev_net_notifier { * int (*ndo_tunnel_ctl)(struct net_device *dev, struct ip_tunnel_parm *p, * int cmd); * Add, change, delete or get information on an IPv4 tunnel. + * bool (*ndo_equal)(struct net_device *dev, const struct net_device_ops *ops) + * Returns if the current network device operations are equal to another + * set. */ struct net_device_ops { int (*ndo_init)(struct net_device *dev); @@ -1487,6 +1490,8 @@ struct net_device_ops { struct devlink_port * (*ndo_get_devlink_port)(struct net_device *dev); int (*ndo_tunnel_ctl)(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); + bool (*ndo_equal)(struct net_device *dev, + const struct net_device_ops *ops); }; /** @@ -2145,6 +2150,27 @@ struct net_device { }; #define to_net_dev(d) container_of(d, struct net_device, dev) +/** + * netdev_ops_equal - Convenience function for testing equality of a + * &struct net_device_ops against another. + * @dev: &struct net_device instance + * @ops: &struct net_device_ops to test against + */ +static inline bool netdev_ops_equal(struct net_device *dev, + const struct net_device_ops *ops) +{ + if (!dev->netdev_ops->ndo_equal) + return dev->netdev_ops == ops; + + return dev->netdev_ops->ndo_equal(dev, ops); +} + +static inline bool __netdev_ops_equal(const struct net_device *dev, + const struct net_device_ops *ops) +{ + return netdev_ops_equal((struct net_device *)dev, ops); +} + static inline bool netif_elide_gro(const struct net_device *dev) { if (!(dev->features & NETIF_F_GRO) || dev->xdp_prog) -- 2.25.1