netfilter: nft_flow_offload: fix interaction with vrf slave device
authorwenxu <wenxu@ucloud.cn>
Thu, 10 Jan 2019 06:51:35 +0000 (14:51 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 10 Jan 2019 23:55:37 +0000 (00:55 +0100)
In the forward chain, the iif is changed from slave device to master vrf
device. Thus, flow offload does not find a match on the lower slave
device.

This patch uses the cached route, ie. dst->dev, to update the iif and
oif fields in the flow entry.

After this patch, the following example works fine:

 # ip addr add dev eth0 1.1.1.1/24
 # ip addr add dev eth1 10.0.0.1/24
 # ip link add user1 type vrf table 1
 # ip l set user1 up
 # ip l set dev eth0 master user1
 # ip l set dev eth1 master user1

 # nft add table firewall
 # nft add flowtable f fb1 { hook ingress priority 0 \; devices = { eth0, eth1 } \; }
 # nft add chain f ftb-all {type filter hook forward priority 0 \; policy accept \; }
 # nft add rule f ftb-all ct zone 1 ip protocol tcp flow offload @fb1
 # nft add rule f ftb-all ct zone 1 ip protocol udp flow offload @fb1

Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_flow_table.h
net/netfilter/nf_flow_table_core.c
net/netfilter/nft_flow_offload.c

index 7d5cda7ce32abefc218ea5d0b5b71d94eb7472fc..3e370cb36263a26335dd65cc7230b50de9eb7564 100644 (file)
@@ -84,7 +84,6 @@ struct flow_offload {
 struct nf_flow_route {
        struct {
                struct dst_entry        *dst;
-               int                     ifindex;
        } tuple[FLOW_OFFLOAD_DIR_MAX];
 };
 
index fa0844e2a68d694183c12e508efb602048321dc2..c0c72ae9df42fb8eff80621753dfe0afa84d7456 100644 (file)
@@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
 {
        struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
        struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
+       struct dst_entry *other_dst = route->tuple[!dir].dst;
        struct dst_entry *dst = route->tuple[dir].dst;
 
        ft->dir = dir;
@@ -50,8 +51,8 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
        ft->src_port = ctt->src.u.tcp.port;
        ft->dst_port = ctt->dst.u.tcp.port;
 
-       ft->iifidx = route->tuple[dir].ifindex;
-       ft->oifidx = route->tuple[!dir].ifindex;
+       ft->iifidx = other_dst->dev->ifindex;
+       ft->oifidx = dst->dev->ifindex;
        ft->dst_cache = dst;
 }
 
index ccdb8f5ababbe864948ee805f4da63090c380443..188c6bbf4e16537dc75958f80a6c0199d5d933a7 100644 (file)
@@ -30,9 +30,11 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
        switch (nft_pf(pkt)) {
        case NFPROTO_IPV4:
                fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+               fl.u.ip4.flowi4_oif = nft_in(pkt)->ifindex;
                break;
        case NFPROTO_IPV6:
                fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+               fl.u.ip6.flowi6_oif = nft_in(pkt)->ifindex;
                break;
        }
 
@@ -41,9 +43,7 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
                return -ENOENT;
 
        route->tuple[dir].dst           = this_dst;
-       route->tuple[dir].ifindex       = nft_in(pkt)->ifindex;
        route->tuple[!dir].dst          = other_dst;
-       route->tuple[!dir].ifindex      = nft_out(pkt)->ifindex;
 
        return 0;
 }