mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 13:48:06 +00:00
kernel: update 5.10 flow offload patches
Includes PPPoE support and VLAN related fixes Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
e90e75b12c
commit
0d5bf53197
@ -1,6 +1,6 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 20 Feb 2018 15:56:02 +0100
|
||||
Subject: [PATCH] netfilter: add xt_OFFLOAD target
|
||||
Subject: [PATCH] netfilter: add xt_FLOWOFFLOAD target
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
|
||||
--- /dev/null
|
||||
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
|
||||
@@ -0,0 +1,660 @@
|
||||
@@ -0,0 +1,658 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2018-2021 Felix Fietkau <nbd@nbd.name>
|
||||
+ *
|
||||
@ -265,20 +265,14 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+xt_flowoffload_check_hook(struct flow_offload *flow, void *data)
|
||||
+{
|
||||
+ struct xt_flowoffload_table *table = data;
|
||||
+ struct flow_offload_tuple *tuple = &flow->tuplehash[0].tuple;
|
||||
+ struct flow_offload_tuple *tuple0 = &flow->tuplehash[0].tuple;
|
||||
+ struct flow_offload_tuple *tuple1 = &flow->tuplehash[1].tuple;
|
||||
+ struct xt_flowoffload_hook *hook;
|
||||
+
|
||||
+ spin_lock_bh(&hooks_lock);
|
||||
+ hlist_for_each_entry(hook, &table->hooks, list) {
|
||||
+ int ifindex;
|
||||
+
|
||||
+ if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT)
|
||||
+ ifindex = tuple->out.ifidx;
|
||||
+ else
|
||||
+ ifindex = tuple->dst_cache->dev->ifindex;
|
||||
+
|
||||
+ if (hook->ops.dev->ifindex != tuple->iifidx &&
|
||||
+ hook->ops.dev->ifindex != ifindex)
|
||||
+ if (hook->ops.dev->ifindex != tuple0->iifidx &&
|
||||
+ hook->ops.dev->ifindex != tuple1->iifidx)
|
||||
+ continue;
|
||||
+
|
||||
+ hook->used = true;
|
||||
@ -357,6 +351,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ int i;
|
||||
+
|
||||
+ route->tuple[!dir].in.ifindex = dev->ifindex;
|
||||
+ route->tuple[dir].out.ifindex = dev->ifindex;
|
||||
+
|
||||
+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM)
|
||||
+ return;
|
||||
@ -386,52 +381,54 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ prev_type = DEV_PATH_ETHERNET;
|
||||
+ for (i = 0; i <= stack.num_paths; i++) {
|
||||
+ const struct net_device_path *path = &stack.path[i];
|
||||
+ int n_vlans = route->tuple[!dir].in.num_vlans;
|
||||
+ int n_encaps = route->tuple[!dir].in.num_encaps;
|
||||
+
|
||||
+ dev = (struct net_device *)path->dev;
|
||||
+ if (flow_is_valid_ether_device(dev)) {
|
||||
+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT)
|
||||
+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) {
|
||||
+ memcpy(route->tuple[dir].out.h_source,
|
||||
+ dev->dev_addr, ETH_ALEN);
|
||||
+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
|
||||
+ route->tuple[dir].out.ifindex = dev->ifindex;
|
||||
+ }
|
||||
+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
|
||||
+ }
|
||||
+
|
||||
+ switch (path->type) {
|
||||
+ case DEV_PATH_PPPOE:
|
||||
+ case DEV_PATH_VLAN:
|
||||
+ if (n_vlans >= NF_FLOW_TABLE_VLAN_MAX ||
|
||||
+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX ||
|
||||
+ i == stack.num_paths) {
|
||||
+ last = true;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ route->tuple[!dir].in.num_vlans++;
|
||||
+ route->tuple[!dir].in.vid[n_vlans] = path->vlan.id;
|
||||
+ route->tuple[!dir].in.vproto[n_vlans] = path->vlan.proto;
|
||||
+ route->tuple[!dir].in.num_encaps++;
|
||||
+ route->tuple[!dir].in.encap[n_encaps].id = path->encap.id;
|
||||
+ route->tuple[!dir].in.encap[n_encaps].proto = path->encap.proto;
|
||||
+ if (path->type == DEV_PATH_PPPOE)
|
||||
+ memcpy(route->tuple[dir].out.h_dest,
|
||||
+ path->encap.h_dest, ETH_ALEN);
|
||||
+ break;
|
||||
+ case DEV_PATH_BRIDGE:
|
||||
+ switch (path->bridge.vlan_mode) {
|
||||
+ case DEV_PATH_BR_VLAN_TAG:
|
||||
+ if (n_vlans >= NF_FLOW_TABLE_VLAN_MAX ||
|
||||
+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX ||
|
||||
+ i == stack.num_paths) {
|
||||
+ last = true;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ route->tuple[!dir].in.num_vlans++;
|
||||
+ route->tuple[!dir].in.vid[n_vlans] =
|
||||
+ route->tuple[!dir].in.num_encaps++;
|
||||
+ route->tuple[!dir].in.encap[n_encaps].id =
|
||||
+ path->bridge.vlan_id;
|
||||
+ route->tuple[!dir].in.vproto[n_vlans] =
|
||||
+ route->tuple[!dir].in.encap[n_encaps].proto =
|
||||
+ path->bridge.vlan_proto;
|
||||
+ break;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||
+ route->tuple[!dir].in.pvid.id =
|
||||
+ route->tuple[!dir].in.vid[n_vlans - 1];
|
||||
+ route->tuple[!dir].in.pvid.proto =
|
||||
+ route->tuple[!dir].in.vproto[n_vlans - 1];
|
||||
+ fallthrough;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG:
|
||||
+ route->tuple[!dir].in.num_vlans--;
|
||||
+ route->tuple[!dir].in.num_encaps--;
|
||||
+ break;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||
+ route->tuple[!dir].in.ingress_vlans |= BIT(n_encaps - 1);
|
||||
+ break;
|
||||
+ case DEV_PATH_BR_VLAN_KEEP:
|
||||
+ break;
|
||||
@ -447,6 +444,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ }
|
||||
+
|
||||
+ *out_dev = dev;
|
||||
+ route->tuple[dir].out.hw_ifindex = dev->ifindex;
|
||||
+ route->tuple[!dir].in.ifindex = dev->ifindex;
|
||||
+}
|
||||
+
|
||||
@ -769,7 +767,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
#include <net/netfilter/nf_flow_table.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
@@ -355,8 +354,7 @@ flow_offload_lookup(struct nf_flowtable
|
||||
@@ -356,8 +355,7 @@ flow_offload_lookup(struct nf_flowtable
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(flow_offload_lookup);
|
||||
|
||||
@ -779,7 +777,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
void (*iter)(struct flow_offload *flow, void *data),
|
||||
void *data)
|
||||
{
|
||||
@@ -388,6 +386,7 @@ nf_flow_table_iterate(struct nf_flowtabl
|
||||
@@ -389,6 +387,7 @@ nf_flow_table_iterate(struct nf_flowtabl
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -809,7 +807,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+#endif /* _XT_FLOWOFFLOAD_H */
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -265,6 +265,10 @@ void nf_flow_table_free(struct nf_flowta
|
||||
@@ -266,6 +266,10 @@ void nf_flow_table_free(struct nf_flowta
|
||||
|
||||
void flow_offload_teardown(struct flow_offload *flow);
|
||||
|
@ -1,5 +1,5 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Sun, 10 Jan 2021 15:53:58 +0100
|
||||
Date: Thu, 4 Mar 2021 23:18:11 +0100
|
||||
Subject: [PATCH] net: resolve forwarding path from virtual netdevice and
|
||||
HW destination address
|
||||
|
||||
|
@ -42,7 +42,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ struct {
|
||||
+ u16 id;
|
||||
+ __be16 proto;
|
||||
+ } vlan;
|
||||
+ } encap;
|
||||
+ };
|
||||
};
|
||||
|
||||
@ -59,8 +59,8 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ struct vlan_dev_priv *vlan = vlan_dev_priv(ctx->dev);
|
||||
+
|
||||
+ path->type = DEV_PATH_VLAN;
|
||||
+ path->vlan.id = vlan->vlan_id;
|
||||
+ path->vlan.proto = vlan->vlan_proto;
|
||||
+ path->encap.id = vlan->vlan_id;
|
||||
+ path->encap.proto = vlan->vlan_proto;
|
||||
+ path->dev = ctx->dev;
|
||||
+ ctx->dev = vlan->real_dev;
|
||||
+
|
||||
|
@ -89,7 +89,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+}
|
||||
+
|
||||
+struct nft_forward_info {
|
||||
+ const struct net_device *dev;
|
||||
+ const struct net_device *indev;
|
||||
+};
|
||||
+
|
||||
+static void nft_dev_path_info(const struct net_device_path_stack *stack,
|
||||
@ -102,12 +102,12 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ path = &stack->path[i];
|
||||
+ switch (path->type) {
|
||||
+ case DEV_PATH_ETHERNET:
|
||||
+ info->dev = path->dev;
|
||||
+ info->indev = path->dev;
|
||||
+ break;
|
||||
+ case DEV_PATH_VLAN:
|
||||
+ case DEV_PATH_BRIDGE:
|
||||
+ default:
|
||||
+ info->dev = NULL;
|
||||
+ info->indev = NULL;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
@ -142,10 +142,10 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ if (nft_dev_fill_forward_path(route, dst, ct, dir, &stack) >= 0)
|
||||
+ nft_dev_path_info(&stack, &info);
|
||||
+
|
||||
+ if (!info.dev || !nft_flowtable_find_dev(info.dev, ft))
|
||||
+ if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
|
||||
+ return;
|
||||
+
|
||||
+ route->tuple[!dir].in.ifindex = info.dev->ifindex;
|
||||
+ route->tuple[!dir].in.ifindex = info.indev->ifindex;
|
||||
+}
|
||||
+
|
||||
static int nft_flow_route(const struct nft_pktinfo *pkt,
|
||||
|
@ -1,5 +1,5 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Fri, 20 Nov 2020 13:49:19 +0100
|
||||
Date: Thu, 4 Mar 2021 03:26:35 +0100
|
||||
Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to
|
||||
obtain egress device
|
||||
|
||||
@ -271,10 +271,11 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
struct neighbour *n;
|
||||
u8 nud_state;
|
||||
|
||||
@@ -66,22 +65,35 @@ static int nft_dev_fill_forward_path(con
|
||||
@@ -66,27 +65,43 @@ static int nft_dev_fill_forward_path(con
|
||||
|
||||
struct nft_forward_info {
|
||||
const struct net_device *dev;
|
||||
const struct net_device *indev;
|
||||
+ const struct net_device *outdev;
|
||||
+ u8 h_source[ETH_ALEN];
|
||||
+ u8 h_dest[ETH_ALEN];
|
||||
+ enum flow_offload_xmit_type xmit_type;
|
||||
@ -294,7 +295,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
path = &stack->path[i];
|
||||
switch (path->type) {
|
||||
case DEV_PATH_ETHERNET:
|
||||
info->dev = path->dev;
|
||||
info->indev = path->dev;
|
||||
+ if (is_zero_ether_addr(info->h_source))
|
||||
+ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
||||
break;
|
||||
@ -307,9 +308,16 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ break;
|
||||
+ case DEV_PATH_VLAN:
|
||||
default:
|
||||
info->dev = NULL;
|
||||
info->indev = NULL;
|
||||
break;
|
||||
@@ -114,14 +126,22 @@ static void nft_dev_forward_path(struct
|
||||
}
|
||||
}
|
||||
+ if (!info->outdev)
|
||||
+ info->outdev = info->indev;
|
||||
}
|
||||
|
||||
static bool nft_flowtable_find_dev(const struct net_device *dev,
|
||||
@@ -114,14 +129,22 @@ static void nft_dev_forward_path(struct
|
||||
const struct dst_entry *dst = route->tuple[dir].dst;
|
||||
struct net_device_path_stack stack;
|
||||
struct nft_forward_info info = {};
|
||||
@ -320,15 +328,15 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
|
||||
+ nft_dev_path_info(&stack, &info, ha);
|
||||
|
||||
if (!info.dev || !nft_flowtable_find_dev(info.dev, ft))
|
||||
if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
|
||||
return;
|
||||
|
||||
route->tuple[!dir].in.ifindex = info.dev->ifindex;
|
||||
route->tuple[!dir].in.ifindex = info.indev->ifindex;
|
||||
+
|
||||
+ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
|
||||
+ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
|
||||
+ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN);
|
||||
+ route->tuple[dir].out.ifindex = info.dev->ifindex;
|
||||
+ route->tuple[dir].out.ifindex = info.outdev->ifindex;
|
||||
+ route->tuple[dir].xmit_type = info.xmit_type;
|
||||
+ }
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
FLOW_OFFLOAD_XMIT_DIRECT,
|
||||
};
|
||||
|
||||
+#define NF_FLOW_TABLE_VLAN_MAX 2
|
||||
+#define NF_FLOW_TABLE_ENCAP_MAX 2
|
||||
+
|
||||
struct flow_offload_tuple {
|
||||
union {
|
||||
@ -28,7 +28,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ struct {
|
||||
+ u16 id;
|
||||
+ __be16 proto;
|
||||
+ } in_vlan[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ } encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||
|
||||
/* All members above are keys for lookups, see flow_offload_hash(). */
|
||||
struct { } __hash;
|
||||
@ -38,17 +38,19 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
-
|
||||
+ u8 dir:4,
|
||||
+ xmit_type:2,
|
||||
+ in_vlan_num:2;
|
||||
+ encap_num:2;
|
||||
u16 mtu;
|
||||
union {
|
||||
struct dst_entry *dst_cache;
|
||||
@@ -174,6 +180,9 @@ struct nf_flow_route {
|
||||
@@ -174,6 +180,11 @@ struct nf_flow_route {
|
||||
struct dst_entry *dst;
|
||||
struct {
|
||||
u32 ifindex;
|
||||
+ u16 vid[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ __be16 vproto[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ u8 num_vlans;
|
||||
+ struct {
|
||||
+ u16 id;
|
||||
+ __be16 proto;
|
||||
+ } encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||
+ u8 num_encaps;
|
||||
} in;
|
||||
struct {
|
||||
u32 ifindex;
|
||||
@ -66,33 +68,36 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
}
|
||||
|
||||
flow_tuple->iifidx = route->tuple[dir].in.ifindex;
|
||||
+ for (i = route->tuple[dir].in.num_vlans - 1; i >= 0; i--) {
|
||||
+ flow_tuple->in_vlan[j].id = route->tuple[dir].in.vid[i];
|
||||
+ flow_tuple->in_vlan[j].proto = route->tuple[dir].in.vproto[i];
|
||||
+ for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) {
|
||||
+ flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id;
|
||||
+ flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto;
|
||||
+ j++;
|
||||
+ }
|
||||
+ flow_tuple->in_vlan_num = route->tuple[dir].in.num_vlans;
|
||||
+ flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
|
||||
|
||||
switch (route->tuple[dir].xmit_type) {
|
||||
case FLOW_OFFLOAD_XMIT_DIRECT:
|
||||
--- a/net/netfilter/nf_flow_table_ip.c
|
||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||
@@ -159,17 +159,35 @@ static bool ip_has_options(unsigned int
|
||||
@@ -159,17 +159,38 @@ static bool ip_has_options(unsigned int
|
||||
return thoff != sizeof(struct iphdr);
|
||||
}
|
||||
|
||||
+static void nf_flow_tuple_vlan(struct sk_buff *skb,
|
||||
+static void nf_flow_tuple_encap(struct sk_buff *skb,
|
||||
+ struct flow_offload_tuple *tuple)
|
||||
+{
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (skb_vlan_tag_present(skb)) {
|
||||
+ tuple->in_vlan[0].id = skb_vlan_tag_get(skb);
|
||||
+ tuple->in_vlan[0].proto = skb->vlan_proto;
|
||||
+ tuple->encap[i].id = skb_vlan_tag_get(skb);
|
||||
+ 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);
|
||||
+
|
||||
+ tuple->in_vlan[1].id = ntohs(veth->h_vlan_TCI);
|
||||
+ tuple->in_vlan[1].proto = skb->protocol;
|
||||
+ tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
|
||||
+ tuple->encap[i].proto = skb->protocol;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
@ -116,7 +121,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
thoff = iph->ihl * 4;
|
||||
|
||||
if (ip_is_fragment(iph) ||
|
||||
@@ -191,11 +209,11 @@ static int nf_flow_tuple_ip(struct sk_bu
|
||||
@@ -191,11 +212,11 @@ static int nf_flow_tuple_ip(struct sk_bu
|
||||
return -1;
|
||||
|
||||
thoff = iph->ihl * 4;
|
||||
@ -131,19 +136,19 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
tuple->src_v4.s_addr = iph->saddr;
|
||||
tuple->dst_v4.s_addr = iph->daddr;
|
||||
@@ -204,6 +222,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->l4proto = iph->protocol;
|
||||
tuple->iifidx = dev->ifindex;
|
||||
+ nf_flow_tuple_vlan(skb, tuple);
|
||||
+ nf_flow_tuple_encap(skb, tuple);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -248,6 +267,37 @@ static unsigned int nf_flow_xmit_xfrm(st
|
||||
@@ -248,6 +270,40 @@ static unsigned int nf_flow_xmit_xfrm(st
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
||||
+static bool nf_flow_skb_vlan_protocol(const struct sk_buff *skb, __be16 proto)
|
||||
+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;
|
||||
@ -156,29 +161,37 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static void nf_flow_vlan_pop(struct sk_buff *skb,
|
||||
+static void nf_flow_encap_pop(struct sk_buff *skb,
|
||||
+ struct flow_offload_tuple_rhash *tuplehash)
|
||||
+{
|
||||
+ struct vlan_hdr *vlan_hdr;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < tuplehash->tuple.in_vlan_num; i++) {
|
||||
+ for (i = 0; i < tuplehash->tuple.encap_num; i++) {
|
||||
+ if (skb_vlan_tag_present(skb)) {
|
||||
+ __vlan_hwaccel_clear_tag(skb);
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (skb->protocol == 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;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
|
||||
const struct flow_offload_tuple_rhash *tuplehash,
|
||||
unsigned short type)
|
||||
@@ -280,9 +330,11 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
unsigned int thoff;
|
||||
@@ -276,13 +332,15 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
enum flow_offload_tuple_dir dir;
|
||||
struct flow_offload *flow;
|
||||
struct net_device *outdev;
|
||||
+ unsigned int thoff, mtu;
|
||||
struct rtable *rt;
|
||||
- unsigned int thoff;
|
||||
struct iphdr *iph;
|
||||
__be32 nexthop;
|
||||
+ u32 offset = 0;
|
||||
@ -186,12 +199,17 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
- if (skb->protocol != htons(ETH_P_IP))
|
||||
+ if (skb->protocol != htons(ETH_P_IP) &&
|
||||
+ !nf_flow_skb_vlan_protocol(skb, htons(ETH_P_IP)))
|
||||
+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0)
|
||||
@@ -298,11 +350,15 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||
@@ -295,14 +353,19 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
dir = tuplehash->tuple.dir;
|
||||
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
|
||||
|
||||
- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||
+ mtu = flow->tuplehash[dir].tuple.mtu + offset;
|
||||
+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
- if (skb_try_make_writable(skb, sizeof(*iph)))
|
||||
@ -209,17 +227,17 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
return NF_ACCEPT;
|
||||
|
||||
flow_offload_refresh(flow_table, flow);
|
||||
@@ -312,6 +368,9 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
@@ -312,6 +375,9 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
+ nf_flow_vlan_pop(skb, tuplehash);
|
||||
+ nf_flow_encap_pop(skb, tuplehash);
|
||||
+ thoff -= offset;
|
||||
+
|
||||
if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
|
||||
return NF_DROP;
|
||||
|
||||
@@ -479,14 +538,17 @@ static int nf_flow_nat_ipv6(const struct
|
||||
@@ -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,
|
||||
struct flow_offload_tuple *tuple)
|
||||
{
|
||||
@ -240,7 +258,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
switch (ip6h->nexthdr) {
|
||||
case IPPROTO_TCP:
|
||||
@@ -503,11 +565,11 @@ static int nf_flow_tuple_ipv6(struct sk_
|
||||
@@ -503,11 +572,11 @@ static int nf_flow_tuple_ipv6(struct sk_
|
||||
return -1;
|
||||
|
||||
thoff = sizeof(*ip6h);
|
||||
@ -255,29 +273,35 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
tuple->src_v6 = ip6h->saddr;
|
||||
tuple->dst_v6 = ip6h->daddr;
|
||||
@@ -516,6 +578,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->l4proto = ip6h->nexthdr;
|
||||
tuple->iifidx = dev->ifindex;
|
||||
+ nf_flow_tuple_vlan(skb, tuple);
|
||||
+ nf_flow_tuple_encap(skb, tuple);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -533,9 +596,11 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
@@ -533,9 +603,12 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
struct net_device *outdev;
|
||||
struct ipv6hdr *ip6h;
|
||||
struct rt6_info *rt;
|
||||
+ unsigned int mtu;
|
||||
+ u32 offset = 0;
|
||||
int ret;
|
||||
|
||||
- if (skb->protocol != htons(ETH_P_IPV6))
|
||||
+ if (skb->protocol != htons(ETH_P_IPV6) &&
|
||||
+ !nf_flow_skb_vlan_protocol(skb, htons(ETH_P_IPV6)))
|
||||
+ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0)
|
||||
@@ -551,8 +616,11 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||
@@ -548,11 +621,15 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
dir = tuplehash->tuple.dir;
|
||||
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
|
||||
|
||||
- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
|
||||
+ mtu = flow->tuplehash[dir].tuple.mtu + offset;
|
||||
+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
- if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb,
|
||||
@ -290,33 +314,35 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
return NF_ACCEPT;
|
||||
|
||||
flow_offload_refresh(flow_table, flow);
|
||||
@@ -562,6 +630,8 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
@@ -562,6 +639,8 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
+ nf_flow_vlan_pop(skb, tuplehash);
|
||||
+ nf_flow_encap_pop(skb, tuplehash);
|
||||
+
|
||||
if (skb_try_make_writable(skb, sizeof(*ip6h)))
|
||||
return NF_DROP;
|
||||
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -65,6 +65,9 @@ static int nft_dev_fill_forward_path(con
|
||||
|
||||
@@ -66,6 +66,11 @@ static int nft_dev_fill_forward_path(con
|
||||
struct nft_forward_info {
|
||||
const struct net_device *dev;
|
||||
+ __u16 vid[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ __be16 vproto[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ u8 num_vlans;
|
||||
const struct net_device *indev;
|
||||
const struct net_device *outdev;
|
||||
+ struct id {
|
||||
+ __u16 id;
|
||||
+ __be16 proto;
|
||||
+ } encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||
+ u8 num_encaps;
|
||||
u8 h_source[ETH_ALEN];
|
||||
u8 h_dest[ETH_ALEN];
|
||||
enum flow_offload_xmit_type xmit_type;
|
||||
@@ -83,9 +86,22 @@ static void nft_dev_path_info(const stru
|
||||
@@ -84,9 +89,23 @@ static void nft_dev_path_info(const stru
|
||||
path = &stack->path[i];
|
||||
switch (path->type) {
|
||||
case DEV_PATH_ETHERNET:
|
||||
+ case DEV_PATH_VLAN:
|
||||
info->dev = path->dev;
|
||||
info->indev = path->dev;
|
||||
if (is_zero_ether_addr(info->h_source))
|
||||
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
||||
+
|
||||
@ -324,25 +350,26 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ break;
|
||||
+
|
||||
+ /* DEV_PATH_VLAN */
|
||||
+ if (info->num_vlans >= NF_FLOW_TABLE_VLAN_MAX) {
|
||||
+ info->dev = NULL;
|
||||
+ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
|
||||
+ info->indev = NULL;
|
||||
+ break;
|
||||
+ }
|
||||
+ info->vid[info->num_vlans] = path->vlan.id;
|
||||
+ info->vproto[info->num_vlans] = path->vlan.proto;
|
||||
+ info->num_vlans++;
|
||||
+ info->outdev = path->dev;
|
||||
+ info->encap[info->num_encaps].id = path->encap.id;
|
||||
+ info->encap[info->num_encaps].proto = path->encap.proto;
|
||||
+ info->num_encaps++;
|
||||
break;
|
||||
case DEV_PATH_BRIDGE:
|
||||
if (is_zero_ether_addr(info->h_source))
|
||||
@@ -93,7 +109,6 @@ static void nft_dev_path_info(const stru
|
||||
@@ -94,7 +113,6 @@ static void nft_dev_path_info(const stru
|
||||
|
||||
info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
|
||||
break;
|
||||
- case DEV_PATH_VLAN:
|
||||
default:
|
||||
info->dev = NULL;
|
||||
info->indev = NULL;
|
||||
break;
|
||||
@@ -127,6 +142,7 @@ static void nft_dev_forward_path(struct
|
||||
@@ -130,6 +148,7 @@ static void nft_dev_forward_path(struct
|
||||
struct net_device_path_stack stack;
|
||||
struct nft_forward_info info = {};
|
||||
unsigned char ha[ETH_ALEN];
|
||||
@ -350,15 +377,15 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
|
||||
nft_dev_path_info(&stack, &info, ha);
|
||||
@@ -135,6 +151,11 @@ static void nft_dev_forward_path(struct
|
||||
@@ -138,6 +157,11 @@ static void nft_dev_forward_path(struct
|
||||
return;
|
||||
|
||||
route->tuple[!dir].in.ifindex = info.dev->ifindex;
|
||||
+ for (i = 0; i < info.num_vlans; i++) {
|
||||
+ route->tuple[!dir].in.vid[i] = info.vid[i];
|
||||
+ route->tuple[!dir].in.vproto[i] = info.vproto[i];
|
||||
route->tuple[!dir].in.ifindex = info.indev->ifindex;
|
||||
+ for (i = 0; i < info.num_encaps; i++) {
|
||||
+ route->tuple[!dir].in.encap[i].id = info.encap[i].id;
|
||||
+ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
|
||||
+ }
|
||||
+ route->tuple[!dir].in.num_vlans = info.num_vlans;
|
||||
+ route->tuple[!dir].in.num_encaps = info.num_encaps;
|
||||
|
||||
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
|
||||
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
|
||||
|
@ -18,7 +18,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
@@ -847,10 +847,20 @@ struct net_device_path {
|
||||
u16 id;
|
||||
__be16 proto;
|
||||
} vlan;
|
||||
} encap;
|
||||
+ struct {
|
||||
+ enum {
|
||||
+ DEV_PATH_BR_VLAN_KEEP,
|
||||
@ -52,7 +52,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
--- a/net/8021q/vlan_dev.c
|
||||
+++ b/net/8021q/vlan_dev.c
|
||||
@@ -777,6 +777,12 @@ static int vlan_dev_fill_forward_path(st
|
||||
path->vlan.proto = vlan->vlan_proto;
|
||||
path->encap.proto = vlan->vlan_proto;
|
||||
path->dev = ctx->dev;
|
||||
ctx->dev = vlan->real_dev;
|
||||
+ if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan))
|
||||
|
@ -10,18 +10,18 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -112,6 +112,18 @@ static void nft_dev_path_info(const stru
|
||||
@@ -111,6 +111,18 @@ static void nft_dev_path_info(const stru
|
||||
if (is_zero_ether_addr(info->h_source))
|
||||
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
||||
|
||||
+ switch (path->bridge.vlan_mode) {
|
||||
+ case DEV_PATH_BR_VLAN_TAG:
|
||||
+ info->vid[info->num_vlans] = path->vlan.id;
|
||||
+ info->vproto[info->num_vlans] = path->vlan.proto;
|
||||
+ info->num_vlans++;
|
||||
+ info->encap[info->num_encaps].id = path->bridge.vlan_id;
|
||||
+ info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
|
||||
+ info->num_encaps++;
|
||||
+ break;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG:
|
||||
+ info->num_vlans--;
|
||||
+ info->num_encaps--;
|
||||
+ break;
|
||||
+ case DEV_PATH_BR_VLAN_KEEP:
|
||||
+ break;
|
@ -0,0 +1,100 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue, 2 Mar 2021 21:45:16 +0100
|
||||
Subject: [PATCH] net: ppp: resolve forwarding path for bridge pppoe
|
||||
devices
|
||||
|
||||
Pass on the PPPoE session ID and the real device.
|
||||
---
|
||||
|
||||
--- a/drivers/net/ppp/ppp_generic.c
|
||||
+++ b/drivers/net/ppp/ppp_generic.c
|
||||
@@ -1450,12 +1450,34 @@ static void ppp_dev_priv_destructor(stru
|
||||
ppp_destroy_interface(ppp);
|
||||
}
|
||||
|
||||
+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_channel *chan;
|
||||
+ struct channel *pch;
|
||||
+
|
||||
+ if (ppp->flags & SC_MULTILINK)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (list_empty(&ppp->channels))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ pch = list_first_entry(&ppp->channels, struct channel, clist);
|
||||
+ chan = pch->chan;
|
||||
+ if (!chan->ops->fill_forward_path)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return chan->ops->fill_forward_path(ctx, path, chan);
|
||||
+}
|
||||
+
|
||||
static const struct net_device_ops ppp_netdev_ops = {
|
||||
.ndo_init = ppp_dev_init,
|
||||
.ndo_uninit = ppp_dev_uninit,
|
||||
.ndo_start_xmit = ppp_start_xmit,
|
||||
.ndo_do_ioctl = ppp_net_ioctl,
|
||||
.ndo_get_stats64 = ppp_get_stats64,
|
||||
+ .ndo_fill_forward_path = ppp_fill_forward_path,
|
||||
};
|
||||
|
||||
static struct device_type ppp_type = {
|
||||
--- a/drivers/net/ppp/pppoe.c
|
||||
+++ b/drivers/net/ppp/pppoe.c
|
||||
@@ -972,8 +972,30 @@ static int pppoe_xmit(struct ppp_channel
|
||||
return __pppoe_xmit(sk, skb);
|
||||
}
|
||||
|
||||
+static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
+ struct net_device_path *path,
|
||||
+ const struct ppp_channel *chan)
|
||||
+{
|
||||
+ struct sock *sk = (struct sock *)chan->private;
|
||||
+ struct pppox_sock *po = pppox_sk(sk);
|
||||
+ struct net_device *dev = po->pppoe_dev;
|
||||
+
|
||||
+ if (sock_flag(sk, SOCK_DEAD) ||
|
||||
+ !(sk->sk_state & PPPOX_CONNECTED) || !dev)
|
||||
+ return -1;
|
||||
+
|
||||
+ path->type = DEV_PATH_PPPOE;
|
||||
+ path->encap.proto = htons(ETH_P_PPP_SES);
|
||||
+ path->encap.id = be16_to_cpu(po->num);
|
||||
+ path->dev = ctx->dev;
|
||||
+ ctx->dev = dev;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct ppp_channel_ops pppoe_chan_ops = {
|
||||
.start_xmit = pppoe_xmit,
|
||||
+ .fill_forward_path = pppoe_fill_forward_path,
|
||||
};
|
||||
|
||||
static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -837,6 +837,7 @@ enum net_device_path_type {
|
||||
DEV_PATH_ETHERNET = 0,
|
||||
DEV_PATH_VLAN,
|
||||
DEV_PATH_BRIDGE,
|
||||
+ DEV_PATH_PPPOE,
|
||||
};
|
||||
|
||||
struct net_device_path {
|
||||
--- a/include/linux/ppp_channel.h
|
||||
+++ b/include/linux/ppp_channel.h
|
||||
@@ -28,6 +28,9 @@ struct ppp_channel_ops {
|
||||
int (*start_xmit)(struct ppp_channel *, struct sk_buff *);
|
||||
/* Handle an ioctl call that has come in via /dev/ppp. */
|
||||
int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long);
|
||||
+ int (*fill_forward_path)(struct net_device_path_ctx *,
|
||||
+ struct net_device_path *,
|
||||
+ const struct ppp_channel *);
|
||||
};
|
||||
|
||||
struct ppp_channel {
|
@ -1,23 +1,21 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 7 Dec 2020 20:31:48 +0100
|
||||
Date: Thu, 4 Mar 2021 23:19:06 +0100
|
||||
Subject: [PATCH] net: dsa: resolve forwarding path for dsa slave ports
|
||||
|
||||
Add .ndo_fill_forward_path for dsa slave port devices
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -837,6 +837,7 @@ enum net_device_path_type {
|
||||
DEV_PATH_ETHERNET = 0,
|
||||
@@ -838,6 +838,7 @@ enum net_device_path_type {
|
||||
DEV_PATH_VLAN,
|
||||
DEV_PATH_BRIDGE,
|
||||
DEV_PATH_PPPOE,
|
||||
+ DEV_PATH_DSA,
|
||||
};
|
||||
|
||||
struct net_device_path {
|
||||
@@ -856,6 +857,10 @@ struct net_device_path {
|
||||
@@ -857,6 +858,10 @@ struct net_device_path {
|
||||
u16 vlan_id;
|
||||
__be16 vlan_proto;
|
||||
} bridge;
|
@ -0,0 +1,263 @@
|
||||
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
|
||||
@@ -848,6 +848,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))
|
@ -1,5 +1,5 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Mon, 18 Jan 2021 22:27:45 +0100
|
||||
Date: Thu, 4 Mar 2021 19:22:55 +0100
|
||||
Subject: [PATCH] netfilter: nft_flow_offload: add dsa support
|
||||
|
||||
Replace the master ethernet device by the dsa slave port.
|
||||
@ -9,15 +9,15 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -86,6 +86,7 @@ static void nft_dev_path_info(const stru
|
||||
@@ -89,6 +89,7 @@ static void nft_dev_path_info(const stru
|
||||
path = &stack->path[i];
|
||||
switch (path->type) {
|
||||
case DEV_PATH_ETHERNET:
|
||||
+ case DEV_PATH_DSA:
|
||||
case DEV_PATH_VLAN:
|
||||
info->dev = path->dev;
|
||||
if (is_zero_ether_addr(info->h_source))
|
||||
@@ -93,6 +94,10 @@ static void nft_dev_path_info(const stru
|
||||
case DEV_PATH_PPPOE:
|
||||
info->indev = path->dev;
|
||||
@@ -97,6 +98,10 @@ static void nft_dev_path_info(const stru
|
||||
|
||||
if (path->type == DEV_PATH_ETHERNET)
|
||||
break;
|
||||
@ -26,5 +26,5 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
/* DEV_PATH_VLAN */
|
||||
if (info->num_vlans >= NF_FLOW_TABLE_VLAN_MAX) {
|
||||
/* DEV_PATH_VLAN and DEV_PATH_PPPOE */
|
||||
if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
|
@ -229,12 +229,12 @@ tag to the driver.
|
||||
|
||||
+ other_tuple = &flow->tuplehash[!dir].tuple;
|
||||
+
|
||||
+ for (i = 0; i < other_tuple->in_vlan_num; i++) {
|
||||
+ for (i = 0; i < other_tuple->encap_num; i++) {
|
||||
+ struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
+
|
||||
+ entry->id = FLOW_ACTION_VLAN_PUSH;
|
||||
+ entry->vlan.vid = other_tuple->in_vlan[i].id;
|
||||
+ entry->vlan.proto = other_tuple->in_vlan[i].proto;
|
||||
+ entry->vlan.vid = other_tuple->encap[i].id;
|
||||
+ entry->vlan.proto = other_tuple->encap[i].proto;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
@ -1,51 +0,0 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue, 2 Feb 2021 17:10:07 +0100
|
||||
Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if
|
||||
hardware offload is enabled
|
||||
|
||||
If there is a forward path to reach an ethernet device and hardware
|
||||
offload is enabled, then use the direct xmit path.
|
||||
---
|
||||
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -73,9 +73,18 @@ struct nft_forward_info {
|
||||
enum flow_offload_xmit_type xmit_type;
|
||||
};
|
||||
|
||||
+static bool nft_is_valid_ether_device(const struct net_device *dev)
|
||||
+{
|
||||
+ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
|
||||
+ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static void nft_dev_path_info(const struct net_device_path_stack *stack,
|
||||
struct nft_forward_info *info,
|
||||
- unsigned char *ha)
|
||||
+ unsigned char *ha, struct nf_flowtable *flowtable)
|
||||
{
|
||||
const struct net_device_path *path;
|
||||
int i;
|
||||
@@ -131,6 +140,10 @@ static void nft_dev_path_info(const stru
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (nf_flowtable_hw_offload(flowtable) &&
|
||||
+ nft_is_valid_ether_device(info->dev))
|
||||
+ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
|
||||
}
|
||||
|
||||
static bool nft_flowtable_find_dev(const struct net_device *dev,
|
||||
@@ -162,7 +175,7 @@ static void nft_dev_forward_path(struct
|
||||
int i;
|
||||
|
||||
if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
|
||||
- nft_dev_path_info(&stack, &info, ha);
|
||||
+ nft_dev_path_info(&stack, &info, ha, &ft->data);
|
||||
|
||||
if (!info.dev || !nft_flowtable_find_dev(info.dev, ft))
|
||||
return;
|
@ -1,22 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 10 Feb 2021 10:23:38 +0100
|
||||
Subject: [PATCH] netfilter: nft_flow_offload: fix bridge vlan tag handling
|
||||
|
||||
the brigde type uses the path->bridge.vlan_* fields
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -123,8 +123,8 @@ static void nft_dev_path_info(const stru
|
||||
|
||||
switch (path->bridge.vlan_mode) {
|
||||
case DEV_PATH_BR_VLAN_TAG:
|
||||
- info->vid[info->num_vlans] = path->vlan.id;
|
||||
- info->vproto[info->num_vlans] = path->vlan.proto;
|
||||
+ info->vid[info->num_vlans] = path->bridge.vlan_id;
|
||||
+ info->vproto[info->num_vlans] = path->bridge.vlan_proto;
|
||||
info->num_vlans++;
|
||||
break;
|
||||
case DEV_PATH_BR_VLAN_UNTAG:
|
@ -1,143 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 10 Feb 2021 19:39:23 +0100
|
||||
Subject: [PATCH] netfilter: flowtable: rework ingress vlan matching
|
||||
|
||||
When dealing with bridges with VLAN filtering and DSA/switchdev offload,
|
||||
the hardware could offload adding a VLAN tag configured in the bridge.
|
||||
Since there doesn't seem to be an easy way to detect that, this patch
|
||||
reworks the code to optionally match the last VLAN tag that would otherwise
|
||||
be inserted by the bridge.
|
||||
This matters when bypassing the bridge and attaching an ingress hook on
|
||||
a DSA port below it.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -115,14 +115,15 @@ struct flow_offload_tuple {
|
||||
|
||||
u8 l3proto;
|
||||
u8 l4proto;
|
||||
- struct {
|
||||
- u16 id;
|
||||
- __be16 proto;
|
||||
- } in_vlan[NF_FLOW_TABLE_VLAN_MAX];
|
||||
|
||||
/* All members above are keys for lookups, see flow_offload_hash(). */
|
||||
struct { } __hash;
|
||||
|
||||
+ struct {
|
||||
+ u16 id;
|
||||
+ __be16 proto;
|
||||
+ } in_vlan[NF_FLOW_TABLE_VLAN_MAX], in_pvid;
|
||||
+
|
||||
u8 dir:4,
|
||||
xmit_type:2,
|
||||
in_vlan_num:2;
|
||||
--- a/net/netfilter/nf_flow_table_ip.c
|
||||
+++ b/net/netfilter/nf_flow_table_ip.c
|
||||
@@ -281,12 +281,13 @@ static bool nf_flow_skb_vlan_protocol(co
|
||||
}
|
||||
|
||||
static void nf_flow_vlan_pop(struct sk_buff *skb,
|
||||
- struct flow_offload_tuple_rhash *tuplehash)
|
||||
+ struct flow_offload_tuple_rhash *tuplehash,
|
||||
+ bool strip_pvid)
|
||||
{
|
||||
struct vlan_hdr *vlan_hdr;
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < tuplehash->tuple.in_vlan_num; i++) {
|
||||
+ for (i = 0; i < tuplehash->tuple.in_vlan_num + strip_pvid; i++) {
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
__vlan_hwaccel_clear_tag(skb);
|
||||
continue;
|
||||
@@ -316,6 +317,31 @@ static unsigned int nf_flow_queue_xmit(s
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+nf_flow_offload_check_vlan(struct flow_offload_tuple *tuple,
|
||||
+ struct flow_offload_tuple *flow_tuple,
|
||||
+ bool *strip_pvid)
|
||||
+{
|
||||
+ int i, cur = 0;
|
||||
+
|
||||
+ if (flow_tuple->in_pvid.proto &&
|
||||
+ !memcmp(&tuple->in_vlan[0], &flow_tuple->in_pvid,
|
||||
+ sizeof(tuple->in_vlan[0])))
|
||||
+ cur++;
|
||||
+
|
||||
+ *strip_pvid = cur;
|
||||
+
|
||||
+ for (i = 0; i < flow_tuple->in_vlan_num; i++, cur++) {
|
||||
+ if (!memcmp(&tuple->in_vlan[cur], &flow_tuple->in_vlan[i],
|
||||
+ sizeof(tuple->in_vlan[0])))
|
||||
+ continue;
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
unsigned int
|
||||
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
@@ -329,6 +355,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
struct rtable *rt;
|
||||
unsigned int thoff;
|
||||
struct iphdr *iph;
|
||||
+ bool strip_pvid;
|
||||
__be32 nexthop;
|
||||
u32 offset = 0;
|
||||
int ret;
|
||||
@@ -344,6 +371,10 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
if (tuplehash == NULL)
|
||||
return NF_ACCEPT;
|
||||
|
||||
+ if (!nf_flow_offload_check_vlan(&tuple, &tuplehash->tuple,
|
||||
+ &strip_pvid))
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
dir = tuplehash->tuple.dir;
|
||||
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
|
||||
|
||||
@@ -368,7 +399,7 @@ nf_flow_offload_ip_hook(void *priv, stru
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
- nf_flow_vlan_pop(skb, tuplehash);
|
||||
+ nf_flow_vlan_pop(skb, tuplehash, strip_pvid);
|
||||
thoff -= offset;
|
||||
|
||||
if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
|
||||
@@ -596,6 +627,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
struct net_device *outdev;
|
||||
struct ipv6hdr *ip6h;
|
||||
struct rt6_info *rt;
|
||||
+ bool strip_pvid;
|
||||
u32 offset = 0;
|
||||
int ret;
|
||||
|
||||
@@ -610,6 +642,10 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
if (tuplehash == NULL)
|
||||
return NF_ACCEPT;
|
||||
|
||||
+ if (!nf_flow_offload_check_vlan(&tuple, &tuplehash->tuple,
|
||||
+ &strip_pvid))
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
dir = tuplehash->tuple.dir;
|
||||
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
|
||||
|
||||
@@ -630,7 +666,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
- nf_flow_vlan_pop(skb, tuplehash);
|
||||
+ nf_flow_vlan_pop(skb, tuplehash, strip_pvid);
|
||||
|
||||
if (skb_try_make_writable(skb, sizeof(*ip6h)))
|
||||
return NF_DROP;
|
@ -0,0 +1,108 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Thu, 4 Mar 2021 19:24:11 +0100
|
||||
Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if
|
||||
hardware offload is enabled
|
||||
|
||||
If there is a forward path to reach an ethernet device and hardware
|
||||
offload is enabled, then use the direct xmit path.
|
||||
---
|
||||
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -131,6 +131,7 @@ struct flow_offload_tuple {
|
||||
struct dst_entry *dst_cache;
|
||||
struct {
|
||||
u32 ifidx;
|
||||
+ u32 hw_ifidx;
|
||||
u8 h_source[ETH_ALEN];
|
||||
u8 h_dest[ETH_ALEN];
|
||||
} out;
|
||||
@@ -188,6 +189,7 @@ struct nf_flow_route {
|
||||
} in;
|
||||
struct {
|
||||
u32 ifindex;
|
||||
+ u32 hw_ifindex;
|
||||
u8 h_source[ETH_ALEN];
|
||||
u8 h_dest[ETH_ALEN];
|
||||
} out;
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -106,6 +106,7 @@ static int flow_offload_fill_route(struc
|
||||
memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source,
|
||||
ETH_ALEN);
|
||||
flow_tuple->out.ifidx = route->tuple[dir].out.ifindex;
|
||||
+ flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex;
|
||||
break;
|
||||
case FLOW_OFFLOAD_XMIT_XFRM:
|
||||
case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||
--- a/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
|
||||
switch (this_tuple->xmit_type) {
|
||||
case FLOW_OFFLOAD_XMIT_DIRECT:
|
||||
this_tuple = &flow->tuplehash[dir].tuple;
|
||||
- ifindex = this_tuple->out.ifidx;
|
||||
+ ifindex = this_tuple->out.hw_ifidx;
|
||||
break;
|
||||
case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||
other_tuple = &flow->tuplehash[!dir].tuple;
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -66,6 +66,7 @@ static int nft_dev_fill_forward_path(con
|
||||
struct nft_forward_info {
|
||||
const struct net_device *indev;
|
||||
const struct net_device *outdev;
|
||||
+ const struct net_device *hw_outdev;
|
||||
struct id {
|
||||
__u16 id;
|
||||
__be16 proto;
|
||||
@@ -76,9 +77,18 @@ struct nft_forward_info {
|
||||
enum flow_offload_xmit_type xmit_type;
|
||||
};
|
||||
|
||||
+static bool nft_is_valid_ether_device(const struct net_device *dev)
|
||||
+{
|
||||
+ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
|
||||
+ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static void nft_dev_path_info(const struct net_device_path_stack *stack,
|
||||
struct nft_forward_info *info,
|
||||
- unsigned char *ha)
|
||||
+ unsigned char *ha, struct nf_flowtable *flowtable)
|
||||
{
|
||||
const struct net_device_path *path;
|
||||
int i;
|
||||
@@ -140,6 +150,12 @@ static void nft_dev_path_info(const stru
|
||||
}
|
||||
if (!info->outdev)
|
||||
info->outdev = info->indev;
|
||||
+
|
||||
+ info->hw_outdev = info->indev;
|
||||
+
|
||||
+ if (nf_flowtable_hw_offload(flowtable) &&
|
||||
+ nft_is_valid_ether_device(info->indev))
|
||||
+ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
|
||||
}
|
||||
|
||||
static bool nft_flowtable_find_dev(const struct net_device *dev,
|
||||
@@ -171,7 +187,7 @@ static void nft_dev_forward_path(struct
|
||||
int i;
|
||||
|
||||
if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
|
||||
- nft_dev_path_info(&stack, &info, ha);
|
||||
+ nft_dev_path_info(&stack, &info, ha, &ft->data);
|
||||
|
||||
if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
|
||||
return;
|
||||
@@ -187,6 +203,7 @@ static void nft_dev_forward_path(struct
|
||||
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
|
||||
memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN);
|
||||
route->tuple[dir].out.ifindex = info.outdev->ifindex;
|
||||
+ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex;
|
||||
route->tuple[dir].xmit_type = info.xmit_type;
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 10 Feb 2021 19:44:33 +0100
|
||||
Subject: [PATCH] netfilter: flowtable: handle bridge vlan filter offload
|
||||
tags from DSA/switchdev
|
||||
|
||||
When a switchdev/DSA port is an untagged member of a bridge vlan, ingress
|
||||
packets could potentially be tagged with the id of the VLAN.
|
||||
When the VLAN port group has been uploaded to switchdev, report the bridge
|
||||
tag mode as DEV_PATH_BR_VLAN_UNTAG_HW instead of DEV_PATH_BR_VLAN_UNTAG
|
||||
and handle it in netfilter flow offloading by storing the tag in the tuple
|
||||
in_pvid field.
|
||||
This allows the ingress hook to detect the optional tag and remove it for
|
||||
software offload. This tag processing is for ingress only, egress needs to be
|
||||
fully untagged
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -853,6 +853,7 @@ struct net_device_path {
|
||||
DEV_PATH_BR_VLAN_KEEP,
|
||||
DEV_PATH_BR_VLAN_TAG,
|
||||
DEV_PATH_BR_VLAN_UNTAG,
|
||||
+ DEV_PATH_BR_VLAN_UNTAG_HW,
|
||||
} vlan_mode;
|
||||
u16 vlan_id;
|
||||
__be16 vlan_proto;
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -183,6 +183,10 @@ struct nf_flow_route {
|
||||
u32 ifindex;
|
||||
u16 vid[NF_FLOW_TABLE_VLAN_MAX];
|
||||
__be16 vproto[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ struct {
|
||||
+ u16 id;
|
||||
+ __be16 proto;
|
||||
+ } pvid;
|
||||
u8 num_vlans;
|
||||
} in;
|
||||
struct {
|
||||
--- a/net/bridge/br_device.c
|
||||
+++ b/net/bridge/br_device.c
|
||||
@@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n
|
||||
ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
|
||||
ctx->num_vlans++;
|
||||
break;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||
case DEV_PATH_BR_VLAN_UNTAG:
|
||||
ctx->num_vlans--;
|
||||
break;
|
||||
--- a/net/bridge/br_vlan.c
|
||||
+++ b/net/bridge/br_vlan.c
|
||||
@@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc
|
||||
|
||||
if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
|
||||
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
|
||||
+ else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)
|
||||
+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
|
||||
else
|
||||
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
|
||||
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -98,6 +98,8 @@ static int flow_offload_fill_route(struc
|
||||
j++;
|
||||
}
|
||||
flow_tuple->in_vlan_num = route->tuple[dir].in.num_vlans;
|
||||
+ flow_tuple->in_pvid.id = route->tuple[dir].in.pvid.id;
|
||||
+ flow_tuple->in_pvid.proto = route->tuple[dir].in.pvid.proto;
|
||||
|
||||
switch (route->tuple[dir].xmit_type) {
|
||||
case FLOW_OFFLOAD_XMIT_DIRECT:
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -67,6 +67,10 @@ struct nft_forward_info {
|
||||
const struct net_device *dev;
|
||||
__u16 vid[NF_FLOW_TABLE_VLAN_MAX];
|
||||
__be16 vproto[NF_FLOW_TABLE_VLAN_MAX];
|
||||
+ struct {
|
||||
+ __u16 id;
|
||||
+ __be16 proto;
|
||||
+ } pvid;
|
||||
u8 num_vlans;
|
||||
u8 h_source[ETH_ALEN];
|
||||
u8 h_dest[ETH_ALEN];
|
||||
@@ -127,6 +131,10 @@ static void nft_dev_path_info(const stru
|
||||
info->vproto[info->num_vlans] = path->bridge.vlan_proto;
|
||||
info->num_vlans++;
|
||||
break;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||
+ info->pvid.id = info->vid[info->num_vlans - 1];
|
||||
+ info->pvid.proto = info->vproto[info->num_vlans - 1];
|
||||
+ fallthrough;
|
||||
case DEV_PATH_BR_VLAN_UNTAG:
|
||||
info->num_vlans--;
|
||||
break;
|
||||
@@ -185,6 +193,8 @@ static void nft_dev_forward_path(struct
|
||||
route->tuple[!dir].in.vid[i] = info.vid[i];
|
||||
route->tuple[!dir].in.vproto[i] = info.vproto[i];
|
||||
}
|
||||
+ route->tuple[!dir].in.pvid.id = info.pvid.id;
|
||||
+ route->tuple[!dir].in.pvid.proto = info.pvid.proto;
|
||||
route->tuple[!dir].in.num_vlans = info.num_vlans;
|
||||
|
||||
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
|
@ -0,0 +1,122 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 8 Mar 2021 12:06:44 +0100
|
||||
Subject: [PATCH] netfilter: nf_flow_table: fix untagging with
|
||||
hardware-offloaded bridge vlan_filtering
|
||||
|
||||
When switchdev offloading is enabled, treat an untagged VLAN as tagged for
|
||||
ingress only
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -855,6 +855,7 @@ struct net_device_path {
|
||||
DEV_PATH_BR_VLAN_KEEP,
|
||||
DEV_PATH_BR_VLAN_TAG,
|
||||
DEV_PATH_BR_VLAN_UNTAG,
|
||||
+ DEV_PATH_BR_VLAN_UNTAG_HW,
|
||||
} vlan_mode;
|
||||
u16 vlan_id;
|
||||
__be16 vlan_proto;
|
||||
--- a/include/net/netfilter/nf_flow_table.h
|
||||
+++ b/include/net/netfilter/nf_flow_table.h
|
||||
@@ -123,9 +123,10 @@ struct flow_offload_tuple {
|
||||
/* All members above are keys for lookups, see flow_offload_hash(). */
|
||||
struct { } __hash;
|
||||
|
||||
- u8 dir:4,
|
||||
+ u8 dir:2,
|
||||
xmit_type:2,
|
||||
- encap_num:2;
|
||||
+ encap_num:2,
|
||||
+ in_vlan_ingress:2;
|
||||
u16 mtu;
|
||||
union {
|
||||
struct dst_entry *dst_cache;
|
||||
@@ -185,7 +186,8 @@ struct nf_flow_route {
|
||||
u16 id;
|
||||
__be16 proto;
|
||||
} encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||
- u8 num_encaps;
|
||||
+ u8 num_encaps:2,
|
||||
+ ingress_vlans:2;
|
||||
} in;
|
||||
struct {
|
||||
u32 ifindex;
|
||||
--- a/net/bridge/br_device.c
|
||||
+++ b/net/bridge/br_device.c
|
||||
@@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n
|
||||
ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
|
||||
ctx->num_vlans++;
|
||||
break;
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||
case DEV_PATH_BR_VLAN_UNTAG:
|
||||
ctx->num_vlans--;
|
||||
break;
|
||||
--- a/net/bridge/br_vlan.c
|
||||
+++ b/net/bridge/br_vlan.c
|
||||
@@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc
|
||||
|
||||
if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
|
||||
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
|
||||
+ else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)
|
||||
+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
|
||||
else
|
||||
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
|
||||
|
||||
--- a/net/netfilter/nf_flow_table_core.c
|
||||
+++ b/net/netfilter/nf_flow_table_core.c
|
||||
@@ -95,6 +95,8 @@ static int flow_offload_fill_route(struc
|
||||
for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) {
|
||||
flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id;
|
||||
flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto;
|
||||
+ if (route->tuple[dir].in.ingress_vlans & BIT(i))
|
||||
+ flow_tuple->in_vlan_ingress |= BIT(j);
|
||||
j++;
|
||||
}
|
||||
flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
|
||||
--- a/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
|
||||
other_tuple = &flow->tuplehash[!dir].tuple;
|
||||
|
||||
for (i = 0; i < other_tuple->encap_num; i++) {
|
||||
- struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
|
||||
+ struct flow_action_entry *entry;
|
||||
|
||||
+ if (other_tuple->in_vlan_ingress & BIT(i))
|
||||
+ continue;
|
||||
+
|
||||
+ entry = flow_action_entry_next(flow_rule);
|
||||
entry->id = FLOW_ACTION_VLAN_PUSH;
|
||||
entry->vlan.vid = other_tuple->encap[i].id;
|
||||
entry->vlan.proto = other_tuple->encap[i].proto;
|
||||
--- a/net/netfilter/nft_flow_offload.c
|
||||
+++ b/net/netfilter/nft_flow_offload.c
|
||||
@@ -72,6 +72,7 @@ struct nft_forward_info {
|
||||
__be16 proto;
|
||||
} encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||
u8 num_encaps;
|
||||
+ u8 ingress_vlans;
|
||||
u8 h_source[ETH_ALEN];
|
||||
u8 h_dest[ETH_ALEN];
|
||||
enum flow_offload_xmit_type xmit_type;
|
||||
@@ -130,6 +131,9 @@ static void nft_dev_path_info(const stru
|
||||
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch (path->bridge.vlan_mode) {
|
||||
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||
+ info->ingress_vlans |= BIT(info->num_encaps - 1);
|
||||
+ break;
|
||||
case DEV_PATH_BR_VLAN_TAG:
|
||||
info->encap[info->num_encaps].id = path->bridge.vlan_id;
|
||||
info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
|
||||
@@ -198,6 +202,7 @@ static void nft_dev_forward_path(struct
|
||||
route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
|
||||
}
|
||||
route->tuple[!dir].in.num_encaps = info.num_encaps;
|
||||
+ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
|
||||
|
||||
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
|
||||
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
|
@ -0,0 +1,26 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue, 2 Mar 2021 00:51:31 +0100
|
||||
Subject: [PATCH] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH
|
||||
|
||||
---
|
||||
|
||||
--- a/include/net/flow_offload.h
|
||||
+++ b/include/net/flow_offload.h
|
||||
@@ -147,6 +147,7 @@ enum flow_action_id {
|
||||
FLOW_ACTION_MPLS_POP,
|
||||
FLOW_ACTION_MPLS_MANGLE,
|
||||
FLOW_ACTION_GATE,
|
||||
+ FLOW_ACTION_PPPOE_PUSH,
|
||||
NUM_FLOW_ACTIONS,
|
||||
};
|
||||
|
||||
@@ -271,6 +272,9 @@ struct flow_action_entry {
|
||||
u32 num_entries;
|
||||
struct action_gate_entry *entries;
|
||||
} gate;
|
||||
+ struct { /* FLOW_ACTION_PPPOE_PUSH */
|
||||
+ u16 sid;
|
||||
+ } pppoe;
|
||||
};
|
||||
struct flow_action_cookie *cookie; /* user defined action cookie */
|
||||
};
|
@ -0,0 +1,31 @@
|
||||
From: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue, 2 Mar 2021 01:01:50 +0100
|
||||
Subject: [PATCH] netfilter: flowtable: support for
|
||||
FLOW_ACTION_PPPOE_PUSH
|
||||
|
||||
---
|
||||
|
||||
--- a/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
|
||||
continue;
|
||||
|
||||
entry = flow_action_entry_next(flow_rule);
|
||||
- entry->id = FLOW_ACTION_VLAN_PUSH;
|
||||
- entry->vlan.vid = other_tuple->encap[i].id;
|
||||
- entry->vlan.proto = other_tuple->encap[i].proto;
|
||||
+
|
||||
+ switch (other_tuple->encap[i].proto) {
|
||||
+ case htons(ETH_P_PPP_SES):
|
||||
+ entry->id = FLOW_ACTION_PPPOE_PUSH;
|
||||
+ entry->pppoe.sid = other_tuple->encap[i].id;
|
||||
+ break;
|
||||
+ case htons(ETH_P_8021Q):
|
||||
+ entry->id = FLOW_ACTION_VLAN_PUSH;
|
||||
+ entry->vlan.vid = other_tuple->encap[i].id;
|
||||
+ entry->vlan.proto = other_tuple->encap[i].proto;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -2031,6 +2031,8 @@ struct net_device {
|
||||
@@ -2033,6 +2033,8 @@ struct net_device {
|
||||
struct netdev_hw_addr_list mc;
|
||||
struct netdev_hw_addr_list dev_addrs;
|
||||
|
||||
|
@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
};
|
||||
|
||||
enum gro_result {
|
||||
@@ -2411,6 +2414,26 @@ void netif_napi_add(struct net_device *d
|
||||
@@ -2413,6 +2416,26 @@ void netif_napi_add(struct net_device *d
|
||||
int (*poll)(struct napi_struct *, int), int weight);
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
#endif /* MTK_ETH_H */
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
||||
@@ -0,0 +1,478 @@
|
||||
@@ -0,0 +1,491 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
|
||||
@ -113,6 +113,10 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ __be16 proto;
|
||||
+ u8 num;
|
||||
+ } vlan;
|
||||
+ struct {
|
||||
+ u16 sid;
|
||||
+ u8 num;
|
||||
+ } pppoe;
|
||||
+};
|
||||
+
|
||||
+struct mtk_flow_entry {
|
||||
@ -311,13 +315,20 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ break;
|
||||
+ case FLOW_ACTION_VLAN_PUSH:
|
||||
+ if (data.vlan.num == 1 ||
|
||||
+ data.vlan.proto != ETH_P_8021Q)
|
||||
+ act->vlan.proto != htons(ETH_P_8021Q))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ data.vlan.id = act->vlan.vid;
|
||||
+ data.vlan.proto = act->vlan.proto;
|
||||
+ data.vlan.num++;
|
||||
+ break;
|
||||
+ case FLOW_ACTION_PPPOE_PUSH:
|
||||
+ if (data.pppoe.num == 1)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ data.pppoe.sid = act->pppoe.sid;
|
||||
+ data.pppoe.num++;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
@ -392,11 +403,13 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
+ }
|
||||
+
|
||||
+ if (data.vlan.num == 1) {
|
||||
+ if (data.vlan.proto != ETH_P_8021Q)
|
||||
+ if (data.vlan.proto != htons(ETH_P_8021Q))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ mtk_foe_entry_set_vlan(&foe, data.vlan.id);
|
||||
+ }
|
||||
+ if (data.pppoe.num == 1)
|
||||
+ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
|
||||
+
|
||||
+ err = mtk_flow_set_output_device(eth, &foe, odev);
|
||||
+ if (err)
|
||||
|
Loading…
Reference in New Issue
Block a user