1#ifndef __LINUX_MROUTE_BASE_H
2#define __LINUX_MROUTE_BASE_H
3
4#include <linux/netdevice.h>
5#include <linux/rhashtable-types.h>
6#include <linux/spinlock.h>
7#include <net/net_namespace.h>
8#include <net/sock.h>
9#include <net/fib_notifier.h>
10#include <net/ip_fib.h>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27struct vif_device {
28 struct net_device *dev;
29 unsigned long bytes_in, bytes_out;
30 unsigned long pkt_in, pkt_out;
31 unsigned long rate_limit;
32 unsigned char threshold;
33 unsigned short flags;
34 int link;
35
36
37 struct netdev_phys_item_id dev_parent_id;
38 __be32 local, remote;
39};
40
41struct vif_entry_notifier_info {
42 struct fib_notifier_info info;
43 struct net_device *dev;
44 unsigned short vif_index;
45 unsigned short vif_flags;
46 u32 tb_id;
47};
48
49static inline int mr_call_vif_notifier(struct notifier_block *nb,
50 unsigned short family,
51 enum fib_event_type event_type,
52 struct vif_device *vif,
53 unsigned short vif_index, u32 tb_id,
54 struct netlink_ext_ack *extack)
55{
56 struct vif_entry_notifier_info info = {
57 .info = {
58 .family = family,
59 .extack = extack,
60 },
61 .dev = vif->dev,
62 .vif_index = vif_index,
63 .vif_flags = vif->flags,
64 .tb_id = tb_id,
65 };
66
67 return call_fib_notifier(nb, event_type, &info.info);
68}
69
70static inline int mr_call_vif_notifiers(struct net *net,
71 unsigned short family,
72 enum fib_event_type event_type,
73 struct vif_device *vif,
74 unsigned short vif_index, u32 tb_id,
75 unsigned int *ipmr_seq)
76{
77 struct vif_entry_notifier_info info = {
78 .info = {
79 .family = family,
80 },
81 .dev = vif->dev,
82 .vif_index = vif_index,
83 .vif_flags = vif->flags,
84 .tb_id = tb_id,
85 };
86
87 ASSERT_RTNL();
88 (*ipmr_seq)++;
89 return call_fib_notifiers(net, event_type, &info.info);
90}
91
92#ifndef MAXVIFS
93
94
95
96#define MAXVIFS 32
97#endif
98
99#define VIF_EXISTS(_mrt, _idx) (!!((_mrt)->vif_table[_idx].dev))
100
101
102
103
104
105enum {
106 MFC_STATIC = BIT(0),
107 MFC_OFFLOAD = BIT(1),
108};
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130struct mr_mfc {
131 struct rhlist_head mnode;
132 unsigned short mfc_parent;
133 int mfc_flags;
134
135 union {
136 struct {
137 unsigned long expires;
138 struct sk_buff_head unresolved;
139 } unres;
140 struct {
141 unsigned long last_assert;
142 int minvif;
143 int maxvif;
144 unsigned long bytes;
145 unsigned long pkt;
146 unsigned long wrong_if;
147 unsigned long lastuse;
148 unsigned char ttls[MAXVIFS];
149 refcount_t refcount;
150 } res;
151 } mfc_un;
152 struct list_head list;
153 struct rcu_head rcu;
154 void (*free)(struct rcu_head *head);
155};
156
157static inline void mr_cache_put(struct mr_mfc *c)
158{
159 if (refcount_dec_and_test(&c->mfc_un.res.refcount))
160 call_rcu(&c->rcu, c->free);
161}
162
163static inline void mr_cache_hold(struct mr_mfc *c)
164{
165 refcount_inc(&c->mfc_un.res.refcount);
166}
167
168struct mfc_entry_notifier_info {
169 struct fib_notifier_info info;
170 struct mr_mfc *mfc;
171 u32 tb_id;
172};
173
174static inline int mr_call_mfc_notifier(struct notifier_block *nb,
175 unsigned short family,
176 enum fib_event_type event_type,
177 struct mr_mfc *mfc, u32 tb_id,
178 struct netlink_ext_ack *extack)
179{
180 struct mfc_entry_notifier_info info = {
181 .info = {
182 .family = family,
183 .extack = extack,
184 },
185 .mfc = mfc,
186 .tb_id = tb_id
187 };
188
189 return call_fib_notifier(nb, event_type, &info.info);
190}
191
192static inline int mr_call_mfc_notifiers(struct net *net,
193 unsigned short family,
194 enum fib_event_type event_type,
195 struct mr_mfc *mfc, u32 tb_id,
196 unsigned int *ipmr_seq)
197{
198 struct mfc_entry_notifier_info info = {
199 .info = {
200 .family = family,
201 },
202 .mfc = mfc,
203 .tb_id = tb_id
204 };
205
206 ASSERT_RTNL();
207 (*ipmr_seq)++;
208 return call_fib_notifiers(net, event_type, &info.info);
209}
210
211struct mr_table;
212
213
214
215
216
217
218struct mr_table_ops {
219 const struct rhashtable_params *rht_params;
220 void *cmparg_any;
221};
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241struct mr_table {
242 struct list_head list;
243 possible_net_t net;
244 struct mr_table_ops ops;
245 u32 id;
246 struct sock __rcu *mroute_sk;
247 struct timer_list ipmr_expire_timer;
248 struct list_head mfc_unres_queue;
249 struct vif_device vif_table[MAXVIFS];
250 struct rhltable mfc_hash;
251 struct list_head mfc_cache_list;
252 int maxvif;
253 atomic_t cache_resolve_queue_len;
254 bool mroute_do_assert;
255 bool mroute_do_pim;
256 bool mroute_do_wrvifwhole;
257 int mroute_reg_vif_num;
258};
259
260#ifdef CONFIG_IP_MROUTE_COMMON
261void vif_device_init(struct vif_device *v,
262 struct net_device *dev,
263 unsigned long rate_limit,
264 unsigned char threshold,
265 unsigned short flags,
266 unsigned short get_iflink_mask);
267
268struct mr_table *
269mr_table_alloc(struct net *net, u32 id,
270 struct mr_table_ops *ops,
271 void (*expire_func)(struct timer_list *t),
272 void (*table_set)(struct mr_table *mrt,
273 struct net *net));
274
275
276
277
278void *mr_mfc_find_parent(struct mr_table *mrt,
279 void *hasharg, int parent);
280void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
281void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
282
283int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
284 struct mr_mfc *c, struct rtmsg *rtm);
285int mr_table_dump(struct mr_table *mrt, struct sk_buff *skb,
286 struct netlink_callback *cb,
287 int (*fill)(struct mr_table *mrt, struct sk_buff *skb,
288 u32 portid, u32 seq, struct mr_mfc *c,
289 int cmd, int flags),
290 spinlock_t *lock, struct fib_dump_filter *filter);
291int mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
292 struct mr_table *(*iter)(struct net *net,
293 struct mr_table *mrt),
294 int (*fill)(struct mr_table *mrt,
295 struct sk_buff *skb,
296 u32 portid, u32 seq, struct mr_mfc *c,
297 int cmd, int flags),
298 spinlock_t *lock, struct fib_dump_filter *filter);
299
300int mr_dump(struct net *net, struct notifier_block *nb, unsigned short family,
301 int (*rules_dump)(struct net *net,
302 struct notifier_block *nb,
303 struct netlink_ext_ack *extack),
304 struct mr_table *(*mr_iter)(struct net *net,
305 struct mr_table *mrt),
306 rwlock_t *mrt_lock, struct netlink_ext_ack *extack);
307#else
308static inline void vif_device_init(struct vif_device *v,
309 struct net_device *dev,
310 unsigned long rate_limit,
311 unsigned char threshold,
312 unsigned short flags,
313 unsigned short get_iflink_mask)
314{
315}
316
317static inline void *mr_mfc_find_parent(struct mr_table *mrt,
318 void *hasharg, int parent)
319{
320 return NULL;
321}
322
323static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
324 int vifi)
325{
326 return NULL;
327}
328
329static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
330 int vifi, void *hasharg)
331{
332 return NULL;
333}
334
335static inline int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
336 struct mr_mfc *c, struct rtmsg *rtm)
337{
338 return -EINVAL;
339}
340
341static inline int
342mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
343 struct mr_table *(*iter)(struct net *net,
344 struct mr_table *mrt),
345 int (*fill)(struct mr_table *mrt,
346 struct sk_buff *skb,
347 u32 portid, u32 seq, struct mr_mfc *c,
348 int cmd, int flags),
349 spinlock_t *lock, struct fib_dump_filter *filter)
350{
351 return -EINVAL;
352}
353
354static inline int mr_dump(struct net *net, struct notifier_block *nb,
355 unsigned short family,
356 int (*rules_dump)(struct net *net,
357 struct notifier_block *nb,
358 struct netlink_ext_ack *extack),
359 struct mr_table *(*mr_iter)(struct net *net,
360 struct mr_table *mrt),
361 rwlock_t *mrt_lock, struct netlink_ext_ack *extack)
362{
363 return -EINVAL;
364}
365#endif
366
367static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
368{
369 return mr_mfc_find_parent(mrt, hasharg, -1);
370}
371
372#ifdef CONFIG_PROC_FS
373struct mr_vif_iter {
374 struct seq_net_private p;
375 struct mr_table *mrt;
376 int ct;
377};
378
379struct mr_mfc_iter {
380 struct seq_net_private p;
381 struct mr_table *mrt;
382 struct list_head *cache;
383
384
385 spinlock_t *lock;
386};
387
388#ifdef CONFIG_IP_MROUTE_COMMON
389void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
390void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
391
392static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
393{
394 return *pos ? mr_vif_seq_idx(seq_file_net(seq),
395 seq->private, *pos - 1)
396 : SEQ_START_TOKEN;
397}
398
399
400
401
402void *mr_mfc_seq_idx(struct net *net,
403 struct mr_mfc_iter *it, loff_t pos);
404void *mr_mfc_seq_next(struct seq_file *seq, void *v,
405 loff_t *pos);
406
407static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
408 struct mr_table *mrt, spinlock_t *lock)
409{
410 struct mr_mfc_iter *it = seq->private;
411
412 it->mrt = mrt;
413 it->cache = NULL;
414 it->lock = lock;
415
416 return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
417 seq->private, *pos - 1)
418 : SEQ_START_TOKEN;
419}
420
421static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
422{
423 struct mr_mfc_iter *it = seq->private;
424 struct mr_table *mrt = it->mrt;
425
426 if (it->cache == &mrt->mfc_unres_queue)
427 spin_unlock_bh(it->lock);
428 else if (it->cache == &mrt->mfc_cache_list)
429 rcu_read_unlock();
430}
431#else
432static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
433 loff_t pos)
434{
435 return NULL;
436}
437
438static inline void *mr_vif_seq_next(struct seq_file *seq,
439 void *v, loff_t *pos)
440{
441 return NULL;
442}
443
444static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
445{
446 return NULL;
447}
448
449static inline void *mr_mfc_seq_idx(struct net *net,
450 struct mr_mfc_iter *it, loff_t pos)
451{
452 return NULL;
453}
454
455static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
456 loff_t *pos)
457{
458 return NULL;
459}
460
461static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
462 struct mr_table *mrt, spinlock_t *lock)
463{
464 return NULL;
465}
466
467static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
468{
469}
470#endif
471#endif
472#endif
473