at v4.5 5.3 kB view raw
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 26struct 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 42int l3mdev_master_ifindex_rcu(struct net_device *dev); 43static 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 54static 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 */ 76static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 77{ 78 return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; 79} 80 81static 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 92u32 l3mdev_fib_table_rcu(const struct net_device *dev); 93u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 94static 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 105static 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 114static 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 133static inline int l3mdev_get_saddr(struct net *net, int ifindex, 134 struct flowi4 *fl4) 135{ 136 struct net_device *dev; 137 int rc = 0; 138 139 if (ifindex) { 140 141 rcu_read_lock(); 142 143 dev = dev_get_by_index_rcu(net, ifindex); 144 if (dev && netif_is_l3_master(dev) && 145 dev->l3mdev_ops->l3mdev_get_saddr) { 146 rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4); 147 } 148 149 rcu_read_unlock(); 150 } 151 152 return rc; 153} 154 155static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev, 156 const struct flowi6 *fl6) 157{ 158 if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rt6_dst) 159 return dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6); 160 161 return NULL; 162} 163 164static inline 165struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net, 166 const struct flowi6 *fl6) 167{ 168 struct dst_entry *dst = NULL; 169 struct net_device *dev; 170 171 dev = dev_get_by_index(net, fl6->flowi6_oif); 172 if (dev) { 173 dst = l3mdev_get_rt6_dst(dev, fl6); 174 dev_put(dev); 175 } 176 177 return dst; 178} 179 180#else 181 182static inline int l3mdev_master_ifindex_rcu(struct net_device *dev) 183{ 184 return 0; 185} 186static inline int l3mdev_master_ifindex(struct net_device *dev) 187{ 188 return 0; 189} 190 191static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 192{ 193 return 0; 194} 195 196static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 197{ 198 return dev ? dev->ifindex : 0; 199} 200static inline int l3mdev_fib_oif(struct net_device *dev) 201{ 202 return dev ? dev->ifindex : 0; 203} 204 205static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 206{ 207 return 0; 208} 209static inline u32 l3mdev_fib_table(const struct net_device *dev) 210{ 211 return 0; 212} 213static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 214{ 215 return 0; 216} 217 218static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 219 const struct flowi4 *fl4) 220{ 221 return NULL; 222} 223 224static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 225{ 226 return false; 227} 228 229static inline int l3mdev_get_saddr(struct net *net, int ifindex, 230 struct flowi4 *fl4) 231{ 232 return 0; 233} 234 235static inline 236struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev, 237 const struct flowi6 *fl6) 238{ 239 return NULL; 240} 241static inline 242struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net, 243 const struct flowi6 *fl6) 244{ 245 return NULL; 246} 247#endif 248 249#endif /* _NET_L3MDEV_H_ */