mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
netfilter: flowtable: add tunnel match offload support
This patch support both ipv4 and ipv6 tunnel_id, tunnel_src and tunnel_dst match for flowtable offload Signed-off-by: wenxu <wenxu@ucloud.cn> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
b5140a36da
commit
cfab6dbd0e
@ -19,11 +19,17 @@ enum flow_offload_tuple_dir;
|
||||
struct nf_flow_key {
|
||||
struct flow_dissector_key_meta meta;
|
||||
struct flow_dissector_key_control control;
|
||||
struct flow_dissector_key_control enc_control;
|
||||
struct flow_dissector_key_basic basic;
|
||||
union {
|
||||
struct flow_dissector_key_ipv4_addrs ipv4;
|
||||
struct flow_dissector_key_ipv6_addrs ipv6;
|
||||
};
|
||||
struct flow_dissector_key_keyid enc_key_id;
|
||||
union {
|
||||
struct flow_dissector_key_ipv4_addrs enc_ipv4;
|
||||
struct flow_dissector_key_ipv6_addrs enc_ipv6;
|
||||
};
|
||||
struct flow_dissector_key_tcp tcp;
|
||||
struct flow_dissector_key_ports tp;
|
||||
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
|
||||
|
@ -28,11 +28,61 @@ struct flow_offload_work {
|
||||
(__match)->dissector.offset[__type] = \
|
||||
offsetof(struct nf_flow_key, __field)
|
||||
|
||||
static int nf_flow_rule_match(struct nf_flow_match *match,
|
||||
const struct flow_offload_tuple *tuple)
|
||||
static void nf_flow_rule_lwt_match(struct nf_flow_match *match,
|
||||
struct ip_tunnel_info *tun_info)
|
||||
{
|
||||
struct nf_flow_key *mask = &match->mask;
|
||||
struct nf_flow_key *key = &match->key;
|
||||
unsigned int enc_keys;
|
||||
|
||||
if (!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX))
|
||||
return;
|
||||
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_ENC_CONTROL, enc_control);
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_ENC_KEYID, enc_key_id);
|
||||
key->enc_key_id.keyid = tunnel_id_to_key32(tun_info->key.tun_id);
|
||||
mask->enc_key_id.keyid = 0xffffffff;
|
||||
enc_keys = BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
|
||||
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL);
|
||||
|
||||
if (ip_tunnel_info_af(tun_info) == AF_INET) {
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
|
||||
enc_ipv4);
|
||||
key->enc_ipv4.src = tun_info->key.u.ipv4.dst;
|
||||
key->enc_ipv4.dst = tun_info->key.u.ipv4.src;
|
||||
if (key->enc_ipv4.src)
|
||||
mask->enc_ipv4.src = 0xffffffff;
|
||||
if (key->enc_ipv4.dst)
|
||||
mask->enc_ipv4.dst = 0xffffffff;
|
||||
enc_keys |= BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS);
|
||||
key->enc_control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
|
||||
} else {
|
||||
memcpy(&key->enc_ipv6.src, &tun_info->key.u.ipv6.dst,
|
||||
sizeof(struct in6_addr));
|
||||
memcpy(&key->enc_ipv6.dst, &tun_info->key.u.ipv6.src,
|
||||
sizeof(struct in6_addr));
|
||||
if (memcmp(&key->enc_ipv6.src, &in6addr_any,
|
||||
sizeof(struct in6_addr)))
|
||||
memset(&key->enc_ipv6.src, 0xff,
|
||||
sizeof(struct in6_addr));
|
||||
if (memcmp(&key->enc_ipv6.dst, &in6addr_any,
|
||||
sizeof(struct in6_addr)))
|
||||
memset(&key->enc_ipv6.dst, 0xff,
|
||||
sizeof(struct in6_addr));
|
||||
enc_keys |= BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS);
|
||||
key->enc_control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
|
||||
}
|
||||
|
||||
match->dissector.used_keys |= enc_keys;
|
||||
}
|
||||
|
||||
static int nf_flow_rule_match(struct nf_flow_match *match,
|
||||
const struct flow_offload_tuple *tuple,
|
||||
struct dst_entry *other_dst)
|
||||
{
|
||||
struct nf_flow_key *mask = &match->mask;
|
||||
struct nf_flow_key *key = &match->key;
|
||||
struct ip_tunnel_info *tun_info;
|
||||
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_META, meta);
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_CONTROL, control);
|
||||
@ -42,6 +92,11 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
|
||||
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
|
||||
|
||||
if (other_dst->lwtstate) {
|
||||
tun_info = lwt_tun_info(other_dst->lwtstate);
|
||||
nf_flow_rule_lwt_match(match, tun_info);
|
||||
}
|
||||
|
||||
key->meta.ingress_ifindex = tuple->iifidx;
|
||||
mask->meta.ingress_ifindex = 0xffffffff;
|
||||
|
||||
@ -480,6 +535,7 @@ nf_flow_offload_rule_alloc(struct net *net,
|
||||
const struct flow_offload *flow = offload->flow;
|
||||
const struct flow_offload_tuple *tuple;
|
||||
struct nf_flow_rule *flow_rule;
|
||||
struct dst_entry *other_dst;
|
||||
int err = -ENOMEM;
|
||||
|
||||
flow_rule = kzalloc(sizeof(*flow_rule), GFP_KERNEL);
|
||||
@ -495,7 +551,8 @@ nf_flow_offload_rule_alloc(struct net *net,
|
||||
flow_rule->rule->match.key = &flow_rule->match.key;
|
||||
|
||||
tuple = &flow->tuplehash[dir].tuple;
|
||||
err = nf_flow_rule_match(&flow_rule->match, tuple);
|
||||
other_dst = flow->tuplehash[!dir].tuple.dst_cache;
|
||||
err = nf_flow_rule_match(&flow_rule->match, tuple, other_dst);
|
||||
if (err < 0)
|
||||
goto err_flow_match;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user