Commit b571bc62 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-More-movement-to-fib_nh_common'



David Ahern says:

====================
net: More movement to fib_nh_common

Second set of three with the end goal of enabling IPv6 gateways with IPv4
routes.

This set moves:
- the ipv4 tracepoint to take a fib_nh_common and updates it to handle
  a v6 gateway.
- consolidates route notifications to use the same fill functions
  for both ipv4 and ipv6

v4
- enhanced the commit message for patches 1 and 2

v3
- comments from Martin:
  + renamed FIB_RES_NH to FIB_RES_NHC
  + removed family check from fib_result_prefsrc
  + in fib_nexthop_info, renamed nexthop arg to nhc and dropped for_ipv4 arg

v2
- dropped patches moving cached routes and exception buckets to
  fib_nh_common. The goal is allowing a fib6_nh to be used with an
  IPv4 route. The hold up is the need for separate exception buckets -
  one for v6 routes and one for v4 routes. When all of the nexthop patches
  are in, adding a secondi exception bucket pushes IPv6 fib6_info
  allocations over 256 which means fib6_info allocations roll up to 512.
  Hence, deferring the patches until some data mining can be done to keep
  the allocations at 256.
====================

Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4950c2ba c0a72077
Loading
Loading
Loading
Loading
+26 −26
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ struct fib_result {
	unsigned char		type;
	unsigned char		scope;
	u32			tclassid;
	struct fib_nh_common	*nhc;
	struct fib_info		*fi;
	struct fib_table	*table;
	struct hlist_head	*fa_head;
@@ -182,11 +183,10 @@ struct fib_result_nl {
	int             err;
};

#ifdef CONFIG_IP_ROUTE_MULTIPATH
#define FIB_RES_NH(res)		((res).fi->fib_nh[(res).nh_sel])
#else /* CONFIG_IP_ROUTE_MULTIPATH */
#define FIB_RES_NH(res)		((res).fi->fib_nh[0])
#endif /* CONFIG_IP_ROUTE_MULTIPATH */
static inline struct fib_nh_common *fib_info_nhc(struct fib_info *fi, int nhsel)
{
	return &fi->fib_nh[nhsel].nh_common;
}

#ifdef CONFIG_IP_MULTIPLE_TABLES
#define FIB_TABLE_HASHSZ 256
@@ -195,18 +195,11 @@ struct fib_result_nl {
#endif

__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
__be32 fib_result_prefsrc(struct net *net, struct fib_result *res);

#define FIB_RES_SADDR(net, res)				\
	((FIB_RES_NH(res).nh_saddr_genid ==		\
	  atomic_read(&(net)->ipv4.dev_addr_genid)) ?	\
	 FIB_RES_NH(res).nh_saddr :			\
	 fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
#define FIB_RES_GW(res)			(FIB_RES_NH(res).fib_nh_gw4)
#define FIB_RES_DEV(res)		(FIB_RES_NH(res).fib_nh_dev)
#define FIB_RES_OIF(res)		(FIB_RES_NH(res).fib_nh_oif)

#define FIB_RES_PREFSRC(net, res)	((res).fi->fib_prefsrc ? : \
					 FIB_RES_SADDR(net, res))
#define FIB_RES_NHC(res)		((res).nhc)
#define FIB_RES_DEV(res)	(FIB_RES_NHC(res)->nhc_dev)
#define FIB_RES_OIF(res)	(FIB_RES_NHC(res)->nhc_oif)

struct fib_entry_notifier_info {
	struct fib_notifier_info info; /* must be first */
@@ -453,10 +446,12 @@ struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
{
#ifdef CONFIG_IP_ROUTE_CLASSID
	struct fib_nh_common *nhc = res->nhc;
	struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
#ifdef CONFIG_IP_MULTIPLE_TABLES
	u32 rtag;
#endif
	*itag = FIB_RES_NH(*res).nh_tclassid<<16;
	*itag = nh->nh_tclassid << 16;
#ifdef CONFIG_IP_MULTIPLE_TABLES
	rtag = res->tclassid;
	if (*itag == 0)
@@ -497,4 +492,9 @@ u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr);
int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
			  struct fib_dump_filter *filter,
			  struct netlink_callback *cb);

int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
		     unsigned int *flags, bool skip_oif);
int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
		    int nh_weight);
#endif  /* _NET_FIB_H */
+26 −19
Original line number Diff line number Diff line
@@ -13,9 +13,9 @@
TRACE_EVENT(fib_table_lookup,

	TP_PROTO(u32 tb_id, const struct flowi4 *flp,
		 const struct fib_nh *nh, int err),
		 const struct fib_nh_common *nhc, int err),

	TP_ARGS(tb_id, flp, nh, err),
	TP_ARGS(tb_id, flp, nhc, err),

	TP_STRUCT__entry(
		__field(	u32,	tb_id		)
@@ -28,14 +28,17 @@ TRACE_EVENT(fib_table_lookup,
		__field(	__u8,	flags		)
		__array(	__u8,	src,	4	)
		__array(	__u8,	dst,	4	)
		__array(	__u8,	gw,	4	)
		__array(	__u8,	saddr,	4	)
		__array(	__u8,	gw4,	4	)
		__array(	__u8,	gw6,	16	)
		__field(	u16,	sport		)
		__field(	u16,	dport		)
		__dynamic_array(char,  name,   IFNAMSIZ )
	),

	TP_fast_assign(
		struct in6_addr in6_zero = {};
		struct net_device *dev;
		struct in6_addr *in6;
		__be32 *p32;

		__entry->tb_id = tb_id;
@@ -62,33 +65,37 @@ TRACE_EVENT(fib_table_lookup,
			__entry->dport = 0;
		}

		if (nh) {
			struct net_device *dev;

			p32 = (__be32 *) __entry->saddr;
			*p32 = nh->nh_saddr;
		dev = nhc ? nhc->nhc_dev : NULL;
		__assign_str(name, dev ? dev->name : "-");

			p32 = (__be32 *) __entry->gw;
			*p32 = nh->fib_nh_gw4;
		if (nhc) {
			if (nhc->nhc_family == AF_INET) {
				p32 = (__be32 *) __entry->gw4;
				*p32 = nhc->nhc_gw.ipv4;

			dev = nh->fib_nh_dev;
			__assign_str(name, dev ? dev->name : "-");
		} else {
			p32 = (__be32 *) __entry->saddr;
				in6 = (struct in6_addr *)__entry->gw6;
				*in6 = in6_zero;
			} else if (nhc->nhc_family == AF_INET6) {
				p32 = (__be32 *) __entry->gw4;
				*p32 = 0;

			p32 = (__be32 *) __entry->gw;
				in6 = (struct in6_addr *)__entry->gw6;
				*in6 = nhc->nhc_gw.ipv6;
			}
		} else {
			p32 = (__be32 *) __entry->gw4;
			*p32 = 0;

			__assign_str(name, "-");
			in6 = (struct in6_addr *)__entry->gw6;
			*in6 = in6_zero;
		}
	),

	TP_printk("table %u oif %d iif %d proto %u %pI4/%u -> %pI4/%u tos %d scope %d flags %x ==> dev %s gw %pI4 src %pI4 err %d",
	TP_printk("table %u oif %d iif %d proto %u %pI4/%u -> %pI4/%u tos %d scope %d flags %x ==> dev %s gw %pI4/%pI6c err %d",
		  __entry->tb_id, __entry->oif, __entry->iif, __entry->proto,
		  __entry->src, __entry->sport, __entry->dst, __entry->dport,
		  __entry->tos, __entry->scope, __entry->flags,
		  __get_str(name), __entry->gw, __entry->saddr, __entry->err)
		  __get_str(name), __entry->gw4, __entry->gw6, __entry->err)
);
#endif /* _TRACE_FIB_H */

+6 −6
Original line number Diff line number Diff line
@@ -4555,11 +4555,11 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params,
static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
			       u32 flags, bool check_mtu)
{
	struct fib_nh_common *nhc;
	struct in_device *in_dev;
	struct neighbour *neigh;
	struct net_device *dev;
	struct fib_result res;
	struct fib_nh *nh;
	struct flowi4 fl4;
	int err;
	u32 mtu;
@@ -4632,15 +4632,15 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
			return BPF_FIB_LKUP_RET_FRAG_NEEDED;
	}

	nh = &res.fi->fib_nh[res.nh_sel];
	nhc = res.nhc;

	/* do not handle lwt encaps right now */
	if (nh->fib_nh_lws)
	if (nhc->nhc_lwtstate)
		return BPF_FIB_LKUP_RET_UNSUPP_LWT;

	dev = nh->fib_nh_dev;
	if (nh->fib_nh_gw4)
		params->ipv4_dst = nh->fib_nh_gw4;
	dev = nhc->nhc_dev;
	if (nhc->nhc_has_gw)
		params->ipv4_dst = nhc->nhc_gw.ipv4;

	params->rt_metric = res.fi->fib_priority;

+3 −3
Original line number Diff line number Diff line
@@ -307,7 +307,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
			.flowi4_mark = vmark ? skb->mark : 0,
		};
		if (!fib_lookup(net, &fl4, &res, 0))
			return FIB_RES_PREFSRC(net, res);
			return fib_result_prefsrc(net, &res);
	} else {
		scope = RT_SCOPE_LINK;
	}
@@ -390,7 +390,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,

	dev_match = fib_info_nh_uses_dev(res.fi, dev);
	if (dev_match) {
		ret = FIB_RES_NH(res).fib_nh_scope >= RT_SCOPE_HOST;
		ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
		return ret;
	}
	if (no_addr)
@@ -402,7 +402,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
	ret = 0;
	if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
		if (res.type == RTN_UNICAST)
			ret = FIB_RES_NH(res).fib_nh_scope >= RT_SCOPE_HOST;
			ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
	}
	return ret;

+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ static inline void fib_result_assign(struct fib_result *res,
{
	/* we used to play games with refcounts, but we now use RCU */
	res->fi = fi;
	res->nhc = fib_info_nhc(fi, 0);
}

struct fib_prop {
Loading