diff --git a/acl+fwstate.yaml b/acl+fwstate.yaml index 20792641..48a98c11 100644 --- a/acl+fwstate.yaml +++ b/acl+fwstate.yaml @@ -13,8 +13,8 @@ rules: # === IPv4 === # Create state for outgoing TCP to port 80 - - action: CreateState - counter: "" + - actions: + - kind: CreateState devices: [] dst_ports: - from: 80 @@ -32,8 +32,8 @@ rules: vlan_ranges: [] # Check state for return traffic - - action: CheckState - counter: "" + - actions: + - kind: CheckState devices: [] dst_ports: - from: 0 @@ -51,8 +51,8 @@ rules: vlan_ranges: [] # Create state for outgoing UDP to port 80 - - action: CreateState - counter: "" + - actions: + - kind: CreateState devices: [] dst_ports: - from: 80 @@ -70,8 +70,8 @@ rules: vlan_ranges: [] # Check state for return UDP traffic - - action: CheckState - counter: "" + - actions: + - kind: CheckState devices: [] dst_ports: - from: 0 @@ -91,8 +91,8 @@ rules: # === IPv6 === # Create state for outgoing TCPv6 to port 80 - - action: CreateState - counter: "" + - actions: + - kind: CreateState devices: [] dst_ports: - from: 80 @@ -110,8 +110,8 @@ rules: vlan_ranges: [] # Check state for return TCPv6 traffic - - action: CheckState - counter: "" + - actions: + - kind: CheckState devices: [] dst_ports: - from: 0 @@ -133,8 +133,8 @@ rules: # Allow external fwstate sync frames (IPv6 UDP to multicast ff02::1 port 9999). # These packets are processed by the fwstate module to create external state # entries and then dropped. - - action: Allow - counter: "" + - actions: + - kind: Allow devices: [] dst_ports: - from: 9999 diff --git a/modules/acl/api/controlplane.c b/modules/acl/api/controlplane.c index f20924ce..cb2ceb88 100644 --- a/modules/acl/api/controlplane.c +++ b/modules/acl/api/controlplane.c @@ -458,19 +458,23 @@ acl_module_config_update( for (uint32_t idx = 0; idx < rule_count; ++idx) { struct acl_rule *acl_rule = acl_rules + idx; - targets[idx].action = acl_rule->action; - if (acl_rule->counter[0] == '\0') + struct acl_action *terminal = + &acl_rule->actions[acl_rule->action_count - 1]; + targets[idx].action = terminal->id; + + const char *counter_name = terminal->counter; + char default_counter[COUNTER_NAME_LEN]; + if (counter_name[0] == '\0') { snprintf( - acl_rule->counter, - sizeof(acl_rule->counter), + default_counter, + sizeof(default_counter), "rule %d", idx ); + counter_name = default_counter; + } if ((targets[idx].counter_id = counter_registry_register( - &cp_module->counter_registry, - acl_rule->counter, - 2, - err + &cp_module->counter_registry, counter_name, 2, err )) == (uint64_t)-1) { goto error_target; } diff --git a/modules/acl/api/controlplane.h b/modules/acl/api/controlplane.h index 174ef169..f181c914 100644 --- a/modules/acl/api/controlplane.h +++ b/modules/acl/api/controlplane.h @@ -19,9 +19,14 @@ acl_module_config_init( void acl_module_config_free(struct cp_module *cp_module); -struct acl_rule { - uint64_t action; +struct acl_action { + uint64_t id; char counter[COUNTER_NAME_LEN]; +}; + +struct acl_rule { + struct acl_action *actions; + uint64_t action_count; struct filter_devices devices; struct filter_vlan_ranges vlan_ranges; diff --git a/modules/acl/cli/src/main.rs b/modules/acl/cli/src/main.rs index 85b29ffd..4afbbcf1 100644 --- a/modules/acl/cli/src/main.rs +++ b/modules/acl/cli/src/main.rs @@ -47,14 +47,13 @@ struct SerializableRule { proto_ranges: Vec, vlan_ranges: Vec, devices: Vec, - action: Option, + actions: Vec, } #[derive(Serialize)] struct SerializableAction { + kind: String, counter: String, - keep_state: bool, - kind: i32, } #[derive(Tabled)] @@ -387,8 +386,17 @@ enum ActionKind { Allow, Deny, Count, + SkipTo, CheckState, CreateState, + Log, +} + +#[derive(Debug, Serialize, Deserialize)] +struct ACLAction { + kind: ActionKind, + #[serde(default)] + counter: String, } #[derive(Debug, Serialize, Deserialize)] @@ -400,8 +408,7 @@ struct ACLRule { proto_ranges: Vec, vlan_ranges: Vec, devices: Vec, - counter: String, - action: ActionKind, + actions: Vec, } /// Converts a YAML `Range` to a protobuf `PortRange`, validating that @@ -470,18 +477,23 @@ impl TryFrom for aclpb::Rule { .collect::>()?, vlan_ranges: acl_rule.vlan_ranges.iter().map(vlan_range).collect::>()?, devices: acl_rule.devices.iter().cloned().map(Device::from).collect(), - action: Some(aclpb::Action { - counter: acl_rule.counter, - keep_state: false, - kind: match acl_rule.action { - ActionKind::Allow => aclpb::ActionKind::Pass, - ActionKind::Deny => aclpb::ActionKind::Deny, - ActionKind::Count => aclpb::ActionKind::Count, - ActionKind::CheckState => aclpb::ActionKind::CheckState, - ActionKind::CreateState => aclpb::ActionKind::CreateState, - } - .into(), - }), + actions: acl_rule + .actions + .iter() + .map(|a| aclpb::Action { + kind: match a.kind { + ActionKind::Allow => aclpb::ActionKind::Pass, + ActionKind::Deny => aclpb::ActionKind::Deny, + ActionKind::Count => aclpb::ActionKind::Count, + ActionKind::SkipTo => aclpb::ActionKind::Skipto, + ActionKind::CheckState => aclpb::ActionKind::CheckState, + ActionKind::CreateState => aclpb::ActionKind::CreateState, + ActionKind::Log => aclpb::ActionKind::Log, + } + .into(), + counter: a.counter.clone(), + }) + .collect(), }) } } @@ -573,11 +585,16 @@ impl ACLService { .map(|r| format!("{}-{}", r.from, r.to)) .collect(), devices: rule.devices.iter().map(|d| d.name.clone()).collect(), - action: rule.action.map(|a| SerializableAction { - counter: a.counter, - keep_state: a.keep_state, - kind: a.kind, - }), + actions: rule + .actions + .iter() + .map(|a| SerializableAction { + kind: aclpb::ActionKind::try_from(a.kind) + .map(|k| k.as_str_name().to_string()) + .unwrap_or_else(|_| a.kind.to_string()), + counter: a.counter.clone(), + }) + .collect(), }) .collect(), }; diff --git a/modules/acl/controlplane/aclpb/acl.proto b/modules/acl/controlplane/aclpb/acl.proto index 9f351d0a..14fcd2d3 100644 --- a/modules/acl/controlplane/aclpb/acl.proto +++ b/modules/acl/controlplane/aclpb/acl.proto @@ -38,7 +38,7 @@ message ShowConfigResponse { } message Rule { - Action action = 1; + repeated Action actions = 1; repeated filterpb.Device devices = 2; repeated filterpb.VlanRange vlan_ranges = 3; @@ -52,7 +52,6 @@ message Rule { message Action { ActionKind kind = 1; string counter = 2; - bool keep_state = 3; } // Defines possible actions for matched traffic @@ -60,8 +59,10 @@ enum ActionKind { ACTION_KIND_PASS = 0; ACTION_KIND_DENY = 1; ACTION_KIND_COUNT = 2; - ACTION_KIND_CHECK_STATE = 3; - ACTION_KIND_CREATE_STATE = 4; + ACTION_KIND_SKIPTO = 3; + ACTION_KIND_CHECK_STATE = 4; + ACTION_KIND_CREATE_STATE = 5; + ACTION_KIND_LOG = 6; } // Delete config with specified name. diff --git a/modules/acl/controlplane/ffi.go b/modules/acl/controlplane/ffi.go index a2f05bf1..50e41640 100644 --- a/modules/acl/controlplane/ffi.go +++ b/modules/acl/controlplane/ffi.go @@ -57,9 +57,13 @@ func (m *ModuleConfig) AsFFIModule() ffi.ModuleConfig { return m.ptr } +type AclAction struct { + ID uint64 + Counter string +} + type AclRule struct { - Action uint64 - Counter string + Actions []AclAction Devices filter.Devices VlanRanges filter.VlanRanges Src4s filter.IPNets @@ -71,14 +75,27 @@ type AclRule struct { DstPortRanges filter.PortRanges } +// CBuildActions writes the C representation of AclActions into dst. +func CBuildActions(dst *C.struct_acl_rule, actions []AclAction, pinner *runtime.Pinner) { + if len(actions) == 0 { + return + } + cActions := make([]C.struct_acl_action, len(actions)) + for idx, a := range actions { + cActions[idx].id = C.uint64_t(a.ID) + cCounter := C.CString(a.Counter) + C.strncpy(&cActions[idx].counter[0], cCounter, C.COUNTER_NAME_LEN) + C.free(unsafe.Pointer(cCounter)) + } + pinner.Pin(&cActions[0]) + dst.actions = &cActions[0] + dst.action_count = C.uint64_t(len(cActions)) +} + func (m *AclRule) CBuild(pinner *runtime.Pinner) C.struct_acl_rule { cRule := C.struct_acl_rule{} - cRule.action = C.uint64_t(m.Action) - cCounter := C.CString(m.Counter) - C.strncpy(&cRule.counter[0], cCounter, C.COUNTER_NAME_LEN) - C.free(unsafe.Pointer(cCounter)) - + CBuildActions(&cRule, m.Actions, pinner) filter.CBuildDevices(&cRule.devices, m.Devices, pinner) filter.CBuildVlanRanges(&cRule.vlan_ranges, m.VlanRanges, pinner) filter.CBuildNet4s(&cRule.src_net4s, m.Src4s, pinner) diff --git a/modules/acl/controlplane/service.go b/modules/acl/controlplane/service.go index 83495956..d29da2f5 100644 --- a/modules/acl/controlplane/service.go +++ b/modules/acl/controlplane/service.go @@ -63,7 +63,33 @@ func (m *ACLService) newHandlerTracker(name string) *handlerMetricTracker { ) } -//////////////////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////////////////// +func terminalAction(protoActions []*aclpb.Action) AclAction { + const ( + cACLActionAllow = 0 + cACLActionDeny = 1 + cACLActionCheckState = 3 + cACLActionCreateState = 4 + ) + + if len(protoActions) == 0 { + return AclAction{ID: cACLActionAllow} + } + + a := protoActions[len(protoActions)-1] + switch a.GetKind() { + case aclpb.ActionKind_ACTION_KIND_PASS: + return AclAction{ID: cACLActionAllow, Counter: a.GetCounter()} + case aclpb.ActionKind_ACTION_KIND_DENY: + return AclAction{ID: cACLActionDeny, Counter: a.GetCounter()} + case aclpb.ActionKind_ACTION_KIND_CHECK_STATE: + return AclAction{ID: cACLActionCheckState, Counter: a.GetCounter()} + case aclpb.ActionKind_ACTION_KIND_CREATE_STATE: + return AclAction{ID: cACLActionCreateState, Counter: a.GetCounter()} + default: + return AclAction{ID: cACLActionDeny, Counter: a.GetCounter()} + } +} func convertRules(reqRules []*aclpb.Rule) ([]AclRule, error) { rules := make([]AclRule, 0, len(reqRules)) @@ -106,7 +132,7 @@ func convertRules(reqRules []*aclpb.Rule) ([]AclRule, error) { } rule := AclRule{ - Counter: reqRule.Action.Counter, + Actions: []AclAction{terminalAction(reqRule.Actions)}, Devices: devices, VlanRanges: vlanRanges, Src4s: src4s, @@ -118,21 +144,6 @@ func convertRules(reqRules []*aclpb.Rule) ([]AclRule, error) { DstPortRanges: dstPortRanges, } - switch reqRule.Action.Kind { - case aclpb.ActionKind_ACTION_KIND_PASS: - rule.Action = 0 // ACL_ACTION_ALLOW - case aclpb.ActionKind_ACTION_KIND_DENY: - rule.Action = 1 // ACL_ACTION_DENY - case aclpb.ActionKind_ACTION_KIND_COUNT: - rule.Action = 2 // ACL_ACTION_COUNT - case aclpb.ActionKind_ACTION_KIND_CHECK_STATE: - rule.Action = 3 // ACL_ACTION_CHECK_STATE - case aclpb.ActionKind_ACTION_KIND_CREATE_STATE: - rule.Action = 4 // ACL_ACTION_CREATE_STATE - default: - rule.Action = 1 // ACL_ACTION_DENY - } - rules = append(rules, rule) } return rules, nil diff --git a/modules/acl/tests/acl/acl_test.go b/modules/acl/tests/acl/acl_test.go index 5468ecec..20453a29 100644 --- a/modules/acl/tests/acl/acl_test.go +++ b/modules/acl/tests/acl/acl_test.go @@ -47,8 +47,7 @@ func (te *testEnv) testPacket(t *testing.T, packetLayers []gopacket.Serializable func createBasicRules() []acl.AclRule { return []acl.AclRule{ { - Action: 0, // PASS - Counter: "", + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, VlanRanges: []filter.VlanRange{}, Src4s: []filter.IPNet{ @@ -71,8 +70,7 @@ func createBasicRules() []acl.AclRule { }, }, { - Action: 1, // DENY - Counter: "", + Actions: []acl.AclAction{{ID: 1}}, // DENY Devices: []filter.Device{{Name: defaultDeviceName}}, VlanRanges: []filter.VlanRange{}, Src4s: []filter.IPNet{ @@ -129,7 +127,7 @@ func TestAcl_BasicRules(t *testing.T) { func createProtocolRules() []acl.AclRule { return []acl.AclRule{ { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.2"), Mask: netip.MustParseAddr("255.255.255.255")}, @@ -181,7 +179,7 @@ func createProtocolRules() []acl.AclRule { }, }, { - Action: 1, // DENY + Actions: []acl.AclAction{{ID: 1}}, // DENY Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("0.0.0.0"), Mask: netip.MustParseAddr("0.0.0.0")}, @@ -217,7 +215,7 @@ func createProtocolRules() []acl.AclRule { }, }, { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.2"), Mask: netip.MustParseAddr("255.255.255.255")}, @@ -268,7 +266,7 @@ func TestAcl_ProtocolRules(t *testing.T) { func createPortRangeRules() []acl.AclRule { return []acl.AclRule{ { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.2"), Mask: netip.MustParseAddr("255.255.255.255")}, @@ -309,7 +307,7 @@ func TestAcl_PortRangeRules(t *testing.T) { func createSubnetRules() []acl.AclRule { return []acl.AclRule{ { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.0"), Mask: netip.MustParseAddr("255.255.255.0")}, @@ -330,7 +328,7 @@ func createSubnetRules() []acl.AclRule { }, }, { - Action: 1, // DENY + Actions: []acl.AclAction{{ID: 1}}, // DENY Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.99.0"), Mask: netip.MustParseAddr("255.255.255.0")}, @@ -373,7 +371,7 @@ func TestAcl_SubnetRules(t *testing.T) { func createIPv6Rules() []acl.AclRule { return []acl.AclRule{ { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{}, Dst4s: []filter.IPNet{}, @@ -394,7 +392,7 @@ func createIPv6Rules() []acl.AclRule { }, }, { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{}, Dst4s: []filter.IPNet{}, @@ -415,7 +413,7 @@ func createIPv6Rules() []acl.AclRule { }, }, { - Action: 1, // DENY + Actions: []acl.AclAction{{ID: 1}}, // DENY Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{}, Dst4s: []filter.IPNet{}, @@ -480,7 +478,7 @@ func TestAcl_IPv6Rules(t *testing.T) { func createOverlappingRules() []acl.AclRule { return []acl.AclRule{ { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.0"), Mask: netip.MustParseAddr("255.255.255.254")}, @@ -501,7 +499,7 @@ func createOverlappingRules() []acl.AclRule { }, }, { - Action: 1, // DENY + Actions: []acl.AclAction{{ID: 1}}, // DENY Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.0"), Mask: netip.MustParseAddr("255.255.255.240")}, @@ -522,7 +520,7 @@ func createOverlappingRules() []acl.AclRule { }, }, { - Action: 0, // PASS + Actions: []acl.AclAction{{ID: 0}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.2.0"), Mask: netip.MustParseAddr("255.255.255.0")}, @@ -543,7 +541,7 @@ func createOverlappingRules() []acl.AclRule { }, }, { - Action: 1, // DENY + Actions: []acl.AclAction{{ID: 1}}, // DENY Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{ {Addr: netip.MustParseAddr("192.0.0.0"), Mask: netip.MustParseAddr("255.255.0.0")}, diff --git a/modules/acl/tests/acl/metrics_test.go b/modules/acl/tests/acl/metrics_test.go index 32fee3cc..8f39bc4d 100644 --- a/modules/acl/tests/acl/metrics_test.go +++ b/modules/acl/tests/acl/metrics_test.go @@ -89,8 +89,7 @@ func gaugeVal(m *commonpb.Metric) float64 { // passRule builds a simple IPv4 UDP PASS rule for the default device func passRule(src, dst, counter string) acl.AclRule { return acl.AclRule{ - Action: 0, - Counter: counter, + Actions: []acl.AclAction{{ID: 0, Counter: counter}}, // PASS Devices: []filter.Device{{Name: defaultDeviceName}}, Src4s: []filter.IPNet{{Addr: netip.MustParseAddr(src), Mask: netip.MustParseAddr("255.255.255.255")}}, Dst4s: []filter.IPNet{{Addr: netip.MustParseAddr(dst), Mask: netip.MustParseAddr("255.255.255.255")}}, @@ -104,7 +103,7 @@ func passRule(src, dst, counter string) acl.AclRule { func denyRule(src, dst string) acl.AclRule { r := passRule(src, dst, "") - r.Action = 1 + r.Actions = []acl.AclAction{{ID: 1}} // DENY return r } @@ -216,7 +215,7 @@ func ip4b(addr string) []byte { return net.ParseIP(addr).To4() } func makeProtoRule(src, dst string, kind aclpb.ActionKind) *aclpb.Rule { mask := ip4b("255.255.255.255") return &aclpb.Rule{ - Action: &aclpb.Action{Kind: kind}, + Actions: []*aclpb.Action{{Kind: kind}}, Devices: []*filterpb.Device{{Name: defaultDeviceName}}, Srcs: []*filterpb.IPNet{{Addr: ip4b(src), Mask: mask}}, Dsts: []*filterpb.IPNet{{Addr: ip4b(dst), Mask: mask}}, diff --git a/tests/functional/testdata/acl-mbuf-leak.yaml b/tests/functional/testdata/acl-mbuf-leak.yaml index 2eda495b..be9643de 100644 --- a/tests/functional/testdata/acl-mbuf-leak.yaml +++ b/tests/functional/testdata/acl-mbuf-leak.yaml @@ -1,6 +1,7 @@ rules: - - action: Count - counter: "count_udp" + - actions: + - kind: Allow + counter: "count_udp" devices: [] dst_ports: - from: 0 @@ -17,8 +18,9 @@ rules: - 192.0.2.30/255.255.255.255 vlan_ranges: [] - - action: CreateState - counter: "create_state_tcp" + - actions: + - kind: CreateState + counter: "create_state_tcp" devices: [] dst_ports: - from: 80 @@ -35,8 +37,9 @@ rules: - 192.0.2.40/255.255.255.255 vlan_ranges: [] - - action: Allow - counter: "allow" + - actions: + - kind: Allow + counter: "allow" devices: [] dst_ports: - from: 0 diff --git a/tests/functional/testdata/acl.yaml b/tests/functional/testdata/acl.yaml index 9c392fff..c7578ba5 100644 --- a/tests/functional/testdata/acl.yaml +++ b/tests/functional/testdata/acl.yaml @@ -5,8 +5,9 @@ # # Structure: # rules: -# - action: Allow|Deny # Action to take -# counter: string # Counter for the rule (currently empty) +# - actions: # List of actions (last one is terminal) +# - kind: Allow|Deny|Count|... # Action kind +# counter: string # Optional counter name # devices: [string] # List of devices (currently empty array) # dst_ports: array # Destination port ranges # - from: int # Start of port range @@ -28,8 +29,8 @@ rules: # Allow UDP 192.0.2.2 -> 192.0.3.1 ports 150-450,600 # 1 # add allow udp from 192.0.2.2 to 192.0.3.1 150-450,600 - - action: Allow - counter: "" + - actions: + - kind: Allow devices: [] dst_ports: - from: 150 @@ -51,8 +52,8 @@ rules: # Deny UDP 192.0.2.99 -> 192.0.3.1 port 600 # 2 # add deny udp from 192.0.2.99 to 192.0.3.1 600 - - action: Deny - counter: "" + - actions: + - kind: Deny devices: [] dst_ports: - from: 600 @@ -73,8 +74,8 @@ rules: # Allow TCP SYN (setup flag) # 3 # add allow tcp from 192.0.2.2 to 192.0.3.1 600 tcpflags syn - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -221,8 +222,8 @@ rules: # Deny TCP RST # 4 # add deny tcp from any to any tcpflags rst - - action: Deny - counter: "" + - actions: + - kind: Deny devices: - "" dst_ports: @@ -307,8 +308,8 @@ rules: # Allow ICMP Echo # 5 # add allow icmp from 192.0.2.2 to 192.0.3.1 icmptypes 8 - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -330,8 +331,8 @@ rules: # Allow subnet 192.0.2.0/24 # 6 # add allow udp from 192.0.2.0/24 to 192.0.3.1 600 - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -352,8 +353,8 @@ rules: # Deny subnet 192.0.99.0/24 # 7 # add deny udp from 192.0.99.0/24 to any - - action: Deny - counter: "" + - actions: + - kind: Deny devices: - "" dst_ports: @@ -376,8 +377,8 @@ rules: # Allow TCPv6 # 8 # add allow tcp from 2001:db8::1 to 2001:db8::2 600 - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -398,8 +399,8 @@ rules: # Allow ICMPv6 Echo # 9 # add allow ipv6-icmp from 2001:db8::1 to 2001:db8::2 icmp6types 128,129 - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -422,8 +423,8 @@ rules: # Deny UDPv6 # 10 # add deny udp from 2001:db8::99 to 2001:db8::2 600 - - action: Deny - counter: "" + - actions: + - kind: Deny devices: - "" dst_ports: @@ -445,8 +446,8 @@ rules: # Rule pyramid (ordered from most specific to most general) # 11 # add allow udp from 192.0.2.0/31 to any 100-200 - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -467,8 +468,8 @@ rules: # 12 # add deny udp from 192.0.2.0/28 to any - - action: Deny - counter: "" + - actions: + - kind: Deny devices: - "" dst_ports: @@ -489,8 +490,8 @@ rules: # 13 # add allow udp from 192.0.2.0/24 to any - - action: Allow - counter: "" + - actions: + - kind: Allow devices: - "" dst_ports: @@ -511,8 +512,8 @@ rules: # 14 # add deny udp from 192.0.0.0/16 to any - - action: Deny - counter: "" + - actions: + - kind: Deny devices: - "" dst_ports: