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 * @l3mdev_get_saddr: Get source address for a flow 22 * 23 * @l3mdev_get_rt6_dst: Get cached IPv6 rt6_info (dst_entry) for device 24 */ 25 26 struct l3mdev_ops { 27 u32 (*l3mdev_fib_table)(const struct net_device *dev); 28 29 /* IPv4 ops */ 30 struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev, 31 const struct flowi4 *fl4); 32 int (*l3mdev_get_saddr)(struct net_device *dev, 33 struct flowi4 *fl4); 34 35 /* IPv6 ops */ 36 struct dst_entry * (*l3mdev_get_rt6_dst)(const struct net_device *dev, 37 const struct flowi6 *fl6); 38 }; 39 40 #ifdef CONFIG_NET_L3_MASTER_DEV 41 42 int l3mdev_master_ifindex_rcu(const struct net_device *dev); 43 static inline int l3mdev_master_ifindex(struct net_device *dev) 44 { 45 int ifindex; 46 47 rcu_read_lock(); 48 ifindex = l3mdev_master_ifindex_rcu(dev); 49 rcu_read_unlock(); 50 51 return ifindex; 52 } 53 54 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 55 { 56 struct net_device *dev; 57 int rc = 0; 58 59 if (likely(ifindex)) { 60 rcu_read_lock(); 61 62 dev = dev_get_by_index_rcu(net, ifindex); 63 if (dev) 64 rc = l3mdev_master_ifindex_rcu(dev); 65 66 rcu_read_unlock(); 67 } 68 69 return rc; 70 } 71 72 /* get index of an interface to use for FIB lookups. For devices 73 * enslaved to an L3 master device FIB lookups are based on the 74 * master index 75 */ 76 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 77 { 78 return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; 79 } 80 81 static inline int l3mdev_fib_oif(struct net_device *dev) 82 { 83 int oif; 84 85 rcu_read_lock(); 86 oif = l3mdev_fib_oif_rcu(dev); 87 rcu_read_unlock(); 88 89 return oif; 90 } 91 92 u32 l3mdev_fib_table_rcu(const struct net_device *dev); 93 u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 94 static inline u32 l3mdev_fib_table(const struct net_device *dev) 95 { 96 u32 tb_id; 97 98 rcu_read_lock(); 99 tb_id = l3mdev_fib_table_rcu(dev); 100 rcu_read_unlock(); 101 102 return tb_id; 103 } 104 105 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 106 const struct flowi4 *fl4) 107 { 108 if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable) 109 return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4); 110 111 return NULL; 112 } 113 114 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 115 { 116 struct net_device *dev; 117 bool rc = false; 118 119 if (ifindex == 0) 120 return false; 121 122 rcu_read_lock(); 123 124 dev = dev_get_by_index_rcu(net, ifindex); 125 if (dev) 126 rc = netif_is_l3_master(dev); 127 128 rcu_read_unlock(); 129 130 return rc; 131 } 132 133 int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4); 134 135 struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6); 136 137 #else 138 139 static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev) 140 { 141 return 0; 142 } 143 static inline int l3mdev_master_ifindex(struct net_device *dev) 144 { 145 return 0; 146 } 147 148 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 149 { 150 return 0; 151 } 152 153 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 154 { 155 return dev ? dev->ifindex : 0; 156 } 157 static inline int l3mdev_fib_oif(struct net_device *dev) 158 { 159 return dev ? dev->ifindex : 0; 160 } 161 162 static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 163 { 164 return 0; 165 } 166 static inline u32 l3mdev_fib_table(const struct net_device *dev) 167 { 168 return 0; 169 } 170 static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 171 { 172 return 0; 173 } 174 175 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 176 const struct flowi4 *fl4) 177 { 178 return NULL; 179 } 180 181 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 182 { 183 return false; 184 } 185 186 static inline int l3mdev_get_saddr(struct net *net, int ifindex, 187 struct flowi4 *fl4) 188 { 189 return 0; 190 } 191 192 static inline 193 struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6) 194 { 195 return NULL; 196 } 197 #endif 198 199 #endif /* _NET_L3MDEV_H_ */ 200