xref: /linux-6.15/include/linux/mroute_base.h (revision 889cd83c)
1 #ifndef __LINUX_MROUTE_BASE_H
2 #define __LINUX_MROUTE_BASE_H
3 
4 #include <linux/netdevice.h>
5 #include <linux/rhashtable.h>
6 #include <linux/spinlock.h>
7 #include <net/net_namespace.h>
8 #include <net/sock.h>
9 
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  */
25 struct 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 
39 #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 
48 /* 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  */
52 enum {
53 	MFC_STATIC = BIT(0),
54 	MFC_OFFLOAD = BIT(1),
55 };
56 
57 /**
58  * 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  */
76 struct 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 
102 struct 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  */
109 struct mr_table_ops {
110 	const struct rhashtable_params *rht_params;
111 	void *cmparg_any;
112 };
113 
114 /**
115  * struct mr_table - a multicast routing table
116  * @list: entry within a list of multicast routing tables
117  * @net: net where this table belongs
118  * @ops: protocol specific operations
119  * @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  */
132 struct mr_table {
133 	struct list_head	list;
134 	possible_net_t		net;
135 	struct mr_table_ops	ops;
136 	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 
150 #ifdef CONFIG_IP_MROUTE_COMMON
151 void 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);
157 
158 struct mr_table *
159 mr_table_alloc(struct net *net, u32 id,
160 	       struct mr_table_ops *ops,
161 	       void (*expire_func)(struct timer_list *t),
162 	       void (*table_set)(struct mr_table *mrt,
163 				 struct net *net));
164 
165 /* These actually return 'struct mr_mfc *', but to avoid need for explicit
166  * castings they simply return void.
167  */
168 void *mr_mfc_find_parent(struct mr_table *mrt,
169 			 void *hasharg, int parent);
170 void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
171 void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
172 
173 #else
174 static 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 }
182 
183 static inline void *
184 mr_table_alloc(struct net *net, u32 id,
185 	       struct mr_table_ops *ops,
186 	       void (*expire_func)(struct timer_list *t),
187 	       void (*table_set)(struct mr_table *mrt,
188 				 struct net *net))
189 {
190 	return NULL;
191 }
192 
193 static inline void *mr_mfc_find_parent(struct mr_table *mrt,
194 				       void *hasharg, int parent)
195 {
196 	return NULL;
197 }
198 
199 static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
200 					   int vifi)
201 {
202 	return NULL;
203 }
204 
205 static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
206 					     int vifi, void *hasharg)
207 {
208 	return NULL;
209 }
210 #endif
211 
212 static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
213 {
214 	return mr_mfc_find_parent(mrt, hasharg, -1);
215 }
216 
217 #ifdef CONFIG_PROC_FS
218 struct mr_vif_iter {
219 	struct seq_net_private p;
220 	struct mr_table *mrt;
221 	int ct;
222 };
223 
224 struct 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
234 void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
235 void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
236 
237 static 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 
244 /* These actually return 'struct mr_mfc *', but to avoid need for explicit
245  * castings they simply return void.
246  */
247 void *mr_mfc_seq_idx(struct net *net,
248 		     struct mr_mfc_iter *it, loff_t pos);
249 void *mr_mfc_seq_next(struct seq_file *seq, void *v,
250 		      loff_t *pos);
251 
252 static 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 
266 static 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
277 static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
278 				   loff_t pos)
279 {
280 	return NULL;
281 }
282 
283 static inline void *mr_vif_seq_next(struct seq_file *seq,
284 				    void *v, loff_t *pos)
285 {
286 	return NULL;
287 }
288 
289 static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
290 {
291 	return NULL;
292 }
293 
294 static inline void *mr_mfc_seq_idx(struct net *net,
295 				   struct mr_mfc_iter *it, loff_t pos)
296 {
297 	return NULL;
298 }
299 
300 static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
301 				    loff_t *pos)
302 {
303 	return NULL;
304 }
305 
306 static 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 
312 static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
313 {
314 }
315 #endif
316 #endif
317 #endif
318