xref: /linux/include/linux/mroute_base.h (revision 889cd83cbe411dda854429f3223ab2d31a860a4a)
16853f21fSYuval Mintz #ifndef __LINUX_MROUTE_BASE_H
26853f21fSYuval Mintz #define __LINUX_MROUTE_BASE_H
36853f21fSYuval Mintz 
46853f21fSYuval Mintz #include <linux/netdevice.h>
5b70432f7SYuval Mintz #include <linux/rhashtable.h>
6c8d61968SYuval Mintz #include <linux/spinlock.h>
7b70432f7SYuval Mintz #include <net/net_namespace.h>
8b70432f7SYuval Mintz #include <net/sock.h>
96853f21fSYuval Mintz 
106853f21fSYuval Mintz /**
116853f21fSYuval Mintz  * struct vif_device - interface representor for multicast routing
126853f21fSYuval Mintz  * @dev: network device being used
136853f21fSYuval Mintz  * @bytes_in: statistic; bytes ingressing
146853f21fSYuval Mintz  * @bytes_out: statistic; bytes egresing
156853f21fSYuval Mintz  * @pkt_in: statistic; packets ingressing
166853f21fSYuval Mintz  * @pkt_out: statistic; packets egressing
176853f21fSYuval Mintz  * @rate_limit: Traffic shaping (NI)
186853f21fSYuval Mintz  * @threshold: TTL threshold
196853f21fSYuval Mintz  * @flags: Control flags
206853f21fSYuval Mintz  * @link: Physical interface index
216853f21fSYuval Mintz  * @dev_parent_id: device parent id
226853f21fSYuval Mintz  * @local: Local address
236853f21fSYuval Mintz  * @remote: Remote address for tunnels
246853f21fSYuval Mintz  */
256853f21fSYuval Mintz struct vif_device {
266853f21fSYuval Mintz 	struct net_device *dev;
276853f21fSYuval Mintz 	unsigned long bytes_in, bytes_out;
286853f21fSYuval Mintz 	unsigned long pkt_in, pkt_out;
296853f21fSYuval Mintz 	unsigned long rate_limit;
306853f21fSYuval Mintz 	unsigned char threshold;
316853f21fSYuval Mintz 	unsigned short flags;
326853f21fSYuval Mintz 	int link;
336853f21fSYuval Mintz 
346853f21fSYuval Mintz 	/* Currently only used by ipmr */
356853f21fSYuval Mintz 	struct netdev_phys_item_id dev_parent_id;
366853f21fSYuval Mintz 	__be32 local, remote;
376853f21fSYuval Mintz };
386853f21fSYuval Mintz 
39b70432f7SYuval Mintz #ifndef MAXVIFS
40b70432f7SYuval Mintz /* This one is nasty; value is defined in uapi using different symbols for
41b70432f7SYuval Mintz  * mroute and morute6 but both map into same 32.
42b70432f7SYuval Mintz  */
43b70432f7SYuval Mintz #define MAXVIFS	32
44b70432f7SYuval Mintz #endif
45b70432f7SYuval Mintz 
46b70432f7SYuval Mintz #define VIF_EXISTS(_mrt, _idx) (!!((_mrt)->vif_table[_idx].dev))
47b70432f7SYuval Mintz 
48*889cd83cSYuval Mintz /* mfc_flags:
49*889cd83cSYuval Mintz  * MFC_STATIC - the entry was added statically (not by a routing daemon)
50*889cd83cSYuval Mintz  * MFC_OFFLOAD - the entry was offloaded to the hardware
51*889cd83cSYuval Mintz  */
52*889cd83cSYuval Mintz enum {
53*889cd83cSYuval Mintz 	MFC_STATIC = BIT(0),
54*889cd83cSYuval Mintz 	MFC_OFFLOAD = BIT(1),
55*889cd83cSYuval Mintz };
56*889cd83cSYuval Mintz 
57b70432f7SYuval Mintz /**
58494fff56SYuval Mintz  * struct mr_mfc - common multicast routing entries
59494fff56SYuval Mintz  * @mnode: rhashtable list
60494fff56SYuval Mintz  * @mfc_parent: source interface (iif)
61494fff56SYuval Mintz  * @mfc_flags: entry flags
62494fff56SYuval Mintz  * @expires: unresolved entry expire time
63494fff56SYuval Mintz  * @unresolved: unresolved cached skbs
64494fff56SYuval Mintz  * @last_assert: time of last assert
65494fff56SYuval Mintz  * @minvif: minimum VIF id
66494fff56SYuval Mintz  * @maxvif: maximum VIF id
67494fff56SYuval Mintz  * @bytes: bytes that have passed for this entry
68494fff56SYuval Mintz  * @pkt: packets that have passed for this entry
69494fff56SYuval Mintz  * @wrong_if: number of wrong source interface hits
70494fff56SYuval Mintz  * @lastuse: time of last use of the group (traffic or update)
71494fff56SYuval Mintz  * @ttls: OIF TTL threshold array
72494fff56SYuval Mintz  * @refcount: reference count for this entry
73494fff56SYuval Mintz  * @list: global entry list
74494fff56SYuval Mintz  * @rcu: used for entry destruction
75494fff56SYuval Mintz  */
76494fff56SYuval Mintz struct mr_mfc {
77494fff56SYuval Mintz 	struct rhlist_head mnode;
78494fff56SYuval Mintz 	unsigned short mfc_parent;
79494fff56SYuval Mintz 	int mfc_flags;
80494fff56SYuval Mintz 
81494fff56SYuval Mintz 	union {
82494fff56SYuval Mintz 		struct {
83494fff56SYuval Mintz 			unsigned long expires;
84494fff56SYuval Mintz 			struct sk_buff_head unresolved;
85494fff56SYuval Mintz 		} unres;
86494fff56SYuval Mintz 		struct {
87494fff56SYuval Mintz 			unsigned long last_assert;
88494fff56SYuval Mintz 			int minvif;
89494fff56SYuval Mintz 			int maxvif;
90494fff56SYuval Mintz 			unsigned long bytes;
91494fff56SYuval Mintz 			unsigned long pkt;
92494fff56SYuval Mintz 			unsigned long wrong_if;
93494fff56SYuval Mintz 			unsigned long lastuse;
94494fff56SYuval Mintz 			unsigned char ttls[MAXVIFS];
95494fff56SYuval Mintz 			refcount_t refcount;
96494fff56SYuval Mintz 		} res;
97494fff56SYuval Mintz 	} mfc_un;
98494fff56SYuval Mintz 	struct list_head list;
99494fff56SYuval Mintz 	struct rcu_head	rcu;
100494fff56SYuval Mintz };
101494fff56SYuval Mintz 
102845c9a7aSYuval Mintz struct mr_table;
103845c9a7aSYuval Mintz 
104845c9a7aSYuval Mintz /**
105845c9a7aSYuval Mintz  * struct mr_table_ops - callbacks and info for protocol-specific ops
106845c9a7aSYuval Mintz  * @rht_params: parameters for accessing the MFC hash
107845c9a7aSYuval Mintz  * @cmparg_any: a hash key to be used for matching on (*,*) routes
108845c9a7aSYuval Mintz  */
109845c9a7aSYuval Mintz struct mr_table_ops {
110845c9a7aSYuval Mintz 	const struct rhashtable_params *rht_params;
111845c9a7aSYuval Mintz 	void *cmparg_any;
112845c9a7aSYuval Mintz };
113845c9a7aSYuval Mintz 
114494fff56SYuval Mintz /**
115b70432f7SYuval Mintz  * struct mr_table - a multicast routing table
116b70432f7SYuval Mintz  * @list: entry within a list of multicast routing tables
117b70432f7SYuval Mintz  * @net: net where this table belongs
118845c9a7aSYuval Mintz  * @ops: protocol specific operations
119b70432f7SYuval Mintz  * @id: identifier of the table
120b70432f7SYuval Mintz  * @mroute_sk: socket associated with the table
121b70432f7SYuval Mintz  * @ipmr_expire_timer: timer for handling unresolved routes
122b70432f7SYuval Mintz  * @mfc_unres_queue: list of unresolved MFC entries
123b70432f7SYuval Mintz  * @vif_table: array containing all possible vifs
124b70432f7SYuval Mintz  * @mfc_hash: Hash table of all resolved routes for easy lookup
125b70432f7SYuval Mintz  * @mfc_cache_list: list of resovled routes for possible traversal
126b70432f7SYuval Mintz  * @maxvif: Identifier of highest value vif currently in use
127b70432f7SYuval Mintz  * @cache_resolve_queue_len: current size of unresolved queue
128b70432f7SYuval Mintz  * @mroute_do_assert: Whether to inform userspace on wrong ingress
129b70432f7SYuval Mintz  * @mroute_do_pim: Whether to receive IGMP PIMv1
130b70432f7SYuval Mintz  * @mroute_reg_vif_num: PIM-device vif index
131b70432f7SYuval Mintz  */
132b70432f7SYuval Mintz struct mr_table {
133b70432f7SYuval Mintz 	struct list_head	list;
134b70432f7SYuval Mintz 	possible_net_t		net;
135845c9a7aSYuval Mintz 	struct mr_table_ops	ops;
136b70432f7SYuval Mintz 	u32			id;
137b70432f7SYuval Mintz 	struct sock __rcu	*mroute_sk;
138b70432f7SYuval Mintz 	struct timer_list	ipmr_expire_timer;
139b70432f7SYuval Mintz 	struct list_head	mfc_unres_queue;
140b70432f7SYuval Mintz 	struct vif_device	vif_table[MAXVIFS];
141b70432f7SYuval Mintz 	struct rhltable		mfc_hash;
142b70432f7SYuval Mintz 	struct list_head	mfc_cache_list;
143b70432f7SYuval Mintz 	int			maxvif;
144b70432f7SYuval Mintz 	atomic_t		cache_resolve_queue_len;
145b70432f7SYuval Mintz 	bool			mroute_do_assert;
146b70432f7SYuval Mintz 	bool			mroute_do_pim;
147b70432f7SYuval Mintz 	int			mroute_reg_vif_num;
148b70432f7SYuval Mintz };
149b70432f7SYuval Mintz 
1506853f21fSYuval Mintz #ifdef CONFIG_IP_MROUTE_COMMON
1516853f21fSYuval Mintz void vif_device_init(struct vif_device *v,
1526853f21fSYuval Mintz 		     struct net_device *dev,
1536853f21fSYuval Mintz 		     unsigned long rate_limit,
1546853f21fSYuval Mintz 		     unsigned char threshold,
1556853f21fSYuval Mintz 		     unsigned short flags,
1566853f21fSYuval Mintz 		     unsigned short get_iflink_mask);
1570bbbf0e7SYuval Mintz 
1580bbbf0e7SYuval Mintz struct mr_table *
1590bbbf0e7SYuval Mintz mr_table_alloc(struct net *net, u32 id,
160845c9a7aSYuval Mintz 	       struct mr_table_ops *ops,
1610bbbf0e7SYuval Mintz 	       void (*expire_func)(struct timer_list *t),
1620bbbf0e7SYuval Mintz 	       void (*table_set)(struct mr_table *mrt,
1630bbbf0e7SYuval Mintz 				 struct net *net));
164845c9a7aSYuval Mintz 
165845c9a7aSYuval Mintz /* These actually return 'struct mr_mfc *', but to avoid need for explicit
166845c9a7aSYuval Mintz  * castings they simply return void.
167845c9a7aSYuval Mintz  */
168845c9a7aSYuval Mintz void *mr_mfc_find_parent(struct mr_table *mrt,
169845c9a7aSYuval Mintz 			 void *hasharg, int parent);
170845c9a7aSYuval Mintz void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
171845c9a7aSYuval Mintz void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
172845c9a7aSYuval Mintz 
1736853f21fSYuval Mintz #else
1746853f21fSYuval Mintz static inline void vif_device_init(struct vif_device *v,
1756853f21fSYuval Mintz 				   struct net_device *dev,
1766853f21fSYuval Mintz 				   unsigned long rate_limit,
1776853f21fSYuval Mintz 				   unsigned char threshold,
1786853f21fSYuval Mintz 				   unsigned short flags,
1796853f21fSYuval Mintz 				   unsigned short get_iflink_mask)
1806853f21fSYuval Mintz {
1816853f21fSYuval Mintz }
1820bbbf0e7SYuval Mintz 
183845c9a7aSYuval Mintz static inline void *
1840bbbf0e7SYuval Mintz mr_table_alloc(struct net *net, u32 id,
185845c9a7aSYuval Mintz 	       struct mr_table_ops *ops,
1860bbbf0e7SYuval Mintz 	       void (*expire_func)(struct timer_list *t),
1870bbbf0e7SYuval Mintz 	       void (*table_set)(struct mr_table *mrt,
1880bbbf0e7SYuval Mintz 				 struct net *net))
1890bbbf0e7SYuval Mintz {
1900bbbf0e7SYuval Mintz 	return NULL;
1910bbbf0e7SYuval Mintz }
192845c9a7aSYuval Mintz 
193845c9a7aSYuval Mintz static inline void *mr_mfc_find_parent(struct mr_table *mrt,
194845c9a7aSYuval Mintz 				       void *hasharg, int parent)
195845c9a7aSYuval Mintz {
196845c9a7aSYuval Mintz 	return NULL;
197845c9a7aSYuval Mintz }
198845c9a7aSYuval Mintz 
199845c9a7aSYuval Mintz static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
200845c9a7aSYuval Mintz 					   int vifi)
201845c9a7aSYuval Mintz {
202845c9a7aSYuval Mintz 	return NULL;
203845c9a7aSYuval Mintz }
204845c9a7aSYuval Mintz 
205845c9a7aSYuval Mintz static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
206845c9a7aSYuval Mintz 					     int vifi, void *hasharg)
207845c9a7aSYuval Mintz {
208845c9a7aSYuval Mintz 	return NULL;
209845c9a7aSYuval Mintz }
2106853f21fSYuval Mintz #endif
211845c9a7aSYuval Mintz 
212845c9a7aSYuval Mintz static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
213845c9a7aSYuval Mintz {
214845c9a7aSYuval Mintz 	return mr_mfc_find_parent(mrt, hasharg, -1);
215845c9a7aSYuval Mintz }
216c8d61968SYuval Mintz 
217c8d61968SYuval Mintz #ifdef CONFIG_PROC_FS
2183feda6b4SYuval Mintz struct mr_vif_iter {
2193feda6b4SYuval Mintz 	struct seq_net_private p;
2203feda6b4SYuval Mintz 	struct mr_table *mrt;
2213feda6b4SYuval Mintz 	int ct;
2223feda6b4SYuval Mintz };
2233feda6b4SYuval Mintz 
224c8d61968SYuval Mintz struct mr_mfc_iter {
225c8d61968SYuval Mintz 	struct seq_net_private p;
226c8d61968SYuval Mintz 	struct mr_table *mrt;
227c8d61968SYuval Mintz 	struct list_head *cache;
228c8d61968SYuval Mintz 
229c8d61968SYuval Mintz 	/* Lock protecting the mr_table's unresolved queue */
230c8d61968SYuval Mintz 	spinlock_t *lock;
231c8d61968SYuval Mintz };
232c8d61968SYuval Mintz 
233c8d61968SYuval Mintz #ifdef CONFIG_IP_MROUTE_COMMON
2343feda6b4SYuval Mintz void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
2353feda6b4SYuval Mintz void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
2363feda6b4SYuval Mintz 
2373feda6b4SYuval Mintz static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
2383feda6b4SYuval Mintz {
2393feda6b4SYuval Mintz 	return *pos ? mr_vif_seq_idx(seq_file_net(seq),
2403feda6b4SYuval Mintz 				     seq->private, *pos - 1)
2413feda6b4SYuval Mintz 		    : SEQ_START_TOKEN;
2423feda6b4SYuval Mintz }
2433feda6b4SYuval Mintz 
244c8d61968SYuval Mintz /* These actually return 'struct mr_mfc *', but to avoid need for explicit
245c8d61968SYuval Mintz  * castings they simply return void.
246c8d61968SYuval Mintz  */
247c8d61968SYuval Mintz void *mr_mfc_seq_idx(struct net *net,
248c8d61968SYuval Mintz 		     struct mr_mfc_iter *it, loff_t pos);
249c8d61968SYuval Mintz void *mr_mfc_seq_next(struct seq_file *seq, void *v,
250c8d61968SYuval Mintz 		      loff_t *pos);
251c8d61968SYuval Mintz 
252c8d61968SYuval Mintz static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
253c8d61968SYuval Mintz 				     struct mr_table *mrt, spinlock_t *lock)
254c8d61968SYuval Mintz {
255c8d61968SYuval Mintz 	struct mr_mfc_iter *it = seq->private;
256c8d61968SYuval Mintz 
257c8d61968SYuval Mintz 	it->mrt = mrt;
258c8d61968SYuval Mintz 	it->cache = NULL;
259c8d61968SYuval Mintz 	it->lock = lock;
260c8d61968SYuval Mintz 
261c8d61968SYuval Mintz 	return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
262c8d61968SYuval Mintz 				     seq->private, *pos - 1)
263c8d61968SYuval Mintz 		    : SEQ_START_TOKEN;
264c8d61968SYuval Mintz }
265c8d61968SYuval Mintz 
266c8d61968SYuval Mintz static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
267c8d61968SYuval Mintz {
268c8d61968SYuval Mintz 	struct mr_mfc_iter *it = seq->private;
269c8d61968SYuval Mintz 	struct mr_table *mrt = it->mrt;
270c8d61968SYuval Mintz 
271c8d61968SYuval Mintz 	if (it->cache == &mrt->mfc_unres_queue)
272c8d61968SYuval Mintz 		spin_unlock_bh(it->lock);
273c8d61968SYuval Mintz 	else if (it->cache == &mrt->mfc_cache_list)
274c8d61968SYuval Mintz 		rcu_read_unlock();
275c8d61968SYuval Mintz }
276c8d61968SYuval Mintz #else
2773feda6b4SYuval Mintz static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
2783feda6b4SYuval Mintz 				   loff_t pos)
2793feda6b4SYuval Mintz {
2803feda6b4SYuval Mintz 	return NULL;
2813feda6b4SYuval Mintz }
2823feda6b4SYuval Mintz 
2833feda6b4SYuval Mintz static inline void *mr_vif_seq_next(struct seq_file *seq,
2843feda6b4SYuval Mintz 				    void *v, loff_t *pos)
2853feda6b4SYuval Mintz {
2863feda6b4SYuval Mintz 	return NULL;
2873feda6b4SYuval Mintz }
2883feda6b4SYuval Mintz 
2893feda6b4SYuval Mintz static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
2903feda6b4SYuval Mintz {
2913feda6b4SYuval Mintz 	return NULL;
2923feda6b4SYuval Mintz }
2933feda6b4SYuval Mintz 
294c8d61968SYuval Mintz static inline void *mr_mfc_seq_idx(struct net *net,
295c8d61968SYuval Mintz 				   struct mr_mfc_iter *it, loff_t pos)
296c8d61968SYuval Mintz {
297c8d61968SYuval Mintz 	return NULL;
298c8d61968SYuval Mintz }
299c8d61968SYuval Mintz 
300c8d61968SYuval Mintz static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
301c8d61968SYuval Mintz 				    loff_t *pos)
302c8d61968SYuval Mintz {
303c8d61968SYuval Mintz 	return NULL;
304c8d61968SYuval Mintz }
305c8d61968SYuval Mintz 
306c8d61968SYuval Mintz static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
307c8d61968SYuval Mintz 				     struct mr_table *mrt, spinlock_t *lock)
308c8d61968SYuval Mintz {
309c8d61968SYuval Mintz 	return NULL;
310c8d61968SYuval Mintz }
311c8d61968SYuval Mintz 
312c8d61968SYuval Mintz static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
313c8d61968SYuval Mintz {
314c8d61968SYuval Mintz }
315c8d61968SYuval Mintz #endif
316c8d61968SYuval Mintz #endif
3176853f21fSYuval Mintz #endif
318