xref: /openbmc/linux/include/net/l3mdev.h (revision 9478d12d)
11b69c6d0SDavid Ahern /*
21b69c6d0SDavid Ahern  * include/net/l3mdev.h - L3 master device API
31b69c6d0SDavid Ahern  * Copyright (c) 2015 Cumulus Networks
41b69c6d0SDavid Ahern  * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com>
51b69c6d0SDavid Ahern  *
61b69c6d0SDavid Ahern  * This program is free software; you can redistribute it and/or modify
71b69c6d0SDavid Ahern  * it under the terms of the GNU General Public License as published by
81b69c6d0SDavid Ahern  * the Free Software Foundation; either version 2 of the License, or
91b69c6d0SDavid Ahern  * (at your option) any later version.
101b69c6d0SDavid Ahern  */
111b69c6d0SDavid Ahern #ifndef _NET_L3MDEV_H_
121b69c6d0SDavid Ahern #define _NET_L3MDEV_H_
131b69c6d0SDavid Ahern 
141b69c6d0SDavid Ahern /**
151b69c6d0SDavid Ahern  * struct l3mdev_ops - l3mdev operations
161b69c6d0SDavid Ahern  *
171b69c6d0SDavid Ahern  * @l3mdev_fib_table: Get FIB table id to use for lookups
181b69c6d0SDavid Ahern  *
191b69c6d0SDavid Ahern  * @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device
201b69c6d0SDavid Ahern  */
211b69c6d0SDavid Ahern 
221b69c6d0SDavid Ahern struct l3mdev_ops {
231b69c6d0SDavid Ahern 	u32		(*l3mdev_fib_table)(const struct net_device *dev);
241b69c6d0SDavid Ahern 	struct rtable *	(*l3mdev_get_rtable)(const struct net_device *dev,
251b69c6d0SDavid Ahern 					     const struct flowi4 *fl4);
261b69c6d0SDavid Ahern };
271b69c6d0SDavid Ahern 
281b69c6d0SDavid Ahern #ifdef CONFIG_NET_L3_MASTER_DEV
291b69c6d0SDavid Ahern 
301b69c6d0SDavid Ahern int l3mdev_master_ifindex_rcu(struct net_device *dev);
311b69c6d0SDavid Ahern static inline int l3mdev_master_ifindex(struct net_device *dev)
321b69c6d0SDavid Ahern {
331b69c6d0SDavid Ahern 	int ifindex;
341b69c6d0SDavid Ahern 
351b69c6d0SDavid Ahern 	rcu_read_lock();
361b69c6d0SDavid Ahern 	ifindex = l3mdev_master_ifindex_rcu(dev);
371b69c6d0SDavid Ahern 	rcu_read_unlock();
381b69c6d0SDavid Ahern 
391b69c6d0SDavid Ahern 	return ifindex;
401b69c6d0SDavid Ahern }
411b69c6d0SDavid Ahern 
421b69c6d0SDavid Ahern /* get index of an interface to use for FIB lookups. For devices
431b69c6d0SDavid Ahern  * enslaved to an L3 master device FIB lookups are based on the
441b69c6d0SDavid Ahern  * master index
451b69c6d0SDavid Ahern  */
461b69c6d0SDavid Ahern static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
471b69c6d0SDavid Ahern {
481b69c6d0SDavid Ahern 	return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex;
491b69c6d0SDavid Ahern }
501b69c6d0SDavid Ahern 
511b69c6d0SDavid Ahern static inline int l3mdev_fib_oif(struct net_device *dev)
521b69c6d0SDavid Ahern {
531b69c6d0SDavid Ahern 	int oif;
541b69c6d0SDavid Ahern 
551b69c6d0SDavid Ahern 	rcu_read_lock();
561b69c6d0SDavid Ahern 	oif = l3mdev_fib_oif_rcu(dev);
571b69c6d0SDavid Ahern 	rcu_read_unlock();
581b69c6d0SDavid Ahern 
591b69c6d0SDavid Ahern 	return oif;
601b69c6d0SDavid Ahern }
611b69c6d0SDavid Ahern 
621b69c6d0SDavid Ahern u32 l3mdev_fib_table_rcu(const struct net_device *dev);
631b69c6d0SDavid Ahern u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
641b69c6d0SDavid Ahern static inline u32 l3mdev_fib_table(const struct net_device *dev)
651b69c6d0SDavid Ahern {
661b69c6d0SDavid Ahern 	u32 tb_id;
671b69c6d0SDavid Ahern 
681b69c6d0SDavid Ahern 	rcu_read_lock();
691b69c6d0SDavid Ahern 	tb_id = l3mdev_fib_table_rcu(dev);
701b69c6d0SDavid Ahern 	rcu_read_unlock();
711b69c6d0SDavid Ahern 
721b69c6d0SDavid Ahern 	return tb_id;
731b69c6d0SDavid Ahern }
741b69c6d0SDavid Ahern 
751b69c6d0SDavid Ahern static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
761b69c6d0SDavid Ahern 					       const struct flowi4 *fl4)
771b69c6d0SDavid Ahern {
781b69c6d0SDavid Ahern 	if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable)
791b69c6d0SDavid Ahern 		return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4);
801b69c6d0SDavid Ahern 
811b69c6d0SDavid Ahern 	return NULL;
821b69c6d0SDavid Ahern }
831b69c6d0SDavid Ahern 
849478d12dSDavid Ahern static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
859478d12dSDavid Ahern {
869478d12dSDavid Ahern 	struct net_device *dev;
879478d12dSDavid Ahern 	bool rc = false;
889478d12dSDavid Ahern 
899478d12dSDavid Ahern 	if (ifindex == 0)
909478d12dSDavid Ahern 		return false;
919478d12dSDavid Ahern 
929478d12dSDavid Ahern 	rcu_read_lock();
939478d12dSDavid Ahern 
949478d12dSDavid Ahern 	dev = dev_get_by_index_rcu(net, ifindex);
959478d12dSDavid Ahern 	if (dev)
969478d12dSDavid Ahern 		rc = netif_is_l3_master(dev);
979478d12dSDavid Ahern 
989478d12dSDavid Ahern 	rcu_read_unlock();
999478d12dSDavid Ahern 
1009478d12dSDavid Ahern 	return rc;
1019478d12dSDavid Ahern }
1029478d12dSDavid Ahern 
1031b69c6d0SDavid Ahern #else
1041b69c6d0SDavid Ahern 
1051b69c6d0SDavid Ahern static inline int l3mdev_master_ifindex_rcu(struct net_device *dev)
1061b69c6d0SDavid Ahern {
1071b69c6d0SDavid Ahern 	return 0;
1081b69c6d0SDavid Ahern }
1091b69c6d0SDavid Ahern static inline int l3mdev_master_ifindex(struct net_device *dev)
1101b69c6d0SDavid Ahern {
1111b69c6d0SDavid Ahern 	return 0;
1121b69c6d0SDavid Ahern }
1131b69c6d0SDavid Ahern 
1141b69c6d0SDavid Ahern static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
1151b69c6d0SDavid Ahern {
1161b69c6d0SDavid Ahern 	return dev ? dev->ifindex : 0;
1171b69c6d0SDavid Ahern }
1181b69c6d0SDavid Ahern static inline int l3mdev_fib_oif(struct net_device *dev)
1191b69c6d0SDavid Ahern {
1201b69c6d0SDavid Ahern 	return dev ? dev->ifindex : 0;
1211b69c6d0SDavid Ahern }
1221b69c6d0SDavid Ahern 
1231b69c6d0SDavid Ahern static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
1241b69c6d0SDavid Ahern {
1251b69c6d0SDavid Ahern 	return 0;
1261b69c6d0SDavid Ahern }
1271b69c6d0SDavid Ahern static inline u32 l3mdev_fib_table(const struct net_device *dev)
1281b69c6d0SDavid Ahern {
1291b69c6d0SDavid Ahern 	return 0;
1301b69c6d0SDavid Ahern }
1311b69c6d0SDavid Ahern static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
1321b69c6d0SDavid Ahern {
1331b69c6d0SDavid Ahern 	return 0;
1341b69c6d0SDavid Ahern }
1351b69c6d0SDavid Ahern 
1361b69c6d0SDavid Ahern static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
1371b69c6d0SDavid Ahern 					       const struct flowi4 *fl4)
1381b69c6d0SDavid Ahern {
1391b69c6d0SDavid Ahern 	return NULL;
1401b69c6d0SDavid Ahern }
1411b69c6d0SDavid Ahern 
1429478d12dSDavid Ahern static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
1439478d12dSDavid Ahern {
1449478d12dSDavid Ahern 	return false;
1459478d12dSDavid Ahern }
1469478d12dSDavid Ahern 
1471b69c6d0SDavid Ahern #endif
1481b69c6d0SDavid Ahern 
1491b69c6d0SDavid Ahern #endif /* _NET_L3MDEV_H_ */
150