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 28 struct 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 49 int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 50 struct fib_lookup_arg *arg); 51 52 int l3mdev_master_ifindex_rcu(const struct net_device *dev); 53 static 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 64 static 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 82 /* get index of an interface to use for FIB lookups. For devices 83 * enslaved to an L3 master device FIB lookups are based on the 84 * master index 85 */ 86 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 87 { 88 return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; 89 } 90 91 static inline int l3mdev_fib_oif(struct net_device *dev) 92 { 93 int oif; 94 95 rcu_read_lock(); 96 oif = l3mdev_fib_oif_rcu(dev); 97 rcu_read_unlock(); 98 99 return oif; 100 } 101 102 u32 l3mdev_fib_table_rcu(const struct net_device *dev); 103 u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 104 static inline u32 l3mdev_fib_table(const struct net_device *dev) 105 { 106 u32 tb_id; 107 108 rcu_read_lock(); 109 tb_id = l3mdev_fib_table_rcu(dev); 110 rcu_read_unlock(); 111 112 return tb_id; 113 } 114 115 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 116 const struct flowi4 *fl4) 117 { 118 if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable) 119 return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4); 120 121 return NULL; 122 } 123 124 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 125 { 126 struct net_device *dev; 127 bool rc = false; 128 129 if (ifindex == 0) 130 return false; 131 132 rcu_read_lock(); 133 134 dev = dev_get_by_index_rcu(net, ifindex); 135 if (dev) 136 rc = netif_is_l3_master(dev); 137 138 rcu_read_unlock(); 139 140 return rc; 141 } 142 143 int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4); 144 145 struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6); 146 int l3mdev_get_saddr6(struct net *net, const struct sock *sk, 147 struct flowi6 *fl6); 148 149 static inline 150 struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto) 151 { 152 struct net_device *master = NULL; 153 154 if (netif_is_l3_slave(skb->dev)) 155 master = netdev_master_upper_dev_get_rcu(skb->dev); 156 else if (netif_is_l3_master(skb->dev)) 157 master = skb->dev; 158 159 if (master && master->l3mdev_ops->l3mdev_l3_rcv) 160 skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto); 161 162 return skb; 163 } 164 165 static inline 166 struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 167 { 168 return l3mdev_l3_rcv(skb, AF_INET); 169 } 170 171 static inline 172 struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 173 { 174 return l3mdev_l3_rcv(skb, AF_INET6); 175 } 176 177 #else 178 179 static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev) 180 { 181 return 0; 182 } 183 static inline int l3mdev_master_ifindex(struct net_device *dev) 184 { 185 return 0; 186 } 187 188 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 189 { 190 return 0; 191 } 192 193 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 194 { 195 return dev ? dev->ifindex : 0; 196 } 197 static inline int l3mdev_fib_oif(struct net_device *dev) 198 { 199 return dev ? dev->ifindex : 0; 200 } 201 202 static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 203 { 204 return 0; 205 } 206 static inline u32 l3mdev_fib_table(const struct net_device *dev) 207 { 208 return 0; 209 } 210 static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 211 { 212 return 0; 213 } 214 215 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 216 const struct flowi4 *fl4) 217 { 218 return NULL; 219 } 220 221 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 222 { 223 return false; 224 } 225 226 static inline int l3mdev_get_saddr(struct net *net, int ifindex, 227 struct flowi4 *fl4) 228 { 229 return 0; 230 } 231 232 static inline 233 struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6) 234 { 235 return NULL; 236 } 237 238 static inline int l3mdev_get_saddr6(struct net *net, const struct sock *sk, 239 struct flowi6 *fl6) 240 { 241 return 0; 242 } 243 244 static inline 245 struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 246 { 247 return skb; 248 } 249 250 static inline 251 struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 252 { 253 return skb; 254 } 255 256 static inline 257 int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 258 struct fib_lookup_arg *arg) 259 { 260 return 1; 261 } 262 #endif 263 264 #endif /* _NET_L3MDEV_H_ */ 265