Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

Merge branch 'ila-precompute'



Tom Herbert says:

====================
ila: Precompute checksums

This patch set:
 - Adds argument ot LWT build_state that holds a pointer to the fib
   configuration being applied to the new route
 - Adds support in ILA to precompute checksum difference for
   performance optimization

v2:
 - Move return argument in build_state to end of arguments

v3:
 - Update the signature for ip6_tun_build_state()
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 54cf7be9 92b78aff
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ struct lwtunnel_state {

struct lwtunnel_encap_ops {
	int (*build_state)(struct net_device *dev, struct nlattr *encap,
			   unsigned int family, const void *cfg,
			   struct lwtunnel_state **ts);
	int (*output)(struct sock *sk, struct sk_buff *skb);
	int (*input)(struct sk_buff *skb);
@@ -80,6 +81,7 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
			   unsigned int num);
int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
			 struct nlattr *encap,
			 unsigned int family, const void *cfg,
			 struct lwtunnel_state **lws);
int lwtunnel_fill_encap(struct sk_buff *skb,
			struct lwtunnel_state *lwtstate);
@@ -130,6 +132,7 @@ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,

static inline int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
				       struct nlattr *encap,
				       unsigned int family, const void *cfg,
				       struct lwtunnel_state **lws)
{
	return -EOPNOTSUPP;
+3 −2
Original line number Diff line number Diff line
@@ -72,7 +72,8 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops,
EXPORT_SYMBOL(lwtunnel_encap_del_ops);

int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
			 struct nlattr *encap, struct lwtunnel_state **lws)
			 struct nlattr *encap, unsigned int family,
			 const void *cfg, struct lwtunnel_state **lws)
{
	const struct lwtunnel_encap_ops *ops;
	int ret = -EINVAL;
@@ -85,7 +86,7 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
	rcu_read_lock();
	ops = rcu_dereference(lwtun_encaps[encap_type]);
	if (likely(ops && ops->build_state))
		ret = ops->build_state(dev, encap, lws);
		ret = ops->build_state(dev, encap, family, cfg, lws);
	rcu_read_unlock();

	return ret;
+10 −7
Original line number Diff line number Diff line
@@ -511,7 +511,8 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
					dev = __dev_get_by_index(net, cfg->fc_oif);
				ret = lwtunnel_build_state(dev, nla_get_u16(
							   nla_entype),
							   nla, &lwtstate);
							   nla,  AF_INET, cfg,
							   &lwtstate);
				if (ret)
					goto errout;
				nexthop_nh->nh_lwtstate =
@@ -535,7 +536,8 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,

static int fib_encap_match(struct net *net, u16 encap_type,
			   struct nlattr *encap,
			   int oif, const struct fib_nh *nh)
			   int oif, const struct fib_nh *nh,
			   const struct fib_config *cfg)
{
	struct lwtunnel_state *lwtstate;
	struct net_device *dev = NULL;
@@ -546,8 +548,8 @@ static int fib_encap_match(struct net *net, u16 encap_type,

	if (oif)
		dev = __dev_get_by_index(net, oif);
	ret = lwtunnel_build_state(dev, encap_type,
				   encap, &lwtstate);
	ret = lwtunnel_build_state(dev, encap_type, encap,
				   AF_INET, cfg, &lwtstate);
	if (!ret) {
		result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
		lwtstate_free(lwtstate);
@@ -571,7 +573,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
		if (cfg->fc_encap) {
			if (fib_encap_match(net, cfg->fc_encap_type,
					    cfg->fc_encap, cfg->fc_oif,
					    fi->fib_nh))
					    fi->fib_nh, cfg))
			    return 1;
		}
		if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) &&
@@ -663,7 +665,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
			struct fib_nh *nh)
{
	int err;
	int err = 0;
	struct net *net;
	struct net_device *dev;

@@ -1005,7 +1007,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
			if (cfg->fc_oif)
				dev = __dev_get_by_index(net, cfg->fc_oif);
			err = lwtunnel_build_state(dev, cfg->fc_encap_type,
						   cfg->fc_encap, &lwtstate);
						   cfg->fc_encap, AF_INET, cfg,
						   &lwtstate);
			if (err)
				goto failure;

+2 −0
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
};

static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
			      unsigned int family, const void *cfg,
			      struct lwtunnel_state **ts)
{
	struct ip_tunnel_info *tun_info;
@@ -311,6 +312,7 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
};

static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr,
			       unsigned int family, const void *cfg,
			       struct lwtunnel_state **ts)
{
	struct ip_tunnel_info *tun_info;
+19 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@

struct ila_params {
	__be64 locator;
	__be64 locator_match;
	__wsum csum_diff;
};

static inline struct ila_params *ila_params_lwtunnel(
@@ -33,6 +35,9 @@ static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to)

static inline __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p)
{
	if (*(__be64 *)&ip6h->daddr == p->locator_match)
		return p->csum_diff;
	else
		return compute_csum_diff8((__be32 *)&ip6h->daddr,
					  (__be32 *)&p->locator);
}
@@ -123,14 +128,19 @@ static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
};

static int ila_build_state(struct net_device *dev, struct nlattr *nla,
			   unsigned int family, const void *cfg,
			   struct lwtunnel_state **ts)
{
	struct ila_params *p;
	struct nlattr *tb[ILA_ATTR_MAX + 1];
	size_t encap_len = sizeof(*p);
	struct lwtunnel_state *newts;
	const struct fib6_config *cfg6 = cfg;
	int ret;

	if (family != AF_INET6)
		return -EINVAL;

	ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla,
			       ila_nl_policy);
	if (ret < 0)
@@ -148,6 +158,15 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,

	p->locator = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);

	if (cfg6->fc_dst_len > sizeof(__be64)) {
		/* Precompute checksum difference for translation since we
		 * know both the old locator and the new one.
		 */
		p->locator_match = *(__be64 *)&cfg6->fc_dst;
		p->csum_diff = compute_csum_diff8(
			(__be32 *)&p->locator_match, (__be32 *)&p->locator);
	}

	newts->type = LWTUNNEL_ENCAP_ILA;
	newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
			LWTUNNEL_STATE_INPUT_REDIRECT;
Loading