at v4.8 6.6 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#include <net/fib_rules.h> 15 16/** 17 * struct l3mdev_ops - l3mdev operations 18 * 19 * @l3mdev_fib_table: Get FIB table id to use for lookups 20 * 21 * @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device 22 * 23 * @l3mdev_get_saddr: Get source address for a flow 24 * 25 * @l3mdev_get_rt6_dst: Get cached IPv6 rt6_info (dst_entry) for device 26 */ 27 28struct l3mdev_ops { 29 u32 (*l3mdev_fib_table)(const struct net_device *dev); 30 struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev, 31 struct sk_buff *skb, u16 proto); 32 33 /* IPv4 ops */ 34 struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev, 35 const struct flowi4 *fl4); 36 int (*l3mdev_get_saddr)(struct net_device *dev, 37 struct flowi4 *fl4); 38 39 /* IPv6 ops */ 40 struct dst_entry * (*l3mdev_get_rt6_dst)(const struct net_device *dev, 41 struct flowi6 *fl6); 42 int (*l3mdev_get_saddr6)(struct net_device *dev, 43 const struct sock *sk, 44 struct flowi6 *fl6); 45}; 46 47#ifdef CONFIG_NET_L3_MASTER_DEV 48 49int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 50 struct fib_lookup_arg *arg); 51 52int l3mdev_master_ifindex_rcu(const struct net_device *dev); 53static inline int l3mdev_master_ifindex(struct net_device *dev) 54{ 55 int ifindex; 56 57 rcu_read_lock(); 58 ifindex = l3mdev_master_ifindex_rcu(dev); 59 rcu_read_unlock(); 60 61 return ifindex; 62} 63 64static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 65{ 66 struct net_device *dev; 67 int rc = 0; 68 69 if (likely(ifindex)) { 70 rcu_read_lock(); 71 72 dev = dev_get_by_index_rcu(net, ifindex); 73 if (dev) 74 rc = l3mdev_master_ifindex_rcu(dev); 75 76 rcu_read_unlock(); 77 } 78 79 return rc; 80} 81 82static inline 83const struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev) 84{ 85 /* netdev_master_upper_dev_get_rcu calls 86 * list_first_or_null_rcu to walk the upper dev list. 87 * list_first_or_null_rcu does not handle a const arg. We aren't 88 * making changes, just want the master device from that list so 89 * typecast to remove the const 90 */ 91 struct net_device *dev = (struct net_device *)_dev; 92 const struct net_device *master; 93 94 if (!dev) 95 return NULL; 96 97 if (netif_is_l3_master(dev)) 98 master = dev; 99 else if (netif_is_l3_slave(dev)) 100 master = netdev_master_upper_dev_get_rcu(dev); 101 else 102 master = NULL; 103 104 return master; 105} 106 107/* get index of an interface to use for FIB lookups. For devices 108 * enslaved to an L3 master device FIB lookups are based on the 109 * master index 110 */ 111static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 112{ 113 return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; 114} 115 116static inline int l3mdev_fib_oif(struct net_device *dev) 117{ 118 int oif; 119 120 rcu_read_lock(); 121 oif = l3mdev_fib_oif_rcu(dev); 122 rcu_read_unlock(); 123 124 return oif; 125} 126 127u32 l3mdev_fib_table_rcu(const struct net_device *dev); 128u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 129static inline u32 l3mdev_fib_table(const struct net_device *dev) 130{ 131 u32 tb_id; 132 133 rcu_read_lock(); 134 tb_id = l3mdev_fib_table_rcu(dev); 135 rcu_read_unlock(); 136 137 return tb_id; 138} 139 140static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 141 const struct flowi4 *fl4) 142{ 143 if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable) 144 return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4); 145 146 return NULL; 147} 148 149static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 150{ 151 struct net_device *dev; 152 bool rc = false; 153 154 if (ifindex == 0) 155 return false; 156 157 rcu_read_lock(); 158 159 dev = dev_get_by_index_rcu(net, ifindex); 160 if (dev) 161 rc = netif_is_l3_master(dev); 162 163 rcu_read_unlock(); 164 165 return rc; 166} 167 168int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4); 169 170struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6); 171int l3mdev_get_saddr6(struct net *net, const struct sock *sk, 172 struct flowi6 *fl6); 173 174static inline 175struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto) 176{ 177 struct net_device *master = NULL; 178 179 if (netif_is_l3_slave(skb->dev)) 180 master = netdev_master_upper_dev_get_rcu(skb->dev); 181 else if (netif_is_l3_master(skb->dev)) 182 master = skb->dev; 183 184 if (master && master->l3mdev_ops->l3mdev_l3_rcv) 185 skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto); 186 187 return skb; 188} 189 190static inline 191struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 192{ 193 return l3mdev_l3_rcv(skb, AF_INET); 194} 195 196static inline 197struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 198{ 199 return l3mdev_l3_rcv(skb, AF_INET6); 200} 201 202#else 203 204static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev) 205{ 206 return 0; 207} 208static inline int l3mdev_master_ifindex(struct net_device *dev) 209{ 210 return 0; 211} 212 213static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 214{ 215 return 0; 216} 217 218static inline 219const struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev) 220{ 221 return NULL; 222} 223 224static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 225{ 226 return dev ? dev->ifindex : 0; 227} 228static inline int l3mdev_fib_oif(struct net_device *dev) 229{ 230 return dev ? dev->ifindex : 0; 231} 232 233static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 234{ 235 return 0; 236} 237static inline u32 l3mdev_fib_table(const struct net_device *dev) 238{ 239 return 0; 240} 241static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 242{ 243 return 0; 244} 245 246static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 247 const struct flowi4 *fl4) 248{ 249 return NULL; 250} 251 252static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 253{ 254 return false; 255} 256 257static inline int l3mdev_get_saddr(struct net *net, int ifindex, 258 struct flowi4 *fl4) 259{ 260 return 0; 261} 262 263static inline 264struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6) 265{ 266 return NULL; 267} 268 269static inline int l3mdev_get_saddr6(struct net *net, const struct sock *sk, 270 struct flowi6 *fl6) 271{ 272 return 0; 273} 274 275static inline 276struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 277{ 278 return skb; 279} 280 281static inline 282struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 283{ 284 return skb; 285} 286 287static inline 288int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 289 struct fib_lookup_arg *arg) 290{ 291 return 1; 292} 293#endif 294 295#endif /* _NET_L3MDEV_H_ */