diff options
author | David S. Miller | 2015-08-24 10:34:40 -0700 |
---|---|---|
committer | David S. Miller | 2015-08-24 10:34:40 -0700 |
commit | b17f29646dfabe147a7a4d54cc628e8046be3761 (patch) | |
tree | 78be9bc4e05a76f531a7798b7f45529b205fa202 | |
parent | 54cf7be992fe86571a3f07b96446cd5334b014ab (diff) | |
parent | 92b78aff855a4815afe5311e3473ec829d3f2a9e (diff) |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/lwtunnel.h | 3 | ||||
-rw-r--r-- | net/core/lwtunnel.c | 5 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 17 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel_core.c | 2 | ||||
-rw-r--r-- | net/ipv6/ila.c | 19 | ||||
-rw-r--r-- | net/ipv6/route.c | 3 | ||||
-rw-r--r-- | net/mpls/mpls_iptunnel.c | 1 |
7 files changed, 40 insertions, 10 deletions
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index 843489884448..fce0e35e74d0 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -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; diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index e924c2e08554..dfb1a9ca0835 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -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; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 01f1c7dcd329..1b2d01170a4d 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -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 @@ errout: 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; diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 289b6c26ce37..934f2ac8ad61 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -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; diff --git a/net/ipv6/ila.c b/net/ipv6/ila.c index f011c3d5ca40..678d2df4b8d9 100644 --- a/net/ipv6/ila.c +++ b/net/ipv6/ila.c @@ -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; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e476f01add87..df3e353a012d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1819,7 +1819,8 @@ int ip6_route_add(struct fib6_config *cfg) struct lwtunnel_state *lwtstate; err = lwtunnel_build_state(dev, cfg->fc_encap_type, - cfg->fc_encap, &lwtstate); + cfg->fc_encap, AF_INET6, cfg, + &lwtstate); if (err) goto out; rt->dst.lwtstate = lwtstate_get(lwtstate); diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c index 3da5ca3ba563..21e70bc9af98 100644 --- a/net/mpls/mpls_iptunnel.c +++ b/net/mpls/mpls_iptunnel.c @@ -123,6 +123,7 @@ drop: } static int mpls_build_state(struct net_device *dev, struct nlattr *nla, + unsigned int family, const void *cfg, struct lwtunnel_state **ts) { struct mpls_iptunnel_encap *tun_encap_info; |