Skip to content

Commit

Permalink
netfilter: flowtable: bridge vlan hardware offload and switchdev
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felix Fietkau authored and David S. Miller committed Mar 24, 2021
1 parent 73f9702 commit 26267bf
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,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;
Expand Down
8 changes: 5 additions & 3 deletions include/net/netfilter/nf_flow_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->num_vlans++;
break;
case DEV_PATH_BR_VLAN_UNTAG_HW:
case DEV_PATH_BR_VLAN_UNTAG:
ctx->num_vlans--;
break;
Expand Down
2 changes: 2 additions & 0 deletions net/bridge/br_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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;

Expand Down
2 changes: 2 additions & 0 deletions net/netfilter/nf_flow_table_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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--) {
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;
Expand Down
6 changes: 5 additions & 1 deletion net/netfilter/nf_flow_table_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,12 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,
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;
Expand Down
5 changes: 5 additions & 0 deletions net/netfilter/nft_flow_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

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;
Expand Down Expand Up @@ -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.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);
Expand Down

0 comments on commit 26267bf

Please sign in to comment.