xref: /linux-6.15/include/linux/mroute_base.h (revision c8d61968)
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 /**
49  * struct mr_mfc - common multicast routing entries
50  * @mnode: rhashtable list
51  * @mfc_parent: source interface (iif)
52  * @mfc_flags: entry flags
53  * @expires: unresolved entry expire time
54  * @unresolved: unresolved cached skbs
55  * @last_assert: time of last assert
56  * @minvif: minimum VIF id
57  * @maxvif: maximum VIF id
58  * @bytes: bytes that have passed for this entry
59  * @pkt: packets that have passed for this entry
60  * @wrong_if: number of wrong source interface hits
61  * @lastuse: time of last use of the group (traffic or update)
62  * @ttls: OIF TTL threshold array
63  * @refcount: reference count for this entry
64  * @list: global entry list
65  * @rcu: used for entry destruction
66  */
67 struct mr_mfc {
68 	struct rhlist_head mnode;
69 	unsigned short mfc_parent;
70 	int mfc_flags;
71 
72 	union {
73 		struct {
74 			unsigned long expires;
75 			struct sk_buff_head unresolved;
76 		} unres;
77 		struct {
78 			unsigned long last_assert;
79 			int minvif;
80 			int maxvif;
81 			unsigned long bytes;
82 			unsigned long pkt;
83 			unsigned long wrong_if;
84 			unsigned long lastuse;
85 			unsigned char ttls[MAXVIFS];
86 			refcount_t refcount;
87 		} res;
88 	} mfc_un;
89 	struct list_head list;
90 	struct rcu_head	rcu;
91 };
92 
93 struct mr_table;
94 
95 /**
96  * struct mr_table_ops - callbacks and info for protocol-specific ops
97  * @rht_params: parameters for accessing the MFC hash
98  * @cmparg_any: a hash key to be used for matching on (*,*) routes
99  */
100 struct mr_table_ops {
101 	const struct rhashtable_params *rht_params;
102 	void *cmparg_any;
103 };
104 
105 /**
106  * struct mr_table - a multicast routing table
107  * @list: entry within a list of multicast routing tables
108  * @net: net where this table belongs
109  * @ops: protocol specific operations
110  * @id: identifier of the table
111  * @mroute_sk: socket associated with the table
112  * @ipmr_expire_timer: timer for handling unresolved routes
113  * @mfc_unres_queue: list of unresolved MFC entries
114  * @vif_table: array containing all possible vifs
115  * @mfc_hash: Hash table of all resolved routes for easy lookup
116  * @mfc_cache_list: list of resovled routes for possible traversal
117  * @maxvif: Identifier of highest value vif currently in use
118  * @cache_resolve_queue_len: current size of unresolved queue
119  * @mroute_do_assert: Whether to inform userspace on wrong ingress
120  * @mroute_do_pim: Whether to receive IGMP PIMv1
121  * @mroute_reg_vif_num: PIM-device vif index
122  */
123 struct mr_table {
124 	struct list_head	list;
125 	possible_net_t		net;
126 	struct mr_table_ops	ops;
127 	u32			id;
128 	struct sock __rcu	*mroute_sk;
129 	struct timer_list	ipmr_expire_timer;
130 	struct list_head	mfc_unres_queue;
131 	struct vif_device	vif_table[MAXVIFS];
132 	struct rhltable		mfc_hash;
133 	struct list_head	mfc_cache_list;
134 	int			maxvif;
135 	atomic_t		cache_resolve_queue_len;
136 	bool			mroute_do_assert;
137 	bool			mroute_do_pim;
138 	int			mroute_reg_vif_num;
139 };
140 
141 #ifdef CONFIG_IP_MROUTE_COMMON
142 void vif_device_init(struct vif_device *v,
143 		     struct net_device *dev,
144 		     unsigned long rate_limit,
145 		     unsigned char threshold,
146 		     unsigned short flags,
147 		     unsigned short get_iflink_mask);
148 
149 struct mr_table *
150 mr_table_alloc(struct net *net, u32 id,
151 	       struct mr_table_ops *ops,
152 	       void (*expire_func)(struct timer_list *t),
153 	       void (*table_set)(struct mr_table *mrt,
154 				 struct net *net));
155 
156 /* These actually return 'struct mr_mfc *', but to avoid need for explicit
157  * castings they simply return void.
158  */
159 void *mr_mfc_find_parent(struct mr_table *mrt,
160 			 void *hasharg, int parent);
161 void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
162 void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
163 
164 #else
165 static inline void vif_device_init(struct vif_device *v,
166 				   struct net_device *dev,
167 				   unsigned long rate_limit,
168 				   unsigned char threshold,
169 				   unsigned short flags,
170 				   unsigned short get_iflink_mask)
171 {
172 }
173 
174 static inline void *
175 mr_table_alloc(struct net *net, u32 id,
176 	       struct mr_table_ops *ops,
177 	       void (*expire_func)(struct timer_list *t),
178 	       void (*table_set)(struct mr_table *mrt,
179 				 struct net *net))
180 {
181 	return NULL;
182 }
183 
184 static inline void *mr_mfc_find_parent(struct mr_table *mrt,
185 				       void *hasharg, int parent)
186 {
187 	return NULL;
188 }
189 
190 static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
191 					   int vifi)
192 {
193 	return NULL;
194 }
195 
196 static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
197 					     int vifi, void *hasharg)
198 {
199 	return NULL;
200 }
201 #endif
202 
203 static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
204 {
205 	return mr_mfc_find_parent(mrt, hasharg, -1);
206 }
207 
208 #ifdef CONFIG_PROC_FS
209 struct mr_mfc_iter {
210 	struct seq_net_private p;
211 	struct mr_table *mrt;
212 	struct list_head *cache;
213 
214 	/* Lock protecting the mr_table's unresolved queue */
215 	spinlock_t *lock;
216 };
217 
218 #ifdef CONFIG_IP_MROUTE_COMMON
219 /* These actually return 'struct mr_mfc *', but to avoid need for explicit
220  * castings they simply return void.
221  */
222 void *mr_mfc_seq_idx(struct net *net,
223 		     struct mr_mfc_iter *it, loff_t pos);
224 void *mr_mfc_seq_next(struct seq_file *seq, void *v,
225 		      loff_t *pos);
226 
227 static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
228 				     struct mr_table *mrt, spinlock_t *lock)
229 {
230 	struct mr_mfc_iter *it = seq->private;
231 
232 	it->mrt = mrt;
233 	it->cache = NULL;
234 	it->lock = lock;
235 
236 	return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
237 				     seq->private, *pos - 1)
238 		    : SEQ_START_TOKEN;
239 }
240 
241 static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
242 {
243 	struct mr_mfc_iter *it = seq->private;
244 	struct mr_table *mrt = it->mrt;
245 
246 	if (it->cache == &mrt->mfc_unres_queue)
247 		spin_unlock_bh(it->lock);
248 	else if (it->cache == &mrt->mfc_cache_list)
249 		rcu_read_unlock();
250 }
251 #else
252 static inline void *mr_mfc_seq_idx(struct net *net,
253 				   struct mr_mfc_iter *it, loff_t pos)
254 {
255 	return NULL;
256 }
257 
258 static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
259 				    loff_t *pos)
260 {
261 	return NULL;
262 }
263 
264 static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
265 				     struct mr_table *mrt, spinlock_t *lock)
266 {
267 	return NULL;
268 }
269 
270 static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
271 {
272 }
273 #endif
274 #endif
275 #endif
276