blob: c2560cb50f1d56733db337be278380a3eb1348eb [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 Mintz7b0db852018-02-28 23:29:39 +0200173int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
174 struct mr_mfc *c, struct rtmsg *rtm);
175int mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
176 struct mr_table *(*iter)(struct net *net,
177 struct mr_table *mrt),
178 int (*fill)(struct mr_table *mrt,
179 struct sk_buff *skb,
180 u32 portid, u32 seq, struct mr_mfc *c,
181 int cmd, int flags),
182 spinlock_t *lock);
Yuval Mintz6853f212018-02-28 23:29:29 +0200183#else
184static inline void vif_device_init(struct vif_device *v,
185 struct net_device *dev,
186 unsigned long rate_limit,
187 unsigned char threshold,
188 unsigned short flags,
189 unsigned short get_iflink_mask)
190{
191}
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200192
Yuval Mintz845c9a72018-02-28 23:29:35 +0200193static inline void *
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200194mr_table_alloc(struct net *net, u32 id,
Yuval Mintz845c9a72018-02-28 23:29:35 +0200195 struct mr_table_ops *ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200196 void (*expire_func)(struct timer_list *t),
197 void (*table_set)(struct mr_table *mrt,
198 struct net *net))
199{
200 return NULL;
201}
Yuval Mintz845c9a72018-02-28 23:29:35 +0200202
203static inline void *mr_mfc_find_parent(struct mr_table *mrt,
204 void *hasharg, int parent)
205{
206 return NULL;
207}
208
209static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
210 int vifi)
211{
212 return NULL;
213}
214
215static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
216 int vifi, void *hasharg)
217{
218 return NULL;
219}
Yuval Mintz7b0db852018-02-28 23:29:39 +0200220
221static inline int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
222 struct mr_mfc *c, struct rtmsg *rtm)
223{
224 return -EINVAL;
225}
226
227static inline int
228mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
229 struct mr_table *(*iter)(struct net *net,
230 struct mr_table *mrt),
231 int (*fill)(struct mr_table *mrt,
232 struct sk_buff *skb,
233 u32 portid, u32 seq, struct mr_mfc *c,
234 int cmd, int flags),
235 spinlock_t *lock)
236{
237 return -EINVAL;
238}
Yuval Mintz6853f212018-02-28 23:29:29 +0200239#endif
Yuval Mintz845c9a72018-02-28 23:29:35 +0200240
241static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
242{
243 return mr_mfc_find_parent(mrt, hasharg, -1);
244}
Yuval Mintzc8d61962018-02-28 23:29:36 +0200245
246#ifdef CONFIG_PROC_FS
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200247struct mr_vif_iter {
248 struct seq_net_private p;
249 struct mr_table *mrt;
250 int ct;
251};
252
Yuval Mintzc8d61962018-02-28 23:29:36 +0200253struct mr_mfc_iter {
254 struct seq_net_private p;
255 struct mr_table *mrt;
256 struct list_head *cache;
257
258 /* Lock protecting the mr_table's unresolved queue */
259 spinlock_t *lock;
260};
261
262#ifdef CONFIG_IP_MROUTE_COMMON
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200263void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
264void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
265
266static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
267{
268 return *pos ? mr_vif_seq_idx(seq_file_net(seq),
269 seq->private, *pos - 1)
270 : SEQ_START_TOKEN;
271}
272
Yuval Mintzc8d61962018-02-28 23:29:36 +0200273/* These actually return 'struct mr_mfc *', but to avoid need for explicit
274 * castings they simply return void.
275 */
276void *mr_mfc_seq_idx(struct net *net,
277 struct mr_mfc_iter *it, loff_t pos);
278void *mr_mfc_seq_next(struct seq_file *seq, void *v,
279 loff_t *pos);
280
281static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
282 struct mr_table *mrt, spinlock_t *lock)
283{
284 struct mr_mfc_iter *it = seq->private;
285
286 it->mrt = mrt;
287 it->cache = NULL;
288 it->lock = lock;
289
290 return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
291 seq->private, *pos - 1)
292 : SEQ_START_TOKEN;
293}
294
295static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
296{
297 struct mr_mfc_iter *it = seq->private;
298 struct mr_table *mrt = it->mrt;
299
300 if (it->cache == &mrt->mfc_unres_queue)
301 spin_unlock_bh(it->lock);
302 else if (it->cache == &mrt->mfc_cache_list)
303 rcu_read_unlock();
304}
305#else
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200306static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
307 loff_t pos)
308{
309 return NULL;
310}
311
312static inline void *mr_vif_seq_next(struct seq_file *seq,
313 void *v, loff_t *pos)
314{
315 return NULL;
316}
317
318static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
319{
320 return NULL;
321}
322
Yuval Mintzc8d61962018-02-28 23:29:36 +0200323static inline void *mr_mfc_seq_idx(struct net *net,
324 struct mr_mfc_iter *it, loff_t pos)
325{
326 return NULL;
327}
328
329static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
330 loff_t *pos)
331{
332 return NULL;
333}
334
335static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
336 struct mr_table *mrt, spinlock_t *lock)
337{
338 return NULL;
339}
340
341static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
342{
343}
344#endif
345#endif
Yuval Mintz6853f212018-02-28 23:29:29 +0200346#endif