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