提交 c46095fd 编写于 作者: L LEAN-ESX

merge upstream flow offload patch

上级 d155f1f0
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 15 Mar 2018 18:21:43 +0100
Subject: [PATCH] netfilter: nf_flow_table: clean up and fix dst handling
dst handling in the code is inconsistent and possibly wrong. In my test,
skb_dst(skb) holds the dst entry after routing but before NAT, so the
code could possibly return the same dst entry for both directions of a
connection.
Additionally, there was some confusion over the dst entry vs the address
passed as parameter to rt_nexthop/rt6_nexthop.
Do an explicit dst lookup for both ends of the connection and always use
the source address for it. When running the IP hook, use the dst entry
for the opposite direction for determining the route.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -238,7 +238,7 @@ nf_flow_offload_ip_hook(void *priv, stru
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache;
+ rt = (const struct rtable *)flow->tuplehash[!dir].tuple.dst_cache;
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) &&
(ip_hdr(skb)->frag_off & htons(IP_DF)) != 0)
@@ -455,7 +455,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache;
+ rt = (struct rt6_info *)flow->tuplehash[!dir].tuple.dst_cache;
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
return NF_ACCEPT;
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -17,27 +17,38 @@ struct nft_flow_offload {
struct nft_flowtable *flowtable;
};
-static int nft_flow_route(const struct nft_pktinfo *pkt,
- const struct nf_conn *ct,
- struct nf_flow_route *route,
- enum ip_conntrack_dir dir)
+static struct dst_entry *
+nft_flow_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir,
+ const struct nft_pktinfo *pkt)
{
- struct dst_entry *this_dst = skb_dst(pkt->skb);
- struct dst_entry *other_dst = NULL;
+ struct dst_entry *dst;
struct flowi fl;
memset(&fl, 0, sizeof(fl));
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
- fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
break;
case NFPROTO_IPV6:
- fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
+ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
break;
}
- nf_route(nft_net(pkt), &other_dst, &fl, false, nft_pf(pkt));
- if (!other_dst)
+ nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt));
+
+ return dst;
+}
+
+static int nft_flow_route(const struct nft_pktinfo *pkt,
+ const struct nf_conn *ct,
+ struct nf_flow_route *route,
+ enum ip_conntrack_dir dir)
+{
+ struct dst_entry *this_dst, *other_dst;
+
+ this_dst = nft_flow_dst(ct, dir, pkt);
+ other_dst = nft_flow_dst(ct, !dir, pkt);
+ if (!this_dst || !other_dst)
return -ENOENT;
route->tuple[dir].dst = this_dst;
From: wenxu <wenxu@ucloud.cn>
Date: Wed, 9 Jan 2019 10:40:11 +0800
Subject: [PATCH] netfilter: nft_flow_offload: Fix reverse route lookup
Using the following example:
client 1.1.1.7 ---> 2.2.2.7 which dnat to 10.0.0.7 server
The first reply packet (ie. syn+ack) uses an incorrect destination
address for the reverse route lookup since it uses:
daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
which is 2.2.2.7 in the scenario that is described above, while this
should be:
daddr = ct->tuplehash[dir].tuple.src.u3.ip;
that is 10.0.0.7.
Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -29,10 +29,10 @@ static int nft_flow_route(const struct n
memset(&fl, 0, sizeof(fl));
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
- fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
break;
case NFPROTO_IPV6:
- fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
+ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
break;
}
...@@ -26,8 +26,8 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -26,8 +26,8 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
dir = tuplehash->tuple.dir; dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- rt = (const struct rtable *)flow->tuplehash[!dir].tuple.dst_cache; - rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache;
+ rt = (struct rtable *)flow->tuplehash[!dir].tuple.dst_cache; + rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache;
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) && if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) &&
(ip_hdr(skb)->frag_off & htons(IP_DF)) != 0) (ip_hdr(skb)->frag_off & htons(IP_DF)) != 0)
......
From: wenxu <wenxu@ucloud.cn>
Date: Thu, 10 Jan 2019 14:51:35 +0800
Subject: [PATCH] netfilter: nft_flow_offload: fix interaction with vrf slave
device
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>
---
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -84,7 +84,6 @@ struct flow_offload {
struct nf_flow_route {
struct {
struct dst_entry *dst;
- int ifindex;
} tuple[FLOW_OFFLOAD_DIR_MAX];
};
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offloa
{
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_offloa
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;
}
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -30,9 +30,11 @@ static int nft_flow_route(const struct n
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 n
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;
}
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 15 Mar 2018 18:21:43 +0100
Subject: [PATCH] netfilter: nf_flow_table: clean up and fix dst handling
dst handling in the code is inconsistent and possibly wrong. In my test,
skb_dst(skb) holds the dst entry after routing but before NAT, so the
code could possibly return the same dst entry for both directions of a
connection.
Additionally, there was some confusion over the dst entry vs the address
passed as parameter to rt_nexthop/rt6_nexthop.
Do an explicit dst lookup for both ends of the connection and always use
the source address for it. When running the IP hook, use the dst entry
for the opposite direction for determining the route.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -244,7 +244,7 @@ nf_flow_offload_ip_hook(void *priv, stru
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache;
+ rt = (struct rtable *)flow->tuplehash[!dir].tuple.dst_cache;
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
return NF_ACCEPT;
@@ -464,7 +464,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache;
+ rt = (struct rt6_info *)flow->tuplehash[!dir].tuple.dst_cache;
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
return NF_ACCEPT;
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -17,13 +17,11 @@ struct nft_flow_offload {
struct nft_flowtable *flowtable;
};
-static int nft_flow_route(const struct nft_pktinfo *pkt,
- const struct nf_conn *ct,
- struct nf_flow_route *route,
- enum ip_conntrack_dir dir)
+static struct dst_entry *
+nft_flow_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir,
+ const struct nft_pktinfo *pkt)
{
- struct dst_entry *this_dst = skb_dst(pkt->skb);
- struct dst_entry *other_dst = NULL;
+ struct dst_entry *dst;
struct flowi fl;
memset(&fl, 0, sizeof(fl));
@@ -38,8 +36,21 @@ static int nft_flow_route(const struct n
break;
}
- nf_route(nft_net(pkt), &other_dst, &fl, false, nft_pf(pkt));
- if (!other_dst)
+ nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt));
+
+ return dst;
+}
+
+static int nft_flow_route(const struct nft_pktinfo *pkt,
+ const struct nf_conn *ct,
+ struct nf_flow_route *route,
+ enum ip_conntrack_dir dir)
+{
+ struct dst_entry *this_dst, *other_dst;
+
+ this_dst = nft_flow_dst(ct, dir, pkt);
+ other_dst = nft_flow_dst(ct, !dir, pkt);
+ if (!this_dst || !other_dst)
return -ENOENT;
route->tuple[dir].dst = this_dst;
--- a/include/net/netfilter/nf_flow_table.h --- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h
@@ -164,6 +164,8 @@ struct nf_flow_table_hw { @@ -163,6 +163,8 @@ struct nf_flow_table_hw {
int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload); int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload);
void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload); void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload);
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
struct flow_offload_entry { struct flow_offload_entry {
struct flow_offload flow; struct flow_offload flow;
@@ -151,6 +152,22 @@ void flow_offload_free(struct flow_offlo @@ -152,6 +153,22 @@ void flow_offload_free(struct flow_offlo
} }
EXPORT_SYMBOL_GPL(flow_offload_free); EXPORT_SYMBOL_GPL(flow_offload_free);
......
...@@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null --- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c +++ b/net/netfilter/xt_FLOWOFFLOAD.c
@@ -0,0 +1,403 @@ @@ -0,0 +1,421 @@
+/* +/*
+ * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
+ * + *
...@@ -112,8 +112,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -112,8 +112,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+#include <linux/netfilter/xt_FLOWOFFLOAD.h> +#include <linux/netfilter/xt_FLOWOFFLOAD.h>
+#include <net/ip.h> +#include <net/ip.h>
+#include <net/netfilter/nf_conntrack.h> +#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_flow_table.h> +#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_helper.h> +#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_flow_table.h>
+ +
+static struct nf_flowtable nf_flowtable; +static struct nf_flowtable nf_flowtable;
+static HLIST_HEAD(hooks); +static HLIST_HEAD(hooks);
...@@ -280,21 +281,24 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -280,21 +281,24 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+} +}
+ +
+static bool +static bool
+xt_flowoffload_skip(struct sk_buff *skb) +xt_flowoffload_skip(struct sk_buff *skb, int family)
+{ +{
+ struct ip_options *opt = &(IPCB(skb)->opt);
+
+ if (unlikely(opt->optlen))
+ return true;
+ if (skb_sec_path(skb)) + if (skb_sec_path(skb))
+ return true; + return true;
+ +
+ if (family == NFPROTO_IPV4) {
+ const struct ip_options *opt = &(IPCB(skb)->opt);
+
+ if (unlikely(opt->optlen))
+ return true;
+ }
+
+ return false; + return false;
+} +}
+ +
+static struct dst_entry * +static struct dst_entry *
+xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir, +xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir,
+ const struct xt_action_param *par) + const struct xt_action_param *par, int ifindex)
+{ +{
+ struct dst_entry *dst = NULL; + struct dst_entry *dst = NULL;
+ struct flowi fl; + struct flowi fl;
...@@ -303,10 +307,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -303,10 +307,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ switch (xt_family(par)) { + switch (xt_family(par)) {
+ case NFPROTO_IPV4: + case NFPROTO_IPV4:
+ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; + fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+ fl.u.ip4.flowi4_oif = ifindex;
+ break; + break;
+ case NFPROTO_IPV6: + case NFPROTO_IPV6:
+ fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6; + fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6;
+ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; + fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+ fl.u.ip6.flowi6_oif = ifindex;
+ break; + break;
+ } + }
+ +
...@@ -322,8 +328,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -322,8 +328,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+{ +{
+ struct dst_entry *this_dst, *other_dst; + struct dst_entry *this_dst, *other_dst;
+ +
+ this_dst = xt_flowoffload_dst(ct, dir, par); + this_dst = xt_flowoffload_dst(ct, !dir, par, xt_out(par)->ifindex);
+ other_dst = xt_flowoffload_dst(ct, !dir, par); + other_dst = xt_flowoffload_dst(ct, dir, par, xt_in(par)->ifindex);
+ if (!this_dst || !other_dst) + if (!this_dst || !other_dst)
+ return -ENOENT; + return -ENOENT;
+ +
...@@ -331,9 +337,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -331,9 +337,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ return -EINVAL; + return -EINVAL;
+ +
+ route->tuple[dir].dst = this_dst; + route->tuple[dir].dst = this_dst;
+ route->tuple[dir].ifindex = xt_in(par)->ifindex;
+ route->tuple[!dir].dst = other_dst; + route->tuple[!dir].dst = other_dst;
+ route->tuple[!dir].ifindex = xt_out(par)->ifindex;
+ +
+ return 0; + return 0;
+} +}
...@@ -342,14 +346,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -342,14 +346,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) +flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{ +{
+ const struct xt_flowoffload_target_info *info = par->targinfo; + const struct xt_flowoffload_target_info *info = par->targinfo;
+ struct tcphdr _tcph, *tcph = NULL;
+ enum ip_conntrack_info ctinfo; + enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir; + enum ip_conntrack_dir dir;
+ struct nf_flow_route route; + struct nf_flow_route route;
+ struct flow_offload *flow; + struct flow_offload *flow;
+ struct nf_conn *ct; + struct nf_conn *ct;
+ const struct nf_conn_help *help; + struct net *net;
+ +
+ if (xt_flowoffload_skip(skb)) + if (xt_flowoffload_skip(skb, xt_family(par)))
+ return XT_CONTINUE; + return XT_CONTINUE;
+ +
+ ct = nf_ct_get(skb, &ctinfo); + ct = nf_ct_get(skb, &ctinfo);
...@@ -360,6 +365,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -360,6 +365,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ case IPPROTO_TCP: + case IPPROTO_TCP:
+ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED)
+ return XT_CONTINUE; + return XT_CONTINUE;
+
+ tcph = skb_header_pointer(skb, par->thoff,
+ sizeof(_tcph), &_tcph);
+ if (unlikely(!tcph || tcph->fin || tcph->rst))
+ return XT_CONTINUE;
+ break; + break;
+ case IPPROTO_UDP: + case IPPROTO_UDP:
+ break; + break;
...@@ -367,12 +377,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -367,12 +377,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ return XT_CONTINUE; + return XT_CONTINUE;
+ } + }
+ +
+ help = nfct_help(ct); + if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) ||
+ if (help) + ct->status & IPS_SEQ_ADJUST)
+ return XT_CONTINUE; + return XT_CONTINUE;
+ +
+ if (ctinfo == IP_CT_NEW || + if (!nf_ct_is_confirmed(ct))
+ ctinfo == IP_CT_RELATED)
+ return XT_CONTINUE; + return XT_CONTINUE;
+ +
+ if (!xt_in(par) || !xt_out(par)) + if (!xt_in(par) || !xt_out(par))
...@@ -390,12 +399,21 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -390,12 +399,21 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ if (!flow) + if (!flow)
+ goto err_flow_alloc; + goto err_flow_alloc;
+ +
+ if (tcph) {
+ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ }
+
+ if (flow_offload_add(&nf_flowtable, flow) < 0) + if (flow_offload_add(&nf_flowtable, flow) < 0)
+ goto err_flow_add; + goto err_flow_add;
+ +
+ xt_flowoffload_check_device(xt_in(par)); + xt_flowoffload_check_device(xt_in(par));
+ xt_flowoffload_check_device(xt_out(par)); + xt_flowoffload_check_device(xt_out(par));
+ +
+ net = read_pnet(&nf_flowtable.ft_net);
+ if (!net)
+ write_pnet(&nf_flowtable.ft_net, xt_net(par));
+
+ if (info->flags & XT_FLOWOFFLOAD_HW) + if (info->flags & XT_FLOWOFFLOAD_HW)
+ nf_flow_offload_hw_add(xt_net(par), flow, ct); + nf_flow_offload_hw_add(xt_net(par), flow, ct);
+ +
......
...@@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null --- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c +++ b/net/netfilter/xt_FLOWOFFLOAD.c
@@ -0,0 +1,366 @@ @@ -0,0 +1,421 @@
+/* +/*
+ * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
+ * + *
...@@ -112,6 +112,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -112,6 +112,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+#include <linux/netfilter/xt_FLOWOFFLOAD.h> +#include <linux/netfilter/xt_FLOWOFFLOAD.h>
+#include <net/ip.h> +#include <net/ip.h>
+#include <net/netfilter/nf_conntrack.h> +#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_flow_table.h> +#include <net/netfilter/nf_flow_table.h>
+ +
+static struct nf_flowtable nf_flowtable; +static struct nf_flowtable nf_flowtable;
...@@ -279,21 +281,24 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -279,21 +281,24 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+} +}
+ +
+static bool +static bool
+xt_flowoffload_skip(struct sk_buff *skb) +xt_flowoffload_skip(struct sk_buff *skb, int family)
+{ +{
+ struct ip_options *opt = &(IPCB(skb)->opt);
+
+ if (unlikely(opt->optlen))
+ return true;
+ if (skb_sec_path(skb)) + if (skb_sec_path(skb))
+ return true; + return true;
+ +
+ if (family == NFPROTO_IPV4) {
+ const struct ip_options *opt = &(IPCB(skb)->opt);
+
+ if (unlikely(opt->optlen))
+ return true;
+ }
+
+ return false; + return false;
+} +}
+ +
+static struct dst_entry * +static struct dst_entry *
+xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir, +xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir,
+ const struct xt_action_param *par) + const struct xt_action_param *par, int ifindex)
+{ +{
+ struct dst_entry *dst = NULL; + struct dst_entry *dst = NULL;
+ struct flowi fl; + struct flowi fl;
...@@ -302,10 +307,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -302,10 +307,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ switch (xt_family(par)) { + switch (xt_family(par)) {
+ case NFPROTO_IPV4: + case NFPROTO_IPV4:
+ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; + fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+ fl.u.ip4.flowi4_oif = ifindex;
+ break; + break;
+ case NFPROTO_IPV6: + case NFPROTO_IPV6:
+ fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6; + fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6;
+ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; + fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+ fl.u.ip6.flowi6_oif = ifindex;
+ break; + break;
+ } + }
+ +
...@@ -321,8 +328,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -321,8 +328,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+{ +{
+ struct dst_entry *this_dst, *other_dst; + struct dst_entry *this_dst, *other_dst;
+ +
+ this_dst = xt_flowoffload_dst(ct, dir, par); + this_dst = xt_flowoffload_dst(ct, !dir, par, xt_out(par)->ifindex);
+ other_dst = xt_flowoffload_dst(ct, !dir, par); + other_dst = xt_flowoffload_dst(ct, dir, par, xt_in(par)->ifindex);
+ if (!this_dst || !other_dst) + if (!this_dst || !other_dst)
+ return -ENOENT; + return -ENOENT;
+ +
...@@ -339,13 +346,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -339,13 +346,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) +flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{ +{
+ const struct xt_flowoffload_target_info *info = par->targinfo; + const struct xt_flowoffload_target_info *info = par->targinfo;
+ struct tcphdr _tcph, *tcph = NULL;
+ enum ip_conntrack_info ctinfo; + enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir; + enum ip_conntrack_dir dir;
+ struct nf_flow_route route; + struct nf_flow_route route;
+ struct flow_offload *flow; + struct flow_offload *flow;
+ struct nf_conn *ct; + struct nf_conn *ct;
+ struct net *net;
+ +
+ if (xt_flowoffload_skip(skb)) + if (xt_flowoffload_skip(skb, xt_family(par)))
+ return XT_CONTINUE; + return XT_CONTINUE;
+ +
+ ct = nf_ct_get(skb, &ctinfo); + ct = nf_ct_get(skb, &ctinfo);
...@@ -356,6 +365,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -356,6 +365,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ case IPPROTO_TCP: + case IPPROTO_TCP:
+ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED)
+ return XT_CONTINUE; + return XT_CONTINUE;
+
+ tcph = skb_header_pointer(skb, par->thoff,
+ sizeof(_tcph), &_tcph);
+ if (unlikely(!tcph || tcph->fin || tcph->rst))
+ return XT_CONTINUE;
+ break; + break;
+ case IPPROTO_UDP: + case IPPROTO_UDP:
+ break; + break;
...@@ -363,11 +377,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -363,11 +377,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ return XT_CONTINUE; + return XT_CONTINUE;
+ } + }
+ +
+ if (test_bit(IPS_HELPER_BIT, &ct->status)) + if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) ||
+ ct->status & IPS_SEQ_ADJUST)
+ return XT_CONTINUE; + return XT_CONTINUE;
+ +
+ if (ctinfo == IP_CT_NEW || + if (!nf_ct_is_confirmed(ct))
+ ctinfo == IP_CT_RELATED)
+ return XT_CONTINUE; + return XT_CONTINUE;
+ +
+ if (!xt_in(par) || !xt_out(par)) + if (!xt_in(par) || !xt_out(par))
...@@ -385,12 +399,21 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -385,12 +399,21 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ if (!flow) + if (!flow)
+ goto err_flow_alloc; + goto err_flow_alloc;
+ +
+ if (tcph) {
+ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ }
+
+ if (flow_offload_add(&nf_flowtable, flow) < 0) + if (flow_offload_add(&nf_flowtable, flow) < 0)
+ goto err_flow_add; + goto err_flow_add;
+ +
+ xt_flowoffload_check_device(xt_in(par)); + xt_flowoffload_check_device(xt_in(par));
+ xt_flowoffload_check_device(xt_out(par)); + xt_flowoffload_check_device(xt_out(par));
+ +
+ net = read_pnet(&nf_flowtable.ft_net);
+ if (!net)
+ write_pnet(&nf_flowtable.ft_net, xt_net(par));
+
+ if (info->flags & XT_FLOWOFFLOAD_HW) + if (info->flags & XT_FLOWOFFLOAD_HW)
+ nf_flow_offload_hw_add(xt_net(par), flow, ct); + nf_flow_offload_hw_add(xt_net(par), flow, ct);
+ +
...@@ -439,10 +462,41 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -439,10 +462,41 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ nf_flow_table_free(table); + nf_flow_table_free(table);
+} +}
+ +
+static int flow_offload_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct xt_flowoffload_hook *hook = NULL;
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+ if (event != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+
+ spin_lock_bh(&hooks_lock);
+ hook = flow_offload_lookup_hook(dev);
+ if (hook) {
+ hlist_del(&hook->list);
+ }
+ spin_unlock_bh(&hooks_lock);
+ if (hook) {
+ nf_unregister_net_hook(hook->net, &hook->ops);
+ kfree(hook);
+ }
+
+ nf_flow_table_cleanup(dev_net(dev), dev);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block flow_offload_netdev_notifier = {
+ .notifier_call = flow_offload_netdev_event,
+};
+
+static int __init xt_flowoffload_tg_init(void) +static int __init xt_flowoffload_tg_init(void)
+{ +{
+ int ret; + int ret;
+ +
+ register_netdevice_notifier(&flow_offload_netdev_notifier);
+
+ INIT_DELAYED_WORK(&hook_work, xt_flowoffload_hook_work); + INIT_DELAYED_WORK(&hook_work, xt_flowoffload_hook_work);
+ +
+ ret = xt_flowoffload_table_init(&nf_flowtable); + ret = xt_flowoffload_table_init(&nf_flowtable);
...@@ -460,6 +514,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -460,6 +514,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+{ +{
+ xt_unregister_target(&offload_tg_reg); + xt_unregister_target(&offload_tg_reg);
+ xt_flowoffload_table_cleanup(&nf_flowtable); + xt_flowoffload_table_cleanup(&nf_flowtable);
+ unregister_netdevice_notifier(&flow_offload_netdev_notifier);
+} +}
+ +
+MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL");
......
From ae56e27e30122f82d244f9eb35fcab8fa60e0d31 Mon Sep 17 00:00:00 2001
From: Chen Minqiang <ptpt52@gmail.com>
Date: Sun, 29 Apr 2018 14:08:57 +0800
Subject: [PATCH] cleanup offload hooks on netdev unregister
This should fix crashdump on reboot when FLOWOFFLOAD enabled
kmsg:
[ 84.188081] Workqueue: events_power_efficient xt_flowoffload_hook_work [xt_FLOWOFFLOAD]
[ 84.209326] task: ffff88000ecd0c80 task.stack: ffffc90000068000
[ 84.224706] RIP: 0010:__nf_unregister_net_hook+0x1/0x90
[ 84.242911] RSP: 0018:ffffc9000006be30 EFLAGS: 00010202
[ 84.257405] RAX: 0000000000000000 RBX: ffff88000c5b3228 RCX: 0000000100170001
[ 84.292175] RDX: ffff88000ecd0c80 RSI: ffff88000c5b3228 RDI: 6b6b6b6b6b6b6b6b
[ 84.305095] RBP: ffffc9000006be58 R08: ffff88000c5b3578 R09: ffff88000c5b3538
[ 84.325980] R10: ffffc9000006be50 R11: ffff88000fc1f310 R12: ffffffff81e6c580
[ 84.396514] R13: ffff88000d1723d0 R14: ffff88000ec0fc00 R15: 0000000000000000
[ 84.459500] FS: 0000000000000000(0000) GS:ffff88000fc00000(0000) knlGS:0000000000000000
[ 84.525121] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 84.565460] CR2: 0000000000a931d8 CR3: 0000000001e08006 CR4: 00000000000606f0
[ 84.638311] Call Trace:
[ 84.655229] ? nf_unregister_net_hook+0x88/0xd0
[ 84.706898] xt_flowoffload_hook_work+0x12a/0x17a [xt_FLOWOFFLOAD]
[ 84.765504] process_one_work+0x1c4/0x310
[ 84.799558] worker_thread+0x20b/0x3c0
[ 84.850119] kthread+0x112/0x120
[ 84.884839] ? process_one_work+0x310/0x310
[ 84.923571] ? kthread_create_on_node+0x40/0x40
[ 84.966100] ret_from_fork+0x35/0x40
[ 84.981738] Code: 41 5c 41 5d 41 5e 41 5f 5d c3 48 8b 05 c1 f1 99 00 55 48 89 e5 48 85 c0 75 02 0f 0b e8 b9 f6 30 00 5d c3 0f 1f 80 00 00 00 00 55 <0f> b7 0f 48 89 e5 48 89 c8 48 c1 e0 04 48 8d 54 07 08 31 c0 eb
[ 85.100453] RIP: __nf_unregister_net_hook+0x1/0x90 RSP: ffffc9000006be30
[ 85.111658] ---[ end trace 5c25a390045cac75 ]---
[ 85.124535] Kernel panic - not syncing: Fatal exception
Signed-off-by: Chen Minqiang <ptpt52@gmail.com>
---
net/netfilter/xt_FLOWOFFLOAD.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
--- a/net/netfilter/xt_FLOWOFFLOAD.c
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
@@ -343,10 +343,41 @@ static void xt_flowoffload_table_cleanup
nf_flow_table_free(table);
}
+static int flow_offload_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct xt_flowoffload_hook *hook = NULL;
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+ if (event != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+
+ spin_lock_bh(&hooks_lock);
+ hook = flow_offload_lookup_hook(dev);
+ if (hook) {
+ hlist_del(&hook->list);
+ }
+ spin_unlock_bh(&hooks_lock);
+ if (hook) {
+ nf_unregister_net_hook(hook->net, &hook->ops);
+ kfree(hook);
+ }
+
+ nf_flow_table_cleanup(dev_net(dev), dev);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block flow_offload_netdev_notifier = {
+ .notifier_call = flow_offload_netdev_event,
+};
+
static int __init xt_flowoffload_tg_init(void)
{
int ret;
+ register_netdevice_notifier(&flow_offload_netdev_notifier);
+
INIT_DELAYED_WORK(&hook_work, xt_flowoffload_hook_work);
ret = xt_flowoffload_table_init(&nf_flowtable);
@@ -364,6 +395,7 @@ static void __exit xt_flowoffload_tg_exi
{
xt_unregister_target(&offload_tg_reg);
xt_flowoffload_table_cleanup(&nf_flowtable);
+ unregister_netdevice_notifier(&flow_offload_netdev_notifier);
}
MODULE_LICENSE("GPL");
...@@ -85,7 +85,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -85,7 +85,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
struct flow_offload { struct flow_offload {
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
@@ -126,6 +133,22 @@ unsigned int nf_flow_offload_ip_hook(voi @@ -125,6 +132,22 @@ unsigned int nf_flow_offload_ip_hook(voi
unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state); const struct nf_hook_state *state);
...@@ -156,7 +156,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -156,7 +156,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
--- a/net/netfilter/nf_flow_table_core.c --- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c
@@ -218,10 +218,16 @@ int flow_offload_add(struct nf_flowtable @@ -219,10 +219,16 @@ int flow_offload_add(struct nf_flowtable
} }
EXPORT_SYMBOL_GPL(flow_offload_add); EXPORT_SYMBOL_GPL(flow_offload_add);
...@@ -173,7 +173,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -173,7 +173,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
rhashtable_remove_fast(&flow_table->rhashtable, rhashtable_remove_fast(&flow_table->rhashtable,
&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node,
@@ -236,6 +242,9 @@ static void flow_offload_del(struct nf_f @@ -237,6 +243,9 @@ static void flow_offload_del(struct nf_f
if (!(flow->flags & FLOW_OFFLOAD_TEARDOWN)) if (!(flow->flags & FLOW_OFFLOAD_TEARDOWN))
flow_offload_fixup_ct_state(e->ct); flow_offload_fixup_ct_state(e->ct);
...@@ -183,7 +183,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -183,7 +183,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
flow_offload_free(flow); flow_offload_free(flow);
} }
@@ -349,6 +358,9 @@ static int nf_flow_offload_gc_step(struc @@ -350,6 +359,9 @@ static int nf_flow_offload_gc_step(struc
if (!teardown) if (!teardown)
nf_ct_offload_timeout(flow); nf_ct_offload_timeout(flow);
...@@ -193,7 +193,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -193,7 +193,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
if (nf_flow_has_expired(flow) || teardown) if (nf_flow_has_expired(flow) || teardown)
flow_offload_del(flow_table, flow); flow_offload_del(flow_table, flow);
} }
@@ -484,10 +496,43 @@ int nf_flow_dnat_port(const struct flow_ @@ -485,10 +497,43 @@ int nf_flow_dnat_port(const struct flow_
} }
EXPORT_SYMBOL_GPL(nf_flow_dnat_port); EXPORT_SYMBOL_GPL(nf_flow_dnat_port);
...@@ -237,7 +237,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -237,7 +237,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc); INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc);
err = rhashtable_init(&flowtable->rhashtable, err = rhashtable_init(&flowtable->rhashtable,
@@ -525,6 +570,8 @@ static void nf_flow_table_iterate_cleanu @@ -526,6 +571,8 @@ static void nf_flow_table_iterate_cleanu
{ {
nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev);
flush_delayed_work(&flowtable->gc_work); flush_delayed_work(&flowtable->gc_work);
...@@ -246,7 +246,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -246,7 +246,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
} }
void nf_flow_table_cleanup(struct net *net, struct net_device *dev) void nf_flow_table_cleanup(struct net *net, struct net_device *dev)
@@ -538,6 +585,26 @@ void nf_flow_table_cleanup(struct net *n @@ -539,6 +586,26 @@ void nf_flow_table_cleanup(struct net *n
} }
EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); EXPORT_SYMBOL_GPL(nf_flow_table_cleanup);
...@@ -273,7 +273,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -273,7 +273,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
void nf_flow_table_free(struct nf_flowtable *flow_table) void nf_flow_table_free(struct nf_flowtable *flow_table)
{ {
mutex_lock(&flowtable_lock); mutex_lock(&flowtable_lock);
@@ -547,9 +614,58 @@ void nf_flow_table_free(struct nf_flowta @@ -548,9 +615,58 @@ void nf_flow_table_free(struct nf_flowta
nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
WARN_ON(!nf_flow_offload_gc_step(flow_table)); WARN_ON(!nf_flow_offload_gc_step(flow_table));
rhashtable_destroy(&flow_table->rhashtable); rhashtable_destroy(&flow_table->rhashtable);
...@@ -553,7 +553,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -553,7 +553,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);
--- a/net/netfilter/nft_flow_offload.c --- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c
@@ -121,6 +121,9 @@ static void nft_flow_offload_eval(const @@ -110,6 +110,9 @@ static void nft_flow_offload_eval(const
if (ret < 0) if (ret < 0)
goto err_flow_add; goto err_flow_add;
......
...@@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ...@@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
--- a/net/netfilter/nf_flow_table_core.c --- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c
@@ -358,7 +358,7 @@ static int nf_flow_offload_gc_step(struc @@ -359,7 +359,7 @@ static int nf_flow_offload_gc_step(struc
if (!teardown) if (!teardown)
nf_ct_offload_timeout(flow); nf_ct_offload_timeout(flow);
......
...@@ -552,7 +552,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> ...@@ -552,7 +552,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);
--- a/net/netfilter/nft_flow_offload.c --- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c
@@ -138,6 +138,9 @@ static void nft_flow_offload_eval(const @@ -127,6 +127,9 @@ static void nft_flow_offload_eval(const
if (ret < 0) if (ret < 0)
goto err_flow_add; goto err_flow_add;
......
...@@ -934,7 +934,7 @@ static int fe_poll_rx(struct napi_struct *napi, int budget, ...@@ -934,7 +934,7 @@ static int fe_poll_rx(struct napi_struct *napi, int budget,
skb->protocol = eth_type_trans(skb, netdev); skb->protocol = eth_type_trans(skb, netdev);
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX &&
RX_DMA_TAG & trxd.rxd2 && RX_DMA_VID(trxd.rxd3)) RX_DMA_VID(trxd.rxd3))
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
RX_DMA_VID(trxd.rxd3)); RX_DMA_VID(trxd.rxd3));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册