diff --git a/pkg/agent/controller/trafficcontrol/controller.go b/pkg/agent/controller/trafficcontrol/controller.go index 1c0d8720a77..f76e2b9a250 100644 --- a/pkg/agent/controller/trafficcontrol/controller.go +++ b/pkg/agent/controller/trafficcontrol/controller.go @@ -920,7 +920,7 @@ func (c *Controller) syncTrafficControl(tcName string) error { for _, port := range sets.List(newOfPorts) { ofPorts = append(ofPorts, uint32(port)) } - if err = c.ofClient.InstallTrafficControlMarkFlows(tc.Name, ofPorts, targetOFPort, tc.Spec.Direction, tc.Spec.Action); err != nil { + if err = c.ofClient.InstallTrafficControlMarkFlows(tc.Name, ofPorts, targetOFPort, tc.Spec.Direction, tc.Spec.Action, openflow.TrafficControlFlowPriorityMedium); err != nil { return err } } diff --git a/pkg/agent/controller/trafficcontrol/controller_test.go b/pkg/agent/controller/trafficcontrol/controller_test.go index 3dab23a1fac..b38366d9002 100644 --- a/pkg/agent/controller/trafficcontrol/controller_test.go +++ b/pkg/agent/controller/trafficcontrol/controller_test.go @@ -35,6 +35,7 @@ import ( "k8s.io/client-go/tools/cache" "antrea.io/antrea/pkg/agent/interfacestore" + "antrea.io/antrea/pkg/agent/openflow" openflowtest "antrea.io/antrea/pkg/agent/openflow/testing" "antrea.io/antrea/pkg/agent/types" "antrea.io/antrea/pkg/agent/util" @@ -332,7 +333,7 @@ func TestTrafficControlAdd(t *testing.T) { mockOVSBridgeClient.EXPECT().CreatePort(networkDeviceName, networkDeviceName, externalIDs) mockOVSBridgeClient.EXPECT().GetOFPort(networkDeviceName, false) mockOVSCtlClient.EXPECT().SetPortNoFlood(0) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -346,7 +347,7 @@ func TestTrafficControlAdd(t *testing.T) { mockOVSBridgeClient.EXPECT().CreateTunnelPortExt(gomock.Any(), ovsconfig.TunnelType(ovsconfig.VXLANTunnel), int32(0), false, "", remoteIP, "", "", extraOptions, externalIDs) mockOVSBridgeClient.EXPECT().GetOFPort(gomock.Any(), false) mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -360,7 +361,7 @@ func TestTrafficControlAdd(t *testing.T) { mockOVSBridgeClient.EXPECT().CreateTunnelPortExt(gomock.Any(), ovsconfig.TunnelType(ovsconfig.GeneveTunnel), int32(0), false, "", remoteIP, "", "", extraOptions, externalIDs) mockOVSBridgeClient.EXPECT().GetOFPort(gomock.Any(), false) mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -374,7 +375,7 @@ func TestTrafficControlAdd(t *testing.T) { mockOVSBridgeClient.EXPECT().CreateTunnelPortExt(gomock.Any(), ovsconfig.TunnelType(ovsconfig.GRETunnel), int32(0), false, "", remoteIP, "", "", extraOptions, externalIDs) mockOVSBridgeClient.EXPECT().GetOFPort(gomock.Any(), false) mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -388,7 +389,7 @@ func TestTrafficControlAdd(t *testing.T) { mockOVSBridgeClient.EXPECT().CreateTunnelPortExt(gomock.Any(), ovsconfig.TunnelType(ovsconfig.ERSPANTunnel), int32(0), false, "", remoteIP, "", "", extraOptions, externalIDs) mockOVSBridgeClient.EXPECT().GetOFPort(gomock.Any(), false) mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -402,7 +403,7 @@ func TestTrafficControlAdd(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort2OFPort, directionIngress, actionRedirect) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort2OFPort, directionIngress, actionRedirect, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -415,7 +416,7 @@ func TestTrafficControlAdd(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort1OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -428,7 +429,7 @@ func TestTrafficControlAdd(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod2OFPort}), targetPort1OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod2OFPort}), targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -441,7 +442,7 @@ func TestTrafficControlAdd(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod2OFPort}, targetPort1OFPort, directionIngress, actionRedirect) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod2OFPort}, targetPort1OFPort, directionIngress, actionRedirect, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -454,7 +455,7 @@ func TestTrafficControlAdd(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionRedirect) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionRedirect, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -467,7 +468,7 @@ func TestTrafficControlAdd(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod1OFPort, pod2OFPort, pod3OFPort, pod4OFPort}, targetPort1OFPort, directionIngress, actionRedirect) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod1OFPort, pod2OFPort, pod3OFPort, pod4OFPort}, targetPort1OFPort, directionIngress, actionRedirect, openflow.TrafficControlFlowPriorityMedium) }, }, } @@ -520,7 +521,7 @@ func TestTrafficControlUpdate(t *testing.T) { mockOVSBridgeClient.EXPECT().CreatePort(targetPort2Name, targetPort2Name, externalIDs) mockOVSBridgeClient.EXPECT().GetOFPort(targetPort2Name, false) mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -534,7 +535,7 @@ func TestTrafficControlUpdate(t *testing.T) { mockOVSBridgeClient.EXPECT().GetOFPort(returnPort1Name, false) mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) mockOFClient.EXPECT().InstallTrafficControlReturnPortFlow(gomock.Any()) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort1OFPort, directionIngress, actionRedirect) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort1OFPort, directionIngress, actionRedirect, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -544,7 +545,7 @@ func TestTrafficControlUpdate(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort1OFPort, directionEgress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), targetPort1OFPort, directionEgress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -554,7 +555,7 @@ func TestTrafficControlUpdate(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod2OFPort, pod4OFPort}), targetPort1OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod2OFPort, pod4OFPort}), targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -564,7 +565,7 @@ func TestTrafficControlUpdate(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient, mockOVSBridgeClient *ovsconfigtest.MockOVSBridgeClient, mockOVSCtlClient *ovsctltest.MockOVSCtlClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod3OFPort}, targetPort1OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod3OFPort}, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, } @@ -637,8 +638,8 @@ func TestSharedTargetPort(t *testing.T) { c.mockOVSBridgeClient.EXPECT().GetOFPort(targetPort1Name, false).Times(1) c.mockOVSCtlClient.EXPECT().SetPortNoFlood(gomock.Any()) // Mark flows for TrafficControl tc1 and tc2 are expected to be installed. - c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror) - c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, gomock.InAnyOrder([]uint32{pod2OFPort, pod4OFPort}), gomock.Any(), directionIngress, actionMirror) + c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, gomock.InAnyOrder([]uint32{pod1OFPort, pod3OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) + c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, gomock.InAnyOrder([]uint32{pod2OFPort, pod4OFPort}), gomock.Any(), directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) // Process the TrafficControl ADD events for TrafficControl tc1 and tc2. waitEvents(t, 2, c) @@ -721,7 +722,7 @@ func TestPodUpdateFromCNIServer(t *testing.T) { require.Equal(t, expectedState, c.tcStates[tc1Name]) // Mark flows are expected to be installed after the interface of the Pod is ready. - c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod1OFPort}, targetPort1OFPort, directionIngress, actionMirror) + c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod1OFPort}, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) // Add the interface information of the test Pod to interface store to mock the interface of the Pod is ready, then // add an update event to podUpdateChannel to trigger a TrafficControl event. @@ -772,7 +773,7 @@ func TestPodLabelsUpdate(t *testing.T) { eventsTriggeredByPodLabelsUpdate: 2, expectedPodBinding: nil, expectedCalls: func(mockOFClient *openflowtest.MockClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -790,8 +791,8 @@ func TestPodLabelsUpdate(t *testing.T) { eventsTriggeredByPodEffectiveTCUpdate: 1, expectedPodBinding: &podToTCBinding{effectiveTC: tc2Name, alternativeTCs: sets.New[string]()}, expectedCalls: func(mockOFClient *openflowtest.MockClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -802,8 +803,8 @@ func TestPodLabelsUpdate(t *testing.T) { eventsTriggeredByPodEffectiveTCUpdate: 1, expectedPodBinding: &podToTCBinding{effectiveTC: tc2Name, alternativeTCs: sets.New[string](tc3Name)}, expectedCalls: func(mockOFClient *openflowtest.MockClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -947,7 +948,7 @@ func TestNamespaceLabelsUpdate(t *testing.T) { updatedNS: newNamespace("ns1", nil), eventsTriggeredByNSLabelsUpdate: 2, expectedCalls: func(mockOFClient *openflowtest.MockClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -965,8 +966,8 @@ func TestNamespaceLabelsUpdate(t *testing.T) { eventsTriggeredByPodEffectiveTCUpdate: 1, expectedPodBinding: &podToTCBinding{effectiveTC: tc2Name, alternativeTCs: sets.New[string]()}, expectedCalls: func(mockOFClient *openflowtest.MockClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -977,8 +978,8 @@ func TestNamespaceLabelsUpdate(t *testing.T) { eventsTriggeredByPodEffectiveTCUpdate: 1, expectedPodBinding: &podToTCBinding{effectiveTC: tc2Name, alternativeTCs: sets.New[string](tc3Name)}, expectedCalls: func(mockOFClient *openflowtest.MockClient) { - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror) - mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, nil, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) + mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc2Name, []uint32{pod1OFPort}, targetPort2OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) }, }, { @@ -1156,7 +1157,7 @@ func TestPodDelete(t *testing.T) { c.queue.Done(item) } - c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod3OFPort}, targetPort1OFPort, directionIngress, actionMirror) + c.mockOFClient.EXPECT().InstallTrafficControlMarkFlows(tc1Name, []uint32{pod3OFPort}, targetPort1OFPort, directionIngress, actionMirror, openflow.TrafficControlFlowPriorityMedium) expectedPod3Binding := &podToTCBinding{ effectiveTC: tc1Name, alternativeTCs: sets.New[string](tc2Name, tc3Name), diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go index 45acf46aac5..f405113ecb9 100644 --- a/pkg/agent/openflow/client.go +++ b/pkg/agent/openflow/client.go @@ -39,6 +39,12 @@ import ( const maxRetryForOFSwitch = 5 +const ( + TrafficControlFlowPriorityHigh = "high" + TrafficControlFlowPriorityMedium = "medium" + TrafficControlFlowPriorityLow = "low" +) + // Client is the interface to program OVS flows for entity connectivity of Antrea. type Client interface { // Initialize sets up all basic flows on the specific OVS bridge. It returns a channel which @@ -323,7 +329,12 @@ type Client interface { igmp ofutil.Message) error // InstallTrafficControlMarkFlows installs the flows to mark the packets for a traffic control rule. - InstallTrafficControlMarkFlows(name string, sourceOFPorts []uint32, targetOFPort uint32, direction crdv1alpha2.Direction, action crdv1alpha2.TrafficControlAction) error + InstallTrafficControlMarkFlows(name string, + sourceOFPorts []uint32, + targetOFPort uint32, + direction crdv1alpha2.Direction, + action crdv1alpha2.TrafficControlAction, + priority string) error // UninstallTrafficControlMarkFlows removes the flows for a traffic control rule. UninstallTrafficControlMarkFlows(name string) error @@ -1449,9 +1460,18 @@ func (c *client) SendIGMPQueryPacketOut( return c.bridge.SendPacketOut(packetOutObj) } -func (c *client) InstallTrafficControlMarkFlows(name string, sourceOFPorts []uint32, targetOFPort uint32, direction crdv1alpha2.Direction, action crdv1alpha2.TrafficControlAction) error { - flows := c.featurePodConnectivity.trafficControlMarkFlows(sourceOFPorts, targetOFPort, direction, action) - cacheKey := fmt.Sprintf("tc_%s", name) +func (c *client) InstallTrafficControlMarkFlows(name string, + sourceOFPorts []uint32, + targetOFPort uint32, + direction crdv1alpha2.Direction, + action crdv1alpha2.TrafficControlAction, + priority string) error { + ofPriority, err := getOFPriority(priority) + if err != nil { + return err + } + flows := c.featurePodConnectivity.trafficControlMarkFlows(sourceOFPorts, targetOFPort, direction, action, ofPriority) + cacheKey := fmt.Sprintf("tc_%s_%s", name, priority) c.replayMutex.RLock() defer c.replayMutex.RUnlock() return c.modifyFlows(c.featurePodConnectivity.tcCachedFlows, cacheKey, flows) @@ -1660,3 +1680,19 @@ func (c *client) getMeterStats() { klog.ErrorS(err, "Failed to get OVS meter stats") } } + +func getOFPriority(tcFlowPriority string) (uint16, error) { + var ofPriority uint16 + var err error + switch tcFlowPriority { + case TrafficControlFlowPriorityHigh: + ofPriority = priorityHigh + case TrafficControlFlowPriorityMedium: + ofPriority = priorityNormal + case TrafficControlFlowPriorityLow: + ofPriority = priorityLow + default: + err = fmt.Errorf("unknown traffic control flow priority: %s", tcFlowPriority) + } + return ofPriority, err +} diff --git a/pkg/agent/openflow/client_test.go b/pkg/agent/openflow/client_test.go index 8ce11c86263..ee889ce5d7a 100644 --- a/pkg/agent/openflow/client_test.go +++ b/pkg/agent/openflow/client_test.go @@ -2425,7 +2425,7 @@ func Test_client_InstallTrafficControlMarkFlows(t *testing.T) { cacheKey := fmt.Sprintf("tc_%s", tcName) - assert.NoError(t, fc.InstallTrafficControlMarkFlows(tcName, sourceOFPorts, targetOFPort, tc.direction, tc.action)) + assert.NoError(t, fc.InstallTrafficControlMarkFlows(tcName, sourceOFPorts, targetOFPort, tc.direction, tc.action, TrafficControlFlowPriorityMedium)) fCacheI, ok := fc.featurePodConnectivity.tcCachedFlows.Load(cacheKey) require.True(t, ok) assert.ElementsMatch(t, tc.expectedFlows, getFlowStrings(fCacheI)) @@ -2768,7 +2768,7 @@ func Test_client_ReplayFlows(t *testing.T) { ) sourceOFPorts := []uint32{50, 100} targetOFPort := uint32(200) - addFlowInCache(fc.featurePodConnectivity.tcCachedFlows, "tcFlows", fc.featurePodConnectivity.trafficControlMarkFlows(sourceOFPorts, targetOFPort, v1alpha2.DirectionEgress, v1alpha2.ActionMirror)) + addFlowInCache(fc.featurePodConnectivity.tcCachedFlows, "tcFlows", fc.featurePodConnectivity.trafficControlMarkFlows(sourceOFPorts, targetOFPort, v1alpha2.DirectionEgress, v1alpha2.ActionMirror, priorityNormal)) replayedFlows = append(replayedFlows, "cookie=0x1010000000000, table=TrafficControl, priority=200,in_port=50 actions=set_field:0xc8->reg9,set_field:0x400000/0xc00000->reg4,goto_table:IngressSecurityClassifier", "cookie=0x1010000000000, table=TrafficControl, priority=200,in_port=100 actions=set_field:0xc8->reg9,set_field:0x400000/0xc00000->reg4,goto_table:IngressSecurityClassifier", diff --git a/pkg/agent/openflow/network_policy.go b/pkg/agent/openflow/network_policy.go index 8a8c96a344d..9ea7de9983c 100644 --- a/pkg/agent/openflow/network_policy.go +++ b/pkg/agent/openflow/network_policy.go @@ -2218,7 +2218,7 @@ func (f *featureNetworkPolicy) l7NPTrafficControlFlows() []binding.Flow { // This generates the flow to output the packets marked with L7NPRedirectCTMark to an application-aware engine // via the target ofPort. Note that, before outputting the packets, VLAN ID stored on field L7NPRuleVlanIDCTMarkField // will be copied to VLAN ID register (OXM_OF_VLAN_VID) to set VLAN ID of the packets. - OutputTable.ofTable.BuildFlow(priorityHigh+1). + OutputTable.ofTable.BuildFlow(priorityHigh+2). Cookie(cookieID). MatchRegMark(OutputToOFPortRegMark). MatchCTMark(L7NPRedirectCTMark). @@ -2239,7 +2239,7 @@ func (f *featureNetworkPolicy) l7NPTrafficControlFlows() []binding.Flow { Done(), // This generates the flow to forward the returned packets (with FromTCReturnRegMark) to stageOutput directly // after loading output port number to reg1 in L2ForwardingCalcTable. - TrafficControlTable.ofTable.BuildFlow(priorityHigh). + TrafficControlTable.ofTable.BuildFlow(priorityHigh+1). Cookie(cookieID). MatchRegMark(OutputToOFPortRegMark, FromTCReturnRegMark). Action().GotoStage(stageOutput). diff --git a/pkg/agent/openflow/network_policy_test.go b/pkg/agent/openflow/network_policy_test.go index 898b178f7b8..355d3f4a23b 100644 --- a/pkg/agent/openflow/network_policy_test.go +++ b/pkg/agent/openflow/network_policy_test.go @@ -1403,8 +1403,8 @@ func networkPolicyInitFlows(ovsMeterSupported, externalNodeEnabled, l7NetworkPol if l7NetworkPolicyEnabled { initFlows = append(initFlows, "cookie=0x1020000000000, table=Classifier, priority=200,in_port=11,vlan_tci=0x1000/0x1000 actions=pop_vlan,set_field:0x6/0xf->reg0,goto_table:L3Forwarding", - "cookie=0x1020000000000, table=TrafficControl, priority=210,reg0=0x200006/0x60000f actions=goto_table:Output", - "cookie=0x1020000000000, table=Output, priority=211,ct_mark=0x80/0x80,reg0=0x200000/0x600000 actions=push_vlan:0x8100,move:NXM_NX_CT_LABEL[64..75]->OXM_OF_VLAN_VID[0..11],output:10", + "cookie=0x1020000000000, table=TrafficControl, priority=211,reg0=0x200006/0x60000f actions=goto_table:Output", + "cookie=0x1020000000000, table=Output, priority=212,ct_mark=0x80/0x80,reg0=0x200000/0x600000 actions=push_vlan:0x8100,move:NXM_NX_CT_LABEL[64..75]->OXM_OF_VLAN_VID[0..11],output:10", ) } return initFlows diff --git a/pkg/agent/openflow/pod_connectivity.go b/pkg/agent/openflow/pod_connectivity.go index 7a073b5bdbd..ec9b366e65c 100644 --- a/pkg/agent/openflow/pod_connectivity.go +++ b/pkg/agent/openflow/pod_connectivity.go @@ -200,7 +200,11 @@ func (f *featurePodConnectivity) replayFlows() []*openflow15.FlowMod { } // trafficControlMarkFlows generates the flows to mark the packets that need to be redirected or mirrored. -func (f *featurePodConnectivity) trafficControlMarkFlows(sourceOFPorts []uint32, targetOFPort uint32, direction v1alpha2.Direction, action v1alpha2.TrafficControlAction) []binding.Flow { +func (f *featurePodConnectivity) trafficControlMarkFlows(sourceOFPorts []uint32, + targetOFPort uint32, + direction v1alpha2.Direction, + action v1alpha2.TrafficControlAction, + priority uint16) []binding.Flow { cookieID := f.cookieAllocator.Request(f.category).Raw() var actionRegMark *binding.RegMark if action == v1alpha2.ActionRedirect { @@ -212,7 +216,7 @@ func (f *featurePodConnectivity) trafficControlMarkFlows(sourceOFPorts []uint32, for _, port := range sourceOFPorts { if direction == v1alpha2.DirectionIngress || direction == v1alpha2.DirectionBoth { // This generates the flow to mark the packets destined for a provided port. - flows = append(flows, TrafficControlTable.ofTable.BuildFlow(priorityNormal). + flows = append(flows, TrafficControlTable.ofTable.BuildFlow(priority). Cookie(cookieID). MatchRegFieldWithValue(TargetOFPortField, port). Action().LoadToRegField(TrafficControlTargetOFPortField, targetOFPort). @@ -222,7 +226,7 @@ func (f *featurePodConnectivity) trafficControlMarkFlows(sourceOFPorts []uint32, } // This generates the flow to mark the packets sourced from a provided port. if direction == v1alpha2.DirectionEgress || direction == v1alpha2.DirectionBoth { - flows = append(flows, TrafficControlTable.ofTable.BuildFlow(priorityNormal). + flows = append(flows, TrafficControlTable.ofTable.BuildFlow(priority). Cookie(cookieID). MatchInPort(port). Action().LoadToRegField(TrafficControlTargetOFPortField, targetOFPort). diff --git a/pkg/agent/openflow/testing/mock_openflow.go b/pkg/agent/openflow/testing/mock_openflow.go index af1e9a34cc2..e1f9723d3e9 100644 --- a/pkg/agent/openflow/testing/mock_openflow.go +++ b/pkg/agent/openflow/testing/mock_openflow.go @@ -532,17 +532,17 @@ func (mr *MockClientMockRecorder) InstallTraceflowFlows(arg0, arg1, arg2, arg3, } // InstallTrafficControlMarkFlows mocks base method. -func (m *MockClient) InstallTrafficControlMarkFlows(arg0 string, arg1 []uint32, arg2 uint32, arg3 v1alpha2.Direction, arg4 v1alpha2.TrafficControlAction) error { +func (m *MockClient) InstallTrafficControlMarkFlows(arg0 string, arg1 []uint32, arg2 uint32, arg3 v1alpha2.Direction, arg4 v1alpha2.TrafficControlAction, arg5 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InstallTrafficControlMarkFlows", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "InstallTrafficControlMarkFlows", arg0, arg1, arg2, arg3, arg4, arg5) ret0, _ := ret[0].(error) return ret0 } // InstallTrafficControlMarkFlows indicates an expected call of InstallTrafficControlMarkFlows. -func (mr *MockClientMockRecorder) InstallTrafficControlMarkFlows(arg0, arg1, arg2, arg3, arg4 any) *gomock.Call { +func (mr *MockClientMockRecorder) InstallTrafficControlMarkFlows(arg0, arg1, arg2, arg3, arg4, arg5 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallTrafficControlMarkFlows", reflect.TypeOf((*MockClient)(nil).InstallTrafficControlMarkFlows), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallTrafficControlMarkFlows", reflect.TypeOf((*MockClient)(nil).InstallTrafficControlMarkFlows), arg0, arg1, arg2, arg3, arg4, arg5) } // InstallTrafficControlReturnPortFlow mocks base method. diff --git a/test/integration/agent/openflow_test.go b/test/integration/agent/openflow_test.go index 8070a45a052..3d71727c31e 100644 --- a/test/integration/agent/openflow_test.go +++ b/test/integration/agent/openflow_test.go @@ -1874,7 +1874,7 @@ func TestTrafficControlFlows(t *testing.T) { returnOFPort := uint32(201) expectedFlows := prepareTrafficControlFlows(sourceOFPorts, targetOFPort, returnOFPort) c.InstallTrafficControlReturnPortFlow(returnOFPort) - c.InstallTrafficControlMarkFlows("tc", sourceOFPorts, targetOFPort, v1alpha2.DirectionBoth, v1alpha2.ActionRedirect) + c.InstallTrafficControlMarkFlows("tc", sourceOFPorts, targetOFPort, v1alpha2.DirectionBoth, v1alpha2.ActionRedirect, ofClient.TrafficControlFlowPriorityMedium) for _, tableFlow := range expectedFlows { ofTestUtils.CheckFlowExists(t, ovsCtlClient, tableFlow.tableName, 0, true, tableFlow.flows) }