diff --git a/docs/antctl.md b/docs/antctl.md index ed7993022e4..5f4cba5c5a8 100644 --- a/docs/antctl.md +++ b/docs/antctl.md @@ -251,7 +251,7 @@ output format. The `NAME` of a control plane NetworkPolicy is the UID of its sou NetworkPolicy. ```bash -antctl get networkpolicy [NAME] [-n NAMESPACE] [-o yaml] +antctl get networkpolicy [NAME] [-n NAMESPACE] [-T K8sNP|ACNP|ANNP|ANP|BANP] [-o yaml] antctl get appliedtogroup [NAME] [-o yaml] antctl get addressgroup [NAME] [-o yaml] ``` @@ -350,7 +350,7 @@ in the specified OVS flow tables, or all or the specified OVS groups. antctl get ovsflows antctl get ovsflows -p POD -n NAMESPACE antctl get ovsflows -S SERVICE -n NAMESPACE -antctl get ovsflows -N NETWORKPOLICY -n NAMESPACE +antctl get ovsflows [-n NAMESPACE] -N NETWORKPOLICY --type NETWORKPOLICY_TYPE antctl get ovsflows -T TABLE_A,TABLE_B antctl get ovsflows -T TABLE_A,TABLE_B_NUM antctl get ovsflows -G all @@ -381,13 +381,22 @@ kube-system kube-dns 160ea6d7-0234-5d1d-8ea0-b703d0aa3b46 1 # Dump OVS flows of NetworkPolicy "kube-dns" $ antctl get of -N kube-dns -n kube-system FLOW -table=90, n_packets=0, n_bytes=0, priority=190,conj_id=1,ip actions=resubmit(,105) -table=90, n_packets=0, n_bytes=0, priority=200,ip actions=conjunction(1,1/3) -table=90, n_packets=0, n_bytes=0, priority=200,ip,reg1=0x5 actions=conjunction(2,2/3),conjunction(1,2/3) -table=90, n_packets=0, n_bytes=0, priority=200,udp,tp_dst=53 actions=conjunction(1,3/3) -table=90, n_packets=0, n_bytes=0, priority=200,tcp,tp_dst=53 actions=conjunction(1,3/3) -table=90, n_packets=0, n_bytes=0, priority=200,tcp,tp_dst=9153 actions=conjunction(1,3/3) -table=100, n_packets=0, n_bytes=0, priority=200,ip,reg1=0x5 actions=drop +table=IngressRule, n_packets=0, n_bytes=0, priority=190,conj_id=1,ip actions=set_field:0x1->reg5,ct(commit,table=IngressMetric,zone=65520,exec(set_field:0x1/0xffffffff->ct_label)) +table=IngressRule, n_packets=0, n_bytes=0, priority=200,ip actions=conjunction(1,1/3) +table=IngressRule, n_packets=0, n_bytes=0, priority=200,ip,reg1=0x5 actions=conjunction(2,2/3),conjunction(1,2/3) +table=IngressRule, n_packets=0, n_bytes=0, priority=200,udp,tp_dst=53 actions=conjunction(1,3/3) +table=IngressRule, n_packets=0, n_bytes=0, priority=200,tcp,tp_dst=53 actions=conjunction(1,3/3) +table=IngressRule, n_packets=0, n_bytes=0, priority=200,tcp,tp_dst=9153 actions=conjunction(1,3/3) +table=IngressDefaultRule, n_packets=0, n_bytes=0, priority=200,ip,reg1=0x5 actions=drop + +# Dump OVS flows of AntreaNetworkPolicy "test-annp" +$ antctl get ovsflows -N test-annp -n default --type ANNP +FLOW +table=AntreaPolicyIngressRule, n_packets=0, n_bytes=0, priority=14900,conj_id=6 actions=set_field:0x6->reg3,set_field:0x400/0x400->reg0,goto_table:IngressMetric +table=AntreaPolicyIngressRule, n_packets=0, n_bytes=0, priority=14900,ip,nw_src=10.20.1.8 actions=conjunction(6,1/3) +table=AntreaPolicyIngressRule, n_packets=0, n_bytes=0, priority=14900,ip,nw_src=10.20.2.8 actions=conjunction(6,1/3) +table=AntreaPolicyIngressRule, n_packets=0, n_bytes=0, priority=14900,reg1=0x3 actions=conjunction(6,2/3) +table=AntreaPolicyIngressRule, n_packets=0, n_bytes=0, priority=14900,tcp,tp_dst=443 actions=conjunction(6,3/3) ``` ### OVS packet tracing diff --git a/pkg/agent/apiserver/handlers/networkpolicy/handler.go b/pkg/agent/apiserver/handlers/networkpolicy/handler.go index 7490d88d489..44f9a0bed6a 100644 --- a/pkg/agent/apiserver/handlers/networkpolicy/handler.go +++ b/pkg/agent/apiserver/handlers/networkpolicy/handler.go @@ -57,15 +57,6 @@ func HandleFunc(aq agentquerier.AgentQuerier) http.HandlerFunc { } } -// From user shorthand input to cpv1beta1.NetworkPolicyType -var mapToNetworkPolicyType = map[string]cpv1beta.NetworkPolicyType{ - "NP": cpv1beta.K8sNetworkPolicy, - "K8SNP": cpv1beta.K8sNetworkPolicy, - "ACNP": cpv1beta.AntreaClusterNetworkPolicy, - "ANNP": cpv1beta.AntreaNetworkPolicy, - "ANP": cpv1beta.AntreaNetworkPolicy, -} - // Create a Network Policy Filter from URL Query func newFilterFromURLQuery(query url.Values) (*querier.NetworkPolicyQueryFilter, string, error) { namespace, pod := query.Get("namespace"), query.Get("pod") @@ -77,9 +68,13 @@ func newFilterFromURLQuery(query url.Values) (*querier.NetworkPolicyQueryFilter, } } strSourceType := strings.ToUpper(query.Get("type")) - npSourceType, ok := mapToNetworkPolicyType[strSourceType] - if strSourceType != "" && !ok { - return nil, "", fmt.Errorf("invalid policy source type. Valid values are K8sNP, ACNP, ANNP and ANP (deprecated)") + var policyType cpv1beta.NetworkPolicyType + if strSourceType != "" { + npSourceType, ok := querier.NetworkPolicyTypeMap[strSourceType] + if !ok { + return nil, "", fmt.Errorf("unknown policy type. Valid types are %v", querier.GetNetworkPolicyTypeShorthands()) + } + policyType = npSourceType } source := query.Get("source") name := query.Get("name") @@ -90,6 +85,6 @@ func newFilterFromURLQuery(query url.Values) (*querier.NetworkPolicyQueryFilter, Name: name, SourceName: source, Namespace: namespace, - SourceType: npSourceType, + SourceType: policyType, }, pod, nil } diff --git a/pkg/agent/apiserver/handlers/ovsflows/handler.go b/pkg/agent/apiserver/handlers/ovsflows/handler.go index 22c3b46f07d..12a9067043f 100644 --- a/pkg/agent/apiserver/handlers/ovsflows/handler.go +++ b/pkg/agent/apiserver/handlers/ovsflows/handler.go @@ -16,6 +16,7 @@ package ovsflows import ( "encoding/json" + "fmt" "net/http" "sort" "strconv" @@ -26,6 +27,7 @@ import ( "antrea.io/antrea/pkg/agent/apis" "antrea.io/antrea/pkg/agent/openflow" agentquerier "antrea.io/antrea/pkg/agent/querier" + cpv1beta "antrea.io/antrea/pkg/apis/controlplane/v1beta2" binding "antrea.io/antrea/pkg/ovs/openflow" "antrea.io/antrea/pkg/querier" ) @@ -35,10 +37,12 @@ var ( getFlowTableName = openflow.GetFlowTableName getFlowTableID = openflow.GetFlowTableID getFlowTableList = openflow.GetTableList + + errAmbiguousQuery = fmt.Errorf("query is ambiguous and matches more than one policy") ) func dumpMatchedFlows(aq agentquerier.AgentQuerier, flowKeys []string) ([]apis.OVSFlowResponse, error) { - resps := []apis.OVSFlowResponse{} + var resps []apis.OVSFlowResponse for _, f := range flowKeys { flowStr, err := aq.GetOVSCtlClient().DumpMatchedFlow(f) if err != nil { @@ -53,7 +57,7 @@ func dumpMatchedFlows(aq agentquerier.AgentQuerier, flowKeys []string) ([]apis.O } func dumpFlows(aq agentquerier.AgentQuerier, table uint8) ([]apis.OVSFlowResponse, error) { - resps := []apis.OVSFlowResponse{} + var resps []apis.OVSFlowResponse var flowStrs []string var err error if table != binding.TableIDAll { @@ -170,19 +174,27 @@ func getServiceFlows(aq agentquerier.AgentQuerier, serviceName, namespace string return append(resps, groupResps...), nil } -func getNetworkPolicyFlows(aq agentquerier.AgentQuerier, npName, namespace string) ([]apis.OVSFlowResponse, error) { - if len(aq.GetNetworkPolicyInfoQuerier().GetNetworkPolicies(&querier.NetworkPolicyQueryFilter{SourceName: npName, Namespace: namespace})) == 0 { +func getNetworkPolicyFlows(aq agentquerier.AgentQuerier, npName, namespace string, policyType cpv1beta.NetworkPolicyType) ([]apis.OVSFlowResponse, error) { + npFilter := &querier.NetworkPolicyQueryFilter{ + SourceName: npName, + Namespace: namespace, + SourceType: policyType, + } + nps := aq.GetNetworkPolicyInfoQuerier().GetNetworkPolicies(npFilter) + if len(nps) == 0 { // NetworkPolicy not found. return nil, nil + } else if len(nps) > 1 { + return nil, errAmbiguousQuery } - - flowKeys := aq.GetOpenflowClient().GetNetworkPolicyFlowKeys(npName, namespace) + namespace, policyType = nps[0].SourceRef.Namespace, nps[0].SourceRef.Type + flowKeys := aq.GetOpenflowClient().GetNetworkPolicyFlowKeys(npName, namespace, policyType) return dumpMatchedFlows(aq, flowKeys) } -func getTableNames(aq agentquerier.AgentQuerier) []apis.OVSFlowResponse { - resps := []apis.OVSFlowResponse{} - names := []string{} +func getTableNames() []apis.OVSFlowResponse { + var resps []apis.OVSFlowResponse + var names []string for _, t := range getFlowTableList() { names = append(names, t.GetName()) } @@ -201,6 +213,7 @@ func HandleFunc(aq agentquerier.AgentQuerier) http.HandlerFunc { pod := r.URL.Query().Get("pod") service := r.URL.Query().Get("service") networkPolicy := r.URL.Query().Get("networkpolicy") + policyType := strings.ToUpper(r.URL.Query().Get("type")) namespace := r.URL.Query().Get("namespace") table := r.URL.Query().Get("table") groups := r.URL.Query().Get("groups") @@ -214,16 +227,31 @@ func HandleFunc(aq agentquerier.AgentQuerier) http.HandlerFunc { } if tableNamesOnly { - resps = getTableNames(aq) + resps = getTableNames() encodeResp() return } - if (pod != "" || service != "" || networkPolicy != "") && namespace == "" { + if (pod != "" || service != "") && namespace == "" { http.Error(w, "namespace must be provided", http.StatusBadRequest) return } - + if networkPolicy != "" && policyType != "" { + _, ok := querier.NetworkPolicyTypeMap[policyType] + if !ok { + errorMsg := fmt.Sprintf("unknown policy type. Valid types are %v", querier.GetNetworkPolicyTypeShorthands()) + http.Error(w, errorMsg, http.StatusBadRequest) + return + } + if querier.NamespaceScopedPolicyTypes.Has(policyType) && namespace == "" { + http.Error(w, "policy Namespace must be provided for policy type "+policyType, http.StatusBadRequest) + return + } + if !querier.NamespaceScopedPolicyTypes.Has(policyType) && namespace != "" { + http.Error(w, "policy Namespace should not be provided for cluster-scoped policy type "+policyType, http.StatusBadRequest) + return + } + } if pod == "" && service == "" && networkPolicy == "" && namespace == "" && table == "" && groups == "" { resps, err = dumpFlows(aq, binding.TableIDAll) } else if pod != "" { @@ -236,7 +264,16 @@ func HandleFunc(aq agentquerier.AgentQuerier) http.HandlerFunc { } resps, err = getServiceFlows(aq, service, namespace) } else if networkPolicy != "" { - resps, err = getNetworkPolicyFlows(aq, networkPolicy, namespace) + var cpPolicyType cpv1beta.NetworkPolicyType + if policyType != "" { + // policyType string has already been validated above + cpPolicyType = querier.NetworkPolicyTypeMap[policyType] + } + resps, err = getNetworkPolicyFlows(aq, networkPolicy, namespace, cpPolicyType) + if err == errAmbiguousQuery { + http.Error(w, errAmbiguousQuery.Error(), http.StatusBadRequest) + return + } } else if table != "" { resps, err = getTableFlows(aq, table) if err == nil && resps == nil { diff --git a/pkg/agent/apiserver/handlers/ovsflows/handler_test.go b/pkg/agent/apiserver/handlers/ovsflows/handler_test.go index 99ebc33bf58..9b3dac9ec62 100644 --- a/pkg/agent/apiserver/handlers/ovsflows/handler_test.go +++ b/pkg/agent/apiserver/handlers/ovsflows/handler_test.go @@ -44,22 +44,36 @@ var ( testDumpGroups = []string{"group1", "group2"} testResponses = []apis.OVSFlowResponse{{Flow: "flow1"}, {Flow: "flow2"}} testGroupResponses = []apis.OVSFlowResponse{{Flow: "group1"}, {Flow: "group2"}} + + testNetworkPolicy = &cpv1beta.NetworkPolicy{ + SourceRef: &cpv1beta.NetworkPolicyReference{ + Type: cpv1beta.K8sNetworkPolicy, + Namespace: "default", + }, + } + testANNP = &cpv1beta.NetworkPolicy{ + SourceRef: &cpv1beta.NetworkPolicyReference{ + Type: cpv1beta.AntreaNetworkPolicy, + Namespace: "default", + }, + } ) type testCase struct { - test string - name string - namespace string - query string - expectedStatus int - resps []apis.OVSFlowResponse + testName string + name string + namespace string + policyType cpv1beta.NetworkPolicyType + policyTypeToReturn cpv1beta.NetworkPolicyType + query string + expectedStatus int + resps []apis.OVSFlowResponse } func TestBadRequests(t *testing.T) { badRequests := map[string]string{ "Pod only": "?pod=pod1", "Service only": "?service=svc1", - "NetworkPolicy only": "?networkpolicy=np1", "Namespace only": "?namespace=ns1", "Pod and NetworkPolicy": "?pod=pod1&&networkpolicy=np1", "Pod and table": "?pod=pod1&&table=0", @@ -88,14 +102,14 @@ func TestPodFlows(t *testing.T) { testInterface := &interfacestore.InterfaceConfig{InterfaceName: "interface0"} testcases := []testCase{ { - test: "Existing Pod", + testName: "Existing Pod", name: "pod1", namespace: "ns1", query: "?pod=pod1&&namespace=ns1", expectedStatus: http.StatusOK, }, { - test: "Non-existing Pod", + testName: "Non-existing Pod", name: "pod2", namespace: "ns2", query: "?pod=pod2&&namespace=ns2", @@ -130,7 +144,7 @@ func TestServiceFlows(t *testing.T) { ctrl := gomock.NewController(t) testcases := []testCase{ { - test: "Existing Service", + testName: "Existing Service", name: "svc1", namespace: "ns1", query: "?service=svc1&&namespace=ns1", @@ -138,7 +152,7 @@ func TestServiceFlows(t *testing.T) { resps: append(testResponses, testGroupResponses...), }, { - test: "Non-existing Service", + testName: "Non-existing Service", name: "svc2", namespace: "ns2", query: "?service=svc2&&namespace=ns2", @@ -169,48 +183,153 @@ func TestServiceFlows(t *testing.T) { } } -func TestNetworkPolicyFlows(t *testing.T) { - ctrl := gomock.NewController(t) - testNetworkPolicy := &cpv1beta.NetworkPolicy{} +func TestNetworkPolicyFlowsSuccess(t *testing.T) { testcases := []testCase{ { - test: "Existing NetworkPolicy", + testName: "Existing NetworkPolicy", name: "np1", - namespace: "ns1", - query: "?networkpolicy=np1&&namespace=ns1", + namespace: "default", + policyType: cpv1beta.K8sNetworkPolicy, + query: "?networkpolicy=np1&namespace=default&type=K8sNP", expectedStatus: http.StatusOK, }, { - test: "Non-existing NetworkPolicy", - name: "np2", - namespace: "ns2", - query: "?networkpolicy=np2&&namespace=ns2", - expectedStatus: http.StatusNotFound, + testName: "Existing ACNP", + name: "acnp1", + policyType: cpv1beta.AntreaClusterNetworkPolicy, + query: "?networkpolicy=acnp1&type=ACNP", + expectedStatus: http.StatusOK, + }, + { + testName: "Existing ANNP", + name: "annp1", + namespace: "default", + policyType: cpv1beta.AntreaNetworkPolicy, + query: "?networkpolicy=annp1&namespace=default&type=ANNP", + expectedStatus: http.StatusOK, + }, + { + testName: "Existing ANNP - no type provided", + name: "annp1", + namespace: "default", + query: "?networkpolicy=annp1&namespace=default", + policyTypeToReturn: cpv1beta.AntreaNetworkPolicy, + expectedStatus: http.StatusOK, + }, + { + testName: "Existing ANP", + name: "anp1", + policyType: cpv1beta.AdminNetworkPolicy, + query: "?networkpolicy=anp1&type=ANP", + expectedStatus: http.StatusOK, }, } for i := range testcases { tc := testcases[i] - npq := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl) - q := aqtest.NewMockAgentQuerier(ctrl) - q.EXPECT().GetNetworkPolicyInfoQuerier().Return(npq).Times(1) - - if tc.expectedStatus != http.StatusNotFound { + t.Run(tc.testName, func(t *testing.T) { + ctrl := gomock.NewController(t) + npq := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl) + q := aqtest.NewMockAgentQuerier(ctrl) ofc := oftest.NewMockClient(ctrl) ovsctl := ovsctltest.NewMockOVSCtlClient(ctrl) - npq.EXPECT().GetNetworkPolicies(&querier.NetworkPolicyQueryFilter{SourceName: tc.name, Namespace: tc.namespace}).Return([]cpv1beta.NetworkPolicy{*testNetworkPolicy}).Times(1) - ofc.EXPECT().GetNetworkPolicyFlowKeys(tc.name, tc.namespace).Return(testFlowKeys).Times(1) + npFilter := &querier.NetworkPolicyQueryFilter{ + SourceName: tc.name, + Namespace: tc.namespace, + SourceType: tc.policyType, + } + q.EXPECT().GetNetworkPolicyInfoQuerier().Return(npq).Times(1) + if tc.policyTypeToReturn == "" { + tc.policyTypeToReturn = tc.policyType + } + npq.EXPECT().GetNetworkPolicies(npFilter).Return([]cpv1beta.NetworkPolicy{ + { + SourceRef: &cpv1beta.NetworkPolicyReference{ + Type: tc.policyTypeToReturn, + Namespace: tc.namespace, + Name: tc.name, + }, + }, + }).Times(1) + ofc.EXPECT().GetNetworkPolicyFlowKeys(tc.name, tc.namespace, tc.policyTypeToReturn).Return(testFlowKeys).Times(1) q.EXPECT().GetOpenflowClient().Return(ofc).Times(1) q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(len(testFlowKeys)) for i := range testFlowKeys { ovsctl.EXPECT().DumpMatchedFlow(testFlowKeys[i]).Return(testDumpFlows[i], nil).Times(1) } - } else { - npq.EXPECT().GetNetworkPolicies(&querier.NetworkPolicyQueryFilter{SourceName: tc.name, Namespace: tc.namespace}).Return(nil).Times(1) - } + runHTTPTest(t, &tc, q) + }) + } +} - runHTTPTest(t, &tc, q) +func TestNetworkPolicyFlowsBadRequest(t *testing.T) { + testcases := []testCase{ + { + testName: "ACNP bad request - namespace should not be provided", + name: "acnp2", + policyType: cpv1beta.AntreaClusterNetworkPolicy, + query: "?networkpolicy=acnp2&type=ACNP&namespace=default", + expectedStatus: http.StatusBadRequest, + }, + { + testName: "ANNP bad request - namespace should be provided", + name: "annp2", + policyType: cpv1beta.AntreaNetworkPolicy, + query: "?networkpolicy=annp2&type=ANNP", + expectedStatus: http.StatusBadRequest, + }, } + for i := range testcases { + tc := testcases[i] + t.Run(tc.testName, func(t *testing.T) { + ctrl := gomock.NewController(t) + q := aqtest.NewMockAgentQuerier(ctrl) + runHTTPTest(t, &tc, q) + }) + } +} +func TestNetworkPolicyFlowsPolicyAmbiguousQuery(t *testing.T) { + tc := &testCase{ + testName: "Ambiguous query", + name: "np-annp-same-name", + namespace: "ns1", + query: "?networkpolicy=np-annp-same-name&namespace=ns1", + expectedStatus: http.StatusBadRequest, + } + ctrl := gomock.NewController(t) + q := aqtest.NewMockAgentQuerier(ctrl) + // Simulates an ambiguous query where more than one matching NP is returned + npq := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl) + q.EXPECT().GetNetworkPolicyInfoQuerier().Return(npq).Times(1) + npFilter := &querier.NetworkPolicyQueryFilter{ + SourceName: tc.name, + Namespace: tc.namespace, + SourceType: tc.policyType, + } + npq.EXPECT().GetNetworkPolicies(npFilter).Return([]cpv1beta.NetworkPolicy{*testNetworkPolicy, *testANNP}).Times(1) + runHTTPTest(t, tc, q) +} + +func TestNetworkPolicyFlowsPolicyNotFound(t *testing.T) { + tc := &testCase{ + testName: "Non-existing NetworkPolicy", + name: "np1", + namespace: "ns1", + policyType: cpv1beta.K8sNetworkPolicy, + query: "?networkpolicy=np1&namespace=ns1&type=K8sNP", + expectedStatus: http.StatusNotFound, + } + ctrl := gomock.NewController(t) + q := aqtest.NewMockAgentQuerier(ctrl) + npq := queriertest.NewMockAgentNetworkPolicyInfoQuerier(ctrl) + q.EXPECT().GetNetworkPolicyInfoQuerier().Return(npq).Times(1) + npFilter := &querier.NetworkPolicyQueryFilter{ + SourceName: tc.name, + Namespace: tc.namespace, + SourceType: tc.policyType, + } + npq.EXPECT().GetNetworkPolicies(npFilter).Return(nil).Times(1) + runHTTPTest(t, tc, q) } func TestTableFlows(t *testing.T) { @@ -219,33 +338,34 @@ func TestTableFlows(t *testing.T) { getFlowTableID = mockGetFlowTableID testcases := []testCase{ { - test: "Table 80", + testName: "Table 80", query: "?table=80", expectedStatus: http.StatusOK, }, { - test: "Table IngressRule", + testName: "Table IngressRule", query: "?table=IngressRule", expectedStatus: http.StatusOK, }, } for i := range testcases { tc := testcases[i] - ovsctl := ovsctltest.NewMockOVSCtlClient(ctrl) - q := aqtest.NewMockAgentQuerier(ctrl) - q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(1) - ovsctl.EXPECT().DumpTableFlows(gomock.Any()).Return(testDumpFlows, nil).Times(1) + t.Run(tc.testName, func(t *testing.T) { + ovsctl := ovsctltest.NewMockOVSCtlClient(ctrl) + q := aqtest.NewMockAgentQuerier(ctrl) + q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(1) + ovsctl.EXPECT().DumpTableFlows(gomock.Any()).Return(testDumpFlows, nil).Times(1) - runHTTPTest(t, &tc, q) + runHTTPTest(t, &tc, q) + }) } - } func TestTableNamesOnly(t *testing.T) { ctrl := gomock.NewController(t) getFlowTableList = mockGetTableList tc := testCase{ - test: "Get table names only", + testName: "Get table names only", query: "?table-names-only", expectedStatus: http.StatusOK, resps: []apis.OVSFlowResponse{{Flow: "table0"}, {Flow: "table1"}}, @@ -284,7 +404,7 @@ func TestGroups(t *testing.T) { }{ { testCase: testCase{ - test: "All groups", + testName: "All groups", query: "?groups=all", expectedStatus: http.StatusOK, resps: testGroupResponses, @@ -293,7 +413,7 @@ func TestGroups(t *testing.T) { }, { testCase: testCase{ - test: "Group 1234", + testName: "Group 1234", query: "?groups=1234", expectedStatus: http.StatusOK, resps: []apis.OVSFlowResponse{{Flow: "group1234"}}, @@ -303,7 +423,7 @@ func TestGroups(t *testing.T) { }, { testCase: testCase{ - test: "Non-existing group 1234", + testName: "Non-existing group 1234", query: "?groups=1234", expectedStatus: http.StatusOK, resps: []apis.OVSFlowResponse{}, @@ -313,7 +433,7 @@ func TestGroups(t *testing.T) { }, { testCase: testCase{ - test: "Group 10, 100, and 1000", + testName: "Group 10, 100, and 1000", query: "?groups=10,100,1000", expectedStatus: http.StatusOK, resps: []apis.OVSFlowResponse{{Flow: "group10"}, {Flow: "group1000"}}, @@ -323,21 +443,22 @@ func TestGroups(t *testing.T) { }, } for _, tc := range testcases { - ovsctl := ovsctltest.NewMockOVSCtlClient(ctrl) - q := aqtest.NewMockAgentQuerier(ctrl) - if tc.groupIDs == nil { - // Get all. - q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(1) - ovsctl.EXPECT().DumpGroups().Return(tc.dumpedGroups, nil).Times(1) - } else { - // Get all. - q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(len(tc.groupIDs)) - for i, id := range tc.groupIDs { - ovsctl.EXPECT().DumpGroup(id).Return(tc.dumpedGroups[i], nil).Times(1) + t.Run(tc.testName, func(t *testing.T) { + ovsctl := ovsctltest.NewMockOVSCtlClient(ctrl) + q := aqtest.NewMockAgentQuerier(ctrl) + if tc.groupIDs == nil { + // Get all. + q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(1) + ovsctl.EXPECT().DumpGroups().Return(tc.dumpedGroups, nil).Times(1) + } else { + // Get all. + q.EXPECT().GetOVSCtlClient().Return(ovsctl).Times(len(tc.groupIDs)) + for i, id := range tc.groupIDs { + ovsctl.EXPECT().DumpGroup(id).Return(tc.dumpedGroups[i], nil).Times(1) + } } - } - - runHTTPTest(t, &tc.testCase, q) + runHTTPTest(t, &tc.testCase, q) + }) } } @@ -348,7 +469,7 @@ func runHTTPTest(t *testing.T, tc *testCase, aq agentquerier.AgentQuerier) { recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, req) - assert.Equal(t, tc.expectedStatus, recorder.Code, tc.test) + assert.Equal(t, tc.expectedStatus, recorder.Code, tc.testName) if tc.expectedStatus == http.StatusOK { var received []apis.OVSFlowResponse diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go index e6d3ec5ef87..e6e77d0cebd 100644 --- a/pkg/agent/openflow/client.go +++ b/pkg/agent/openflow/client.go @@ -216,7 +216,7 @@ type Client interface { // flows for a NetworkPolicy. Flows are grouped by policy rules, and duplicated // entries can be added due to conjunctive match flows shared by multiple // rules. - GetNetworkPolicyFlowKeys(npName, npNamespace string) []string + GetNetworkPolicyFlowKeys(npName, npNamespace string, npType v1beta2.NetworkPolicyType) []string // ReassignFlowPriorities takes a list of priority updates, and update the actionFlows to replace // the old priority with the desired one, for each priority update on that table. @@ -445,7 +445,7 @@ func (c *client) addFlowsWithMultipleKeys(cache *flowCategoryCache, keyToFlows m for _, flow := range flows { msg := getFlowModMessage(flow, binding.AddMessage) allMessages = append(allMessages, msg) - fCache[getFlowKey(msg)] = msg + fCache[getFlowModKey(msg)] = msg } flowCacheMap[flowCacheKey] = fCache } @@ -473,7 +473,7 @@ func (c *client) modifyFlows(cache *flowCategoryCache, flowCacheKey string, flow for _, flow := range flows { msg := getFlowModMessage(flow, binding.AddMessage) messages = append(messages, msg) - fCache[getFlowKey(msg)] = msg + fCache[getFlowModKey(msg)] = msg } err = c.ofEntryOperations.AddAll(messages) } else { @@ -695,7 +695,7 @@ func (c *client) getFlowKeysFromCache(cache *flowCategoryCache, cacheKey string) c.replayMutex.RLock() defer c.replayMutex.RUnlock() for _, flow := range fCache { - flowKeys = append(flowKeys, getFlowKey(flow)) + flowKeys = append(flowKeys, getFlowModKey(flow)) } return flowKeys } diff --git a/pkg/agent/openflow/network_policy.go b/pkg/agent/openflow/network_policy.go index 95e61760eb7..babc9e83971 100644 --- a/pkg/agent/openflow/network_policy.go +++ b/pkg/agent/openflow/network_policy.go @@ -1515,13 +1515,12 @@ func (c *policyRuleConjunction) calculateChangesForRuleDeletion() []*conjMatchFl return ctxChanges } -// getAllFlowKeys returns the matching strings of actions flows of -// policyRuleConjunction, as well as matching flows of all its clauses. +// getAllFlowKeys returns the match strings used in ovs-ofctl dump-flows command, including +// actions flows of policyRuleConjunction, as well as matching flows of all its clauses. func (c *policyRuleConjunction) getAllFlowKeys() []string { - flowKeys := []string{} - dropFlowKeys := []string{} + var flowKeys, dropFlowKeys []string for _, flow := range c.actionFlows { - flowKeys = append(flowKeys, getFlowKey(flow)) + flowKeys = append(flowKeys, getFlowDumpKey(flow)) } addClauseFlowKeys := func(clause *clause) { @@ -1530,10 +1529,10 @@ func (c *policyRuleConjunction) getAllFlowKeys() []string { } for _, ctx := range clause.matches { if ctx.flow != nil { - flowKeys = append(flowKeys, getFlowKey(ctx.flow)) + flowKeys = append(flowKeys, getFlowDumpKey(ctx.flow)) } if ctx.dropFlow != nil { - dropFlowKeys = append(dropFlowKeys, getFlowKey(ctx.dropFlow)) + dropFlowKeys = append(dropFlowKeys, getFlowDumpKey(ctx.dropFlow)) } } } @@ -1710,8 +1709,8 @@ func (c *client) DeletePolicyRuleAddress(ruleID uint32, addrType types.AddressTy return c.featureNetworkPolicy.applyConjunctiveMatchFlows(changes) } -func (c *client) GetNetworkPolicyFlowKeys(npName, npNamespace string) []string { - flowKeys := []string{} +func (c *client) GetNetworkPolicyFlowKeys(npName, npNamespace string, npType v1beta2.NetworkPolicyType) []string { + var flowKeys []string // Hold replayMutex write lock to protect flows from being modified by // NetworkPolicy updates and replayFlows. This is more for logic // cleanliness, as: for now flow updates do not impact the matching string @@ -1727,7 +1726,7 @@ func (c *client) GetNetworkPolicyFlowKeys(npName, npNamespace string) []string { if conj.npRef == nil { continue } - if conj.npRef.Name == npName && conj.npRef.Namespace == npNamespace { + if conj.npRef.Name == npName && conj.npRef.Namespace == npNamespace && conj.npRef.Type == npType { // There can be duplicated flows added due to conjunctive matches // shared by multiple policy rules (clauses). flowKeys = append(flowKeys, conj.getAllFlowKeys()...) diff --git a/pkg/agent/openflow/network_policy_test.go b/pkg/agent/openflow/network_policy_test.go index 40f10570c3f..3951e1b0afd 100644 --- a/pkg/agent/openflow/network_policy_test.go +++ b/pkg/agent/openflow/network_policy_test.go @@ -240,11 +240,11 @@ func TestInstallPolicyRuleFlows(t *testing.T) { err = c.featureNetworkPolicy.applyConjunctiveMatchFlows(ctxChanges2) require.Nil(t, err) - assert.Equal(t, 0, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 0, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) err = c.InstallPolicyRuleFlows(rule2) require.Nil(t, err) checkConjunctionConfig(t, ruleID2, 1, 2, 1, 0) - assert.Equal(t, 6, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 6, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) ruleID3 := uint32(103) port1 := intstr.FromInt(8080) @@ -288,7 +288,7 @@ func TestInstallPolicyRuleFlows(t *testing.T) { err = c.InstallPolicyRuleFlows(rule3) require.Nil(t, err, "Failed to invoke InstallPolicyRuleFlows") checkConjunctionConfig(t, ruleID3, 1, 2, 1, 3) - assert.Equal(t, 15, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 15, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) ctxChanges4 := conj.calculateChangesForRuleDeletion() matchFlows4, dropFlows4 := getChangedFlows(ctxChanges4) @@ -305,7 +305,7 @@ func TestInstallPolicyRuleFlows(t *testing.T) { assert.Equal(t, 2, getChangedFlowOPCount(matchFlows5, deletion)) assert.Equal(t, 1, getChangedFlowOPCount(matchFlows5, modification)) err = c.featureNetworkPolicy.applyConjunctiveMatchFlows(ctxChanges5) - assert.Equal(t, 12, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 12, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) require.Nil(t, err) } @@ -741,11 +741,11 @@ func TestInstallPolicyRuleFlowsInDualStackCluster(t *testing.T) { err = c.featureNetworkPolicy.applyConjunctiveMatchFlows(ctxChanges2) require.Nil(t, err) - assert.Equal(t, 0, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 0, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) err = c.InstallPolicyRuleFlows(rule2) require.Nil(t, err) checkConjunctionConfig(t, ruleID2, 2, 3, 1, 0) - assert.Equal(t, 9, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 9, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) ruleID3 := uint32(103) port1 := intstr.FromInt(8080) @@ -788,7 +788,7 @@ func TestInstallPolicyRuleFlowsInDualStackCluster(t *testing.T) { err = c.InstallPolicyRuleFlows(rule3) require.Nil(t, err, "Failed to invoke InstallPolicyRuleFlows") checkConjunctionConfig(t, ruleID3, 2, 2, 1, 4) - assert.Equal(t, 20, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 20, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) ctxChanges4 := conj.calculateChangesForRuleDeletion() matchFlows4, dropFlows4 := getChangedFlows(ctxChanges4) @@ -805,7 +805,7 @@ func TestInstallPolicyRuleFlowsInDualStackCluster(t *testing.T) { assert.Equal(t, 3, getChangedFlowOPCount(matchFlows5, deletion)) assert.Equal(t, 1, getChangedFlowOPCount(matchFlows5, modification)) err = c.featureNetworkPolicy.applyConjunctiveMatchFlows(ctxChanges5) - assert.Equal(t, 15, len(c.GetNetworkPolicyFlowKeys("np1", "ns1"))) + assert.Equal(t, 15, len(c.GetNetworkPolicyFlowKeys("np1", "ns1", v1beta2.K8sNetworkPolicy))) require.Nil(t, err) } diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go index 601e910f186..a1eb6655d35 100644 --- a/pkg/agent/openflow/pipeline.go +++ b/pkg/agent/openflow/pipeline.go @@ -368,7 +368,7 @@ func copyFlowWithNewPriority(flowMod *openflow15.FlowMod, priority uint16) *open } func flowMessageMatched(oldFlow, newFlow *openflow15.FlowMod) bool { - return oldFlow.Priority == newFlow.Priority && getFlowKey(oldFlow) == getFlowKey(newFlow) + return oldFlow.Priority == newFlow.Priority && getFlowModKey(oldFlow) == getFlowModKey(newFlow) } // isDropFlow returns true if no instructions are defined in the OpenFlow modification message. @@ -378,10 +378,14 @@ func isDropFlow(f *openflow15.FlowMod) bool { return len(f.Instructions) == 0 } -func getFlowKey(fm *openflow15.FlowMod) string { +func getFlowModKey(fm *openflow15.FlowMod) string { return binding.FlowModMatchString(fm) } +func getFlowDumpKey(fm *openflow15.FlowMod) string { + return binding.FlowModMatchString(fm, "priority") +} + type flowMessageCache map[string]*openflow15.FlowMod type flowCategoryCache struct { diff --git a/pkg/agent/openflow/testing/mock_openflow.go b/pkg/agent/openflow/testing/mock_openflow.go index 99c21e47119..96dd46af1ea 100644 --- a/pkg/agent/openflow/testing/mock_openflow.go +++ b/pkg/agent/openflow/testing/mock_openflow.go @@ -178,17 +178,17 @@ func (mr *MockClientMockRecorder) GetFlowTableStatus() *gomock.Call { } // GetNetworkPolicyFlowKeys mocks base method. -func (m *MockClient) GetNetworkPolicyFlowKeys(arg0, arg1 string) []string { +func (m *MockClient) GetNetworkPolicyFlowKeys(arg0, arg1 string, arg2 v1beta2.NetworkPolicyType) []string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNetworkPolicyFlowKeys", arg0, arg1) + ret := m.ctrl.Call(m, "GetNetworkPolicyFlowKeys", arg0, arg1, arg2) ret0, _ := ret[0].([]string) return ret0 } // GetNetworkPolicyFlowKeys indicates an expected call of GetNetworkPolicyFlowKeys. -func (mr *MockClientMockRecorder) GetNetworkPolicyFlowKeys(arg0, arg1 any) *gomock.Call { +func (mr *MockClientMockRecorder) GetNetworkPolicyFlowKeys(arg0, arg1, arg2 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkPolicyFlowKeys", reflect.TypeOf((*MockClient)(nil).GetNetworkPolicyFlowKeys), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkPolicyFlowKeys", reflect.TypeOf((*MockClient)(nil).GetNetworkPolicyFlowKeys), arg0, arg1, arg2) } // GetPodFlowKeys mocks base method. diff --git a/pkg/antctl/antctl.go b/pkg/antctl/antctl.go index 946dbb3d53e..ddd91e6a6ab 100644 --- a/pkg/antctl/antctl.go +++ b/pkg/antctl/antctl.go @@ -215,9 +215,10 @@ $ antctl get podmulticaststats pod -n namespace`, shorthand: "p", }, { - name: "type", - usage: "Get NetworkPolicies with specific type. Type means the type of its source NetworkPolicy: K8sNP, ACNP, ANNP", - shorthand: "T", + name: "type", + usage: "Get NetworkPolicies with specific type. Type refers to the type of its source NetworkPolicy: K8sNP, ACNP, ANNP, BANP or ANP", + shorthand: "T", + supportedValues: []string{"K8sNP", "ACNP", "ANNP", "BANP", "ANP"}, }, }, getSortByFlag()), outputType: multiple, @@ -371,7 +372,7 @@ $ antctl get podmulticaststats pod -n namespace`, Dump OVS flows of a Service $ antctl get ovsflows -S svc1 -n ns1 Dump OVS flows of a NetworkPolicy - $ antctl get ovsflows -N np1 -n ns1 + $ antctl get ovsflows -N np1 -n ns1 --type K8sNP Dump OVS flows of a flow Table $ antctl get ovsflows -T IngressRule Dump OVS groups @@ -399,9 +400,14 @@ $ antctl get podmulticaststats pod -n namespace`, }, { name: "networkpolicy", - usage: "NetworkPolicy name. If present, Namespace must be provided.", + usage: "NetworkPolicy name. Namespace must be provided for non-cluster-scoped policy types if a type is specified.", shorthand: "N", }, + { + name: "type", + usage: "NetworkPolicy type. Valid types are K8sNP, ACNP, ANNP, BANP or ANP.", + supportedValues: []string{"K8sNP", "ACNP", "ANNP", "BANP", "ANP"}, + }, { name: "table", usage: "Comma separated Antrea OVS flow table names or numbers", diff --git a/pkg/ovs/openflow/utils.go b/pkg/ovs/openflow/utils.go index 1fc53beda5c..f0df875dcd5 100644 --- a/pkg/ovs/openflow/utils.go +++ b/pkg/ovs/openflow/utils.go @@ -17,6 +17,7 @@ package openflow import ( "fmt" "net" + "slices" "strings" "antrea.io/libOpenflow/openflow15" @@ -1222,8 +1223,22 @@ func FlowModToString(flowMod *openflow15.FlowMod) string { return fmt.Sprintf("%s, %s %s", getFlowModBaseString(flowMod), getFlowModMatch(flowMod), getFlowModAction(flowMod)) } -func FlowModMatchString(flowMod *openflow15.FlowMod) string { - return fmt.Sprintf("table=%d,%s", flowMod.TableId, getFlowModMatch(flowMod)) +func FlowModMatchString(flowMod *openflow15.FlowMod, omitFields ...string) string { + flowModMatch := getFlowModMatch(flowMod) + if len(omitFields) == 0 { + return fmt.Sprintf("table=%d,%s", flowMod.TableId, flowModMatch) + } + var flowDumpMatch []string + for _, m := range strings.Split(flowModMatch, ",") { + // Omit specific fields if needed. For example, the priority match field is not supported + // for the ovs-ofctl dump-flows command, and should be removed. + if !slices.ContainsFunc(omitFields, func(field string) bool { + return strings.HasPrefix(m, field) + }) { + flowDumpMatch = append(flowDumpMatch, m) + } + } + return fmt.Sprintf("table=%d,%s", flowMod.TableId, strings.Join(flowDumpMatch, ",")) } func GroupModToString(groupMod *openflow15.GroupMod) string { diff --git a/pkg/ovs/openflow/utils_test.go b/pkg/ovs/openflow/utils_test.go index bf88f902eee..e0d52e13610 100644 --- a/pkg/ovs/openflow/utils_test.go +++ b/pkg/ovs/openflow/utils_test.go @@ -143,7 +143,7 @@ func TestFlowModToString(t *testing.T) { newFb := *(basicFB.CopyToBuilder(basicFB.FlowPriority(), false).(*ofFlowBuilder)) f := tt.flowFunc(&newFb) messages, err := f.GetBundleMessages(AddMessage) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, 1, len(messages)) fm, ok := messages[0].GetMessage().(*openflow15.FlowMod) assert.True(t, ok) @@ -303,7 +303,7 @@ func TestFlowModMatchString(t *testing.T) { newFb := *(basicFB.CopyToBuilder(basicFB.FlowPriority(), false).(*ofFlowBuilder)) f := tt.flowFunc(&newFb) messages, err := f.GetBundleMessages(AddMessage) - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, 1, len(messages)) fm, ok := messages[0].GetMessage().(*openflow15.FlowMod) assert.True(t, ok) @@ -313,6 +313,81 @@ func TestFlowModMatchString(t *testing.T) { } } +func TestFlowModStringForDumpCommand(t *testing.T) { + rm := &RegMark{field: NewRegField(0, 0, 3), value: 2} + table := &ofTable{Table: &ofctrl.Table{TableId: 1}} + basicFB := table.BuildFlow(100).(*ofFlowBuilder) + basicFB.Cookie(0x12345678).MatchInPort(3) + for _, tt := range []struct { + name string + flowFunc func(fb *ofFlowBuilder) Flow + expectedMatch string + }{ + { + name: "reg mark flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchRegMark(rm). + MatchXXReg(1, ip6Dst). + Done() + }, + expectedMatch: "table=1,reg0=0x2/0xf,xxreg1=0xfe000000000000000000000ca80a03,in_port=3", + }, + { + name: "IPv4 flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchDstMAC(ethDst).MatchSrcMAC(ethSrc).MatchDstIP(ipDst).MatchSrcIP(ipSrc).Done() + }, + expectedMatch: "table=1,in_port=3,dl_src=10:1a:1b:1c:1d:1f,dl_dst=20:2a:2b:2c:2d:2f,nw_src=192.168.10.2,nw_dst=192.168.20.3", + }, + { + name: "IPv4 net flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchSrcIPNet(*ipSrcNet).MatchDstIPNet(*ipDstNet).Done() + }, + expectedMatch: "table=1,in_port=3,nw_src=192.168.10.0/24,nw_dst=192.168.20.0/24", + }, + { + name: "IPv6 flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchDstIP(ip6Dst).MatchSrcIP(ip6Src).Done() + }, + expectedMatch: "table=1,in_port=3,ipv6_src=fe::ca8:a02,ipv6_dst=fe::ca8:a03", + }, + { + name: "IPv4 UDP flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchIPProtocolValue(false, 17).MatchDstPort(8080, nil).Done() + }, + expectedMatch: "table=1,udp,in_port=3,tp_dst=8080", + }, { + name: "IPv4 ICMP flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchProtocol(ProtocolICMP).MatchICMPCode(0).MatchICMPType(8).Done() + }, + expectedMatch: "table=1,icmp,in_port=3,icmp_type=8,icmp_code=0", + }, + { + name: "conjunction flow", + flowFunc: func(fb *ofFlowBuilder) Flow { + return fb.MatchProtocol(ProtocolIP).MatchConjID(101).Done() + }, + expectedMatch: "table=1,conj_id=101,ip,in_port=3", + }, + } { + t.Run(tt.name, func(t *testing.T) { + newFb := *(basicFB.CopyToBuilder(basicFB.FlowPriority(), false).(*ofFlowBuilder)) + f := tt.flowFunc(&newFb) + messages, err := f.GetBundleMessages(AddMessage) + require.NoError(t, err) + require.Equal(t, 1, len(messages)) + fm, ok := messages[0].GetMessage().(*openflow15.FlowMod) + assert.True(t, ok) + fmStr := FlowModMatchString(fm, "priority") + assert.Equal(t, tt.expectedMatch, fmStr) + }) + } +} + func TestGroupModToString(t *testing.T) { rf := NewRegField(1, 0, 31) for _, tt := range []struct { diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 1ebf4fa0f06..886ec8f3ab5 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -17,6 +17,7 @@ package querier import ( v1 "k8s.io/api/core/v1" apitypes "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" "antrea.io/antrea/pkg/agent/apis" "antrea.io/antrea/pkg/agent/interfacestore" @@ -108,10 +109,29 @@ type NetworkPolicyQueryFilter struct { SourceName string // The namespace of the original Namespace that the internal NetworkPolicy is created for. Namespace string - // The type of the original NetworkPolicy that the internal NetworkPolicy is created for.(K8sNP, ACNP, ANNP) + // The type of the original NetworkPolicy that the internal NetworkPolicy is created for.(K8sNP, ACNP, ANNP, ANP and BANP) SourceType cpv1beta.NetworkPolicyType } +// From user shorthand input to cpv1beta1.NetworkPolicyType +var NetworkPolicyTypeMap = map[string]cpv1beta.NetworkPolicyType{ + "K8SNP": cpv1beta.K8sNetworkPolicy, + "ACNP": cpv1beta.AntreaClusterNetworkPolicy, + "ANNP": cpv1beta.AntreaNetworkPolicy, + "ANP": cpv1beta.AdminNetworkPolicy, + "BANP": cpv1beta.BaselineAdminNetworkPolicy, +} + +func GetNetworkPolicyTypeShorthands() []string { + validTypes := make([]string, 0, len(NetworkPolicyTypeMap)) + for k := range NetworkPolicyTypeMap { + validTypes = append(validTypes, k) + } + return validTypes +} + +var NamespaceScopedPolicyTypes = sets.New[string]("ANNP", "K8SNP") + // ServiceExternalIPStatusQuerier queries the Service external IP status for debugging purposes. // Ideally, every Node should have consistent results eventually. This should only be used when // ServiceExternalIP feature is enabled.