Currently, the zone based config has a single line for a zone peering, along with one line for intra-zone traffic. This scales very poorly, especially when there are a large number of zones. This will slow down the processing of traffic dramatically when there are a large number of peerings. With only 10 zones, that can potentially create 90 zone pairings, plus 10 intra-zone rules, for a total of 100 rules.
Vmaps can solve this by using a hash-map of jump targets, allowing for traffic to only need to traverse a single rule rather than 100. Traffic enters the vmap, and looks up the hash for the iifname and oifname pairing, and jumps to the appropriate chain.
Config:
set firewall ipv4 name A_B default-action 'accept' set firewall ipv4 name A_C default-action 'accept' set firewall ipv4 name A_D default-action 'accept' set firewall ipv4 name A_E default-action 'accept' set firewall ipv4 name A_F default-action 'accept' set firewall ipv4 name A_G default-action 'accept' set firewall zone A from B firewall name 'A_B' set firewall zone A from C firewall name 'A_C' set firewall zone A from D firewall name 'A_D' set firewall zone A from E firewall name 'A_E' set firewall zone A from F firewall name 'A_F' set firewall zone A from G firewall name 'A_G' set firewall zone A interface 'eth0.100' set firewall zone A intra-zone-filtering action 'drop' set firewall zone B interface 'eth0.101' set firewall zone C interface 'eth0.102' set firewall zone D interface 'eth0.103' set firewall zone E interface 'eth0.104' set firewall zone F interface 'eth0.105' set firewall zone G interface 'eth0.106'
Existing nft config that is generated:
You can see that I only have explicit zone pairings from zone 'A' to the other zones, and don't even have the return pairings, or any other pairings like 'B' to 'C'. Even with that, there are still 7 rules to traverse in VYOS_ZONE_FORWARD , along with 15 rules in VZONE_A
table ip vyos_filter {
chain NAME_A_B {
counter accept comment "NAM-A_B default-action accept"
}
chain NAME_A_C {
counter accept comment "NAM-A_C default-action accept"
}
chain NAME_A_D {
counter accept comment "NAM-A_D default-action accept"
}
chain NAME_A_E {
counter accept comment "NAM-A_E default-action accept"
}
chain NAME_A_F {
counter accept comment "NAM-A_F default-action accept"
}
chain NAME_A_G {
counter accept comment "NAM-A_G default-action accept"
}
chain VYOS_ZONE_FORWARD {
type filter hook forward priority filter + 1; policy accept;
oifname "eth0.100" counter jump VZONE_A
oifname "eth0.101" counter jump VZONE_B
oifname "eth0.102" counter jump VZONE_C
oifname "eth0.103" counter jump VZONE_D
oifname "eth0.104" counter jump VZONE_E
oifname "eth0.105" counter jump VZONE_F
oifname "eth0.106" counter jump VZONE_G
}
chain VYOS_ZONE_LOCAL {
type filter hook input priority filter + 1; policy accept;
}
chain VYOS_ZONE_OUTPUT {
type filter hook output priority filter + 1; policy accept;
}
chain VZONE_A {
iifname "eth0.100" counter drop
iifname "eth0.100" counter return
iifname "eth0.101" counter jump NAME_A_B
iifname "eth0.101" counter return
iifname "eth0.102" counter jump NAME_A_C
iifname "eth0.102" counter return
iifname "eth0.103" counter jump NAME_A_D
iifname "eth0.103" counter return
iifname "eth0.104" counter jump NAME_A_E
iifname "eth0.104" counter return
iifname "eth0.105" counter jump NAME_A_F
iifname "eth0.105" counter return
iifname "eth0.106" counter jump NAME_A_G
iifname "eth0.106" counter return
counter drop comment "zone_A default-action drop"
}
chain VZONE_B {
iifname "eth0.101" counter return
counter drop comment "zone_B default-action drop"
}
chain VZONE_C {
iifname "eth0.102" counter return
counter drop comment "zone_C default-action drop"
}
chain VZONE_D {
iifname "eth0.103" counter return
counter drop comment "zone_D default-action drop"
}
chain VZONE_E {
iifname "eth0.104" counter return
counter drop comment "zone_E default-action drop"
}
chain VZONE_F {
iifname "eth0.105" counter return
counter drop comment "zone_F default-action drop"
}
chain VZONE_G {
iifname "eth0.106" counter return
counter drop comment "zone_G default-action drop"
}
}Proposed change to the generated nft config:
In this solution, all of the VZONE chains are removed in favor of a single vmap. A single rule in VYOS_ZONE_FORWARD is used to enter the vmap. This is radically more efficient when processing traffic. Even with this minimal config of 6 zone pairings, you'd see efficiency gains.
table ip vyos_filter {
map zone_fwd {
type ifname . ifname : verdict
counter
elements = { "eth0.100" . "eth0.100" counter : drop,
"eth0.100" . "eth0.101" counter : jump NAME_A_B,
"eth0.101" . "eth0.101" counter : return,
"eth0.100" . "eth0.102" counter : jump NAME_A_C,
"eth0.102" . "eth0.102" counter : return,
"eth0.100" . "eth0.103" counter : jump NAME_A_D,
"eth0.103" . "eth0.103" counter : return,
"eth0.100" . "eth0.104" counter : jump NAME_A_E,
"eth0.104" . "eth0.104" counter : return,
"eth0.100" . "eth0.105" counter : jump NAME_A_F,
"eth0.105" . "eth0.105" counter : return,
"eth0.100" . "eth0.106" counter : jump NAME_A_G,
"eth0.106" . "eth0.106" counter : return }
}
chain NAME_A_B {
counter accept comment "NAM-A_B default-action accept"
}
chain NAME_A_C {
counter accept comment "NAM-A_C default-action accept"
}
chain NAME_A_D {
counter accept comment "NAM-A_D default-action accept"
}
chain NAME_A_E {
counter accept comment "NAM-A_E default-action accept"
}
chain NAME_A_F {
counter accept comment "NAM-A_F default-action accept"
}
chain NAME_A_G {
counter accept comment "NAM-A_G default-action accept"
}
chain VYOS_ZONE_FORWARD {
type filter hook forward priority filter + 1; policy accept;
oifname . iifname vmap @zone_fwd
counter log prefix "[default-drop]" drop comment "zone default-action drop"
}
chain VYOS_ZONE_LOCAL {
type filter hook input priority filter + 1; policy accept;
}
chain VYOS_ZONE_OUTPUT {
type filter hook output priority filter + 1; policy accept;
}
}