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

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
...@@ -26,6 +26,7 @@ struct lwtunnel_state { ...@@ -26,6 +26,7 @@ struct lwtunnel_state {
struct lwtunnel_encap_ops { struct lwtunnel_encap_ops {
int (*build_state)(struct net_device *dev, struct nlattr *encap, int (*build_state)(struct net_device *dev, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts); struct lwtunnel_state **ts);
int (*output)(struct sock *sk, struct sk_buff *skb); int (*output)(struct sock *sk, struct sk_buff *skb);
int (*input)(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, ...@@ -80,6 +81,7 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
unsigned int num); unsigned int num);
int lwtunnel_build_state(struct net_device *dev, u16 encap_type, int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
struct nlattr *encap, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **lws); struct lwtunnel_state **lws);
int lwtunnel_fill_encap(struct sk_buff *skb, int lwtunnel_fill_encap(struct sk_buff *skb,
struct lwtunnel_state *lwtstate); struct lwtunnel_state *lwtstate);
...@@ -130,6 +132,7 @@ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op, ...@@ -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, static inline int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
struct nlattr *encap, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **lws) struct lwtunnel_state **lws)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -72,7 +72,8 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops, ...@@ -72,7 +72,8 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops,
EXPORT_SYMBOL(lwtunnel_encap_del_ops); EXPORT_SYMBOL(lwtunnel_encap_del_ops);
int lwtunnel_build_state(struct net_device *dev, u16 encap_type, 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; const struct lwtunnel_encap_ops *ops;
int ret = -EINVAL; int ret = -EINVAL;
...@@ -85,7 +86,7 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type, ...@@ -85,7 +86,7 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
rcu_read_lock(); rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[encap_type]); ops = rcu_dereference(lwtun_encaps[encap_type]);
if (likely(ops && ops->build_state)) 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(); rcu_read_unlock();
return ret; return ret;
......
...@@ -511,7 +511,8 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, ...@@ -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); dev = __dev_get_by_index(net, cfg->fc_oif);
ret = lwtunnel_build_state(dev, nla_get_u16( ret = lwtunnel_build_state(dev, nla_get_u16(
nla_entype), nla_entype),
nla, &lwtstate); nla, AF_INET, cfg,
&lwtstate);
if (ret) if (ret)
goto errout; goto errout;
nexthop_nh->nh_lwtstate = nexthop_nh->nh_lwtstate =
...@@ -535,7 +536,8 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, ...@@ -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, static int fib_encap_match(struct net *net, u16 encap_type,
struct nlattr *encap, 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 lwtunnel_state *lwtstate;
struct net_device *dev = NULL; struct net_device *dev = NULL;
...@@ -546,8 +548,8 @@ static int fib_encap_match(struct net *net, u16 encap_type, ...@@ -546,8 +548,8 @@ static int fib_encap_match(struct net *net, u16 encap_type,
if (oif) if (oif)
dev = __dev_get_by_index(net, oif); dev = __dev_get_by_index(net, oif);
ret = lwtunnel_build_state(dev, encap_type, ret = lwtunnel_build_state(dev, encap_type, encap,
encap, &lwtstate); AF_INET, cfg, &lwtstate);
if (!ret) { if (!ret) {
result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate); result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
lwtstate_free(lwtstate); lwtstate_free(lwtstate);
...@@ -571,7 +573,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) ...@@ -571,7 +573,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
if (cfg->fc_encap) { if (cfg->fc_encap) {
if (fib_encap_match(net, cfg->fc_encap_type, if (fib_encap_match(net, cfg->fc_encap_type,
cfg->fc_encap, cfg->fc_oif, cfg->fc_encap, cfg->fc_oif,
fi->fib_nh)) fi->fib_nh, cfg))
return 1; return 1;
} }
if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && 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) ...@@ -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, static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
struct fib_nh *nh) struct fib_nh *nh)
{ {
int err; int err = 0;
struct net *net; struct net *net;
struct net_device *dev; struct net_device *dev;
...@@ -1005,7 +1007,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg) ...@@ -1005,7 +1007,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
if (cfg->fc_oif) if (cfg->fc_oif)
dev = __dev_get_by_index(net, cfg->fc_oif); dev = __dev_get_by_index(net, cfg->fc_oif);
err = lwtunnel_build_state(dev, cfg->fc_encap_type, err = lwtunnel_build_state(dev, cfg->fc_encap_type,
cfg->fc_encap, &lwtstate); cfg->fc_encap, AF_INET, cfg,
&lwtstate);
if (err) if (err)
goto failure; goto failure;
......
...@@ -204,6 +204,7 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = { ...@@ -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, static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts)
{ {
struct ip_tunnel_info *tun_info; struct ip_tunnel_info *tun_info;
...@@ -311,6 +312,7 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = { ...@@ -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, static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts)
{ {
struct ip_tunnel_info *tun_info; struct ip_tunnel_info *tun_info;
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
struct ila_params { struct ila_params {
__be64 locator; __be64 locator;
__be64 locator_match;
__wsum csum_diff;
}; };
static inline struct ila_params *ila_params_lwtunnel( static inline struct ila_params *ila_params_lwtunnel(
...@@ -33,6 +35,9 @@ static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to) ...@@ -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) 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, return compute_csum_diff8((__be32 *)&ip6h->daddr,
(__be32 *)&p->locator); (__be32 *)&p->locator);
} }
...@@ -123,14 +128,19 @@ static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { ...@@ -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, static int ila_build_state(struct net_device *dev, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts)
{ {
struct ila_params *p; struct ila_params *p;
struct nlattr *tb[ILA_ATTR_MAX + 1]; struct nlattr *tb[ILA_ATTR_MAX + 1];
size_t encap_len = sizeof(*p); size_t encap_len = sizeof(*p);
struct lwtunnel_state *newts; struct lwtunnel_state *newts;
const struct fib6_config *cfg6 = cfg;
int ret; int ret;
if (family != AF_INET6)
return -EINVAL;
ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla,
ila_nl_policy); ila_nl_policy);
if (ret < 0) if (ret < 0)
...@@ -148,6 +158,15 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla, ...@@ -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]); 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->type = LWTUNNEL_ENCAP_ILA;
newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT | newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
LWTUNNEL_STATE_INPUT_REDIRECT; LWTUNNEL_STATE_INPUT_REDIRECT;
......
...@@ -1819,7 +1819,8 @@ int ip6_route_add(struct fib6_config *cfg) ...@@ -1819,7 +1819,8 @@ int ip6_route_add(struct fib6_config *cfg)
struct lwtunnel_state *lwtstate; struct lwtunnel_state *lwtstate;
err = lwtunnel_build_state(dev, cfg->fc_encap_type, err = lwtunnel_build_state(dev, cfg->fc_encap_type,
cfg->fc_encap, &lwtstate); cfg->fc_encap, AF_INET6, cfg,
&lwtstate);
if (err) if (err)
goto out; goto out;
rt->dst.lwtstate = lwtstate_get(lwtstate); rt->dst.lwtstate = lwtstate_get(lwtstate);
......
...@@ -123,6 +123,7 @@ int mpls_output(struct sock *sk, struct sk_buff *skb) ...@@ -123,6 +123,7 @@ int mpls_output(struct sock *sk, struct sk_buff *skb)
} }
static int mpls_build_state(struct net_device *dev, struct nlattr *nla, static int mpls_build_state(struct net_device *dev, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts)
{ {
struct mpls_iptunnel_encap *tun_encap_info; struct mpls_iptunnel_encap *tun_encap_info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment