mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 06:34:11 +08:00
5481d73f81
Use helpers to access fib_nh and fib_nhs fields of a fib_info. Drop the fib_dev macro which is an alias for the first nexthop. Replacements: fi->fib_dev --> fib_info_nh(fi, 0)->fib_nh_dev fi->fib_nh --> fib_info_nh(fi, 0) fi->fib_nh[i] --> fib_info_nh(fi, i) fi->fib_nhs --> fib_info_num_path(fi) where fib_info_nh(fi, i) returns fi->fib_nh[nhsel] and fib_info_num_path returns fi->fib_nhs. Move the existing fib_info_nhc to nexthop.h and define the new ones there. A later patch adds a check if a fib_info uses a nexthop object, and defining the helpers in nexthop.h avoid circular header dependencies. After this all remaining open coded references to fi->fib_nhs and fi->fib_nh are in: - fib_create_info and helpers used to lookup an existing fib_info entry, and - the netdev event functions fib_sync_down_dev and fib_sync_up. The latter two will not be reused for nexthops, and the fib_create_info will be updated to handle a nexthop in a fib_info. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
211 lines
4.1 KiB
C
211 lines
4.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Generic nexthop implementation
|
|
*
|
|
* Copyright (c) 2017-19 Cumulus Networks
|
|
* Copyright (c) 2017-19 David Ahern <dsa@cumulusnetworks.com>
|
|
*/
|
|
|
|
#ifndef __LINUX_NEXTHOP_H
|
|
#define __LINUX_NEXTHOP_H
|
|
|
|
#include <linux/netdevice.h>
|
|
#include <linux/types.h>
|
|
#include <net/ip_fib.h>
|
|
#include <net/ip6_fib.h>
|
|
#include <net/netlink.h>
|
|
|
|
#define NEXTHOP_VALID_USER_FLAGS RTNH_F_ONLINK
|
|
|
|
struct nexthop;
|
|
|
|
struct nh_config {
|
|
u32 nh_id;
|
|
|
|
u8 nh_family;
|
|
u8 nh_protocol;
|
|
u8 nh_blackhole;
|
|
u32 nh_flags;
|
|
|
|
int nh_ifindex;
|
|
struct net_device *dev;
|
|
|
|
union {
|
|
__be32 ipv4;
|
|
struct in6_addr ipv6;
|
|
} gw;
|
|
|
|
struct nlattr *nh_grp;
|
|
u16 nh_grp_type;
|
|
|
|
struct nlattr *nh_encap;
|
|
u16 nh_encap_type;
|
|
|
|
u32 nlflags;
|
|
struct nl_info nlinfo;
|
|
};
|
|
|
|
struct nh_info {
|
|
struct hlist_node dev_hash; /* entry on netns devhash */
|
|
struct nexthop *nh_parent;
|
|
|
|
u8 family;
|
|
bool reject_nh;
|
|
|
|
union {
|
|
struct fib_nh_common fib_nhc;
|
|
struct fib_nh fib_nh;
|
|
struct fib6_nh fib6_nh;
|
|
};
|
|
};
|
|
|
|
struct nh_grp_entry {
|
|
struct nexthop *nh;
|
|
u8 weight;
|
|
atomic_t upper_bound;
|
|
|
|
struct list_head nh_list;
|
|
struct nexthop *nh_parent; /* nexthop of group with this entry */
|
|
};
|
|
|
|
struct nh_group {
|
|
u16 num_nh;
|
|
bool mpath;
|
|
bool has_v4;
|
|
struct nh_grp_entry nh_entries[0];
|
|
};
|
|
|
|
struct nexthop {
|
|
struct rb_node rb_node; /* entry on netns rbtree */
|
|
struct list_head grp_list; /* nh group entries using this nh */
|
|
struct net *net;
|
|
|
|
u32 id;
|
|
|
|
u8 protocol; /* app managing this nh */
|
|
u8 nh_flags;
|
|
bool is_group;
|
|
|
|
refcount_t refcnt;
|
|
struct rcu_head rcu;
|
|
|
|
union {
|
|
struct nh_info __rcu *nh_info;
|
|
struct nh_group __rcu *nh_grp;
|
|
};
|
|
};
|
|
|
|
/* caller is holding rcu or rtnl; no reference taken to nexthop */
|
|
struct nexthop *nexthop_find_by_id(struct net *net, u32 id);
|
|
void nexthop_free_rcu(struct rcu_head *head);
|
|
|
|
static inline bool nexthop_get(struct nexthop *nh)
|
|
{
|
|
return refcount_inc_not_zero(&nh->refcnt);
|
|
}
|
|
|
|
static inline void nexthop_put(struct nexthop *nh)
|
|
{
|
|
if (refcount_dec_and_test(&nh->refcnt))
|
|
call_rcu(&nh->rcu, nexthop_free_rcu);
|
|
}
|
|
|
|
static inline bool nexthop_is_multipath(const struct nexthop *nh)
|
|
{
|
|
if (nh->is_group) {
|
|
struct nh_group *nh_grp;
|
|
|
|
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
|
|
return nh_grp->mpath;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
struct nexthop *nexthop_select_path(struct nexthop *nh, int hash);
|
|
|
|
static inline unsigned int nexthop_num_path(const struct nexthop *nh)
|
|
{
|
|
unsigned int rc = 1;
|
|
|
|
if (nexthop_is_multipath(nh)) {
|
|
struct nh_group *nh_grp;
|
|
|
|
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
|
|
rc = nh_grp->num_nh;
|
|
} else {
|
|
const struct nh_info *nhi;
|
|
|
|
nhi = rcu_dereference_rtnl(nh->nh_info);
|
|
if (nhi->reject_nh)
|
|
rc = 0;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static inline
|
|
struct nexthop *nexthop_mpath_select(const struct nexthop *nh, int nhsel)
|
|
{
|
|
const struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp);
|
|
|
|
/* for_nexthops macros in fib_semantics.c grabs a pointer to
|
|
* the nexthop before checking nhsel
|
|
*/
|
|
if (nhsel > nhg->num_nh)
|
|
return NULL;
|
|
|
|
return nhg->nh_entries[nhsel].nh;
|
|
}
|
|
|
|
static inline
|
|
int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh)
|
|
{
|
|
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
|
|
int i;
|
|
|
|
for (i = 0; i < nhg->num_nh; i++) {
|
|
struct nexthop *nhe = nhg->nh_entries[i].nh;
|
|
struct nh_info *nhi = rcu_dereference_rtnl(nhe->nh_info);
|
|
struct fib_nh_common *nhc = &nhi->fib_nhc;
|
|
int weight = nhg->nh_entries[i].weight;
|
|
|
|
if (fib_add_nexthop(skb, nhc, weight) < 0)
|
|
return -EMSGSIZE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* called with rcu lock */
|
|
static inline bool nexthop_is_blackhole(const struct nexthop *nh)
|
|
{
|
|
const struct nh_info *nhi;
|
|
|
|
if (nexthop_is_multipath(nh)) {
|
|
if (nexthop_num_path(nh) > 1)
|
|
return false;
|
|
nh = nexthop_mpath_select(nh, 0);
|
|
if (!nh)
|
|
return false;
|
|
}
|
|
|
|
nhi = rcu_dereference_rtnl(nh->nh_info);
|
|
return nhi->reject_nh;
|
|
}
|
|
|
|
static inline unsigned int fib_info_num_path(const struct fib_info *fi)
|
|
{
|
|
return fi->fib_nhs;
|
|
}
|
|
|
|
static inline struct fib_nh_common *fib_info_nhc(struct fib_info *fi, int nhsel)
|
|
{
|
|
return &fi->fib_nh[nhsel].nh_common;
|
|
}
|
|
|
|
static inline struct fib_nh *fib_info_nh(struct fib_info *fi, int nhsel)
|
|
{
|
|
return &fi->fib_nh[nhsel];
|
|
}
|
|
#endif
|