/* Multipath routes: * siblings is a list of fib6_info that have the same metric/weight, * destination, but not the same gateway. nsiblings is just a cache * to speed up lookup.
*/ union { struct list_head fib6_siblings; struct list_head nh_list;
}; unsignedint fib6_nsiblings;
/* The callers should hold f6i->fib6_table->tb6_lock if a route has ever * been added to a table before.
*/ staticinlinevoid fib6_clean_expires(struct fib6_info *f6i)
{
f6i->fib6_flags &= ~RTF_EXPIRES;
f6i->expires = 0;
}
/* The callers should hold f6i->fib6_table->tb6_lock if a route has ever * been added to a table before.
*/ staticinlinevoid fib6_set_expires(struct fib6_info *f6i, unsignedlong expires)
{
f6i->expires = expires;
f6i->fib6_flags |= RTF_EXPIRES;
}
/* Function to safely get fn->fn_sernum for passed in rt * and store result in passed in cookie. * Return true if we can get cookie safely * Return false if not
*/ staticinlinebool fib6_get_cookie_safe(conststruct fib6_info *f6i,
u32 *cookie)
{ struct fib6_node *fn; bool status = false;
fn = rcu_dereference(f6i->fib6_node);
if (fn) {
*cookie = READ_ONCE(fn->fn_sernum); /* pairs with smp_wmb() in __fib6_update_sernum_upto_root() */
smp_rmb();
status = true;
}
from = rcu_dereference(rt->from); if (from)
fib6_get_cookie_safe(from, &cookie);
rcu_read_unlock();
return cookie;
}
staticinlinevoid ip6_rt_put(struct rt6_info *rt)
{ /* dst_release() accepts a NULL parameter. * We rely on dst being first structure in struct rt6_info
*/
BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
dst_release(&rt->dst);
}
struct fib6_entry_notifier_info { struct fib_notifier_info info; /* must be first */ struct fib6_info *rt; unsignedint nsiblings;
};
/* * exported functions
*/
struct fib6_table *fib6_get_table(struct net *net, u32 id); struct fib6_table *fib6_new_table(struct net *net, u32 id); struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, conststruct sk_buff *skb, int flags, pol_lookup_t lookup);
/* called with rcu lock held; can return error pointer * caller needs to select path
*/ int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, struct fib6_result *res, int flags);
/* called with rcu lock held; caller needs to select path */ int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif, struct flowi6 *fl6, struct fib6_result *res, int strict);
void fib6_select_path(conststruct net *net, struct fib6_result *res, struct flowi6 *fl6, int oif, bool have_oif_match, conststruct sk_buff *skb, int strict); struct fib6_node *fib6_node_lookup(struct fib6_node *root, conststruct in6_addr *daddr, conststruct in6_addr *saddr);
struct fib6_node *fib6_locate(struct fib6_node *root, conststruct in6_addr *daddr, int dst_len, conststruct in6_addr *saddr, int src_len, bool exact_match);
void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *arg), void *arg); void fib6_clean_all_skip_notify(struct net *net, int (*func)(struct fib6_info *, void *arg), void *arg);
int fib6_add(struct fib6_node *root, struct fib6_info *rt, struct nl_info *info, struct netlink_ext_ack *extack); int fib6_del(struct fib6_info *rt, struct nl_info *info);
int call_fib6_entry_notifiers(struct net *net, enum fib_event_type event_type, struct fib6_info *rt, struct netlink_ext_ack *extack); int call_fib6_multipath_entry_notifiers(struct net *net, enum fib_event_type event_type, struct fib6_info *rt, unsignedint nsiblings, struct netlink_ext_ack *extack); int call_fib6_entry_notifiers_replace(struct net *net, struct fib6_info *rt); void fib6_rt_update(struct net *net, struct fib6_info *rt, struct nl_info *info); void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, unsignedint flags);
void fib6_run_gc(unsignedlong expires, struct net *net, bool force);
void fib6_gc_cleanup(void);
int fib6_init(void);
/* Add the route to the gc list if it is not already there * * The callers should hold f6i->fib6_table->tb6_lock.
*/ staticinlinevoid fib6_add_gc_list(struct fib6_info *f6i)
{ /* If fib6_node is null, the f6i is not in (or removed from) the * table. * * There is a gap between finding the f6i from the table and * calling this function without the protection of the tb6_lock. * This check makes sure the f6i is not added to the gc list when * it is not on the table.
*/ if (!rcu_dereference_protected(f6i->fib6_node,
lockdep_is_held(&f6i->fib6_table->tb6_lock))) return;
if (hlist_unhashed(&f6i->gc_link))
hlist_add_head(&f6i->gc_link, &f6i->fib6_table->tb6_gc_hlist);
}
/* Remove the route from the gc list if it is on the list. * * The callers should hold f6i->fib6_table->tb6_lock.
*/ staticinlinevoid fib6_remove_gc_list(struct fib6_info *f6i)
{ if (!hlist_unhashed(&f6i->gc_link))
hlist_del_init(&f6i->gc_link);
}
int call_fib6_notifier(struct notifier_block *nb, enum fib_event_type event_type, struct fib_notifier_info *info); int call_fib6_notifiers(struct net *net, enum fib_event_type event_type, struct fib_notifier_info *info);
int __net_init fib6_notifier_init(struct net *net); void __net_exit fib6_notifier_exit(struct net *net);
unsignedint fib6_tables_seq_read(conststruct net *net); int fib6_tables_dump(struct net *net, struct notifier_block *nb, struct netlink_ext_ack *extack);
void fib6_update_sernum(struct net *net, struct fib6_info *rt); void fib6_update_sernum_upto_root(struct net *net, struct fib6_info *rt); void fib6_update_sernum_stub(struct net *net, struct fib6_info *f6i);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.