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