mirror of https://gitee.com/openkylin/linux.git
netfilter: flowtable: bridge vlan hardware offload and switchdev
The switch might have already added the VLAN tag through PVID hardware offload. Keep this extra VLAN in the flowtable but skip it on egress. Signed-off-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
73f97025a9
commit
26267bf9bb
|
@ -870,6 +870,7 @@ struct net_device_path {
|
||||||
DEV_PATH_BR_VLAN_KEEP,
|
DEV_PATH_BR_VLAN_KEEP,
|
||||||
DEV_PATH_BR_VLAN_TAG,
|
DEV_PATH_BR_VLAN_TAG,
|
||||||
DEV_PATH_BR_VLAN_UNTAG,
|
DEV_PATH_BR_VLAN_UNTAG,
|
||||||
|
DEV_PATH_BR_VLAN_UNTAG_HW,
|
||||||
} vlan_mode;
|
} vlan_mode;
|
||||||
u16 vlan_id;
|
u16 vlan_id;
|
||||||
__be16 vlan_proto;
|
__be16 vlan_proto;
|
||||||
|
|
|
@ -123,9 +123,10 @@ struct flow_offload_tuple {
|
||||||
/* All members above are keys for lookups, see flow_offload_hash(). */
|
/* All members above are keys for lookups, see flow_offload_hash(). */
|
||||||
struct { } __hash;
|
struct { } __hash;
|
||||||
|
|
||||||
u8 dir:4,
|
u8 dir:2,
|
||||||
xmit_type:2,
|
xmit_type:2,
|
||||||
encap_num:2;
|
encap_num:2,
|
||||||
|
in_vlan_ingress:2;
|
||||||
u16 mtu;
|
u16 mtu;
|
||||||
union {
|
union {
|
||||||
struct dst_entry *dst_cache;
|
struct dst_entry *dst_cache;
|
||||||
|
@ -185,7 +186,8 @@ struct nf_flow_route {
|
||||||
u16 id;
|
u16 id;
|
||||||
__be16 proto;
|
__be16 proto;
|
||||||
} encap[NF_FLOW_TABLE_ENCAP_MAX];
|
} encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||||
u8 num_encaps;
|
u8 num_encaps:2,
|
||||||
|
ingress_vlans:2;
|
||||||
} in;
|
} in;
|
||||||
struct {
|
struct {
|
||||||
u32 ifindex;
|
u32 ifindex;
|
||||||
|
|
|
@ -422,6 +422,7 @@ static int br_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||||
ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
|
ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
|
||||||
ctx->num_vlans++;
|
ctx->num_vlans++;
|
||||||
break;
|
break;
|
||||||
|
case DEV_PATH_BR_VLAN_UNTAG_HW:
|
||||||
case DEV_PATH_BR_VLAN_UNTAG:
|
case DEV_PATH_BR_VLAN_UNTAG:
|
||||||
ctx->num_vlans--;
|
ctx->num_vlans--;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1386,6 +1386,8 @@ int br_vlan_fill_forward_path_mode(struct net_bridge *br,
|
||||||
|
|
||||||
if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
|
if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
|
||||||
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
|
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
|
else
|
||||||
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
|
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,8 @@ static int flow_offload_fill_route(struct flow_offload *flow,
|
||||||
for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; 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].id = route->tuple[dir].in.encap[i].id;
|
||||||
flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto;
|
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++;
|
j++;
|
||||||
}
|
}
|
||||||
flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
|
flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
|
||||||
|
|
|
@ -594,8 +594,12 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,
|
||||||
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++) {
|
||||||
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->id = FLOW_ACTION_VLAN_PUSH;
|
||||||
entry->vlan.vid = other_tuple->encap[i].id;
|
entry->vlan.vid = other_tuple->encap[i].id;
|
||||||
entry->vlan.proto = other_tuple->encap[i].proto;
|
entry->vlan.proto = other_tuple->encap[i].proto;
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct nft_forward_info {
|
||||||
__be16 proto;
|
__be16 proto;
|
||||||
} encap[NF_FLOW_TABLE_ENCAP_MAX];
|
} encap[NF_FLOW_TABLE_ENCAP_MAX];
|
||||||
u8 num_encaps;
|
u8 num_encaps;
|
||||||
|
u8 ingress_vlans;
|
||||||
u8 h_source[ETH_ALEN];
|
u8 h_source[ETH_ALEN];
|
||||||
u8 h_dest[ETH_ALEN];
|
u8 h_dest[ETH_ALEN];
|
||||||
enum flow_offload_xmit_type xmit_type;
|
enum flow_offload_xmit_type xmit_type;
|
||||||
|
@ -130,6 +131,9 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
|
||||||
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
|
||||||
|
|
||||||
switch (path->bridge.vlan_mode) {
|
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:
|
case DEV_PATH_BR_VLAN_TAG:
|
||||||
info->encap[info->num_encaps].id = path->bridge.vlan_id;
|
info->encap[info->num_encaps].id = path->bridge.vlan_id;
|
||||||
info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
|
info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
|
||||||
|
@ -198,6 +202,7 @@ static void nft_dev_forward_path(struct nf_flow_route *route,
|
||||||
route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
|
route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
|
||||||
}
|
}
|
||||||
route->tuple[!dir].in.num_encaps = info.num_encaps;
|
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) {
|
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_source, info.h_source, ETH_ALEN);
|
||||||
|
|
Loading…
Reference in New Issue