mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-19 11:16:32 +00:00
kernel: update flow offload patches to upstream version
Move patches to backport-5.10, since the series was accepted upstream Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
012a9aa00b
commit
f07fe36f22
@ -0,0 +1,98 @@
|
|||||||
|
From: Oz Shlomo <ozsh@nvidia.com>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:19 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: separate replace, destroy and
|
||||||
|
stats to different workqueues
|
||||||
|
|
||||||
|
Currently the flow table offload replace, destroy and stats work items are
|
||||||
|
executed on a single workqueue. As such, DESTROY and STATS commands may
|
||||||
|
be backloged after a burst of REPLACE work items. This scenario can bloat
|
||||||
|
up memory and may cause active connections to age.
|
||||||
|
|
||||||
|
Instatiate add, del and stats workqueues to avoid backlogs of non-dependent
|
||||||
|
actions. Provide sysfs control over the workqueue attributes, allowing
|
||||||
|
userspace applications to control the workqueue cpumask.
|
||||||
|
|
||||||
|
Signed-off-by: Oz Shlomo <ozsh@nvidia.com>
|
||||||
|
Reviewed-by: Paul Blakey <paulb@nvidia.com>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_offload.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_offload.c
|
||||||
|
@@ -13,7 +13,9 @@
|
||||||
|
#include <net/netfilter/nf_conntrack_core.h>
|
||||||
|
#include <net/netfilter/nf_conntrack_tuple.h>
|
||||||
|
|
||||||
|
-static struct workqueue_struct *nf_flow_offload_wq;
|
||||||
|
+static struct workqueue_struct *nf_flow_offload_add_wq;
|
||||||
|
+static struct workqueue_struct *nf_flow_offload_del_wq;
|
||||||
|
+static struct workqueue_struct *nf_flow_offload_stats_wq;
|
||||||
|
|
||||||
|
struct flow_offload_work {
|
||||||
|
struct list_head list;
|
||||||
|
@@ -826,7 +828,12 @@ static void flow_offload_work_handler(st
|
||||||
|
|
||||||
|
static void flow_offload_queue_work(struct flow_offload_work *offload)
|
||||||
|
{
|
||||||
|
- queue_work(nf_flow_offload_wq, &offload->work);
|
||||||
|
+ if (offload->cmd == FLOW_CLS_REPLACE)
|
||||||
|
+ queue_work(nf_flow_offload_add_wq, &offload->work);
|
||||||
|
+ else if (offload->cmd == FLOW_CLS_DESTROY)
|
||||||
|
+ queue_work(nf_flow_offload_del_wq, &offload->work);
|
||||||
|
+ else
|
||||||
|
+ queue_work(nf_flow_offload_stats_wq, &offload->work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct flow_offload_work *
|
||||||
|
@@ -898,8 +905,11 @@ void nf_flow_offload_stats(struct nf_flo
|
||||||
|
|
||||||
|
void nf_flow_table_offload_flush(struct nf_flowtable *flowtable)
|
||||||
|
{
|
||||||
|
- if (nf_flowtable_hw_offload(flowtable))
|
||||||
|
- flush_workqueue(nf_flow_offload_wq);
|
||||||
|
+ if (nf_flowtable_hw_offload(flowtable)) {
|
||||||
|
+ flush_workqueue(nf_flow_offload_add_wq);
|
||||||
|
+ flush_workqueue(nf_flow_offload_del_wq);
|
||||||
|
+ flush_workqueue(nf_flow_offload_stats_wq);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,
|
||||||
|
@@ -1011,15 +1021,33 @@ EXPORT_SYMBOL_GPL(nf_flow_table_offload_
|
||||||
|
|
||||||
|
int nf_flow_table_offload_init(void)
|
||||||
|
{
|
||||||
|
- nf_flow_offload_wq = alloc_workqueue("nf_flow_table_offload",
|
||||||
|
- WQ_UNBOUND, 0);
|
||||||
|
- if (!nf_flow_offload_wq)
|
||||||
|
+ nf_flow_offload_add_wq = alloc_workqueue("nf_ft_offload_add",
|
||||||
|
+ WQ_UNBOUND | WQ_SYSFS, 0);
|
||||||
|
+ if (!nf_flow_offload_add_wq)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
+ nf_flow_offload_del_wq = alloc_workqueue("nf_ft_offload_del",
|
||||||
|
+ WQ_UNBOUND | WQ_SYSFS, 0);
|
||||||
|
+ if (!nf_flow_offload_del_wq)
|
||||||
|
+ goto err_del_wq;
|
||||||
|
+
|
||||||
|
+ nf_flow_offload_stats_wq = alloc_workqueue("nf_ft_offload_stats",
|
||||||
|
+ WQ_UNBOUND | WQ_SYSFS, 0);
|
||||||
|
+ if (!nf_flow_offload_stats_wq)
|
||||||
|
+ goto err_stats_wq;
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+err_stats_wq:
|
||||||
|
+ destroy_workqueue(nf_flow_offload_del_wq);
|
||||||
|
+err_del_wq:
|
||||||
|
+ destroy_workqueue(nf_flow_offload_add_wq);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nf_flow_table_offload_exit(void)
|
||||||
|
{
|
||||||
|
- destroy_workqueue(nf_flow_offload_wq);
|
||||||
|
+ destroy_workqueue(nf_flow_offload_add_wq);
|
||||||
|
+ destroy_workqueue(nf_flow_offload_del_wq);
|
||||||
|
+ destroy_workqueue(nf_flow_offload_stats_wq);
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:20 +0100
|
||||||
|
Subject: [PATCH] netfilter: Fix fall-through warnings for Clang
|
||||||
|
|
||||||
|
In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple
|
||||||
|
warnings by explicitly adding multiple break statements instead of just
|
||||||
|
letting the code fall through to the next case.
|
||||||
|
|
||||||
|
Link: https://github.com/KSPP/linux/issues/115
|
||||||
|
Acked-by: Florian Westphal <fw@strlen.de>
|
||||||
|
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_conntrack_proto_dccp.c
|
||||||
|
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
|
||||||
|
@@ -397,6 +397,7 @@ dccp_new(struct nf_conn *ct, const struc
|
||||||
|
msg = "not picking up existing connection ";
|
||||||
|
goto out_invalid;
|
||||||
|
}
|
||||||
|
+ break;
|
||||||
|
case CT_DCCP_REQUEST:
|
||||||
|
break;
|
||||||
|
case CT_DCCP_INVALID:
|
||||||
|
--- a/net/netfilter/nf_tables_api.c
|
||||||
|
+++ b/net/netfilter/nf_tables_api.c
|
||||||
|
@@ -8364,6 +8364,7 @@ static int nf_tables_check_loops(const s
|
||||||
|
data->verdict.chain);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--- a/net/netfilter/nft_ct.c
|
||||||
|
+++ b/net/netfilter/nft_ct.c
|
||||||
|
@@ -528,6 +528,7 @@ static void __nft_ct_set_destroy(const s
|
||||||
|
case NFT_CT_ZONE:
|
||||||
|
if (--nft_ct_pcpu_template_refcnt == 0)
|
||||||
|
nft_ct_tmpl_put_pcpu();
|
||||||
|
+ break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
@ -0,0 +1,22 @@
|
|||||||
|
From: YueHaibing <yuehaibing@huawei.com>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:21 +0100
|
||||||
|
Subject: [PATCH] netfilter: conntrack: Remove unused variable
|
||||||
|
declaration
|
||||||
|
|
||||||
|
commit e97c3e278e95 ("tproxy: split off ipv6 defragmentation to a separate
|
||||||
|
module") left behind this.
|
||||||
|
|
||||||
|
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
|
||||||
|
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
|
||||||
|
@@ -4,7 +4,4 @@
|
||||||
|
|
||||||
|
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
|
||||||
|
|
||||||
|
-#include <linux/sysctl.h>
|
||||||
|
-extern struct ctl_table nf_ct_ipv6_sysctl_table[];
|
||||||
|
-
|
||||||
|
#endif /* _NF_CONNTRACK_IPV6_H*/
|
@ -0,0 +1,291 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:22 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: consolidate
|
||||||
|
skb_try_make_writable() call
|
||||||
|
|
||||||
|
Fetch the layer 4 header size to be mangled by NAT when building the
|
||||||
|
tuple, then use it to make writable the network and the transport
|
||||||
|
headers. After this update, the NAT routines now assumes that the skbuff
|
||||||
|
area is writable. Do the pointer refetch only after the single
|
||||||
|
skb_try_make_writable() call.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_core.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_core.c
|
||||||
|
@@ -395,9 +395,6 @@ static int nf_flow_nat_port_tcp(struct s
|
||||||
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
tcph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false);
|
||||||
|
|
||||||
|
@@ -409,9 +406,6 @@ static int nf_flow_nat_port_udp(struct s
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
udph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||||
|
inet_proto_csum_replace2(&udph->check, skb, port,
|
||||||
|
@@ -447,9 +441,6 @@ int nf_flow_snat_port(const struct flow_
|
||||||
|
struct flow_ports *hdr;
|
||||||
|
__be16 port, new_port;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*hdr)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
hdr = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
|
||||||
|
switch (dir) {
|
||||||
|
@@ -478,9 +469,6 @@ int nf_flow_dnat_port(const struct flow_
|
||||||
|
struct flow_ports *hdr;
|
||||||
|
__be16 port, new_port;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*hdr)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
hdr = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
|
||||||
|
switch (dir) {
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -39,9 +39,6 @@ static int nf_flow_nat_ip_tcp(struct sk_
|
||||||
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
tcph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true);
|
||||||
|
|
||||||
|
@@ -53,9 +50,6 @@ static int nf_flow_nat_ip_udp(struct sk_
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
udph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||||
|
inet_proto_csum_replace4(&udph->check, skb, addr,
|
||||||
|
@@ -136,19 +130,17 @@ static int nf_flow_dnat_ip(const struct
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
|
||||||
|
- unsigned int thoff, enum flow_offload_tuple_dir dir)
|
||||||
|
+ unsigned int thoff, enum flow_offload_tuple_dir dir,
|
||||||
|
+ struct iphdr *iph)
|
||||||
|
{
|
||||||
|
- struct iphdr *iph = ip_hdr(skb);
|
||||||
|
-
|
||||||
|
if (test_bit(NF_FLOW_SNAT, &flow->flags) &&
|
||||||
|
(nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
|
||||||
|
- nf_flow_snat_ip(flow, skb, ip_hdr(skb), thoff, dir) < 0))
|
||||||
|
+ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
- iph = ip_hdr(skb);
|
||||||
|
if (test_bit(NF_FLOW_DNAT, &flow->flags) &&
|
||||||
|
(nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
|
||||||
|
- nf_flow_dnat_ip(flow, skb, ip_hdr(skb), thoff, dir) < 0))
|
||||||
|
+ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -160,10 +152,10 @@ static bool ip_has_options(unsigned int
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
||||||
|
- struct flow_offload_tuple *tuple)
|
||||||
|
+ struct flow_offload_tuple *tuple, u32 *hdrsize)
|
||||||
|
{
|
||||||
|
- unsigned int thoff, hdrsize;
|
||||||
|
struct flow_ports *ports;
|
||||||
|
+ unsigned int thoff;
|
||||||
|
struct iphdr *iph;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||||
|
@@ -178,10 +170,10 @@ static int nf_flow_tuple_ip(struct sk_bu
|
||||||
|
|
||||||
|
switch (iph->protocol) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
- hdrsize = sizeof(struct tcphdr);
|
||||||
|
+ *hdrsize = sizeof(struct tcphdr);
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
- hdrsize = sizeof(struct udphdr);
|
||||||
|
+ *hdrsize = sizeof(struct udphdr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
@@ -191,7 +183,7 @@ static int nf_flow_tuple_ip(struct sk_bu
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
thoff = iph->ihl * 4;
|
||||||
|
- if (!pskb_may_pull(skb, thoff + hdrsize))
|
||||||
|
+ if (!pskb_may_pull(skb, thoff + *hdrsize))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
iph = ip_hdr(skb);
|
||||||
|
@@ -252,11 +244,12 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
unsigned int thoff;
|
||||||
|
struct iphdr *iph;
|
||||||
|
__be32 nexthop;
|
||||||
|
+ u32 hdrsize;
|
||||||
|
|
||||||
|
if (skb->protocol != htons(ETH_P_IP))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0)
|
||||||
|
+ if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize) < 0)
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
tuplehash = flow_offload_lookup(flow_table, &tuple);
|
||||||
|
@@ -271,11 +264,13 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, sizeof(*iph)))
|
||||||
|
+ iph = ip_hdr(skb);
|
||||||
|
+ thoff = iph->ihl * 4;
|
||||||
|
+ if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
- thoff = ip_hdr(skb)->ihl * 4;
|
||||||
|
- if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
|
||||||
|
+ iph = ip_hdr(skb);
|
||||||
|
+ if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
flow_offload_refresh(flow_table, flow);
|
||||||
|
@@ -285,10 +280,9 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
|
||||||
|
+ if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0)
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
- iph = ip_hdr(skb);
|
||||||
|
ip_decrease_ttl(iph);
|
||||||
|
skb->tstamp = 0;
|
||||||
|
|
||||||
|
@@ -317,9 +311,6 @@ static int nf_flow_nat_ipv6_tcp(struct s
|
||||||
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
tcph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32,
|
||||||
|
new_addr->s6_addr32, true);
|
||||||
|
@@ -333,9 +324,6 @@ static int nf_flow_nat_ipv6_udp(struct s
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
udph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||||
|
inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32,
|
||||||
|
@@ -417,31 +405,30 @@ static int nf_flow_dnat_ipv6(const struc
|
||||||
|
|
||||||
|
static int nf_flow_nat_ipv6(const struct flow_offload *flow,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
- enum flow_offload_tuple_dir dir)
|
||||||
|
+ enum flow_offload_tuple_dir dir,
|
||||||
|
+ struct ipv6hdr *ip6h)
|
||||||
|
{
|
||||||
|
- struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||||
|
unsigned int thoff = sizeof(*ip6h);
|
||||||
|
|
||||||
|
if (test_bit(NF_FLOW_SNAT, &flow->flags) &&
|
||||||
|
(nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 ||
|
||||||
|
- nf_flow_snat_ipv6(flow, skb, ipv6_hdr(skb), thoff, dir) < 0))
|
||||||
|
+ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
- ip6h = ipv6_hdr(skb);
|
||||||
|
if (test_bit(NF_FLOW_DNAT, &flow->flags) &&
|
||||||
|
(nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 ||
|
||||||
|
- nf_flow_dnat_ipv6(flow, skb, ipv6_hdr(skb), thoff, dir) < 0))
|
||||||
|
+ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
||||||
|
- struct flow_offload_tuple *tuple)
|
||||||
|
+ struct flow_offload_tuple *tuple, u32 *hdrsize)
|
||||||
|
{
|
||||||
|
- unsigned int thoff, hdrsize;
|
||||||
|
struct flow_ports *ports;
|
||||||
|
struct ipv6hdr *ip6h;
|
||||||
|
+ unsigned int thoff;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, sizeof(*ip6h)))
|
||||||
|
return -1;
|
||||||
|
@@ -450,10 +437,10 @@ static int nf_flow_tuple_ipv6(struct sk_
|
||||||
|
|
||||||
|
switch (ip6h->nexthdr) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
- hdrsize = sizeof(struct tcphdr);
|
||||||
|
+ *hdrsize = sizeof(struct tcphdr);
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
- hdrsize = sizeof(struct udphdr);
|
||||||
|
+ *hdrsize = sizeof(struct udphdr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
@@ -463,7 +450,7 @@ static int nf_flow_tuple_ipv6(struct sk_
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
thoff = sizeof(*ip6h);
|
||||||
|
- if (!pskb_may_pull(skb, thoff + hdrsize))
|
||||||
|
+ if (!pskb_may_pull(skb, thoff + *hdrsize))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ip6h = ipv6_hdr(skb);
|
||||||
|
@@ -493,11 +480,12 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
struct net_device *outdev;
|
||||||
|
struct ipv6hdr *ip6h;
|
||||||
|
struct rt6_info *rt;
|
||||||
|
+ u32 hdrsize;
|
||||||
|
|
||||||
|
if (skb->protocol != htons(ETH_P_IPV6))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0)
|
||||||
|
+ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize) < 0)
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
tuplehash = flow_offload_lookup(flow_table, &tuple);
|
||||||
|
@@ -523,13 +511,13 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, sizeof(*ip6h)))
|
||||||
|
+ if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize))
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
- if (nf_flow_nat_ipv6(flow, skb, dir) < 0)
|
||||||
|
+ ip6h = ipv6_hdr(skb);
|
||||||
|
+ if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0)
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
- ip6h = ipv6_hdr(skb);
|
||||||
|
ip6h->hop_limit--;
|
||||||
|
skb->tstamp = 0;
|
||||||
|
|
@ -0,0 +1,35 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:23 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: move skb_try_make_writable()
|
||||||
|
before NAT in IPv4
|
||||||
|
|
||||||
|
For consistency with the IPv6 flowtable datapath and to make sure the
|
||||||
|
skbuff is writable right before the NAT header updates.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -266,10 +266,6 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
|
||||||
|
iph = ip_hdr(skb);
|
||||||
|
thoff = iph->ihl * 4;
|
||||||
|
- if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||||
|
- return NF_DROP;
|
||||||
|
-
|
||||||
|
- iph = ip_hdr(skb);
|
||||||
|
if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
@@ -280,6 +276,10 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||||
|
+ return NF_DROP;
|
||||||
|
+
|
||||||
|
+ iph = ip_hdr(skb);
|
||||||
|
if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0)
|
||||||
|
return NF_DROP;
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:24 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: move FLOW_OFFLOAD_DIR_MAX away
|
||||||
|
from enumeration
|
||||||
|
|
||||||
|
This allows to remove the default case which should not ever happen and
|
||||||
|
that was added to avoid gcc warnings on unhandled FLOW_OFFLOAD_DIR_MAX
|
||||||
|
enumeration case.
|
||||||
|
|
||||||
|
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
|
||||||
|
@@ -86,8 +86,8 @@ static inline bool nf_flowtable_hw_offlo
|
||||||
|
enum flow_offload_tuple_dir {
|
||||||
|
FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL,
|
||||||
|
FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY,
|
||||||
|
- FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX
|
||||||
|
};
|
||||||
|
+#define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX
|
||||||
|
|
||||||
|
struct flow_offload_tuple {
|
||||||
|
union {
|
||||||
|
--- a/net/netfilter/nf_flow_table_core.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_core.c
|
||||||
|
@@ -454,8 +454,6 @@ int nf_flow_snat_port(const struct flow_
|
||||||
|
new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port;
|
||||||
|
hdr->dest = new_port;
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nf_flow_nat_port(skb, thoff, protocol, port, new_port);
|
||||||
|
@@ -482,8 +480,6 @@ int nf_flow_dnat_port(const struct flow_
|
||||||
|
new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port;
|
||||||
|
hdr->source = new_port;
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nf_flow_nat_port(skb, thoff, protocol, port, new_port);
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -96,8 +96,6 @@ static int nf_flow_snat_ip(const struct
|
||||||
|
new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr;
|
||||||
|
iph->daddr = new_addr;
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
csum_replace4(&iph->check, addr, new_addr);
|
||||||
|
|
||||||
|
@@ -121,8 +119,6 @@ static int nf_flow_dnat_ip(const struct
|
||||||
|
new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr;
|
||||||
|
iph->saddr = new_addr;
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
csum_replace4(&iph->check, addr, new_addr);
|
||||||
|
|
||||||
|
@@ -371,8 +367,6 @@ static int nf_flow_snat_ipv6(const struc
|
||||||
|
new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6;
|
||||||
|
ip6h->daddr = new_addr;
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
|
||||||
|
@@ -396,8 +390,6 @@ static int nf_flow_dnat_ipv6(const struc
|
||||||
|
new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6;
|
||||||
|
ip6h->saddr = new_addr;
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
|
@ -0,0 +1,394 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:25 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: fast NAT functions never fail
|
||||||
|
|
||||||
|
Simplify existing fast NAT routines by returning void. After the
|
||||||
|
skb_try_make_writable() call consolidation, these routines cannot ever
|
||||||
|
fail.
|
||||||
|
|
||||||
|
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
|
||||||
|
@@ -229,12 +229,12 @@ void nf_flow_table_free(struct nf_flowta
|
||||||
|
|
||||||
|
void flow_offload_teardown(struct flow_offload *flow);
|
||||||
|
|
||||||
|
-int nf_flow_snat_port(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- u8 protocol, enum flow_offload_tuple_dir dir);
|
||||||
|
-int nf_flow_dnat_port(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- u8 protocol, enum flow_offload_tuple_dir dir);
|
||||||
|
+void nf_flow_snat_port(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ u8 protocol, enum flow_offload_tuple_dir dir);
|
||||||
|
+void nf_flow_dnat_port(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ u8 protocol, enum flow_offload_tuple_dir dir);
|
||||||
|
|
||||||
|
struct flow_ports {
|
||||||
|
__be16 source, dest;
|
||||||
|
--- a/net/netfilter/nf_flow_table_core.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_core.c
|
||||||
|
@@ -389,20 +389,17 @@ static void nf_flow_offload_work_gc(stru
|
||||||
|
queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
-static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- __be16 port, __be16 new_port)
|
||||||
|
+static void nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ __be16 port, __be16 new_port)
|
||||||
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
tcph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- __be16 port, __be16 new_port)
|
||||||
|
+static void nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ __be16 port, __be16 new_port)
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
@@ -413,30 +410,24 @@ static int nf_flow_nat_port_udp(struct s
|
||||||
|
if (!udph->check)
|
||||||
|
udph->check = CSUM_MANGLED_0;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- u8 protocol, __be16 port, __be16 new_port)
|
||||||
|
+static void nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ u8 protocol, __be16 port, __be16 new_port)
|
||||||
|
{
|
||||||
|
switch (protocol) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
- if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_port_tcp(skb, thoff, port, new_port);
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
- if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_port_udp(skb, thoff, port, new_port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int nf_flow_snat_port(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- u8 protocol, enum flow_offload_tuple_dir dir)
|
||||||
|
+void nf_flow_snat_port(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ u8 protocol, enum flow_offload_tuple_dir dir)
|
||||||
|
{
|
||||||
|
struct flow_ports *hdr;
|
||||||
|
__be16 port, new_port;
|
||||||
|
@@ -456,13 +447,13 @@ int nf_flow_snat_port(const struct flow_
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return nf_flow_nat_port(skb, thoff, protocol, port, new_port);
|
||||||
|
+ nf_flow_nat_port(skb, thoff, protocol, port, new_port);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nf_flow_snat_port);
|
||||||
|
|
||||||
|
-int nf_flow_dnat_port(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- u8 protocol, enum flow_offload_tuple_dir dir)
|
||||||
|
+void nf_flow_dnat_port(const struct flow_offload *flow, struct sk_buff *skb,
|
||||||
|
+ unsigned int thoff, u8 protocol,
|
||||||
|
+ enum flow_offload_tuple_dir dir)
|
||||||
|
{
|
||||||
|
struct flow_ports *hdr;
|
||||||
|
__be16 port, new_port;
|
||||||
|
@@ -482,7 +473,7 @@ int nf_flow_dnat_port(const struct flow_
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return nf_flow_nat_port(skb, thoff, protocol, port, new_port);
|
||||||
|
+ nf_flow_nat_port(skb, thoff, protocol, port, new_port);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nf_flow_dnat_port);
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -34,19 +34,17 @@ static int nf_flow_state_check(struct fl
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- __be32 addr, __be32 new_addr)
|
||||||
|
+static void nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ __be32 addr, __be32 new_addr)
|
||||||
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
tcph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- __be32 addr, __be32 new_addr)
|
||||||
|
+static void nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ __be32 addr, __be32 new_addr)
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
@@ -57,31 +55,25 @@ static int nf_flow_nat_ip_udp(struct sk_
|
||||||
|
if (!udph->check)
|
||||||
|
udph->check = CSUM_MANGLED_0;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph,
|
||||||
|
- unsigned int thoff, __be32 addr,
|
||||||
|
- __be32 new_addr)
|
||||||
|
+static void nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph,
|
||||||
|
+ unsigned int thoff, __be32 addr,
|
||||||
|
+ __be32 new_addr)
|
||||||
|
{
|
||||||
|
switch (iph->protocol) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
- if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr);
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
- if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_ip_udp(skb, thoff, addr, new_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb,
|
||||||
|
- struct iphdr *iph, unsigned int thoff,
|
||||||
|
- enum flow_offload_tuple_dir dir)
|
||||||
|
+static void nf_flow_snat_ip(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, struct iphdr *iph,
|
||||||
|
+ unsigned int thoff, enum flow_offload_tuple_dir dir)
|
||||||
|
{
|
||||||
|
__be32 addr, new_addr;
|
||||||
|
|
||||||
|
@@ -99,12 +91,12 @@ static int nf_flow_snat_ip(const struct
|
||||||
|
}
|
||||||
|
csum_replace4(&iph->check, addr, new_addr);
|
||||||
|
|
||||||
|
- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
|
||||||
|
+ nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb,
|
||||||
|
- struct iphdr *iph, unsigned int thoff,
|
||||||
|
- enum flow_offload_tuple_dir dir)
|
||||||
|
+static void nf_flow_dnat_ip(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, struct iphdr *iph,
|
||||||
|
+ unsigned int thoff, enum flow_offload_tuple_dir dir)
|
||||||
|
{
|
||||||
|
__be32 addr, new_addr;
|
||||||
|
|
||||||
|
@@ -122,24 +114,21 @@ static int nf_flow_dnat_ip(const struct
|
||||||
|
}
|
||||||
|
csum_replace4(&iph->check, addr, new_addr);
|
||||||
|
|
||||||
|
- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
|
||||||
|
+ nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
|
||||||
|
+static void nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
|
||||||
|
unsigned int thoff, enum flow_offload_tuple_dir dir,
|
||||||
|
struct iphdr *iph)
|
||||||
|
{
|
||||||
|
- if (test_bit(NF_FLOW_SNAT, &flow->flags) &&
|
||||||
|
- (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
|
||||||
|
- nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- if (test_bit(NF_FLOW_DNAT, &flow->flags) &&
|
||||||
|
- (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
|
||||||
|
- nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
||||||
|
+ nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir);
|
||||||
|
+ nf_flow_snat_ip(flow, skb, iph, thoff, dir);
|
||||||
|
+ }
|
||||||
|
+ if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
|
||||||
|
+ nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir);
|
||||||
|
+ nf_flow_dnat_ip(flow, skb, iph, thoff, dir);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ip_has_options(unsigned int thoff)
|
||||||
|
@@ -276,8 +265,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
iph = ip_hdr(skb);
|
||||||
|
- if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_ip(flow, skb, thoff, dir, iph);
|
||||||
|
|
||||||
|
ip_decrease_ttl(iph);
|
||||||
|
skb->tstamp = 0;
|
||||||
|
@@ -301,22 +289,21 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- struct in6_addr *addr,
|
||||||
|
- struct in6_addr *new_addr)
|
||||||
|
+static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ struct in6_addr *addr,
|
||||||
|
+ struct in6_addr *new_addr,
|
||||||
|
+ struct ipv6hdr *ip6h)
|
||||||
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
tcph = (void *)(skb_network_header(skb) + thoff);
|
||||||
|
inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32,
|
||||||
|
new_addr->s6_addr32, true);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
- struct in6_addr *addr,
|
||||||
|
- struct in6_addr *new_addr)
|
||||||
|
+static void nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
|
||||||
|
+ struct in6_addr *addr,
|
||||||
|
+ struct in6_addr *new_addr)
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
@@ -327,32 +314,26 @@ static int nf_flow_nat_ipv6_udp(struct s
|
||||||
|
if (!udph->check)
|
||||||
|
udph->check = CSUM_MANGLED_0;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h,
|
||||||
|
- unsigned int thoff, struct in6_addr *addr,
|
||||||
|
- struct in6_addr *new_addr)
|
||||||
|
+static void nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h,
|
||||||
|
+ unsigned int thoff, struct in6_addr *addr,
|
||||||
|
+ struct in6_addr *new_addr)
|
||||||
|
{
|
||||||
|
switch (ip6h->nexthdr) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
- if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr, ip6h);
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
- if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_snat_ipv6(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb, struct ipv6hdr *ip6h,
|
||||||
|
- unsigned int thoff,
|
||||||
|
- enum flow_offload_tuple_dir dir)
|
||||||
|
+static void nf_flow_snat_ipv6(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, struct ipv6hdr *ip6h,
|
||||||
|
+ unsigned int thoff,
|
||||||
|
+ enum flow_offload_tuple_dir dir)
|
||||||
|
{
|
||||||
|
struct in6_addr addr, new_addr;
|
||||||
|
|
||||||
|
@@ -369,13 +350,13 @@ static int nf_flow_snat_ipv6(const struc
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
|
||||||
|
+ nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_dnat_ipv6(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb, struct ipv6hdr *ip6h,
|
||||||
|
- unsigned int thoff,
|
||||||
|
- enum flow_offload_tuple_dir dir)
|
||||||
|
+static void nf_flow_dnat_ipv6(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb, struct ipv6hdr *ip6h,
|
||||||
|
+ unsigned int thoff,
|
||||||
|
+ enum flow_offload_tuple_dir dir)
|
||||||
|
{
|
||||||
|
struct in6_addr addr, new_addr;
|
||||||
|
|
||||||
|
@@ -392,27 +373,24 @@ static int nf_flow_dnat_ipv6(const struc
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
|
||||||
|
+ nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_nat_ipv6(const struct flow_offload *flow,
|
||||||
|
- struct sk_buff *skb,
|
||||||
|
- enum flow_offload_tuple_dir dir,
|
||||||
|
- struct ipv6hdr *ip6h)
|
||||||
|
+static void nf_flow_nat_ipv6(const struct flow_offload *flow,
|
||||||
|
+ struct sk_buff *skb,
|
||||||
|
+ enum flow_offload_tuple_dir dir,
|
||||||
|
+ struct ipv6hdr *ip6h)
|
||||||
|
{
|
||||||
|
unsigned int thoff = sizeof(*ip6h);
|
||||||
|
|
||||||
|
- if (test_bit(NF_FLOW_SNAT, &flow->flags) &&
|
||||||
|
- (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 ||
|
||||||
|
- nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- if (test_bit(NF_FLOW_DNAT, &flow->flags) &&
|
||||||
|
- (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 ||
|
||||||
|
- nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0))
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
||||||
|
+ nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir);
|
||||||
|
+ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir);
|
||||||
|
+ }
|
||||||
|
+ if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
|
||||||
|
+ nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir);
|
||||||
|
+ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
||||||
|
@@ -507,8 +485,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
ip6h = ipv6_hdr(skb);
|
||||||
|
- if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0)
|
||||||
|
- return NF_DROP;
|
||||||
|
+ nf_flow_nat_ipv6(flow, skb, dir, ip6h);
|
||||||
|
|
||||||
|
ip6h->hop_limit--;
|
||||||
|
skb->tstamp = 0;
|
@ -0,0 +1,46 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:26 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: call dst_check() to fall back to
|
||||||
|
classic forwarding
|
||||||
|
|
||||||
|
In case the route is stale, pass up the packet to the classic forwarding
|
||||||
|
path for re-evaluation and schedule this flow entry for removal.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -197,14 +197,6 @@ static bool nf_flow_exceeds_mtu(const st
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nf_flow_offload_dst_check(struct dst_entry *dst)
|
||||||
|
-{
|
||||||
|
- if (unlikely(dst_xfrm(dst)))
|
||||||
|
- return dst_check(dst, 0) ? 0 : -1;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
|
||||||
|
const struct nf_hook_state *state,
|
||||||
|
struct dst_entry *dst)
|
||||||
|
@@ -256,7 +248,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
|
||||||
|
flow_offload_refresh(flow_table, flow);
|
||||||
|
|
||||||
|
- if (nf_flow_offload_dst_check(&rt->dst)) {
|
||||||
|
+ if (!dst_check(&rt->dst, 0)) {
|
||||||
|
flow_offload_teardown(flow);
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
||||||
|
@@ -476,7 +468,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
|
||||||
|
flow_offload_refresh(flow_table, flow);
|
||||||
|
|
||||||
|
- if (nf_flow_offload_dst_check(&rt->dst)) {
|
||||||
|
+ if (!dst_check(&rt->dst, 0)) {
|
||||||
|
flow_offload_teardown(flow);
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:27 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: refresh timeout after dst and
|
||||||
|
writable checks
|
||||||
|
|
||||||
|
Refresh the timeout (and retry hardware offload) once the skbuff dst
|
||||||
|
is confirmed to be current and after the skbuff is made writable.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -246,8 +246,6 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- flow_offload_refresh(flow_table, flow);
|
||||||
|
-
|
||||||
|
if (!dst_check(&rt->dst, 0)) {
|
||||||
|
flow_offload_teardown(flow);
|
||||||
|
return NF_ACCEPT;
|
||||||
|
@@ -256,6 +254,8 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
+ flow_offload_refresh(flow_table, flow);
|
||||||
|
+
|
||||||
|
iph = ip_hdr(skb);
|
||||||
|
nf_flow_nat_ip(flow, skb, thoff, dir, iph);
|
||||||
|
|
||||||
|
@@ -466,8 +466,6 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
sizeof(*ip6h)))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- flow_offload_refresh(flow_table, flow);
|
||||||
|
-
|
||||||
|
if (!dst_check(&rt->dst, 0)) {
|
||||||
|
flow_offload_teardown(flow);
|
||||||
|
return NF_ACCEPT;
|
||||||
|
@@ -476,6 +474,8 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize))
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
+ flow_offload_refresh(flow_table, flow);
|
||||||
|
+
|
||||||
|
ip6h = ipv6_hdr(skb);
|
||||||
|
nf_flow_nat_ipv6(flow, skb, dir, ip6h);
|
||||||
|
|
@ -0,0 +1,103 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Tue, 23 Mar 2021 00:56:28 +0100
|
||||||
|
Subject: [PATCH] netfilter: nftables: update table flags from the commit
|
||||||
|
phase
|
||||||
|
|
||||||
|
Do not update table flags from the preparation phase. Store the flags
|
||||||
|
update into the transaction, then update the flags from the commit
|
||||||
|
phase.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/include/net/netfilter/nf_tables.h
|
||||||
|
+++ b/include/net/netfilter/nf_tables.h
|
||||||
|
@@ -1470,13 +1470,16 @@ struct nft_trans_chain {
|
||||||
|
|
||||||
|
struct nft_trans_table {
|
||||||
|
bool update;
|
||||||
|
- bool enable;
|
||||||
|
+ u8 state;
|
||||||
|
+ u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define nft_trans_table_update(trans) \
|
||||||
|
(((struct nft_trans_table *)trans->data)->update)
|
||||||
|
-#define nft_trans_table_enable(trans) \
|
||||||
|
- (((struct nft_trans_table *)trans->data)->enable)
|
||||||
|
+#define nft_trans_table_state(trans) \
|
||||||
|
+ (((struct nft_trans_table *)trans->data)->state)
|
||||||
|
+#define nft_trans_table_flags(trans) \
|
||||||
|
+ (((struct nft_trans_table *)trans->data)->flags)
|
||||||
|
|
||||||
|
struct nft_trans_elem {
|
||||||
|
struct nft_set *set;
|
||||||
|
--- a/net/netfilter/nf_tables_api.c
|
||||||
|
+++ b/net/netfilter/nf_tables_api.c
|
||||||
|
@@ -891,6 +891,12 @@ static void nf_tables_table_disable(stru
|
||||||
|
nft_table_disable(net, table, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+enum {
|
||||||
|
+ NFT_TABLE_STATE_UNCHANGED = 0,
|
||||||
|
+ NFT_TABLE_STATE_DORMANT,
|
||||||
|
+ NFT_TABLE_STATE_WAKEUP
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static int nf_tables_updtable(struct nft_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct nft_trans *trans;
|
||||||
|
@@ -914,19 +920,17 @@ static int nf_tables_updtable(struct nft
|
||||||
|
|
||||||
|
if ((flags & NFT_TABLE_F_DORMANT) &&
|
||||||
|
!(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
|
||||||
|
- nft_trans_table_enable(trans) = false;
|
||||||
|
+ nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT;
|
||||||
|
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
|
||||||
|
ctx->table->flags & NFT_TABLE_F_DORMANT) {
|
||||||
|
- ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
|
||||||
|
ret = nf_tables_table_enable(ctx->net, ctx->table);
|
||||||
|
if (ret >= 0)
|
||||||
|
- nft_trans_table_enable(trans) = true;
|
||||||
|
- else
|
||||||
|
- ctx->table->flags |= NFT_TABLE_F_DORMANT;
|
||||||
|
+ nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP;
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
+ nft_trans_table_flags(trans) = flags;
|
||||||
|
nft_trans_table_update(trans) = true;
|
||||||
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
||||||
|
return 0;
|
||||||
|
@@ -7873,11 +7877,10 @@ static int nf_tables_commit(struct net *
|
||||||
|
switch (trans->msg_type) {
|
||||||
|
case NFT_MSG_NEWTABLE:
|
||||||
|
if (nft_trans_table_update(trans)) {
|
||||||
|
- if (!nft_trans_table_enable(trans)) {
|
||||||
|
- nf_tables_table_disable(net,
|
||||||
|
- trans->ctx.table);
|
||||||
|
- trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
||||||
|
- }
|
||||||
|
+ if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT)
|
||||||
|
+ nf_tables_table_disable(net, trans->ctx.table);
|
||||||
|
+
|
||||||
|
+ trans->ctx.table->flags = nft_trans_table_flags(trans);
|
||||||
|
} else {
|
||||||
|
nft_clear(net, trans->ctx.table);
|
||||||
|
}
|
||||||
|
@@ -8090,11 +8093,9 @@ static int __nf_tables_abort(struct net
|
||||||
|
switch (trans->msg_type) {
|
||||||
|
case NFT_MSG_NEWTABLE:
|
||||||
|
if (nft_trans_table_update(trans)) {
|
||||||
|
- if (nft_trans_table_enable(trans)) {
|
||||||
|
- nf_tables_table_disable(net,
|
||||||
|
- trans->ctx.table);
|
||||||
|
- trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
||||||
|
- }
|
||||||
|
+ if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP)
|
||||||
|
+ nf_tables_table_disable(net, trans->ctx.table);
|
||||||
|
+
|
||||||
|
nft_trans_destroy(trans);
|
||||||
|
} else {
|
||||||
|
list_del_rcu(&trans->ctx.table->list);
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Thu, 4 Mar 2021 23:18:11 +0100
|
Date: Wed, 24 Mar 2021 02:30:32 +0100
|
||||||
Subject: [PATCH] net: resolve forwarding path from virtual netdevice and
|
Subject: [PATCH] net: resolve forwarding path from virtual netdevice and
|
||||||
HW destination address
|
HW destination address
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Fri, 20 Nov 2020 13:49:16 +0100
|
Date: Wed, 24 Mar 2021 02:30:33 +0100
|
||||||
Subject: [PATCH] net: 8021q: resolve forwarding path for vlan devices
|
Subject: [PATCH] net: 8021q: resolve forwarding path for vlan devices
|
||||||
|
|
||||||
Add .ndo_fill_forward_path for vlan devices.
|
Add .ndo_fill_forward_path for vlan devices.
|
@ -1,6 +1,6 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Fri, 20 Nov 2020 13:49:17 +0100
|
Date: Wed, 24 Mar 2021 02:30:34 +0100
|
||||||
Subject: [PATCH] bridge: resolve forwarding path for bridge devices
|
Subject: [PATCH] net: bridge: resolve forwarding path for bridge devices
|
||||||
|
|
||||||
Add .ndo_fill_forward_path for bridge devices.
|
Add .ndo_fill_forward_path for bridge devices.
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Mon, 7 Dec 2020 20:31:45 +0100
|
Date: Wed, 24 Mar 2021 02:30:35 +0100
|
||||||
Subject: [PATCH] net: bridge: resolve VLAN tag actions in forwarding
|
Subject: [PATCH] net: bridge: resolve forwarding path for VLAN tag
|
||||||
path for bridge devices
|
actions in bridge devices
|
||||||
|
|
||||||
Depending on the VLAN settings of the bridge and the port, the bridge can
|
Depending on the VLAN settings of the bridge and the port, the bridge can
|
||||||
either add or remove a tag. When vlan filtering is enabled, the fdb lookup
|
either add or remove a tag. When vlan filtering is enabled, the fdb lookup
|
@ -1,9 +1,13 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Tue, 2 Mar 2021 21:45:16 +0100
|
Date: Wed, 24 Mar 2021 02:30:36 +0100
|
||||||
Subject: [PATCH] net: ppp: resolve forwarding path for bridge pppoe
|
Subject: [PATCH] net: ppp: resolve forwarding path for bridge pppoe
|
||||||
devices
|
devices
|
||||||
|
|
||||||
Pass on the PPPoE session ID and the real device.
|
Pass on the PPPoE session ID, destination hardware address and the real
|
||||||
|
device.
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/drivers/net/ppp/ppp_generic.c
|
--- a/drivers/net/ppp/ppp_generic.c
|
||||||
@ -15,7 +19,7 @@ Pass on the PPPoE session ID and the real device.
|
|||||||
+static int ppp_fill_forward_path(struct net_device_path_ctx *ctx,
|
+static int ppp_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||||
+ struct net_device_path *path)
|
+ struct net_device_path *path)
|
||||||
+{
|
+{
|
||||||
+ struct ppp *ppp = netdev_priv(path->dev);
|
+ struct ppp *ppp = netdev_priv(ctx->dev);
|
||||||
+ struct ppp_channel *chan;
|
+ struct ppp_channel *chan;
|
||||||
+ struct channel *pch;
|
+ struct channel *pch;
|
||||||
+
|
+
|
||||||
@ -45,7 +49,7 @@ Pass on the PPPoE session ID and the real device.
|
|||||||
static struct device_type ppp_type = {
|
static struct device_type ppp_type = {
|
||||||
--- a/drivers/net/ppp/pppoe.c
|
--- a/drivers/net/ppp/pppoe.c
|
||||||
+++ b/drivers/net/ppp/pppoe.c
|
+++ b/drivers/net/ppp/pppoe.c
|
||||||
@@ -972,8 +972,30 @@ static int pppoe_xmit(struct ppp_channel
|
@@ -972,8 +972,31 @@ static int pppoe_xmit(struct ppp_channel
|
||||||
return __pppoe_xmit(sk, skb);
|
return __pppoe_xmit(sk, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +68,7 @@ Pass on the PPPoE session ID and the real device.
|
|||||||
+ path->type = DEV_PATH_PPPOE;
|
+ path->type = DEV_PATH_PPPOE;
|
||||||
+ path->encap.proto = htons(ETH_P_PPP_SES);
|
+ path->encap.proto = htons(ETH_P_PPP_SES);
|
||||||
+ path->encap.id = be16_to_cpu(po->num);
|
+ path->encap.id = be16_to_cpu(po->num);
|
||||||
|
+ memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN);
|
||||||
+ path->dev = ctx->dev;
|
+ path->dev = ctx->dev;
|
||||||
+ ctx->dev = dev;
|
+ ctx->dev = dev;
|
||||||
+
|
+
|
||||||
@ -86,6 +91,14 @@ Pass on the PPPoE session ID and the real device.
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct net_device_path {
|
struct net_device_path {
|
||||||
|
@@ -840,6 +841,7 @@ struct net_device_path {
|
||||||
|
struct {
|
||||||
|
u16 id;
|
||||||
|
__be16 proto;
|
||||||
|
+ u8 h_dest[ETH_ALEN];
|
||||||
|
} encap;
|
||||||
|
struct {
|
||||||
|
enum {
|
||||||
--- a/include/linux/ppp_channel.h
|
--- a/include/linux/ppp_channel.h
|
||||||
+++ b/include/linux/ppp_channel.h
|
+++ b/include/linux/ppp_channel.h
|
||||||
@@ -28,6 +28,9 @@ struct ppp_channel_ops {
|
@@ -28,6 +28,9 @@ struct ppp_channel_ops {
|
@ -1,8 +1,11 @@
|
|||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Thu, 4 Mar 2021 23:19:06 +0100
|
Date: Wed, 24 Mar 2021 02:30:37 +0100
|
||||||
Subject: [PATCH] net: dsa: resolve forwarding path for dsa slave ports
|
Subject: [PATCH] net: dsa: resolve forwarding path for dsa slave ports
|
||||||
|
|
||||||
Add .ndo_fill_forward_path for dsa slave port devices
|
Add .ndo_fill_forward_path for dsa slave port devices
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/include/linux/netdevice.h
|
--- a/include/linux/netdevice.h
|
||||||
@ -15,7 +18,7 @@ Add .ndo_fill_forward_path for dsa slave port devices
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct net_device_path {
|
struct net_device_path {
|
||||||
@@ -851,6 +852,10 @@ struct net_device_path {
|
@@ -852,6 +853,10 @@ struct net_device_path {
|
||||||
u16 vlan_id;
|
u16 vlan_id;
|
||||||
__be16 vlan_proto;
|
__be16 vlan_proto;
|
||||||
} bridge;
|
} bridge;
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Fri, 20 Nov 2020 13:49:14 +0100
|
Date: Wed, 24 Mar 2021 02:30:38 +0100
|
||||||
Subject: [PATCH] netfilter: flowtable: add xmit path types
|
Subject: [PATCH] netfilter: flowtable: add xmit path types
|
||||||
|
|
||||||
Add the xmit_type field that defines the two supported xmit paths in the
|
Add the xmit_type field that defines the two supported xmit paths in the
|
||||||
@ -12,8 +12,8 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
--- 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
|
||||||
@@ -89,6 +89,11 @@ enum flow_offload_tuple_dir {
|
@@ -89,6 +89,11 @@ enum flow_offload_tuple_dir {
|
||||||
FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX
|
|
||||||
};
|
};
|
||||||
|
#define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX
|
||||||
|
|
||||||
+enum flow_offload_xmit_type {
|
+enum flow_offload_xmit_type {
|
||||||
+ FLOW_OFFLOAD_XMIT_NEIGH = 0,
|
+ FLOW_OFFLOAD_XMIT_NEIGH = 0,
|
||||||
@ -55,30 +55,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
return 0;
|
return 0;
|
||||||
--- a/net/netfilter/nf_flow_table_ip.c
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
@@ -220,10 +220,20 @@ static bool nf_flow_exceeds_mtu(const st
|
@@ -235,8 +235,6 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int nf_flow_offload_dst_check(struct dst_entry *dst)
|
|
||||||
+static inline struct dst_entry *
|
|
||||||
+nft_flow_dst(struct flow_offload_tuple_rhash *tuplehash)
|
|
||||||
{
|
|
||||||
- if (unlikely(dst_xfrm(dst)))
|
|
||||||
+ return tuplehash->tuple.dst_cache;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int nf_flow_offload_dst_check(struct flow_offload_tuple_rhash *tuplehash)
|
|
||||||
+{
|
|
||||||
+ struct dst_entry *dst;
|
|
||||||
+
|
|
||||||
+ if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
|
||||||
+ dst = nft_flow_dst(tuplehash);
|
|
||||||
return dst_check(dst, 0) ? 0 : -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -265,8 +275,6 @@ nf_flow_offload_ip_hook(void *priv, stru
|
|
||||||
|
|
||||||
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]);
|
||||||
@ -87,16 +64,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
|
|
||||||
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
@@ -280,7 +288,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
@@ -265,13 +263,16 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
|
||||||
flow_offload_refresh(flow_table, flow);
|
|
||||||
|
|
||||||
- if (nf_flow_offload_dst_check(&rt->dst)) {
|
|
||||||
+ if (nf_flow_offload_dst_check(tuplehash)) {
|
|
||||||
flow_offload_teardown(flow);
|
|
||||||
return NF_ACCEPT;
|
|
||||||
}
|
|
||||||
@@ -295,13 +303,16 @@ nf_flow_offload_ip_hook(void *priv, stru
|
|
||||||
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
||||||
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
||||||
|
|
||||||
@ -114,7 +82,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
skb->dev = outdev;
|
skb->dev = outdev;
|
||||||
nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
|
nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
|
||||||
skb_dst_set_noref(skb, &rt->dst);
|
skb_dst_set_noref(skb, &rt->dst);
|
||||||
@@ -506,8 +517,6 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
@@ -456,8 +457,6 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
|
||||||
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]);
|
||||||
@ -123,16 +91,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
|
|
||||||
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
@@ -518,7 +527,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
@@ -485,13 +484,16 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
|
||||||
flow_offload_refresh(flow_table, flow);
|
|
||||||
|
|
||||||
- if (nf_flow_offload_dst_check(&rt->dst)) {
|
|
||||||
+ if (nf_flow_offload_dst_check(tuplehash)) {
|
|
||||||
flow_offload_teardown(flow);
|
|
||||||
return NF_ACCEPT;
|
|
||||||
}
|
|
||||||
@@ -536,13 +545,16 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
|
||||||
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
||||||
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Fri, 20 Nov 2020 13:49:18 +0100
|
Date: Wed, 24 Mar 2021 02:30:39 +0100
|
||||||
Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to
|
Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to
|
||||||
obtain ingress device
|
obtain ingress device
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Thu, 4 Mar 2021 03:26:35 +0100
|
Date: Wed, 24 Mar 2021 02:30:40 +0100
|
||||||
Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to
|
Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to
|
||||||
obtain egress device
|
obtain egress device
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
void flow_offload_free(struct flow_offload *flow)
|
void flow_offload_free(struct flow_offload *flow)
|
||||||
--- a/net/netfilter/nf_flow_table_ip.c
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
@@ -248,6 +248,24 @@ static unsigned int nf_flow_xmit_xfrm(st
|
@@ -207,6 +207,24 @@ static unsigned int nf_flow_xmit_xfrm(st
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,25 +158,41 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
unsigned int
|
unsigned int
|
||||||
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||||
const struct nf_hook_state *state)
|
const struct nf_hook_state *state)
|
||||||
@@ -262,6 +280,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
@@ -222,6 +240,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
unsigned int thoff;
|
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
__be32 nexthop;
|
__be32 nexthop;
|
||||||
|
u32 hdrsize;
|
||||||
+ int ret;
|
+ int ret;
|
||||||
|
|
||||||
if (skb->protocol != htons(ETH_P_IP))
|
if (skb->protocol != htons(ETH_P_IP))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
@@ -303,22 +322,32 @@ nf_flow_offload_ip_hook(void *priv, stru
|
@@ -244,9 +263,13 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- if (!dst_check(&rt->dst, 0)) {
|
||||||
|
- flow_offload_teardown(flow);
|
||||||
|
- return NF_ACCEPT;
|
||||||
|
+ if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
|
||||||
|
+ tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
|
||||||
|
+ rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
||||||
|
+ if (!dst_check(&rt->dst, 0)) {
|
||||||
|
+ flow_offload_teardown(flow);
|
||||||
|
+ return NF_ACCEPT;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||||
|
@@ -263,8 +286,6 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
||||||
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
||||||
|
|
||||||
- rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
- rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
||||||
-
|
-
|
||||||
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
||||||
+ rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
|
||||||
memset(skb->cb, 0, sizeof(struct inet_skb_parm));
|
memset(skb->cb, 0, sizeof(struct inet_skb_parm));
|
||||||
IPCB(skb)->iif = skb->dev->ifindex;
|
IPCB(skb)->iif = skb->dev->ifindex;
|
||||||
IPCB(skb)->flags = IPSKB_FORWARDED;
|
@@ -272,13 +293,23 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
return nf_flow_xmit_xfrm(skb, state, &rt->dst);
|
return nf_flow_xmit_xfrm(skb, state, &rt->dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +203,6 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb);
|
- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb);
|
||||||
+ switch (tuplehash->tuple.xmit_type) {
|
+ switch (tuplehash->tuple.xmit_type) {
|
||||||
+ case FLOW_OFFLOAD_XMIT_NEIGH:
|
+ case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||||
+ rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
|
||||||
+ outdev = rt->dst.dev;
|
+ outdev = rt->dst.dev;
|
||||||
+ skb->dev = outdev;
|
+ skb->dev = outdev;
|
||||||
+ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
|
+ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
|
||||||
@ -207,25 +222,41 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
|
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
|
||||||
|
|
||||||
@@ -504,6 +533,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
@@ -444,6 +475,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
struct net_device *outdev;
|
|
||||||
struct ipv6hdr *ip6h;
|
struct ipv6hdr *ip6h;
|
||||||
struct rt6_info *rt;
|
struct rt6_info *rt;
|
||||||
|
u32 hdrsize;
|
||||||
+ int ret;
|
+ int ret;
|
||||||
|
|
||||||
if (skb->protocol != htons(ETH_P_IPV6))
|
if (skb->protocol != htons(ETH_P_IPV6))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
@@ -545,21 +575,31 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
@@ -465,9 +497,13 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
sizeof(*ip6h)))
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
- if (!dst_check(&rt->dst, 0)) {
|
||||||
|
- flow_offload_teardown(flow);
|
||||||
|
- return NF_ACCEPT;
|
||||||
|
+ if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
|
||||||
|
+ tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
|
||||||
|
+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
||||||
|
+ if (!dst_check(&rt->dst, 0)) {
|
||||||
|
+ flow_offload_teardown(flow);
|
||||||
|
+ return NF_ACCEPT;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize))
|
||||||
|
@@ -484,8 +520,6 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
if (flow_table->flags & NF_FLOWTABLE_COUNTER)
|
||||||
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
||||||
|
|
||||||
- rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
- rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
||||||
-
|
-
|
||||||
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
||||||
+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
|
||||||
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
||||||
IP6CB(skb)->iif = skb->dev->ifindex;
|
IP6CB(skb)->iif = skb->dev->ifindex;
|
||||||
IP6CB(skb)->flags = IP6SKB_FORWARDED;
|
@@ -493,12 +527,22 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
return nf_flow_xmit_xfrm(skb, state, &rt->dst);
|
return nf_flow_xmit_xfrm(skb, state, &rt->dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +267,6 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb);
|
- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb);
|
||||||
+ switch (tuplehash->tuple.xmit_type) {
|
+ switch (tuplehash->tuple.xmit_type) {
|
||||||
+ case FLOW_OFFLOAD_XMIT_NEIGH:
|
+ case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||||
+ rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
|
||||||
+ outdev = rt->dst.dev;
|
+ outdev = rt->dst.dev;
|
||||||
+ skb->dev = outdev;
|
+ skb->dev = outdev;
|
||||||
+ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
|
+ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
|
@ -1,11 +1,15 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Fri, 20 Nov 2020 13:49:20 +0100
|
Date: Wed, 24 Mar 2021 02:30:41 +0100
|
||||||
Subject: [PATCH] netfilter: flowtable: add vlan support
|
Subject: [PATCH] netfilter: flowtable: add vlan support
|
||||||
|
|
||||||
Add the vlan id and protocol to the flow tuple to uniquely identify
|
Add the vlan id and protocol to the flow tuple to uniquely identify
|
||||||
flows from the receive path. For the transmit path, dev_hard_header() on
|
flows from the receive path. For the transmit path, dev_hard_header() on
|
||||||
the vlan device push the headers. This patch includes support for two
|
the vlan device push the headers. This patch includes support for two
|
||||||
VLAN headers (QinQ) from the ingress path.
|
vlan headers (QinQ) from the ingress path.
|
||||||
|
|
||||||
|
Add a generic encap field to the flowtable entry which stores the
|
||||||
|
protocol and the tag id. This allows to reuse these fields in the PPPoE
|
||||||
|
support coming in a later patch.
|
||||||
|
|
||||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
@ -79,7 +83,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
case FLOW_OFFLOAD_XMIT_DIRECT:
|
case FLOW_OFFLOAD_XMIT_DIRECT:
|
||||||
--- a/net/netfilter/nf_flow_table_ip.c
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
@@ -159,17 +159,38 @@ static bool ip_has_options(unsigned int
|
@@ -136,23 +136,44 @@ static bool ip_has_options(unsigned int
|
||||||
return thoff != sizeof(struct iphdr);
|
return thoff != sizeof(struct iphdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,41 +106,46 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
||||||
struct flow_offload_tuple *tuple)
|
- struct flow_offload_tuple *tuple, u32 *hdrsize)
|
||||||
|
+ struct flow_offload_tuple *tuple, u32 *hdrsize,
|
||||||
|
+ u32 offset)
|
||||||
{
|
{
|
||||||
- unsigned int thoff, hdrsize;
|
|
||||||
+ unsigned int thoff, hdrsize, offset = 0;
|
|
||||||
struct flow_ports *ports;
|
struct flow_ports *ports;
|
||||||
|
unsigned int thoff;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
|
|
||||||
- if (!pskb_may_pull(skb, sizeof(*iph)))
|
- if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||||
+ if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
+ offset += VLAN_HLEN;
|
|
||||||
+
|
|
||||||
+ if (!pskb_may_pull(skb, sizeof(*iph) + offset))
|
+ if (!pskb_may_pull(skb, sizeof(*iph) + offset))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
- iph = ip_hdr(skb);
|
- iph = ip_hdr(skb);
|
||||||
|
- thoff = iph->ihl * 4;
|
||||||
+ iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
+ iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
||||||
thoff = iph->ihl * 4;
|
+ thoff = (iph->ihl * 4);
|
||||||
|
|
||||||
if (ip_is_fragment(iph) ||
|
if (ip_is_fragment(iph) ||
|
||||||
@@ -191,11 +212,11 @@ static int nf_flow_tuple_ip(struct sk_bu
|
unlikely(ip_has_options(thoff)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
thoff = iph->ihl * 4;
|
+ thoff += offset;
|
||||||
- if (!pskb_may_pull(skb, thoff + hdrsize))
|
+
|
||||||
+ if (!pskb_may_pull(skb, thoff + hdrsize + offset))
|
switch (iph->protocol) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
*hdrsize = sizeof(struct tcphdr);
|
||||||
|
@@ -167,11 +188,10 @@ static int nf_flow_tuple_ip(struct sk_bu
|
||||||
|
if (iph->ttl <= 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
- thoff = iph->ihl * 4;
|
||||||
|
if (!pskb_may_pull(skb, thoff + *hdrsize))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
- iph = ip_hdr(skb);
|
- iph = ip_hdr(skb);
|
||||||
- ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
|
||||||
+ iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
+ iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
||||||
+ ports = (struct flow_ports *)(skb_network_header(skb) + thoff + offset);
|
ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
||||||
|
|
||||||
tuple->src_v4.s_addr = iph->saddr;
|
tuple->src_v4.s_addr = iph->saddr;
|
||||||
tuple->dst_v4.s_addr = iph->daddr;
|
@@ -181,6 +201,7 @@ static int nf_flow_tuple_ip(struct sk_bu
|
||||||
@@ -204,6 +225,7 @@ static int nf_flow_tuple_ip(struct sk_bu
|
|
||||||
tuple->l3proto = AF_INET;
|
tuple->l3proto = AF_INET;
|
||||||
tuple->l4proto = iph->protocol;
|
tuple->l4proto = iph->protocol;
|
||||||
tuple->iifidx = dev->ifindex;
|
tuple->iifidx = dev->ifindex;
|
||||||
@ -144,19 +153,22 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -248,6 +270,40 @@ static unsigned int nf_flow_xmit_xfrm(st
|
@@ -207,6 +228,43 @@ static unsigned int nf_flow_xmit_xfrm(st
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
+static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto)
|
+static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
|
||||||
|
+ u32 *offset)
|
||||||
+{
|
+{
|
||||||
+ if (skb->protocol == htons(ETH_P_8021Q)) {
|
+ if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||||
+ struct vlan_ethhdr *veth;
|
+ struct vlan_ethhdr *veth;
|
||||||
+
|
+
|
||||||
+ veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
+ veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
||||||
+ if (veth->h_vlan_encapsulated_proto == proto)
|
+ if (veth->h_vlan_encapsulated_proto == proto) {
|
||||||
|
+ *offset += VLAN_HLEN;
|
||||||
+ return true;
|
+ return true;
|
||||||
+ }
|
+ }
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
+ return false;
|
+ return false;
|
||||||
+}
|
+}
|
||||||
@ -185,25 +197,30 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
|
static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
|
||||||
const struct flow_offload_tuple_rhash *tuplehash,
|
const struct flow_offload_tuple_rhash *tuplehash,
|
||||||
unsigned short type)
|
unsigned short type)
|
||||||
@@ -276,13 +332,15 @@ nf_flow_offload_ip_hook(void *priv, stru
|
@@ -235,17 +293,18 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
enum flow_offload_tuple_dir dir;
|
enum flow_offload_tuple_dir dir;
|
||||||
struct flow_offload *flow;
|
struct flow_offload *flow;
|
||||||
struct net_device *outdev;
|
struct net_device *outdev;
|
||||||
|
+ u32 hdrsize, offset = 0;
|
||||||
+ unsigned int thoff, mtu;
|
+ unsigned int thoff, mtu;
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
- unsigned int thoff;
|
- unsigned int thoff;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
__be32 nexthop;
|
__be32 nexthop;
|
||||||
+ u32 offset = 0;
|
- u32 hdrsize;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
- if (skb->protocol != htons(ETH_P_IP))
|
- if (skb->protocol != htons(ETH_P_IP))
|
||||||
+ if (skb->protocol != htons(ETH_P_IP) &&
|
+ if (skb->protocol != htons(ETH_P_IP) &&
|
||||||
+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP)))
|
+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP), &offset))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0)
|
- if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize) < 0)
|
||||||
@@ -295,14 +353,19 @@ nf_flow_offload_ip_hook(void *priv, stru
|
+ if (nf_flow_tuple_ip(skb, state->in, &tuple, &hdrsize, offset) < 0)
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
tuplehash = flow_offload_lookup(flow_table, &tuple);
|
||||||
|
@@ -255,11 +314,12 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
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]);
|
||||||
|
|
||||||
@ -212,45 +229,38 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
|
+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
- if (skb_try_make_writable(skb, sizeof(*iph)))
|
- iph = ip_hdr(skb);
|
||||||
+ if (skb->protocol == htons(ETH_P_8021Q))
|
- thoff = iph->ihl * 4;
|
||||||
+ offset += VLAN_HLEN;
|
|
||||||
+
|
|
||||||
+ if (skb_try_make_writable(skb, sizeof(*iph) + offset))
|
|
||||||
return NF_DROP;
|
|
||||||
|
|
||||||
- thoff = ip_hdr(skb)->ihl * 4;
|
|
||||||
- if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
|
|
||||||
+ iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
+ iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
||||||
+ thoff = (iph->ihl * 4) + offset;
|
+ thoff = (iph->ihl * 4) + offset;
|
||||||
+ if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
@@ -277,6 +337,9 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||||
|
|
||||||
flow_offload_refresh(flow_table, flow);
|
flow_offload_refresh(flow_table, flow);
|
||||||
@@ -312,6 +375,9 @@ nf_flow_offload_ip_hook(void *priv, stru
|
|
||||||
return NF_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ nf_flow_encap_pop(skb, tuplehash);
|
+ nf_flow_encap_pop(skb, tuplehash);
|
||||||
+ thoff -= offset;
|
+ thoff -= offset;
|
||||||
+
|
+
|
||||||
if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
|
iph = ip_hdr(skb);
|
||||||
return NF_DROP;
|
nf_flow_nat_ip(flow, skb, thoff, dir, iph);
|
||||||
|
|
||||||
|
@@ -418,16 +481,18 @@ static void nf_flow_nat_ipv6(const struc
|
||||||
|
}
|
||||||
|
|
||||||
@@ -479,14 +545,17 @@ static int nf_flow_nat_ipv6(const struct
|
|
||||||
static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
||||||
struct flow_offload_tuple *tuple)
|
- struct flow_offload_tuple *tuple, u32 *hdrsize)
|
||||||
|
+ struct flow_offload_tuple *tuple, u32 *hdrsize,
|
||||||
|
+ u32 offset)
|
||||||
{
|
{
|
||||||
- unsigned int thoff, hdrsize;
|
|
||||||
+ unsigned int thoff, hdrsize, offset = 0;
|
|
||||||
struct flow_ports *ports;
|
struct flow_ports *ports;
|
||||||
struct ipv6hdr *ip6h;
|
struct ipv6hdr *ip6h;
|
||||||
|
unsigned int thoff;
|
||||||
|
|
||||||
- if (!pskb_may_pull(skb, sizeof(*ip6h)))
|
- if (!pskb_may_pull(skb, sizeof(*ip6h)))
|
||||||
+ if (skb->protocol == htons(ETH_P_8021Q))
|
+ thoff = sizeof(*ip6h) + offset;
|
||||||
+ offset += VLAN_HLEN;
|
+ if (!pskb_may_pull(skb, thoff))
|
||||||
+
|
|
||||||
+ if (!pskb_may_pull(skb, sizeof(*ip6h) + offset))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
- ip6h = ipv6_hdr(skb);
|
- ip6h = ipv6_hdr(skb);
|
||||||
@ -258,22 +268,20 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
|
|
||||||
switch (ip6h->nexthdr) {
|
switch (ip6h->nexthdr) {
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
@@ -503,11 +572,11 @@ static int nf_flow_tuple_ipv6(struct sk_
|
@@ -443,11 +508,10 @@ static int nf_flow_tuple_ipv6(struct sk_
|
||||||
|
if (ip6h->hop_limit <= 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
thoff = sizeof(*ip6h);
|
- thoff = sizeof(*ip6h);
|
||||||
- if (!pskb_may_pull(skb, thoff + hdrsize))
|
if (!pskb_may_pull(skb, thoff + *hdrsize))
|
||||||
+ if (!pskb_may_pull(skb, thoff + hdrsize + offset))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
- ip6h = ipv6_hdr(skb);
|
- ip6h = ipv6_hdr(skb);
|
||||||
- ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
|
||||||
+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
||||||
+ ports = (struct flow_ports *)(skb_network_header(skb) + thoff + offset);
|
ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
||||||
|
|
||||||
tuple->src_v6 = ip6h->saddr;
|
tuple->src_v6 = ip6h->saddr;
|
||||||
tuple->dst_v6 = ip6h->daddr;
|
@@ -457,6 +521,7 @@ static int nf_flow_tuple_ipv6(struct sk_
|
||||||
@@ -516,6 +585,7 @@ static int nf_flow_tuple_ipv6(struct sk_
|
|
||||||
tuple->l3proto = AF_INET6;
|
tuple->l3proto = AF_INET6;
|
||||||
tuple->l4proto = ip6h->nexthdr;
|
tuple->l4proto = ip6h->nexthdr;
|
||||||
tuple->iifidx = dev->ifindex;
|
tuple->iifidx = dev->ifindex;
|
||||||
@ -281,21 +289,28 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -533,9 +603,12 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
@@ -472,15 +537,17 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
|
const struct in6_addr *nexthop;
|
||||||
|
struct flow_offload *flow;
|
||||||
struct net_device *outdev;
|
struct net_device *outdev;
|
||||||
|
+ unsigned int thoff, mtu;
|
||||||
|
+ u32 hdrsize, offset = 0;
|
||||||
struct ipv6hdr *ip6h;
|
struct ipv6hdr *ip6h;
|
||||||
struct rt6_info *rt;
|
struct rt6_info *rt;
|
||||||
+ unsigned int mtu;
|
- u32 hdrsize;
|
||||||
+ u32 offset = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
- if (skb->protocol != htons(ETH_P_IPV6))
|
- if (skb->protocol != htons(ETH_P_IPV6))
|
||||||
+ if (skb->protocol != htons(ETH_P_IPV6) &&
|
+ if (skb->protocol != htons(ETH_P_IPV6) &&
|
||||||
+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6)))
|
+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6), &offset))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0)
|
- if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize) < 0)
|
||||||
@@ -548,11 +621,15 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
+ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &hdrsize, offset) < 0)
|
||||||
|
return NF_ACCEPT;
|
||||||
|
|
||||||
|
tuplehash = flow_offload_lookup(flow_table, &tuple);
|
||||||
|
@@ -490,11 +557,13 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
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]);
|
||||||
|
|
||||||
@ -306,22 +321,26 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
|
|
||||||
- if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb,
|
- if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb,
|
||||||
- sizeof(*ip6h)))
|
- sizeof(*ip6h)))
|
||||||
+ if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
+ offset += VLAN_HLEN;
|
|
||||||
+
|
|
||||||
+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
||||||
+ if (nf_flow_state_check(flow, ip6h->nexthdr, skb, sizeof(*ip6h)))
|
+ thoff = sizeof(*ip6h) + offset;
|
||||||
|
+ if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
|
|
||||||
flow_offload_refresh(flow_table, flow);
|
if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
|
||||||
@@ -562,6 +639,8 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
@@ -506,11 +575,13 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||||
return NF_ACCEPT;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (skb_try_make_writable(skb, sizeof(*ip6h) + hdrsize))
|
||||||
|
+ if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||||
|
return NF_DROP;
|
||||||
|
|
||||||
|
flow_offload_refresh(flow_table, flow);
|
||||||
|
|
||||||
+ nf_flow_encap_pop(skb, tuplehash);
|
+ nf_flow_encap_pop(skb, tuplehash);
|
||||||
+
|
+
|
||||||
if (skb_try_make_writable(skb, sizeof(*ip6h)))
|
ip6h = ipv6_hdr(skb);
|
||||||
return NF_DROP;
|
nf_flow_nat_ipv6(flow, skb, dir, ip6h);
|
||||||
|
|
||||||
--- 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
|
@ -1,7 +1,6 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Sun, 24 Jan 2021 18:01:34 +0100
|
Date: Wed, 24 Mar 2021 02:30:42 +0100
|
||||||
Subject: [PATCH] netfilter: nft_flow_offload: add bridge vlan filtering
|
Subject: [PATCH] netfilter: flowtable: add bridge vlan filtering support
|
||||||
support
|
|
||||||
|
|
||||||
Add the vlan tag based when PVID is set on.
|
Add the vlan tag based when PVID is set on.
|
||||||
|
|
@ -0,0 +1,145 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Wed, 24 Mar 2021 02:30:43 +0100
|
||||||
|
Subject: [PATCH] netfilter: flowtable: add pppoe support
|
||||||
|
|
||||||
|
Add the PPPoE protocol and session id to the flow tuple using the encap
|
||||||
|
fields to uniquely identify flows from the receive path. For the
|
||||||
|
transmit path, dev_hard_header() on the vlan device push the headers.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/net/netfilter/nf_flow_table_ip.c
|
||||||
|
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||||
|
@@ -7,6 +7,9 @@
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
+#include <linux/if_ether.h>
|
||||||
|
+#include <linux/if_pppox.h>
|
||||||
|
+#include <linux/ppp_defs.h>
|
||||||
|
#include <net/ip.h>
|
||||||
|
#include <net/ipv6.h>
|
||||||
|
#include <net/ip6_route.h>
|
||||||
|
@@ -139,6 +142,8 @@ static bool ip_has_options(unsigned int
|
||||||
|
static void nf_flow_tuple_encap(struct sk_buff *skb,
|
||||||
|
struct flow_offload_tuple *tuple)
|
||||||
|
{
|
||||||
|
+ struct vlan_ethhdr *veth;
|
||||||
|
+ struct pppoe_hdr *phdr;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (skb_vlan_tag_present(skb)) {
|
||||||
|
@@ -146,11 +151,17 @@ static void nf_flow_tuple_encap(struct s
|
||||||
|
tuple->encap[i].proto = skb->vlan_proto;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
- if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||||
|
- struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
||||||
|
-
|
||||||
|
+ switch (skb->protocol) {
|
||||||
|
+ case htons(ETH_P_8021Q):
|
||||||
|
+ veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
||||||
|
tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
|
||||||
|
tuple->encap[i].proto = skb->protocol;
|
||||||
|
+ break;
|
||||||
|
+ case htons(ETH_P_PPP_SES):
|
||||||
|
+ phdr = (struct pppoe_hdr *)skb_mac_header(skb);
|
||||||
|
+ tuple->encap[i].id = ntohs(phdr->sid);
|
||||||
|
+ tuple->encap[i].proto = skb->protocol;
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -228,17 +239,41 @@ static unsigned int nf_flow_xmit_xfrm(st
|
||||||
|
return NF_STOLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ __be16 proto;
|
||||||
|
+
|
||||||
|
+ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
|
||||||
|
+ sizeof(struct pppoe_hdr)));
|
||||||
|
+ switch (proto) {
|
||||||
|
+ case htons(PPP_IP):
|
||||||
|
+ return htons(ETH_P_IP);
|
||||||
|
+ case htons(PPP_IPV6):
|
||||||
|
+ return htons(ETH_P_IPV6);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
|
||||||
|
u32 *offset)
|
||||||
|
{
|
||||||
|
- if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||||
|
- struct vlan_ethhdr *veth;
|
||||||
|
+ struct vlan_ethhdr *veth;
|
||||||
|
|
||||||
|
+ switch (skb->protocol) {
|
||||||
|
+ case htons(ETH_P_8021Q):
|
||||||
|
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
||||||
|
if (veth->h_vlan_encapsulated_proto == proto) {
|
||||||
|
*offset += VLAN_HLEN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
+ break;
|
||||||
|
+ case htons(ETH_P_PPP_SES):
|
||||||
|
+ if (nf_flow_pppoe_proto(skb) == proto) {
|
||||||
|
+ *offset += PPPOE_SES_HLEN;
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
@@ -255,12 +290,18 @@ static void nf_flow_encap_pop(struct sk_
|
||||||
|
__vlan_hwaccel_clear_tag(skb);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||||
|
+ switch (skb->protocol) {
|
||||||
|
+ case htons(ETH_P_8021Q):
|
||||||
|
vlan_hdr = (struct vlan_hdr *)skb->data;
|
||||||
|
__skb_pull(skb, VLAN_HLEN);
|
||||||
|
vlan_set_encap_proto(skb, vlan_hdr);
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
break;
|
||||||
|
+ case htons(ETH_P_PPP_SES):
|
||||||
|
+ skb->protocol = nf_flow_pppoe_proto(skb);
|
||||||
|
+ skb_pull(skb, PPPOE_SES_HLEN);
|
||||||
|
+ skb_reset_network_header(skb);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- a/net/netfilter/nft_flow_offload.c
|
||||||
|
+++ b/net/netfilter/nft_flow_offload.c
|
||||||
|
@@ -90,6 +90,7 @@ static void nft_dev_path_info(const stru
|
||||||
|
switch (path->type) {
|
||||||
|
case DEV_PATH_ETHERNET:
|
||||||
|
case DEV_PATH_VLAN:
|
||||||
|
+ case DEV_PATH_PPPOE:
|
||||||
|
info->indev = path->dev;
|
||||||
|
if (is_zero_ether_addr(info->h_source))
|
||||||
|
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
||||||
|
@@ -97,7 +98,7 @@ static void nft_dev_path_info(const stru
|
||||||
|
if (path->type == DEV_PATH_ETHERNET)
|
||||||
|
break;
|
||||||
|
|
||||||
|
- /* DEV_PATH_VLAN */
|
||||||
|
+ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */
|
||||||
|
if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
|
||||||
|
info->indev = NULL;
|
||||||
|
break;
|
||||||
|
@@ -106,6 +107,8 @@ static void nft_dev_path_info(const stru
|
||||||
|
info->encap[info->num_encaps].id = path->encap.id;
|
||||||
|
info->encap[info->num_encaps].proto = path->encap.proto;
|
||||||
|
info->num_encaps++;
|
||||||
|
+ if (path->type == DEV_PATH_PPPOE)
|
||||||
|
+ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN);
|
||||||
|
break;
|
||||||
|
case DEV_PATH_BRIDGE:
|
||||||
|
if (is_zero_ether_addr(info->h_source))
|
@ -1,8 +1,10 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Thu, 4 Mar 2021 19:22:55 +0100
|
Date: Wed, 24 Mar 2021 02:30:44 +0100
|
||||||
Subject: [PATCH] netfilter: nft_flow_offload: add dsa support
|
Subject: [PATCH] netfilter: flowtable: add dsa support
|
||||||
|
|
||||||
Replace the master ethernet device by the dsa slave port.
|
Replace the master ethernet device by the dsa slave port. Packets coming
|
||||||
|
in from the software ingress path use the dsa slave port as input
|
||||||
|
device.
|
||||||
|
|
||||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
@ -1,14 +1,14 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Fri, 20 Nov 2020 13:49:21 +0100
|
Date: Wed, 24 Mar 2021 02:30:45 +0100
|
||||||
Subject: [PATCH] selftests: netfilter: flowtable bridge and VLAN support
|
Subject: [PATCH] selftests: netfilter: flowtable bridge and vlan support
|
||||||
|
|
||||||
This patch adds two new tests to cover bridge and VLAN support:
|
This patch adds two new tests to cover bridge and vlan support:
|
||||||
|
|
||||||
- Add a bridge device to the Router1 (nsr1) container and attach the
|
- Add a bridge device to the Router1 (nsr1) container and attach the
|
||||||
veth0 device to the bridge. Set the IP address to the bridge device
|
veth0 device to the bridge. Set the IP address to the bridge device
|
||||||
to exercise the bridge forwarding path.
|
to exercise the bridge forwarding path.
|
||||||
|
|
||||||
- Add VLAN encapsulation between to the bridge device in the Router1 and
|
- Add vlan encapsulation between to the bridge device in the Router1 and
|
||||||
one of the sender containers (ns1).
|
one of the sender containers (ns1).
|
||||||
|
|
||||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Mon, 7 Dec 2020 20:31:44 +0100
|
Date: Wed, 24 Mar 2021 02:30:46 +0100
|
||||||
Subject: [PATCH] netfilter: flowtable: add offload support for xmit path
|
Subject: [PATCH] netfilter: flowtable: add offload support for xmit path
|
||||||
types
|
types
|
||||||
|
|
||||||
@ -9,11 +9,13 @@ need to be used.
|
|||||||
|
|
||||||
This patch also adds the FLOW_ACTION_VLAN_PUSH action to pass the VLAN
|
This patch also adds the FLOW_ACTION_VLAN_PUSH action to pass the VLAN
|
||||||
tag to the driver.
|
tag to the driver.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/net/netfilter/nf_flow_table_offload.c
|
--- a/net/netfilter/nf_flow_table_offload.c
|
||||||
+++ b/net/netfilter/nf_flow_table_offload.c
|
+++ b/net/netfilter/nf_flow_table_offload.c
|
||||||
@@ -175,28 +175,45 @@ static int flow_offload_eth_src(struct n
|
@@ -177,28 +177,45 @@ static int flow_offload_eth_src(struct n
|
||||||
enum flow_offload_tuple_dir dir,
|
enum flow_offload_tuple_dir dir,
|
||||||
struct nf_flow_rule *flow_rule)
|
struct nf_flow_rule *flow_rule)
|
||||||
{
|
{
|
||||||
@ -67,7 +69,7 @@ tag to the driver.
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -208,27 +225,40 @@ static int flow_offload_eth_dst(struct n
|
@@ -210,27 +227,40 @@ static int flow_offload_eth_dst(struct n
|
||||||
{
|
{
|
||||||
struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule);
|
struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule);
|
||||||
struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule);
|
struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule);
|
||||||
@ -120,7 +122,7 @@ tag to the driver.
|
|||||||
}
|
}
|
||||||
|
|
||||||
mask = ~0xffffffff;
|
mask = ~0xffffffff;
|
||||||
@@ -241,7 +271,6 @@ static int flow_offload_eth_dst(struct n
|
@@ -243,7 +273,6 @@ static int flow_offload_eth_dst(struct n
|
||||||
val = val16;
|
val = val16;
|
||||||
flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
|
flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
|
||||||
&val, &mask);
|
&val, &mask);
|
||||||
@ -128,7 +130,7 @@ tag to the driver.
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -463,27 +492,52 @@ static void flow_offload_ipv4_checksum(s
|
@@ -465,27 +494,52 @@ static void flow_offload_ipv4_checksum(s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +190,7 @@ tag to the driver.
|
|||||||
if (dst && dst->lwtstate) {
|
if (dst && dst->lwtstate) {
|
||||||
struct ip_tunnel_info *tun_info;
|
struct ip_tunnel_info *tun_info;
|
||||||
|
|
||||||
@@ -500,10 +554,15 @@ static void flow_offload_decap_tunnel(co
|
@@ -502,10 +556,15 @@ static void flow_offload_decap_tunnel(co
|
||||||
enum flow_offload_tuple_dir dir,
|
enum flow_offload_tuple_dir dir,
|
||||||
struct nf_flow_rule *flow_rule)
|
struct nf_flow_rule *flow_rule)
|
||||||
{
|
{
|
||||||
@ -205,7 +207,7 @@ tag to the driver.
|
|||||||
if (dst && dst->lwtstate) {
|
if (dst && dst->lwtstate) {
|
||||||
struct ip_tunnel_info *tun_info;
|
struct ip_tunnel_info *tun_info;
|
||||||
|
|
||||||
@@ -515,10 +574,14 @@ static void flow_offload_decap_tunnel(co
|
@@ -517,10 +576,14 @@ static void flow_offload_decap_tunnel(co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +225,7 @@ tag to the driver.
|
|||||||
flow_offload_decap_tunnel(flow, dir, flow_rule);
|
flow_offload_decap_tunnel(flow, dir, flow_rule);
|
||||||
flow_offload_encap_tunnel(flow, dir, flow_rule);
|
flow_offload_encap_tunnel(flow, dir, flow_rule);
|
||||||
|
|
||||||
@@ -526,6 +589,26 @@ int nf_flow_rule_route_ipv4(struct net *
|
@@ -528,6 +591,26 @@ int nf_flow_rule_route_ipv4(struct net *
|
||||||
flow_offload_eth_dst(net, flow, dir, flow_rule) < 0)
|
flow_offload_eth_dst(net, flow, dir, flow_rule) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -250,7 +252,7 @@ tag to the driver.
|
|||||||
if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
||||||
flow_offload_ipv4_snat(net, flow, dir, flow_rule);
|
flow_offload_ipv4_snat(net, flow, dir, flow_rule);
|
||||||
flow_offload_port_snat(net, flow, dir, flow_rule);
|
flow_offload_port_snat(net, flow, dir, flow_rule);
|
||||||
@@ -538,7 +621,7 @@ int nf_flow_rule_route_ipv4(struct net *
|
@@ -540,7 +623,7 @@ int nf_flow_rule_route_ipv4(struct net *
|
||||||
test_bit(NF_FLOW_DNAT, &flow->flags))
|
test_bit(NF_FLOW_DNAT, &flow->flags))
|
||||||
flow_offload_ipv4_checksum(net, flow, flow_rule);
|
flow_offload_ipv4_checksum(net, flow, flow_rule);
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ tag to the driver.
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -548,11 +631,7 @@ int nf_flow_rule_route_ipv6(struct net *
|
@@ -550,11 +633,7 @@ int nf_flow_rule_route_ipv6(struct net *
|
||||||
enum flow_offload_tuple_dir dir,
|
enum flow_offload_tuple_dir dir,
|
||||||
struct nf_flow_rule *flow_rule)
|
struct nf_flow_rule *flow_rule)
|
||||||
{
|
{
|
||||||
@ -272,7 +274,7 @@ tag to the driver.
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
|
||||||
@@ -564,7 +643,7 @@ int nf_flow_rule_route_ipv6(struct net *
|
@@ -566,7 +645,7 @@ int nf_flow_rule_route_ipv6(struct net *
|
||||||
flow_offload_port_dnat(net, flow, dir, flow_rule);
|
flow_offload_port_dnat(net, flow, dir, flow_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +283,7 @@ tag to the driver.
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -578,10 +657,10 @@ nf_flow_offload_rule_alloc(struct net *n
|
@@ -580,10 +659,10 @@ nf_flow_offload_rule_alloc(struct net *n
|
||||||
enum flow_offload_tuple_dir dir)
|
enum flow_offload_tuple_dir dir)
|
||||||
{
|
{
|
||||||
const struct nf_flowtable *flowtable = offload->flowtable;
|
const struct nf_flowtable *flowtable = offload->flowtable;
|
||||||
@ -294,7 +296,7 @@ tag to the driver.
|
|||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
|
|
||||||
flow_rule = kzalloc(sizeof(*flow_rule), GFP_KERNEL);
|
flow_rule = kzalloc(sizeof(*flow_rule), GFP_KERNEL);
|
||||||
@@ -597,7 +676,10 @@ nf_flow_offload_rule_alloc(struct net *n
|
@@ -599,7 +678,10 @@ nf_flow_offload_rule_alloc(struct net *n
|
||||||
flow_rule->rule->match.key = &flow_rule->match.key;
|
flow_rule->rule->match.key = &flow_rule->match.key;
|
||||||
|
|
||||||
tuple = &flow->tuplehash[dir].tuple;
|
tuple = &flow->tuplehash[dir].tuple;
|
@ -1,10 +1,16 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Thu, 4 Mar 2021 19:24:11 +0100
|
Date: Wed, 24 Mar 2021 02:30:47 +0100
|
||||||
Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if
|
Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if
|
||||||
hardware offload is enabled
|
hardware offload is enabled
|
||||||
|
|
||||||
If there is a forward path to reach an ethernet device and hardware
|
If there is a forward path to reach an ethernet device and hardware
|
||||||
offload is enabled, then use the direct xmit path.
|
offload is enabled, then use the direct xmit path.
|
||||||
|
|
||||||
|
Moreover, store the real device in the direct xmit path info since
|
||||||
|
software datapath uses dev_hard_header() to push the layer encapsulation
|
||||||
|
headers while hardware offload refers to the real device.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/include/net/netfilter/nf_flow_table.h
|
--- a/include/net/netfilter/nf_flow_table.h
|
||||||
@ -37,7 +43,7 @@ offload is enabled, then use the direct xmit path.
|
|||||||
case FLOW_OFFLOAD_XMIT_NEIGH:
|
case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||||
--- a/net/netfilter/nf_flow_table_offload.c
|
--- a/net/netfilter/nf_flow_table_offload.c
|
||||||
+++ b/net/netfilter/nf_flow_table_offload.c
|
+++ b/net/netfilter/nf_flow_table_offload.c
|
||||||
@@ -506,7 +506,7 @@ static void flow_offload_redirect(struct
|
@@ -508,7 +508,7 @@ static void flow_offload_redirect(struct
|
||||||
switch (this_tuple->xmit_type) {
|
switch (this_tuple->xmit_type) {
|
||||||
case FLOW_OFFLOAD_XMIT_DIRECT:
|
case FLOW_OFFLOAD_XMIT_DIRECT:
|
||||||
this_tuple = &flow->tuplehash[dir].tuple;
|
this_tuple = &flow->tuplehash[dir].tuple;
|
@ -1,12 +1,13 @@
|
|||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Mon, 8 Mar 2021 12:06:44 +0100
|
Date: Wed, 24 Mar 2021 02:30:48 +0100
|
||||||
Subject: [PATCH] netfilter: nf_flow_table: fix untagging with
|
Subject: [PATCH] netfilter: flowtable: bridge vlan hardware offload and
|
||||||
hardware-offloaded bridge vlan_filtering
|
switchdev
|
||||||
|
|
||||||
When switchdev offloading is enabled, treat an untagged VLAN as tagged for
|
The switch might have already added the VLAN tag through PVID hardware
|
||||||
ingress only
|
offload. Keep this extra VLAN in the flowtable but skip it on egress.
|
||||||
|
|
||||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/include/linux/netdevice.h
|
--- a/include/linux/netdevice.h
|
||||||
@ -78,7 +79,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
|
flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
|
||||||
--- a/net/netfilter/nf_flow_table_offload.c
|
--- a/net/netfilter/nf_flow_table_offload.c
|
||||||
+++ b/net/netfilter/nf_flow_table_offload.c
|
+++ b/net/netfilter/nf_flow_table_offload.c
|
||||||
@@ -592,8 +592,12 @@ nf_flow_rule_route_common(struct net *ne
|
@@ -594,8 +594,12 @@ nf_flow_rule_route_common(struct net *ne
|
||||||
other_tuple = &flow->tuplehash[!dir].tuple;
|
other_tuple = &flow->tuplehash[!dir].tuple;
|
||||||
|
|
||||||
for (i = 0; i < other_tuple->encap_num; i++) {
|
for (i = 0; i < other_tuple->encap_num; i++) {
|
@ -1,7 +1,11 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Tue, 2 Mar 2021 00:51:31 +0100
|
Date: Wed, 24 Mar 2021 02:30:49 +0100
|
||||||
Subject: [PATCH] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH
|
Subject: [PATCH] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH
|
||||||
|
|
||||||
|
Add an action to represent the PPPoE hardware offload support that
|
||||||
|
includes the session ID.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/include/net/flow_offload.h
|
--- a/include/net/flow_offload.h
|
@ -1,13 +1,17 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Tue, 2 Mar 2021 01:01:50 +0100
|
Date: Wed, 24 Mar 2021 02:30:50 +0100
|
||||||
Subject: [PATCH] netfilter: flowtable: support for
|
Subject: [PATCH] netfilter: flowtable: support for
|
||||||
FLOW_ACTION_PPPOE_PUSH
|
FLOW_ACTION_PPPOE_PUSH
|
||||||
|
|
||||||
|
Add a PPPoE push action if layer 2 protocol is ETH_P_PPP_SES to add
|
||||||
|
PPPoE flowtable hardware offload support.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/net/netfilter/nf_flow_table_offload.c
|
--- a/net/netfilter/nf_flow_table_offload.c
|
||||||
+++ b/net/netfilter/nf_flow_table_offload.c
|
+++ b/net/netfilter/nf_flow_table_offload.c
|
||||||
@@ -598,9 +598,18 @@ nf_flow_rule_route_common(struct net *ne
|
@@ -600,9 +600,18 @@ nf_flow_rule_route_common(struct net *ne
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
entry = flow_action_entry_next(flow_rule);
|
entry = flow_action_entry_next(flow_rule);
|
@ -1,5 +1,5 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
Date: Mon, 18 Jan 2021 22:39:17 +0100
|
Date: Wed, 24 Mar 2021 02:30:51 +0100
|
||||||
Subject: [PATCH] dsa: slave: add support for TC_SETUP_FT
|
Subject: [PATCH] dsa: slave: add support for TC_SETUP_FT
|
||||||
|
|
||||||
The dsa infrastructure provides a well-defined hierarchy of devices,
|
The dsa infrastructure provides a well-defined hierarchy of devices,
|
@ -1,11 +1,12 @@
|
|||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Sun, 13 Sep 2020 08:17:02 +0200
|
Date: Wed, 24 Mar 2021 02:30:52 +0100
|
||||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: fix parsing packets in GDM
|
Subject: [PATCH] net: ethernet: mtk_eth_soc: fix parsing packets in GDM
|
||||||
|
|
||||||
When using DSA, set the special tag in GDM ingress control to allow the MAC
|
When using DSA, set the special tag in GDM ingress control to allow the MAC
|
||||||
to parse packets properly earlier. This affects rx DMA source port reporting.
|
to parse packets properly earlier. This affects rx DMA source port reporting.
|
||||||
|
|
||||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@ -18,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
#include "mtk_eth_soc.h"
|
#include "mtk_eth_soc.h"
|
||||||
|
|
||||||
@@ -1263,13 +1264,12 @@ static int mtk_poll_rx(struct napi_struc
|
@@ -1264,13 +1265,12 @@ static int mtk_poll_rx(struct napi_struc
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* find out which mac the packet come from. values start at 1 */
|
/* find out which mac the packet come from. values start at 1 */
|
||||||
@ -37,7 +38,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
|
if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
|
||||||
!eth->netdev[mac]))
|
!eth->netdev[mac]))
|
||||||
@@ -2251,6 +2251,9 @@ static void mtk_gdm_config(struct mtk_et
|
@@ -2233,6 +2233,9 @@ static void mtk_gdm_config(struct mtk_et
|
||||||
|
|
||||||
val |= config;
|
val |= config;
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
/* Reset and enable PSE */
|
/* Reset and enable PSE */
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -82,6 +82,7 @@
|
@@ -81,6 +81,7 @@
|
||||||
|
|
||||||
/* GDM Exgress Control Register */
|
/* GDM Exgress Control Register */
|
||||||
#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000))
|
#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000))
|
||||||
@ -57,7 +58,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#define MTK_GDMA_ICS_EN BIT(22)
|
#define MTK_GDMA_ICS_EN BIT(22)
|
||||||
#define MTK_GDMA_TCS_EN BIT(21)
|
#define MTK_GDMA_TCS_EN BIT(21)
|
||||||
#define MTK_GDMA_UCS_EN BIT(20)
|
#define MTK_GDMA_UCS_EN BIT(20)
|
||||||
@@ -311,6 +312,7 @@
|
@@ -304,6 +305,7 @@
|
||||||
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
|
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
|
||||||
#define RX_DMA_FPORT_SHIFT 19
|
#define RX_DMA_FPORT_SHIFT 19
|
||||||
#define RX_DMA_FPORT_MASK 0x7
|
#define RX_DMA_FPORT_MASK 0x7
|
@ -1,6 +1,6 @@
|
|||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Sun, 11 Oct 2020 22:23:08 +0200
|
Date: Wed, 24 Mar 2021 02:30:53 +0100
|
||||||
Subject: [PATCH] ethernet: mediatek: mtk_eth_soc: add support for
|
Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for
|
||||||
initializing the PPE
|
initializing the PPE
|
||||||
|
|
||||||
The PPE (packet processing engine) is used to offload NAT/routed or even
|
The PPE (packet processing engine) is used to offload NAT/routed or even
|
||||||
@ -9,6 +9,7 @@ hash. It also contains some functionality that will be used to bring up
|
|||||||
flow offloading.
|
flow offloading.
|
||||||
|
|
||||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
---
|
---
|
||||||
create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
|
create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||||
create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.h
|
create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe.h
|
||||||
@ -26,7 +27,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o
|
obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -2284,12 +2284,17 @@ static int mtk_open(struct net_device *d
|
@@ -2258,12 +2258,17 @@ static int mtk_open(struct net_device *d
|
||||||
|
|
||||||
/* we run 2 netdevs on the same dma ring so we only bring it up once */
|
/* we run 2 netdevs on the same dma ring so we only bring it up once */
|
||||||
if (!refcount_read(ð->dma_refcnt)) {
|
if (!refcount_read(ð->dma_refcnt)) {
|
||||||
@ -46,7 +47,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
napi_enable(ð->tx_napi);
|
napi_enable(ð->tx_napi);
|
||||||
napi_enable(ð->rx_napi);
|
napi_enable(ð->rx_napi);
|
||||||
@@ -2359,6 +2364,9 @@ static int mtk_stop(struct net_device *d
|
@@ -2330,6 +2335,9 @@ static int mtk_stop(struct net_device *d
|
||||||
|
|
||||||
mtk_dma_free(eth);
|
mtk_dma_free(eth);
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3148,6 +3156,13 @@ static int mtk_probe(struct platform_dev
|
@@ -3058,6 +3066,13 @@ static int mtk_probe(struct platform_dev
|
||||||
goto err_free_dev;
|
goto err_free_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||||
if (!eth->netdev[i])
|
if (!eth->netdev[i])
|
||||||
continue;
|
continue;
|
||||||
@@ -3222,6 +3237,7 @@ static const struct mtk_soc_data mt7621_
|
@@ -3132,6 +3147,7 @@ static const struct mtk_soc_data mt7621_
|
||||||
.hw_features = MTK_HW_FEATURES,
|
.hw_features = MTK_HW_FEATURES,
|
||||||
.required_clks = MT7621_CLKS_BITMAP,
|
.required_clks = MT7621_CLKS_BITMAP,
|
||||||
.required_pctl = false,
|
.required_pctl = false,
|
||||||
@ -78,7 +79,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct mtk_soc_data mt7622_data = {
|
static const struct mtk_soc_data mt7622_data = {
|
||||||
@@ -3230,6 +3246,7 @@ static const struct mtk_soc_data mt7622_
|
@@ -3140,6 +3156,7 @@ static const struct mtk_soc_data mt7622_
|
||||||
.hw_features = MTK_HW_FEATURES,
|
.hw_features = MTK_HW_FEATURES,
|
||||||
.required_clks = MT7622_CLKS_BITMAP,
|
.required_clks = MT7622_CLKS_BITMAP,
|
||||||
.required_pctl = false,
|
.required_pctl = false,
|
||||||
@ -88,15 +89,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
static const struct mtk_soc_data mt7623_data = {
|
static const struct mtk_soc_data mt7623_data = {
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -16,6 +16,7 @@
|
@@ -15,6 +15,7 @@
|
||||||
|
#include <linux/u64_stats_sync.h>
|
||||||
#include <linux/refcount.h>
|
#include <linux/refcount.h>
|
||||||
#include <linux/phylink.h>
|
#include <linux/phylink.h>
|
||||||
#include <linux/dim.h>
|
|
||||||
+#include "mtk_ppe.h"
|
+#include "mtk_ppe.h"
|
||||||
|
|
||||||
#define MTK_QDMA_PAGE_SIZE 2048
|
#define MTK_QDMA_PAGE_SIZE 2048
|
||||||
#define MTK_MAX_RX_LENGTH 1536
|
#define MTK_MAX_RX_LENGTH 1536
|
||||||
@@ -87,6 +88,7 @@
|
@@ -86,6 +87,7 @@
|
||||||
#define MTK_GDMA_TCS_EN BIT(21)
|
#define MTK_GDMA_TCS_EN BIT(21)
|
||||||
#define MTK_GDMA_UCS_EN BIT(20)
|
#define MTK_GDMA_UCS_EN BIT(20)
|
||||||
#define MTK_GDMA_TO_PDMA 0x0
|
#define MTK_GDMA_TO_PDMA 0x0
|
||||||
@ -104,7 +105,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#define MTK_GDMA_DROP_ALL 0x7777
|
#define MTK_GDMA_DROP_ALL 0x7777
|
||||||
|
|
||||||
/* Unicast Filter MAC Address Register - Low */
|
/* Unicast Filter MAC Address Register - Low */
|
||||||
@@ -308,6 +310,12 @@
|
@@ -301,6 +303,12 @@
|
||||||
#define RX_DMA_VID(_x) ((_x) & 0xfff)
|
#define RX_DMA_VID(_x) ((_x) & 0xfff)
|
||||||
|
|
||||||
/* QDMA descriptor rxd4 */
|
/* QDMA descriptor rxd4 */
|
||||||
@ -117,7 +118,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#define RX_DMA_L4_VALID BIT(24)
|
#define RX_DMA_L4_VALID BIT(24)
|
||||||
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
|
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
|
||||||
#define RX_DMA_FPORT_SHIFT 19
|
#define RX_DMA_FPORT_SHIFT 19
|
||||||
@@ -807,6 +815,7 @@ struct mtk_soc_data {
|
@@ -798,6 +806,7 @@ struct mtk_soc_data {
|
||||||
u32 caps;
|
u32 caps;
|
||||||
u32 required_clks;
|
u32 required_clks;
|
||||||
bool required_pctl;
|
bool required_pctl;
|
||||||
@ -125,7 +126,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
netdev_features_t hw_features;
|
netdev_features_t hw_features;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -918,6 +927,8 @@ struct mtk_eth {
|
@@ -897,6 +906,8 @@ struct mtk_eth {
|
||||||
u32 tx_int_status_reg;
|
u32 tx_int_status_reg;
|
||||||
u32 rx_dma_l4_valid;
|
u32 rx_dma_l4_valid;
|
||||||
int ip_align;
|
int ip_align;
|
||||||
@ -185,7 +186,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
+{
|
+{
|
||||||
+ unsigned long timeout = jiffies + HZ;
|
+ unsigned long timeout = jiffies + HZ;
|
||||||
+
|
+
|
||||||
+ while (time_is_after_jiffies(timeout)) {
|
+ while (time_is_before_jiffies(timeout)) {
|
||||||
+ if (!(ppe_r32(ppe, MTK_PPE_GLO_CFG) & MTK_PPE_GLO_CFG_BUSY))
|
+ if (!(ppe_r32(ppe, MTK_PPE_GLO_CFG) & MTK_PPE_GLO_CFG_BUSY))
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+
|
+
|
@ -1,9 +1,9 @@
|
|||||||
From: Felix Fietkau <nbd@nbd.name>
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
Date: Thu, 10 Dec 2020 12:19:18 +0100
|
Date: Wed, 24 Mar 2021 02:30:54 +0100
|
||||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: add flow offloading support
|
Subject: [PATCH] net: ethernet: mtk_eth_soc: add flow offloading support
|
||||||
|
|
||||||
This adds support for offloading IPv4 routed flows, including SNAT/DNAT,
|
This adds support for offloading IPv4 routed flows, including SNAT/DNAT,
|
||||||
one VLAN, and DSA.
|
one VLAN, PPPoE and DSA.
|
||||||
|
|
||||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
@ -21,7 +21,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o
|
obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -2896,6 +2896,7 @@ static const struct net_device_ops mtk_n
|
@@ -2813,6 +2813,7 @@ static const struct net_device_ops mtk_n
|
||||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
.ndo_poll_controller = mtk_poll_controller,
|
.ndo_poll_controller = mtk_poll_controller,
|
||||||
#endif
|
#endif
|
||||||
@ -29,7 +29,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
||||||
@@ -3161,6 +3162,10 @@ static int mtk_probe(struct platform_dev
|
@@ -3071,6 +3072,10 @@ static int mtk_probe(struct platform_dev
|
||||||
eth->base + MTK_ETH_PPE_BASE, 2);
|
eth->base + MTK_ETH_PPE_BASE, 2);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_free_dev;
|
goto err_free_dev;
|
||||||
@ -42,15 +42,15 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -16,6 +16,7 @@
|
@@ -15,6 +15,7 @@
|
||||||
|
#include <linux/u64_stats_sync.h>
|
||||||
#include <linux/refcount.h>
|
#include <linux/refcount.h>
|
||||||
#include <linux/phylink.h>
|
#include <linux/phylink.h>
|
||||||
#include <linux/dim.h>
|
|
||||||
+#include <linux/rhashtable.h>
|
+#include <linux/rhashtable.h>
|
||||||
#include "mtk_ppe.h"
|
#include "mtk_ppe.h"
|
||||||
|
|
||||||
#define MTK_QDMA_PAGE_SIZE 2048
|
#define MTK_QDMA_PAGE_SIZE 2048
|
||||||
@@ -41,7 +42,8 @@
|
@@ -40,7 +41,8 @@
|
||||||
NETIF_F_HW_VLAN_CTAG_RX | \
|
NETIF_F_HW_VLAN_CTAG_RX | \
|
||||||
NETIF_F_SG | NETIF_F_TSO | \
|
NETIF_F_SG | NETIF_F_TSO | \
|
||||||
NETIF_F_TSO6 | \
|
NETIF_F_TSO6 | \
|
||||||
@ -60,7 +60,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
#define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM)
|
#define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM)
|
||||||
#define NEXT_DESP_IDX(X, Y) (((X) + 1) & ((Y) - 1))
|
#define NEXT_DESP_IDX(X, Y) (((X) + 1) & ((Y) - 1))
|
||||||
|
|
||||||
@@ -929,6 +931,7 @@ struct mtk_eth {
|
@@ -908,6 +910,7 @@ struct mtk_eth {
|
||||||
int ip_align;
|
int ip_align;
|
||||||
|
|
||||||
struct mtk_ppe ppe;
|
struct mtk_ppe ppe;
|
||||||
@ -68,7 +68,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* struct mtk_mac - the structure that holds the info about the MACs of the
|
/* struct mtk_mac - the structure that holds the info about the MACs of the
|
||||||
@@ -973,4 +976,9 @@ int mtk_gmac_sgmii_path_setup(struct mtk
|
@@ -952,4 +955,9 @@ int mtk_gmac_sgmii_path_setup(struct mtk
|
||||||
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
|
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
|
||||||
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
|
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
#endif /* MTK_ETH_H */
|
#endif /* MTK_ETH_H */
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
||||||
@@ -0,0 +1,491 @@
|
@@ -0,0 +1,485 @@
|
||||||
+// SPDX-License-Identifier: GPL-2.0-only
|
+// SPDX-License-Identifier: GPL-2.0-only
|
||||||
+/*
|
+/*
|
||||||
+ * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
|
+ * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
|
||||||
@ -220,12 +220,6 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|||||||
+ if (IS_ERR(dp))
|
+ if (IS_ERR(dp))
|
||||||
+ return -ENODEV;
|
+ return -ENODEV;
|
||||||
+
|
+
|
||||||
+ if (!dp->cpu_dp)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+
|
|
||||||
+ if (!dp->cpu_dp->tag_ops)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+
|
|
||||||
+ if (dp->cpu_dp->tag_ops->proto != DSA_TAG_PROTO_MTK)
|
+ if (dp->cpu_dp->tag_ops->proto != DSA_TAG_PROTO_MTK)
|
||||||
+ return -ENODEV;
|
+ return -ENODEV;
|
||||||
+
|
+
|
@ -0,0 +1,236 @@
|
|||||||
|
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
Date: Wed, 24 Mar 2021 02:30:55 +0100
|
||||||
|
Subject: [PATCH] docs: nf_flowtable: update documentation with
|
||||||
|
enhancements
|
||||||
|
|
||||||
|
This patch updates the flowtable documentation to describe recent
|
||||||
|
enhancements:
|
||||||
|
|
||||||
|
- Offload action is available after the first packets go through the
|
||||||
|
classic forwarding path.
|
||||||
|
- IPv4 and IPv6 are supported. Only TCP and UDP layer 4 are supported at
|
||||||
|
this stage.
|
||||||
|
- Tuple has been augmented to track VLAN id and PPPoE session id.
|
||||||
|
- Bridge and IP forwarding integration, including bridge VLAN filtering
|
||||||
|
support.
|
||||||
|
- Hardware offload support.
|
||||||
|
- Describe the [OFFLOAD] and [HW_OFFLOAD] tags in the conntrack table
|
||||||
|
listing.
|
||||||
|
- Replace 'flow offload' by 'flow add' in example rulesets (preferred
|
||||||
|
syntax).
|
||||||
|
- Describe existing cache limitations.
|
||||||
|
|
||||||
|
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/Documentation/networking/nf_flowtable.rst
|
||||||
|
+++ b/Documentation/networking/nf_flowtable.rst
|
||||||
|
@@ -4,35 +4,38 @@
|
||||||
|
Netfilter's flowtable infrastructure
|
||||||
|
====================================
|
||||||
|
|
||||||
|
-This documentation describes the software flowtable infrastructure available in
|
||||||
|
-Netfilter since Linux kernel 4.16.
|
||||||
|
+This documentation describes the Netfilter flowtable infrastructure which allows
|
||||||
|
+you to define a fastpath through the flowtable datapath. This infrastructure
|
||||||
|
+also provides hardware offload support. The flowtable supports for the layer 3
|
||||||
|
+IPv4 and IPv6 and the layer 4 TCP and UDP protocols.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
-Initial packets follow the classic forwarding path, once the flow enters the
|
||||||
|
-established state according to the conntrack semantics (ie. we have seen traffic
|
||||||
|
-in both directions), then you can decide to offload the flow to the flowtable
|
||||||
|
-from the forward chain via the 'flow offload' action available in nftables.
|
||||||
|
-
|
||||||
|
-Packets that find an entry in the flowtable (ie. flowtable hit) are sent to the
|
||||||
|
-output netdevice via neigh_xmit(), hence, they bypass the classic forwarding
|
||||||
|
-path (the visible effect is that you do not see these packets from any of the
|
||||||
|
-netfilter hooks coming after the ingress). In case of flowtable miss, the packet
|
||||||
|
-follows the classic forward path.
|
||||||
|
-
|
||||||
|
-The flowtable uses a resizable hashtable, lookups are based on the following
|
||||||
|
-7-tuple selectors: source, destination, layer 3 and layer 4 protocols, source
|
||||||
|
-and destination ports and the input interface (useful in case there are several
|
||||||
|
-conntrack zones in place).
|
||||||
|
-
|
||||||
|
-Flowtables are populated via the 'flow offload' nftables action, so the user can
|
||||||
|
-selectively specify what flows are placed into the flow table. Hence, packets
|
||||||
|
-follow the classic forwarding path unless the user explicitly instruct packets
|
||||||
|
-to use this new alternative forwarding path via nftables policy.
|
||||||
|
+Once the first packet of the flow successfully goes through the IP forwarding
|
||||||
|
+path, from the second packet on, you might decide to offload the flow to the
|
||||||
|
+flowtable through your ruleset. The flowtable infrastructure provides a rule
|
||||||
|
+action that allows you to specify when to add a flow to the flowtable.
|
||||||
|
+
|
||||||
|
+A packet that finds a matching entry in the flowtable (ie. flowtable hit) is
|
||||||
|
+transmitted to the output netdevice via neigh_xmit(), hence, packets bypass the
|
||||||
|
+classic IP forwarding path (the visible effect is that you do not see these
|
||||||
|
+packets from any of the Netfilter hooks coming after ingress). In case that
|
||||||
|
+there is no matching entry in the flowtable (ie. flowtable miss), the packet
|
||||||
|
+follows the classic IP forwarding path.
|
||||||
|
+
|
||||||
|
+The flowtable uses a resizable hashtable. Lookups are based on the following
|
||||||
|
+n-tuple selectors: layer 2 protocol encapsulation (VLAN and PPPoE), layer 3
|
||||||
|
+source and destination, layer 4 source and destination ports and the input
|
||||||
|
+interface (useful in case there are several conntrack zones in place).
|
||||||
|
+
|
||||||
|
+The 'flow add' action allows you to populate the flowtable, the user selectively
|
||||||
|
+specifies what flows are placed into the flowtable. Hence, packets follow the
|
||||||
|
+classic IP forwarding path unless the user explicitly instruct flows to use this
|
||||||
|
+new alternative forwarding path via policy.
|
||||||
|
|
||||||
|
-This is represented in Fig.1, which describes the classic forwarding path
|
||||||
|
-including the Netfilter hooks and the flowtable fastpath bypass.
|
||||||
|
+The flowtable datapath is represented in Fig.1, which describes the classic IP
|
||||||
|
+forwarding path including the Netfilter hooks and the flowtable fastpath bypass.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
@@ -67,11 +70,13 @@ including the Netfilter hooks and the fl
|
||||||
|
Fig.1 Netfilter hooks and flowtable interactions
|
||||||
|
|
||||||
|
The flowtable entry also stores the NAT configuration, so all packets are
|
||||||
|
-mangled according to the NAT policy that matches the initial packets that went
|
||||||
|
-through the classic forwarding path. The TTL is decremented before calling
|
||||||
|
-neigh_xmit(). Fragmented traffic is passed up to follow the classic forwarding
|
||||||
|
-path given that the transport selectors are missing, therefore flowtable lookup
|
||||||
|
-is not possible.
|
||||||
|
+mangled according to the NAT policy that is specified from the classic IP
|
||||||
|
+forwarding path. The TTL is decremented before calling neigh_xmit(). Fragmented
|
||||||
|
+traffic is passed up to follow the classic IP forwarding path given that the
|
||||||
|
+transport header is missing, in this case, flowtable lookups are not possible.
|
||||||
|
+TCP RST and FIN packets are also passed up to the classic IP forwarding path to
|
||||||
|
+release the flow gracefully. Packets that exceed the MTU are also passed up to
|
||||||
|
+the classic forwarding path to report packet-too-big ICMP errors to the sender.
|
||||||
|
|
||||||
|
Example configuration
|
||||||
|
---------------------
|
||||||
|
@@ -85,7 +90,7 @@ flowtable and add one rule to your forwa
|
||||||
|
}
|
||||||
|
chain y {
|
||||||
|
type filter hook forward priority 0; policy accept;
|
||||||
|
- ip protocol tcp flow offload @f
|
||||||
|
+ ip protocol tcp flow add @f
|
||||||
|
counter packets 0 bytes 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -103,6 +108,117 @@ flow is offloaded, you will observe that
|
||||||
|
does not get updated for the packets that are being forwarded through the
|
||||||
|
forwarding bypass.
|
||||||
|
|
||||||
|
+You can identify offloaded flows through the [OFFLOAD] tag when listing your
|
||||||
|
+connection tracking table.
|
||||||
|
+
|
||||||
|
+::
|
||||||
|
+ # conntrack -L
|
||||||
|
+ tcp 6 src=10.141.10.2 dst=192.168.10.2 sport=52728 dport=5201 src=192.168.10.2 dst=192.168.10.1 sport=5201 dport=52728 [OFFLOAD] mark=0 use=2
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+Layer 2 encapsulation
|
||||||
|
+---------------------
|
||||||
|
+
|
||||||
|
+Since Linux kernel 5.13, the flowtable infrastructure discovers the real
|
||||||
|
+netdevice behind VLAN and PPPoE netdevices. The flowtable software datapath
|
||||||
|
+parses the VLAN and PPPoE layer 2 headers to extract the ethertype and the
|
||||||
|
+VLAN ID / PPPoE session ID which are used for the flowtable lookups. The
|
||||||
|
+flowtable datapath also deals with layer 2 decapsulation.
|
||||||
|
+
|
||||||
|
+You do not need to add the PPPoE and the VLAN devices to your flowtable,
|
||||||
|
+instead the real device is sufficient for the flowtable to track your flows.
|
||||||
|
+
|
||||||
|
+Bridge and IP forwarding
|
||||||
|
+------------------------
|
||||||
|
+
|
||||||
|
+Since Linux kernel 5.13, you can add bridge ports to the flowtable. The
|
||||||
|
+flowtable infrastructure discovers the topology behind the bridge device. This
|
||||||
|
+allows the flowtable to define a fastpath bypass between the bridge ports
|
||||||
|
+(represented as eth1 and eth2 in the example figure below) and the gateway
|
||||||
|
+device (represented as eth0) in your switch/router.
|
||||||
|
+
|
||||||
|
+::
|
||||||
|
+ fastpath bypass
|
||||||
|
+ .-------------------------.
|
||||||
|
+ / \
|
||||||
|
+ | IP forwarding |
|
||||||
|
+ | / \ \/
|
||||||
|
+ | br0 eth0 ..... eth0
|
||||||
|
+ . / \ *host B*
|
||||||
|
+ -> eth1 eth2
|
||||||
|
+ . *switch/router*
|
||||||
|
+ .
|
||||||
|
+ .
|
||||||
|
+ eth0
|
||||||
|
+ *host A*
|
||||||
|
+
|
||||||
|
+The flowtable infrastructure also supports for bridge VLAN filtering actions
|
||||||
|
+such as PVID and untagged. You can also stack a classic VLAN device on top of
|
||||||
|
+your bridge port.
|
||||||
|
+
|
||||||
|
+If you would like that your flowtable defines a fastpath between your bridge
|
||||||
|
+ports and your IP forwarding path, you have to add your bridge ports (as
|
||||||
|
+represented by the real netdevice) to your flowtable definition.
|
||||||
|
+
|
||||||
|
+Counters
|
||||||
|
+--------
|
||||||
|
+
|
||||||
|
+The flowtable can synchronize packet and byte counters with the existing
|
||||||
|
+connection tracking entry by specifying the counter statement in your flowtable
|
||||||
|
+definition, e.g.
|
||||||
|
+
|
||||||
|
+::
|
||||||
|
+ table inet x {
|
||||||
|
+ flowtable f {
|
||||||
|
+ hook ingress priority 0; devices = { eth0, eth1 };
|
||||||
|
+ counter
|
||||||
|
+ }
|
||||||
|
+ ...
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+Counter support is available since Linux kernel 5.7.
|
||||||
|
+
|
||||||
|
+Hardware offload
|
||||||
|
+----------------
|
||||||
|
+
|
||||||
|
+If your network device provides hardware offload support, you can turn it on by
|
||||||
|
+means of the 'offload' flag in your flowtable definition, e.g.
|
||||||
|
+
|
||||||
|
+::
|
||||||
|
+ table inet x {
|
||||||
|
+ flowtable f {
|
||||||
|
+ hook ingress priority 0; devices = { eth0, eth1 };
|
||||||
|
+ flags offload;
|
||||||
|
+ }
|
||||||
|
+ ...
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+There is a workqueue that adds the flows to the hardware. Note that a few
|
||||||
|
+packets might still run over the flowtable software path until the workqueue has
|
||||||
|
+a chance to offload the flow to the network device.
|
||||||
|
+
|
||||||
|
+You can identify hardware offloaded flows through the [HW_OFFLOAD] tag when
|
||||||
|
+listing your connection tracking table. Please, note that the [OFFLOAD] tag
|
||||||
|
+refers to the software offload mode, so there is a distinction between [OFFLOAD]
|
||||||
|
+which refers to the software flowtable fastpath and [HW_OFFLOAD] which refers
|
||||||
|
+to the hardware offload datapath being used by the flow.
|
||||||
|
+
|
||||||
|
+The flowtable hardware offload infrastructure also supports for the DSA
|
||||||
|
+(Distributed Switch Architecture).
|
||||||
|
+
|
||||||
|
+Limitations
|
||||||
|
+-----------
|
||||||
|
+
|
||||||
|
+The flowtable behaves like a cache. The flowtable entries might get stale if
|
||||||
|
+either the destination MAC address or the egress netdevice that is used for
|
||||||
|
+transmission changes.
|
||||||
|
+
|
||||||
|
+This might be a problem if:
|
||||||
|
+
|
||||||
|
+- You run the flowtable in software mode and you combine bridge and IP
|
||||||
|
+ forwarding in your setup.
|
||||||
|
+- Hardware offload is enabled.
|
||||||
|
+
|
||||||
|
More reading
|
||||||
|
------------
|
||||||
|
|
@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
|
|
||||||
--- a/net/dsa/slave.c
|
--- a/net/dsa/slave.c
|
||||||
+++ b/net/dsa/slave.c
|
+++ b/net/dsa/slave.c
|
||||||
@@ -2075,7 +2075,9 @@ static void dsa_slave_switchdev_event_wo
|
@@ -2109,7 +2109,9 @@ static void dsa_slave_switchdev_event_wo
|
||||||
|
|
||||||
err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid);
|
err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fdb_info->offloaded = true;
|
fdb_info->offloaded = true;
|
||||||
@@ -2090,9 +2092,11 @@ static void dsa_slave_switchdev_event_wo
|
@@ -2124,9 +2126,11 @@ static void dsa_slave_switchdev_event_wo
|
||||||
|
|
||||||
err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid);
|
err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
struct sk_buff * (*xmit)(struct sk_buff *skb,
|
struct sk_buff * (*xmit)(struct sk_buff *skb,
|
||||||
--- a/net/dsa/slave.c
|
--- a/net/dsa/slave.c
|
||||||
+++ b/net/dsa/slave.c
|
+++ b/net/dsa/slave.c
|
||||||
@@ -2050,76 +2050,66 @@ static int dsa_slave_netdevice_event(str
|
@@ -2084,76 +2084,66 @@ static int dsa_slave_netdevice_event(str
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Called under rcu_read_lock() */
|
/* Called under rcu_read_lock() */
|
||||||
@@ -2127,7 +2117,9 @@ static int dsa_slave_switchdev_event(str
|
@@ -2161,7 +2151,9 @@ static int dsa_slave_switchdev_event(str
|
||||||
unsigned long event, void *ptr)
|
unsigned long event, void *ptr)
|
||||||
{
|
{
|
||||||
struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
|
struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
|
||||||
@ -177,7 +177,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (event == SWITCHDEV_PORT_ATTR_SET) {
|
if (event == SWITCHDEV_PORT_ATTR_SET) {
|
||||||
@@ -2140,20 +2132,32 @@ static int dsa_slave_switchdev_event(str
|
@@ -2174,20 +2166,32 @@ static int dsa_slave_switchdev_event(str
|
||||||
if (!dsa_slave_dev_check(dev))
|
if (!dsa_slave_dev_check(dev))
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -2163,10 +2167,6 @@ static int dsa_slave_switchdev_event(str
|
@@ -2197,10 +2201,6 @@ static int dsa_slave_switchdev_event(str
|
||||||
|
|
||||||
dsa_schedule_work(&switchdev_work->work);
|
dsa_schedule_work(&switchdev_work->work);
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
|
@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
|
|
||||||
--- a/net/dsa/slave.c
|
--- a/net/dsa/slave.c
|
||||||
+++ b/net/dsa/slave.c
|
+++ b/net/dsa/slave.c
|
||||||
@@ -2122,31 +2122,29 @@ static int dsa_slave_switchdev_event(str
|
@@ -2156,31 +2156,29 @@ static int dsa_slave_switchdev_event(str
|
||||||
struct dsa_port *dp;
|
struct dsa_port *dp;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
fdb_info = ptr;
|
fdb_info = ptr;
|
||||||
|
|
||||||
if (!fdb_info->added_by_user) {
|
if (!fdb_info->added_by_user) {
|
||||||
@@ -2159,13 +2157,12 @@ static int dsa_slave_switchdev_event(str
|
@@ -2193,13 +2191,12 @@ static int dsa_slave_switchdev_event(str
|
||||||
switchdev_work->vid = fdb_info->vid;
|
switchdev_work->vid = fdb_info->vid;
|
||||||
|
|
||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
|
@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
|
|
||||||
--- a/net/dsa/slave.c
|
--- a/net/dsa/slave.c
|
||||||
+++ b/net/dsa/slave.c
|
+++ b/net/dsa/slave.c
|
||||||
@@ -2135,6 +2135,9 @@ static int dsa_slave_switchdev_event(str
|
@@ -2169,6 +2169,9 @@ static int dsa_slave_switchdev_event(str
|
||||||
|
|
||||||
dp = dsa_slave_to_port(dev);
|
dp = dsa_slave_to_port(dev);
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
*/
|
*/
|
||||||
--- a/net/dsa/slave.c
|
--- a/net/dsa/slave.c
|
||||||
+++ b/net/dsa/slave.c
|
+++ b/net/dsa/slave.c
|
||||||
@@ -2112,6 +2112,28 @@ static void dsa_slave_switchdev_event_wo
|
@@ -2146,6 +2146,28 @@ static void dsa_slave_switchdev_event_wo
|
||||||
dev_put(dp->slave);
|
dev_put(dp->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
/* Called under rcu_read_lock() */
|
/* Called under rcu_read_lock() */
|
||||||
static int dsa_slave_switchdev_event(struct notifier_block *unused,
|
static int dsa_slave_switchdev_event(struct notifier_block *unused,
|
||||||
unsigned long event, void *ptr)
|
unsigned long event, void *ptr)
|
||||||
@@ -2130,10 +2152,37 @@ static int dsa_slave_switchdev_event(str
|
@@ -2164,10 +2186,37 @@ static int dsa_slave_switchdev_event(str
|
||||||
return notifier_from_errno(err);
|
return notifier_from_errno(err);
|
||||||
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
case SWITCHDEV_FDB_ADD_TO_DEVICE:
|
||||||
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
case SWITCHDEV_FDB_DEL_TO_DEVICE:
|
||||||
@ -240,7 +240,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
|
|
||||||
if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del)
|
if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del)
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
@@ -2148,18 +2197,13 @@ static int dsa_slave_switchdev_event(str
|
@@ -2182,18 +2231,13 @@ static int dsa_slave_switchdev_event(str
|
||||||
switchdev_work->port = dp->index;
|
switchdev_work->port = dp->index;
|
||||||
switchdev_work->event = event;
|
switchdev_work->event = event;
|
||||||
|
|
||||||
|
@ -815,6 +815,6 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
+ void (*iter)(struct flow_offload *flow, void *data),
|
+ void (*iter)(struct flow_offload *flow, void *data),
|
||||||
+ void *data);
|
+ void *data);
|
||||||
+
|
+
|
||||||
int nf_flow_snat_port(const struct flow_offload *flow,
|
void nf_flow_snat_port(const struct flow_offload *flow,
|
||||||
struct sk_buff *skb, unsigned int thoff,
|
struct sk_buff *skb, unsigned int thoff,
|
||||||
u8 protocol, enum flow_offload_tuple_dir dir);
|
u8 protocol, enum flow_offload_tuple_dir dir);
|
||||||
|
@ -1,263 +0,0 @@
|
|||||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
|
||||||
Date: Mon, 1 Mar 2021 23:52:49 +0100
|
|
||||||
Subject: [PATCH] netfilter: flowtable: add pppoe support
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
--- a/drivers/net/ppp/ppp_generic.c
|
|
||||||
+++ b/drivers/net/ppp/ppp_generic.c
|
|
||||||
@@ -1453,7 +1453,7 @@ static void ppp_dev_priv_destructor(stru
|
|
||||||
static int ppp_fill_forward_path(struct net_device_path_ctx *ctx,
|
|
||||||
struct net_device_path *path)
|
|
||||||
{
|
|
||||||
- struct ppp *ppp = netdev_priv(path->dev);
|
|
||||||
+ struct ppp *ppp = netdev_priv(ctx->dev);
|
|
||||||
struct ppp_channel *chan;
|
|
||||||
struct channel *pch;
|
|
||||||
|
|
||||||
--- a/drivers/net/ppp/pppoe.c
|
|
||||||
+++ b/drivers/net/ppp/pppoe.c
|
|
||||||
@@ -987,6 +987,7 @@ static int pppoe_fill_forward_path(struc
|
|
||||||
path->type = DEV_PATH_PPPOE;
|
|
||||||
path->encap.proto = htons(ETH_P_PPP_SES);
|
|
||||||
path->encap.id = be16_to_cpu(po->num);
|
|
||||||
+ memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN);
|
|
||||||
path->dev = ctx->dev;
|
|
||||||
ctx->dev = dev;
|
|
||||||
|
|
||||||
--- a/include/linux/netdevice.h
|
|
||||||
+++ b/include/linux/netdevice.h
|
|
||||||
@@ -842,6 +842,7 @@ struct net_device_path {
|
|
||||||
struct {
|
|
||||||
u16 id;
|
|
||||||
__be16 proto;
|
|
||||||
+ u8 h_dest[ETH_ALEN];
|
|
||||||
} encap;
|
|
||||||
struct {
|
|
||||||
enum {
|
|
||||||
--- a/net/netfilter/nf_flow_table_ip.c
|
|
||||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
|
||||||
@@ -7,6 +7,9 @@
|
|
||||||
#include <linux/ip.h>
|
|
||||||
#include <linux/ipv6.h>
|
|
||||||
#include <linux/netdevice.h>
|
|
||||||
+#include <linux/if_ether.h>
|
|
||||||
+#include <linux/if_pppox.h>
|
|
||||||
+#include <linux/ppp_defs.h>
|
|
||||||
#include <net/ip.h>
|
|
||||||
#include <net/ipv6.h>
|
|
||||||
#include <net/ip6_route.h>
|
|
||||||
@@ -162,6 +165,8 @@ static bool ip_has_options(unsigned int
|
|
||||||
static void nf_flow_tuple_encap(struct sk_buff *skb,
|
|
||||||
struct flow_offload_tuple *tuple)
|
|
||||||
{
|
|
||||||
+ struct vlan_ethhdr *veth;
|
|
||||||
+ struct pppoe_hdr *phdr;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (skb_vlan_tag_present(skb)) {
|
|
||||||
@@ -169,23 +174,35 @@ static void nf_flow_tuple_encap(struct s
|
|
||||||
tuple->encap[i].proto = skb->vlan_proto;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q)) {
|
|
||||||
- struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
|
||||||
-
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case htons(ETH_P_8021Q):
|
|
||||||
+ veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
|
||||||
tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
|
|
||||||
tuple->encap[i].proto = skb->protocol;
|
|
||||||
+ break;
|
|
||||||
+ case htons(ETH_P_PPP_SES):
|
|
||||||
+ phdr = (struct pppoe_hdr *)skb_mac_header(skb);
|
|
||||||
+ tuple->encap[i].id = ntohs(phdr->sid);
|
|
||||||
+ tuple->encap[i].proto = skb->protocol;
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
|
||||||
- struct flow_offload_tuple *tuple)
|
|
||||||
+ struct flow_offload_tuple *tuple, u32 *nhoff)
|
|
||||||
{
|
|
||||||
unsigned int thoff, hdrsize, offset = 0;
|
|
||||||
struct flow_ports *ports;
|
|
||||||
struct iphdr *iph;
|
|
||||||
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case htons(ETH_P_8021Q):
|
|
||||||
offset += VLAN_HLEN;
|
|
||||||
+ break;
|
|
||||||
+ case htons(ETH_P_PPP_SES):
|
|
||||||
+ offset += PPPOE_SES_HLEN;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof(*iph) + offset))
|
|
||||||
return -1;
|
|
||||||
@@ -226,6 +243,7 @@ static int nf_flow_tuple_ip(struct sk_bu
|
|
||||||
tuple->l4proto = iph->protocol;
|
|
||||||
tuple->iifidx = dev->ifindex;
|
|
||||||
nf_flow_tuple_encap(skb, tuple);
|
|
||||||
+ *nhoff = offset;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -270,14 +288,36 @@ static unsigned int nf_flow_xmit_xfrm(st
|
|
||||||
return NF_STOLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ __be16 proto;
|
|
||||||
+
|
|
||||||
+ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
|
|
||||||
+ sizeof(struct pppoe_hdr)));
|
|
||||||
+ switch (proto) {
|
|
||||||
+ case htons(PPP_IP):
|
|
||||||
+ return htons(ETH_P_IP);
|
|
||||||
+ case htons(PPP_IPV6):
|
|
||||||
+ return htons(ETH_P_IPV6);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto)
|
|
||||||
{
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q)) {
|
|
||||||
- struct vlan_ethhdr *veth;
|
|
||||||
+ struct vlan_ethhdr *veth;
|
|
||||||
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case htons(ETH_P_8021Q):
|
|
||||||
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
|
|
||||||
if (veth->h_vlan_encapsulated_proto == proto)
|
|
||||||
return true;
|
|
||||||
+ break;
|
|
||||||
+ case htons(ETH_P_PPP_SES):
|
|
||||||
+ if (nf_flow_pppoe_proto(skb) == proto)
|
|
||||||
+ return true;
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
@@ -294,12 +334,18 @@ static void nf_flow_encap_pop(struct sk_
|
|
||||||
__vlan_hwaccel_clear_tag(skb);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q)) {
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case htons(ETH_P_8021Q):
|
|
||||||
vlan_hdr = (struct vlan_hdr *)skb->data;
|
|
||||||
__skb_pull(skb, VLAN_HLEN);
|
|
||||||
vlan_set_encap_proto(skb, vlan_hdr);
|
|
||||||
skb_reset_network_header(skb);
|
|
||||||
break;
|
|
||||||
+ case htons(ETH_P_PPP_SES):
|
|
||||||
+ skb->protocol = nf_flow_pppoe_proto(skb);
|
|
||||||
+ skb_pull(skb, PPPOE_SES_HLEN);
|
|
||||||
+ skb_reset_network_header(skb);
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -343,7 +389,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
|
||||||
!nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP)))
|
|
||||||
return NF_ACCEPT;
|
|
||||||
|
|
||||||
- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0)
|
|
||||||
+ if (nf_flow_tuple_ip(skb, state->in, &tuple, &offset) < 0)
|
|
||||||
return NF_ACCEPT;
|
|
||||||
|
|
||||||
tuplehash = flow_offload_lookup(flow_table, &tuple);
|
|
||||||
@@ -357,9 +403,6 @@ nf_flow_offload_ip_hook(void *priv, stru
|
|
||||||
if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
|
|
||||||
return NF_ACCEPT;
|
|
||||||
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
- offset += VLAN_HLEN;
|
|
||||||
-
|
|
||||||
if (skb_try_make_writable(skb, sizeof(*iph) + offset))
|
|
||||||
return NF_DROP;
|
|
||||||
|
|
||||||
@@ -543,14 +586,20 @@ static int nf_flow_nat_ipv6(const struct
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
|
||||||
- struct flow_offload_tuple *tuple)
|
|
||||||
+ struct flow_offload_tuple *tuple, u32 *nhoff)
|
|
||||||
{
|
|
||||||
unsigned int thoff, hdrsize, offset = 0;
|
|
||||||
struct flow_ports *ports;
|
|
||||||
struct ipv6hdr *ip6h;
|
|
||||||
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case htons(ETH_P_8021Q):
|
|
||||||
offset += VLAN_HLEN;
|
|
||||||
+ break;
|
|
||||||
+ case htons(ETH_P_PPP_SES):
|
|
||||||
+ offset += PPPOE_SES_HLEN;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof(*ip6h) + offset))
|
|
||||||
return -1;
|
|
||||||
@@ -586,6 +635,7 @@ static int nf_flow_tuple_ipv6(struct sk_
|
|
||||||
tuple->l4proto = ip6h->nexthdr;
|
|
||||||
tuple->iifidx = dev->ifindex;
|
|
||||||
nf_flow_tuple_encap(skb, tuple);
|
|
||||||
+ *nhoff = offset;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -611,7 +661,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
|
||||||
!nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6)))
|
|
||||||
return NF_ACCEPT;
|
|
||||||
|
|
||||||
- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0)
|
|
||||||
+ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &offset) < 0)
|
|
||||||
return NF_ACCEPT;
|
|
||||||
|
|
||||||
tuplehash = flow_offload_lookup(flow_table, &tuple);
|
|
||||||
@@ -625,9 +675,6 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
|
||||||
if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
|
|
||||||
return NF_ACCEPT;
|
|
||||||
|
|
||||||
- if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
- offset += VLAN_HLEN;
|
|
||||||
-
|
|
||||||
ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
|
||||||
if (nf_flow_state_check(flow, ip6h->nexthdr, skb, sizeof(*ip6h)))
|
|
||||||
return NF_ACCEPT;
|
|
||||||
--- a/net/netfilter/nft_flow_offload.c
|
|
||||||
+++ b/net/netfilter/nft_flow_offload.c
|
|
||||||
@@ -90,6 +90,7 @@ static void nft_dev_path_info(const stru
|
|
||||||
switch (path->type) {
|
|
||||||
case DEV_PATH_ETHERNET:
|
|
||||||
case DEV_PATH_VLAN:
|
|
||||||
+ case DEV_PATH_PPPOE:
|
|
||||||
info->indev = path->dev;
|
|
||||||
if (is_zero_ether_addr(info->h_source))
|
|
||||||
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
|
||||||
@@ -97,7 +98,7 @@ static void nft_dev_path_info(const stru
|
|
||||||
if (path->type == DEV_PATH_ETHERNET)
|
|
||||||
break;
|
|
||||||
|
|
||||||
- /* DEV_PATH_VLAN */
|
|
||||||
+ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */
|
|
||||||
if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
|
|
||||||
info->indev = NULL;
|
|
||||||
break;
|
|
||||||
@@ -106,6 +107,8 @@ static void nft_dev_path_info(const stru
|
|
||||||
info->encap[info->num_encaps].id = path->encap.id;
|
|
||||||
info->encap[info->num_encaps].proto = path->encap.proto;
|
|
||||||
info->num_encaps++;
|
|
||||||
+ if (path->type == DEV_PATH_PPPOE)
|
|
||||||
+ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN);
|
|
||||||
break;
|
|
||||||
case DEV_PATH_BRIDGE:
|
|
||||||
if (is_zero_ether_addr(info->h_source))
|
|
@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -857,7 +857,8 @@ static int txd_to_idx(struct mtk_tx_ring
|
@@ -858,7 +858,8 @@ static int txd_to_idx(struct mtk_tx_ring
|
||||||
return ((void *)dma - (void *)ring->dma) / sizeof(*dma);
|
return ((void *)dma - (void *)ring->dma) / sizeof(*dma);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
{
|
{
|
||||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
|
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
|
||||||
if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) {
|
if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) {
|
||||||
@@ -889,8 +890,12 @@ static void mtk_tx_unmap(struct mtk_eth
|
@@ -890,8 +891,12 @@ static void mtk_tx_unmap(struct mtk_eth
|
||||||
|
|
||||||
tx_buf->flags = 0;
|
tx_buf->flags = 0;
|
||||||
if (tx_buf->skb &&
|
if (tx_buf->skb &&
|
||||||
@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
tx_buf->skb = NULL;
|
tx_buf->skb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1068,7 +1073,7 @@ err_dma:
|
@@ -1069,7 +1074,7 @@ err_dma:
|
||||||
tx_buf = mtk_desc_to_tx_buf(ring, itxd);
|
tx_buf = mtk_desc_to_tx_buf(ring, itxd);
|
||||||
|
|
||||||
/* unmap dma */
|
/* unmap dma */
|
||||||
|
@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -85,7 +85,7 @@ static int mtk_mdio_busy_wait(struct mtk
|
@@ -86,7 +86,7 @@ static int mtk_mdio_busy_wait(struct mtk
|
||||||
return 0;
|
return 0;
|
||||||
if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT))
|
if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT))
|
||||||
break;
|
break;
|
||||||
|
@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
skb_record_rx_queue(skb, 0);
|
skb_record_rx_queue(skb, 0);
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -295,6 +295,7 @@
|
@@ -300,6 +300,7 @@
|
||||||
#define RX_DMA_LSO BIT(30)
|
#define RX_DMA_LSO BIT(30)
|
||||||
#define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16)
|
#define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16)
|
||||||
#define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff)
|
#define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff)
|
||||||
|
@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -1130,17 +1130,6 @@ static void mtk_wake_queue(struct mtk_et
|
@@ -1131,17 +1131,6 @@ static void mtk_wake_queue(struct mtk_et
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct mtk_mac *mac = netdev_priv(dev);
|
struct mtk_mac *mac = netdev_priv(dev);
|
||||||
@@ -1161,7 +1150,7 @@ static netdev_tx_t mtk_start_xmit(struct
|
@@ -1162,7 +1151,7 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||||
|
|
||||||
tx_num = mtk_cal_txd_req(skb);
|
tx_num = mtk_cal_txd_req(skb);
|
||||||
if (unlikely(atomic_read(&ring->free_count) <= tx_num)) {
|
if (unlikely(atomic_read(&ring->free_count) <= tx_num)) {
|
||||||
@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
netif_err(eth, tx_queued, dev,
|
netif_err(eth, tx_queued, dev,
|
||||||
"Tx Ring full when queue awake!\n");
|
"Tx Ring full when queue awake!\n");
|
||||||
spin_unlock(ð->page_lock);
|
spin_unlock(ð->page_lock);
|
||||||
@@ -1187,7 +1176,7 @@ static netdev_tx_t mtk_start_xmit(struct
|
@@ -1188,7 +1177,7 @@ static netdev_tx_t mtk_start_xmit(struct
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
|
if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
|
||||||
|
@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
MTK_QDMA_GLO_CFG);
|
MTK_QDMA_GLO_CFG);
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -197,7 +197,7 @@
|
@@ -202,7 +202,7 @@
|
||||||
#define MTK_RX_BT_32DWORDS (3 << 11)
|
#define MTK_RX_BT_32DWORDS (3 << 11)
|
||||||
#define MTK_NDP_CO_PRO BIT(10)
|
#define MTK_NDP_CO_PRO BIT(10)
|
||||||
#define MTK_TX_WB_DDONE BIT(6)
|
#define MTK_TX_WB_DDONE BIT(6)
|
||||||
|
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -19,7 +19,7 @@
|
@@ -21,7 +21,7 @@
|
||||||
#define MTK_QDMA_PAGE_SIZE 2048
|
#define MTK_QDMA_PAGE_SIZE 2048
|
||||||
#define MTK_MAX_RX_LENGTH 1536
|
#define MTK_MAX_RX_LENGTH 1536
|
||||||
#define MTK_TX_DMA_BUF_LEN 0x3fff
|
#define MTK_TX_DMA_BUF_LEN 0x3fff
|
||||||
|
@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
MediaTek SoC family.
|
MediaTek SoC family.
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -1232,12 +1232,13 @@ static void mtk_update_rx_cpu_idx(struct
|
@@ -1233,12 +1233,13 @@ static void mtk_update_rx_cpu_idx(struct
|
||||||
static int mtk_poll_rx(struct napi_struct *napi, int budget,
|
static int mtk_poll_rx(struct napi_struct *napi, int budget,
|
||||||
struct mtk_eth *eth)
|
struct mtk_eth *eth)
|
||||||
{
|
{
|
||||||
@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
if (likely(napi_schedule_prep(ð->tx_napi))) {
|
if (likely(napi_schedule_prep(ð->tx_napi))) {
|
||||||
__napi_schedule(ð->tx_napi);
|
__napi_schedule(ð->tx_napi);
|
||||||
mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
|
mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
|
||||||
@@ -2315,6 +2332,9 @@ static int mtk_stop(struct net_device *d
|
@@ -2323,6 +2340,9 @@ static int mtk_stop(struct net_device *d
|
||||||
napi_disable(ð->tx_napi);
|
napi_disable(ð->tx_napi);
|
||||||
napi_disable(ð->rx_napi);
|
napi_disable(ð->rx_napi);
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
|
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
|
||||||
mtk_stop_dma(eth, MTK_QDMA_GLO_CFG);
|
mtk_stop_dma(eth, MTK_QDMA_GLO_CFG);
|
||||||
mtk_stop_dma(eth, MTK_PDMA_GLO_CFG);
|
mtk_stop_dma(eth, MTK_PDMA_GLO_CFG);
|
||||||
@@ -2364,6 +2384,64 @@ err_disable_clks:
|
@@ -2375,6 +2395,64 @@ err_disable_clks:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
static int mtk_hw_init(struct mtk_eth *eth)
|
static int mtk_hw_init(struct mtk_eth *eth)
|
||||||
{
|
{
|
||||||
int i, val, ret;
|
int i, val, ret;
|
||||||
@@ -2385,9 +2463,6 @@ static int mtk_hw_init(struct mtk_eth *e
|
@@ -2396,9 +2474,6 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||||
goto err_disable_pm;
|
goto err_disable_pm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
/* disable delay and normal interrupt */
|
/* disable delay and normal interrupt */
|
||||||
mtk_tx_irq_disable(eth, ~0);
|
mtk_tx_irq_disable(eth, ~0);
|
||||||
mtk_rx_irq_disable(eth, ~0);
|
mtk_rx_irq_disable(eth, ~0);
|
||||||
@@ -2426,11 +2501,10 @@ static int mtk_hw_init(struct mtk_eth *e
|
@@ -2437,11 +2512,10 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||||
/* Enable RX VLan Offloading */
|
/* Enable RX VLan Offloading */
|
||||||
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
|
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
mtk_tx_irq_disable(eth, ~0);
|
mtk_tx_irq_disable(eth, ~0);
|
||||||
mtk_rx_irq_disable(eth, ~0);
|
mtk_rx_irq_disable(eth, ~0);
|
||||||
|
|
||||||
@@ -2934,6 +3008,13 @@ static int mtk_probe(struct platform_dev
|
@@ -2946,6 +3020,13 @@ static int mtk_probe(struct platform_dev
|
||||||
spin_lock_init(ð->page_lock);
|
spin_lock_init(ð->page_lock);
|
||||||
spin_lock_init(ð->tx_irq_lock);
|
spin_lock_init(ð->tx_irq_lock);
|
||||||
spin_lock_init(ð->rx_irq_lock);
|
spin_lock_init(ð->rx_irq_lock);
|
||||||
@ -210,15 +210,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -15,6 +15,7 @@
|
@@ -16,6 +16,7 @@
|
||||||
#include <linux/u64_stats_sync.h>
|
|
||||||
#include <linux/refcount.h>
|
#include <linux/refcount.h>
|
||||||
#include <linux/phylink.h>
|
#include <linux/phylink.h>
|
||||||
|
#include <linux/rhashtable.h>
|
||||||
+#include <linux/dim.h>
|
+#include <linux/dim.h>
|
||||||
|
#include "mtk_ppe.h"
|
||||||
|
|
||||||
#define MTK_QDMA_PAGE_SIZE 2048
|
#define MTK_QDMA_PAGE_SIZE 2048
|
||||||
#define MTK_MAX_RX_LENGTH 1536
|
@@ -136,13 +137,18 @@
|
||||||
@@ -131,13 +132,18 @@
|
|
||||||
|
|
||||||
/* PDMA Delay Interrupt Register */
|
/* PDMA Delay Interrupt Register */
|
||||||
#define MTK_PDMA_DELAY_INT 0xa0c
|
#define MTK_PDMA_DELAY_INT 0xa0c
|
||||||
@ -242,7 +242,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
/* PDMA Interrupt Status Register */
|
/* PDMA Interrupt Status Register */
|
||||||
#define MTK_PDMA_INT_STATUS 0xa20
|
#define MTK_PDMA_INT_STATUS 0xa20
|
||||||
@@ -219,6 +225,7 @@
|
@@ -224,6 +230,7 @@
|
||||||
/* QDMA Interrupt Status Register */
|
/* QDMA Interrupt Status Register */
|
||||||
#define MTK_QDMA_INT_STATUS 0x1A18
|
#define MTK_QDMA_INT_STATUS 0x1A18
|
||||||
#define MTK_RX_DONE_DLY BIT(30)
|
#define MTK_RX_DONE_DLY BIT(30)
|
||||||
@ -250,7 +250,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#define MTK_RX_DONE_INT3 BIT(19)
|
#define MTK_RX_DONE_INT3 BIT(19)
|
||||||
#define MTK_RX_DONE_INT2 BIT(18)
|
#define MTK_RX_DONE_INT2 BIT(18)
|
||||||
#define MTK_RX_DONE_INT1 BIT(17)
|
#define MTK_RX_DONE_INT1 BIT(17)
|
||||||
@@ -228,8 +235,7 @@
|
@@ -233,8 +240,7 @@
|
||||||
#define MTK_TX_DONE_INT1 BIT(1)
|
#define MTK_TX_DONE_INT1 BIT(1)
|
||||||
#define MTK_TX_DONE_INT0 BIT(0)
|
#define MTK_TX_DONE_INT0 BIT(0)
|
||||||
#define MTK_RX_DONE_INT MTK_RX_DONE_DLY
|
#define MTK_RX_DONE_INT MTK_RX_DONE_DLY
|
||||||
@ -260,7 +260,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
/* QDMA Interrupt grouping registers */
|
/* QDMA Interrupt grouping registers */
|
||||||
#define MTK_QDMA_INT_GRP1 0x1a20
|
#define MTK_QDMA_INT_GRP1 0x1a20
|
||||||
@@ -892,6 +898,18 @@ struct mtk_eth {
|
@@ -905,6 +911,18 @@ struct mtk_eth {
|
||||||
|
|
||||||
const struct mtk_soc_data *soc;
|
const struct mtk_soc_data *soc;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
} else {
|
} else {
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -624,6 +624,7 @@ struct mtk_tx_buf {
|
@@ -636,6 +636,7 @@ struct mtk_tx_buf {
|
||||||
* @phys: The physical addr of tx_buf
|
* @phys: The physical addr of tx_buf
|
||||||
* @next_free: Pointer to the next free descriptor
|
* @next_free: Pointer to the next free descriptor
|
||||||
* @last_free: Pointer to the last free descriptor
|
* @last_free: Pointer to the last free descriptor
|
||||||
@ -57,7 +57,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
* @thresh: The threshold of minimum amount of free descriptors
|
* @thresh: The threshold of minimum amount of free descriptors
|
||||||
* @free_count: QDMA uses a linked list. Track how many free descriptors
|
* @free_count: QDMA uses a linked list. Track how many free descriptors
|
||||||
* are present
|
* are present
|
||||||
@@ -634,6 +635,7 @@ struct mtk_tx_ring {
|
@@ -646,6 +647,7 @@ struct mtk_tx_ring {
|
||||||
dma_addr_t phys;
|
dma_addr_t phys;
|
||||||
struct mtk_tx_dma *next_free;
|
struct mtk_tx_dma *next_free;
|
||||||
struct mtk_tx_dma *last_free;
|
struct mtk_tx_dma *last_free;
|
||||||
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -776,13 +776,18 @@ static inline int mtk_max_buf_size(int f
|
@@ -777,13 +777,18 @@ static inline int mtk_max_buf_size(int f
|
||||||
return buf_size;
|
return buf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* the qdma core needs scratch memory to be setup */
|
/* the qdma core needs scratch memory to be setup */
|
||||||
@@ -1254,8 +1259,7 @@ static int mtk_poll_rx(struct napi_struc
|
@@ -1255,8 +1260,7 @@ static int mtk_poll_rx(struct napi_struc
|
||||||
rxd = &ring->dma[idx];
|
rxd = &ring->dma[idx];
|
||||||
data = ring->data[idx];
|
data = ring->data[idx];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user