1 /* 2 * include/net/l3mdev.h - L3 master device API 3 * Copyright (c) 2015 Cumulus Networks 4 * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 #ifndef _NET_L3MDEV_H_ 12 #define _NET_L3MDEV_H_ 13 14 /** 15 * struct l3mdev_ops - l3mdev operations 16 * 17 * @l3mdev_fib_table: Get FIB table id to use for lookups 18 * 19 * @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device 20 */ 21 22 struct l3mdev_ops { 23 u32 (*l3mdev_fib_table)(const struct net_device *dev); 24 struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev, 25 const struct flowi4 *fl4); 26 }; 27 28 #ifdef CONFIG_NET_L3_MASTER_DEV 29 30 int l3mdev_master_ifindex_rcu(struct net_device *dev); 31 static inline int l3mdev_master_ifindex(struct net_device *dev) 32 { 33 int ifindex; 34 35 rcu_read_lock(); 36 ifindex = l3mdev_master_ifindex_rcu(dev); 37 rcu_read_unlock(); 38 39 return ifindex; 40 } 41 42 /* get index of an interface to use for FIB lookups. For devices 43 * enslaved to an L3 master device FIB lookups are based on the 44 * master index 45 */ 46 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 47 { 48 return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; 49 } 50 51 static inline int l3mdev_fib_oif(struct net_device *dev) 52 { 53 int oif; 54 55 rcu_read_lock(); 56 oif = l3mdev_fib_oif_rcu(dev); 57 rcu_read_unlock(); 58 59 return oif; 60 } 61 62 u32 l3mdev_fib_table_rcu(const struct net_device *dev); 63 u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 64 static inline u32 l3mdev_fib_table(const struct net_device *dev) 65 { 66 u32 tb_id; 67 68 rcu_read_lock(); 69 tb_id = l3mdev_fib_table_rcu(dev); 70 rcu_read_unlock(); 71 72 return tb_id; 73 } 74 75 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 76 const struct flowi4 *fl4) 77 { 78 if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable) 79 return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4); 80 81 return NULL; 82 } 83 84 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 85 { 86 struct net_device *dev; 87 bool rc = false; 88 89 if (ifindex == 0) 90 return false; 91 92 rcu_read_lock(); 93 94 dev = dev_get_by_index_rcu(net, ifindex); 95 if (dev) 96 rc = netif_is_l3_master(dev); 97 98 rcu_read_unlock(); 99 100 return rc; 101 } 102 103 #else 104 105 static inline int l3mdev_master_ifindex_rcu(struct net_device *dev) 106 { 107 return 0; 108 } 109 static inline int l3mdev_master_ifindex(struct net_device *dev) 110 { 111 return 0; 112 } 113 114 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 115 { 116 return dev ? dev->ifindex : 0; 117 } 118 static inline int l3mdev_fib_oif(struct net_device *dev) 119 { 120 return dev ? dev->ifindex : 0; 121 } 122 123 static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 124 { 125 return 0; 126 } 127 static inline u32 l3mdev_fib_table(const struct net_device *dev) 128 { 129 return 0; 130 } 131 static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 132 { 133 return 0; 134 } 135 136 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 137 const struct flowi4 *fl4) 138 { 139 return NULL; 140 } 141 142 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 143 { 144 return false; 145 } 146 147 #endif 148 149 #endif /* _NET_L3MDEV_H_ */ 150