16853f21fSYuval Mintz #ifndef __LINUX_MROUTE_BASE_H
26853f21fSYuval Mintz #define __LINUX_MROUTE_BASE_H
36853f21fSYuval Mintz
46853f21fSYuval Mintz #include <linux/netdevice.h>
50eb71a9dSNeilBrown #include <linux/rhashtable-types.h>
6c8d61968SYuval Mintz #include <linux/spinlock.h>
7b70432f7SYuval Mintz #include <net/net_namespace.h>
8b70432f7SYuval Mintz #include <net/sock.h>
9bc67a0daSYuval Mintz #include <net/fib_notifier.h>
10cb167893SDavid Ahern #include <net/ip_fib.h>
116853f21fSYuval Mintz
126853f21fSYuval Mintz /**
136853f21fSYuval Mintz * struct vif_device - interface representor for multicast routing
146853f21fSYuval Mintz * @dev: network device being used
1542120a86SEric Dumazet * @dev_tracker: refcount tracker for @dev reference
166853f21fSYuval Mintz * @bytes_in: statistic; bytes ingressing
176853f21fSYuval Mintz * @bytes_out: statistic; bytes egresing
186853f21fSYuval Mintz * @pkt_in: statistic; packets ingressing
196853f21fSYuval Mintz * @pkt_out: statistic; packets egressing
206853f21fSYuval Mintz * @rate_limit: Traffic shaping (NI)
216853f21fSYuval Mintz * @threshold: TTL threshold
226853f21fSYuval Mintz * @flags: Control flags
236853f21fSYuval Mintz * @link: Physical interface index
246853f21fSYuval Mintz * @dev_parent_id: device parent id
256853f21fSYuval Mintz * @local: Local address
266853f21fSYuval Mintz * @remote: Remote address for tunnels
276853f21fSYuval Mintz */
286853f21fSYuval Mintz struct vif_device {
29ebc31979SEric Dumazet struct net_device __rcu *dev;
3042120a86SEric Dumazet netdevice_tracker dev_tracker;
316853f21fSYuval Mintz unsigned long bytes_in, bytes_out;
326853f21fSYuval Mintz unsigned long pkt_in, pkt_out;
336853f21fSYuval Mintz unsigned long rate_limit;
346853f21fSYuval Mintz unsigned char threshold;
356853f21fSYuval Mintz unsigned short flags;
366853f21fSYuval Mintz int link;
376853f21fSYuval Mintz
386853f21fSYuval Mintz /* Currently only used by ipmr */
396853f21fSYuval Mintz struct netdev_phys_item_id dev_parent_id;
406853f21fSYuval Mintz __be32 local, remote;
416853f21fSYuval Mintz };
426853f21fSYuval Mintz
43bc67a0daSYuval Mintz struct vif_entry_notifier_info {
44bc67a0daSYuval Mintz struct fib_notifier_info info;
45bc67a0daSYuval Mintz struct net_device *dev;
46bc67a0daSYuval Mintz unsigned short vif_index;
47bc67a0daSYuval Mintz unsigned short vif_flags;
48bc67a0daSYuval Mintz u32 tb_id;
49bc67a0daSYuval Mintz };
50bc67a0daSYuval Mintz
mr_call_vif_notifier(struct notifier_block * nb,unsigned short family,enum fib_event_type event_type,struct vif_device * vif,struct net_device * vif_dev,unsigned short vif_index,u32 tb_id,struct netlink_ext_ack * extack)51bc67a0daSYuval Mintz static inline int mr_call_vif_notifier(struct notifier_block *nb,
52bc67a0daSYuval Mintz unsigned short family,
53bc67a0daSYuval Mintz enum fib_event_type event_type,
54bc67a0daSYuval Mintz struct vif_device *vif,
55ebc31979SEric Dumazet struct net_device *vif_dev,
56b7a59557SJiri Pirko unsigned short vif_index, u32 tb_id,
57b7a59557SJiri Pirko struct netlink_ext_ack *extack)
58bc67a0daSYuval Mintz {
59bc67a0daSYuval Mintz struct vif_entry_notifier_info info = {
60bc67a0daSYuval Mintz .info = {
61bc67a0daSYuval Mintz .family = family,
62b7a59557SJiri Pirko .extack = extack,
63bc67a0daSYuval Mintz },
64ebc31979SEric Dumazet .dev = vif_dev,
65bc67a0daSYuval Mintz .vif_index = vif_index,
66bc67a0daSYuval Mintz .vif_flags = vif->flags,
67bc67a0daSYuval Mintz .tb_id = tb_id,
68bc67a0daSYuval Mintz };
69bc67a0daSYuval Mintz
707c550dafSJiri Pirko return call_fib_notifier(nb, event_type, &info.info);
71bc67a0daSYuval Mintz }
72bc67a0daSYuval Mintz
mr_call_vif_notifiers(struct net * net,unsigned short family,enum fib_event_type event_type,struct vif_device * vif,struct net_device * vif_dev,unsigned short vif_index,u32 tb_id,unsigned int * ipmr_seq)73bc67a0daSYuval Mintz static inline int mr_call_vif_notifiers(struct net *net,
74bc67a0daSYuval Mintz unsigned short family,
75bc67a0daSYuval Mintz enum fib_event_type event_type,
76bc67a0daSYuval Mintz struct vif_device *vif,
77ebc31979SEric Dumazet struct net_device *vif_dev,
78bc67a0daSYuval Mintz unsigned short vif_index, u32 tb_id,
79bc67a0daSYuval Mintz unsigned int *ipmr_seq)
80bc67a0daSYuval Mintz {
81bc67a0daSYuval Mintz struct vif_entry_notifier_info info = {
82bc67a0daSYuval Mintz .info = {
83bc67a0daSYuval Mintz .family = family,
84bc67a0daSYuval Mintz },
85ebc31979SEric Dumazet .dev = vif_dev,
86bc67a0daSYuval Mintz .vif_index = vif_index,
87bc67a0daSYuval Mintz .vif_flags = vif->flags,
88bc67a0daSYuval Mintz .tb_id = tb_id,
89bc67a0daSYuval Mintz };
90bc67a0daSYuval Mintz
91bc67a0daSYuval Mintz ASSERT_RTNL();
92bc67a0daSYuval Mintz (*ipmr_seq)++;
93bc67a0daSYuval Mintz return call_fib_notifiers(net, event_type, &info.info);
94bc67a0daSYuval Mintz }
95bc67a0daSYuval Mintz
96b70432f7SYuval Mintz #ifndef MAXVIFS
97b70432f7SYuval Mintz /* This one is nasty; value is defined in uapi using different symbols for
98b70432f7SYuval Mintz * mroute and morute6 but both map into same 32.
99b70432f7SYuval Mintz */
100b70432f7SYuval Mintz #define MAXVIFS 32
101b70432f7SYuval Mintz #endif
102b70432f7SYuval Mintz
103ebc31979SEric Dumazet /* Note: This helper is deprecated. */
104ebc31979SEric Dumazet #define VIF_EXISTS(_mrt, _idx) (!!rcu_access_pointer((_mrt)->vif_table[_idx].dev))
105b70432f7SYuval Mintz
106889cd83cSYuval Mintz /* mfc_flags:
107889cd83cSYuval Mintz * MFC_STATIC - the entry was added statically (not by a routing daemon)
108889cd83cSYuval Mintz * MFC_OFFLOAD - the entry was offloaded to the hardware
109889cd83cSYuval Mintz */
110889cd83cSYuval Mintz enum {
111889cd83cSYuval Mintz MFC_STATIC = BIT(0),
112889cd83cSYuval Mintz MFC_OFFLOAD = BIT(1),
113889cd83cSYuval Mintz };
114889cd83cSYuval Mintz
115b70432f7SYuval Mintz /**
116494fff56SYuval Mintz * struct mr_mfc - common multicast routing entries
117494fff56SYuval Mintz * @mnode: rhashtable list
118494fff56SYuval Mintz * @mfc_parent: source interface (iif)
119494fff56SYuval Mintz * @mfc_flags: entry flags
120494fff56SYuval Mintz * @expires: unresolved entry expire time
121494fff56SYuval Mintz * @unresolved: unresolved cached skbs
122494fff56SYuval Mintz * @last_assert: time of last assert
123494fff56SYuval Mintz * @minvif: minimum VIF id
124494fff56SYuval Mintz * @maxvif: maximum VIF id
125494fff56SYuval Mintz * @bytes: bytes that have passed for this entry
126494fff56SYuval Mintz * @pkt: packets that have passed for this entry
127494fff56SYuval Mintz * @wrong_if: number of wrong source interface hits
128494fff56SYuval Mintz * @lastuse: time of last use of the group (traffic or update)
129494fff56SYuval Mintz * @ttls: OIF TTL threshold array
130494fff56SYuval Mintz * @refcount: reference count for this entry
131494fff56SYuval Mintz * @list: global entry list
132494fff56SYuval Mintz * @rcu: used for entry destruction
1338c13af2aSYuval Mintz * @free: Operation used for freeing an entry under RCU
134494fff56SYuval Mintz */
135494fff56SYuval Mintz struct mr_mfc {
136494fff56SYuval Mintz struct rhlist_head mnode;
137494fff56SYuval Mintz unsigned short mfc_parent;
138494fff56SYuval Mintz int mfc_flags;
139494fff56SYuval Mintz
140494fff56SYuval Mintz union {
141494fff56SYuval Mintz struct {
142494fff56SYuval Mintz unsigned long expires;
143494fff56SYuval Mintz struct sk_buff_head unresolved;
144494fff56SYuval Mintz } unres;
145494fff56SYuval Mintz struct {
146494fff56SYuval Mintz unsigned long last_assert;
147494fff56SYuval Mintz int minvif;
148494fff56SYuval Mintz int maxvif;
1493440fa34SEric Dumazet atomic_long_t bytes;
1503440fa34SEric Dumazet atomic_long_t pkt;
1513440fa34SEric Dumazet atomic_long_t wrong_if;
152494fff56SYuval Mintz unsigned long lastuse;
153494fff56SYuval Mintz unsigned char ttls[MAXVIFS];
154494fff56SYuval Mintz refcount_t refcount;
155494fff56SYuval Mintz } res;
156494fff56SYuval Mintz } mfc_un;
157494fff56SYuval Mintz struct list_head list;
158494fff56SYuval Mintz struct rcu_head rcu;
1598c13af2aSYuval Mintz void (*free)(struct rcu_head *head);
160494fff56SYuval Mintz };
161494fff56SYuval Mintz
mr_cache_put(struct mr_mfc * c)1628c13af2aSYuval Mintz static inline void mr_cache_put(struct mr_mfc *c)
1638c13af2aSYuval Mintz {
1648c13af2aSYuval Mintz if (refcount_dec_and_test(&c->mfc_un.res.refcount))
1658c13af2aSYuval Mintz call_rcu(&c->rcu, c->free);
1668c13af2aSYuval Mintz }
1678c13af2aSYuval Mintz
mr_cache_hold(struct mr_mfc * c)1688c13af2aSYuval Mintz static inline void mr_cache_hold(struct mr_mfc *c)
1698c13af2aSYuval Mintz {
1708c13af2aSYuval Mintz refcount_inc(&c->mfc_un.res.refcount);
1718c13af2aSYuval Mintz }
1728c13af2aSYuval Mintz
17354c4cad9SYuval Mintz struct mfc_entry_notifier_info {
17454c4cad9SYuval Mintz struct fib_notifier_info info;
17554c4cad9SYuval Mintz struct mr_mfc *mfc;
17654c4cad9SYuval Mintz u32 tb_id;
17754c4cad9SYuval Mintz };
17854c4cad9SYuval Mintz
mr_call_mfc_notifier(struct notifier_block * nb,unsigned short family,enum fib_event_type event_type,struct mr_mfc * mfc,u32 tb_id,struct netlink_ext_ack * extack)17954c4cad9SYuval Mintz static inline int mr_call_mfc_notifier(struct notifier_block *nb,
18054c4cad9SYuval Mintz unsigned short family,
18154c4cad9SYuval Mintz enum fib_event_type event_type,
182b7a59557SJiri Pirko struct mr_mfc *mfc, u32 tb_id,
183b7a59557SJiri Pirko struct netlink_ext_ack *extack)
18454c4cad9SYuval Mintz {
18554c4cad9SYuval Mintz struct mfc_entry_notifier_info info = {
18654c4cad9SYuval Mintz .info = {
18754c4cad9SYuval Mintz .family = family,
188b7a59557SJiri Pirko .extack = extack,
18954c4cad9SYuval Mintz },
19054c4cad9SYuval Mintz .mfc = mfc,
19154c4cad9SYuval Mintz .tb_id = tb_id
19254c4cad9SYuval Mintz };
19354c4cad9SYuval Mintz
1947c550dafSJiri Pirko return call_fib_notifier(nb, event_type, &info.info);
19554c4cad9SYuval Mintz }
19654c4cad9SYuval Mintz
mr_call_mfc_notifiers(struct net * net,unsigned short family,enum fib_event_type event_type,struct mr_mfc * mfc,u32 tb_id,unsigned int * ipmr_seq)19754c4cad9SYuval Mintz static inline int mr_call_mfc_notifiers(struct net *net,
19854c4cad9SYuval Mintz unsigned short family,
19954c4cad9SYuval Mintz enum fib_event_type event_type,
20054c4cad9SYuval Mintz struct mr_mfc *mfc, u32 tb_id,
20154c4cad9SYuval Mintz unsigned int *ipmr_seq)
20254c4cad9SYuval Mintz {
20354c4cad9SYuval Mintz struct mfc_entry_notifier_info info = {
20454c4cad9SYuval Mintz .info = {
20554c4cad9SYuval Mintz .family = family,
20654c4cad9SYuval Mintz },
20754c4cad9SYuval Mintz .mfc = mfc,
20854c4cad9SYuval Mintz .tb_id = tb_id
20954c4cad9SYuval Mintz };
21054c4cad9SYuval Mintz
21154c4cad9SYuval Mintz ASSERT_RTNL();
21254c4cad9SYuval Mintz (*ipmr_seq)++;
21354c4cad9SYuval Mintz return call_fib_notifiers(net, event_type, &info.info);
21454c4cad9SYuval Mintz }
21554c4cad9SYuval Mintz
216845c9a7aSYuval Mintz struct mr_table;
217845c9a7aSYuval Mintz
218845c9a7aSYuval Mintz /**
219845c9a7aSYuval Mintz * struct mr_table_ops - callbacks and info for protocol-specific ops
220845c9a7aSYuval Mintz * @rht_params: parameters for accessing the MFC hash
221845c9a7aSYuval Mintz * @cmparg_any: a hash key to be used for matching on (*,*) routes
222845c9a7aSYuval Mintz */
223845c9a7aSYuval Mintz struct mr_table_ops {
224845c9a7aSYuval Mintz const struct rhashtable_params *rht_params;
225845c9a7aSYuval Mintz void *cmparg_any;
226845c9a7aSYuval Mintz };
227845c9a7aSYuval Mintz
228494fff56SYuval Mintz /**
229b70432f7SYuval Mintz * struct mr_table - a multicast routing table
230b70432f7SYuval Mintz * @list: entry within a list of multicast routing tables
231b70432f7SYuval Mintz * @net: net where this table belongs
232845c9a7aSYuval Mintz * @ops: protocol specific operations
233b70432f7SYuval Mintz * @id: identifier of the table
234b70432f7SYuval Mintz * @mroute_sk: socket associated with the table
235b70432f7SYuval Mintz * @ipmr_expire_timer: timer for handling unresolved routes
236b70432f7SYuval Mintz * @mfc_unres_queue: list of unresolved MFC entries
237b70432f7SYuval Mintz * @vif_table: array containing all possible vifs
238b70432f7SYuval Mintz * @mfc_hash: Hash table of all resolved routes for easy lookup
239b70432f7SYuval Mintz * @mfc_cache_list: list of resovled routes for possible traversal
240b70432f7SYuval Mintz * @maxvif: Identifier of highest value vif currently in use
241b70432f7SYuval Mintz * @cache_resolve_queue_len: current size of unresolved queue
242b70432f7SYuval Mintz * @mroute_do_assert: Whether to inform userspace on wrong ingress
243b70432f7SYuval Mintz * @mroute_do_pim: Whether to receive IGMP PIMv1
244b70432f7SYuval Mintz * @mroute_reg_vif_num: PIM-device vif index
245b70432f7SYuval Mintz */
246b70432f7SYuval Mintz struct mr_table {
247b70432f7SYuval Mintz struct list_head list;
248b70432f7SYuval Mintz possible_net_t net;
249845c9a7aSYuval Mintz struct mr_table_ops ops;
250b70432f7SYuval Mintz u32 id;
251b70432f7SYuval Mintz struct sock __rcu *mroute_sk;
252b70432f7SYuval Mintz struct timer_list ipmr_expire_timer;
253b70432f7SYuval Mintz struct list_head mfc_unres_queue;
254b70432f7SYuval Mintz struct vif_device vif_table[MAXVIFS];
255b70432f7SYuval Mintz struct rhltable mfc_hash;
256b70432f7SYuval Mintz struct list_head mfc_cache_list;
257b70432f7SYuval Mintz int maxvif;
258b70432f7SYuval Mintz atomic_t cache_resolve_queue_len;
259b70432f7SYuval Mintz bool mroute_do_assert;
260b70432f7SYuval Mintz bool mroute_do_pim;
261c921c207SNikolay Aleksandrov bool mroute_do_wrvifwhole;
262b70432f7SYuval Mintz int mroute_reg_vif_num;
263b70432f7SYuval Mintz };
264b70432f7SYuval Mintz
mr_can_free_table(struct net * net)265*c46286fdSPaolo Abeni static inline bool mr_can_free_table(struct net *net)
266*c46286fdSPaolo Abeni {
267*c46286fdSPaolo Abeni return !check_net(net) || !net_initialized(net);
268*c46286fdSPaolo Abeni }
269*c46286fdSPaolo Abeni
2706853f21fSYuval Mintz #ifdef CONFIG_IP_MROUTE_COMMON
2716853f21fSYuval Mintz void vif_device_init(struct vif_device *v,
2726853f21fSYuval Mintz struct net_device *dev,
2736853f21fSYuval Mintz unsigned long rate_limit,
2746853f21fSYuval Mintz unsigned char threshold,
2756853f21fSYuval Mintz unsigned short flags,
2766853f21fSYuval Mintz unsigned short get_iflink_mask);
2770bbbf0e7SYuval Mintz
2780bbbf0e7SYuval Mintz struct mr_table *
2790bbbf0e7SYuval Mintz mr_table_alloc(struct net *net, u32 id,
280845c9a7aSYuval Mintz struct mr_table_ops *ops,
2810bbbf0e7SYuval Mintz void (*expire_func)(struct timer_list *t),
2820bbbf0e7SYuval Mintz void (*table_set)(struct mr_table *mrt,
2830bbbf0e7SYuval Mintz struct net *net));
284845c9a7aSYuval Mintz
285845c9a7aSYuval Mintz /* These actually return 'struct mr_mfc *', but to avoid need for explicit
286845c9a7aSYuval Mintz * castings they simply return void.
287845c9a7aSYuval Mintz */
288845c9a7aSYuval Mintz void *mr_mfc_find_parent(struct mr_table *mrt,
289845c9a7aSYuval Mintz void *hasharg, int parent);
290845c9a7aSYuval Mintz void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);
291845c9a7aSYuval Mintz void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);
292845c9a7aSYuval Mintz
2937b0db857SYuval Mintz int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2947b0db857SYuval Mintz struct mr_mfc *c, struct rtmsg *rtm);
295e1cedae1SDavid Ahern int mr_table_dump(struct mr_table *mrt, struct sk_buff *skb,
296e1cedae1SDavid Ahern struct netlink_callback *cb,
297e1cedae1SDavid Ahern int (*fill)(struct mr_table *mrt, struct sk_buff *skb,
298e1cedae1SDavid Ahern u32 portid, u32 seq, struct mr_mfc *c,
299e1cedae1SDavid Ahern int cmd, int flags),
300cb167893SDavid Ahern spinlock_t *lock, struct fib_dump_filter *filter);
3017b0db857SYuval Mintz int mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
3027b0db857SYuval Mintz struct mr_table *(*iter)(struct net *net,
3037b0db857SYuval Mintz struct mr_table *mrt),
3047b0db857SYuval Mintz int (*fill)(struct mr_table *mrt,
3057b0db857SYuval Mintz struct sk_buff *skb,
3067b0db857SYuval Mintz u32 portid, u32 seq, struct mr_mfc *c,
3077b0db857SYuval Mintz int cmd, int flags),
308cb167893SDavid Ahern spinlock_t *lock, struct fib_dump_filter *filter);
309cdc9f944SYuval Mintz
310cdc9f944SYuval Mintz int mr_dump(struct net *net, struct notifier_block *nb, unsigned short family,
311cdc9f944SYuval Mintz int (*rules_dump)(struct net *net,
312b7a59557SJiri Pirko struct notifier_block *nb,
313b7a59557SJiri Pirko struct netlink_ext_ack *extack),
314cdc9f944SYuval Mintz struct mr_table *(*mr_iter)(struct net *net,
315cdc9f944SYuval Mintz struct mr_table *mrt),
316194366b2SEric Dumazet struct netlink_ext_ack *extack);
3176853f21fSYuval Mintz #else
vif_device_init(struct vif_device * v,struct net_device * dev,unsigned long rate_limit,unsigned char threshold,unsigned short flags,unsigned short get_iflink_mask)3186853f21fSYuval Mintz static inline void vif_device_init(struct vif_device *v,
3196853f21fSYuval Mintz struct net_device *dev,
3206853f21fSYuval Mintz unsigned long rate_limit,
3216853f21fSYuval Mintz unsigned char threshold,
3226853f21fSYuval Mintz unsigned short flags,
3236853f21fSYuval Mintz unsigned short get_iflink_mask)
3246853f21fSYuval Mintz {
3256853f21fSYuval Mintz }
3260bbbf0e7SYuval Mintz
mr_mfc_find_parent(struct mr_table * mrt,void * hasharg,int parent)327845c9a7aSYuval Mintz static inline void *mr_mfc_find_parent(struct mr_table *mrt,
328845c9a7aSYuval Mintz void *hasharg, int parent)
329845c9a7aSYuval Mintz {
330845c9a7aSYuval Mintz return NULL;
331845c9a7aSYuval Mintz }
332845c9a7aSYuval Mintz
mr_mfc_find_any_parent(struct mr_table * mrt,int vifi)333845c9a7aSYuval Mintz static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,
334845c9a7aSYuval Mintz int vifi)
335845c9a7aSYuval Mintz {
336845c9a7aSYuval Mintz return NULL;
337845c9a7aSYuval Mintz }
338845c9a7aSYuval Mintz
mr_mfc_find_any(struct mr_table * mrt,int vifi,void * hasharg)339845c9a7aSYuval Mintz static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,
340845c9a7aSYuval Mintz int vifi, void *hasharg)
341845c9a7aSYuval Mintz {
342845c9a7aSYuval Mintz return NULL;
343845c9a7aSYuval Mintz }
3447b0db857SYuval Mintz
mr_fill_mroute(struct mr_table * mrt,struct sk_buff * skb,struct mr_mfc * c,struct rtmsg * rtm)3457b0db857SYuval Mintz static inline int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
3467b0db857SYuval Mintz struct mr_mfc *c, struct rtmsg *rtm)
3477b0db857SYuval Mintz {
3487b0db857SYuval Mintz return -EINVAL;
3497b0db857SYuval Mintz }
3507b0db857SYuval Mintz
3517b0db857SYuval Mintz static inline int
mr_rtm_dumproute(struct sk_buff * skb,struct netlink_callback * cb,struct mr_table * (* iter)(struct net * net,struct mr_table * mrt),int (* fill)(struct mr_table * mrt,struct sk_buff * skb,u32 portid,u32 seq,struct mr_mfc * c,int cmd,int flags),spinlock_t * lock,struct fib_dump_filter * filter)3527b0db857SYuval Mintz mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
3537b0db857SYuval Mintz struct mr_table *(*iter)(struct net *net,
3547b0db857SYuval Mintz struct mr_table *mrt),
3557b0db857SYuval Mintz int (*fill)(struct mr_table *mrt,
3567b0db857SYuval Mintz struct sk_buff *skb,
3577b0db857SYuval Mintz u32 portid, u32 seq, struct mr_mfc *c,
3587b0db857SYuval Mintz int cmd, int flags),
359cb167893SDavid Ahern spinlock_t *lock, struct fib_dump_filter *filter)
3607b0db857SYuval Mintz {
3617b0db857SYuval Mintz return -EINVAL;
3627b0db857SYuval Mintz }
363cdc9f944SYuval Mintz
mr_dump(struct net * net,struct notifier_block * nb,unsigned short family,int (* rules_dump)(struct net * net,struct notifier_block * nb,struct netlink_ext_ack * extack),struct mr_table * (* mr_iter)(struct net * net,struct mr_table * mrt),struct netlink_ext_ack * extack)364cdc9f944SYuval Mintz static inline int mr_dump(struct net *net, struct notifier_block *nb,
365cdc9f944SYuval Mintz unsigned short family,
366cdc9f944SYuval Mintz int (*rules_dump)(struct net *net,
367b7a59557SJiri Pirko struct notifier_block *nb,
368b7a59557SJiri Pirko struct netlink_ext_ack *extack),
369cdc9f944SYuval Mintz struct mr_table *(*mr_iter)(struct net *net,
370cdc9f944SYuval Mintz struct mr_table *mrt),
371194366b2SEric Dumazet struct netlink_ext_ack *extack)
372cdc9f944SYuval Mintz {
373cdc9f944SYuval Mintz return -EINVAL;
374cdc9f944SYuval Mintz }
3756853f21fSYuval Mintz #endif
376845c9a7aSYuval Mintz
mr_mfc_find(struct mr_table * mrt,void * hasharg)377845c9a7aSYuval Mintz static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
378845c9a7aSYuval Mintz {
379845c9a7aSYuval Mintz return mr_mfc_find_parent(mrt, hasharg, -1);
380845c9a7aSYuval Mintz }
381c8d61968SYuval Mintz
382c8d61968SYuval Mintz #ifdef CONFIG_PROC_FS
3833feda6b4SYuval Mintz struct mr_vif_iter {
3843feda6b4SYuval Mintz struct seq_net_private p;
3853feda6b4SYuval Mintz struct mr_table *mrt;
3863feda6b4SYuval Mintz int ct;
3873feda6b4SYuval Mintz };
3883feda6b4SYuval Mintz
389c8d61968SYuval Mintz struct mr_mfc_iter {
390c8d61968SYuval Mintz struct seq_net_private p;
391c8d61968SYuval Mintz struct mr_table *mrt;
392c8d61968SYuval Mintz struct list_head *cache;
393c8d61968SYuval Mintz
394c8d61968SYuval Mintz /* Lock protecting the mr_table's unresolved queue */
395c8d61968SYuval Mintz spinlock_t *lock;
396c8d61968SYuval Mintz };
397c8d61968SYuval Mintz
398c8d61968SYuval Mintz #ifdef CONFIG_IP_MROUTE_COMMON
3993feda6b4SYuval Mintz void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);
4003feda6b4SYuval Mintz void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);
4013feda6b4SYuval Mintz
mr_vif_seq_start(struct seq_file * seq,loff_t * pos)4023feda6b4SYuval Mintz static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
4033feda6b4SYuval Mintz {
4043feda6b4SYuval Mintz return *pos ? mr_vif_seq_idx(seq_file_net(seq),
4053feda6b4SYuval Mintz seq->private, *pos - 1)
4063feda6b4SYuval Mintz : SEQ_START_TOKEN;
4073feda6b4SYuval Mintz }
4083feda6b4SYuval Mintz
409c8d61968SYuval Mintz /* These actually return 'struct mr_mfc *', but to avoid need for explicit
410c8d61968SYuval Mintz * castings they simply return void.
411c8d61968SYuval Mintz */
412c8d61968SYuval Mintz void *mr_mfc_seq_idx(struct net *net,
413c8d61968SYuval Mintz struct mr_mfc_iter *it, loff_t pos);
414c8d61968SYuval Mintz void *mr_mfc_seq_next(struct seq_file *seq, void *v,
415c8d61968SYuval Mintz loff_t *pos);
416c8d61968SYuval Mintz
mr_mfc_seq_start(struct seq_file * seq,loff_t * pos,struct mr_table * mrt,spinlock_t * lock)417c8d61968SYuval Mintz static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
418c8d61968SYuval Mintz struct mr_table *mrt, spinlock_t *lock)
419c8d61968SYuval Mintz {
420c8d61968SYuval Mintz struct mr_mfc_iter *it = seq->private;
421c8d61968SYuval Mintz
422c8d61968SYuval Mintz it->mrt = mrt;
423c8d61968SYuval Mintz it->cache = NULL;
424c8d61968SYuval Mintz it->lock = lock;
425c8d61968SYuval Mintz
426c8d61968SYuval Mintz return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
427c8d61968SYuval Mintz seq->private, *pos - 1)
428c8d61968SYuval Mintz : SEQ_START_TOKEN;
429c8d61968SYuval Mintz }
430c8d61968SYuval Mintz
mr_mfc_seq_stop(struct seq_file * seq,void * v)431c8d61968SYuval Mintz static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
432c8d61968SYuval Mintz {
433c8d61968SYuval Mintz struct mr_mfc_iter *it = seq->private;
434c8d61968SYuval Mintz struct mr_table *mrt = it->mrt;
435c8d61968SYuval Mintz
436c8d61968SYuval Mintz if (it->cache == &mrt->mfc_unres_queue)
437c8d61968SYuval Mintz spin_unlock_bh(it->lock);
438c8d61968SYuval Mintz else if (it->cache == &mrt->mfc_cache_list)
439c8d61968SYuval Mintz rcu_read_unlock();
440c8d61968SYuval Mintz }
441c8d61968SYuval Mintz #else
mr_vif_seq_idx(struct net * net,struct mr_vif_iter * iter,loff_t pos)4423feda6b4SYuval Mintz static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,
4433feda6b4SYuval Mintz loff_t pos)
4443feda6b4SYuval Mintz {
4453feda6b4SYuval Mintz return NULL;
4463feda6b4SYuval Mintz }
4473feda6b4SYuval Mintz
mr_vif_seq_next(struct seq_file * seq,void * v,loff_t * pos)4483feda6b4SYuval Mintz static inline void *mr_vif_seq_next(struct seq_file *seq,
4493feda6b4SYuval Mintz void *v, loff_t *pos)
4503feda6b4SYuval Mintz {
4513feda6b4SYuval Mintz return NULL;
4523feda6b4SYuval Mintz }
4533feda6b4SYuval Mintz
mr_vif_seq_start(struct seq_file * seq,loff_t * pos)4543feda6b4SYuval Mintz static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
4553feda6b4SYuval Mintz {
4563feda6b4SYuval Mintz return NULL;
4573feda6b4SYuval Mintz }
4583feda6b4SYuval Mintz
mr_mfc_seq_idx(struct net * net,struct mr_mfc_iter * it,loff_t pos)459c8d61968SYuval Mintz static inline void *mr_mfc_seq_idx(struct net *net,
460c8d61968SYuval Mintz struct mr_mfc_iter *it, loff_t pos)
461c8d61968SYuval Mintz {
462c8d61968SYuval Mintz return NULL;
463c8d61968SYuval Mintz }
464c8d61968SYuval Mintz
mr_mfc_seq_next(struct seq_file * seq,void * v,loff_t * pos)465c8d61968SYuval Mintz static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
466c8d61968SYuval Mintz loff_t *pos)
467c8d61968SYuval Mintz {
468c8d61968SYuval Mintz return NULL;
469c8d61968SYuval Mintz }
470c8d61968SYuval Mintz
mr_mfc_seq_start(struct seq_file * seq,loff_t * pos,struct mr_table * mrt,spinlock_t * lock)471c8d61968SYuval Mintz static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
472c8d61968SYuval Mintz struct mr_table *mrt, spinlock_t *lock)
473c8d61968SYuval Mintz {
474c8d61968SYuval Mintz return NULL;
475c8d61968SYuval Mintz }
476c8d61968SYuval Mintz
mr_mfc_seq_stop(struct seq_file * seq,void * v)477c8d61968SYuval Mintz static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
478c8d61968SYuval Mintz {
479c8d61968SYuval Mintz }
480c8d61968SYuval Mintz #endif
481c8d61968SYuval Mintz #endif
4826853f21fSYuval Mintz #endif
483