1
2
3
4
5
6
7
8
9
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#include <linux/rh_kabi.h>
18
19struct l3mdev_ops_extended_rh {
20};
21
22
23
24
25
26
27
28
29
30
31
32
33
34struct l3mdev_ops {
35 u32 (*l3mdev_fib_table)(const struct net_device *dev);
36 struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev,
37 struct sk_buff *skb, u16 proto);
38 struct sk_buff * (*l3mdev_l3_out)(struct net_device *dev,
39 struct sock *sk, struct sk_buff *skb,
40 u16 proto);
41
42
43 struct dst_entry * (*l3mdev_link_scope_lookup)(const struct net_device *dev,
44 struct flowi6 *fl6);
45
46 RH_KABI_RESERVE(1)
47 RH_KABI_RESERVE(2)
48 RH_KABI_RESERVE(3)
49 RH_KABI_RESERVE(4)
50 RH_KABI_RESERVE(5)
51 RH_KABI_RESERVE(6)
52 RH_KABI_RESERVE(7)
53 RH_KABI_SIZE_AND_EXTEND(l3mdev_ops_extended)
54};
55
56#ifdef CONFIG_NET_L3_MASTER_DEV
57
58int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
59 struct fib_lookup_arg *arg);
60
61void l3mdev_update_flow(struct net *net, struct flowi *fl);
62
63int l3mdev_master_ifindex_rcu(const struct net_device *dev);
64static inline int l3mdev_master_ifindex(struct net_device *dev)
65{
66 int ifindex;
67
68 rcu_read_lock();
69 ifindex = l3mdev_master_ifindex_rcu(dev);
70 rcu_read_unlock();
71
72 return ifindex;
73}
74
75static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
76{
77 struct net_device *dev;
78 int rc = 0;
79
80 if (likely(ifindex)) {
81 rcu_read_lock();
82
83 dev = dev_get_by_index_rcu(net, ifindex);
84 if (dev)
85 rc = l3mdev_master_ifindex_rcu(dev);
86
87 rcu_read_unlock();
88 }
89
90 return rc;
91}
92
93static inline
94struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
95{
96
97
98
99
100
101
102 struct net_device *dev = (struct net_device *)_dev;
103 struct net_device *master;
104
105 if (!dev)
106 return NULL;
107
108 if (netif_is_l3_master(dev))
109 master = dev;
110 else if (netif_is_l3_slave(dev))
111 master = netdev_master_upper_dev_get_rcu(dev);
112 else
113 master = NULL;
114
115 return master;
116}
117
118u32 l3mdev_fib_table_rcu(const struct net_device *dev);
119u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
120static inline u32 l3mdev_fib_table(const struct net_device *dev)
121{
122 u32 tb_id;
123
124 rcu_read_lock();
125 tb_id = l3mdev_fib_table_rcu(dev);
126 rcu_read_unlock();
127
128 return tb_id;
129}
130
131static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
132{
133 struct net_device *dev;
134 bool rc = false;
135
136 if (ifindex == 0)
137 return false;
138
139 rcu_read_lock();
140
141 dev = dev_get_by_index_rcu(net, ifindex);
142 if (dev)
143 rc = netif_is_l3_master(dev);
144
145 rcu_read_unlock();
146
147 return rc;
148}
149
150struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6);
151
152static inline
153struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
154{
155 struct net_device *master = NULL;
156
157 if (netif_is_l3_slave(skb->dev))
158 master = netdev_master_upper_dev_get_rcu(skb->dev);
159 else if (netif_is_l3_master(skb->dev) ||
160 netif_has_l3_rx_handler(skb->dev))
161 master = skb->dev;
162
163 if (master && master->l3mdev_ops->l3mdev_l3_rcv)
164 skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
165
166 return skb;
167}
168
169static inline
170struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
171{
172 return l3mdev_l3_rcv(skb, AF_INET);
173}
174
175static inline
176struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
177{
178 return l3mdev_l3_rcv(skb, AF_INET6);
179}
180
181static inline
182struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto)
183{
184 struct net_device *dev = skb_dst(skb)->dev;
185
186 if (netif_is_l3_slave(dev)) {
187 struct net_device *master;
188
189 master = netdev_master_upper_dev_get_rcu(dev);
190 if (master && master->l3mdev_ops->l3mdev_l3_out)
191 skb = master->l3mdev_ops->l3mdev_l3_out(master, sk,
192 skb, proto);
193 }
194
195 return skb;
196}
197
198static inline
199struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
200{
201 return l3mdev_l3_out(sk, skb, AF_INET);
202}
203
204static inline
205struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
206{
207 return l3mdev_l3_out(sk, skb, AF_INET6);
208}
209#else
210
211static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
212{
213 return 0;
214}
215static inline int l3mdev_master_ifindex(struct net_device *dev)
216{
217 return 0;
218}
219
220static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
221{
222 return 0;
223}
224
225static inline
226struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
227{
228 return NULL;
229}
230
231static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
232{
233 return 0;
234}
235static inline u32 l3mdev_fib_table(const struct net_device *dev)
236{
237 return 0;
238}
239static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
240{
241 return 0;
242}
243
244static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
245{
246 return false;
247}
248
249static inline
250struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6)
251{
252 return NULL;
253}
254
255static inline
256struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
257{
258 return skb;
259}
260
261static inline
262struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
263{
264 return skb;
265}
266
267static inline
268struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
269{
270 return skb;
271}
272
273static inline
274struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
275{
276 return skb;
277}
278
279static inline
280int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
281 struct fib_lookup_arg *arg)
282{
283 return 1;
284}
285static inline
286void l3mdev_update_flow(struct net *net, struct flowi *fl)
287{
288}
289#endif
290
291#endif
292