forked from Minki/linux
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>
This commit is contained in:
commit
b17f29646d
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user