From f6414ce18e82ed140e636ee847b184ae0d8f1683 Mon Sep 17 00:00:00 2001 From: gugu <404200721@qq.com> Date: Fri, 5 May 2023 15:06:53 +0800 Subject: [PATCH] replace acl/address_set function call with ovnClient (#2648) --- mocks/pkg/ovs/interface.go | 269 +++++++---- pkg/controller/init.go | 4 +- pkg/controller/network_policy.go | 282 +++++++----- pkg/controller/node.go | 13 +- pkg/controller/security_group.go | 43 +- pkg/controller/subnet.go | 41 +- pkg/ovs/interface.go | 18 +- pkg/ovs/ovn-nb-acl.go | 513 ++++++++++++++++----- pkg/ovs/ovn-nb-acl_test.go | 693 ++++++++++++++++++++-------- pkg/ovs/ovn-nb-address_set.go | 18 + pkg/ovs/ovn-nb-suite_test.go | 33 +- pkg/ovs/ovn-nb.go | 2 +- pkg/ovs/ovn-nb_test.go | 3 - pkg/ovs/ovn-nbctl-legacy.go | 766 ------------------------------- pkg/ovs/util.go | 12 + 15 files changed, 1341 insertions(+), 1369 deletions(-) diff --git a/mocks/pkg/ovs/interface.go b/mocks/pkg/ovs/interface.go index 6caa173f6ee..ceca5924979 100644 --- a/mocks/pkg/ovs/interface.go +++ b/mocks/pkg/ovs/interface.go @@ -11,6 +11,7 @@ import ( v1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1" ovs "github.com/kubeovn/kube-ovn/pkg/ovs" ovnnb "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb" + util "github.com/kubeovn/kube-ovn/pkg/util" ovsdb "github.com/ovn-org/libovsdb/ovsdb" v10 "k8s.io/api/networking/v1" ) @@ -771,20 +772,6 @@ func (mr *MockLogicalSwitchPortMockRecorder) SetLogicalSwitchPortsSecurityGroup( return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogicalSwitchPortsSecurityGroup", reflect.TypeOf((*MockLogicalSwitchPort)(nil).SetLogicalSwitchPortsSecurityGroup), sgName, op) } -// UpdateLogicalSwitchAcl mocks base method. -func (m *MockLogicalSwitchPort) UpdateLogicalSwitchAcl(lsName string, subnetAcls []v1.Acl) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateLogicalSwitchAcl", lsName, subnetAcls) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateLogicalSwitchAcl indicates an expected call of UpdateLogicalSwitchAcl. -func (mr *MockLogicalSwitchPortMockRecorder) UpdateLogicalSwitchAcl(lsName, subnetAcls interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateLogicalSwitchAcl", reflect.TypeOf((*MockLogicalSwitchPort)(nil).UpdateLogicalSwitchAcl), lsName, subnetAcls) -} - // MockLoadBalancer is a mock of LoadBalancer interface. type MockLoadBalancer struct { ctrl *gomock.Controller @@ -1099,60 +1086,46 @@ func (m *MockACL) EXPECT() *MockACLMockRecorder { return m.recorder } -// CreateEgressAcl mocks base method. -func (m *MockACL) CreateEgressAcl(pgName, asEgressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateEgressAcl", pgName, asEgressName, asExceptName, protocol, npp) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateEgressAcl indicates an expected call of CreateEgressAcl. -func (mr *MockACLMockRecorder) CreateEgressAcl(pgName, asEgressName, asExceptName, protocol, npp interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateEgressAcl", reflect.TypeOf((*MockACL)(nil).CreateEgressAcl), pgName, asEgressName, asExceptName, protocol, npp) -} - // CreateGatewayAcl mocks base method. -func (m *MockACL) CreateGatewayAcl(pgName, gateway string) error { +func (m *MockACL) CreateGatewayAcl(lsName, pgName, gateway string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateGatewayAcl", pgName, gateway) + ret := m.ctrl.Call(m, "CreateGatewayAcl", lsName, pgName, gateway) ret0, _ := ret[0].(error) return ret0 } // CreateGatewayAcl indicates an expected call of CreateGatewayAcl. -func (mr *MockACLMockRecorder) CreateGatewayAcl(pgName, gateway interface{}) *gomock.Call { +func (mr *MockACLMockRecorder) CreateGatewayAcl(lsName, pgName, gateway interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGatewayAcl", reflect.TypeOf((*MockACL)(nil).CreateGatewayAcl), pgName, gateway) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGatewayAcl", reflect.TypeOf((*MockACL)(nil).CreateGatewayAcl), lsName, pgName, gateway) } -// CreateIngressAcl mocks base method. -func (m *MockACL) CreateIngressAcl(pgName, asIngressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort) error { +// CreateNodeAcl mocks base method. +func (m *MockACL) CreateNodeAcl(pgName, nodeIpStr, joinIpStr string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateIngressAcl", pgName, asIngressName, asExceptName, protocol, npp) + ret := m.ctrl.Call(m, "CreateNodeAcl", pgName, nodeIpStr, joinIpStr) ret0, _ := ret[0].(error) return ret0 } -// CreateIngressAcl indicates an expected call of CreateIngressAcl. -func (mr *MockACLMockRecorder) CreateIngressAcl(pgName, asIngressName, asExceptName, protocol, npp interface{}) *gomock.Call { +// CreateNodeAcl indicates an expected call of CreateNodeAcl. +func (mr *MockACLMockRecorder) CreateNodeAcl(pgName, nodeIpStr, joinIpStr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateIngressAcl", reflect.TypeOf((*MockACL)(nil).CreateIngressAcl), pgName, asIngressName, asExceptName, protocol, npp) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNodeAcl", reflect.TypeOf((*MockACL)(nil).CreateNodeAcl), pgName, nodeIpStr, joinIpStr) } -// CreateNodeAcl mocks base method. -func (m *MockACL) CreateNodeAcl(pgName, nodeIp string) error { +// CreateSgBaseACL mocks base method. +func (m *MockACL) CreateSgBaseACL(sgName, direction string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateNodeAcl", pgName, nodeIp) + ret := m.ctrl.Call(m, "CreateSgBaseACL", sgName, direction) ret0, _ := ret[0].(error) return ret0 } -// CreateNodeAcl indicates an expected call of CreateNodeAcl. -func (mr *MockACLMockRecorder) CreateNodeAcl(pgName, nodeIp interface{}) *gomock.Call { +// CreateSgBaseACL indicates an expected call of CreateSgBaseACL. +func (mr *MockACLMockRecorder) CreateSgBaseACL(sgName, direction interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNodeAcl", reflect.TypeOf((*MockACL)(nil).CreateNodeAcl), pgName, nodeIp) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSgBaseACL", reflect.TypeOf((*MockACL)(nil).CreateSgBaseACL), sgName, direction) } // CreateSgDenyAllAcl mocks base method. @@ -1170,31 +1143,46 @@ func (mr *MockACLMockRecorder) CreateSgDenyAllAcl(sgName interface{}) *gomock.Ca } // DeleteAcls mocks base method. -func (m *MockACL) DeleteAcls(parentName, parentType, direction string) error { +func (m *MockACL) DeleteAcls(parentName, parentType, direction string, externalIDs map[string]string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAcls", parentName, parentType, direction) + ret := m.ctrl.Call(m, "DeleteAcls", parentName, parentType, direction, externalIDs) ret0, _ := ret[0].(error) return ret0 } // DeleteAcls indicates an expected call of DeleteAcls. -func (mr *MockACLMockRecorder) DeleteAcls(parentName, parentType, direction interface{}) *gomock.Call { +func (mr *MockACLMockRecorder) DeleteAcls(parentName, parentType, direction, externalIDs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAcls", reflect.TypeOf((*MockACL)(nil).DeleteAcls), parentName, parentType, direction) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAcls", reflect.TypeOf((*MockACL)(nil).DeleteAcls), parentName, parentType, direction, externalIDs) +} + +// DeleteAclsOps mocks base method. +func (m *MockACL) DeleteAclsOps(parentName, parentType, direction string, externalIDs map[string]string) ([]ovsdb.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteAclsOps", parentName, parentType, direction, externalIDs) + ret0, _ := ret[0].([]ovsdb.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteAclsOps indicates an expected call of DeleteAclsOps. +func (mr *MockACLMockRecorder) DeleteAclsOps(parentName, parentType, direction, externalIDs interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAclsOps", reflect.TypeOf((*MockACL)(nil).DeleteAclsOps), parentName, parentType, direction, externalIDs) } // SetAclLog mocks base method. -func (m *MockACL) SetAclLog(pgName string, logEnable, isIngress bool) error { +func (m *MockACL) SetAclLog(pgName, protocol string, logEnable, isIngress bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetAclLog", pgName, logEnable, isIngress) + ret := m.ctrl.Call(m, "SetAclLog", pgName, protocol, logEnable, isIngress) ret0, _ := ret[0].(error) return ret0 } // SetAclLog indicates an expected call of SetAclLog. -func (mr *MockACLMockRecorder) SetAclLog(pgName, logEnable, isIngress interface{}) *gomock.Call { +func (mr *MockACLMockRecorder) SetAclLog(pgName, protocol, logEnable, isIngress interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAclLog", reflect.TypeOf((*MockACL)(nil).SetAclLog), pgName, logEnable, isIngress) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAclLog", reflect.TypeOf((*MockACL)(nil).SetAclLog), pgName, protocol, logEnable, isIngress) } // SetLogicalSwitchPrivate mocks base method. @@ -1211,6 +1199,50 @@ func (mr *MockACLMockRecorder) SetLogicalSwitchPrivate(lsName, cidrBlock, allowS return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogicalSwitchPrivate", reflect.TypeOf((*MockACL)(nil).SetLogicalSwitchPrivate), lsName, cidrBlock, allowSubnets) } +// UpdateEgressAclOps mocks base method. +func (m *MockACL) UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateEgressAclOps", pgName, asEgressName, asExceptName, protocol, npp, logEnable, namedPortMap) + ret0, _ := ret[0].([]ovsdb.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateEgressAclOps indicates an expected call of UpdateEgressAclOps. +func (mr *MockACLMockRecorder) UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol, npp, logEnable, namedPortMap interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateEgressAclOps", reflect.TypeOf((*MockACL)(nil).UpdateEgressAclOps), pgName, asEgressName, asExceptName, protocol, npp, logEnable, namedPortMap) +} + +// UpdateIngressAclOps mocks base method. +func (m *MockACL) UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateIngressAclOps", pgName, asIngressName, asExceptName, protocol, npp, logEnable, namedPortMap) + ret0, _ := ret[0].([]ovsdb.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateIngressAclOps indicates an expected call of UpdateIngressAclOps. +func (mr *MockACLMockRecorder) UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol, npp, logEnable, namedPortMap interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateIngressAclOps", reflect.TypeOf((*MockACL)(nil).UpdateIngressAclOps), pgName, asIngressName, asExceptName, protocol, npp, logEnable, namedPortMap) +} + +// UpdateLogicalSwitchAcl mocks base method. +func (m *MockACL) UpdateLogicalSwitchAcl(lsName string, subnetAcls []v1.Acl) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateLogicalSwitchAcl", lsName, subnetAcls) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateLogicalSwitchAcl indicates an expected call of UpdateLogicalSwitchAcl. +func (mr *MockACLMockRecorder) UpdateLogicalSwitchAcl(lsName, subnetAcls interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateLogicalSwitchAcl", reflect.TypeOf((*MockACL)(nil).UpdateLogicalSwitchAcl), lsName, subnetAcls) +} + // UpdateSgAcl mocks base method. func (m *MockACL) UpdateSgAcl(sg *v1.SecurityGroup, direction string) error { m.ctrl.T.Helper() @@ -1891,32 +1923,18 @@ func (mr *MockOvnClientMockRecorder) CreateBareLogicalSwitchPort(lsName, lspName return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateBareLogicalSwitchPort", reflect.TypeOf((*MockOvnClient)(nil).CreateBareLogicalSwitchPort), lsName, lspName, ip, mac) } -// CreateEgressAcl mocks base method. -func (m *MockOvnClient) CreateEgressAcl(pgName, asEgressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateEgressAcl", pgName, asEgressName, asExceptName, protocol, npp) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateEgressAcl indicates an expected call of CreateEgressAcl. -func (mr *MockOvnClientMockRecorder) CreateEgressAcl(pgName, asEgressName, asExceptName, protocol, npp interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateEgressAcl", reflect.TypeOf((*MockOvnClient)(nil).CreateEgressAcl), pgName, asEgressName, asExceptName, protocol, npp) -} - // CreateGatewayAcl mocks base method. -func (m *MockOvnClient) CreateGatewayAcl(pgName, gateway string) error { +func (m *MockOvnClient) CreateGatewayAcl(lsName, pgName, gateway string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateGatewayAcl", pgName, gateway) + ret := m.ctrl.Call(m, "CreateGatewayAcl", lsName, pgName, gateway) ret0, _ := ret[0].(error) return ret0 } // CreateGatewayAcl indicates an expected call of CreateGatewayAcl. -func (mr *MockOvnClientMockRecorder) CreateGatewayAcl(pgName, gateway interface{}) *gomock.Call { +func (mr *MockOvnClientMockRecorder) CreateGatewayAcl(lsName, pgName, gateway interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGatewayAcl", reflect.TypeOf((*MockOvnClient)(nil).CreateGatewayAcl), pgName, gateway) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGatewayAcl", reflect.TypeOf((*MockOvnClient)(nil).CreateGatewayAcl), lsName, pgName, gateway) } // CreateGatewayLogicalSwitch mocks base method. @@ -1938,20 +1956,6 @@ func (mr *MockOvnClientMockRecorder) CreateGatewayLogicalSwitch(lsName, lrName, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateGatewayLogicalSwitch", reflect.TypeOf((*MockOvnClient)(nil).CreateGatewayLogicalSwitch), varargs...) } -// CreateIngressAcl mocks base method. -func (m *MockOvnClient) CreateIngressAcl(pgName, asIngressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateIngressAcl", pgName, asIngressName, asExceptName, protocol, npp) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateIngressAcl indicates an expected call of CreateIngressAcl. -func (mr *MockOvnClientMockRecorder) CreateIngressAcl(pgName, asIngressName, asExceptName, protocol, npp interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateIngressAcl", reflect.TypeOf((*MockOvnClient)(nil).CreateIngressAcl), pgName, asIngressName, asExceptName, protocol, npp) -} - // CreateLoadBalancer mocks base method. func (m *MockOvnClient) CreateLoadBalancer(lbName, protocol, selectFields string) error { m.ctrl.T.Helper() @@ -2056,17 +2060,17 @@ func (mr *MockOvnClientMockRecorder) CreateLogicalSwitchPort(lsName, lspName, ip } // CreateNodeAcl mocks base method. -func (m *MockOvnClient) CreateNodeAcl(pgName, nodeIp string) error { +func (m *MockOvnClient) CreateNodeAcl(pgName, nodeIpStr, joinIpStr string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateNodeAcl", pgName, nodeIp) + ret := m.ctrl.Call(m, "CreateNodeAcl", pgName, nodeIpStr, joinIpStr) ret0, _ := ret[0].(error) return ret0 } // CreateNodeAcl indicates an expected call of CreateNodeAcl. -func (mr *MockOvnClientMockRecorder) CreateNodeAcl(pgName, nodeIp interface{}) *gomock.Call { +func (mr *MockOvnClientMockRecorder) CreateNodeAcl(pgName, nodeIpStr, joinIpStr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNodeAcl", reflect.TypeOf((*MockOvnClient)(nil).CreateNodeAcl), pgName, nodeIp) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNodeAcl", reflect.TypeOf((*MockOvnClient)(nil).CreateNodeAcl), pgName, nodeIpStr, joinIpStr) } // CreatePeerRouterPort mocks base method. @@ -2097,6 +2101,20 @@ func (mr *MockOvnClientMockRecorder) CreatePortGroup(pgName, externalIDs interfa return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatePortGroup", reflect.TypeOf((*MockOvnClient)(nil).CreatePortGroup), pgName, externalIDs) } +// CreateSgBaseACL mocks base method. +func (m *MockOvnClient) CreateSgBaseACL(sgName, direction string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateSgBaseACL", sgName, direction) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateSgBaseACL indicates an expected call of CreateSgBaseACL. +func (mr *MockOvnClientMockRecorder) CreateSgBaseACL(sgName, direction interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSgBaseACL", reflect.TypeOf((*MockOvnClient)(nil).CreateSgBaseACL), sgName, direction) +} + // CreateSgDenyAllAcl mocks base method. func (m *MockOvnClient) CreateSgDenyAllAcl(sgName string) error { m.ctrl.T.Helper() @@ -2131,17 +2149,32 @@ func (mr *MockOvnClientMockRecorder) CreateVirtualLogicalSwitchPorts(lsName inte } // DeleteAcls mocks base method. -func (m *MockOvnClient) DeleteAcls(parentName, parentType, direction string) error { +func (m *MockOvnClient) DeleteAcls(parentName, parentType, direction string, externalIDs map[string]string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteAcls", parentName, parentType, direction) + ret := m.ctrl.Call(m, "DeleteAcls", parentName, parentType, direction, externalIDs) ret0, _ := ret[0].(error) return ret0 } // DeleteAcls indicates an expected call of DeleteAcls. -func (mr *MockOvnClientMockRecorder) DeleteAcls(parentName, parentType, direction interface{}) *gomock.Call { +func (mr *MockOvnClientMockRecorder) DeleteAcls(parentName, parentType, direction, externalIDs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAcls", reflect.TypeOf((*MockOvnClient)(nil).DeleteAcls), parentName, parentType, direction) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAcls", reflect.TypeOf((*MockOvnClient)(nil).DeleteAcls), parentName, parentType, direction, externalIDs) +} + +// DeleteAclsOps mocks base method. +func (m *MockOvnClient) DeleteAclsOps(parentName, parentType, direction string, externalIDs map[string]string) ([]ovsdb.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteAclsOps", parentName, parentType, direction, externalIDs) + ret0, _ := ret[0].([]ovsdb.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteAclsOps indicates an expected call of DeleteAclsOps. +func (mr *MockOvnClientMockRecorder) DeleteAclsOps(parentName, parentType, direction, externalIDs interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAclsOps", reflect.TypeOf((*MockOvnClient)(nil).DeleteAclsOps), parentName, parentType, direction, externalIDs) } // DeleteAddressSet mocks base method. @@ -3015,17 +3048,17 @@ func (mr *MockOvnClientMockRecorder) RemoveLogicalPatchPort(lspName, lrpName int } // SetAclLog mocks base method. -func (m *MockOvnClient) SetAclLog(pgName string, logEnable, isIngress bool) error { +func (m *MockOvnClient) SetAclLog(pgName, protocol string, logEnable, isIngress bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetAclLog", pgName, logEnable, isIngress) + ret := m.ctrl.Call(m, "SetAclLog", pgName, protocol, logEnable, isIngress) ret0, _ := ret[0].(error) return ret0 } // SetAclLog indicates an expected call of SetAclLog. -func (mr *MockOvnClientMockRecorder) SetAclLog(pgName, logEnable, isIngress interface{}) *gomock.Call { +func (mr *MockOvnClientMockRecorder) SetAclLog(pgName, protocol, logEnable, isIngress interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAclLog", reflect.TypeOf((*MockOvnClient)(nil).SetAclLog), pgName, logEnable, isIngress) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAclLog", reflect.TypeOf((*MockOvnClient)(nil).SetAclLog), pgName, protocol, logEnable, isIngress) } // SetAzName mocks base method. @@ -3201,6 +3234,20 @@ func (mr *MockOvnClientMockRecorder) SetUseCtInvMatch() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUseCtInvMatch", reflect.TypeOf((*MockOvnClient)(nil).SetUseCtInvMatch)) } +// Transact mocks base method. +func (m *MockOvnClient) Transact(method string, operations []ovsdb.Operation) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Transact", method, operations) + ret0, _ := ret[0].(error) + return ret0 +} + +// Transact indicates an expected call of Transact. +func (mr *MockOvnClientMockRecorder) Transact(method, operations interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transact", reflect.TypeOf((*MockOvnClient)(nil).Transact), method, operations) +} + // UpdateDHCPOptions mocks base method. func (m *MockOvnClient) UpdateDHCPOptions(subnet *v1.Subnet) (*ovs.DHCPOptionsUUIDs, error) { m.ctrl.T.Helper() @@ -3230,6 +3277,36 @@ func (mr *MockOvnClientMockRecorder) UpdateDnatAndSnat(lrName, externalIP, logic return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDnatAndSnat", reflect.TypeOf((*MockOvnClient)(nil).UpdateDnatAndSnat), lrName, externalIP, logicalIP, lspName, externalMac, gatewayType) } +// UpdateEgressAclOps mocks base method. +func (m *MockOvnClient) UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateEgressAclOps", pgName, asEgressName, asExceptName, protocol, npp, logEnable, namedPortMap) + ret0, _ := ret[0].([]ovsdb.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateEgressAclOps indicates an expected call of UpdateEgressAclOps. +func (mr *MockOvnClientMockRecorder) UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol, npp, logEnable, namedPortMap interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateEgressAclOps", reflect.TypeOf((*MockOvnClient)(nil).UpdateEgressAclOps), pgName, asEgressName, asExceptName, protocol, npp, logEnable, namedPortMap) +} + +// UpdateIngressAclOps mocks base method. +func (m *MockOvnClient) UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol string, npp []v10.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateIngressAclOps", pgName, asIngressName, asExceptName, protocol, npp, logEnable, namedPortMap) + ret0, _ := ret[0].([]ovsdb.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateIngressAclOps indicates an expected call of UpdateIngressAclOps. +func (mr *MockOvnClientMockRecorder) UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol, npp, logEnable, namedPortMap interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateIngressAclOps", reflect.TypeOf((*MockOvnClient)(nil).UpdateIngressAclOps), pgName, asIngressName, asExceptName, protocol, npp, logEnable, namedPortMap) +} + // UpdateLogicalRouterPortRA mocks base method. func (m *MockOvnClient) UpdateLogicalRouterPortRA(lrpName, ipv6RAConfigsStr string, enableIPv6RA bool) error { m.ctrl.T.Helper() diff --git a/pkg/controller/init.go b/pkg/controller/init.go index 48f864470de..4ad3e24ec7a 100644 --- a/pkg/controller/init.go +++ b/pkg/controller/init.go @@ -773,8 +773,8 @@ func (c *Controller) migrateNodeRoute(af int, node, ip, nexthop string) error { return err } - if err := c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete obsolete address set %s for node %s: %v", asName, node, err) + if err := c.ovnClient.DeleteAddressSet(asName); err != nil { + klog.Errorf("delete obsolete address set %s for node %s: %v", asName, node, err) return err } diff --git a/pkg/controller/network_policy.go b/pkg/controller/network_policy.go index e30ecceecb7..5e506d5ef17 100644 --- a/pkg/controller/network_policy.go +++ b/pkg/controller/network_policy.go @@ -16,6 +16,8 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" + "github.com/ovn-org/libovsdb/ovsdb" + kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1" "github.com/kubeovn/kube-ovn/pkg/ovs" "github.com/kubeovn/kube-ovn/pkg/util" @@ -228,25 +230,31 @@ func (c *Controller) handleUpdateNp(key string) error { svcAsName = svcAsNameIPv6 svcIPs = svcIpv6s } - if err = c.ovnLegacyClient.CreateNpAddressSet(svcAsName, np.Namespace, npName, "service"); err != nil { - klog.Errorf("failed to create address_set %s, %v", svcAsNameIPv4, err) + + if err = c.ovnClient.CreateAddressSet(svcAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "service"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", svcAsName, key, err) return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(svcIPs, svcAsName); err != nil { - klog.Errorf("failed to set netpol svc, %v", err) + + if err = c.ovnClient.AddressSetUpdateAddress(svcAsName, svcIPs...); err != nil { + klog.Errorf("set service ips to address set %s: %v", svcAsName, err) return err } } - var ingressAclCmd []string - exist, err := c.ovnClient.PortGroupExists(pgName) + var ingressAclOps []ovsdb.Operation + + clearIngressAclOps, err := c.ovnClient.DeleteAclsOps(pgName, portGroupKey, "to-lport", nil) if err != nil { - klog.Errorf("failed to query np %s port group, %v", key, err) + klog.Errorf("generate operations that clear np %s ingress acls: %v", key, err) return err } - if exist { - ingressAclCmd = []string{"--type=port-group", "acl-del", pgName, "to-lport"} - } + + // put clear acl and update acl in a single transaction to imitate update acl + ingressAclOps = append(ingressAclOps, clearIngressAclOps...) + if hasIngressRule(np) { for _, cidrBlock := range strings.Split(subnet.Spec.CIDRBlock, ",") { protocol := util.CheckProtocol(cidrBlock) @@ -275,66 +283,92 @@ func (c *Controller) handleUpdateNp(key string) error { } } klog.Infof("UpdateNp Ingress, allows is %v, excepts is %v, log %v", allows, excepts, logEnable) - if err = c.ovnLegacyClient.CreateNpAddressSet(ingressAllowAsName, np.Namespace, npName, "ingress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", ingressAllowAsName, err) + + if err = c.ovnClient.CreateAddressSet(ingressAllowAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "ingress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", ingressAllowAsName, key, err) return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(allows, ingressAllowAsName); err != nil { - klog.Errorf("failed to set ingress allow address_set, %v", err) + + if err = c.ovnClient.AddressSetUpdateAddress(ingressAllowAsName, allows...); err != nil { + klog.Errorf("set ingress allow ips to address set %s: %v", ingressAllowAsName, err) return err } - if err = c.ovnLegacyClient.CreateNpAddressSet(ingressExceptAsName, np.Namespace, npName, "ingress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", ingressExceptAsName, err) + if err = c.ovnClient.CreateAddressSet(ingressExceptAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "ingress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", ingressExceptAsName, key, err) return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(excepts, ingressExceptAsName); err != nil { - klog.Errorf("failed to set ingress except address_set, %v", err) + + if err = c.ovnClient.AddressSetUpdateAddress(ingressExceptAsName, excepts...); err != nil { + klog.Errorf("set ingress except ips to address set %s: %v", ingressExceptAsName, err) return err } + npp := []netv1.NetworkPolicyPort{} if len(allows) != 0 || len(excepts) != 0 { - ingressAclCmd = c.ovnLegacyClient.CombineIngressACLCmd(pgName, ingressAllowAsName, ingressExceptAsName, protocol, npr.Ports, logEnable, ingressAclCmd, idx, namedPortMap) - } else { - ingressAclCmd = c.ovnLegacyClient.CombineIngressACLCmd(pgName, ingressAllowAsName, ingressExceptAsName, protocol, []netv1.NetworkPolicyPort{}, logEnable, ingressAclCmd, idx, namedPortMap) + npp = npr.Ports + } + + ops, err := c.ovnClient.UpdateIngressAclOps(pgName, ingressAllowAsName, ingressExceptAsName, protocol, npp, logEnable, namedPortMap) + if err != nil { + klog.Errorf("generate operations that add ingress acls to np %s: %v", key, err) + return err } + + ingressAclOps = append(ingressAclOps, ops...) } if len(np.Spec.Ingress) == 0 { ingressAllowAsName := fmt.Sprintf("%s.%s.all", ingressAllowAsNamePrefix, protocol) ingressExceptAsName := fmt.Sprintf("%s.%s.all", ingressExceptAsNamePrefix, protocol) - if err = c.ovnLegacyClient.CreateNpAddressSet(ingressAllowAsName, np.Namespace, npName, "ingress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", ingressAllowAsName, err) + + if err = c.ovnClient.CreateAddressSet(ingressAllowAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "ingress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", ingressAllowAsName, key, err) + return err + } + + if err = c.ovnClient.CreateAddressSet(ingressExceptAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "ingress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", ingressExceptAsName, key, err) return err } - if err = c.ovnLegacyClient.CreateNpAddressSet(ingressExceptAsName, np.Namespace, npName, "ingress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", ingressExceptAsName, err) + ops, err := c.ovnClient.UpdateIngressAclOps(pgName, ingressAllowAsName, ingressExceptAsName, protocol, []netv1.NetworkPolicyPort{}, logEnable, namedPortMap) + if err != nil { + klog.Errorf("generate operations that add ingress acls to np %s: %v", key, err) return err } - ingressPorts := []netv1.NetworkPolicyPort{} - ingressAclCmd = c.ovnLegacyClient.CombineIngressACLCmd(pgName, ingressAllowAsName, ingressExceptAsName, protocol, ingressPorts, logEnable, ingressAclCmd, 0, namedPortMap) + + ingressAclOps = append(ingressAclOps, ops...) } - klog.Infof("create ingress acl cmd is: %v", ingressAclCmd) - if err = c.ovnLegacyClient.CreateACL(ingressAclCmd); err != nil { - klog.Errorf("failed to create ingress acls for np %s, %v", key, err) - return err + if err = c.ovnClient.Transact("add-ingress-acls", ingressAclOps); err != nil { + return fmt.Errorf("add ingress acls to %s: %v", pgName, err) } - if err = c.ovnLegacyClient.SetAclLog(pgName, logEnable, true); err != nil { + if err = c.ovnClient.SetAclLog(pgName, protocol, logEnable, true); err != nil { // just log and do not return err here klog.Errorf("failed to set ingress acl log for np %s, %v", key, err) } } - var asNames []string - if asNames, err = c.ovnLegacyClient.ListNpAddressSet(np.Namespace, npName, "ingress"); err != nil { - klog.Errorf("failed to list address_set, %v", err) + ass, err := c.ovnClient.ListAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "ingress"), + }) + if err != nil { + klog.Errorf("list np %s address sets: %v", key, err) return err } + // The format of asName is like "test.network.policy.test.ingress.except.0" or "test.network.policy.test.ingress.allow.0" for ingress - for _, asName := range asNames { - values := strings.Split(asName, ".") + for _, as := range ass { + values := strings.Split(as.Name, ".") if len(values) <= 1 { continue } @@ -344,39 +378,37 @@ func (c *Controller) handleUpdateNp(key string) error { } idx, _ := strconv.Atoi(idxStr) if idx >= len(np.Spec.Ingress) { - if err = c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { + if err = c.ovnClient.DeleteAddressSet(as.Name); err != nil { klog.Errorf("failed to delete np %s address set, %v", key, err) return err } } } } else { - if err = c.ovnLegacyClient.DeleteACL(pgName, "to-lport"); err != nil { - klog.Errorf("failed to delete np %s ingress acls, %v", key, err) + if err = c.ovnClient.DeleteAcls(pgName, portGroupKey, "to-lport", nil); err != nil { + klog.Errorf("delete np %s ingress acls: %v", key, err) return err } - asNames, err := c.ovnLegacyClient.ListNpAddressSet(np.Namespace, npName, "ingress") - if err != nil { - klog.Errorf("failed to list address_set, %v", err) + if err := c.ovnClient.DeleteAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "ingress"), + }); err != nil { + klog.Errorf("delete np %s ingress address set: %v", key, err) return err } - for _, asName := range asNames { - if err = c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete np %s address set, %v", key, err) - return err - } - } } - var egressAclCmd []string - if exist, err = c.ovnClient.PortGroupExists(pgName); err != nil { - klog.Errorf("failed to query np %s port group, %v", key, err) + var egressAclOps []ovsdb.Operation + + clearEgressAclOps, err := c.ovnClient.DeleteAclsOps(pgName, portGroupKey, "from-lport", nil) + if err != nil { + klog.Errorf("generate operations that clear np %s egress acls: %v", key, err) return err } - if exist { - egressAclCmd = []string{"--type=port-group", "acl-del", pgName, "from-lport"} - } + + // put clear and add acl in a single transaction to imitate acl update + egressAclOps = append(egressAclOps, clearEgressAclOps...) + if hasEgressRule(np) { for _, cidrBlock := range strings.Split(subnet.Spec.CIDRBlock, ",") { protocol := util.CheckProtocol(cidrBlock) @@ -405,64 +437,89 @@ func (c *Controller) handleUpdateNp(key string) error { } } klog.Infof("UpdateNp Egress, allows is %v, excepts is %v, log %v", allows, excepts, logEnable) - if err = c.ovnLegacyClient.CreateNpAddressSet(egressAllowAsName, np.Namespace, npName, "egress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", egressAllowAsName, err) + + if err = c.ovnClient.CreateAddressSet(egressAllowAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "egress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", egressAllowAsName, key, err) return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(allows, egressAllowAsName); err != nil { - klog.Errorf("failed to set egress allow address_set, %v", err) + + if err = c.ovnClient.AddressSetUpdateAddress(egressAllowAsName, allows...); err != nil { + klog.Errorf("set egress allow ips to address set %s: %v", egressAllowAsName, err) return err } - if err = c.ovnLegacyClient.CreateNpAddressSet(egressExceptAsName, np.Namespace, npName, "egress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", egressExceptAsName, err) + if err = c.ovnClient.CreateAddressSet(egressExceptAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "egress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", egressExceptAsName, key, err) return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(excepts, egressExceptAsName); err != nil { - klog.Errorf("failed to set egress except address_set, %v", err) + + if err = c.ovnClient.AddressSetUpdateAddress(egressExceptAsName, excepts...); err != nil { + klog.Errorf("set egress except ips to address set %s: %v", egressExceptAsName, err) return err } if len(allows) != 0 || len(excepts) != 0 { - egressAclCmd = c.ovnLegacyClient.CombineEgressACLCmd(pgName, egressAllowAsName, egressExceptAsName, protocol, npr.Ports, logEnable, egressAclCmd, idx, namedPortMap) + ops, err := c.ovnClient.UpdateEgressAclOps(pgName, egressAllowAsName, egressExceptAsName, protocol, npr.Ports, logEnable, namedPortMap) + if err != nil { + klog.Errorf("generate operations that add egress acls to np %s: %v", key, err) + return err + } + + egressAclOps = append(egressAclOps, ops...) } } if len(np.Spec.Egress) == 0 { egressAllowAsName := fmt.Sprintf("%s.%s.all", egressAllowAsNamePrefix, protocol) egressExceptAsName := fmt.Sprintf("%s.%s.all", egressExceptAsNamePrefix, protocol) - if err = c.ovnLegacyClient.CreateNpAddressSet(egressAllowAsName, np.Namespace, npName, "egress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", egressAllowAsName, err) + + if err = c.ovnClient.CreateAddressSet(egressAllowAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "egress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", egressAllowAsName, key, err) + return err + } + + if err = c.ovnClient.CreateAddressSet(egressExceptAsName, map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "egress"), + }); err != nil { + klog.Errorf("create address set %s for np %s: %v", egressExceptAsName, key, err) return err } - if err = c.ovnLegacyClient.CreateNpAddressSet(egressExceptAsName, np.Namespace, npName, "egress"); err != nil { - klog.Errorf("failed to create address_set %s, %v", egressExceptAsName, err) + ops, err := c.ovnClient.UpdateEgressAclOps(pgName, egressAllowAsName, egressExceptAsName, protocol, []netv1.NetworkPolicyPort{}, logEnable, namedPortMap) + if err != nil { + klog.Errorf("generate operations that add egress acls to np %s: %v", key, err) return err } - egressPorts := []netv1.NetworkPolicyPort{} - egressAclCmd = c.ovnLegacyClient.CombineEgressACLCmd(pgName, egressAllowAsName, egressExceptAsName, protocol, egressPorts, logEnable, egressAclCmd, 0, namedPortMap) + + egressAclOps = append(egressAclOps, ops...) } - klog.Infof("create egress acl cmd is: %v", egressAclCmd) - if err = c.ovnLegacyClient.CreateACL(egressAclCmd); err != nil { - klog.Errorf("failed to create egress acls for np %s, %v", key, err) - return err + if err = c.ovnClient.Transact("add-egress-acls", egressAclOps); err != nil { + return fmt.Errorf("add egress acls to %s: %v", pgName, err) } - if err = c.ovnLegacyClient.SetAclLog(pgName, logEnable, false); err != nil { + if err = c.ovnClient.SetAclLog(pgName, protocol, logEnable, false); err != nil { // just log and do not return err here klog.Errorf("failed to set egress acl log for np %s, %v", key, err) } } - var asNames []string - if asNames, err = c.ovnLegacyClient.ListNpAddressSet(np.Namespace, npName, "egress"); err != nil { - klog.Errorf("failed to list address_set, %v", err) + ass, err := c.ovnClient.ListAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "egress"), + }) + if err != nil { + klog.Errorf("list np %s address sets: %v", key, err) return err } + // The format of asName is like "test.network.policy.test.egress.except.0" or "test.network.policy.test.egress.allow.0" for egress - for _, asName := range asNames { - values := strings.Split(asName, ".") + for _, as := range ass { + values := strings.Split(as.Name, ".") if len(values) <= 1 { continue } @@ -473,33 +530,28 @@ func (c *Controller) handleUpdateNp(key string) error { idx, _ := strconv.Atoi(idxStr) if idx >= len(np.Spec.Egress) { - if err = c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete np %s address set, %v", key, err) + if err = c.ovnClient.DeleteAddressSet(as.Name); err != nil { + klog.Errorf("delete np %s address set: %v", key, err) return err } } } } else { - if err = c.ovnLegacyClient.DeleteACL(pgName, "from-lport"); err != nil { - klog.Errorf("failed to delete np %s egress acls, %v", key, err) + if err = c.ovnClient.DeleteAcls(pgName, portGroupKey, "from-lport", nil); err != nil { + klog.Errorf("delete np %s egress acls: %v", key, err) return err } - asNames, err := c.ovnLegacyClient.ListNpAddressSet(np.Namespace, npName, "egress") - if err != nil { - klog.Errorf("failed to list egress address_set, %v", err) + if err := c.ovnClient.DeleteAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, np.Name, "egress"), + }); err != nil { + klog.Errorf("delete np %s egress address set: %v", key, err) return err } - for _, asName := range asNames { - if err = c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete np %s address set, %v", key, err) - return err - } - } } - if err = c.ovnLegacyClient.CreateGatewayACL("", pgName, subnet.Spec.Gateway, subnet.Spec.CIDRBlock); err != nil { - klog.Errorf("failed to create gateway acl, %v", err) + if err = c.ovnClient.CreateGatewayAcl("", pgName, subnet.Spec.Gateway); err != nil { + klog.Errorf("create gateway acl: %v", err) return err } return nil @@ -527,41 +579,27 @@ func (c *Controller) handleDeleteNp(key string) error { klog.Errorf("delete np %s port group: %v", key, err) } - svcAsNames, err := c.ovnLegacyClient.ListNpAddressSet(namespace, npName, "service") - if err != nil { - klog.Errorf("failed to list svc address_set, %v", err) + if err := c.ovnClient.DeleteAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "service"), + }); err != nil { + klog.Errorf("delete np %s service address set: %v", key, err) return err } - for _, asName := range svcAsNames { - if err := c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete np %s address set, %v", key, err) - return err - } - } - ingressAsNames, err := c.ovnLegacyClient.ListNpAddressSet(namespace, npName, "ingress") - if err != nil { - klog.Errorf("failed to list address_set, %v", err) + if err := c.ovnClient.DeleteAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "ingress"), + }); err != nil { + klog.Errorf("delete np %s ingress address set: %v", key, err) return err } - for _, asName := range ingressAsNames { - if err := c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete np %s address set, %v", key, err) - return err - } - } - egressAsNames, err := c.ovnLegacyClient.ListNpAddressSet(namespace, npName, "egress") - if err != nil { - klog.Errorf("failed to list address_set, %v", err) + if err := c.ovnClient.DeleteAddressSets(map[string]string{ + networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "egress"), + }); err != nil { + klog.Errorf("delete np %s egress address set: %v", key, err) return err } - for _, asName := range egressAsNames { - if err := c.ovnLegacyClient.DeleteAddressSet(asName); err != nil { - klog.Errorf("failed to delete np %s address set, %v", key, err) - return err - } - } + return nil } diff --git a/pkg/controller/node.go b/pkg/controller/node.go index 5e419e7f6f0..81b17ce840a 100644 --- a/pkg/controller/node.go +++ b/pkg/controller/node.go @@ -498,11 +498,11 @@ func (c *Controller) handleDeleteNode(key string) error { return err } } - if err := c.ovnLegacyClient.DeleteAddressSet(nodeUnderlayAddressSetName(key, 4)); err != nil { + if err := c.ovnClient.DeleteAddressSet(nodeUnderlayAddressSetName(key, 4)); err != nil { klog.Errorf("failed to delete address set for node %s: %v", key, err) return err } - if err := c.ovnLegacyClient.DeleteAddressSet(nodeUnderlayAddressSetName(key, 6)); err != nil { + if err := c.ovnClient.DeleteAddressSet(nodeUnderlayAddressSetName(key, 6)); err != nil { klog.Errorf("failed to delete address set for node %s: %v", key, err) return err } @@ -989,12 +989,13 @@ func (c *Controller) checkAndUpdateNodePortGroup() error { } if networkPolicyExists { - if err := c.ovnLegacyClient.CreateACLForNodePg(pgName, nodeIP, joinIP); err != nil { - klog.Errorf("failed to create node acl for node pg %v, %v", pgName, err) + if err := c.ovnClient.CreateNodeAcl(pgName, nodeIP, joinIP); err != nil { + klog.Errorf("create node acl for node pg %s: %v", pgName, err) } } else { - if err := c.ovnLegacyClient.DeleteAclForNodePg(pgName); err != nil { - klog.Errorf("failed to delete node acl for node pg %v, %v", pgName, err) + // clear all acl + if err = c.ovnClient.DeleteAcls(pgName, portGroupKey, "", nil); err != nil { + klog.Errorf("delete node acl for node pg %s: %v", pgName, err) } } } diff --git a/pkg/controller/security_group.go b/pkg/controller/security_group.go index b189a3dda22..f6be78b9b5e 100644 --- a/pkg/controller/security_group.go +++ b/pkg/controller/security_group.go @@ -176,7 +176,8 @@ func (c *Controller) initDenyAllSecurityGroup() error { return err } - if err := c.ovnLegacyClient.CreateSgDenyAllACL(); err != nil { + if err := c.ovnClient.CreateSgDenyAllAcl(util.DenyAllSecurityGroup); err != nil { + klog.Errorf("create deny all acl for sg %s: %v", util.DenyAllSecurityGroup, err) return err } @@ -259,8 +260,20 @@ func (c *Controller) handleAddOrUpdateSg(key string) error { return err } - if err = c.ovnLegacyClient.CreateSgAssociatedAddressSet(sg.Name); err != nil { - return fmt.Errorf("failed to create sg associated address_set %s, %v", key, err.Error()) + v4AsName := ovs.GetSgV4AssociatedName(sg.Name) + v6AsName := ovs.GetSgV6AssociatedName(sg.Name) + externalIDs := map[string]string{ + sgKey: sg.Name, + } + + if err = c.ovnClient.CreateAddressSet(v4AsName, externalIDs); err != nil { + klog.Errorf("create address set %s for sg %s: %v", v4AsName, key, err) + return err + } + + if err = c.ovnClient.CreateAddressSet(v6AsName, externalIDs); err != nil { + klog.Errorf("create address set %s for sg %s: %v", v6AsName, key, err) + return err } ingressNeedUpdate := false @@ -287,12 +300,13 @@ func (c *Controller) handleAddOrUpdateSg(key string) error { // update sg rule if ingressNeedUpdate { - if err = c.ovnLegacyClient.UpdateSgACL(sg, ovs.SgAclIngressDirection); err != nil { + if err = c.ovnClient.UpdateSgAcl(sg, ovnnb.ACLDirectionToLport); err != nil { sg.Status.IngressLastSyncSuccess = false c.patchSgStatus(sg) return err } - if err := c.ovnLegacyClient.CreateSgBaseIngressACL(sg.Name); err != nil { + + if err := c.ovnClient.CreateSgBaseACL(sg.Name, ovnnb.ACLDirectionToLport); err != nil { return err } sg.Status.IngressMd5 = newIngressMd5 @@ -300,14 +314,16 @@ func (c *Controller) handleAddOrUpdateSg(key string) error { c.patchSgStatus(sg) } if egressNeedUpdate { - if err = c.ovnLegacyClient.UpdateSgACL(sg, ovs.SgAclEgressDirection); err != nil { - sg.Status.EgressLastSyncSuccess = false + if err = c.ovnClient.UpdateSgAcl(sg, ovnnb.ACLDirectionFromLport); err != nil { + sg.Status.IngressLastSyncSuccess = false c.patchSgStatus(sg) return err } - if err := c.ovnLegacyClient.CreateSgBaseEgressACL(sg.Name); err != nil { + + if err := c.ovnClient.CreateSgBaseACL(sg.Name, ovnnb.ACLDirectionFromLport); err != nil { return err } + sg.Status.EgressMd5 = newEgressMd5 sg.Status.EgressLastSyncSuccess = true c.patchSgStatus(sg) @@ -433,15 +449,18 @@ func (c *Controller) syncSgLogicalPort(key string) error { return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(v4s, ovs.GetSgV4AssociatedName(key)); err != nil { - klog.Errorf("failed to set address_set, %v", err) + v4AsName := ovs.GetSgV4AssociatedName(key) + if err := c.ovnClient.AddressSetUpdateAddress(v4AsName, v4s...); err != nil { + klog.Errorf("set ips to address set %s: %v", v4AsName, err) return err } - if err = c.ovnLegacyClient.SetAddressesToAddressSet(v6s, ovs.GetSgV6AssociatedName(key)); err != nil { - klog.Errorf("failed to set address_set, %v", err) + v6AsName := ovs.GetSgV6AssociatedName(key) + if err := c.ovnClient.AddressSetUpdateAddress(v6AsName, v6s...); err != nil { + klog.Errorf("set ips to address set %s: %v", v6AsName, err) return err } + c.addOrUpdateSgQueue.Add(util.DenyAllSecurityGroup) return nil } diff --git a/pkg/controller/subnet.go b/pkg/controller/subnet.go index 57481b0ef10..1358abfee70 100644 --- a/pkg/controller/subnet.go +++ b/pkg/controller/subnet.go @@ -749,25 +749,28 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error { } if subnet.Spec.Private { - if err := c.ovnLegacyClient.SetPrivateLogicalSwitch(subnet.Name, subnet.Spec.CIDRBlock, subnet.Spec.AllowSubnets); err != nil { + if err := c.ovnClient.SetLogicalSwitchPrivate(subnet.Name, subnet.Spec.CIDRBlock, subnet.Spec.AllowSubnets); err != nil { c.patchSubnetStatus(subnet, "SetPrivateLogicalSwitchFailed", err.Error()) return err } + c.patchSubnetStatus(subnet, "SetPrivateLogicalSwitchSuccess", "") } else { - if err := c.ovnLegacyClient.ResetLogicalSwitchAcl(subnet.Name); err != nil { + // clear acl when direction is "" + if err = c.ovnClient.DeleteAcls(subnet.Name, logicalSwitchKey, "", nil); err != nil { c.patchSubnetStatus(subnet, "ResetLogicalSwitchAclFailed", err.Error()) return err } + c.patchSubnetStatus(subnet, "ResetLogicalSwitchAclSuccess", "") } - if err := c.ovnLegacyClient.CreateGatewayACL(subnet.Name, "", subnet.Spec.Gateway, subnet.Spec.CIDRBlock); err != nil { + if err := c.ovnClient.CreateGatewayAcl(subnet.Name, "", subnet.Spec.Gateway); err != nil { klog.Errorf("create gateway acl %s failed, %v", subnet.Name, err) return err } - if err := c.ovnLegacyClient.UpdateSubnetACL(subnet.Name, subnet.Spec.Acls); err != nil { + if err := c.ovnClient.UpdateLogicalSwitchAcl(subnet.Name, subnet.Spec.Acls); err != nil { c.patchSubnetStatus(subnet, "SetLogicalSwitchAclsFailed", err.Error()) return err } @@ -820,8 +823,9 @@ func (c *Controller) handleDeleteLogicalSwitch(key string) (err error) { return nil } - if err = c.ovnLegacyClient.CleanLogicalSwitchAcl(key); err != nil { - klog.Errorf("failed to delete acl of logical switch %s %v", key, err) + // clear acl when direction is "" + if err = c.ovnClient.DeleteAcls(key, logicalSwitchKey, "", nil); err != nil { + klog.Errorf("clear logical switch %s acls: %v", key, err) return err } @@ -2389,26 +2393,27 @@ func (c *Controller) addPolicyRouteForU2OInterconn(subnet *kubeovnv1.Subnet) err u2oExcludeIp4Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip4"), "-", ".", -1) u2oExcludeIp6Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip6"), "-", ".", -1) - if err := c.ovnLegacyClient.CreateAddressSet(u2oExcludeIp4Ag); err != nil { - klog.Errorf("failed to create address set %s %v", u2oExcludeIp4Ag, err) + + if err := c.ovnClient.CreateAddressSet(u2oExcludeIp4Ag, externalIDs); err != nil { + klog.Errorf("create address set %s: %v", u2oExcludeIp4Ag, err) return err } - if err := c.ovnLegacyClient.CreateAddressSet(u2oExcludeIp6Ag); err != nil { - klog.Errorf("failed to create address set %s %v", u2oExcludeIp6Ag, err) + if err := c.ovnClient.CreateAddressSet(u2oExcludeIp6Ag, externalIDs); err != nil { + klog.Errorf("create address set %s: %v", u2oExcludeIp6Ag, err) return err } if len(nodesIPv4) > 0 { - if err := c.ovnLegacyClient.SetAddressesToAddressSet(nodesIPv4, u2oExcludeIp4Ag); err != nil { - klog.Errorf("failed to set v4 address set %s with address %v err %v", u2oExcludeIp4Ag, nodesIPv4, err) + if err := c.ovnClient.AddressSetUpdateAddress(u2oExcludeIp4Ag, nodesIPv4...); err != nil { + klog.Errorf("set v4 address set %s with address %v: %v", u2oExcludeIp4Ag, nodesIPv4, err) return err } } if len(nodesIPv6) > 0 { - if err := c.ovnLegacyClient.SetAddressesToAddressSet(nodesIPv6, u2oExcludeIp6Ag); err != nil { - klog.Errorf("failed to set v6 address set %s with address %v err %v", u2oExcludeIp6Ag, nodesIPv6, err) + if err := c.ovnClient.AddressSetUpdateAddress(u2oExcludeIp6Ag, nodesIPv6...); err != nil { + klog.Errorf("set v6 address set %s with address %v: %v", u2oExcludeIp6Ag, nodesIPv6, err) return err } } @@ -2491,13 +2496,13 @@ func (c *Controller) deletePolicyRouteForU2OInterconn(subnet *kubeovnv1.Subnet) u2oExcludeIp4Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip4"), "-", ".", -1) u2oExcludeIp6Ag := strings.Replace(fmt.Sprintf(util.U2OExcludeIPAg, subnet.Name, "ip6"), "-", ".", -1) - if err := c.ovnLegacyClient.DeleteAddressSet(u2oExcludeIp4Ag); err != nil { - klog.Errorf("failed to delete address set %s %v", u2oExcludeIp4Ag, err) + if err := c.ovnClient.DeleteAddressSet(u2oExcludeIp4Ag); err != nil { + klog.Errorf("delete address set %s: %v", u2oExcludeIp4Ag, err) return err } - if err := c.ovnLegacyClient.DeleteAddressSet(u2oExcludeIp6Ag); err != nil { - klog.Errorf("failed to delete address set %s %v", u2oExcludeIp6Ag, err) + if err := c.ovnClient.DeleteAddressSet(u2oExcludeIp6Ag); err != nil { + klog.Errorf("delete address set %s: %v", u2oExcludeIp6Ag, err) return err } diff --git a/pkg/ovs/interface.go b/pkg/ovs/interface.go index 4ee503f3e32..4f4616d6630 100644 --- a/pkg/ovs/interface.go +++ b/pkg/ovs/interface.go @@ -7,6 +7,7 @@ import ( kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1" "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb" + "github.com/kubeovn/kube-ovn/pkg/util" ) type NbGlobal interface { @@ -58,7 +59,6 @@ type LogicalSwitchPort interface { SetLogicalSwitchPortExternalIds(lspName string, externalIds map[string]string) error SetLogicalSwitchPortVlanTag(lspName string, vlanID int) error SetLogicalSwitchPortsSecurityGroup(sgName string, op string) error - UpdateLogicalSwitchAcl(lsName string, subnetAcls []kubeovnv1.Acl) error EnablePortLayer2forward(lspName string) error DeleteLogicalSwitchPort(lspName string) error ListLogicalSwitchPorts(needVendorFilter bool, externalIDs map[string]string, filter func(lsp *ovnnb.LogicalSwitchPort) bool) ([]ovnnb.LogicalSwitchPort, error) @@ -91,15 +91,18 @@ type PortGroup interface { } type ACL interface { - CreateIngressAcl(pgName, asIngressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort) error - CreateEgressAcl(pgName, asEgressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort) error - CreateGatewayAcl(pgName, gateway string) error - CreateNodeAcl(pgName, nodeIp string) error + UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) + UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) + CreateGatewayAcl(lsName, pgName, gateway string) error + CreateNodeAcl(pgName, nodeIpStr, joinIpStr string) error CreateSgDenyAllAcl(sgName string) error + CreateSgBaseACL(sgName string, direction string) error UpdateSgAcl(sg *kubeovnv1.SecurityGroup, direction string) error - SetAclLog(pgName string, logEnable, isIngress bool) error + UpdateLogicalSwitchAcl(lsName string, subnetAcls []kubeovnv1.Acl) error + SetAclLog(pgName, protocol string, logEnable, isIngress bool) error SetLogicalSwitchPrivate(lsName, cidrBlock string, allowSubnets []string) error - DeleteAcls(parentName, parentType string, direction string) error + DeleteAcls(parentName, parentType string, direction string, externalIDs map[string]string) error + DeleteAclsOps(parentName, parentType string, direction string, externalIDs map[string]string) ([]ovsdb.Operation, error) } type AddressSet interface { @@ -165,4 +168,5 @@ type OvnClient interface { DeleteLogicalGatewaySwitch(lsName, lrName string) error DeleteSecurityGroup(sgName string) error GetEntityInfo(entity interface{}) error + Transact(method string, operations []ovsdb.Operation) error } diff --git a/pkg/ovs/ovn-nb-acl.go b/pkg/ovs/ovn-nb-acl.go index add8f91eed4..325f9f4e1b4 100644 --- a/pkg/ovs/ovn-nb-acl.go +++ b/pkg/ovs/ovn-nb-acl.go @@ -7,6 +7,8 @@ import ( "strings" netv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/klog/v2" "github.com/ovn-org/libovsdb/model" "github.com/ovn-org/libovsdb/ovsdb" @@ -17,90 +19,123 @@ import ( "github.com/kubeovn/kube-ovn/pkg/util" ) -// CreateIngressACL creates an ingress ACL -func (c *ovnClient) CreateIngressAcl(pgName, asIngressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort) error { +// UpdateIngressAclOps return operation that creates an ingress ACL +func (c *ovnClient) UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) { acls := make([]*ovnnb.ACL, 0) + ipSuffix := "ip4" + if protocol == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + } + /* default drop acl */ - AllIpMatch := NewAndAclMatch( + allIpMatch := NewAndAclMatch( NewAclMatch("outport", "==", "@"+pgName, ""), - NewAclMatch("ip", "", "", ""), + NewAclMatch(ipSuffix, "", "", ""), ) options := func(acl *ovnnb.ACL) { - acl.Name = &pgName - acl.Log = true - acl.Severity = &ovnnb.ACLSeverityWarning + if logEnable { + acl.Log = true + acl.Severity = &ovnnb.ACLSeverityWarning + } } - defaultDropAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, AllIpMatch.String(), ovnnb.ACLActionDrop, options) + defaultDropAcl, err := c.newAclWithoutCheck(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, allIpMatch.String(), ovnnb.ACLActionDrop, options) if err != nil { - return fmt.Errorf("new default drop ingress acl for port group %s: %v", pgName, err) + return nil, fmt.Errorf("new default drop ingress acl for port group %s: %v", pgName, err) } acls = append(acls, defaultDropAcl) /* allow acl */ - matches := newNetworkPolicyAclMatch(pgName, asIngressName, asExceptName, protocol, ovnnb.ACLDirectionToLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asIngressName, asExceptName, protocol, ovnnb.ACLDirectionToLport, npp, namedPortMap) for _, m := range matches { - allowAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, m, ovnnb.ACLActionAllowRelated) + allowAcl, err := c.newAclWithoutCheck(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, m, ovnnb.ACLActionAllowRelated) if err != nil { - return fmt.Errorf("new allow ingress acl for port group %s: %v", pgName, err) + return nil, fmt.Errorf("new allow ingress acl for port group %s: %v", pgName, err) } acls = append(acls, allowAcl) } - if err := c.CreateAcls(pgName, portGroupKey, acls...); err != nil { - return fmt.Errorf("add ingress acls to port group %s: %v", pgName, err) + ops, err := c.CreateAclsOps(pgName, portGroupKey, acls...) + if err != nil { + return nil, err } - return nil + return ops, nil } -// CreateIngressACL creates an egress ACL -func (c *ovnClient) CreateEgressAcl(pgName, asEgressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort) error { +// UpdateEgressAclOps return operation that creates an egress ACL +func (c *ovnClient) UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort, logEnable bool, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) { acls := make([]*ovnnb.ACL, 0) + ipSuffix := "ip4" + if protocol == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + } + /* default drop acl */ - AllIpMatch := NewAndAclMatch( + allIpMatch := NewAndAclMatch( NewAclMatch("inport", "==", "@"+pgName, ""), - NewAclMatch("ip", "", "", ""), + NewAclMatch(ipSuffix, "", "", ""), ) options := func(acl *ovnnb.ACL) { - acl.Name = &pgName - acl.Log = true - acl.Severity = &ovnnb.ACLSeverityWarning + if logEnable { + acl.Log = true + acl.Severity = &ovnnb.ACLSeverityWarning + } + + if acl.Options == nil { + acl.Options = make(map[string]string) + } + acl.Options["apply-after-lb"] = "true" } - defaultDropAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressDefaultDrop, AllIpMatch.String(), ovnnb.ACLActionDrop, options) + defaultDropAcl, err := c.newAclWithoutCheck(pgName, ovnnb.ACLDirectionFromLport, util.EgressDefaultDrop, allIpMatch.String(), ovnnb.ACLActionDrop, options) if err != nil { - return fmt.Errorf("new default drop egress acl for port group %s: %v", pgName, err) + return nil, fmt.Errorf("new default drop egress acl for port group %s: %v", pgName, err) } acls = append(acls, defaultDropAcl) /* allow acl */ - matches := newNetworkPolicyAclMatch(pgName, asEgressName, asExceptName, protocol, ovnnb.ACLDirectionFromLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asEgressName, asExceptName, protocol, ovnnb.ACLDirectionFromLport, npp, namedPortMap) for _, m := range matches { - allowAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, m, ovnnb.ACLActionAllowRelated) + allowAcl, err := c.newAclWithoutCheck(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, m, ovnnb.ACLActionAllowRelated, func(acl *ovnnb.ACL) { + if acl.Options == nil { + acl.Options = make(map[string]string) + } + acl.Options["apply-after-lb"] = "true" + }) if err != nil { - return fmt.Errorf("new allow egress acl for port group %s: %v", pgName, err) + return nil, fmt.Errorf("new allow egress acl for port group %s: %v", pgName, err) } acls = append(acls, allowAcl) } - if err := c.CreateAcls(pgName, portGroupKey, acls...); err != nil { - return fmt.Errorf("add egress acls to port group %s: %v", pgName, err) + ops, err := c.CreateAclsOps(pgName, portGroupKey, acls...) + if err != nil { + return nil, err } - return nil + return ops, nil } // CreateGatewayACL create allow acl for subnet gateway -func (c *ovnClient) CreateGatewayAcl(pgName, gateway string) error { +func (c *ovnClient) CreateGatewayAcl(lsName, pgName, gateway string) error { acls := make([]*ovnnb.ACL, 0) + var parentName, parentType string + if len(pgName) != 0 { + parentName, parentType = pgName, portGroupKey + } else if len(lsName) != 0 { + parentName, parentType = lsName, logicalSwitchKey + } else { + return fmt.Errorf("one of port group name and logical switch name must be specified") + } + for _, gw := range strings.Split(gateway, ",") { protocol := util.CheckProtocol(gw) ipSuffix := "ip4" @@ -108,43 +143,68 @@ func (c *ovnClient) CreateGatewayAcl(pgName, gateway string) error { ipSuffix = "ip6" } - allowIngressAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, fmt.Sprintf("%s.src == %s", ipSuffix, gw), ovnnb.ACLActionAllowRelated) + allowIngressAcl, err := c.newAcl(parentName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, fmt.Sprintf("%s.src == %s", ipSuffix, gw), ovnnb.ACLActionAllowRelated) if err != nil { - return fmt.Errorf("new allow ingress acl for port group %s: %v", pgName, err) + return fmt.Errorf("new allow ingress acl for %s: %v", parentName, err) } - allowEgressAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, fmt.Sprintf("%s.dst == %s", ipSuffix, gw), ovnnb.ACLActionAllowRelated) + options := func(acl *ovnnb.ACL) { + if acl.Options == nil { + acl.Options = make(map[string]string) + } + acl.Options["apply-after-lb"] = "true" + } + + allowEgressAcl, err := c.newAcl(parentName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, fmt.Sprintf("%s.dst == %s", ipSuffix, gw), ovnnb.ACLActionAllowRelated, options) if err != nil { - return fmt.Errorf("new allow egress acl for port group %s: %v", pgName, err) + return fmt.Errorf("new allow egress acl for %s: %v", parentName, err) } acls = append(acls, allowIngressAcl, allowEgressAcl) + + if ipSuffix == "ip6" { + ndAcl, err := c.newAcl(parentName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, "nd || nd_ra || nd_rs", ovnnb.ACLActionAllowRelated, options) + if err != nil { + return fmt.Errorf("new nd acl for %s: %v", parentName, err) + } + + acls = append(acls, ndAcl) + } + } - if err := c.CreateAcls(pgName, portGroupKey, acls...); err != nil { - return fmt.Errorf("add gateway acls to port group %s: %v", pgName, err) + if err := c.CreateAcls(parentName, parentType, acls...); err != nil { + return fmt.Errorf("add gateway acls to %s: %v", pgName, err) } return nil } // CreateGatewayACL create allow acl for node join ip -func (c *ovnClient) CreateNodeAcl(pgName, nodeIp string) error { +func (c *ovnClient) CreateNodeAcl(pgName, nodeIpStr, joinIpStr string) error { acls := make([]*ovnnb.ACL, 0) - for _, ip := range strings.Split(nodeIp, ",") { - protocol := util.CheckProtocol(ip) + nodeIPs := strings.Split(nodeIpStr, ",") + for _, nodeIP := range nodeIPs { + protocol := util.CheckProtocol(nodeIP) ipSuffix := "ip4" if protocol == kubeovnv1.ProtocolIPv6 { ipSuffix = "ip6" } pgAs := fmt.Sprintf("%s_%s", pgName, ipSuffix) - allowIngressAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, ip, ipSuffix, pgAs), ovnnb.ACLActionAllowRelated) + allowIngressAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, nodeIP, ipSuffix, pgAs), ovnnb.ACLActionAllowRelated) if err != nil { return fmt.Errorf("new allow ingress acl for port group %s: %v", pgName, err) } - allowEgressAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionFromLport, util.NodeAllowPriority, fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, ip, ipSuffix, pgAs), ovnnb.ACLActionAllowRelated) + options := func(acl *ovnnb.ACL) { + if acl.Options == nil { + acl.Options = make(map[string]string) + } + acl.Options["apply-after-lb"] = "true" + } + + allowEgressAcl, err := c.newAcl(pgName, ovnnb.ACLDirectionFromLport, util.NodeAllowPriority, fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, nodeIP, ipSuffix, pgAs), ovnnb.ACLActionAllowRelated, options) if err != nil { return fmt.Errorf("new allow egress acl for port group %s: %v", pgName, err) } @@ -152,6 +212,30 @@ func (c *ovnClient) CreateNodeAcl(pgName, nodeIp string) error { acls = append(acls, allowIngressAcl, allowEgressAcl) } + for _, joinIp := range strings.Split(joinIpStr, ",") { + if util.ContainsString(nodeIPs, joinIp) { + continue + } + + protocol := util.CheckProtocol(joinIp) + ipSuffix := "ip4" + if protocol == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + } + + pgAs := fmt.Sprintf("%s_%s", pgName, ipSuffix) + + if err := c.DeleteAcl(pgName, portGroupKey, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, joinIp, ipSuffix, pgAs)); err != nil { + klog.Errorf("delete ingress acl from port group %s: %v", pgName, err) + return err + } + + if err := c.DeleteAcl(pgName, portGroupKey, ovnnb.ACLDirectionFromLport, util.NodeAllowPriority, fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, joinIp, ipSuffix, pgAs)); err != nil { + klog.Errorf("delete egress acl from port group %s: %v", pgName, err) + return err + } + } + if err := c.CreateAcls(pgName, portGroupKey, acls...); err != nil { return fmt.Errorf("add node acls to port group %s: %v", pgName, err) } @@ -179,11 +263,76 @@ func (c *ovnClient) CreateSgDenyAllAcl(sgName string) error { return nil } +func (c *ovnClient) CreateSgBaseACL(sgName string, direction string) error { + pgName := GetSgPortGroupName(sgName) + + // ingress rule + portDirection := "outport" + dhcpv4UdpSrc, dhcpv4UdpDst := "67", "68" + dhcpv6UdpSrc, dhcpv6UdpDst := "547", "546" + if direction == ovnnb.ACLDirectionFromLport { // egress rule + portDirection = "inport" + dhcpv4UdpSrc, dhcpv4UdpDst = dhcpv4UdpDst, dhcpv4UdpSrc + dhcpv6UdpSrc, dhcpv6UdpDst = dhcpv6UdpDst, dhcpv6UdpSrc + } + + acls := make([]*ovnnb.ACL, 0) + + newAcl := func(match string) { + acl, err := c.newAcl(pgName, ovnnb.ACLDirectionToLport, util.SecurityGroupBasePriority, match, ovnnb.ACLActionAllowRelated) + if err != nil { + klog.Errorf("new base ingress acl for security group %s: %v", sgName, err) + return + } + acls = append(acls, acl) + } + + // allow arp + AllArpMatch := NewAndAclMatch( + NewAclMatch(portDirection, "==", "@"+pgName, ""), + NewAclMatch("arp", "", "", ""), + ) + newAcl(AllArpMatch.String()) + + // icmpv6 + icmpv6Match := NewAndAclMatch( + NewAclMatch(portDirection, "==", "@"+pgName, ""), + NewAclMatch("icmp6.type", "==", "{130, 134, 135, 136}", ""), + NewAclMatch("icmp6.code", "==", "0", ""), + NewAclMatch("ip.ttl", "==", "255", ""), + ) + newAcl(icmpv6Match.String()) + + // dhcpv4 offer + dhcpv4Match := NewAndAclMatch( + NewAclMatch(portDirection, "==", "@"+pgName, ""), + NewAclMatch("udp.src", "==", dhcpv4UdpSrc, ""), + NewAclMatch("udp.dst", "==", dhcpv4UdpDst, ""), + NewAclMatch("ip4", "", "", ""), + ) + newAcl(dhcpv4Match.String()) + + // dhcpv6 offer + dhcpv6Match := NewAndAclMatch( + NewAclMatch(portDirection, "==", "@"+pgName, ""), + NewAclMatch("udp.src", "==", dhcpv6UdpSrc, ""), + NewAclMatch("udp.dst", "==", dhcpv6UdpDst, ""), + NewAclMatch("ip6", "", "", ""), + ) + + newAcl(dhcpv6Match.String()) + + if err := c.CreateAcls(pgName, portGroupKey, acls...); err != nil { + return fmt.Errorf("add ingress acls to port group %s: %v", pgName, err) + } + return nil +} + func (c *ovnClient) UpdateSgAcl(sg *kubeovnv1.SecurityGroup, direction string) error { pgName := GetSgPortGroupName(sg.Name) // clear acl - if err := c.DeleteAcls(pgName, portGroupKey, direction); err != nil { + if err := c.DeleteAcls(pgName, portGroupKey, direction, nil); err != nil { return fmt.Errorf("delete direction '%s' acls from port group %s: %v", direction, pgName, err) } @@ -236,8 +385,8 @@ func (c *ovnClient) UpdateSgAcl(sg *kubeovnv1.SecurityGroup, direction string) e } func (c *ovnClient) UpdateLogicalSwitchAcl(lsName string, subnetAcls []kubeovnv1.Acl) error { - if err := c.DeleteAcls(lsName, logicalSwitchKey, ""); err != nil { - return fmt.Errorf("clear logical switch %s acls: %v", lsName, err) + if err := c.DeleteAcls(lsName, logicalSwitchKey, "", map[string]string{"subnet": lsName}); err != nil { + return fmt.Errorf("delete subnet acls from %s: %v", lsName, err) } if len(subnetAcls) == 0 { @@ -245,9 +394,16 @@ func (c *ovnClient) UpdateLogicalSwitchAcl(lsName string, subnetAcls []kubeovnv1 } acls := make([]*ovnnb.ACL, 0, len(subnetAcls)) + options := func(acl *ovnnb.ACL) { + if acl.ExternalIDs == nil { + acl.ExternalIDs = make(map[string]string) + } + acl.ExternalIDs["subnet"] = lsName + } + /* recreate logical switch acl */ for _, subnetAcl := range subnetAcls { - acl, err := c.newAcl(lsName, subnetAcl.Direction, strconv.Itoa(subnetAcl.Priority), subnetAcl.Match, subnetAcl.Action) + acl, err := c.newAcl(lsName, subnetAcl.Direction, strconv.Itoa(subnetAcl.Priority), subnetAcl.Match, subnetAcl.Action, options) if err != nil { return fmt.Errorf("new acl for logical switch %s: %v", lsName, err) } @@ -282,14 +438,14 @@ func (c *ovnClient) UpdateAcl(acl *ovnnb.ACL, fields ...interface{}) error { // SetLogicalSwitchPrivate will drop all ingress traffic except allow subnets, same subnet and node subnet func (c *ovnClient) SetLogicalSwitchPrivate(lsName, cidrBlock string, allowSubnets []string) error { // clear acls - if err := c.DeleteAcls(lsName, logicalSwitchKey, ""); err != nil { + if err := c.DeleteAcls(lsName, logicalSwitchKey, "", nil); err != nil { return fmt.Errorf("clear logical switch %s acls: %v", lsName, err) } acls := make([]*ovnnb.ACL, 0) /* default drop acl */ - AllIpMatch := NewAclMatch("ip", "", "", "") + allIpMatch := NewAclMatch("ip", "", "", "") options := func(acl *ovnnb.ACL) { acl.Name = &lsName @@ -297,7 +453,7 @@ func (c *ovnClient) SetLogicalSwitchPrivate(lsName, cidrBlock string, allowSubne acl.Severity = &ovnnb.ACLSeverityWarning } - defaultDropAcl, err := c.newAcl(lsName, ovnnb.ACLDirectionToLport, util.DefaultDropPriority, AllIpMatch.String(), ovnnb.ACLActionDrop, options) + defaultDropAcl, err := c.newAcl(lsName, ovnnb.ACLDirectionToLport, util.DefaultDropPriority, allIpMatch.String(), ovnnb.ACLActionDrop, options) if err != nil { return fmt.Errorf("new default drop ingress acl for logical switch %s: %v", lsName, err) } @@ -311,9 +467,7 @@ func (c *ovnClient) SetLogicalSwitchPrivate(lsName, cidrBlock string, allowSubne continue } - match := NewAndAclMatch( - NewAclMatch(ipSuffix+".src", "==", nodeCidr, ""), - ) + match := NewAclMatch(ipSuffix+".src", "==", nodeCidr, "") acl, err := c.newAcl(lsName, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, match.String(), ovnnb.ACLActionAllowRelated) if err != nil { @@ -399,7 +553,7 @@ func (c *ovnClient) SetLogicalSwitchPrivate(lsName, cidrBlock string, allowSubne return nil } -func (c *ovnClient) SetAclLog(pgName string, logEnable, isIngress bool) error { +func (c *ovnClient) SetAclLog(pgName, protocol string, logEnable, isIngress bool) error { direction := ovnnb.ACLDirectionToLport portDirection := "outport" if !isIngress { @@ -407,17 +561,26 @@ func (c *ovnClient) SetAclLog(pgName string, logEnable, isIngress bool) error { portDirection = "inport" } + ipSuffix := "ip4" + if protocol == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + } + // match all traffic to or from pgName - AllIpMatch := NewAndAclMatch( + allIpMatch := NewAndAclMatch( NewAclMatch(portDirection, "==", "@"+pgName, ""), - NewAclMatch("ip", "", "", ""), + NewAclMatch(ipSuffix, "", "", ""), ) - acl, err := c.GetAcl(pgName, direction, util.IngressDefaultDrop, AllIpMatch.String(), false) + acl, err := c.GetAcl(pgName, direction, util.IngressDefaultDrop, allIpMatch.String(), true) if err != nil { return err } + if acl == nil { + return nil //skip if acl not found + } + acl.Log = logEnable err = c.UpdateAcl(acl, &acl.Log) @@ -431,45 +594,11 @@ func (c *ovnClient) SetAclLog(pgName string, logEnable, isIngress bool) error { // CreateAcls create several acl once // parentType is 'ls' or 'pg' func (c *ovnClient) CreateAcls(parentName, parentType string, acls ...*ovnnb.ACL) error { - if parentType != portGroupKey && parentType != logicalSwitchKey { - return fmt.Errorf("acl parent type must be '%s' or '%s'", portGroupKey, logicalSwitchKey) - } - - if len(acls) == 0 { - return nil - } - - models := make([]model.Model, 0, len(acls)) - aclUUIDs := make([]string, 0, len(acls)) - for _, acl := range acls { - if acl != nil { - models = append(models, model.Model(acl)) - aclUUIDs = append(aclUUIDs, acl.UUID) - } - } - - createAclsOp, err := c.ovnNbClient.Create(models...) + ops, err := c.CreateAclsOps(parentName, parentType, acls...) if err != nil { - return fmt.Errorf("generate operations for creating acls: %v", err) - } - - var aclAddOp []ovsdb.Operation - if parentType == portGroupKey { // acl attach to port group - aclAddOp, err = c.portGroupUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationInsert) - if err != nil { - return fmt.Errorf("generate operations for adding acls to port group %s: %v", parentName, err) - } - } else { // acl attach to logical switch - aclAddOp, err = c.logicalSwitchUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationInsert) - if err != nil { - return fmt.Errorf("generate operations for adding acls to logical switch %s: %v", parentName, err) - } + return err } - ops := make([]ovsdb.Operation, 0, len(createAclsOp)+len(aclAddOp)) - ops = append(ops, createAclsOp...) - ops = append(ops, aclAddOp...) - if err = c.Transact("acls-add", ops); err != nil { return fmt.Errorf("add acls to type %s %s: %v", parentType, parentName, err) } @@ -498,44 +627,44 @@ func (c *ovnClient) CreateBareAcl(parentName, direction, priority, match, action // DeleteAcls delete several acl once, // delete to-lport and from-lport direction acl when direction is empty, otherwise one-way // parentType is 'ls' or 'pg' -func (c *ovnClient) DeleteAcls(parentName, parentType string, direction string) error { - externalIDs := map[string]string{aclParentKey: parentName} +func (c *ovnClient) DeleteAcls(parentName, parentType string, direction string, externalIDs map[string]string) error { + ops, err := c.DeleteAclsOps(parentName, parentType, direction, externalIDs) + if err != nil { + return err + } - /* delete acls from port group or logical switch */ - acls, err := c.ListAcls(direction, externalIDs) + if err = c.Transact("acls-del", ops); err != nil { + return fmt.Errorf("del acls from type %s %s: %v", parentType, parentName, err) + } + + return nil +} + +func (c *ovnClient) DeleteAcl(parentName, parentType, direction, priority, match string) error { + acl, err := c.GetAcl(parentName, direction, priority, match, true) if err != nil { - return fmt.Errorf("list type %s %s acls: %v", parentType, parentName, err) + return err } - aclUUIDs := make([]string, 0, len(acls)) - for _, acl := range acls { - aclUUIDs = append(aclUUIDs, acl.UUID) + if acl == nil { + return nil // skip if acl not exist } + // the acls column has a strong reference to the ACL table, so there is no need to delete the ACL var removeAclOp []ovsdb.Operation if parentType == portGroupKey { // remove acl from port group - removeAclOp, err = c.portGroupUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationDelete) + removeAclOp, err = c.portGroupUpdateAclOp(parentName, []string{acl.UUID}, ovsdb.MutateOperationDelete) if err != nil { - return fmt.Errorf("generate operations for deleting acls from port group %s: %v", parentName, err) + return fmt.Errorf("generate operations for deleting acl from port group %s: %v", parentName, err) } } else { // remove acl from logical switch - removeAclOp, err = c.logicalSwitchUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationDelete) + removeAclOp, err = c.logicalSwitchUpdateAclOp(parentName, []string{acl.UUID}, ovsdb.MutateOperationDelete) if err != nil { - return fmt.Errorf("generate operations for deleting acls from logical switch %s: %v", parentName, err) + return fmt.Errorf("generate operations for deleting acl from logical switch %s: %v", parentName, err) } } - // delete acls - delAclsOp, err := c.WhereCache(aclFilter(direction, externalIDs)).Delete() - if err != nil { - return fmt.Errorf("generate operation for deleting acls: %v", err) - } - - ops := make([]ovsdb.Operation, 0, len(removeAclOp)+len(delAclsOp)) - ops = append(ops, removeAclOp...) - ops = append(ops, delAclsOp...) - - if err = c.Transact("acls-del", ops); err != nil { + if err = c.Transact("acls-del", removeAclOp); err != nil { return fmt.Errorf("del acls from type %s %s: %v", parentType, parentName, err) } @@ -640,6 +769,38 @@ func (c *ovnClient) newAcl(parent, direction, priority, match, action string, op return acl, nil } +// newAclWithoutCheck return acl with basic information without check acl exists, +// this would cause duplicated acl, so don't use this function to create acl normally, +// but maybe used for updating network policy acl +func (c *ovnClient) newAclWithoutCheck(parent, direction, priority, match, action string, options ...func(acl *ovnnb.ACL)) (*ovnnb.ACL, error) { + if len(parent) == 0 { + return nil, fmt.Errorf("the parent name is required") + } + + if len(direction) == 0 || len(priority) == 0 || len(match) == 0 || len(action) == 0 { + return nil, fmt.Errorf("acl 'direction %s' and 'priority %s' and 'match %s' and 'action %s' is required", direction, priority, match, action) + } + + intPriority, _ := strconv.Atoi(priority) + + acl := &ovnnb.ACL{ + UUID: ovsclient.NamedUUID(), + Action: action, + Direction: direction, + Match: match, + Priority: intPriority, + ExternalIDs: map[string]string{ + aclParentKey: parent, + }, + } + + for _, option := range options { + option(acl) + } + + return acl, nil +} + // createSgRuleACL create security group rule acl func (c *ovnClient) newSgRuleACL(sgName string, direction string, rule *kubeovnv1.SgRule) (*ovnnb.ACL, error) { ipSuffix := "ip4" @@ -659,7 +820,7 @@ func (c *ovnClient) newSgRuleACL(sgName string, direction string, rule *kubeovnv ipKey := ipSuffix + "." + srcOrDst /* match all traffic to or from pgName */ - AllIpMatch := NewAndAclMatch( + allIpMatch := NewAndAclMatch( NewAclMatch(portDirection, "==", "@"+pgName, ""), NewAclMatch(ipSuffix, "", "", ""), ) @@ -667,15 +828,19 @@ func (c *ovnClient) newSgRuleACL(sgName string, direction string, rule *kubeovnv /* allow allowed ip traffic */ // type address allowedIpMatch := NewAndAclMatch( - AllIpMatch, + allIpMatch, NewAclMatch(ipKey, "==", rule.RemoteAddress, ""), ) // type securityGroup + remotePgName := GetSgV4AssociatedName(rule.RemoteSecurityGroup) + if rule.IPVersion == "ipv6" { + remotePgName = GetSgV6AssociatedName(rule.RemoteSecurityGroup) + } if rule.RemoteType == kubeovnv1.SgRemoteTypeSg { allowedIpMatch = NewAndAclMatch( - AllIpMatch, - NewAclMatch(ipKey, "==", "$"+rule.RemoteSecurityGroup, ""), + allIpMatch, + NewAclMatch(ipKey, "==", "$"+remotePgName, ""), ) } @@ -717,7 +882,7 @@ func (c *ovnClient) newSgRuleACL(sgName string, direction string, rule *kubeovnv return acl, nil } -func newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, protocol, direction string, npp []netv1.NetworkPolicyPort) []string { +func newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, protocol, direction string, npp []netv1.NetworkPolicyPort, namedPortMap map[string]*util.NamedPortInfo) []string { ipSuffix := "ip4" if protocol == kubeovnv1.ProtocolIPv6 { ipSuffix = "ip6" @@ -733,13 +898,13 @@ func newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, protocol, direc ipKey := ipSuffix + "." + srcOrDst // match all traffic to or from pgName - AllIpMatch := NewAndAclMatch( + allIpMatch := NewAndAclMatch( NewAclMatch(portDirection, "==", "@"+pgName, ""), NewAclMatch("ip", "", "", ""), ) allowedIpMatch := NewAndAclMatch( - AllIpMatch, + allIpMatch, NewAclMatch(ipKey, "==", "$"+asAllowName, ""), NewAclMatch(ipKey, "!=", "$"+asExceptName, ""), ) @@ -768,12 +933,31 @@ func newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, protocol, direc // allow one tcp or udp port traffic if port.EndPort == nil { tcpKey := protocol + ".dst" + + var portId int32 = 0 + + if port.Port.Type == intstr.Int { + portId = port.Port.IntVal + } else { + if namedPortMap != nil { + _, ok := namedPortMap[port.Port.StrVal] + if !ok { + // for cyclonus network policy test case 'should allow ingress access on one named port' + // this case expect all-deny if no named port defined + klog.Errorf("no named port with name %s found ", port.Port.StrVal) + } else { + portId = namedPortMap[port.Port.StrVal].PortId + } + } + } + oneTcpMatch := NewAndAclMatch( allowedIpMatch, - NewAclMatch(tcpKey, "==", fmt.Sprintf("%d", port.Port.IntVal), ""), + NewAclMatch(tcpKey, "==", fmt.Sprintf("%d", portId), ""), ) matches = append(matches, oneTcpMatch.String()) + continue } @@ -823,3 +1007,86 @@ func aclFilter(direction string, externalIDs map[string]string) func(acl *ovnnb. return true } } + +// CreateAcls return operations which create several acl once +// parentType is 'ls' or 'pg' +func (c *ovnClient) CreateAclsOps(parentName, parentType string, acls ...*ovnnb.ACL) ([]ovsdb.Operation, error) { + if parentType != portGroupKey && parentType != logicalSwitchKey { + return nil, fmt.Errorf("acl parent type must be '%s' or '%s'", portGroupKey, logicalSwitchKey) + } + + if len(acls) == 0 { + return nil, nil + } + + models := make([]model.Model, 0, len(acls)) + aclUUIDs := make([]string, 0, len(acls)) + for _, acl := range acls { + if acl != nil { + models = append(models, model.Model(acl)) + aclUUIDs = append(aclUUIDs, acl.UUID) + } + } + + createAclsOp, err := c.ovnNbClient.Create(models...) + if err != nil { + return nil, fmt.Errorf("generate operations for creating acls: %v", err) + } + + var aclAddOp []ovsdb.Operation + if parentType == portGroupKey { // acl attach to port group + aclAddOp, err = c.portGroupUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationInsert) + if err != nil { + return nil, fmt.Errorf("generate operations for adding acls to port group %s: %v", parentName, err) + } + } else { // acl attach to logical switch + aclAddOp, err = c.logicalSwitchUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationInsert) + if err != nil { + return nil, fmt.Errorf("generate operations for adding acls to logical switch %s: %v", parentName, err) + } + } + + ops := make([]ovsdb.Operation, 0, len(createAclsOp)+len(aclAddOp)) + ops = append(ops, createAclsOp...) + ops = append(ops, aclAddOp...) + + return ops, nil +} + +// DeleteAcls return operation which delete several acl once, +// delete to-lport and from-lport direction acl when direction is empty, otherwise one-way +// parentType is 'ls' or 'pg' +func (c *ovnClient) DeleteAclsOps(parentName, parentType string, direction string, externalIDs map[string]string) ([]ovsdb.Operation, error) { + if externalIDs == nil { + externalIDs = make(map[string]string) + } + + externalIDs[aclParentKey] = parentName + + /* delete acls from port group or logical switch */ + acls, err := c.ListAcls(direction, externalIDs) + if err != nil { + return nil, fmt.Errorf("list type %s %s acls: %v", parentType, parentName, err) + } + + aclUUIDs := make([]string, 0, len(acls)) + for _, acl := range acls { + aclUUIDs = append(aclUUIDs, acl.UUID) + } + + // the acls column has a strong reference to the ACL table, so there is no need to delete the ACL + var removeAclOp []ovsdb.Operation + if parentType == portGroupKey { // remove acl from port group + removeAclOp, err = c.portGroupUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationDelete) + if err != nil { + return nil, fmt.Errorf("generate operations for deleting acls from port group %s: %v", parentName, err) + } + } else { // remove acl from logical switch + removeAclOp, err = c.logicalSwitchUpdateAclOp(parentName, aclUUIDs, ovsdb.MutateOperationDelete) + if err != nil { + return nil, fmt.Errorf("generate operations for deleting acls from logical switch %s: %v", parentName, err) + } + } + + return removeAclOp, nil +} diff --git a/pkg/ovs/ovn-nb-acl_test.go b/pkg/ovs/ovn-nb-acl_test.go index 81426d0a579..636a9a0eeb3 100644 --- a/pkg/ovs/ovn-nb-acl_test.go +++ b/pkg/ovs/ovn-nb-acl_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/ovn-org/libovsdb/ovsdb" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" @@ -62,12 +63,21 @@ func newAcl(parentName, direction, priority, match, action string, options ...fu return acl } -func (suite *OvnClientTestSuite) testCreateIngressAcl() { +func (suite *OvnClientTestSuite) testUpdateIngressAclOps() { t := suite.T() t.Parallel() ovnClient := suite.ovnClient + expect := func(row ovsdb.Row, action, direction, match, priority string) { + intPriority, err := strconv.Atoi(priority) + require.NoError(t, err) + require.Equal(t, action, row["action"]) + require.Equal(t, direction, row["direction"]) + require.Equal(t, match, row["match"]) + require.Equal(t, intPriority, row["priority"]) + } + t.Run("ipv4 acl", func(t *testing.T) { t.Parallel() @@ -81,37 +91,18 @@ func (suite *OvnClientTestSuite) testCreateIngressAcl() { npp := mockNetworkPolicyPort() - err = ovnClient.CreateIngressAcl(pgName, asIngressName, asExceptName, protocol, npp) - require.NoError(t, err) - - pg, err := ovnClient.GetPortGroup(pgName, false) + ops, err := ovnClient.UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol, npp, true, nil) require.NoError(t, err) - require.Len(t, pg.ACLs, 3) + require.Len(t, ops, 4) - match := fmt.Sprintf("outport == @%s && ip", pgName) - defaultDropAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, match, false) - require.NoError(t, err) + expect(ops[0].Row, "drop", ovnnb.ACLDirectionToLport, fmt.Sprintf("outport == @%s && ip4", pgName), util.IngressDefaultDrop) - expect := newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, match, ovnnb.ACLActionDrop, func(acl *ovnnb.ACL) { - acl.Name = &pgName - acl.Log = true - acl.Severity = &ovnnb.ACLSeverityWarning - acl.UUID = defaultDropAcl.UUID - }) - - require.Equal(t, expect, defaultDropAcl) - require.Contains(t, pg.ACLs, defaultDropAcl.UUID) - - matches := newNetworkPolicyAclMatch(pgName, asIngressName, asExceptName, protocol, ovnnb.ACLDirectionToLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asIngressName, asExceptName, protocol, ovnnb.ACLDirectionToLport, npp, nil) + i := 1 for _, m := range matches { - allowAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, m, false) - require.NoError(t, err) - - expect := newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, m, ovnnb.ACLActionAllowRelated) - expect.UUID = allowAcl.UUID - require.Equal(t, expect, allowAcl) - - require.Contains(t, pg.ACLs, allowAcl.UUID) + require.Equal(t, m, ops[i].Row["match"]) + expect(ops[i].Row, ovnnb.ACLActionAllowRelated, ovnnb.ACLDirectionToLport, m, util.IngressAllowPriority) + i++ } }) @@ -126,47 +117,37 @@ func (suite *OvnClientTestSuite) testCreateIngressAcl() { err := ovnClient.CreatePortGroup(pgName, nil) require.NoError(t, err) - err = ovnClient.CreateIngressAcl(pgName, asIngressName, asExceptName, protocol, nil) - require.NoError(t, err) - - pg, err := ovnClient.GetPortGroup(pgName, false) - require.NoError(t, err) - require.Len(t, pg.ACLs, 2) - - match := fmt.Sprintf("outport == @%s && ip", pgName) - defaultDropAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, match, false) + ops, err := ovnClient.UpdateIngressAclOps(pgName, asIngressName, asExceptName, protocol, nil, true, nil) require.NoError(t, err) + require.Len(t, ops, 3) - expect := newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, match, ovnnb.ACLActionDrop, func(acl *ovnnb.ACL) { - acl.Name = &pgName - acl.Log = true - acl.Severity = &ovnnb.ACLSeverityWarning - acl.UUID = defaultDropAcl.UUID - }) - - require.Equal(t, expect, defaultDropAcl) - require.Contains(t, pg.ACLs, defaultDropAcl.UUID) + expect(ops[0].Row, "drop", ovnnb.ACLDirectionToLport, fmt.Sprintf("outport == @%s && ip6", pgName), util.IngressDefaultDrop) - matches := newNetworkPolicyAclMatch(pgName, asIngressName, asExceptName, protocol, ovnnb.ACLDirectionToLport, nil) + matches := newNetworkPolicyAclMatch(pgName, asIngressName, asExceptName, protocol, ovnnb.ACLDirectionToLport, nil, nil) + i := 1 for _, m := range matches { - allowAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, m, false) - require.NoError(t, err) - - expect := newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, m, ovnnb.ACLActionAllowRelated) - expect.UUID = allowAcl.UUID - require.Equal(t, expect, allowAcl) - - require.Contains(t, pg.ACLs, allowAcl.UUID) + require.Equal(t, m, ops[i].Row["match"]) + expect(ops[i].Row, ovnnb.ACLActionAllowRelated, ovnnb.ACLDirectionToLport, m, util.IngressAllowPriority) + i++ } }) } -func (suite *OvnClientTestSuite) testCreateEgressAcl() { +func (suite *OvnClientTestSuite) testUpdateEgressAclOps() { t := suite.T() t.Parallel() ovnClient := suite.ovnClient + expect := func(row ovsdb.Row, action, direction, match, priority string) { + intPriority, err := strconv.Atoi(priority) + require.NoError(t, err) + require.Equal(t, action, row["action"]) + require.Equal(t, direction, row["direction"]) + require.Equal(t, match, row["match"]) + require.Equal(t, intPriority, row["priority"]) + } + t.Run("ipv4 acl", func(t *testing.T) { t.Parallel() @@ -180,37 +161,18 @@ func (suite *OvnClientTestSuite) testCreateEgressAcl() { npp := mockNetworkPolicyPort() - err = ovnClient.CreateEgressAcl(pgName, asEgressName, asExceptName, protocol, npp) - require.NoError(t, err) - - pg, err := ovnClient.GetPortGroup(pgName, false) - require.NoError(t, err) - require.Len(t, pg.ACLs, 3) - - match := fmt.Sprintf("inport == @%s && ip", pgName) - defaultDropAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressDefaultDrop, match, false) + ops, err := ovnClient.UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol, npp, true, nil) require.NoError(t, err) + require.Len(t, ops, 4) - expect := newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressDefaultDrop, match, ovnnb.ACLActionDrop, func(acl *ovnnb.ACL) { - acl.Name = &pgName - acl.Log = true - acl.Severity = &ovnnb.ACLSeverityWarning - acl.UUID = defaultDropAcl.UUID - }) - - require.Equal(t, expect, defaultDropAcl) - require.Contains(t, pg.ACLs, defaultDropAcl.UUID) + expect(ops[0].Row, "drop", ovnnb.ACLDirectionFromLport, fmt.Sprintf("inport == @%s && ip4", pgName), util.EgressDefaultDrop) - matches := newNetworkPolicyAclMatch(pgName, asEgressName, asExceptName, protocol, ovnnb.ACLDirectionFromLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asEgressName, asExceptName, protocol, ovnnb.ACLDirectionFromLport, npp, nil) + i := 1 for _, m := range matches { - allowAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, m, false) - require.NoError(t, err) - - expect := newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, m, ovnnb.ACLActionAllowRelated) - expect.UUID = allowAcl.UUID - require.Equal(t, expect, allowAcl) - - require.Contains(t, pg.ACLs, allowAcl.UUID) + require.Equal(t, m, ops[i].Row["match"]) + expect(ops[i].Row, ovnnb.ACLActionAllowRelated, ovnnb.ACLDirectionFromLport, m, util.EgressAllowPriority) + i++ } }) @@ -225,37 +187,18 @@ func (suite *OvnClientTestSuite) testCreateEgressAcl() { err := ovnClient.CreatePortGroup(pgName, nil) require.NoError(t, err) - err = ovnClient.CreateEgressAcl(pgName, asEgressName, asExceptName, protocol, nil) + ops, err := ovnClient.UpdateEgressAclOps(pgName, asEgressName, asExceptName, protocol, nil, true, nil) require.NoError(t, err) + require.Len(t, ops, 3) - pg, err := ovnClient.GetPortGroup(pgName, false) - require.NoError(t, err) - require.Len(t, pg.ACLs, 2) - - match := fmt.Sprintf("inport == @%s && ip", pgName) - defaultDropAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressDefaultDrop, match, false) - require.NoError(t, err) - - expect := newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressDefaultDrop, match, ovnnb.ACLActionDrop, func(acl *ovnnb.ACL) { - acl.Name = &pgName - acl.Log = true - acl.Severity = &ovnnb.ACLSeverityWarning - acl.UUID = defaultDropAcl.UUID - }) - - require.Equal(t, expect, defaultDropAcl) - require.Contains(t, pg.ACLs, defaultDropAcl.UUID) + expect(ops[0].Row, "drop", ovnnb.ACLDirectionFromLport, fmt.Sprintf("inport == @%s && ip6", pgName), util.EgressDefaultDrop) - matches := newNetworkPolicyAclMatch(pgName, asEgressName, asExceptName, protocol, ovnnb.ACLDirectionFromLport, nil) + matches := newNetworkPolicyAclMatch(pgName, asEgressName, asExceptName, protocol, ovnnb.ACLDirectionFromLport, nil, nil) + i := 1 for _, m := range matches { - allowAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, m, false) - require.NoError(t, err) - - expect := newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, m, ovnnb.ACLActionAllowRelated) - expect.UUID = allowAcl.UUID - require.Equal(t, expect, allowAcl) - - require.Contains(t, pg.ACLs, allowAcl.UUID) + require.Equal(t, m, ops[i].Row["match"]) + expect(ops[i].Row, ovnnb.ACLActionAllowRelated, ovnnb.ACLDirectionFromLport, m, util.EgressAllowPriority) + i++ } }) } @@ -265,42 +208,147 @@ func (suite *OvnClientTestSuite) testCreateGatewayAcl() { t.Parallel() ovnClient := suite.ovnClient - pgName := "test_create_gw_acl_pg" - gateway := "10.244.0.1,fc00::0af4:01" - err := ovnClient.CreatePortGroup(pgName, nil) - require.NoError(t, err) + checkAcl := func(parent interface{}, direction, priority, match string, options map[string]string) { + pg, isPg := parent.(*ovnnb.PortGroup) + var name string + var acls []string + + if isPg { + name = pg.Name + acls = pg.ACLs + } else { + ls := parent.(*ovnnb.LogicalSwitch) + name = ls.Name + acls = ls.ACLs + } - err = ovnClient.CreateGatewayAcl(pgName, gateway) - require.NoError(t, err) + acl, err := ovnClient.GetAcl(name, direction, priority, match, false) + require.NoError(t, err) + expect := newAcl(name, direction, priority, match, ovnnb.ACLActionAllowRelated) + expect.UUID = acl.UUID + if len(options) != 0 { + expect.Options = options + } + require.Equal(t, expect, acl) + require.Contains(t, acls, acl.UUID) - pg, err := ovnClient.GetPortGroup(pgName, false) - require.NoError(t, err) - require.Len(t, pg.ACLs, 4) + } - for _, gw := range strings.Split(gateway, ",") { - protocol := util.CheckProtocol(gw) - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } + expect := func(parent interface{}, gateway string) { + for _, gw := range strings.Split(gateway, ",") { + protocol := util.CheckProtocol(gw) + ipSuffix := "ip4" + if protocol == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + } - match := fmt.Sprintf("%s.src == %s", ipSuffix, gw) - allowIngressAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, match, false) - require.NoError(t, err) - expect := newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, match, ovnnb.ACLActionAllowRelated) - expect.UUID = allowIngressAcl.UUID - require.Equal(t, expect, allowIngressAcl) - require.Contains(t, pg.ACLs, allowIngressAcl.UUID) + match := fmt.Sprintf("%s.src == %s", ipSuffix, gw) + checkAcl(parent, ovnnb.ACLDirectionToLport, util.IngressAllowPriority, match, nil) - match = fmt.Sprintf("%s.dst == %s", ipSuffix, gw) - allowEgressAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, match, false) - require.NoError(t, err) - expect = newAcl(pgName, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, match, ovnnb.ACLActionAllowRelated) - expect.UUID = allowEgressAcl.UUID - require.Equal(t, expect, allowEgressAcl) - require.Contains(t, pg.ACLs, allowEgressAcl.UUID) + match = fmt.Sprintf("%s.dst == %s", ipSuffix, gw) + checkAcl(parent, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, match, map[string]string{ + "apply-after-lb": "true", + }) + + if ipSuffix == "ip6" { + match = "nd || nd_ra || nd_rs" + checkAcl(parent, ovnnb.ACLDirectionFromLport, util.EgressAllowPriority, match, map[string]string{ + "apply-after-lb": "true", + }) + } + } } + + t.Run("add acl to pg", func(t *testing.T) { + t.Parallel() + + t.Run("gateway's protocol is dual", func(t *testing.T) { + t.Parallel() + + pgName := "test_create_gw_acl_pg_dual" + gateway := "10.244.0.1,fc00::0af4:01" + + err := ovnClient.CreatePortGroup(pgName, nil) + require.NoError(t, err) + + err = ovnClient.CreateGatewayAcl("", pgName, gateway) + require.NoError(t, err) + + pg, err := ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Len(t, pg.ACLs, 5) + + expect(pg, gateway) + }) + + t.Run("gateway's protocol is ipv4", func(t *testing.T) { + t.Parallel() + + pgName := "test_create_gw_acl_pg_v4" + gateway := "10.244.0.1" + + err := ovnClient.CreatePortGroup(pgName, nil) + require.NoError(t, err) + + err = ovnClient.CreateGatewayAcl("", pgName, gateway) + require.NoError(t, err) + + pg, err := ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Len(t, pg.ACLs, 2) + + expect(pg, gateway) + }) + + t.Run("gateway's protocol is ipv6", func(t *testing.T) { + t.Parallel() + + pgName := "test_create_gw_acl_pg_v6" + gateway := "fc00::0af4:01" + + err := ovnClient.CreatePortGroup(pgName, nil) + require.NoError(t, err) + + err = ovnClient.CreateGatewayAcl("", pgName, gateway) + require.NoError(t, err) + + pg, err := ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Len(t, pg.ACLs, 3) + + expect(pg, gateway) + }) + }) + + t.Run("add acl to ls", func(t *testing.T) { + t.Parallel() + + t.Run("gateway's protocol is dual", func(t *testing.T) { + t.Parallel() + + lsName := "test_create_gw_acl_ls_dual" + gateway := "10.244.0.1,fc00::0af4:01" + + err := ovnClient.CreateBareLogicalSwitch(lsName) + require.NoError(t, err) + + err = ovnClient.CreateGatewayAcl(lsName, "", gateway) + require.NoError(t, err) + + ls, err := ovnClient.GetLogicalSwitch(lsName, false) + require.NoError(t, err) + require.Len(t, ls.ACLs, 5) + + expect(ls, gateway) + }) + }) + + t.Run("has no pg name and ls name", func(t *testing.T) { + t.Parallel() + err := ovnClient.CreateGatewayAcl("", "", "") + require.EqualError(t, err, "one of port group name and logical switch name must be specified") + }) } func (suite *OvnClientTestSuite) testCreateNodeAcl() { @@ -309,43 +357,52 @@ func (suite *OvnClientTestSuite) testCreateNodeAcl() { ovnClient := suite.ovnClient pgName := "test_create_node_acl_pg" - nodeIp := "100.64.0.2,fd00:100:64::2" + nodeIp := "192.168.20.3" + joinIp := "100.64.0.2,fd00:100:64::2" + + checkAcl := func(pg *ovnnb.PortGroup, direction, priority, match string, options map[string]string) { + acl, err := ovnClient.GetAcl(pg.Name, direction, priority, match, false) + require.NoError(t, err) + expect := newAcl(pg.Name, direction, priority, match, ovnnb.ACLActionAllowRelated) + expect.UUID = acl.UUID + if len(options) != 0 { + expect.Options = options + } + require.Equal(t, expect, acl) + require.Contains(t, pg.ACLs, acl.UUID) + } + + expect := func(pg *ovnnb.PortGroup, gateway string) { + for _, ip := range strings.Split(nodeIp, ",") { + protocol := util.CheckProtocol(ip) + ipSuffix := "ip4" + if protocol == kubeovnv1.ProtocolIPv6 { + ipSuffix = "ip6" + } + + pgAs := fmt.Sprintf("%s_%s", pgName, ipSuffix) + + match := fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, ip, ipSuffix, pgAs) + checkAcl(pg, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, match, nil) + + match = fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, ip, ipSuffix, pgAs) + checkAcl(pg, ovnnb.ACLDirectionFromLport, util.NodeAllowPriority, match, map[string]string{ + "apply-after-lb": "true", + }) + } + } err := ovnClient.CreatePortGroup(pgName, nil) require.NoError(t, err) - err = ovnClient.CreateNodeAcl(pgName, nodeIp) + err = ovnClient.CreateNodeAcl(pgName, nodeIp, joinIp) require.NoError(t, err) pg, err := ovnClient.GetPortGroup(pgName, false) require.NoError(t, err) - require.Len(t, pg.ACLs, 4) + require.Len(t, pg.ACLs, 2) - for _, ip := range strings.Split(nodeIp, ",") { - protocol := util.CheckProtocol(ip) - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } - - pgAs := fmt.Sprintf("%s_%s", pgName, ipSuffix) - - match := fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, ip, ipSuffix, pgAs) - allowIngressAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, match, false) - require.NoError(t, err) - expect := newAcl(pgName, ovnnb.ACLDirectionToLport, util.NodeAllowPriority, match, ovnnb.ACLActionAllowRelated) - expect.UUID = allowIngressAcl.UUID - require.Equal(t, expect, allowIngressAcl) - require.Contains(t, pg.ACLs, allowIngressAcl.UUID) - - match = fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, ip, ipSuffix, pgAs) - allowEgressAcl, err := ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.NodeAllowPriority, match, false) - require.NoError(t, err) - expect = newAcl(pgName, ovnnb.ACLDirectionFromLport, util.NodeAllowPriority, match, ovnnb.ACLActionAllowRelated) - expect.UUID = allowEgressAcl.UUID - require.Equal(t, expect, allowEgressAcl) - require.Contains(t, pg.ACLs, allowEgressAcl.UUID) - } + expect(pg, nodeIp) } func (suite *OvnClientTestSuite) testCreateSgDenyAllAcl() { @@ -384,6 +441,96 @@ func (suite *OvnClientTestSuite) testCreateSgDenyAllAcl() { require.Contains(t, pg.ACLs, egressAcl.UUID) } +func (suite *OvnClientTestSuite) testCreateSgBaseACL() { + t := suite.T() + t.Parallel() + + ovnClient := suite.ovnClient + + expect := func(pg *ovnnb.PortGroup, match string) { + arpAcl, err := ovnClient.GetAcl(pg.Name, ovnnb.ACLDirectionToLport, util.SecurityGroupBasePriority, match, false) + require.NoError(t, err) + + expect := newAcl(pg.Name, ovnnb.ACLDirectionToLport, util.SecurityGroupBasePriority, match, ovnnb.ACLActionAllowRelated, func(acl *ovnnb.ACL) { + acl.UUID = arpAcl.UUID + }) + + require.Equal(t, expect, arpAcl) + require.Contains(t, pg.ACLs, arpAcl.UUID) + } + + t.Run("create sg base ingress acl", func(t *testing.T) { + t.Parallel() + + sgName := "test_create_sg_base_ingress_acl" + pgName := GetSgPortGroupName(sgName) + portDirection := "outport" + + err := ovnClient.CreatePortGroup(pgName, nil) + require.NoError(t, err) + + // ingress + err = ovnClient.CreateSgBaseACL(sgName, ovnnb.ACLDirectionToLport) + require.NoError(t, err) + + pg, err := ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Len(t, pg.ACLs, 4) + + // arp + match := fmt.Sprintf("%s == @%s && arp", portDirection, pgName) + expect(pg, match) + + // icmpv6 + match = fmt.Sprintf("%s == @%s && icmp6.type == {130, 134, 135, 136} && icmp6.code == 0 && ip.ttl == 255", portDirection, pgName) + expect(pg, match) + + // dhcpv4 + match = fmt.Sprintf("%s == @%s && udp.src == 67 && udp.dst == 68 && ip4", portDirection, pgName) + expect(pg, match) + + // dhcpv6 + match = fmt.Sprintf("%s == @%s && udp.src == 547 && udp.dst == 546 && ip6", portDirection, pgName) + expect(pg, match) + }) + + t.Run("create sg base egress acl", func(t *testing.T) { + t.Parallel() + + sgName := "test_create_sg_base_egress_acl" + pgName := GetSgPortGroupName(sgName) + portDirection := "inport" + + err := ovnClient.CreatePortGroup(pgName, nil) + require.NoError(t, err) + + // egress + err = ovnClient.CreateSgBaseACL(sgName, ovnnb.ACLDirectionFromLport) + require.NoError(t, err) + + pg, err := ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Len(t, pg.ACLs, 4) + + // arp + match := fmt.Sprintf("%s == @%s && arp", portDirection, pgName) + expect(pg, match) + + // icmpv6 + match = fmt.Sprintf("%s == @%s && icmp6.type == {130, 134, 135, 136} && icmp6.code == 0 && ip.ttl == 255", portDirection, pgName) + expect(pg, match) + + // dhcpv4 + match = fmt.Sprintf("%s == @%s && udp.src == 68 && udp.dst == 67 && ip4", portDirection, pgName) + expect(pg, match) + + // dhcpv6 + match = fmt.Sprintf("%s == @%s && udp.src == 546 && udp.dst == 547 && ip6", portDirection, pgName) + expect(pg, match) + }) + +} + func (suite *OvnClientTestSuite) testUpdateSgAcl() { t := suite.T() t.Parallel() @@ -533,6 +680,7 @@ func (suite *OvnClientTestSuite) testUpdateLogicalSwitchAcl() { require.NoError(t, err) expect := newAcl(lsName, subnetAcl.Direction, strconv.Itoa(subnetAcl.Priority), subnetAcl.Match, subnetAcl.Action) expect.UUID = acl.UUID + expect.ExternalIDs["subnet"] = lsName require.Equal(t, expect, acl) require.Contains(t, ls.ACLs, acl.UUID) } @@ -549,7 +697,7 @@ func (suite *OvnClientTestSuite) testSetAclLog() { require.NoError(t, err) t.Run("set ingress acl log to false", func(t *testing.T) { - match := fmt.Sprintf("outport == @%s && ip", pgName) + match := fmt.Sprintf("outport == @%s && ip4", pgName) acl := newAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, match, ovnnb.ACLActionDrop, func(acl *ovnnb.ACL) { acl.Name = &pgName acl.Log = true @@ -559,7 +707,7 @@ func (suite *OvnClientTestSuite) testSetAclLog() { err = ovnClient.CreateAcls(pgName, portGroupKey, acl) require.NoError(t, err) - err = ovnClient.SetAclLog(pgName, false, true) + err = ovnClient.SetAclLog(pgName, kubeovnv1.ProtocolIPv4, false, true) require.NoError(t, err) acl, err = ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, util.IngressDefaultDrop, match, false) @@ -568,7 +716,7 @@ func (suite *OvnClientTestSuite) testSetAclLog() { }) t.Run("set egress acl log to false", func(t *testing.T) { - match := fmt.Sprintf("inport == @%s && ip", pgName) + match := fmt.Sprintf("inport == @%s && ip4", pgName) acl := newAcl(pgName, ovnnb.ACLDirectionFromLport, util.IngressDefaultDrop, match, ovnnb.ACLActionDrop, func(acl *ovnnb.ACL) { acl.Name = &pgName acl.Log = false @@ -578,7 +726,7 @@ func (suite *OvnClientTestSuite) testSetAclLog() { err = ovnClient.CreateAcls(pgName, portGroupKey, acl) require.NoError(t, err) - err = ovnClient.SetAclLog(pgName, true, false) + err = ovnClient.SetAclLog(pgName, kubeovnv1.ProtocolIPv4, true, false) require.NoError(t, err) acl, err = ovnClient.GetAcl(pgName, ovnnb.ACLDirectionFromLport, util.IngressDefaultDrop, match, false) @@ -593,7 +741,7 @@ func (suite *OvnClientTestSuite) testSetLogicalSwitchPrivate() { t.Parallel() ovnClient := suite.ovnClient - lsName := "test_set_private_ls" + cidrBlock := "10.244.0.0/16,fc00::af4:0/112" allowSubnets := []string{ "10.230.0.0/16", @@ -603,10 +751,13 @@ func (suite *OvnClientTestSuite) testSetLogicalSwitchPrivate() { } direction := ovnnb.ACLDirectionToLport - err := ovnClient.CreateBareLogicalSwitch(lsName) - require.NoError(t, err) - t.Run("subnet protocol is dual", func(t *testing.T) { + t.Parallel() + + lsName := "test_set_private_ls_dual" + err := ovnClient.CreateBareLogicalSwitch(lsName) + require.NoError(t, err) + err = ovnClient.SetLogicalSwitchPrivate(lsName, cidrBlock, allowSubnets) require.NoError(t, err) @@ -669,6 +820,12 @@ func (suite *OvnClientTestSuite) testSetLogicalSwitchPrivate() { }) t.Run("subnet protocol is ipv4", func(t *testing.T) { + t.Parallel() + + lsName := "test_set_private_ls_v4" + err := ovnClient.CreateBareLogicalSwitch(lsName) + require.NoError(t, err) + cidrBlock := "10.244.0.0/16" err = ovnClient.SetLogicalSwitchPrivate(lsName, cidrBlock, allowSubnets) require.NoError(t, err) @@ -761,7 +918,7 @@ func (suite *OvnClientTestSuite) test_newSgRuleACL() { acl, err := ovnClient.newSgRuleACL(sgName, ovnnb.ACLDirectionToLport, sgRule) require.NoError(t, err) - match := fmt.Sprintf("outport == @%s && ip4 && ip4.src == $%s && icmp4", pgName, sgRule.RemoteSecurityGroup) + match := fmt.Sprintf("outport == @%s && ip4 && ip4.src == $%s && icmp4", pgName, GetSgV4AssociatedName(sgRule.RemoteSecurityGroup)) expect := newAcl(pgName, ovnnb.ACLDirectionToLport, priority, match, ovnnb.ACLActionAllowRelated) expect.UUID = acl.UUID require.Equal(t, expect, acl) @@ -998,7 +1155,7 @@ func (suite *OvnClientTestSuite) testDeleteAcls() { require.NoError(t, err) require.Len(t, pg.ACLs, 5) - err = ovnClient.DeleteAcls(pgName, portGroupKey, "") + err = ovnClient.DeleteAcls(pgName, portGroupKey, "", nil) require.NoError(t, err) pg, err = ovnClient.GetPortGroup(pgName, false) @@ -1035,7 +1192,7 @@ func (suite *OvnClientTestSuite) testDeleteAcls() { require.Len(t, pg.ACLs, 5) /* delete to-lport direction acl */ - err = ovnClient.DeleteAcls(pgName, portGroupKey, ovnnb.ACLDirectionToLport) + err = ovnClient.DeleteAcls(pgName, portGroupKey, ovnnb.ACLDirectionToLport, nil) require.NoError(t, err) pg, err = ovnClient.GetPortGroup(pgName, false) @@ -1043,7 +1200,7 @@ func (suite *OvnClientTestSuite) testDeleteAcls() { require.Len(t, pg.ACLs, 3) /* delete from-lport direction acl */ - err = ovnClient.DeleteAcls(pgName, portGroupKey, ovnnb.ACLDirectionFromLport) + err = ovnClient.DeleteAcls(pgName, portGroupKey, ovnnb.ACLDirectionFromLport, nil) require.NoError(t, err) pg, err = ovnClient.GetPortGroup(pgName, false) @@ -1079,7 +1236,7 @@ func (suite *OvnClientTestSuite) testDeleteAcls() { require.NoError(t, err) require.Len(t, ls.ACLs, 5) - err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, "") + err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, "", nil) require.NoError(t, err) ls, err = ovnClient.GetLogicalSwitch(lsName, false) @@ -1116,7 +1273,7 @@ func (suite *OvnClientTestSuite) testDeleteAcls() { require.Len(t, ls.ACLs, 5) /* delete to-lport direction acl */ - err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, ovnnb.ACLDirectionToLport) + err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, ovnnb.ACLDirectionToLport, nil) require.NoError(t, err) ls, err = ovnClient.GetLogicalSwitch(lsName, false) @@ -1124,7 +1281,106 @@ func (suite *OvnClientTestSuite) testDeleteAcls() { require.Len(t, ls.ACLs, 3) /* delete from-lport direction acl */ - err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, ovnnb.ACLDirectionFromLport) + err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, ovnnb.ACLDirectionFromLport, nil) + require.NoError(t, err) + + ls, err = ovnClient.GetLogicalSwitch(lsName, false) + require.NoError(t, err) + require.Empty(t, ls.ACLs) + }) + + t.Run("delete acls with additional external ids", func(t *testing.T) { + priority := "5801" + basePort := 5801 + acls := make([]*ovnnb.ACL, 0, 5) + + // to-lport + + match := fmt.Sprintf("%s && udp.dst == %d", matchPrefix, basePort) + acl, err := ovnClient.newAcl(lsName, ovnnb.ACLDirectionToLport, priority, match, ovnnb.ACLActionAllowRelated, func(acl *ovnnb.ACL) { + if acl.ExternalIDs == nil { + acl.ExternalIDs = make(map[string]string) + } + acl.ExternalIDs["subnet"] = lsName + }) + require.NoError(t, err) + acls = append(acls, acl) + + err = ovnClient.CreateAcls(lsName, logicalSwitchKey, acls...) + require.NoError(t, err) + + ls, err := ovnClient.GetLogicalSwitch(lsName, false) + require.NoError(t, err) + require.Len(t, ls.ACLs, 1) + + newAcl := &ovnnb.ACL{UUID: ls.ACLs[0]} + err = ovnClient.GetEntityInfo(newAcl) + require.NoError(t, err) + + /* delete to-lport direction acl */ + err = ovnClient.DeleteAcls(lsName, logicalSwitchKey, ovnnb.ACLDirectionToLport, map[string]string{"subnet": lsName}) + require.NoError(t, err) + + ls, err = ovnClient.GetLogicalSwitch(lsName, false) + require.NoError(t, err) + require.Empty(t, ls.ACLs) + }) +} + +func (suite *OvnClientTestSuite) testDeleteAcl() { + t := suite.T() + t.Parallel() + + ovnClient := suite.ovnClient + pgName := "test-del-acl-pg" + lsName := "test-del-acl-ls" + matchPrefix := "outport == @ovn.sg.test_del_acl_pg && ip" + + err := ovnClient.CreatePortGroup(pgName, nil) + require.NoError(t, err) + + err = ovnClient.CreateBareLogicalSwitch(lsName) + require.NoError(t, err) + + t.Run("delete acl from port group", func(t *testing.T) { + priority := "5601" + basePort := 5601 + + match := fmt.Sprintf("%s && tcp.dst == %d", matchPrefix, basePort) + acl, err := ovnClient.newAcl(pgName, ovnnb.ACLDirectionToLport, priority, match, ovnnb.ACLActionAllowRelated) + require.NoError(t, err) + + err = ovnClient.CreateAcls(pgName, portGroupKey, acl) + require.NoError(t, err) + + pg, err := ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Len(t, pg.ACLs, 1) + + err = ovnClient.DeleteAcl(pgName, portGroupKey, ovnnb.ACLDirectionToLport, priority, match) + require.NoError(t, err) + + pg, err = ovnClient.GetPortGroup(pgName, false) + require.NoError(t, err) + require.Empty(t, pg.ACLs) + }) + + t.Run("delete all direction acls from logical switch", func(t *testing.T) { + priority := "5601" + basePort := 5601 + + match := fmt.Sprintf("%s && tcp.dst == %d", matchPrefix, basePort) + acl, err := ovnClient.newAcl(lsName, ovnnb.ACLDirectionToLport, priority, match, ovnnb.ACLActionAllowRelated) + require.NoError(t, err) + + err = ovnClient.CreateAcls(lsName, logicalSwitchKey, acl) + require.NoError(t, err) + + ls, err := ovnClient.GetLogicalSwitch(lsName, false) + require.NoError(t, err) + require.Len(t, ls.ACLs, 1) + + err = ovnClient.DeleteAcl(lsName, logicalSwitchKey, ovnnb.ACLDirectionToLport, priority, match) require.NoError(t, err) ls, err = ovnClient.GetLogicalSwitch(lsName, false) @@ -1263,7 +1519,7 @@ func (suite *OvnClientTestSuite) testnewNetworkPolicyAclMatch() { t.Parallel() npp := mockNetworkPolicyPort() - matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp, nil) require.ElementsMatch(t, []string{ fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[0].Port.IntVal), fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && %d <= tcp.dst <= %d", pgName, asAllowName, asExceptName, npp[1].Port.IntVal, *npp[1].EndPort), @@ -1275,7 +1531,7 @@ func (suite *OvnClientTestSuite) testnewNetworkPolicyAclMatch() { npp := mockNetworkPolicyPort() - matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionFromLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionFromLport, npp, nil) require.ElementsMatch(t, []string{ fmt.Sprintf("inport == @%s && ip && ip4.dst == $%s && ip4.dst != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[0].Port.IntVal), fmt.Sprintf("inport == @%s && ip && ip4.dst == $%s && ip4.dst != $%s && %d <= tcp.dst <= %d", pgName, asAllowName, asExceptName, npp[1].Port.IntVal, *npp[1].EndPort), @@ -1285,7 +1541,7 @@ func (suite *OvnClientTestSuite) testnewNetworkPolicyAclMatch() { t.Run("network policy port is nil", func(t *testing.T) { t.Parallel() - matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, nil) + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, nil, nil) require.ElementsMatch(t, []string{ fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s", pgName, asAllowName, asExceptName), }, matches) @@ -1297,7 +1553,7 @@ func (suite *OvnClientTestSuite) testnewNetworkPolicyAclMatch() { npp := mockNetworkPolicyPort() npp[1].Port = nil - matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp) + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp, nil) require.ElementsMatch(t, []string{ fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[0].Port.IntVal), fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp", pgName, asAllowName, asExceptName), @@ -1307,14 +1563,65 @@ func (suite *OvnClientTestSuite) testnewNetworkPolicyAclMatch() { t.Run("has network policy port but endPort is not set", func(t *testing.T) { t.Parallel() - npp := mockNetworkPolicyPort() - npp[1].EndPort = nil + t.Run("port type is Int", func(t *testing.T) { + t.Parallel() + npp := mockNetworkPolicyPort() + npp[1].EndPort = nil - matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp) - require.ElementsMatch(t, []string{ - fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[0].Port.IntVal), - fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[1].Port.IntVal), - }, matches) + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp, nil) + require.ElementsMatch(t, []string{ + fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[0].Port.IntVal), + fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, npp[1].Port.IntVal), + }, matches) + }) + + t.Run("port type is String", func(t *testing.T) { + t.Parallel() + protocolTcp := v1.ProtocolTCP + npp := []netv1.NetworkPolicyPort{ + { + Port: &intstr.IntOrString{ + Type: intstr.String, + StrVal: "test-pod-port", + }, + Protocol: &protocolTcp, + }, + } + + namedPortMap := map[string]*util.NamedPortInfo{ + "test-pod-port": { + PortId: 13455, + }, + } + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp, namedPortMap) + require.ElementsMatch(t, []string{ + fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, 13455), + }, matches) + }) + + t.Run("port type is String and not find named port", func(t *testing.T) { + t.Parallel() + protocolTcp := v1.ProtocolTCP + npp := []netv1.NetworkPolicyPort{ + { + Port: &intstr.IntOrString{ + Type: intstr.String, + StrVal: "test-pod-port-x", + }, + Protocol: &protocolTcp, + }, + } + + namedPortMap := map[string]*util.NamedPortInfo{ + "test-pod-port": { + PortId: 13455, + }, + } + matches := newNetworkPolicyAclMatch(pgName, asAllowName, asExceptName, kubeovnv1.ProtocolIPv4, ovnnb.ACLDirectionToLport, npp, namedPortMap) + require.ElementsMatch(t, []string{ + fmt.Sprintf("outport == @%s && ip && ip4.src == $%s && ip4.src != $%s && tcp.dst == %d", pgName, asAllowName, asExceptName, 0), + }, matches) + }) }) } diff --git a/pkg/ovs/ovn-nb-address_set.go b/pkg/ovs/ovn-nb-address_set.go index a3881fe08ab..d506714f581 100644 --- a/pkg/ovs/ovn-nb-address_set.go +++ b/pkg/ovs/ovn-nb-address_set.go @@ -3,10 +3,14 @@ package ovs import ( "context" "fmt" + "net" + "strings" "github.com/ovn-org/libovsdb/client" + "k8s.io/klog/v2" "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb" + "github.com/kubeovn/kube-ovn/pkg/util" ) // CreateAddressSet create address set with external ids @@ -51,6 +55,20 @@ func (c *ovnClient) AddressSetUpdateAddress(asName string, addresses ...string) return fmt.Errorf("get address set %s: %v", asName, err) } + // update will failed when slice contains duplicate elements + addresses = util.UniqString(addresses) + + // format CIDR to keep addresses the same in both nb and sb + for i, addr := range addresses { + if strings.ContainsRune(addr, '/') { + _, ipNet, err := net.ParseCIDR(addr) + if err != nil { + klog.Warningf("failed to parse CIDR %q: %v", addr, err) + continue + } + addresses[i] = ipNet.String() + } + } // clear addresses when addresses is empty as.Addresses = addresses diff --git a/pkg/ovs/ovn-nb-suite_test.go b/pkg/ovs/ovn-nb-suite_test.go index a05cff40d52..e6b4e543107 100644 --- a/pkg/ovs/ovn-nb-suite_test.go +++ b/pkg/ovs/ovn-nb-suite_test.go @@ -397,12 +397,12 @@ func (suite *OvnClientTestSuite) Test_addressSetFilter() { } /* acl unit test */ -func (suite *OvnClientTestSuite) Test_CreateIngressAcl() { - suite.testCreateIngressAcl() +func (suite *OvnClientTestSuite) Test_testUpdateIngressAclOps() { + suite.testUpdateIngressAclOps() } -func (suite *OvnClientTestSuite) Test_CreateEgressAcl() { - suite.testCreateEgressAcl() +func (suite *OvnClientTestSuite) Test_UpdateEgressAclOps() { + suite.testUpdateEgressAclOps() } func (suite *OvnClientTestSuite) Test_CreateGatewayAcl() { @@ -417,6 +417,10 @@ func (suite *OvnClientTestSuite) Test_CreateSgDenyAllAcl() { suite.testCreateSgDenyAllAcl() } +func (suite *OvnClientTestSuite) Test_CreateSgBaseACL() { + suite.testCreateSgBaseACL() +} + func (suite *OvnClientTestSuite) Test_UpdateSgAcl() { suite.testUpdateSgAcl() } @@ -445,6 +449,10 @@ func (suite *OvnClientTestSuite) Test_DeleteAcls() { suite.testDeleteAcls() } +func (suite *OvnClientTestSuite) Test_DeleteAcl() { + suite.testDeleteAcl() +} + func (suite *OvnClientTestSuite) Test_GetAcl() { suite.testGetAcl() } @@ -624,22 +632,7 @@ func Test_scratch(t *testing.T) { ovnClient, err := newOvnClient(t, endpoint, 10, "") require.NoError(t, err) - lbName := "test-lb" - err = ovnClient.CreateLoadBalancer(lbName, "tcp", "ip_src") - require.NoError(t, err) - - vips := map[string]string{ - "10.96.0.1:443": "192.168.20.11:6443", - "10.107.43.237:8080": "10.244.0.100:8080,10.244.0.16:8080,10.244.0.17:8080", - "[fd00:10:96::e82f]:8080": "[fc00::af4:f]:8080,[fc00::af4:10]:8080,[fc00::af4:11]:8080", - } - - for vip, backends := range vips { - err = ovnClient.LoadBalancerAddVip(lbName, vip, strings.Split(backends, ",")...) - require.NoError(t, err) - } - - err = ovnClient.LoadBalancerDeleteVip(lbName, "10.96.0.1:443") + err = ovnClient.DeleteAcls("test_pg", portGroupKey, ovnnb.ACLDirectionToLport, nil) require.NoError(t, err) } diff --git a/pkg/ovs/ovn-nb.go b/pkg/ovs/ovn-nb.go index 77e6c1758ce..f2cdf189b6e 100644 --- a/pkg/ovs/ovn-nb.go +++ b/pkg/ovs/ovn-nb.go @@ -101,7 +101,7 @@ func (c *ovnClient) DeleteSecurityGroup(sgName string) error { pgName := GetSgPortGroupName(sgName) // clear acl - if err := c.DeleteAcls(pgName, portGroupKey, ""); err != nil { + if err := c.DeleteAcls(pgName, portGroupKey, "", nil); err != nil { return fmt.Errorf("delete acls from port group %s: %v", pgName, err) } diff --git a/pkg/ovs/ovn-nb_test.go b/pkg/ovs/ovn-nb_test.go index 942e8e4ee2e..a8878dfebc3 100644 --- a/pkg/ovs/ovn-nb_test.go +++ b/pkg/ovs/ovn-nb_test.go @@ -202,9 +202,6 @@ func (suite *OvnClientTestSuite) testDeleteSecurityGroup() { err = ovnClient.DeleteSecurityGroup(sgName) require.NoError(t, err) - _, err = ovnClient.GetAcl(pgName, ovnnb.ACLDirectionToLport, priority, match, false) - require.ErrorContains(t, err, "not found acl") - _, err = ovnClient.GetAddressSet(asName, false) require.ErrorContains(t, err, "object not found") diff --git a/pkg/ovs/ovn-nbctl-legacy.go b/pkg/ovs/ovn-nbctl-legacy.go index 40339cb1fb2..685f6b9d75a 100644 --- a/pkg/ovs/ovn-nbctl-legacy.go +++ b/pkg/ovs/ovn-nbctl-legacy.go @@ -13,19 +13,10 @@ import ( "time" "golang.org/x/exp/slices" - netv1 "k8s.io/api/networking/v1" "k8s.io/klog/v2" kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1" "github.com/kubeovn/kube-ovn/pkg/util" - "k8s.io/apimachinery/pkg/util/intstr" -) - -type AclDirection string - -const ( - SgAclIngressDirection AclDirection = "to-lport" - SgAclEgressDirection AclDirection = "from-lport" ) var nbctlDaemonSocketRegexp = regexp.MustCompile(`^/var/run/ovn/ovn-nbctl\.[0-9]+\.ctl$`) @@ -671,412 +662,6 @@ func (c LegacyClient) DeleteStaticRouteByNextHop(nextHop string) error { return nil } -// CleanLogicalSwitchAcl clean acl of a switch -func (c LegacyClient) CleanLogicalSwitchAcl(ls string) error { - _, err := c.ovnNbCommand("acl-del", ls) - return err -} - -// ResetLogicalSwitchAcl reset acl of a switch -func (c LegacyClient) ResetLogicalSwitchAcl(ls string) error { - _, err := c.ovnNbCommand("acl-del", ls) - return err -} - -// SetPrivateLogicalSwitch will drop all ingress traffic except allow subnets -func (c LegacyClient) SetPrivateLogicalSwitch(ls, cidr string, allow []string) error { - ovnArgs := []string{"acl-del", ls} - trimName := ls - if len(ls) > 63 { - trimName = ls[:63] - } - dropArgs := []string{"--", "--log", fmt.Sprintf("--name=%s", trimName), fmt.Sprintf("--severity=%s", "warning"), "acl-add", ls, "to-lport", util.DefaultDropPriority, "ip", "drop"} - ovnArgs = append(ovnArgs, dropArgs...) - - for _, cidrBlock := range strings.Split(cidr, ",") { - allowArgs := []string{} - protocol := util.CheckProtocol(cidrBlock) - if protocol == kubeovnv1.ProtocolIPv4 { - allowArgs = append(allowArgs, "--", MayExist, "acl-add", ls, "to-lport", util.SubnetAllowPriority, fmt.Sprintf(`ip4.src==%s && ip4.dst==%s`, cidrBlock, cidrBlock), "allow-related") - } else if protocol == kubeovnv1.ProtocolIPv6 { - allowArgs = append(allowArgs, "--", MayExist, "acl-add", ls, "to-lport", util.SubnetAllowPriority, fmt.Sprintf(`ip6.src==%s && ip6.dst==%s`, cidrBlock, cidrBlock), "allow-related") - } else { - klog.Errorf("the cidrBlock: %s format is error in subnet: %s", cidrBlock, ls) - continue - } - - for _, nodeCidrBlock := range strings.Split(c.NodeSwitchCIDR, ",") { - if protocol != util.CheckProtocol(nodeCidrBlock) { - continue - } - - if protocol == kubeovnv1.ProtocolIPv4 { - allowArgs = append(allowArgs, "--", MayExist, "acl-add", ls, "to-lport", util.NodeAllowPriority, fmt.Sprintf("ip4.src==%s", nodeCidrBlock), "allow-related") - } else if protocol == kubeovnv1.ProtocolIPv6 { - allowArgs = append(allowArgs, "--", MayExist, "acl-add", ls, "to-lport", util.NodeAllowPriority, fmt.Sprintf("ip6.src==%s", nodeCidrBlock), "allow-related") - } - } - - for _, subnet := range allow { - if strings.TrimSpace(subnet) != "" { - allowProtocol := util.CheckProtocol(strings.TrimSpace(subnet)) - if allowProtocol != protocol { - continue - } - - var match string - switch protocol { - case kubeovnv1.ProtocolIPv4: - match = fmt.Sprintf("(ip4.src==%s && ip4.dst==%s) || (ip4.src==%s && ip4.dst==%s)", strings.TrimSpace(subnet), cidrBlock, cidrBlock, strings.TrimSpace(subnet)) - case kubeovnv1.ProtocolIPv6: - match = fmt.Sprintf("(ip6.src==%s && ip6.dst==%s) || (ip6.src==%s && ip6.dst==%s)", strings.TrimSpace(subnet), cidrBlock, cidrBlock, strings.TrimSpace(subnet)) - } - - allowArgs = append(allowArgs, "--", MayExist, "acl-add", ls, "to-lport", util.SubnetAllowPriority, match, "allow-related") - } - } - ovnArgs = append(ovnArgs, allowArgs...) - } - _, err := c.ovnNbCommand(ovnArgs...) - return err -} - -func (c LegacyClient) CreateAddressSet(name string) error { - output, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=_uuid", "find", "address_set", fmt.Sprintf("name=%s", name)) - if err != nil { - klog.Errorf("failed to find address_set %s: %v, %q", name, err, output) - return err - } - if output != "" { - return nil - } - _, err = c.ovnNbCommand("create", "address_set", fmt.Sprintf("name=%s", name), fmt.Sprintf("external_ids:vendor=%s", util.CniTypeName)) - return err -} - -func (c LegacyClient) CreateAddressSetWithAddresses(name string, addresses ...string) error { - output, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=_uuid", "find", "address_set", fmt.Sprintf("name=%s", name)) - if err != nil { - klog.Errorf("failed to find address_set %s: %v, %q", name, err, output) - return err - } - - var args []string - argAddrs := strings.ReplaceAll(strings.Join(addresses, ","), ":", `\:`) - if output == "" { - args = []string{"create", "address_set", fmt.Sprintf("name=%s", name), fmt.Sprintf("external_ids:vendor=%s", util.CniTypeName)} - if argAddrs != "" { - args = append(args, fmt.Sprintf("addresses=%s", argAddrs)) - } - } else { - args = []string{"clear", "address_set", name, "addresses"} - if argAddrs != "" { - args = append(args, "--", "set", "address_set", name, "addresses", argAddrs) - } - } - - _, err = c.ovnNbCommand(args...) - return err -} - -func (c LegacyClient) AddAddressSetAddresses(name string, address string) error { - output, err := c.ovnNbCommand("add", "address_set", name, "addresses", strings.ReplaceAll(address, ":", `\:`)) - if err != nil { - klog.Errorf("failed to add address %s to address_set %s: %v, %q", address, name, err, output) - return err - } - return nil -} - -func (c LegacyClient) RemoveAddressSetAddresses(name string, address string) error { - output, err := c.ovnNbCommand("remove", "address_set", name, "addresses", strings.ReplaceAll(address, ":", `\:`)) - if err != nil { - klog.Errorf("failed to remove address %s from address_set %s: %v, %q", address, name, err, output) - return err - } - return nil -} - -func (c LegacyClient) DeleteAddressSet(name string) error { - _, err := c.ovnNbCommand(IfExists, "destroy", "address_set", name) - return err -} - -func (c LegacyClient) ListNpAddressSet(npNamespace, npName, direction string) ([]string, error) { - output, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=name", "find", "address_set", fmt.Sprintf("external_ids:np=%s/%s/%s", npNamespace, npName, direction)) - if err != nil { - klog.Errorf("failed to list address_set of %s/%s/%s: %v, %q", npNamespace, npName, direction, err, output) - return nil, err - } - return strings.Split(output, "\n"), nil -} - -func (c LegacyClient) ListAddressesByName(addressSetName string) ([]string, error) { - output, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=addresses", "find", "address_set", fmt.Sprintf("name=%s", addressSetName)) - if err != nil { - klog.Errorf("failed to list address_set of %s, error %v", addressSetName, err) - return nil, err - } - - lines := strings.Split(output, "\n") - result := make([]string, 0, len(lines)) - for _, l := range lines { - if len(strings.TrimSpace(l)) == 0 { - continue - } - result = append(result, strings.Fields(l)...) - } - return result, nil -} - -func (c LegacyClient) CreateNpAddressSet(asName, npNamespace, npName, direction string) error { - output, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=_uuid", "find", "address_set", fmt.Sprintf("name=%s", asName)) - if err != nil { - klog.Errorf("failed to find address_set %s: %v, %q", asName, err, output) - return err - } - if output != "" { - return nil - } - _, err = c.ovnNbCommand("create", "address_set", fmt.Sprintf("name=%s", asName), fmt.Sprintf("external_ids:np=%s/%s/%s", npNamespace, npName, direction)) - return err -} - -func (c LegacyClient) CombineIngressACLCmd(pgName, asIngressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort, logEnable bool, aclCmds []string, index int, namedPortMap map[string]*util.NamedPortInfo) []string { - var allowArgs, ovnArgs []string - - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } - id := pgName + "_" + ipSuffix - - if logEnable { - ovnArgs = []string{"--", fmt.Sprintf("--id=@%s.drop.%d", id, index), "create", "acl", "action=drop", "direction=to-lport", "log=true", "severity=warning", fmt.Sprintf("priority=%s", util.IngressDefaultDrop), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("outport==@%s && ip", pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.drop.%d", id, index)} - } else { - ovnArgs = []string{"--", fmt.Sprintf("--id=@%s.drop.%d", id, index), "create", "acl", "action=drop", "direction=to-lport", "log=false", fmt.Sprintf("priority=%s", util.IngressDefaultDrop), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("outport==@%s && ip", pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.drop.%d", id, index)} - } - - if len(npp) == 0 { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.noport.%d", id, index), "create", "acl", "action=allow-related", "direction=to-lport", fmt.Sprintf("priority=%s", util.IngressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.src == $%s && %s.src != $%s && outport==@%s && ip", ipSuffix, asIngressName, ipSuffix, asExceptName, pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.noport.%d", id, index)} - ovnArgs = append(ovnArgs, allowArgs...) - } else { - for pidx, port := range npp { - if port.Port != nil { - if port.EndPort != nil { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=to-lport", fmt.Sprintf("priority=%s", util.IngressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.src == $%s && %s.src != $%s && %d <= %s.dst <= %d && outport==@%s && ip", ipSuffix, asIngressName, ipSuffix, asExceptName, port.Port.IntVal, strings.ToLower(string(*port.Protocol)), *port.EndPort, pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } else { - if port.Port.Type == intstr.Int { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=to-lport", fmt.Sprintf("priority=%s", util.IngressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.src == $%s && %s.src != $%s && %s.dst == %d && outport==@%s && ip", ipSuffix, asIngressName, ipSuffix, asExceptName, strings.ToLower(string(*port.Protocol)), port.Port.IntVal, pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } else { - var portId int32 = 0 - if namedPortMap != nil { - _, ok := namedPortMap[port.Port.StrVal] - if !ok { - // for cyclonus network policy test case 'should allow ingress access on one named port' - // this case expect all-deny if no named port defined - klog.Errorf("no named port with name %s found ", port.Port.StrVal) - } else { - portId = namedPortMap[port.Port.StrVal].PortId - } - } - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=to-lport", fmt.Sprintf("priority=%s", util.IngressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.src == $%s && %s.src != $%s && %s.dst == %d && outport==@%s && ip", ipSuffix, asIngressName, ipSuffix, asExceptName, strings.ToLower(string(*port.Protocol)), portId, pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } - } - } else { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=to-lport", fmt.Sprintf("priority=%s", util.IngressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.src == $%s && %s.src != $%s && %s && outport==@%s && ip", ipSuffix, asIngressName, ipSuffix, asExceptName, strings.ToLower(string(*port.Protocol)), pgName)), "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } - ovnArgs = append(ovnArgs, allowArgs...) - } - } - aclCmds = append(aclCmds, ovnArgs...) - return aclCmds -} - -func (c LegacyClient) CreateACL(aclCmds []string) error { - _, err := c.ovnNbCommand(aclCmds...) - return err -} - -func (c LegacyClient) CombineEgressACLCmd(pgName, asEgressName, asExceptName, protocol string, npp []netv1.NetworkPolicyPort, logEnable bool, aclCmds []string, index int, namedPortMap map[string]*util.NamedPortInfo) []string { - var allowArgs, ovnArgs []string - - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } - id := pgName + "_" + ipSuffix - - if logEnable { - ovnArgs = []string{"--", fmt.Sprintf("--id=@%s.drop.%d", id, index), "create", "acl", "action=drop", "direction=from-lport", "log=true", "severity=warning", fmt.Sprintf("priority=%s", util.EgressDefaultDrop), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("inport==@%s && ip", pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.drop.%d", id, index)} - } else { - ovnArgs = []string{"--", fmt.Sprintf("--id=@%s.drop.%d", id, index), "create", "acl", "action=drop", "direction=from-lport", "log=false", fmt.Sprintf("priority=%s", util.EgressDefaultDrop), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("inport==@%s && ip", pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.drop.%d", id, index)} - } - - if len(npp) == 0 { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.noport.%d", id, index), "create", "acl", "action=allow-related", "direction=from-lport", fmt.Sprintf("priority=%s", util.EgressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.dst == $%s && %s.dst != $%s && inport==@%s && ip", ipSuffix, asEgressName, ipSuffix, asExceptName, pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.noport.%d", id, index)} - ovnArgs = append(ovnArgs, allowArgs...) - } else { - for pidx, port := range npp { - if port.Port != nil { - if port.EndPort != nil { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=from-lport", fmt.Sprintf("priority=%s", util.EgressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.dst == $%s && %s.dst != $%s && %d <= %s.dst <= %d && inport==@%s && ip", ipSuffix, asEgressName, ipSuffix, asExceptName, port.Port.IntVal, strings.ToLower(string(*port.Protocol)), *port.EndPort, pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } else { - if port.Port.Type == intstr.Int { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=from-lport", fmt.Sprintf("priority=%s", util.EgressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.dst == $%s && %s.dst != $%s && %s.dst == %d && inport==@%s && ip", ipSuffix, asEgressName, ipSuffix, asExceptName, strings.ToLower(string(*port.Protocol)), port.Port.IntVal, pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } else { - var portId int32 = 0 - if namedPortMap != nil { - _, ok := namedPortMap[port.Port.StrVal] - if !ok { - klog.Errorf("no named port with name %s found ", port.Port.StrVal) - } else { - portId = namedPortMap[port.Port.StrVal].PortId - } - } - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=from-lport", fmt.Sprintf("priority=%s", util.EgressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.dst == $%s && %s.dst != $%s && %s.dst == %d && inport==@%s && ip", ipSuffix, asEgressName, ipSuffix, asExceptName, strings.ToLower(string(*port.Protocol)), portId, pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } - } - } else { - allowArgs = []string{"--", fmt.Sprintf("--id=@%s.%d.port.%d", id, index, pidx), "create", "acl", "action=allow-related", "direction=from-lport", fmt.Sprintf("priority=%s", util.EgressAllowPriority), fmt.Sprintf("match=\"%s\"", fmt.Sprintf("%s.dst == $%s && %s.dst != $%s && %s && inport==@%s && ip", ipSuffix, asEgressName, ipSuffix, asExceptName, strings.ToLower(string(*port.Protocol)), pgName)), "options={apply-after-lb=\"true\"}", "--", "add", "port-group", pgName, "acls", fmt.Sprintf("@%s.%d.port.%d", id, index, pidx)} - } - ovnArgs = append(ovnArgs, allowArgs...) - } - } - aclCmds = append(aclCmds, ovnArgs...) - return aclCmds -} - -func (c LegacyClient) DeleteACL(pgName, direction string) (err error) { - if _, err := c.ovnNbCommand("get", "port_group", pgName, "_uuid"); err != nil { - if strings.Contains(err.Error(), "no row") { - return nil - } - klog.Errorf("failed to get pg %s, %v", pgName, err) - return err - } - - if direction != "" { - _, err = c.ovnNbCommand("--type=port-group", "acl-del", pgName, direction) - } else { - _, err = c.ovnNbCommand("--type=port-group", "acl-del", pgName) - } - return -} - -func (c LegacyClient) CreateGatewayACL(ls, pgName, gateway, cidr string) error { - for _, cidrBlock := range strings.Split(cidr, ",") { - for _, gw := range strings.Split(gateway, ",") { - if util.CheckProtocol(cidrBlock) != util.CheckProtocol(gw) { - continue - } - protocol := util.CheckProtocol(cidrBlock) - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } - - var ingressArgs, egressArgs []string - if pgName != "" { - ingressArgs = []string{"--", MayExist, "--type=port-group", "acl-add", pgName, "to-lport", util.IngressAllowPriority, fmt.Sprintf("%s.src == %s", ipSuffix, gw), "allow-related"} - egressArgs = []string{"--", MayExist, "--type=port-group", "--apply-after-lb", "acl-add", pgName, "from-lport", util.EgressAllowPriority, fmt.Sprintf("%s.dst == %s", ipSuffix, gw), "allow-related"} - if ipSuffix == "ip6" { - egressArgs = append(egressArgs, []string{"--", "--type=port-group", MayExist, "--apply-after-lb", "acl-add", pgName, "from-lport", util.EgressAllowPriority, `nd || nd_ra || nd_rs`, "allow-related"}...) - } - } else if ls != "" { - ingressArgs = []string{"--", MayExist, "acl-add", ls, "to-lport", util.IngressAllowPriority, fmt.Sprintf(`%s.src == %s`, ipSuffix, gw), "allow-stateless"} - egressArgs = []string{"--", MayExist, "--apply-after-lb", "acl-add", ls, "from-lport", util.EgressAllowPriority, fmt.Sprintf(`%s.dst == %s`, ipSuffix, gw), "allow-stateless"} - if ipSuffix == "ip6" { - egressArgs = append(egressArgs, []string{"--", MayExist, "--apply-after-lb", "acl-add", ls, "from-lport", util.EgressAllowPriority, `nd || nd_ra || nd_rs`, "allow-stateless"}...) - } - } - - ovnArgs := append(ingressArgs, egressArgs...) - if _, err := c.ovnNbCommand(ovnArgs...); err != nil { - return err - } - } - } - return nil -} - -func (c LegacyClient) CreateACLForNodePg(pgName, nodeIpStr, joinIpStr string) error { - nodeIPs := strings.Split(nodeIpStr, ",") - for _, nodeIp := range nodeIPs { - protocol := util.CheckProtocol(nodeIp) - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } - pgAs := fmt.Sprintf("%s_%s", pgName, ipSuffix) - - ingressArgs := []string{MayExist, "--type=port-group", "acl-add", pgName, "to-lport", util.NodeAllowPriority, fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, nodeIp, ipSuffix, pgAs), "allow-related"} - egressArgs := []string{"--", MayExist, "--type=port-group", "--apply-after-lb", "acl-add", pgName, "from-lport", util.NodeAllowPriority, fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, nodeIp, ipSuffix, pgAs), "allow-related"} - ovnArgs := append(ingressArgs, egressArgs...) - if _, err := c.ovnNbCommand(ovnArgs...); err != nil { - klog.Errorf("failed to add node port-group acl: %v", err) - return err - } - } - for _, joinIp := range strings.Split(joinIpStr, ",") { - if util.ContainsString(nodeIPs, joinIp) { - continue - } - - protocol := util.CheckProtocol(joinIp) - ipSuffix := "ip4" - if protocol == kubeovnv1.ProtocolIPv6 { - ipSuffix = "ip6" - } - pgAs := fmt.Sprintf("%s_%s", pgName, ipSuffix) - - ingressArgs := []string{"acl-del", pgName, "to-lport", util.NodeAllowPriority, fmt.Sprintf("%s.src == %s && %s.dst == $%s", ipSuffix, joinIp, ipSuffix, pgAs)} - egressArgs := []string{"--", "acl-del", pgName, "from-lport", util.NodeAllowPriority, fmt.Sprintf("%s.dst == %s && %s.src == $%s", ipSuffix, joinIp, ipSuffix, pgAs)} - ovnArgs := append(ingressArgs, egressArgs...) - if _, err := c.ovnNbCommand(ovnArgs...); err != nil { - klog.Errorf("failed to delete node port-group acl: %v", err) - return err - } - } - - return nil -} - -func (c LegacyClient) DeleteAclForNodePg(pgName string) error { - ingressArgs := []string{"acl-del", pgName, "to-lport"} - if _, err := c.ovnNbCommand(ingressArgs...); err != nil { - klog.Errorf("failed to delete node port-group ingress acl: %v", err) - return err - } - - egressArgs := []string{"acl-del", pgName, "from-lport"} - if _, err := c.ovnNbCommand(egressArgs...); err != nil { - klog.Errorf("failed to delete node port-group egress acl: %v", err) - return err - } - - return nil -} - -func (c LegacyClient) SetAddressesToAddressSet(addresses []string, as string) error { - ovnArgs := []string{"clear", "address_set", as, "addresses"} - if len(addresses) > 0 { - var newAddrs []string - for _, addr := range addresses { - if util.CheckProtocol(addr) == kubeovnv1.ProtocolIPv6 { - newAddr := strings.ReplaceAll(addr, ":", "\\:") - newAddrs = append(newAddrs, newAddr) - } else { - newAddrs = append(newAddrs, addr) - } - } - ovnArgs = append(ovnArgs, "--", "add", "address_set", as, "addresses") - ovnArgs = append(ovnArgs, newAddrs...) - } - _, err := c.ovnNbCommand(ovnArgs...) - return err -} - // StartOvnNbctlDaemon start a daemon and set OVN_NB_DAEMON env func StartOvnNbctlDaemon(ovnNbAddr string) error { klog.Infof("start ovn-nbctl daemon") @@ -1143,266 +728,6 @@ func CheckAlive() error { return nil } -func GetSgPortGroupName(sgName string) string { - return strings.Replace(fmt.Sprintf("ovn.sg.%s", sgName), "-", ".", -1) -} - -func GetSgV4AssociatedName(sgName string) string { - return strings.Replace(fmt.Sprintf("ovn.sg.%s.associated.v4", sgName), "-", ".", -1) -} - -func GetSgV6AssociatedName(sgName string) string { - return strings.Replace(fmt.Sprintf("ovn.sg.%s.associated.v6", sgName), "-", ".", -1) -} - -func (c LegacyClient) CreateSgAssociatedAddressSet(sgName string) error { - v4AsName := GetSgV4AssociatedName(sgName) - v6AsName := GetSgV6AssociatedName(sgName) - outputV4, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=_uuid", "find", "address_set", fmt.Sprintf("name=%s", v4AsName)) - if err != nil { - klog.Errorf("failed to find address_set for sg %s: %v", sgName, err) - return err - } - outputV6, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=_uuid", "find", "address_set", fmt.Sprintf("name=%s", v6AsName)) - if err != nil { - klog.Errorf("failed to find address_set for sg %s: %v", sgName, err) - return err - } - - if outputV4 == "" { - _, err = c.ovnNbCommand("create", "address_set", fmt.Sprintf("name=%s", v4AsName), fmt.Sprintf("external_ids:sg=%s", sgName)) - if err != nil { - klog.Errorf("failed to create v4 address_set for sg %s: %v", sgName, err) - return err - } - } - if outputV6 == "" { - _, err = c.ovnNbCommand("create", "address_set", fmt.Sprintf("name=%s", v6AsName), fmt.Sprintf("external_ids:sg=%s", sgName)) - if err != nil { - klog.Errorf("failed to create v6 address_set for sg %s: %v", sgName, err) - return err - } - } - return nil -} - -func (c LegacyClient) ListSgRuleAddressSet(sgName string, direction AclDirection) ([]string, error) { - ovnCmd := []string{"--data=bare", "--no-heading", "--columns=name", "find", "address_set", fmt.Sprintf("external_ids:sg=%s", sgName)} - if direction != "" { - ovnCmd = append(ovnCmd, fmt.Sprintf("external_ids:direction=%s", direction)) - } - output, err := c.ovnNbCommand(ovnCmd...) - if err != nil { - klog.Errorf("failed to list sg address_set of %s, direction %s: %v, %q", sgName, direction, err, output) - return nil, err - } - return strings.Split(output, "\n"), nil -} - -func (c LegacyClient) createSgRuleACL(sgName string, direction AclDirection, rule *kubeovnv1.SgRule) error { - ipSuffix := "ip4" - if rule.IPVersion == "ipv6" { - ipSuffix = "ip6" - } - - sgPortGroupName := GetSgPortGroupName(sgName) - var matchArgs []string - if rule.RemoteType == kubeovnv1.SgRemoteTypeAddress { - if direction == SgAclIngressDirection { - matchArgs = append(matchArgs, fmt.Sprintf("outport==@%s && %s && %s.src==%s", sgPortGroupName, ipSuffix, ipSuffix, rule.RemoteAddress)) - } else { - matchArgs = append(matchArgs, fmt.Sprintf("inport==@%s && %s && %s.dst==%s", sgPortGroupName, ipSuffix, ipSuffix, rule.RemoteAddress)) - } - } else { - remotePgName := GetSgV4AssociatedName(rule.RemoteSecurityGroup) - if rule.IPVersion == "ipv6" { - remotePgName = GetSgV6AssociatedName(rule.RemoteSecurityGroup) - } - if direction == SgAclIngressDirection { - matchArgs = append(matchArgs, fmt.Sprintf("outport==@%s && %s && %s.src==$%s", sgPortGroupName, ipSuffix, ipSuffix, remotePgName)) - } else { - matchArgs = append(matchArgs, fmt.Sprintf("inport==@%s && %s && %s.dst==$%s", sgPortGroupName, ipSuffix, ipSuffix, remotePgName)) - } - } - - if rule.Protocol == kubeovnv1.ProtocolICMP { - if ipSuffix == "ip4" { - matchArgs = append(matchArgs, "icmp4") - } else { - matchArgs = append(matchArgs, "icmp6") - } - } else if rule.Protocol == kubeovnv1.ProtocolTCP || rule.Protocol == kubeovnv1.ProtocolUDP { - matchArgs = append(matchArgs, fmt.Sprintf("%d<=%s.dst<=%d", rule.PortRangeMin, rule.Protocol, rule.PortRangeMax)) - } - - matchStr := strings.Join(matchArgs, " && ") - action := "drop" - if rule.Policy == kubeovnv1.PolicyAllow { - action = "allow-related" - } - highestPriority, err := strconv.Atoi(util.SecurityGroupHighestPriority) - if err != nil { - return err - } - _, err = c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", sgPortGroupName, string(direction), strconv.Itoa(highestPriority-rule.Priority), matchStr, action) - return err -} - -func (c LegacyClient) CreateSgDenyAllACL() error { - portGroupName := GetSgPortGroupName(util.DenyAllSecurityGroup) - exist, err := c.AclExists(util.SecurityGroupDropPriority, string(SgAclIngressDirection)) - if err != nil { - return err - } - if !exist { - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclIngressDirection), util.SecurityGroupDropPriority, - fmt.Sprintf("outport==@%s && ip", portGroupName), "drop"); err != nil { - return err - } - } - exist, err = c.AclExists(util.SecurityGroupDropPriority, string(SgAclEgressDirection)) - if err != nil { - return err - } - if !exist { - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclEgressDirection), util.SecurityGroupDropPriority, - fmt.Sprintf("inport==@%s && ip", portGroupName), "drop"); err != nil { - return err - } - } - return nil -} - -func (c LegacyClient) CreateSgBaseEgressACL(sgName string) error { - portGroupName := GetSgPortGroupName(sgName) - klog.Infof("add base egress acl, sg: %s", portGroupName) - // allow arp - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclEgressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("inport==@%s && arp", portGroupName), "allow-related"); err != nil { - return err - } - - // icmpv6 - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclEgressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("inport==@%s && icmp6.type=={130, 133, 135, 136} && icmp6.code == 0 && ip.ttl == 255", portGroupName), "allow-related"); err != nil { - return err - } - - // dhcpv4 res - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclEgressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("inport==@%s && udp.src==68 && udp.dst==67 && ip4", portGroupName), "allow-related"); err != nil { - return err - } - - // dhcpv6 res - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclEgressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("inport==@%s && udp.src==546 && udp.dst==547 && ip6", portGroupName), "allow-related"); err != nil { - return err - } - return nil -} - -func (c LegacyClient) CreateSgBaseIngressACL(sgName string) error { - portGroupName := GetSgPortGroupName(sgName) - klog.Infof("add base ingress acl, sg: %s", portGroupName) - // allow arp - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclIngressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("outport==@%s && arp", portGroupName), "allow-related"); err != nil { - return err - } - - // icmpv6 - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclIngressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("outport==@%s && icmp6.type=={130, 134, 135, 136} && icmp6.code == 0 && ip.ttl == 255", portGroupName), "allow-related"); err != nil { - return err - } - - // dhcpv4 offer - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclIngressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("outport==@%s && udp.src==67 && udp.dst==68 && ip4", portGroupName), "allow-related"); err != nil { - return err - } - - // dhcpv6 offer - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", portGroupName, string(SgAclIngressDirection), util.SecurityGroupBasePriority, - fmt.Sprintf("outport==@%s && udp.src==547 && udp.dst==546 && ip6", portGroupName), "allow-related"); err != nil { - return err - } - - return nil -} - -func (c LegacyClient) UpdateSgACL(sg *kubeovnv1.SecurityGroup, direction AclDirection) error { - sgPortGroupName := GetSgPortGroupName(sg.Name) - // clear acl - if err := c.DeleteACL(sgPortGroupName, string(direction)); err != nil { - return err - } - - // clear rule address_set - asList, err := c.ListSgRuleAddressSet(sg.Name, direction) - if err != nil { - return err - } - for _, as := range asList { - if err = c.DeleteAddressSet(as); err != nil { - return err - } - } - - // create port_group associated acl - if sg.Spec.AllowSameGroupTraffic { - v4AsName := GetSgV4AssociatedName(sg.Name) - v6AsName := GetSgV6AssociatedName(sg.Name) - if direction == SgAclIngressDirection { - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", sgPortGroupName, "to-lport", util.SecurityGroupAllowPriority, - fmt.Sprintf("outport==@%s && ip4 && ip4.src==$%s", sgPortGroupName, v4AsName), "allow-related"); err != nil { - return err - } - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", sgPortGroupName, "to-lport", util.SecurityGroupAllowPriority, - fmt.Sprintf("outport==@%s && ip6 && ip6.src==$%s", sgPortGroupName, v6AsName), "allow-related"); err != nil { - return err - } - } else { - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", sgPortGroupName, "from-lport", util.SecurityGroupAllowPriority, - fmt.Sprintf("inport==@%s && ip4 && ip4.dst==$%s", sgPortGroupName, v4AsName), "allow-related"); err != nil { - return err - } - if _, err := c.ovnNbCommand(MayExist, "--type=port-group", "acl-add", sgPortGroupName, "from-lport", util.SecurityGroupAllowPriority, - fmt.Sprintf("inport==@%s && ip6 && ip6.dst==$%s", sgPortGroupName, v6AsName), "allow-related"); err != nil { - return err - } - } - } - - // recreate rule ACL - var sgRules []*kubeovnv1.SgRule - if direction == SgAclIngressDirection { - sgRules = sg.Spec.IngressRules - } else { - sgRules = sg.Spec.EgressRules - } - for _, rule := range sgRules { - if err = c.createSgRuleACL(sg.Name, direction, rule); err != nil { - return err - } - } - return nil -} - -func (c *LegacyClient) AclExists(priority, direction string) (bool, error) { - priorityVal, _ := strconv.Atoi(priority) - results, err := c.CustomFindEntity("acl", []string{"match"}, fmt.Sprintf("priority=%d", priorityVal), fmt.Sprintf("direction=%s", direction)) - if err != nil { - klog.Errorf("customFindEntity failed, %v", err) - return false, err - } - if len(results) == 0 { - return false, nil - } - return true, nil -} - func (c *LegacyClient) VpcHasPolicyRoute(vpc string, nextHops []string, priority int32) (bool, error) { // get all policies by vpc outPolicies, err := c.ovnNbCommand("--data=bare", "--no-heading", @@ -1778,66 +1103,6 @@ func (c *LegacyClient) DeleteDHCPOptions(ls string, protocol string) error { return c.DeleteDHCPOptionsByUUIDs(uuidToDeleteList) } -func (c LegacyClient) DeleteSubnetACL(ls string) error { - results, err := c.CustomFindEntity("acl", []string{"direction", "priority", "match"}, fmt.Sprintf("external_ids:subnet=\"%s\"", ls)) - if err != nil { - klog.Errorf("customFindEntity failed, %v", err) - return err - } - if len(results) == 0 { - return nil - } - - for _, result := range results { - aclArgs := []string{"acl-del", ls} - aclArgs = append(aclArgs, result["direction"][0], result["priority"][0], result["match"][0]) - - _, err := c.ovnNbCommand(aclArgs...) - if err != nil { - return err - } - } - return nil -} - -func (c LegacyClient) UpdateSubnetACL(ls string, acls []kubeovnv1.Acl) error { - if err := c.DeleteSubnetACL(ls); err != nil { - klog.Errorf("failed to delete acls for subnet %s, %v", ls, err) - return err - } - if len(acls) == 0 { - return nil - } - - for _, acl := range acls { - aclArgs := []string{} - aclArgs = append(aclArgs, "--", MayExist, "acl-add", ls, acl.Direction, strconv.Itoa(acl.Priority), acl.Match, acl.Action) - _, err := c.ovnNbCommand(aclArgs...) - if err != nil { - klog.Errorf("failed to create acl for subnet %s, %v", ls, err) - return err - } - - results, err := c.CustomFindEntity("acl", []string{"_uuid"}, fmt.Sprintf("priority=%d", acl.Priority), fmt.Sprintf("direction=%s", acl.Direction), fmt.Sprintf("match=\"%s\"", acl.Match)) - if err != nil { - klog.Errorf("customFindEntity failed, %v", err) - return err - } - if len(results) == 0 { - return nil - } - - uuid := results[0]["_uuid"][0] - ovnCmd := []string{"set", "acl", uuid} - ovnCmd = append(ovnCmd, fmt.Sprintf("external_ids:subnet=\"%s\"", ls)) - - if _, err := c.ovnNbCommand(ovnCmd...); err != nil { - return fmt.Errorf("failed to set acl externalIds for subnet %s, %v", ls, err) - } - } - return nil -} - func (c *LegacyClient) GetLspExternalIds(lsp string) map[string]string { result, err := c.CustomFindEntity("Logical_Switch_Port", []string{"external_ids"}, fmt.Sprintf("name=%s", lsp)) if err != nil { @@ -1873,37 +1138,6 @@ func (c *LegacyClient) GetLspExternalIds(lsp string) map[string]string { return nameNsMap } -func (c LegacyClient) SetAclLog(pgName string, logEnable, isIngress bool) error { - var direction, match string - if isIngress { - direction = "to-lport" - match = fmt.Sprintf("outport==@%s && ip", pgName) - } else { - direction = "from-lport" - match = fmt.Sprintf("inport==@%s && ip", pgName) - } - - priority, _ := strconv.Atoi(util.IngressDefaultDrop) - result, err := c.CustomFindEntity("acl", []string{"_uuid"}, fmt.Sprintf("priority=%d", priority), fmt.Sprintf(`match="%s"`, match), fmt.Sprintf("direction=%s", direction), "action=drop") - if err != nil { - klog.Errorf("failed to get acl UUID: %v", err) - return err - } - - if len(result) == 0 { - return nil - } - - uuid := result[0]["_uuid"][0] - ovnCmd := []string{"set", "acl", uuid, fmt.Sprintf("log=%v", logEnable)} - - if _, err := c.ovnNbCommand(ovnCmd...); err != nil { - return fmt.Errorf("failed to set acl log, %v", err) - } - - return nil -} - func (c *LegacyClient) GetNatIPInfo(uuid string) (string, error) { var logical_ip string diff --git a/pkg/ovs/util.go b/pkg/ovs/util.go index 64e13e17d2f..1fc90b8011e 100644 --- a/pkg/ovs/util.go +++ b/pkg/ovs/util.go @@ -36,6 +36,18 @@ func LogicalSwitchPortName(lr, ls string) string { return fmt.Sprintf("%s-%s", ls, lr) } +func GetSgPortGroupName(sgName string) string { + return strings.Replace(fmt.Sprintf("ovn.sg.%s", sgName), "-", ".", -1) +} + +func GetSgV4AssociatedName(sgName string) string { + return strings.Replace(fmt.Sprintf("ovn.sg.%s.associated.v4", sgName), "-", ".", -1) +} + +func GetSgV6AssociatedName(sgName string) string { + return strings.Replace(fmt.Sprintf("ovn.sg.%s.associated.v6", sgName), "-", ".", -1) +} + // parseIpv6RaConfigs parses the ipv6 ra config, // return default Ipv6RaConfigs when raw="", // the raw config's format is: address_mode=dhcpv6_stateful,max_interval=30,min_interval=5,send_periodic=true