File Index
Files and directories
Sign in
FILE

mroute_base.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/mroute_base.h C
  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 * struct vif_device - interface representor for multicast routing
 14 * @dev: network device being used
 15 * @dev_tracker: refcount tracker for @dev reference
 16 * @bytes_in: statistic; bytes ingressing
 17 * @bytes_out: statistic; bytes egresing
 18 * @pkt_in: statistic; packets ingressing
 19 * @pkt_out: statistic; packets egressing
 20 * @rate_limit: Traffic shaping (NI)
 21 * @threshold: TTL threshold
 22 * @flags: Control flags
 23 * @link: Physical interface index
 24 * @dev_parent_id: device parent id
 25 * @local: Local address
 26 * @remote: Remote address for tunnels
 27 */
 28struct vif_device {
 29	struct net_device __rcu *dev;
 30	netdevice_tracker dev_tracker;
 31	unsigned long bytes_in, bytes_out;
 32	unsigned long pkt_in, pkt_out;
 33	unsigned long rate_limit;
 34	unsigned char threshold;
 35	unsigned short flags;
 36	int link;
 37
 38	/* Currently only used by ipmr */
 39	struct netdev_phys_item_id dev_parent_id;
 40	__be32 local, remote;
 41};
 42
 43struct vif_entry_notifier_info {
 44	struct fib_notifier_info info;
 45	struct net_device *dev;
 46	unsigned short vif_index;
 47	unsigned short vif_flags;
 48	u32 tb_id;
 49};
 50
 51static inline int mr_call_vif_notifier(struct notifier_block *nb,
 52				       unsigned short family,
 53				       enum fib_event_type event_type,
 54				       struct vif_device *vif,
 55				       struct net_device *vif_dev,
 56				       unsigned short vif_index, u32 tb_id,
 57				       struct netlink_ext_ack *extack)
 58{
 59	struct vif_entry_notifier_info info = {
 60		.info = {
 61			.family = family,
 62			.extack = extack,
 63		},
 64		.dev = vif_dev,
 65		.vif_index = vif_index,
 66		.vif_flags = vif->flags,
 67		.tb_id = tb_id,
 68	};
 69
 70	return call_fib_notifier(nb, event_type, &info.info);
 71}
 72
 73static inline int mr_call_vif_notifiers(struct net *net,
 74					unsigned short family,
 75					enum fib_event_type event_type,
 76					struct vif_device *vif,
 77					struct net_device *vif_dev,
 78					unsigned short vif_index, u32 tb_id,
 79					unsigned int *ipmr_seq)
 80{
 81	struct vif_entry_notifier_info info = {
 82		.info = {
 83			.family = family,
 84		},
 85		.dev = vif_dev,
 86		.vif_index = vif_index,
 87		.vif_flags = vif->flags,
 88		.tb_id = tb_id,
 89	};
 90
 91	ASSERT_RTNL();
 92	(*ipmr_seq)++;
 93	return call_fib_notifiers(net, event_type, &info.info);
 94}
 95
 96#ifndef MAXVIFS
 97/* This one is nasty; value is defined in uapi using different symbols for
 98 * mroute and morute6 but both map into same 32.
 99 */
100#define MAXVIFS	32
101#endif
102
103/* Note: This helper is deprecated. */
104#define VIF_EXISTS(_mrt, _idx) (!!rcu_access_pointer((_mrt)->vif_table[_idx].dev))
105
106/* mfc_flags:
107 * MFC_STATIC - the entry was added statically (not by a routing daemon)
108 * MFC_OFFLOAD - the entry was offloaded to the hardware
109 */
110enum {
111	MFC_STATIC = BIT(0),
112	MFC_OFFLOAD = BIT(1),
113};
114
115/**
116 * struct mr_mfc - common multicast routing entries
117 * @mnode: rhashtable list
118 * @mfc_parent: source interface (iif)
119 * @mfc_flags: entry flags
120 * @expires: unresolved entry expire time
121 * @unresolved: unresolved cached skbs
122 * @last_assert: time of last assert
123 * @minvif: minimum VIF id
124 * @maxvif: maximum VIF id
125 * @bytes: bytes that have passed for this entry
126 * @pkt: packets that have passed for this entry
127 * @wrong_if: number of wrong source interface hits
128 * @lastuse: time of last use of the group (traffic or update)
129 * @ttls: OIF TTL threshold array
130 * @refcount: reference count for this entry
131 * @list: global entry list
132 * @rcu: used for entry destruction
133 * @free: Operation used for freeing an entry under RCU
134 */
135struct mr_mfc {
136	struct rhlist_head mnode;
137	unsigned short mfc_parent;
138	int mfc_flags;
139
140	union {
141		struct {
142			unsigned long expires;
143			struct sk_buff_head unresolved;
144		} unres;
145		struct {
146			unsigned long last_assert;
147			int minvif;
148			int maxvif;
149			atomic_long_t bytes;
150			atomic_long_t pkt;
151			atomic_long_t wrong_if;
152			unsigned long lastuse;
153			unsigned char ttls[MAXVIFS];
154			refcount_t refcount;
155		} res;
156	} mfc_un;
157	struct list_head list;
158	struct rcu_head	rcu;
159	void (*free)(struct rcu_head *head);
160};
161
162static inline void mr_cache_put(struct mr_mfc *c)
163{
164	if (refcount_dec_and_test(&c->mfc_un.res.refcount))
165		call_rcu(&c->rcu, c->free);
166}
167
168static inline void mr_cache_hold(struct mr_mfc *c)
169{
170	refcount_inc(&c->mfc_un.res.refcount);
171}
172
173struct mfc_entry_notifier_info {
174	struct fib_notifier_info info;
175	struct mr_mfc *mfc;
176	u32 tb_id;
177};
178
179static inline int mr_call_mfc_notifier(struct notifier_block *nb,
180				       unsigned short family,
181				       enum fib_event_type event_type,
182				       struct mr_mfc *mfc, u32 tb_id,
183				       struct netlink_ext_ack *extack)
184{
185	struct mfc_entry_notifier_info info = {
186		.info = {
187			.family = family,
188			.extack = extack,
189		},
190		.mfc = mfc,
191		.tb_id = tb_id
192	};
193
194	return call_fib_notifier(nb, event_type, &info.info);
195}
196
197static inline int mr_call_mfc_notifiers(struct net *net,
198					unsigned short family,
199					enum fib_event_type event_type,
200					struct mr_mfc *mfc, u32 tb_id,
201					unsigned int *ipmr_seq)
202{
203	struct mfc_entry_notifier_info info = {
204		.info = {
205			.family = family,
206		},
207		.mfc = mfc,
208		.tb_id = tb_id
209	};
210
211	ASSERT_RTNL();
212	(*ipmr_seq)++;
213	return call_fib_notifiers(net, event_type, &info.info);
214}
215
216struct mr_table;
217
218/**
219 * struct mr_table_ops - callbacks and info for protocol-specific ops
220 * @rht_params: parameters for accessing the MFC hash
221 * @cmparg_any: a hash key to be used for matching on (*,*) routes
222 */
223struct mr_table_ops {
224	const struct rhashtable_params *rht_params;
225	void *cmparg_any;
226};
227
228/**
229 * struct mr_table - a multicast routing table
230 * @list: entry within a list of multicast routing tables
231 * @net: net where this table belongs
232 * @ops: protocol specific operations
233 * @id: identifier of the table
234 * @mroute_sk: socket associated with the table
235 * @ipmr_expire_timer: timer for handling unresolved routes
236 * @mfc_unres_queue: list of unresolved MFC entries
237 * @vif_table: array containing all possible vifs
238 * @mfc_hash: Hash table of all resolved routes for easy lookup
239 * @mfc_cache_list: list of resovled routes for possible traversal
240 * @maxvif: Identifier of highest value vif currently in use
241 * @cache_resolve_queue_len: current size of unresolved queue
242 * @mroute_do_assert: Whether to inform userspace on wrong ingress
243 * @mroute_do_pim: Whether to receive IGMP PIMv1
244 * @mroute_reg_vif_num: PIM-device vif index
245 */
246struct mr_table {
247	struct list_head	list;
248	possible_net_t		net;
249	struct mr_table_ops	ops;
250	u32			id;
251	struct sock __rcu	*mroute_sk;
252	struct timer_list	ipmr_expire_timer;
253	struct list_head	mfc_unres_queue;
254	struct vif_device	vif_table[MAXVIFS];
255	struct rhltable		mfc_hash;
256	struct list_head	mfc_cache_list;
257	int			maxvif;
258	atomic_t		cache_resolve_queue_len;
259	bool			mroute_do_assert;
260	bool			mroute_do_pim;
261	bool			mroute_do_wrvifwhole;
262	int			mroute_reg_vif_num;
263};
264
265static inline bool mr_can_free_table(struct net *net)
266{
267	return !check_net(net) || !net_initialized(net);
268}
269
270#ifdef CONFIG_IP_MROUTE_COMMON
271void vif_device_init(struct vif_device *v,
272		     struct net_device *dev,
273		     unsigned long rate_limit,
274		     unsigned char threshold,
275		     unsigned short flags,
276		     unsigned short get_iflink_mask);
277
278struct mr_table *
279mr_table_alloc(struct net *net, u32 id,
280	       struct mr_table_ops *ops,
281	       void (*expire_func)(struct timer_list *t),
282	       void (*table_set)(struct mr_table *mrt,
283				 struct net *net));
284
285/* These actually return 'struct mr_mfc *', but to avoid need for explicit
286 * castings they simply return void.
287 */
288void *mr_mfc_find_parent(struct mr_table *mrt,
289			 void *hasharg, int parent);
290void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
291void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
292
293int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
294		   struct mr_mfc *c, struct rtmsg *rtm);
295int mr_table_dump(struct mr_table *mrt, struct sk_buff *skb,
296		  struct netlink_callback *cb,
297		  int (*fill)(struct mr_table *mrt, struct sk_buff *skb,
298			      u32 portid, u32 seq, struct mr_mfc *c,
299			      int cmd, int flags),
300		  spinlock_t *lock, struct fib_dump_filter *filter);
301int mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
302		     struct mr_table *(*iter)(struct net *net,
303					      struct mr_table *mrt),
304		     int (*fill)(struct mr_table *mrt,
305				 struct sk_buff *skb,
306				 u32 portid, u32 seq, struct mr_mfc *c,
307				 int cmd, int flags),
308		     spinlock_t *lock, struct fib_dump_filter *filter);
309
310int mr_dump(struct net *net, struct notifier_block *nb, unsigned short family,
311	    int (*rules_dump)(struct net *net,
312			      struct notifier_block *nb,
313			      struct netlink_ext_ack *extack),
314	    struct mr_table *(*mr_iter)(struct net *net,
315					struct mr_table *mrt),
316	    struct netlink_ext_ack *extack);
317#else
318static inline void vif_device_init(struct vif_device *v,
319				   struct net_device *dev,
320				   unsigned long rate_limit,
321				   unsigned char threshold,
322				   unsigned short flags,
323				   unsigned short get_iflink_mask)
324{
325}
326
327static inline void *mr_mfc_find_parent(struct mr_table *mrt,
328				       void *hasharg, int parent)
329{
330	return NULL;
331}
332
333static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
334					   int vifi)
335{
336	return NULL;
337}
338
339static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
340					     int vifi, void *hasharg)
341{
342	return NULL;
343}
344
345static inline int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
346				 struct mr_mfc *c, struct rtmsg *rtm)
347{
348	return -EINVAL;
349}
350
351static inline int
352mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
353		 struct mr_table *(*iter)(struct net *net,
354					  struct mr_table *mrt),
355		 int (*fill)(struct mr_table *mrt,
356			     struct sk_buff *skb,
357			     u32 portid, u32 seq, struct mr_mfc *c,
358			     int cmd, int flags),
359		 spinlock_t *lock, struct fib_dump_filter *filter)
360{
361	return -EINVAL;
362}
363
364static inline int mr_dump(struct net *net, struct notifier_block *nb,
365			  unsigned short family,
366			  int (*rules_dump)(struct net *net,
367					    struct notifier_block *nb,
368					    struct netlink_ext_ack *extack),
369			  struct mr_table *(*mr_iter)(struct net *net,
370						      struct mr_table *mrt),
371			  struct netlink_ext_ack *extack)
372{
373	return -EINVAL;
374}
375#endif
376
377static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
378{
379	return mr_mfc_find_parent(mrt, hasharg, -1);
380}
381
382#ifdef CONFIG_PROC_FS
383struct mr_vif_iter {
384	struct seq_net_private p;
385	struct mr_table *mrt;
386	int ct;
387};
388
389struct mr_mfc_iter {
390	struct seq_net_private p;
391	struct mr_table *mrt;
392	struct list_head *cache;
393
394	/* Lock protecting the mr_table's unresolved queue */
395	spinlock_t *lock;
396};
397
398#ifdef CONFIG_IP_MROUTE_COMMON
399void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
400void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
401
402static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
403{
404	return *pos ? mr_vif_seq_idx(seq_file_net(seq),
405				     seq->private, *pos - 1)
406		    : SEQ_START_TOKEN;
407}
408
409/* These actually return 'struct mr_mfc *', but to avoid need for explicit
410 * castings they simply return void.
411 */
412void *mr_mfc_seq_idx(struct net *net,
413		     struct mr_mfc_iter *it, loff_t pos);
414void *mr_mfc_seq_next(struct seq_file *seq, void *v,
415		      loff_t *pos);
416
417static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
418				     struct mr_table *mrt, spinlock_t *lock)
419{
420	struct mr_mfc_iter *it = seq->private;
421
422	it->mrt = mrt;
423	it->cache = NULL;
424	it->lock = lock;
425
426	return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
427				     seq->private, *pos - 1)
428		    : SEQ_START_TOKEN;
429}
430
431static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
432{
433	struct mr_mfc_iter *it = seq->private;
434	struct mr_table *mrt = it->mrt;
435
436	if (it->cache == &mrt->mfc_unres_queue)
437		spin_unlock_bh(it->lock);
438	else if (it->cache == &mrt->mfc_cache_list)
439		rcu_read_unlock();
440}
441#else
442static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
443				   loff_t pos)
444{
445	return NULL;
446}
447
448static inline void *mr_vif_seq_next(struct seq_file *seq,
449				    void *v, loff_t *pos)
450{
451	return NULL;
452}
453
454static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
455{
456	return NULL;
457}
458
459static inline void *mr_mfc_seq_idx(struct net *net,
460				   struct mr_mfc_iter *it, loff_t pos)
461{
462	return NULL;
463}
464
465static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
466				    loff_t *pos)
467{
468	return NULL;
469}
470
471static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
472				     struct mr_table *mrt, spinlock_t *lock)
473{
474	return NULL;
475}
476
477static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
478{
479}
480#endif
481#endif
482#endif
~/ Read-only file preview.