blob: f40202b16dae00bf65d48d41dcdb1ebcb3405113 [file] [log] [blame]
Yuval Mintz6853f212018-02-28 23:29:29 +02001#ifndef __LINUX_MROUTE_BASE_H
2#define __LINUX_MROUTE_BASE_H
3
4#include <linux/netdevice.h>
Yuval Mintzb70432f2018-02-28 23:29:32 +02005#include <linux/rhashtable.h>
Yuval Mintzc8d61962018-02-28 23:29:36 +02006#include <linux/spinlock.h>
Yuval Mintzb70432f2018-02-28 23:29:32 +02007#include <net/net_namespace.h>
8#include <net/sock.h>
Yuval Mintz6853f212018-02-28 23:29:29 +02009
10/**
11 * struct vif_device - interface representor for multicast routing
12 * @dev: network device being used
13 * @bytes_in: statistic; bytes ingressing
14 * @bytes_out: statistic; bytes egresing
15 * @pkt_in: statistic; packets ingressing
16 * @pkt_out: statistic; packets egressing
17 * @rate_limit: Traffic shaping (NI)
18 * @threshold: TTL threshold
19 * @flags: Control flags
20 * @link: Physical interface index
21 * @dev_parent_id: device parent id
22 * @local: Local address
23 * @remote: Remote address for tunnels
24 */
25struct vif_device {
26 struct net_device *dev;
27 unsigned long bytes_in, bytes_out;
28 unsigned long pkt_in, pkt_out;
29 unsigned long rate_limit;
30 unsigned char threshold;
31 unsigned short flags;
32 int link;
33
34 /* Currently only used by ipmr */
35 struct netdev_phys_item_id dev_parent_id;
36 __be32 local, remote;
37};
38
Yuval Mintzb70432f2018-02-28 23:29:32 +020039#ifndef MAXVIFS
40/* This one is nasty; value is defined in uapi using different symbols for
41 * mroute and morute6 but both map into same 32.
42 */
43#define MAXVIFS 32
44#endif
45
46#define VIF_EXISTS(_mrt, _idx) (!!((_mrt)->vif_table[_idx].dev))
47
Yuval Mintz889cd832018-02-28 23:29:38 +020048/* mfc_flags:
49 * MFC_STATIC - the entry was added statically (not by a routing daemon)
50 * MFC_OFFLOAD - the entry was offloaded to the hardware
51 */
52enum {
53 MFC_STATIC = BIT(0),
54 MFC_OFFLOAD = BIT(1),
55};
56
Yuval Mintzb70432f2018-02-28 23:29:32 +020057/**
Yuval Mintz494fff52018-02-28 23:29:34 +020058 * struct mr_mfc - common multicast routing entries
59 * @mnode: rhashtable list
60 * @mfc_parent: source interface (iif)
61 * @mfc_flags: entry flags
62 * @expires: unresolved entry expire time
63 * @unresolved: unresolved cached skbs
64 * @last_assert: time of last assert
65 * @minvif: minimum VIF id
66 * @maxvif: maximum VIF id
67 * @bytes: bytes that have passed for this entry
68 * @pkt: packets that have passed for this entry
69 * @wrong_if: number of wrong source interface hits
70 * @lastuse: time of last use of the group (traffic or update)
71 * @ttls: OIF TTL threshold array
72 * @refcount: reference count for this entry
73 * @list: global entry list
74 * @rcu: used for entry destruction
75 */
76struct mr_mfc {
77 struct rhlist_head mnode;
78 unsigned short mfc_parent;
79 int mfc_flags;
80
81 union {
82 struct {
83 unsigned long expires;
84 struct sk_buff_head unresolved;
85 } unres;
86 struct {
87 unsigned long last_assert;
88 int minvif;
89 int maxvif;
90 unsigned long bytes;
91 unsigned long pkt;
92 unsigned long wrong_if;
93 unsigned long lastuse;
94 unsigned char ttls[MAXVIFS];
95 refcount_t refcount;
96 } res;
97 } mfc_un;
98 struct list_head list;
99 struct rcu_head rcu;
100};
101
Yuval Mintz845c9a72018-02-28 23:29:35 +0200102struct mr_table;
103
104/**
105 * struct mr_table_ops - callbacks and info for protocol-specific ops
106 * @rht_params: parameters for accessing the MFC hash
107 * @cmparg_any: a hash key to be used for matching on (*,*) routes
108 */
109struct mr_table_ops {
110 const struct rhashtable_params *rht_params;
111 void *cmparg_any;
112};
113
Yuval Mintz494fff52018-02-28 23:29:34 +0200114/**
Yuval Mintzb70432f2018-02-28 23:29:32 +0200115 * struct mr_table - a multicast routing table
116 * @list: entry within a list of multicast routing tables
117 * @net: net where this table belongs
Yuval Mintz845c9a72018-02-28 23:29:35 +0200118 * @ops: protocol specific operations
Yuval Mintzb70432f2018-02-28 23:29:32 +0200119 * @id: identifier of the table
120 * @mroute_sk: socket associated with the table
121 * @ipmr_expire_timer: timer for handling unresolved routes
122 * @mfc_unres_queue: list of unresolved MFC entries
123 * @vif_table: array containing all possible vifs
124 * @mfc_hash: Hash table of all resolved routes for easy lookup
125 * @mfc_cache_list: list of resovled routes for possible traversal
126 * @maxvif: Identifier of highest value vif currently in use
127 * @cache_resolve_queue_len: current size of unresolved queue
128 * @mroute_do_assert: Whether to inform userspace on wrong ingress
129 * @mroute_do_pim: Whether to receive IGMP PIMv1
130 * @mroute_reg_vif_num: PIM-device vif index
131 */
132struct mr_table {
133 struct list_head list;
134 possible_net_t net;
Yuval Mintz845c9a72018-02-28 23:29:35 +0200135 struct mr_table_ops ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200136 u32 id;
137 struct sock __rcu *mroute_sk;
138 struct timer_list ipmr_expire_timer;
139 struct list_head mfc_unres_queue;
140 struct vif_device vif_table[MAXVIFS];
141 struct rhltable mfc_hash;
142 struct list_head mfc_cache_list;
143 int maxvif;
144 atomic_t cache_resolve_queue_len;
145 bool mroute_do_assert;
146 bool mroute_do_pim;
147 int mroute_reg_vif_num;
148};
149
Yuval Mintz6853f212018-02-28 23:29:29 +0200150#ifdef CONFIG_IP_MROUTE_COMMON
151void vif_device_init(struct vif_device *v,
152 struct net_device *dev,
153 unsigned long rate_limit,
154 unsigned char threshold,
155 unsigned short flags,
156 unsigned short get_iflink_mask);
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200157
158struct mr_table *
159mr_table_alloc(struct net *net, u32 id,
Yuval Mintz845c9a72018-02-28 23:29:35 +0200160 struct mr_table_ops *ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200161 void (*expire_func)(struct timer_list *t),
162 void (*table_set)(struct mr_table *mrt,
163 struct net *net));
Yuval Mintz845c9a72018-02-28 23:29:35 +0200164
165/* These actually return 'struct mr_mfc *', but to avoid need for explicit
166 * castings they simply return void.
167 */
168void *mr_mfc_find_parent(struct mr_table *mrt,
169 void *hasharg, int parent);
170void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
171void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
172
Yuval Mintz6853f212018-02-28 23:29:29 +0200173#else
174static inline void vif_device_init(struct vif_device *v,
175 struct net_device *dev,
176 unsigned long rate_limit,
177 unsigned char threshold,
178 unsigned short flags,
179 unsigned short get_iflink_mask)
180{
181}
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200182
Yuval Mintz845c9a72018-02-28 23:29:35 +0200183static inline void *
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200184mr_table_alloc(struct net *net, u32 id,
Yuval Mintz845c9a72018-02-28 23:29:35 +0200185 struct mr_table_ops *ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200186 void (*expire_func)(struct timer_list *t),
187 void (*table_set)(struct mr_table *mrt,
188 struct net *net))
189{
190 return NULL;
191}
Yuval Mintz845c9a72018-02-28 23:29:35 +0200192
193static inline void *mr_mfc_find_parent(struct mr_table *mrt,
194 void *hasharg, int parent)
195{
196 return NULL;
197}
198
199static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
200 int vifi)
201{
202 return NULL;
203}
204
205static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
206 int vifi, void *hasharg)
207{
208 return NULL;
209}
Yuval Mintz6853f212018-02-28 23:29:29 +0200210#endif
Yuval Mintz845c9a72018-02-28 23:29:35 +0200211
212static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
213{
214 return mr_mfc_find_parent(mrt, hasharg, -1);
215}
Yuval Mintzc8d61962018-02-28 23:29:36 +0200216
217#ifdef CONFIG_PROC_FS
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200218struct mr_vif_iter {
219 struct seq_net_private p;
220 struct mr_table *mrt;
221 int ct;
222};
223
Yuval Mintzc8d61962018-02-28 23:29:36 +0200224struct mr_mfc_iter {
225 struct seq_net_private p;
226 struct mr_table *mrt;
227 struct list_head *cache;
228
229 /* Lock protecting the mr_table's unresolved queue */
230 spinlock_t *lock;
231};
232
233#ifdef CONFIG_IP_MROUTE_COMMON
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200234void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
235void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
236
237static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
238{
239 return *pos ? mr_vif_seq_idx(seq_file_net(seq),
240 seq->private, *pos - 1)
241 : SEQ_START_TOKEN;
242}
243
Yuval Mintzc8d61962018-02-28 23:29:36 +0200244/* These actually return 'struct mr_mfc *', but to avoid need for explicit
245 * castings they simply return void.
246 */
247void *mr_mfc_seq_idx(struct net *net,
248 struct mr_mfc_iter *it, loff_t pos);
249void *mr_mfc_seq_next(struct seq_file *seq, void *v,
250 loff_t *pos);
251
252static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
253 struct mr_table *mrt, spinlock_t *lock)
254{
255 struct mr_mfc_iter *it = seq->private;
256
257 it->mrt = mrt;
258 it->cache = NULL;
259 it->lock = lock;
260
261 return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
262 seq->private, *pos - 1)
263 : SEQ_START_TOKEN;
264}
265
266static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
267{
268 struct mr_mfc_iter *it = seq->private;
269 struct mr_table *mrt = it->mrt;
270
271 if (it->cache == &mrt->mfc_unres_queue)
272 spin_unlock_bh(it->lock);
273 else if (it->cache == &mrt->mfc_cache_list)
274 rcu_read_unlock();
275}
276#else
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200277static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
278 loff_t pos)
279{
280 return NULL;
281}
282
283static inline void *mr_vif_seq_next(struct seq_file *seq,
284 void *v, loff_t *pos)
285{
286 return NULL;
287}
288
289static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
290{
291 return NULL;
292}
293
Yuval Mintzc8d61962018-02-28 23:29:36 +0200294static inline void *mr_mfc_seq_idx(struct net *net,
295 struct mr_mfc_iter *it, loff_t pos)
296{
297 return NULL;
298}
299
300static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
301 loff_t *pos)
302{
303 return NULL;
304}
305
306static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
307 struct mr_table *mrt, spinlock_t *lock)
308{
309 return NULL;
310}
311
312static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
313{
314}
315#endif
316#endif
Yuval Mintz6853f212018-02-28 23:29:29 +0200317#endif