blob: a007c5ad0fde56033430c52ca7827dbbfe9ca98d [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
48/**
Yuval Mintz494fff52018-02-28 23:29:34 +020049 * 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 */
67struct 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
Yuval Mintz845c9a72018-02-28 23:29:35 +020093struct 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 */
100struct mr_table_ops {
101 const struct rhashtable_params *rht_params;
102 void *cmparg_any;
103};
104
Yuval Mintz494fff52018-02-28 23:29:34 +0200105/**
Yuval Mintzb70432f2018-02-28 23:29:32 +0200106 * struct mr_table - a multicast routing table
107 * @list: entry within a list of multicast routing tables
108 * @net: net where this table belongs
Yuval Mintz845c9a72018-02-28 23:29:35 +0200109 * @ops: protocol specific operations
Yuval Mintzb70432f2018-02-28 23:29:32 +0200110 * @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 */
123struct mr_table {
124 struct list_head list;
125 possible_net_t net;
Yuval Mintz845c9a72018-02-28 23:29:35 +0200126 struct mr_table_ops ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200127 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
Yuval Mintz6853f212018-02-28 23:29:29 +0200141#ifdef CONFIG_IP_MROUTE_COMMON
142void 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);
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200148
149struct mr_table *
150mr_table_alloc(struct net *net, u32 id,
Yuval Mintz845c9a72018-02-28 23:29:35 +0200151 struct mr_table_ops *ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200152 void (*expire_func)(struct timer_list *t),
153 void (*table_set)(struct mr_table *mrt,
154 struct net *net));
Yuval Mintz845c9a72018-02-28 23:29:35 +0200155
156/* These actually return 'struct mr_mfc *', but to avoid need for explicit
157 * castings they simply return void.
158 */
159void *mr_mfc_find_parent(struct mr_table *mrt,
160 void *hasharg, int parent);
161void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
162void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
163
Yuval Mintz6853f212018-02-28 23:29:29 +0200164#else
165static 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}
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200173
Yuval Mintz845c9a72018-02-28 23:29:35 +0200174static inline void *
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200175mr_table_alloc(struct net *net, u32 id,
Yuval Mintz845c9a72018-02-28 23:29:35 +0200176 struct mr_table_ops *ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200177 void (*expire_func)(struct timer_list *t),
178 void (*table_set)(struct mr_table *mrt,
179 struct net *net))
180{
181 return NULL;
182}
Yuval Mintz845c9a72018-02-28 23:29:35 +0200183
184static inline void *mr_mfc_find_parent(struct mr_table *mrt,
185 void *hasharg, int parent)
186{
187 return NULL;
188}
189
190static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
191 int vifi)
192{
193 return NULL;
194}
195
196static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
197 int vifi, void *hasharg)
198{
199 return NULL;
200}
Yuval Mintz6853f212018-02-28 23:29:29 +0200201#endif
Yuval Mintz845c9a72018-02-28 23:29:35 +0200202
203static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
204{
205 return mr_mfc_find_parent(mrt, hasharg, -1);
206}
Yuval Mintzc8d61962018-02-28 23:29:36 +0200207
208#ifdef CONFIG_PROC_FS
209struct 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 */
222void *mr_mfc_seq_idx(struct net *net,
223 struct mr_mfc_iter *it, loff_t pos);
224void *mr_mfc_seq_next(struct seq_file *seq, void *v,
225 loff_t *pos);
226
227static 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
241static 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
252static inline void *mr_mfc_seq_idx(struct net *net,
253 struct mr_mfc_iter *it, loff_t pos)
254{
255 return NULL;
256}
257
258static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
259 loff_t *pos)
260{
261 return NULL;
262}
263
264static 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
270static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
271{
272}
273#endif
274#endif
Yuval Mintz6853f212018-02-28 23:29:29 +0200275#endif