478 lines · c
1#ifndef __LINUX_MROUTE_BASE_H2#define __LINUX_MROUTE_BASE_H3 4#include <linux/netdevice.h>5#include <linux/rhashtable-types.h>6#include <linux/spinlock.h>7#include <net/net_namespace.h>8#include <net/sock.h>9#include <net/fib_notifier.h>10#include <net/ip_fib.h>11 12/**13 * struct vif_device - interface representor for multicast routing14 * @dev: network device being used15 * @dev_tracker: refcount tracker for @dev reference16 * @bytes_in: statistic; bytes ingressing17 * @bytes_out: statistic; bytes egresing18 * @pkt_in: statistic; packets ingressing19 * @pkt_out: statistic; packets egressing20 * @rate_limit: Traffic shaping (NI)21 * @threshold: TTL threshold22 * @flags: Control flags23 * @link: Physical interface index24 * @dev_parent_id: device parent id25 * @local: Local address26 * @remote: Remote address for tunnels27 */28struct vif_device {29 struct net_device __rcu *dev;30 netdevice_tracker dev_tracker;31 unsigned long bytes_in, bytes_out;32 unsigned long pkt_in, pkt_out;33 unsigned long rate_limit;34 unsigned char threshold;35 unsigned short flags;36 int link;37 38 /* Currently only used by ipmr */39 struct netdev_phys_item_id dev_parent_id;40 __be32 local, remote;41};42 43struct vif_entry_notifier_info {44 struct fib_notifier_info info;45 struct net_device *dev;46 unsigned short vif_index;47 unsigned short vif_flags;48 u32 tb_id;49};50 51static inline int mr_call_vif_notifier(struct notifier_block *nb,52 unsigned short family,53 enum fib_event_type event_type,54 struct vif_device *vif,55 struct net_device *vif_dev,56 unsigned short vif_index, u32 tb_id,57 struct netlink_ext_ack *extack)58{59 struct vif_entry_notifier_info info = {60 .info = {61 .family = family,62 .extack = extack,63 },64 .dev = vif_dev,65 .vif_index = vif_index,66 .vif_flags = vif->flags,67 .tb_id = tb_id,68 };69 70 return call_fib_notifier(nb, event_type, &info.info);71}72 73static inline int mr_call_vif_notifiers(struct net *net,74 unsigned short family,75 enum fib_event_type event_type,76 struct vif_device *vif,77 struct net_device *vif_dev,78 unsigned short vif_index, u32 tb_id,79 unsigned int *ipmr_seq)80{81 struct vif_entry_notifier_info info = {82 .info = {83 .family = family,84 },85 .dev = vif_dev,86 .vif_index = vif_index,87 .vif_flags = vif->flags,88 .tb_id = tb_id,89 };90 91 ASSERT_RTNL();92 (*ipmr_seq)++;93 return call_fib_notifiers(net, event_type, &info.info);94}95 96#ifndef MAXVIFS97/* This one is nasty; value is defined in uapi using different symbols for98 * mroute and morute6 but both map into same 32.99 */100#define MAXVIFS 32101#endif102 103/* Note: This helper is deprecated. */104#define VIF_EXISTS(_mrt, _idx) (!!rcu_access_pointer((_mrt)->vif_table[_idx].dev))105 106/* mfc_flags:107 * MFC_STATIC - the entry was added statically (not by a routing daemon)108 * MFC_OFFLOAD - the entry was offloaded to the hardware109 */110enum {111 MFC_STATIC = BIT(0),112 MFC_OFFLOAD = BIT(1),113};114 115/**116 * struct mr_mfc - common multicast routing entries117 * @mnode: rhashtable list118 * @mfc_parent: source interface (iif)119 * @mfc_flags: entry flags120 * @expires: unresolved entry expire time121 * @unresolved: unresolved cached skbs122 * @last_assert: time of last assert123 * @minvif: minimum VIF id124 * @maxvif: maximum VIF id125 * @bytes: bytes that have passed for this entry126 * @pkt: packets that have passed for this entry127 * @wrong_if: number of wrong source interface hits128 * @lastuse: time of last use of the group (traffic or update)129 * @ttls: OIF TTL threshold array130 * @refcount: reference count for this entry131 * @list: global entry list132 * @rcu: used for entry destruction133 * @free: Operation used for freeing an entry under RCU134 */135struct mr_mfc {136 struct rhlist_head mnode;137 unsigned short mfc_parent;138 int mfc_flags;139 140 union {141 struct {142 unsigned long expires;143 struct sk_buff_head unresolved;144 } unres;145 struct {146 unsigned long last_assert;147 int minvif;148 int maxvif;149 unsigned long bytes;150 unsigned long pkt;151 unsigned long wrong_if;152 unsigned long lastuse;153 unsigned char ttls[MAXVIFS];154 refcount_t refcount;155 } res;156 } mfc_un;157 struct list_head list;158 struct rcu_head rcu;159 void (*free)(struct rcu_head *head);160};161 162static inline void mr_cache_put(struct mr_mfc *c)163{164 if (refcount_dec_and_test(&c->mfc_un.res.refcount))165 call_rcu(&c->rcu, c->free);166}167 168static inline void mr_cache_hold(struct mr_mfc *c)169{170 refcount_inc(&c->mfc_un.res.refcount);171}172 173struct mfc_entry_notifier_info {174 struct fib_notifier_info info;175 struct mr_mfc *mfc;176 u32 tb_id;177};178 179static inline int mr_call_mfc_notifier(struct notifier_block *nb,180 unsigned short family,181 enum fib_event_type event_type,182 struct mr_mfc *mfc, u32 tb_id,183 struct netlink_ext_ack *extack)184{185 struct mfc_entry_notifier_info info = {186 .info = {187 .family = family,188 .extack = extack,189 },190 .mfc = mfc,191 .tb_id = tb_id192 };193 194 return call_fib_notifier(nb, event_type, &info.info);195}196 197static inline int mr_call_mfc_notifiers(struct net *net,198 unsigned short family,199 enum fib_event_type event_type,200 struct mr_mfc *mfc, u32 tb_id,201 unsigned int *ipmr_seq)202{203 struct mfc_entry_notifier_info info = {204 .info = {205 .family = family,206 },207 .mfc = mfc,208 .tb_id = tb_id209 };210 211 ASSERT_RTNL();212 (*ipmr_seq)++;213 return call_fib_notifiers(net, event_type, &info.info);214}215 216struct mr_table;217 218/**219 * struct mr_table_ops - callbacks and info for protocol-specific ops220 * @rht_params: parameters for accessing the MFC hash221 * @cmparg_any: a hash key to be used for matching on (*,*) routes222 */223struct mr_table_ops {224 const struct rhashtable_params *rht_params;225 void *cmparg_any;226};227 228/**229 * struct mr_table - a multicast routing table230 * @list: entry within a list of multicast routing tables231 * @net: net where this table belongs232 * @ops: protocol specific operations233 * @id: identifier of the table234 * @mroute_sk: socket associated with the table235 * @ipmr_expire_timer: timer for handling unresolved routes236 * @mfc_unres_queue: list of unresolved MFC entries237 * @vif_table: array containing all possible vifs238 * @mfc_hash: Hash table of all resolved routes for easy lookup239 * @mfc_cache_list: list of resovled routes for possible traversal240 * @maxvif: Identifier of highest value vif currently in use241 * @cache_resolve_queue_len: current size of unresolved queue242 * @mroute_do_assert: Whether to inform userspace on wrong ingress243 * @mroute_do_pim: Whether to receive IGMP PIMv1244 * @mroute_reg_vif_num: PIM-device vif index245 */246struct mr_table {247 struct list_head list;248 possible_net_t net;249 struct mr_table_ops ops;250 u32 id;251 struct sock __rcu *mroute_sk;252 struct timer_list ipmr_expire_timer;253 struct list_head mfc_unres_queue;254 struct vif_device vif_table[MAXVIFS];255 struct rhltable mfc_hash;256 struct list_head mfc_cache_list;257 int maxvif;258 atomic_t cache_resolve_queue_len;259 bool mroute_do_assert;260 bool mroute_do_pim;261 bool mroute_do_wrvifwhole;262 int mroute_reg_vif_num;263};264 265#ifdef CONFIG_IP_MROUTE_COMMON266void vif_device_init(struct vif_device *v,267 struct net_device *dev,268 unsigned long rate_limit,269 unsigned char threshold,270 unsigned short flags,271 unsigned short get_iflink_mask);272 273struct mr_table *274mr_table_alloc(struct net *net, u32 id,275 struct mr_table_ops *ops,276 void (*expire_func)(struct timer_list *t),277 void (*table_set)(struct mr_table *mrt,278 struct net *net));279 280/* These actually return 'struct mr_mfc *', but to avoid need for explicit281 * castings they simply return void.282 */283void *mr_mfc_find_parent(struct mr_table *mrt,284 void *hasharg, int parent);285void *mr_mfc_find_any_parent(struct mr_table *mrt, int vifi);286void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg);287 288int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,289 struct mr_mfc *c, struct rtmsg *rtm);290int mr_table_dump(struct mr_table *mrt, struct sk_buff *skb,291 struct netlink_callback *cb,292 int (*fill)(struct mr_table *mrt, struct sk_buff *skb,293 u32 portid, u32 seq, struct mr_mfc *c,294 int cmd, int flags),295 spinlock_t *lock, struct fib_dump_filter *filter);296int mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,297 struct mr_table *(*iter)(struct net *net,298 struct mr_table *mrt),299 int (*fill)(struct mr_table *mrt,300 struct sk_buff *skb,301 u32 portid, u32 seq, struct mr_mfc *c,302 int cmd, int flags),303 spinlock_t *lock, struct fib_dump_filter *filter);304 305int mr_dump(struct net *net, struct notifier_block *nb, unsigned short family,306 int (*rules_dump)(struct net *net,307 struct notifier_block *nb,308 struct netlink_ext_ack *extack),309 struct mr_table *(*mr_iter)(struct net *net,310 struct mr_table *mrt),311 struct netlink_ext_ack *extack);312#else313static inline void vif_device_init(struct vif_device *v,314 struct net_device *dev,315 unsigned long rate_limit,316 unsigned char threshold,317 unsigned short flags,318 unsigned short get_iflink_mask)319{320}321 322static inline void *mr_mfc_find_parent(struct mr_table *mrt,323 void *hasharg, int parent)324{325 return NULL;326}327 328static inline void *mr_mfc_find_any_parent(struct mr_table *mrt,329 int vifi)330{331 return NULL;332}333 334static inline struct mr_mfc *mr_mfc_find_any(struct mr_table *mrt,335 int vifi, void *hasharg)336{337 return NULL;338}339 340static inline int mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,341 struct mr_mfc *c, struct rtmsg *rtm)342{343 return -EINVAL;344}345 346static inline int347mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,348 struct mr_table *(*iter)(struct net *net,349 struct mr_table *mrt),350 int (*fill)(struct mr_table *mrt,351 struct sk_buff *skb,352 u32 portid, u32 seq, struct mr_mfc *c,353 int cmd, int flags),354 spinlock_t *lock, struct fib_dump_filter *filter)355{356 return -EINVAL;357}358 359static inline int mr_dump(struct net *net, struct notifier_block *nb,360 unsigned short family,361 int (*rules_dump)(struct net *net,362 struct notifier_block *nb,363 struct netlink_ext_ack *extack),364 struct mr_table *(*mr_iter)(struct net *net,365 struct mr_table *mrt),366 struct netlink_ext_ack *extack)367{368 return -EINVAL;369}370#endif371 372static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)373{374 return mr_mfc_find_parent(mrt, hasharg, -1);375}376 377#ifdef CONFIG_PROC_FS378struct mr_vif_iter {379 struct seq_net_private p;380 struct mr_table *mrt;381 int ct;382};383 384struct mr_mfc_iter {385 struct seq_net_private p;386 struct mr_table *mrt;387 struct list_head *cache;388 389 /* Lock protecting the mr_table's unresolved queue */390 spinlock_t *lock;391};392 393#ifdef CONFIG_IP_MROUTE_COMMON394void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter, loff_t pos);395void *mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos);396 397static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)398{399 return *pos ? mr_vif_seq_idx(seq_file_net(seq),400 seq->private, *pos - 1)401 : SEQ_START_TOKEN;402}403 404/* These actually return 'struct mr_mfc *', but to avoid need for explicit405 * castings they simply return void.406 */407void *mr_mfc_seq_idx(struct net *net,408 struct mr_mfc_iter *it, loff_t pos);409void *mr_mfc_seq_next(struct seq_file *seq, void *v,410 loff_t *pos);411 412static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,413 struct mr_table *mrt, spinlock_t *lock)414{415 struct mr_mfc_iter *it = seq->private;416 417 it->mrt = mrt;418 it->cache = NULL;419 it->lock = lock;420 421 return *pos ? mr_mfc_seq_idx(seq_file_net(seq),422 seq->private, *pos - 1)423 : SEQ_START_TOKEN;424}425 426static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)427{428 struct mr_mfc_iter *it = seq->private;429 struct mr_table *mrt = it->mrt;430 431 if (it->cache == &mrt->mfc_unres_queue)432 spin_unlock_bh(it->lock);433 else if (it->cache == &mrt->mfc_cache_list)434 rcu_read_unlock();435}436#else437static inline void *mr_vif_seq_idx(struct net *net, struct mr_vif_iter *iter,438 loff_t pos)439{440 return NULL;441}442 443static inline void *mr_vif_seq_next(struct seq_file *seq,444 void *v, loff_t *pos)445{446 return NULL;447}448 449static inline void *mr_vif_seq_start(struct seq_file *seq, loff_t *pos)450{451 return NULL;452}453 454static inline void *mr_mfc_seq_idx(struct net *net,455 struct mr_mfc_iter *it, loff_t pos)456{457 return NULL;458}459 460static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,461 loff_t *pos)462{463 return NULL;464}465 466static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,467 struct mr_table *mrt, spinlock_t *lock)468{469 return NULL;470}471 472static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)473{474}475#endif476#endif477#endif478