From 50c1726ab8134d3ccc5e07cd1f1df8765a2df93d Mon Sep 17 00:00:00 2001 From: wenyingd Date: Mon, 9 Aug 2021 07:23:01 -0700 Subject: [PATCH] Modify OF table name 1. Use Multipart messages to query OVS table features and modify the table name property if the table is defined in Antrea pipeline 2. Use openflow.Table in the ofClient under pkg/agent/openflow directly, and remove the pipeline map and FlowTables in pipeline.go 3. Remove the typed type TableIDType, and use uint8 for table id directly. Signed-off-by: wenyingd --- go.mod | 4 +- go.sum | 8 +- .../apiserver/handlers/ovsflows/handler.go | 18 +- .../handlers/ovsflows/handler_test.go | 16 + .../controller/networkpolicy/packetin.go | 22 +- .../controller/networkpolicy/reconciler.go | 36 +- .../networkpolicy/reconciler_test.go | 6 +- pkg/agent/controller/traceflow/packetin.go | 32 +- .../controller/traceflow/packetin_test.go | 8 +- .../connections/conntrack_connections_test.go | 4 +- pkg/agent/openflow/client.go | 2 +- pkg/agent/openflow/client_test.go | 2 +- pkg/agent/openflow/network_policy.go | 40 +- pkg/agent/openflow/network_policy_test.go | 143 ++-- pkg/agent/openflow/pipeline.go | 755 ++++++++---------- pkg/agent/openflow/pipeline_windows.go | 26 +- pkg/agent/openflow/testing/mock_openflow.go | 2 +- pkg/agent/querier/querier.go | 4 +- pkg/agent/querier/querier_test.go | 1 + pkg/agent/types/networkpolicy.go | 2 +- pkg/antctl/antctl.go | 4 +- pkg/ovs/openflow/interfaces.go | 30 +- pkg/ovs/openflow/ofctrl_action.go | 18 +- pkg/ovs/openflow/ofctrl_bridge.go | 132 ++- pkg/ovs/openflow/ofctrl_flow.go | 2 +- pkg/ovs/openflow/ofctrl_flow_test.go | 16 +- pkg/ovs/openflow/ofctrl_group.go | 4 +- pkg/ovs/openflow/testing/mock_openflow.go | 60 +- pkg/ovs/ovsctl/interface.go | 3 + pkg/ovs/ovsctl/ofctl.go | 18 +- pkg/ovs/ovsctl/testing/mock_ovsctl.go | 19 + plugins/octant/go.sum | 4 +- test/integration/agent/openflow_test.go | 12 +- test/integration/ovs/ofctrl_test.go | 58 +- test/integration/ovs/openflow_test_utils.go | 4 +- 35 files changed, 831 insertions(+), 684 deletions(-) diff --git a/go.mod b/go.mod index c3682576aad..cfa76cf878e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module antrea.io/antrea go 1.17 require ( - antrea.io/libOpenflow v0.2.0 - antrea.io/ofnet v0.1.0 + antrea.io/libOpenflow v0.5.2 + antrea.io/ofnet v0.2.3 github.com/Mellanox/sriovnet v1.0.2 github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331 github.com/Microsoft/hcsshim v0.8.9 diff --git a/go.sum b/go.sum index 974aba166dd..fe3d355e78e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -antrea.io/libOpenflow v0.2.0 h1:bBNT3CI8q2FMQRdphP0dynImRK1LBDmA+cQOu7JULj4= -antrea.io/libOpenflow v0.2.0/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o= -antrea.io/ofnet v0.1.0 h1:r5c/TM5pa8xSVd5xEUj1L2vYfc4EjIzCWs6cHbeuVFc= -antrea.io/ofnet v0.1.0/go.mod h1:fLmHHD9XWeVza2pz/HEdLkGyA7pNutxlXCqodlwWQsA= +antrea.io/libOpenflow v0.5.2 h1:EFTyAHlG6UH8ZHpiPi6QPVPETqoIk0eB2B6i88VqacM= +antrea.io/libOpenflow v0.5.2/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o= +antrea.io/ofnet v0.2.3 h1:wxXOqWaT5swtn9Ly6hV7pqvIgfmrr3aQfCGVQqHykr4= +antrea.io/ofnet v0.2.3/go.mod h1:jW4ICTvGjLO+Qr6GG/Glmjy34k6k/TfVlQhOm76UH84= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= diff --git a/pkg/agent/apiserver/handlers/ovsflows/handler.go b/pkg/agent/apiserver/handlers/ovsflows/handler.go index ac7afcaa41c..a3971cecf23 100644 --- a/pkg/agent/apiserver/handlers/ovsflows/handler.go +++ b/pkg/agent/apiserver/handlers/ovsflows/handler.go @@ -30,6 +30,12 @@ import ( "antrea.io/antrea/pkg/querier" ) +var ( + // Use function variables for tests. + getFlowTableName = openflow.GetFlowTableName + getFlowTableID = openflow.GetFlowTableID +) + // Response is the response struct of ovsflows command. type Response struct { Flow string `json:"flow,omitempty"` @@ -50,12 +56,12 @@ func dumpMatchedFlows(aq agentquerier.AgentQuerier, flowKeys []string) ([]Respon return resps, nil } -func dumpFlows(aq agentquerier.AgentQuerier, table binding.TableIDType) ([]Response, error) { +func dumpFlows(aq agentquerier.AgentQuerier, table uint8) ([]Response, error) { resps := []Response{} var flowStrs []string var err error if table != binding.TableIDAll { - flowStrs, err = aq.GetOVSCtlClient().DumpTableFlows(uint8(table)) + flowStrs, err = aq.GetOVSCtlClient().DumpTableFlows(table) } else { flowStrs, err = aq.GetOVSCtlClient().DumpFlows() } @@ -89,16 +95,16 @@ func getTableFlows(aq agentquerier.AgentQuerier, tables string) ([]Response, err var resps []Response for _, tableSeg := range strings.Split(tables, ",") { tableSeg = strings.TrimSpace(tableSeg) - var tableNumber binding.TableIDType + var tableNumber uint8 // Table nubmer is a 8-bit unsigned integer. n, err := strconv.ParseUint(tableSeg, 10, 8) if err == nil { - tableNumber = binding.TableIDType(n) - if openflow.GetFlowTableName(tableNumber) == "" { + tableNumber = uint8(n) + if getFlowTableName(tableNumber) == "" { return nil, nil } } else { - tableNumber = openflow.GetFlowTableNumber(tableSeg) + tableNumber = getFlowTableID(tableSeg) if tableNumber == binding.TableIDAll { return nil, nil } diff --git a/pkg/agent/apiserver/handlers/ovsflows/handler_test.go b/pkg/agent/apiserver/handlers/ovsflows/handler_test.go index d115f490742..5f0ea97a3cc 100644 --- a/pkg/agent/apiserver/handlers/ovsflows/handler_test.go +++ b/pkg/agent/apiserver/handlers/ovsflows/handler_test.go @@ -222,6 +222,8 @@ func TestTableFlows(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() + getFlowTableName = mockGetFlowTableName + getFlowTableID = mockGetFlowTableID testcases := []testCase{ { test: "Table 80", @@ -246,6 +248,20 @@ func TestTableFlows(t *testing.T) { } +func mockGetFlowTableName(id uint8) string { + if id == 80 { + return "IngressRule" + } + return "" +} + +func mockGetFlowTableID(tableName string) uint8 { + if tableName == "IngressRule" { + return 80 + } + return binding.TableIDAll +} + func TestGroups(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() diff --git a/pkg/agent/controller/networkpolicy/packetin.go b/pkg/agent/controller/networkpolicy/packetin.go index 6ca86c8d063..8a600fdafaf 100644 --- a/pkg/agent/controller/networkpolicy/packetin.go +++ b/pkg/agent/controller/networkpolicy/packetin.go @@ -94,19 +94,19 @@ func getMatchRegField(matchers *ofctrl.Matchers, field *binding.RegField) *ofctr // getMatch receives ofctrl matchers and table id, match field. // Modifies match field to Ingress/Egress register based on tableID. -func getMatch(matchers *ofctrl.Matchers, tableID binding.TableIDType, disposition uint32) *ofctrl.MatchField { +func getMatch(matchers *ofctrl.Matchers, tableID uint8, disposition uint32) *ofctrl.MatchField { // Get match from CNPDenyConjIDReg if disposition is not allow. if disposition != openflow.DispositionAllow { return getMatchRegField(matchers, openflow.CNPDenyConjIDField) } // Get match from ingress/egress reg if disposition is allow for _, table := range append(openflow.GetAntreaPolicyEgressTables(), openflow.EgressRuleTable) { - if tableID == table { + if tableID == table.GetID() { return getMatchRegField(matchers, openflow.TFEgressConjIDField) } } for _, table := range append(openflow.GetAntreaPolicyIngressTables(), openflow.IngressRuleTable) { - if tableID == table { + if tableID == table.GetID() { return getMatchRegField(matchers, openflow.TFIngressConjIDField) } } @@ -130,7 +130,7 @@ func getNetworkPolicyInfo(pktIn *ofctrl.PacketIn, c *Controller, ob *logInfo) er matchers := pktIn.GetMatches() var match *ofctrl.MatchField // Get table name - tableID := binding.TableIDType(pktIn.TableId) + tableID := pktIn.TableId ob.tableName = openflow.GetFlowTableName(tableID) // Get disposition Allow or Drop @@ -326,7 +326,7 @@ func (c *Controller) storeDenyConnection(pktIn *ofctrl.PacketIn) error { matchers := pktIn.GetMatches() var match *ofctrl.MatchField // Get table ID - tableID := binding.TableIDType(pktIn.TableId) + tableID := pktIn.TableId // Get disposition Allow, Drop or Reject match = getMatchRegField(matchers, openflow.APDispositionField) id, err := getInfoInReg(match, openflow.APDispositionField.GetRange().ToNXRange()) @@ -363,10 +363,10 @@ func (c *Controller) storeDenyConnection(pktIn *ofctrl.PacketIn) error { } } else { // For K8s NetworkPolicy implicit drop action, we cannot get name/namespace. - if tableID == openflow.IngressDefaultTable { + if tableID == openflow.IngressDefaultTable.GetID() { denyConn.IngressNetworkPolicyType = registry.PolicyTypeK8sNetworkPolicy denyConn.IngressNetworkPolicyRuleAction = flowexporter.RuleActionToUint8(disposition) - } else if tableID == openflow.EgressDefaultTable { + } else if tableID == openflow.EgressDefaultTable.GetID() { denyConn.EgressNetworkPolicyType = registry.PolicyTypeK8sNetworkPolicy denyConn.EgressNetworkPolicyRuleAction = flowexporter.RuleActionToUint8(disposition) } @@ -375,18 +375,18 @@ func (c *Controller) storeDenyConnection(pktIn *ofctrl.PacketIn) error { return nil } -func isAntreaPolicyIngressTable(tableID binding.TableIDType) bool { +func isAntreaPolicyIngressTable(tableID uint8) bool { for _, table := range openflow.GetAntreaPolicyIngressTables() { - if table == tableID { + if table.GetID() == tableID { return true } } return false } -func isAntreaPolicyEgressTable(tableID binding.TableIDType) bool { +func isAntreaPolicyEgressTable(tableID uint8) bool { for _, table := range openflow.GetAntreaPolicyEgressTables() { - if table == tableID { + if table.GetID() == tableID { return true } } diff --git a/pkg/agent/controller/networkpolicy/reconciler.go b/pkg/agent/controller/networkpolicy/reconciler.go index febe547b429..1809a485903 100644 --- a/pkg/agent/controller/networkpolicy/reconciler.go +++ b/pkg/agent/controller/networkpolicy/reconciler.go @@ -190,7 +190,7 @@ type reconciler struct { idAllocator *idAllocator // priorityAssigners provides interfaces to manage OF priorities for each OVS table. - priorityAssigners map[binding.TableIDType]*tablePriorityAssigner + priorityAssigners map[uint8]*tablePriorityAssigner // ipv4Enabled tells if IPv4 is supported on this Node or not. ipv4Enabled bool // ipv6Enabled tells is IPv6 is supported on this Node or not. @@ -208,14 +208,14 @@ func newReconciler(ofClient openflow.Client, idAllocator *idAllocator, fqdnController *fqdnController, ) *reconciler { - priorityAssigners := map[binding.TableIDType]*tablePriorityAssigner{} + priorityAssigners := map[uint8]*tablePriorityAssigner{} for _, table := range openflow.GetAntreaPolicyBaselineTierTables() { - priorityAssigners[table] = &tablePriorityAssigner{ + priorityAssigners[table.GetID()] = &tablePriorityAssigner{ assigner: newPriorityAssigner(true), } } for _, table := range openflow.GetAntreaPolicyMultiTierTables() { - priorityAssigners[table] = &tablePriorityAssigner{ + priorityAssigners[table.GetID()] = &tablePriorityAssigner{ assigner: newPriorityAssigner(false), } } @@ -279,28 +279,28 @@ func (r *reconciler) Reconcile(rule *CompletedRule) error { // getOFRuleTable retreives the OpenFlow table to install the CompletedRule. // The decision is made based on whether the rule is created for a CNP/ANP, and // the Tier of that NetworkPolicy. -func (r *reconciler) getOFRuleTable(rule *CompletedRule) binding.TableIDType { +func (r *reconciler) getOFRuleTable(rule *CompletedRule) uint8 { if !rule.isAntreaNetworkPolicyRule() { if rule.Direction == v1beta2.DirectionIn { - return openflow.IngressRuleTable + return openflow.IngressRuleTable.GetID() } - return openflow.EgressRuleTable + return openflow.EgressRuleTable.GetID() } - var ruleTables []binding.TableIDType + var ruleTables []binding.Table if rule.Direction == v1beta2.DirectionIn { ruleTables = openflow.GetAntreaPolicyIngressTables() } else { ruleTables = openflow.GetAntreaPolicyEgressTables() } if *rule.TierPriority != baselineTierPriority { - return ruleTables[0] + return ruleTables[0].GetID() } - return ruleTables[1] + return ruleTables[1].GetID() } // getOFPriority retrieves the OFPriority for the input CompletedRule to be installed, // and re-arranges installed priorities on OVS if necessary. -func (r *reconciler) getOFPriority(rule *CompletedRule, table binding.TableIDType, pa *tablePriorityAssigner) (*uint16, bool, error) { +func (r *reconciler) getOFPriority(rule *CompletedRule, tableID uint8, pa *tablePriorityAssigner) (*uint16, bool, error) { if !rule.isAntreaNetworkPolicyRule() { klog.V(2).Infof("Assigning default priority for k8s NetworkPolicy.") return nil, true, nil @@ -326,7 +326,7 @@ func (r *reconciler) getOFPriority(rule *CompletedRule, table binding.TableIDTyp } // Re-assign installed priorities on OVS if len(priorityUpdates) > 0 { - err := r.ofClient.ReassignFlowPriorities(priorityUpdates, table) + err := r.ofClient.ReassignFlowPriorities(priorityUpdates, tableID) if err != nil { revertFunc() return nil, registered, err @@ -344,7 +344,7 @@ func (r *reconciler) getOFPriority(rule *CompletedRule, table binding.TableIDTyp func (r *reconciler) BatchReconcile(rules []*CompletedRule) error { var rulesToInstall []*CompletedRule var priorities []*uint16 - prioritiesByTable := map[binding.TableIDType][]*uint16{} + prioritiesByTable := map[uint8][]*uint16{} for _, rule := range rules { if _, exists := r.lastRealizeds.Load(rule.ID); exists { klog.Errorf("rule %s already realized during the initialization phase", rule.ID) @@ -382,7 +382,7 @@ func (r *reconciler) BatchReconcile(rules []*CompletedRule) error { // registerOFPriorities constructs a Priority type for each CompletedRule in the input list, // and registers those Priorities with appropriate tablePriorityAssigner based on Tier. func (r *reconciler) registerOFPriorities(rules []*CompletedRule) error { - prioritiesToRegister := map[binding.TableIDType][]types.Priority{} + prioritiesToRegister := map[uint8][]types.Priority{} for _, rule := range rules { if rule.isAntreaNetworkPolicyRule() { ruleTable := r.getOFRuleTable(rule) @@ -403,7 +403,7 @@ func (r *reconciler) registerOFPriorities(rules []*CompletedRule) error { } // add converts CompletedRule to PolicyRule(s) and invokes installOFRule to install them. -func (r *reconciler) add(rule *CompletedRule, ofPriority *uint16, table binding.TableIDType) error { +func (r *reconciler) add(rule *CompletedRule, ofPriority *uint16, table uint8) error { klog.V(2).Infof("Adding new rule %v", rule) ofRuleByServicesMap, lastRealized := r.computeOFRulesForAdd(rule, ofPriority, table) for svcKey, ofRule := range ofRuleByServicesMap { @@ -424,7 +424,7 @@ func (r *reconciler) add(rule *CompletedRule, ofPriority *uint16, table binding. return nil } -func (r *reconciler) computeOFRulesForAdd(rule *CompletedRule, ofPriority *uint16, table binding.TableIDType) ( +func (r *reconciler) computeOFRulesForAdd(rule *CompletedRule, ofPriority *uint16, table uint8) ( map[servicesKey]*types.PolicyRule, *lastRealized) { lastRealized := newLastRealized(rule) // TODO: Handle the case that the following processing fails or partially succeeds. @@ -570,7 +570,7 @@ func (r *reconciler) batchAdd(rules []*CompletedRule, ofPriorities []*uint16) er // update calculates the difference of Addresses between oldRule and newRule, // and invokes Openflow client's methods to reconcile them. -func (r *reconciler) update(lastRealized *lastRealized, newRule *CompletedRule, ofPriority *uint16, table binding.TableIDType) error { +func (r *reconciler) update(lastRealized *lastRealized, newRule *CompletedRule, ofPriority *uint16, table uint8) error { klog.V(2).Infof("Updating existing rule %v", newRule) // staleOFIDs tracks servicesKey that are no long needed. // Firstly fill it with the last realized ofIDs. @@ -758,7 +758,7 @@ func (r *reconciler) updateOFRule(ofID uint32, addedFrom []types.Address, addedT return nil } -func (r *reconciler) uninstallOFRule(ofID uint32, table binding.TableIDType) error { +func (r *reconciler) uninstallOFRule(ofID uint32, table uint8) error { klog.V(2).Infof("Uninstalling ofRule %d", ofID) stalePriorities, err := r.ofClient.UninstallPolicyRuleFlows(ofID) if err != nil { diff --git a/pkg/agent/controller/networkpolicy/reconciler_test.go b/pkg/agent/controller/networkpolicy/reconciler_test.go index 3e1706145c3..e9993027962 100644 --- a/pkg/agent/controller/networkpolicy/reconciler_test.go +++ b/pkg/agent/controller/networkpolicy/reconciler_test.go @@ -611,7 +611,7 @@ func TestReconcileWithTransientError(t *testing.T) { To: ipsToOFAddresses(sets.NewString("1.1.1.1")), Service: []v1beta2.Service{serviceTCP80, serviceTCP8080}, PolicyRef: &np1, - TableID: openflow.EgressRuleTable, + TableID: openflow.EgressRuleTable.GetID(), }, { Direction: v1beta2.DirectionOut, @@ -619,7 +619,7 @@ func TestReconcileWithTransientError(t *testing.T) { To: ipsToOFAddresses(sets.NewString("1.1.1.2")), Service: []v1beta2.Service{serviceTCP443, serviceTCP8080}, PolicyRef: &np1, - TableID: openflow.EgressRuleTable, + TableID: openflow.EgressRuleTable.GetID(), }, { Direction: v1beta2.DirectionOut, @@ -627,7 +627,7 @@ func TestReconcileWithTransientError(t *testing.T) { To: append(ipsToOFAddresses(sets.NewString("1.1.1.3")), openflow.NewIPNetAddress(ipNet)), Service: []v1beta2.Service{serviceTCP8080}, PolicyRef: &np1, - TableID: openflow.EgressRuleTable, + TableID: openflow.EgressRuleTable.GetID(), }, } for _, policyRule := range policyRules { diff --git a/pkg/agent/controller/traceflow/packetin.go b/pkg/agent/controller/traceflow/packetin.go index 3278ceaafdb..660ce9eb7d5 100644 --- a/pkg/agent/controller/traceflow/packetin.go +++ b/pkg/agent/controller/traceflow/packetin.go @@ -205,8 +205,8 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } // Get drop table. - if tableID == uint8(openflow.EgressMetricTable) || tableID == uint8(openflow.IngressMetricTable) { - ob := getNetworkPolicyObservation(tableID, tableID == uint8(openflow.IngressMetricTable)) + if tableID == openflow.EgressMetricTable.GetID() || tableID == openflow.IngressMetricTable.GetID() { + ob := getNetworkPolicyObservation(tableID, tableID == openflow.IngressMetricTable.GetID()) if match := getMatchRegField(matchers, openflow.CNPDenyConjIDField); match != nil { notAllowConjInfo, err := getRegValue(match, nil) if err != nil { @@ -222,13 +222,13 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } } obs = append(obs, *ob) - } else if tableID == uint8(openflow.EgressDefaultTable) || tableID == uint8(openflow.IngressDefaultTable) { - ob := getNetworkPolicyObservation(tableID, tableID == uint8(openflow.IngressDefaultTable)) + } else if tableID == openflow.EgressDefaultTable.GetID() || tableID == openflow.IngressDefaultTable.GetID() { + ob := getNetworkPolicyObservation(tableID, tableID == openflow.IngressDefaultTable.GetID()) obs = append(obs, *ob) } // Get output table. - if tableID == uint8(openflow.L2ForwardingOutTable) { + if tableID == openflow.L2ForwardingOutTable.GetID() { ob := new(crdv1alpha1.Observation) tunnelDstIP := "" isIPv6 := c.nodeConfig.NodeIPv6Addr != nil @@ -262,7 +262,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl // Output port is Pod port, packet is delivered. ob.Action = crdv1alpha1.ActionDelivered } - ob.ComponentInfo = openflow.GetFlowTableName(binding.TableIDType(tableID)) + ob.ComponentInfo = openflow.L2ForwardingOutTable.GetName() ob.Component = crdv1alpha1.ComponentForwarding obs = append(obs, *ob) } @@ -340,22 +340,30 @@ func getNetworkPolicyObservation(tableID uint8, ingress bool) *crdv1alpha1.Obser ob.Component = crdv1alpha1.ComponentNetworkPolicy if ingress { switch tableID { - case uint8(openflow.IngressMetricTable), uint8(openflow.IngressDefaultTable): + case openflow.IngressMetricTable.GetID(): // Packet dropped by ANP/default drop rule - ob.ComponentInfo = openflow.GetFlowTableName(binding.TableIDType(tableID)) + ob.ComponentInfo = openflow.IngressMetricTable.GetName() + ob.Action = crdv1alpha1.ActionDropped + case openflow.IngressDefaultTable.GetID(): + // Packet dropped by ANP/default drop rule + ob.ComponentInfo = openflow.IngressDefaultTable.GetName() ob.Action = crdv1alpha1.ActionDropped default: - ob.ComponentInfo = openflow.GetFlowTableName(openflow.IngressRuleTable) + ob.ComponentInfo = openflow.IngressRuleTable.GetName() ob.Action = crdv1alpha1.ActionForwarded } } else { switch tableID { - case uint8(openflow.EgressMetricTable), uint8(openflow.EgressDefaultTable): + case openflow.EgressMetricTable.GetID(): + // Packet dropped by ANP/default drop rule + ob.ComponentInfo = openflow.EgressMetricTable.GetName() + ob.Action = crdv1alpha1.ActionDropped + case openflow.EgressDefaultTable.GetID(): // Packet dropped by ANP/default drop rule - ob.ComponentInfo = openflow.GetFlowTableName(binding.TableIDType(tableID)) + ob.ComponentInfo = openflow.EgressDefaultTable.GetName() ob.Action = crdv1alpha1.ActionDropped default: - ob.ComponentInfo = openflow.GetFlowTableName(openflow.EgressRuleTable) + ob.ComponentInfo = openflow.EgressRuleTable.GetName() ob.Action = crdv1alpha1.ActionForwarded } } diff --git a/pkg/agent/controller/traceflow/packetin_test.go b/pkg/agent/controller/traceflow/packetin_test.go index 96c6cceb275..2cc437bb340 100644 --- a/pkg/agent/controller/traceflow/packetin_test.go +++ b/pkg/agent/controller/traceflow/packetin_test.go @@ -41,7 +41,7 @@ func Test_getNetworkPolicyObservation(t *testing.T) { { name: "ingress metric drop", args: args{ - tableID: uint8(openflow.IngressMetricTable), + tableID: openflow.IngressMetricTable.GetID(), ingress: true, }, want: &crdv1alpha1.Observation{ @@ -53,7 +53,7 @@ func Test_getNetworkPolicyObservation(t *testing.T) { { name: "ingress accept", args: args{ - tableID: uint8(openflow.L2ForwardingOutTable), + tableID: openflow.L2ForwardingOutTable.GetID(), ingress: true, }, want: &crdv1alpha1.Observation{ @@ -65,7 +65,7 @@ func Test_getNetworkPolicyObservation(t *testing.T) { { name: "egress default drop", args: args{ - tableID: uint8(openflow.EgressDefaultTable), + tableID: openflow.EgressDefaultTable.GetID(), ingress: false, }, want: &crdv1alpha1.Observation{ @@ -77,7 +77,7 @@ func Test_getNetworkPolicyObservation(t *testing.T) { { name: "egress accept", args: args{ - tableID: uint8(openflow.L2ForwardingOutTable), + tableID: openflow.L2ForwardingOutTable.GetID(), ingress: false, }, want: &crdv1alpha1.Observation{ diff --git a/pkg/agent/flowexporter/connections/conntrack_connections_test.go b/pkg/agent/flowexporter/connections/conntrack_connections_test.go index acf78ff4e49..9adbbe9621b 100644 --- a/pkg/agent/flowexporter/connections/conntrack_connections_test.go +++ b/pkg/agent/flowexporter/connections/conntrack_connections_test.go @@ -69,7 +69,7 @@ var ( Priority: nil, Name: "", FlowID: uint32(0), - TableID: ofclient.IngressRuleTable, + TableID: ofclient.IngressRuleTable.GetID(), PolicyRef: &np1, EnableLogging: false, } @@ -83,7 +83,7 @@ var ( Priority: &priority, Name: "allow", FlowID: uint32(0), - TableID: ofclient.EgressRuleTable, + TableID: ofclient.EgressRuleTable.GetID(), PolicyRef: &np2, EnableLogging: false, } diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go index fdca7152519..c442d2ce74e 100644 --- a/pkg/agent/openflow/client.go +++ b/pkg/agent/openflow/client.go @@ -217,7 +217,7 @@ type Client interface { // 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. - ReassignFlowPriorities(updates map[uint16]uint16, table binding.TableIDType) error + ReassignFlowPriorities(updates map[uint16]uint16, table uint8) error // SubscribePacketIn subscribes to packet in messages for the given reason. Packets // will be placed in the queue and if the queue is full, the packet in messages diff --git a/pkg/agent/openflow/client_test.go b/pkg/agent/openflow/client_test.go index 5a3cecce579..811f1f23944 100644 --- a/pkg/agent/openflow/client_test.go +++ b/pkg/agent/openflow/client_test.go @@ -411,7 +411,7 @@ func prepareTraceflowFlow(ctrl *gomock.Controller) *client { mFlow := ovsoftest.NewMockFlow(ctrl) ctx := &conjMatchFlowContext{dropFlow: mFlow} mFlow.EXPECT().FlowProtocol().Return(binding.Protocol("ip")) - mFlow.EXPECT().CopyToBuilder(priorityNormal+2, false).Return(c.pipeline[EgressDefaultTable].BuildFlow(priorityNormal + 2)).Times(1) + mFlow.EXPECT().CopyToBuilder(priorityNormal+2, false).Return(EgressDefaultTable.BuildFlow(priorityNormal + 2)).Times(1) c.globalConjMatchFlowCache["mockContext"] = ctx c.policyCache.Add(&policyRuleConjunction{metricFlows: []binding.Flow{c.denyRuleMetricFlow(123, false)}}) return c diff --git a/pkg/agent/openflow/network_policy.go b/pkg/agent/openflow/network_policy.go index 117630e801b..4c926455025 100644 --- a/pkg/agent/openflow/network_policy.go +++ b/pkg/agent/openflow/network_policy.go @@ -181,7 +181,7 @@ func newConjunctionNotFound(conjunctionID uint32) *ConjunctionNotFound { // address or ofport number, matchProtocol is "ip". When conjunctiveMatch is used to match Service // port, matchProtocol is Service protocol. If Service protocol is not set, "tcp" is used by default. type conjunctiveMatch struct { - tableID binding.TableIDType + tableID uint8 priority *uint16 matchKey *types.MatchKey matchValue interface{} @@ -507,7 +507,7 @@ type policyRuleConjunction struct { metricFlows []binding.Flow // NetworkPolicy reference information for debugging usage. npRef *v1beta2.NetworkPolicyReference - ruleTableID binding.TableIDType + ruleTableID uint8 } // clause groups conjunctive match flows. Matches in a clause represent source addresses(for fromClause), or destination @@ -536,7 +536,7 @@ func (c *client) NewDNSpacketInConjunction(id uint32) error { } conj := &policyRuleConjunction{ id: id, - ruleTableID: AntreaPolicyIngressRuleTable, + ruleTableID: AntreaPolicyIngressRuleTable.GetID(), actionFlows: []binding.Flow{c.dnsPacketInFlow(id), c.dnsResponseBypassPacketInFlow(), c.dnsResponseBypassConntrackFlow()}, } if err := c.ofEntryOperations.AddAll(conj.actionFlows); err != nil { @@ -547,8 +547,8 @@ func (c *client) NewDNSpacketInConjunction(id uint32) error { Port: &dnsPort, } dnsPriority := priorityDNSIntercept - conj.serviceClause = conj.newClause(1, 2, c.pipeline[conj.ruleTableID], nil) - conj.toClause = conj.newClause(2, 2, c.pipeline[conj.ruleTableID], nil) + conj.serviceClause = conj.newClause(1, 2, getTableByID(conj.ruleTableID), nil) + conj.toClause = conj.newClause(2, 2, getTableByID(conj.ruleTableID), nil) c.conjMatchFlowLock.Lock() defer c.conjMatchFlowLock.Unlock() @@ -595,7 +595,7 @@ func (c *clause) addConjunctiveMatchFlow(client *client, match *conjunctiveMatch // Generate the default drop flow if dropTable is not nil and the default drop flow is not set yet. if c.dropTable != nil && context.dropFlow == nil { dropFlow = &flowChange{ - flow: context.client.defaultDropFlow(c.dropTable.GetID(), match.matchKey, match.matchValue), + flow: context.client.defaultDropFlow(c.dropTable, match.matchKey, match.matchValue), changeType: insertion, } } @@ -629,7 +629,7 @@ func (c *clause) addConjunctiveMatchFlow(client *client, match *conjunctiveMatch return ctxChanges } -func generateAddressConjMatch(ruleTableID binding.TableIDType, addr types.Address, addrType types.AddressType, priority *uint16) *conjunctiveMatch { +func generateAddressConjMatch(ruleTableID uint8, addr types.Address, addrType types.AddressType, priority *uint16) *conjunctiveMatch { matchKey := addr.GetMatchKey(addrType) matchValue := addr.GetValue() match := &conjunctiveMatch{ @@ -689,7 +689,7 @@ func getServiceMatchType(protocol *v1beta2.Protocol, ipv4Enabled, ipv6Enabled, m return matchKeys } -func generateServicePortConjMatches(ruleTableID binding.TableIDType, service v1beta2.Service, priority *uint16, ipv4Enabled, ipv6Enabled, matchSrc bool) []*conjunctiveMatch { +func generateServicePortConjMatches(ruleTableID uint8, service v1beta2.Service, priority *uint16, ipv4Enabled, ipv6Enabled, matchSrc bool) []*conjunctiveMatch { matchKeys := getServiceMatchType(service.Protocol, ipv4Enabled, ipv6Enabled, matchSrc) ovsBitRanges := serviceToBitRanges(service) var matches []*conjunctiveMatch @@ -933,13 +933,13 @@ func (c *client) calculateActionFlowChangesForRule(rule *types.PolicyRule) *poli var metricFlows []binding.Flow if rule.IsAntreaNetworkPolicyRule() && *rule.Action == crdv1alpha1.RuleActionDrop { metricFlows = append(metricFlows, c.denyRuleMetricFlow(ruleOfID, isIngress)) - actionFlows = append(actionFlows, c.conjunctionActionDenyFlow(ruleOfID, ruleTable.GetID(), rule.Priority, DispositionDrop, rule.EnableLogging)) + actionFlows = append(actionFlows, c.conjunctionActionDenyFlow(ruleOfID, ruleTable, rule.Priority, DispositionDrop, rule.EnableLogging)) } else if rule.IsAntreaNetworkPolicyRule() && *rule.Action == crdv1alpha1.RuleActionReject { metricFlows = append(metricFlows, c.denyRuleMetricFlow(ruleOfID, isIngress)) - actionFlows = append(actionFlows, c.conjunctionActionDenyFlow(ruleOfID, ruleTable.GetID(), rule.Priority, DispositionRej, rule.EnableLogging)) + actionFlows = append(actionFlows, c.conjunctionActionDenyFlow(ruleOfID, ruleTable, rule.Priority, DispositionRej, rule.EnableLogging)) } else { metricFlows = append(metricFlows, c.allowRulesMetricFlows(ruleOfID, isIngress)...) - actionFlows = append(actionFlows, c.conjunctionActionFlow(ruleOfID, ruleTable.GetID(), dropTable.GetNext(), rule.Priority, rule.EnableLogging)...) + actionFlows = append(actionFlows, c.conjunctionActionFlow(ruleOfID, ruleTable, dropTable.GetNext(), rule.Priority, rule.EnableLogging)...) } conj.actionFlows = actionFlows conj.metricFlows = metricFlows @@ -1002,7 +1002,7 @@ func (c *client) addActionToConjunctiveMatch(clause *clause, match *conjunctiveM } // Generate the default drop flow if dropTable is not nil. if clause.dropTable != nil { - context.dropFlow = context.client.defaultDropFlow(clause.dropTable.GetID(), match.matchKey, match.matchValue) + context.dropFlow = context.client.defaultDropFlow(clause.dropTable, match.matchKey, match.matchValue) } c.globalConjMatchFlowCache[matcherKey] = context } @@ -1138,12 +1138,12 @@ func (c *policyRuleConjunction) calculateClauses(rule *types.PolicyRule, clnt *c var isEgressRule = false switch rule.Direction { case v1beta2.DirectionOut: - dropTable = clnt.pipeline[EgressDefaultTable] + dropTable = EgressDefaultTable isEgressRule = true default: - dropTable = clnt.pipeline[IngressDefaultTable] + dropTable = IngressDefaultTable } - ruleTable := clnt.pipeline[rule.TableID] + ruleTable := getTableByID(rule.TableID) var fromID, toID, serviceID, nClause uint8 // Calculate clause IDs and the total number of clauses. @@ -1304,7 +1304,7 @@ func (c *client) UninstallPolicyRuleFlows(ruleID uint32) ([]string, error) { // policyRuleConjunction is installed, after the deletion of that policyRuleConjunction. func (c *client) getStalePriorities(conj *policyRuleConjunction) (staleOFPriorities []string) { var ofPrioritiesPotentiallyStale []string - if conj.ruleTableID != IngressRuleTable && conj.ruleTableID != EgressRuleTable { + if conj.ruleTableID != IngressRuleTable.GetID() && conj.ruleTableID != EgressRuleTable.GetID() { ofPrioritiesPotentiallyStale = conj.ActionFlowPriorities() } klog.V(4).Infof("Potential stale ofpriority %v found", ofPrioritiesPotentiallyStale) @@ -1535,7 +1535,7 @@ func (c *client) updateConjunctionMatchFlows(conj *policyRuleConjunction, newPri } // calculateFlowUpdates calculates the flow updates required for the priority re-assignments specified in the input map. -func (c *client) calculateFlowUpdates(updates map[uint16]uint16, table binding.TableIDType) (addFlows, delFlows []binding.Flow, +func (c *client) calculateFlowUpdates(updates map[uint16]uint16, table uint8) (addFlows, delFlows []binding.Flow, conjFlowUpdates map[uint32]flowUpdates) { conjFlowUpdates = map[uint32]flowUpdates{} for original, newPriority := range updates { @@ -1574,7 +1574,7 @@ func (c *client) calculateFlowUpdates(updates map[uint16]uint16, table binding.T // ReassignFlowPriorities takes a list of priority updates, and update the actionFlows to replace // the old priority with the desired one, for each priority update. -func (c *client) ReassignFlowPriorities(updates map[uint16]uint16, table binding.TableIDType) error { +func (c *client) ReassignFlowPriorities(updates map[uint16]uint16, table uint8) error { addFlows, delFlows, conjFlowUpdates := c.calculateFlowUpdates(updates, table) add, update, del := c.processFlowUpdates(addFlows, delFlows) // Commit the flows updates calculated. @@ -1651,8 +1651,8 @@ func parseMetricFlow(flow string) (uint32, types.RuleMetric) { func (c *client) NetworkPolicyMetrics() map[uint32]*types.RuleMetric { result := map[uint32]*types.RuleMetric{} - egressFlows, _ := c.ovsctlClient.DumpTableFlows(uint8(EgressMetricTable)) - ingressFlows, _ := c.ovsctlClient.DumpTableFlows(uint8(IngressMetricTable)) + egressFlows, _ := c.ovsctlClient.DumpTableFlows(EgressMetricTable.GetID()) + ingressFlows, _ := c.ovsctlClient.DumpTableFlows(IngressMetricTable.GetID()) collectMetricsFromFlows := func(flows []string) { for _, flow := range flows { diff --git a/pkg/agent/openflow/network_policy_test.go b/pkg/agent/openflow/network_policy_test.go index 4ebe9a4d80d..71857300969 100644 --- a/pkg/agent/openflow/network_policy_test.go +++ b/pkg/agent/openflow/network_policy_test.go @@ -166,7 +166,7 @@ func TestInstallPolicyRuleFlows(t *testing.T) { Action: &defaultAction, Priority: nil, FlowID: ruleID1, - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -199,7 +199,7 @@ func TestInstallPolicyRuleFlows(t *testing.T) { Action: &defaultAction, To: parseAddresses([]string{"0.0.0.0/0"}), FlowID: ruleID2, - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -243,7 +243,7 @@ func TestInstallPolicyRuleFlows(t *testing.T) { Action: &defaultAction, Service: []v1beta2.Service{npPort1, npPort2}, FlowID: ruleID3, - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -306,7 +306,7 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { From: parseAddresses([]string{"192.168.1.40", "192.168.1.50"}), To: parseAddresses([]string{"0.0.0.0/0"}), FlowID: uint32(10), - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -322,7 +322,7 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { To: parseAddresses([]string{"0.0.0.0/0"}), Service: []v1beta2.Service{{Protocol: &protocolTCP, Port: &port8080}}, FlowID: uint32(11), - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -335,52 +335,52 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { cookiePolicy := c.cookieAllocator.Request(cookie.Policy).Raw() cookieDefault := c.cookieAllocator.Request(cookie.Default).Raw() return []binding.Flow{ - c.pipeline[EgressRuleTable].BuildFlow(priorityLow).Cookie(cookiePolicy). + EgressRuleTable.BuildFlow(priorityLow).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchConjID(10). Action().LoadToRegField(TFEgressConjIDField, 10). - Action().CT(true, EgressMetricTable, CtZone).LoadToLabelField(10, EgressRuleCTLabel).CTDone().Done(), - c.pipeline[EgressRuleTable].BuildFlow(priorityLow).Cookie(cookiePolicy). + Action().CT(true, EgressMetricTable.GetID(), CtZone).LoadToLabelField(10, EgressRuleCTLabel).CTDone().Done(), + EgressRuleTable.BuildFlow(priorityLow).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchConjID(11). Action().LoadToRegField(TFEgressConjIDField, 11). - Action().CT(true, EgressMetricTable, CtZone).LoadToLabelField(11, EgressRuleCTLabel).CTDone().Done(), - c.pipeline[EgressRuleTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + Action().CT(true, EgressMetricTable.GetID(), CtZone).LoadToLabelField(11, EgressRuleCTLabel).CTDone().Done(), + EgressRuleTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.40")). Action().Conjunction(10, 1, 2). Action().Conjunction(11, 1, 3).Done(), - c.pipeline[EgressRuleTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + EgressRuleTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.50")). Action().Conjunction(10, 1, 2).Done(), - c.pipeline[EgressRuleTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + EgressRuleTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.51")). Action().Conjunction(11, 1, 3).Done(), - c.pipeline[EgressRuleTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + EgressRuleTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchDstIPNet(*ip.MustParseCIDR("0.0.0.0/0")). Action().Conjunction(10, 2, 2). Action().Conjunction(11, 2, 3).Done(), - c.pipeline[EgressRuleTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + EgressRuleTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolTCP).MatchDstPort(8080, nil). Action().Conjunction(11, 3, 3).Done(), - c.pipeline[EgressDefaultTable].BuildFlow(priorityNormal).Cookie(cookieDefault). + EgressDefaultTable.BuildFlow(priorityNormal).Cookie(cookieDefault). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.40")). Action().Drop().Done(), - c.pipeline[EgressDefaultTable].BuildFlow(priorityNormal).Cookie(cookieDefault). + EgressDefaultTable.BuildFlow(priorityNormal).Cookie(cookieDefault). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.50")). Action().Drop().Done(), - c.pipeline[EgressDefaultTable].BuildFlow(priorityNormal).Cookie(cookieDefault). + EgressDefaultTable.BuildFlow(priorityNormal).Cookie(cookieDefault). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.51")). Action().Drop().Done(), - c.pipeline[EgressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + EgressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchCTStateNew(true).MatchCTLabelField(0, uint64(10)<<32, EgressRuleCTLabel). - Action().GotoTable(l3ForwardingTable).Done(), - c.pipeline[EgressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + Action().GotoTable(L3ForwardingTable.GetID()).Done(), + EgressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchCTStateNew(false).MatchCTLabelField(0, uint64(10)<<32, EgressRuleCTLabel). - Action().GotoTable(l3ForwardingTable).Done(), - c.pipeline[EgressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + Action().GotoTable(L3ForwardingTable.GetID()).Done(), + EgressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchCTStateNew(true).MatchCTLabelField(0, uint64(11)<<32, EgressRuleCTLabel). - Action().GotoTable(l3ForwardingTable).Done(), - c.pipeline[EgressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + Action().GotoTable(L3ForwardingTable.GetID()).Done(), + EgressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchCTStateNew(false).MatchCTLabelField(0, uint64(11)<<32, EgressRuleCTLabel). - Action().GotoTable(l3ForwardingTable).Done(), + Action().GotoTable(L3ForwardingTable.GetID()).Done(), } }, }, @@ -394,7 +394,7 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { Priority: &priority100, To: []types.Address{NewOFPortAddress(1), NewOFPortAddress(2)}, FlowID: uint32(10), - TableID: AntreaPolicyIngressRuleTable, + TableID: AntreaPolicyIngressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -411,7 +411,7 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { To: []types.Address{NewOFPortAddress(1), NewOFPortAddress(3)}, Service: []v1beta2.Service{{Protocol: &protocolTCP, Port: &port8080}}, FlowID: uint32(11), - TableID: AntreaPolicyIngressRuleTable, + TableID: AntreaPolicyIngressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -428,7 +428,7 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { To: []types.Address{NewOFPortAddress(1)}, Service: []v1beta2.Service{{Protocol: &protocolTCP, Port: &port8080}}, FlowID: uint32(12), - TableID: AntreaPolicyIngressRuleTable, + TableID: AntreaPolicyIngressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -440,62 +440,62 @@ func TestBatchInstallPolicyRuleFlows(t *testing.T) { expectedFlowsFn: func(c *client) []binding.Flow { cookiePolicy := c.cookieAllocator.Request(cookie.Policy).Raw() return []binding.Flow{ - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchConjID(10). Action().LoadToRegField(TFIngressConjIDField, 10). - Action().CT(true, IngressMetricTable, CtZone).LoadToLabelField(10, IngressRuleCTLabel).CTDone().Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + Action().CT(true, IngressMetricTable.GetID(), CtZone).LoadToLabelField(10, IngressRuleCTLabel).CTDone().Done(), + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchConjID(11). Action().LoadToRegField(CNPDenyConjIDField, 11). Action().LoadRegMark(CnpDenyRegMark). - Action().GotoTable(IngressMetricTable).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority200).Cookie(cookiePolicy). + Action().GotoTable(IngressMetricTable.GetID()).Done(), + AntreaPolicyIngressRuleTable.BuildFlow(priority200).Cookie(cookiePolicy). MatchConjID(12). Action().LoadToRegField(CNPDenyConjIDField, 12). Action().LoadRegMark(CnpDenyRegMark). - Action().GotoTable(IngressMetricTable).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + Action().GotoTable(IngressMetricTable.GetID()).Done(), + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.40")). Action().Conjunction(10, 1, 2). Action().Conjunction(11, 1, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority200).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority200).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.40")). Action().Conjunction(12, 1, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.50")). Action().Conjunction(10, 1, 2).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchSrcIP(net.ParseIP("192.168.1.51")). Action().Conjunction(11, 1, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchRegFieldWithValue(TargetOFPortField, uint32(1)). Action().Conjunction(10, 2, 2). Action().Conjunction(11, 2, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority200).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority200).Cookie(cookiePolicy). MatchRegFieldWithValue(TargetOFPortField, uint32(1)). Action().Conjunction(12, 2, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchRegFieldWithValue(TargetOFPortField, uint32(2)). Action().Conjunction(10, 2, 2).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchRegFieldWithValue(TargetOFPortField, uint32(3)). Action().Conjunction(11, 2, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority100).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority100).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolTCP).MatchDstPort(8080, nil). Action().Conjunction(11, 3, 3).Done(), - c.pipeline[AntreaPolicyIngressRuleTable].BuildFlow(priority200).Cookie(cookiePolicy). + AntreaPolicyIngressRuleTable.BuildFlow(priority200).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolTCP).MatchDstPort(8080, nil). Action().Conjunction(12, 3, 3).Done(), - c.pipeline[IngressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + IngressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchCTStateNew(true).MatchCTLabelField(0, 10, IngressRuleCTLabel). - Action().GotoTable(conntrackCommitTable).Done(), - c.pipeline[IngressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + Action().GotoTable(ConntrackCommitTable.GetID()).Done(), + IngressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchProtocol(binding.ProtocolIP).MatchCTStateNew(false).MatchCTLabelField(0, 10, IngressRuleCTLabel). - Action().GotoTable(conntrackCommitTable).Done(), - c.pipeline[IngressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + Action().GotoTable(ConntrackCommitTable.GetID()).Done(), + IngressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchRegMark(CnpDenyRegMark).MatchRegFieldWithValue(CNPDenyConjIDField, 11). Action().Drop().Done(), - c.pipeline[IngressMetricTable].BuildFlow(priorityNormal).Cookie(cookiePolicy). + IngressMetricTable.BuildFlow(priorityNormal).Cookie(cookiePolicy). MatchRegMark(CnpDenyRegMark).MatchRegFieldWithValue(CNPDenyConjIDField, 12). Action().Drop().Done(), } @@ -563,7 +563,7 @@ func BenchmarkBatchInstallPolicyRuleFlows(b *testing.B) { Priority: &priority100, To: []types.Address{NewOFPortAddress(1), NewOFPortAddress(int32(i))}, FlowID: uint32(i), - TableID: AntreaPolicyIngressRuleTable, + TableID: AntreaPolicyIngressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -620,7 +620,7 @@ func TestConjMatchFlowContextKeyConflict(t *testing.T) { err = c.applyConjunctiveMatchFlows(flowChange2) require.Nil(t, err, "no error expect in applyConjunctiveMatchFlows") - expectedMatchKey := fmt.Sprintf("table:%d,priority:%s,type:%v,value:%s", EgressRuleTable, strconv.Itoa(int(priorityNormal)), MatchDstIPNet, ipNet.String()) + expectedMatchKey := fmt.Sprintf("table:%d,priority:%s,type:%v,value:%s", EgressRuleTable.GetID(), strconv.Itoa(int(priorityNormal)), MatchDstIPNet, ipNet.String()) ctx, found := c.globalConjMatchFlowCache[expectedMatchKey] assert.True(t, found) assert.Equal(t, 2, len(ctx.actions)) @@ -648,7 +648,7 @@ func TestInstallPolicyRuleFlowsInDualStackCluster(t *testing.T) { Action: &defaultAction, Priority: nil, FlowID: ruleID1, - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -681,7 +681,7 @@ func TestInstallPolicyRuleFlowsInDualStackCluster(t *testing.T) { Action: &defaultAction, To: parseAddresses([]string{"0.0.0.0/0"}), FlowID: ruleID2, - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -724,7 +724,7 @@ func TestInstallPolicyRuleFlowsInDualStackCluster(t *testing.T) { Action: &defaultAction, Service: []v1beta2.Service{npPort1, npPort2}, FlowID: ruleID3, - TableID: EgressRuleTable, + TableID: EgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.K8sNetworkPolicy, Namespace: "ns1", @@ -936,11 +936,13 @@ func parseAddresses(addrs []string) []types.Address { return addresses } -func createMockTable(ctrl *gomock.Controller, tableID binding.TableIDType, nextTable binding.TableIDType, missAction binding.MissActionType) *mocks.MockTable { +func createMockTable(ctrl *gomock.Controller, tableID uint8, nextTable uint8, missAction binding.MissActionType) *mocks.MockTable { table := mocks.NewMockTable(ctrl) table.EXPECT().GetID().Return(tableID).AnyTimes() table.EXPECT().GetNext().Return(nextTable).AnyTimes() table.EXPECT().GetMissAction().Return(missAction).AnyTimes() + table.EXPECT().GetName().Return("table").AnyTimes() + ofTableCache.Update(table) return table } @@ -951,19 +953,12 @@ func prepareClient(ctrl *gomock.Controller) *client { ) bridge := mocks.NewMockBridge(ctrl) bridge.EXPECT().AddFlowsInBundle(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - cnpOutTable = createMockTable(ctrl, AntreaPolicyEgressRuleTable, EgressRuleTable, binding.TableMissActionNext) - outTable = createMockTable(ctrl, EgressRuleTable, EgressDefaultTable, binding.TableMissActionNext) - outDropTable = createMockTable(ctrl, EgressDefaultTable, EgressMetricTable, binding.TableMissActionNext) - metricTable = createMockTable(ctrl, EgressMetricTable, l3ForwardingTable, binding.TableMissActionNext) - outAllowTable = createMockTable(ctrl, l3ForwardingTable, l2ForwardingCalcTable, binding.TableMissActionNext) + cnpOutTable = createMockTable(ctrl, AntreaPolicyEgressRuleTable.GetID(), EgressRuleTable.GetID(), binding.TableMissActionNext) + outTable = createMockTable(ctrl, EgressRuleTable.GetID(), EgressDefaultTable.GetID(), binding.TableMissActionNext) + outDropTable = createMockTable(ctrl, EgressDefaultTable.GetID(), EgressMetricTable.GetID(), binding.TableMissActionNext) + metricTable = createMockTable(ctrl, EgressMetricTable.GetID(), L3ForwardingTable.GetID(), binding.TableMissActionNext) + outAllowTable = createMockTable(ctrl, L3ForwardingTable.GetID(), L2ForwardingCalcTable.GetID(), binding.TableMissActionNext) c = &client{ - pipeline: map[binding.TableIDType]binding.Table{ - AntreaPolicyEgressRuleTable: cnpOutTable, - EgressRuleTable: outTable, - EgressDefaultTable: outDropTable, - EgressMetricTable: metricTable, - l3ForwardingTable: outAllowTable, - }, policyCache: policyCache, globalConjMatchFlowCache: map[string]*conjMatchFlowContext{}, bridge: bridge, @@ -1104,8 +1099,8 @@ func TestNetworkPolicyMetrics(t *testing.T) { mockOVSClient := ovsctltest.NewMockOVSCtlClient(ctrl) c.ovsctlClient = mockOVSClient gomock.InOrder( - mockOVSClient.EXPECT().DumpTableFlows(uint8(EgressMetricTable)).Return(tt.egressFlows, nil), - mockOVSClient.EXPECT().DumpTableFlows(uint8(IngressMetricTable)).Return(tt.ingressFlows, nil), + mockOVSClient.EXPECT().DumpTableFlows(EgressMetricTable.GetID()).Return(tt.egressFlows, nil), + mockOVSClient.EXPECT().DumpTableFlows(IngressMetricTable.GetID()).Return(tt.ingressFlows, nil), ) got := c.NetworkPolicyMetrics() assert.Equal(t, tt.want, got) @@ -1137,7 +1132,7 @@ func TestGetMatchFlowUpdates(t *testing.T) { Priority: &priority100, To: []types.Address{NewOFPortAddress(1), NewOFPortAddress(2)}, FlowID: uint32(10), - TableID: AntreaPolicyEgressRuleTable, + TableID: AntreaPolicyEgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -1154,7 +1149,7 @@ func TestGetMatchFlowUpdates(t *testing.T) { To: []types.Address{NewOFPortAddress(1), NewOFPortAddress(3)}, Service: []v1beta2.Service{{Protocol: &protocolTCP, Port: &port8080}}, FlowID: uint32(11), - TableID: AntreaPolicyEgressRuleTable, + TableID: AntreaPolicyEgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -1171,7 +1166,7 @@ func TestGetMatchFlowUpdates(t *testing.T) { To: []types.Address{NewOFPortAddress(1)}, Service: []v1beta2.Service{{Protocol: &protocolTCP, Port: &port8080}}, FlowID: uint32(12), - TableID: AntreaPolicyEgressRuleTable, + TableID: AntreaPolicyEgressRuleTable.GetID(), PolicyRef: &v1beta2.NetworkPolicyReference{ Type: v1beta2.AntreaNetworkPolicy, Namespace: "ns1", @@ -1186,6 +1181,6 @@ func TestGetMatchFlowUpdates(t *testing.T) { priority100: 101, priority200: 202, } - err = c.ReassignFlowPriorities(updatedPriorities, AntreaPolicyEgressRuleTable) + err = c.ReassignFlowPriorities(updatedPriorities, AntreaPolicyEgressRuleTable.GetID()) assert.Nil(t, err) } diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go index b07dbd06cc7..f00c1e7fed2 100644 --- a/pkg/agent/openflow/pipeline.go +++ b/pkg/agent/openflow/pipeline.go @@ -20,7 +20,6 @@ import ( "math" "net" "sort" - "strings" "sync" "time" @@ -41,40 +40,39 @@ import ( "antrea.io/antrea/third_party/proxy" ) -const ( - // Flow table id index - ClassifierTable binding.TableIDType = 0 - uplinkTable binding.TableIDType = 5 - spoofGuardTable binding.TableIDType = 10 - arpResponderTable binding.TableIDType = 20 - ipv6Table binding.TableIDType = 21 - serviceHairpinTable binding.TableIDType = 23 - serviceConntrackTable binding.TableIDType = 24 // serviceConntrackTable use a new ct_zone to transform SNAT'd connections. - conntrackTable binding.TableIDType = 30 - conntrackStateTable binding.TableIDType = 31 - serviceClassifierTable binding.TableIDType = 35 - sessionAffinityTable binding.TableIDType = 40 - dnatTable binding.TableIDType = 40 - serviceLBTable binding.TableIDType = 41 - endpointDNATTable binding.TableIDType = 42 - AntreaPolicyEgressRuleTable binding.TableIDType = 45 - DefaultTierEgressRuleTable binding.TableIDType = 49 - EgressRuleTable binding.TableIDType = 50 - EgressDefaultTable binding.TableIDType = 60 - EgressMetricTable binding.TableIDType = 61 - l3ForwardingTable binding.TableIDType = 70 - snatTable binding.TableIDType = 71 - l3DecTTLTable binding.TableIDType = 72 - l2ForwardingCalcTable binding.TableIDType = 80 - AntreaPolicyIngressRuleTable binding.TableIDType = 85 - DefaultTierIngressRuleTable binding.TableIDType = 89 - IngressRuleTable binding.TableIDType = 90 - IngressDefaultTable binding.TableIDType = 100 - IngressMetricTable binding.TableIDType = 101 - conntrackCommitTable binding.TableIDType = 105 - serviceConntrackCommitTable binding.TableIDType = 106 - hairpinSNATTable binding.TableIDType = 108 - L2ForwardingOutTable binding.TableIDType = 110 +var ( + ClassifierTable = binding.NewOFTable(0, "Classification") + UplinkTable = binding.NewOFTable(5, "Uplink") + SpoofGuardTable = binding.NewOFTable(10, "SpoofGuard") + arpResponderTable = binding.NewOFTable(20, "ARPResponder") + IPv6Table = binding.NewOFTable(21, "IPv6") + ServiceHairpinTable = binding.NewOFTable(23, "ServiceHairpin") + ServiceConntrackTable = binding.NewOFTable(24, "ServiceConntrack") // serviceConntrackTable use a new ct_zone to transform SNAT'd connections. + ConntrackTable = binding.NewOFTable(30, "ConntrackZone") + ConntrackStateTable = binding.NewOFTable(31, "ConntrackState") + ServiceClassifierTable = binding.NewOFTable(35, "ServiceClassifier") + SessionAffinityTable = binding.NewOFTable(40, "SessionAffinity") + DNATTable = binding.NewOFTable(40, "DNAT(SessionAffinity)") + ServiceLBTable = binding.NewOFTable(41, "ServiceLB") + EndpointDNATTable = binding.NewOFTable(42, "EndpointDNAT") + AntreaPolicyEgressRuleTable = binding.NewOFTable(45, "AntreaPolicyEgressRule") + DefaultTierEgressRuleTable = binding.NewOFTable(49, "DefaultTierEgressRule") + EgressRuleTable = binding.NewOFTable(50, "EgressRule") + EgressDefaultTable = binding.NewOFTable(60, "EgressDefaultRule") + EgressMetricTable = binding.NewOFTable(61, "EgressMetric") + L3ForwardingTable = binding.NewOFTable(70, "L3Forwarding") + SNATTable = binding.NewOFTable(71, "SNAT") + L3DecTTLTable = binding.NewOFTable(72, "IPTTLDec") + L2ForwardingCalcTable = binding.NewOFTable(80, "L2Forwarding") + AntreaPolicyIngressRuleTable = binding.NewOFTable(85, "AntreaPolicyIngressRule") + DefaultTierIngressRuleTable = binding.NewOFTable(89, "DefaultTierIngressRule") + IngressRuleTable = binding.NewOFTable(90, "IngressRule") + IngressDefaultTable = binding.NewOFTable(100, "IngressDefaultRule") + IngressMetricTable = binding.NewOFTable(101, "IngressMetric") + ConntrackCommitTable = binding.NewOFTable(105, "ConntrackCommit") + ServiceConntrackCommitTable = binding.NewOFTable(106, "ServiceConntrackCommit") + HairpinSNATTable = binding.NewOFTable(108, "HairpinSNAT") + L2ForwardingOutTable = binding.NewOFTable(110, "Output") // Flow priority level priorityHigh = uint16(210) @@ -96,6 +94,8 @@ const ( // Operation field values in ARP packets arpOpRequest = uint16(1) arpOpReply = uint16(2) + + tableNameIndex = "tableNameIndex" ) type ofAction int32 @@ -122,114 +122,92 @@ func (a ofAction) String() string { var ( // egressTables map records all IDs of tables related to // egress rules. - egressTables = map[binding.TableIDType]struct{}{ - AntreaPolicyEgressRuleTable: {}, - EgressRuleTable: {}, - EgressDefaultTable: {}, - } - - FlowTables = []struct { - Number binding.TableIDType - Name string - }{ - {ClassifierTable, "Classification"}, - {uplinkTable, "Uplink"}, - {spoofGuardTable, "SpoofGuard"}, - {arpResponderTable, "ARPResponder"}, - {ipv6Table, "IPv6"}, - {serviceHairpinTable, "ServiceHairpin"}, - {serviceConntrackTable, "ServiceConntrack"}, - {conntrackTable, "ConntrackZone"}, - {conntrackStateTable, "ConntrackState"}, - {serviceClassifierTable, "ServiceClassifier"}, - {dnatTable, "DNAT(SessionAffinity)"}, - {sessionAffinityTable, "SessionAffinity"}, - {serviceLBTable, "ServiceLB"}, - {endpointDNATTable, "EndpointDNAT"}, - {AntreaPolicyEgressRuleTable, "AntreaPolicyEgressRule"}, - {EgressRuleTable, "EgressRule"}, - {EgressDefaultTable, "EgressDefaultRule"}, - {EgressMetricTable, "EgressMetric"}, - {l3ForwardingTable, "L3Forwarding"}, - {snatTable, "SNAT"}, - {l3DecTTLTable, "IPTTLDec"}, - {l2ForwardingCalcTable, "L2Forwarding"}, - {AntreaPolicyIngressRuleTable, "AntreaPolicyIngressRule"}, - {IngressRuleTable, "IngressRule"}, - {IngressDefaultTable, "IngressDefaultRule"}, - {IngressMetricTable, "IngressMetric"}, - {conntrackCommitTable, "ConntrackCommit"}, - {serviceConntrackCommitTable, "ServiceConntrackCommit"}, - {hairpinSNATTable, "HairpinSNATTable"}, - {L2ForwardingOutTable, "Output"}, + egressTables = map[uint8]struct{}{ + AntreaPolicyEgressRuleTable.GetID(): {}, + EgressRuleTable.GetID(): {}, + EgressDefaultTable.GetID(): {}, } + + // ofTableCache caches the OpenFlow tables used in the pipeline, and it supports using the table ID and name as the index to query the OpenFlow table. + ofTableCache = cache.NewIndexer(tableIDKeyFunc, cache.Indexers{tableNameIndex: tableNameIndexFunc}) ) -// GetFlowTableName returns the flow table name given the table number. An empty +func tableNameIndexFunc(obj interface{}) ([]string, error) { + ofTable := obj.(binding.Table) + return []string{ofTable.GetName()}, nil +} + +func tableIDKeyFunc(obj interface{}) (string, error) { + ofTable := obj.(binding.Table) + return fmt.Sprintf("%d", ofTable.GetID()), nil +} + +func getTableByID(id uint8) binding.Table { + obj, exists, _ := ofTableCache.GetByKey(fmt.Sprintf("%d", id)) + if !exists { + return nil + } + return obj.(binding.Table) +} + +// GetFlowTableName returns the flow table name given the table ID. An empty // string is returned if the table cannot be found. -func GetFlowTableName(tableNumber binding.TableIDType) string { - for _, t := range FlowTables { - if t.Number == tableNumber { - return t.Name - } +func GetFlowTableName(tableID uint8) string { + table := getTableByID(tableID) + if table == nil { + return "" } - return "" + return table.GetName() } -// GetFlowTableNumber does a case insensitive lookup of the table name, and +// GetFlowTableID does a case insensitive lookup of the table name, and // returns the flow table number if the table is found. Otherwise TableIDAll is // returned if the table cannot be found. -func GetFlowTableNumber(tableName string) binding.TableIDType { - for _, t := range FlowTables { - if strings.EqualFold(t.Name, tableName) { - return t.Number - } +func GetFlowTableID(tableName string) uint8 { + objs, _ := ofTableCache.ByIndex(tableNameIndex, tableName) + if len(objs) == 0 { + return binding.TableIDAll } - return binding.TableIDAll + return objs[0].(binding.Table).GetID() } -func GetAntreaPolicyEgressTables() []binding.TableIDType { - return []binding.TableIDType{ +func GetTableList() []binding.Table { + tables := make([]binding.Table, 0) + for _, obj := range ofTableCache.List() { + t := obj.(binding.Table) + tables = append(tables, t) + } + return tables +} + +func GetAntreaPolicyEgressTables() []binding.Table { + return []binding.Table{ AntreaPolicyEgressRuleTable, EgressDefaultTable, } } -func GetAntreaPolicyIngressTables() []binding.TableIDType { - return []binding.TableIDType{ +func GetAntreaPolicyIngressTables() []binding.Table { + return []binding.Table{ AntreaPolicyIngressRuleTable, IngressDefaultTable, } } -func GetAntreaPolicyBaselineTierTables() []binding.TableIDType { - return []binding.TableIDType{ +func GetAntreaPolicyBaselineTierTables() []binding.Table { + return []binding.Table{ EgressDefaultTable, IngressDefaultTable, } } -func GetAntreaPolicyMultiTierTables() []binding.TableIDType { - return []binding.TableIDType{ +func GetAntreaPolicyMultiTierTables() []binding.Table { + return []binding.Table{ AntreaPolicyEgressRuleTable, AntreaPolicyIngressRuleTable, } } -type regType uint - -func (rt regType) number() string { - return fmt.Sprint(rt) -} - -func (rt regType) nxm() string { - return fmt.Sprintf("NXM_NX_REG%d", rt) -} - -func (rt regType) reg() string { - return fmt.Sprintf("reg%d", rt) -} - const ( CtZone = 0xfff0 CtZoneV6 = 0xffe6 @@ -313,9 +291,8 @@ type client struct { roundInfo types.RoundInfo cookieAllocator cookie.Allocator bridge binding.Bridge - egressEntryTable binding.TableIDType - ingressEntryTable binding.TableIDType - pipeline map[binding.TableIDType]binding.Table + egressEntryTable uint8 + ingressEntryTable uint8 // Flow caches for corresponding deletions. nodeFlowCache, podFlowCache, serviceFlowCache, snatFlowCache, tfFlowCache *flowCategoryCache // "fixed" flows installed by the agent after initialization and which do not change during @@ -454,7 +431,8 @@ func (c *client) DeleteOFEntries(ofEntries []binding.OFEntry) error { // defaultFlows generates the default flows of all tables. func (c *client) defaultFlows() (flows []binding.Flow) { - for _, table := range c.pipeline { + for _, obj := range ofTableCache.List() { + table := obj.(binding.Table) flowBuilder := table.BuildFlow(priorityMiss) switch table.GetMissAction() { case binding.TableMissActionNext: @@ -475,70 +453,65 @@ func (c *client) defaultFlows() (flows []binding.Flow) { // tunnelClassifierFlow generates the flow to mark traffic comes from the tunnelOFPort. func (c *client) tunnelClassifierFlow(tunnelOFPort uint32, category cookie.Category) binding.Flow { - nextTable := conntrackTable + nextTable := ConntrackTable if c.proxyAll { - nextTable = serviceConntrackTable + nextTable = ServiceConntrackTable } - return c.pipeline[ClassifierTable].BuildFlow(priorityNormal). + return ClassifierTable.BuildFlow(priorityNormal). MatchInPort(tunnelOFPort). Action().LoadRegMark(FromTunnelRegMark). Action().LoadRegMark(RewriteMACRegMark). - Action().GotoTable(nextTable). + Action().GotoTable(nextTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } // gatewayClassifierFlow generates the flow to mark traffic comes from the gatewayOFPort. func (c *client) gatewayClassifierFlow(category cookie.Category) binding.Flow { - classifierTable := c.pipeline[ClassifierTable] - return classifierTable.BuildFlow(priorityNormal). + return ClassifierTable.BuildFlow(priorityNormal). MatchInPort(config.HostGatewayOFPort). Action().LoadRegMark(FromGatewayRegMark). - Action().GotoTable(classifierTable.GetNext()). + Action().GotoTable(ClassifierTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } // podClassifierFlow generates the flow to mark traffic comes from the podOFPort. func (c *client) podClassifierFlow(podOFPort uint32, category cookie.Category) binding.Flow { - classifierTable := c.pipeline[ClassifierTable] - return classifierTable.BuildFlow(priorityLow). + return ClassifierTable.BuildFlow(priorityLow). MatchInPort(podOFPort). Action().LoadRegMark(FromLocalRegMark). - Action().GotoTable(classifierTable.GetNext()). + Action().GotoTable(ClassifierTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } // connectionTrackFlows generates flows that redirect traffic to ct_zone and handle traffic according to ct_state: -// 1) commit new connections to ct_zone(0xfff0) in the conntrackCommitTable. +// 1) commit new connections to ct_zone(0xfff0) in the ConntrackCommitTable. // 2) Add ct_mark on the packet if it is sent to the switch from the host gateway. // 3) Allow traffic if it hits ct_mark and is sent from the host gateway. // 4) Drop all invalid traffic. -// 5) Let other traffic go to the sessionAffinityTable first and then the serviceLBTable. -// The sessionAffinityTable is a side-effect table which means traffic will not +// 5) Let other traffic go to the SessionAffinityTable first and then the ServiceLBTable. +// The SessionAffinityTable is a side-effect table which means traffic will not // be resubmitted to any table. serviceLB does Endpoint selection for traffic // to a Service. // 6) Add a flow to bypass reject response packet sent by the controller. func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { - connectionTrackTable := c.pipeline[conntrackTable] - connectionTrackStateTable := c.pipeline[conntrackStateTable] - connectionTrackCommitTable := c.pipeline[conntrackCommitTable] flows := c.conntrackBasicFlows(category) if c.enableProxy { // Replace the default flow with multiple resubmits actions. if c.proxyAll { - flows = append(flows, connectionTrackStateTable.BuildFlow(priorityMiss). + flows = append(flows, ConntrackStateTable.BuildFlow(priorityMiss). Cookie(c.cookieAllocator.Request(category).Raw()). - Action().ResubmitToTable(serviceClassifierTable). - Action().ResubmitToTable(sessionAffinityTable). - Action().ResubmitToTable(serviceLBTable). + Action().ResubmitToTable(ServiceClassifierTable.GetID()). + Action().ResubmitToTable(SessionAffinityTable.GetID()). + Action().ResubmitToTable(ServiceLBTable.GetID()). Done()) } else { - flows = append(flows, connectionTrackStateTable.BuildFlow(priorityMiss). + flows = append(flows, ConntrackStateTable.BuildFlow(priorityMiss). Cookie(c.cookieAllocator.Request(category).Raw()). - Action().ResubmitToTable(sessionAffinityTable). - Action().ResubmitToTable(serviceLBTable). + Action().ResubmitToTable(SessionAffinityTable.GetID()). + Action().ResubmitToTable(ServiceLBTable.GetID()). Done()) } @@ -555,35 +528,33 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { } flows = append(flows, // This flow is used to maintain DNAT conntrack for Service traffic. - connectionTrackTable.BuildFlow(priorityNormal).MatchProtocol(proto). - Action().CT(false, connectionTrackTable.GetNext(), ctZone).NAT().CTDone(). + ConntrackTable.BuildFlow(priorityNormal).MatchProtocol(proto). + Action().CT(false, ConntrackTable.GetNext(), ctZone).NAT().CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), - connectionTrackCommitTable.BuildFlow(priorityLow).MatchProtocol(proto). + ConntrackCommitTable.BuildFlow(priorityLow).MatchProtocol(proto). MatchCTStateTrk(true). MatchCTMark(ServiceCTMark). MatchRegMark(EpSelectedRegMark). Cookie(c.cookieAllocator.Request(category).Raw()). - Action().GotoTable(connectionTrackCommitTable.GetNext()). + Action().GotoTable(ConntrackCommitTable.GetNext()). Done(), ) if c.proxyAll { - serviceConnectionTrackTable := c.pipeline[serviceConntrackTable] - serviceConnectionTrackCommitTable := c.pipeline[serviceConntrackCommitTable] flows = append(flows, // This flow is used to match the Service traffic from Antrea gateway. The Service traffic from gateway // should enter table serviceConntrackCommitTable, otherwise it will be matched by other flows in // table connectionTrackCommit. - connectionTrackCommitTable.BuildFlow(priorityHigh).MatchProtocol(proto). + ConntrackCommitTable.BuildFlow(priorityHigh).MatchProtocol(proto). MatchCTMark(ServiceCTMark). MatchRegMark(FromGatewayRegMark). - Action().GotoTable(serviceConntrackCommitTable). + Action().GotoTable(ServiceConntrackCommitTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), // This flow is used to maintain SNAT conntrack for Service traffic. - serviceConnectionTrackTable.BuildFlow(priorityNormal).MatchProtocol(proto). - Action().CT(false, serviceConnectionTrackTable.GetNext(), snatZone).NAT().CTDone(). + ServiceConntrackTable.BuildFlow(priorityNormal).MatchProtocol(proto). + Action().CT(false, ServiceConntrackTable.GetNext(), snatZone).NAT().CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), // This flow is used to match the following cases: @@ -597,24 +568,24 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { // - The first packet of ClusterIP and the Endpoint is not on local Pod CIDR or any remote Pod CIDRs. // As the packet is from Antrea gateway, and it will pass through Antrea gateway, a virtual IP is used // to perform SNAT for the packet, rather than Antrea gateway's IP. - serviceConnectionTrackCommitTable.BuildFlow(priorityHigh).MatchProtocol(proto). + ServiceConntrackCommitTable.BuildFlow(priorityHigh).MatchProtocol(proto). MatchRegMark(ToGatewayRegMark). Cookie(c.cookieAllocator.Request(category).Raw()). MatchCTStateNew(true). MatchCTStateTrk(true). - Action().CT(true, serviceConnectionTrackCommitTable.GetNext(), snatZone). + Action().CT(true, ServiceConntrackCommitTable.GetNext(), snatZone). SNAT(&binding.IPRange{StartIP: serviceVirtualIP, EndIP: serviceVirtualIP}, nil). CTDone(). Done(), // This flow is used to match the first packet of NodePort/LoadBalancer whose output port is not // Antrea gateway, and externalTrafficPolicy is Cluster. This packet requires SNAT. Antrea gateway // IP is used to perform SNAT for the packet. - serviceConnectionTrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). + ServiceConntrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). MatchRegMark(ServiceNeedSNATRegMark). Cookie(c.cookieAllocator.Request(category).Raw()). MatchCTStateNew(true). MatchCTStateTrk(true). - Action().CT(true, serviceConnectionTrackCommitTable.GetNext(), snatZone). + Action().CT(true, ServiceConntrackCommitTable.GetNext(), snatZone). SNAT(&binding.IPRange{StartIP: gatewayIP, EndIP: gatewayIP}, nil). CTDone(). Done(), @@ -651,11 +622,11 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { 192.168.77.1:12345<->192.168.77.100:30001, and the source IP is still 192.168.77.100. Before output, pkt 3 needs SNAT, but the connection has been committed. The flow is for pkt 3 to perform SNAT. */ - serviceConnectionTrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). + ServiceConntrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). Cookie(c.cookieAllocator.Request(category).Raw()). MatchCTStateNew(false). MatchCTStateTrk(true). - Action().CT(false, serviceConnectionTrackCommitTable.GetNext(), snatZone). + Action().CT(false, ServiceConntrackCommitTable.GetNext(), snatZone). NAT(). CTDone(). Done(), @@ -675,10 +646,10 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { } flows = append(flows, // Connections initiated through the gateway are marked with FromGatewayCTMark. - connectionTrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). + ConntrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). MatchRegMark(FromGatewayRegMark). MatchCTStateNew(true).MatchCTStateTrk(true). - Action().CT(true, connectionTrackCommitTable.GetNext(), ctZone).LoadToCtMark(FromGatewayCTMark).CTDone(). + Action().CT(true, ConntrackCommitTable.GetNext(), ctZone).LoadToCtMark(FromGatewayCTMark).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), // Add reject response packet bypass flow. @@ -691,26 +662,25 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { // conntrackBypassRejectFlow generates a flow which is used to bypass the reject // response packet sent by the controller to avoid unexpected packet drop. func (c *client) conntrackBypassRejectFlow(proto binding.Protocol) binding.Flow { - connectionTrackStateTable := c.pipeline[conntrackStateTable] - return connectionTrackStateTable.BuildFlow(priorityHigh). + return ConntrackStateTable.BuildFlow(priorityHigh). MatchProtocol(proto). MatchRegMark(CustomReasonRejectRegMark). Cookie(c.cookieAllocator.Request(cookie.Default).Raw()). - Action().ResubmitToTable(connectionTrackStateTable.GetNext()). + Action().ResubmitToTable(ConntrackStateTable.GetNext()). Done() } // dnsResponseBypassConntrackFlow generates a flow which is used to bypass the // dns response packetout from conntrack, to avoid unexpected packet drop. func (c *client) dnsResponseBypassConntrackFlow() binding.Flow { - table := c.pipeline[conntrackTable] + table := ConntrackTable if c.proxyAll { - table = c.pipeline[serviceConntrackTable] + table = ServiceConntrackTable } return table.BuildFlow(priorityHigh). MatchRegFieldWithValue(CustomReasonField, CustomReasonDNS). Cookie(c.cookieAllocator.Request(cookie.Default).Raw()). - Action().ResubmitToTable(l2ForwardingCalcTable). + Action().ResubmitToTable(L2ForwardingCalcTable.GetID()). Done() } @@ -719,21 +689,18 @@ func (c *client) dnsResponseBypassConntrackFlow() binding.Flow { // should be sent directly to the requesting client without being intercepted // again. func (c *client) dnsResponseBypassPacketInFlow() binding.Flow { - dnsPacketInTable := c.pipeline[AntreaPolicyIngressRuleTable] // TODO: use a unified register bit to mark packetOuts. The pipeline does not need to be // aware of why the packetOut is being set by the controller, it just needs to be aware that // this is a packetOut message and that some pipeline stages (conntrack, policy enforcement) // should therefore be skipped. - return dnsPacketInTable.BuildFlow(priorityDNSBypass). + return AntreaPolicyIngressRuleTable.BuildFlow(priorityDNSBypass). MatchRegFieldWithValue(CustomReasonField, CustomReasonDNS). Cookie(c.cookieAllocator.Request(cookie.Default).Raw()). - Action().ResubmitToTable(L2ForwardingOutTable). + Action().ResubmitToTable(L2ForwardingOutTable.GetID()). Done() } func (c *client) conntrackBasicFlows(category cookie.Category) []binding.Flow { - connectionTrackStateTable := c.pipeline[conntrackStateTable] - connectionTrackCommitTable := c.pipeline[conntrackCommitTable] var flows []binding.Flow for _, proto := range c.ipProtocols { ctZone := CtZone @@ -741,14 +708,14 @@ func (c *client) conntrackBasicFlows(category cookie.Category) []binding.Flow { ctZone = CtZoneV6 } flows = append(flows, - connectionTrackStateTable.BuildFlow(priorityLow).MatchProtocol(proto). + ConntrackStateTable.BuildFlow(priorityLow).MatchProtocol(proto). MatchCTStateInv(true).MatchCTStateTrk(true). Action().Drop(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), - connectionTrackCommitTable.BuildFlow(priorityLow).MatchProtocol(proto). + ConntrackCommitTable.BuildFlow(priorityLow).MatchProtocol(proto). MatchCTStateNew(true).MatchCTStateTrk(true). - Action().CT(true, connectionTrackCommitTable.GetNext(), ctZone).CTDone(). + Action().CT(true, ConntrackCommitTable.GetNext(), ctZone).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), ) @@ -757,7 +724,6 @@ func (c *client) conntrackBasicFlows(category cookie.Category) []binding.Flow { } func (c *client) kubeProxyFlows(category cookie.Category) []binding.Flow { - connectionTrackTable := c.pipeline[conntrackTable] var flows []binding.Flow for _, proto := range c.ipProtocols { ctZone := CtZone @@ -765,8 +731,8 @@ func (c *client) kubeProxyFlows(category cookie.Category) []binding.Flow { ctZone = CtZoneV6 } flows = append(flows, - connectionTrackTable.BuildFlow(priorityNormal).MatchProtocol(proto). - Action().CT(false, connectionTrackTable.GetNext(), ctZone).CTDone(). + ConntrackTable.BuildFlow(priorityNormal).MatchProtocol(proto). + Action().CT(false, ConntrackTable.GetNext(), ctZone).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), ) @@ -777,7 +743,7 @@ func (c *client) kubeProxyFlows(category cookie.Category) []binding.Flow { // TODO: Use DuplicateToBuilder or integrate this function into original one to avoid unexpected // difference. // traceflowConnectionTrackFlows generates Traceflow specific flows in the -// connectionTrackStateTable or l2ForwardingCalcTable. When packet is not +// connectionTrackStateTable or L2ForwardingCalcTable. When packet is not // provided, the flows bypass the drop flow in connectionTrackFlows to avoid // unexpected drop of the injected Traceflow packet, and to drop any Traceflow // packet that has ct_state +rpl, which may happen when the Traceflow request @@ -786,29 +752,28 @@ func (c *client) kubeProxyFlows(category cookie.Category) []binding.Flow { // first connection that matches the provided packet - as the Traceflow packet. // The flow is added in connectionTrackStateTable when receiverOnly is false and // it also matches in_port to be the provided ofPort (the sender Pod); otherwise -// when receiverOnly is true, the flow is added into l2ForwardingCalcTable and +// when receiverOnly is true, the flow is added into L2ForwardingCalcTable and // matches the destination MAC (the receiver Pod MAC). func (c *client) traceflowConnectionTrackFlows(dataplaneTag uint8, receiverOnly bool, packet *binding.Packet, ofPort uint32, timeout uint16, category cookie.Category) []binding.Flow { - connectionTrackStateTable := c.pipeline[conntrackStateTable] var flows []binding.Flow if packet == nil { for _, ipProtocol := range c.ipProtocols { - flowBuilder := connectionTrackStateTable.BuildFlow(priorityLow + 1). + flowBuilder := ConntrackStateTable.BuildFlow(priorityLow + 1). MatchProtocol(ipProtocol). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). Cookie(c.cookieAllocator.Request(category).Raw()) if c.enableProxy { flowBuilder = flowBuilder. - Action().ResubmitToTable(sessionAffinityTable). - Action().ResubmitToTable(serviceLBTable) + Action().ResubmitToTable(SessionAffinityTable.GetID()). + Action().ResubmitToTable(ServiceLBTable.GetID()) } else { flowBuilder = flowBuilder. - Action().ResubmitToTable(connectionTrackStateTable.GetNext()) + Action().ResubmitToTable(ConntrackStateTable.GetNext()) } flows = append(flows, flowBuilder.Done()) - flows = append(flows, connectionTrackStateTable.BuildFlow(priorityLow+2). + flows = append(flows, ConntrackStateTable.BuildFlow(priorityLow+2). MatchProtocol(ipProtocol). MatchIPDSCP(dataplaneTag). MatchCTStateTrk(true).MatchCTStateRpl(true). @@ -820,7 +785,7 @@ func (c *client) traceflowConnectionTrackFlows(dataplaneTag uint8, receiverOnly } else { var flowBuilder binding.FlowBuilder if !receiverOnly { - flowBuilder = connectionTrackStateTable.BuildFlow(priorityLow). + flowBuilder = ConntrackStateTable.BuildFlow(priorityLow). MatchInPort(ofPort). Action().LoadIPDSCP(dataplaneTag) if packet.DestinationIP != nil { @@ -828,16 +793,15 @@ func (c *client) traceflowConnectionTrackFlows(dataplaneTag uint8, receiverOnly } if c.enableProxy { flowBuilder = flowBuilder. - Action().ResubmitToTable(sessionAffinityTable). - Action().ResubmitToTable(serviceLBTable) + Action().ResubmitToTable(SessionAffinityTable.GetID()). + Action().ResubmitToTable(ServiceLBTable.GetID()) } else { flowBuilder = flowBuilder. - Action().ResubmitToTable(connectionTrackStateTable.GetNext()) + Action().ResubmitToTable(ConntrackStateTable.GetNext()) } } else { - l2FwdCalcTable := c.pipeline[l2ForwardingCalcTable] nextTable := c.ingressEntryTable - flowBuilder = l2FwdCalcTable.BuildFlow(priorityHigh). + flowBuilder = L2ForwardingCalcTable.BuildFlow(priorityHigh). MatchDstMAC(packet.DestinationMAC). Action().LoadToRegField(TargetOFPortField, ofPort). Action().LoadRegMark(OFPortFoundRegMark). @@ -955,23 +919,22 @@ func (c *client) traceflowNetworkPolicyFlows(dataplaneTag uint8, timeout uint16, // serviceLBBypassFlows makes packets that belong to a tracked connection bypass // service LB tables and enter egressRuleTable directly. func (c *client) serviceLBBypassFlows(ipProtocol binding.Protocol) []binding.Flow { - connectionTrackStateTable := c.pipeline[conntrackStateTable] flows := []binding.Flow{ // Tracked connections with the ServiceCTMark (load-balanced by AntreaProxy) receive // the macRewriteMark and are sent to egressRuleTable. - connectionTrackStateTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + ConntrackStateTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchCTMark(ServiceCTMark). MatchCTStateNew(false).MatchCTStateTrk(true). Action().LoadRegMark(RewriteMACRegMark). - Action().GotoTable(EgressRuleTable). + Action().GotoTable(EgressRuleTable.GetID()). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done(), // Tracked connections without the ServiceCTMark are sent to egressRuleTable // directly. This is meant to match connections which were load-balanced by // kube-proxy before AntreaProxy got enabled. - connectionTrackStateTable.BuildFlow(priorityLow).MatchProtocol(ipProtocol). + ConntrackStateTable.BuildFlow(priorityLow).MatchProtocol(ipProtocol). MatchCTStateNew(false).MatchCTStateTrk(true). - Action().GotoTable(EgressRuleTable). + Action().GotoTable(EgressRuleTable.GetID()). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done(), } @@ -980,13 +943,12 @@ func (c *client) serviceLBBypassFlows(ipProtocol binding.Protocol) []binding.Flo // l2ForwardCalcFlow generates the flow that matches dst MAC and loads ofPort to reg. func (c *client) l2ForwardCalcFlow(dstMAC net.HardwareAddr, ofPort uint32, skipIngressRules bool, category cookie.Category) binding.Flow { - l2FwdCalcTable := c.pipeline[l2ForwardingCalcTable] - nextTable := l2FwdCalcTable.GetNext() + nextTable := L2ForwardingCalcTable.GetNext() if !skipIngressRules { // Go to ingress NetworkPolicy tables for traffic to local Pods. nextTable = c.ingressEntryTable } - return l2FwdCalcTable.BuildFlow(priorityNormal). + return L2ForwardingCalcTable.BuildFlow(priorityNormal). MatchDstMAC(dstMAC). Action().LoadToRegField(TargetOFPortField, ofPort). Action().LoadRegMark(OFPortFoundRegMark). @@ -1001,11 +963,10 @@ func (c *client) l2ForwardCalcFlow(dstMAC net.HardwareAddr, ofPort uint32, skipI // to OVS port and Antrea Agent after L2forwarding calculation. func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, droppedOnly bool, timeout uint16, category cookie.Category) []binding.Flow { flows := []binding.Flow{} - l2FwdOutTable := c.pipeline[L2ForwardingOutTable] for _, ipProtocol := range c.ipProtocols { if c.networkConfig.TrafficEncapMode.SupportsEncap() { // SendToController and Output if output port is tunnel port. - fb1 := l2FwdOutTable.BuildFlow(priorityNormal+3). + fb1 := L2ForwardingOutTable.BuildFlow(priorityNormal+3). MatchRegFieldWithValue(TargetOFPortField, config.DefaultTunOFPort). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). @@ -1017,7 +978,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, // gateway. In encapMode, a Traceflow packet going out of the gateway // port (i.e. exiting the overlay) essentially means that the Traceflow // request is complete. - fb2 := l2FwdOutTable.BuildFlow(priorityNormal+2). + fb2 := L2ForwardingOutTable.BuildFlow(priorityNormal+2). MatchRegFieldWithValue(TargetOFPortField, config.HostGatewayOFPort). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). @@ -1044,7 +1005,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, // SendToController and Output if output port is local gateway. Unlike in // encapMode, inter-Node Pod-to-Pod traffic is expected to go out of the // gateway port on the way to its destination. - fb1 := l2FwdOutTable.BuildFlow(priorityNormal+2). + fb1 := L2ForwardingOutTable.BuildFlow(priorityNormal+2). MatchRegFieldWithValue(TargetOFPortField, config.HostGatewayOFPort). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). @@ -1066,7 +1027,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, gatewayIP = c.nodeConfig.GatewayConfig.IPv6 } if gatewayIP != nil { - fb := l2FwdOutTable.BuildFlow(priorityNormal+3). + fb := L2ForwardingOutTable.BuildFlow(priorityNormal+3). MatchRegFieldWithValue(TargetOFPortField, config.HostGatewayOFPort). MatchDstIP(gatewayIP). MatchIPDSCP(dataplaneTag). @@ -1087,7 +1048,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, flows = append(flows, fb.Done()) } // Only SendToController if output port is Pod port. - fb := l2FwdOutTable.BuildFlow(priorityNormal + 2). + fb := L2ForwardingOutTable.BuildFlow(priorityNormal + 2). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). @@ -1107,7 +1068,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, if c.enableProxy { // Only SendToController for hairpin traffic. // This flow must have higher priority than the one installed by l2ForwardOutputServiceHairpinFlow - fbHairpin := l2FwdOutTable.BuildFlow(priorityHigh + 2). + fbHairpin := L2ForwardingOutTable.BuildFlow(priorityHigh + 2). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). @@ -1132,7 +1093,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, // l2ForwardOutputServiceHairpinFlow uses in_port action for Service // hairpin packets to avoid packets from being dropped by OVS. func (c *client) l2ForwardOutputServiceHairpinFlow() binding.Flow { - return c.pipeline[L2ForwardingOutTable].BuildFlow(priorityHigh). + return L2ForwardingOutTable.BuildFlow(priorityHigh). MatchRegMark(HairpinRegMark). Action().OutputInPort(). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). @@ -1143,12 +1104,12 @@ func (c *client) l2ForwardOutputServiceHairpinFlow() binding.Flow { func (c *client) l2ForwardOutputFlows(category cookie.Category) []binding.Flow { var flows []binding.Flow flows = append(flows, - c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). + L2ForwardingOutTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). MatchRegMark(OFPortFoundRegMark). Action().OutputToRegField(TargetOFPortField). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), - c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). + L2ForwardingOutTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). MatchRegMark(OFPortFoundRegMark). Action().OutputToRegField(TargetOFPortField). Cookie(c.cookieAllocator.Request(category).Raw()). @@ -1162,17 +1123,16 @@ func (c *client) l2ForwardOutputFlows(category cookie.Category) []binding.Flow { // the Pod interface MAC, and rewrites the source MAC to the gateway interface // MAC. func (c *client) l3FwdFlowToPod(localGatewayMAC net.HardwareAddr, podInterfaceIPs []net.IP, podInterfaceMAC net.HardwareAddr, category cookie.Category) []binding.Flow { - l3FwdTable := c.pipeline[l3ForwardingTable] var flows []binding.Flow for _, ip := range podInterfaceIPs { ipProtocol := getIPProtocol(ip) - flows = append(flows, l3FwdTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + flows = append(flows, L3ForwardingTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchRegMark(RewriteMACRegMark). MatchDstIP(ip). Action().SetSrcMAC(localGatewayMAC). // Rewrite src MAC to local gateway MAC, and rewrite dst MAC to pod MAC Action().SetDstMAC(podInterfaceMAC). - Action().GotoTable(l3DecTTLTable). + Action().GotoTable(L3DecTTLTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } @@ -1184,14 +1144,13 @@ func (c *client) l3FwdFlowToPod(localGatewayMAC net.HardwareAddr, podInterfaceIP // interface MAC. The flow is used in the networkPolicyOnly mode for the traffic // from the gateway to a local Pod. func (c *client) l3FwdFlowRouteToPod(podInterfaceIPs []net.IP, podInterfaceMAC net.HardwareAddr, category cookie.Category) []binding.Flow { - l3FwdTable := c.pipeline[l3ForwardingTable] var flows []binding.Flow for _, ip := range podInterfaceIPs { ipProtocol := getIPProtocol(ip) - flows = append(flows, l3FwdTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + flows = append(flows, L3ForwardingTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchDstIP(ip). Action().SetDstMAC(podInterfaceMAC). - Action().GotoTable(l3DecTTLTable). + Action().GotoTable(L3DecTTLTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } @@ -1203,12 +1162,11 @@ func (c *client) l3FwdFlowRouteToPod(podInterfaceIPs []net.IP, podInterfaceMAC n // interface MAC. The flow is used in the networkPolicyOnly mode for the traffic // from a local Pod to remote Pods, Nodes, or external network. func (c *client) l3FwdFlowRouteToGW(gwMAC net.HardwareAddr, category cookie.Category) []binding.Flow { - l3FwdTable := c.pipeline[l3ForwardingTable] var flows []binding.Flow for _, ipProto := range c.ipProtocols { - flows = append(flows, l3FwdTable.BuildFlow(priorityLow).MatchProtocol(ipProto). + flows = append(flows, L3ForwardingTable.BuildFlow(priorityLow).MatchProtocol(ipProto). Action().SetDstMAC(gwMAC). - Action().GotoTable(l3FwdTable.GetNext()). + Action().GotoTable(L3ForwardingTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), ) @@ -1219,15 +1177,14 @@ func (c *client) l3FwdFlowRouteToGW(gwMAC net.HardwareAddr, category cookie.Cate // l3FwdFlowToGateway generates the L3 forward flows to rewrite the destination MAC of the packets to the gateway interface // MAC if the destination IP is the gateway IP or the connection was initiated through the gateway interface. func (c *client) l3FwdFlowToGateway(localGatewayIPs []net.IP, localGatewayMAC net.HardwareAddr, category cookie.Category) []binding.Flow { - l3FwdTable := c.pipeline[l3ForwardingTable] var flows []binding.Flow for _, ip := range localGatewayIPs { ipProtocol := getIPProtocol(ip) - flows = append(flows, l3FwdTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + flows = append(flows, L3ForwardingTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchRegMark(RewriteMACRegMark). MatchDstIP(ip). Action().SetDstMAC(localGatewayMAC). - Action().GotoTable(l3FwdTable.GetNext()). + Action().GotoTable(L3ForwardingTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } @@ -1244,11 +1201,11 @@ func (c *client) l3FwdFlowToGateway(localGatewayIPs []net.IP, localGatewayMAC ne // AntreaProxy is enabled by default). One example is a Pod accessing a NodePort Service for which // externalTrafficPolicy is set to Local, using the local Node's IP address. for _, proto := range c.ipProtocols { - flows = append(flows, l3FwdTable.BuildFlow(priorityHigh).MatchProtocol(proto). + flows = append(flows, L3ForwardingTable.BuildFlow(priorityHigh).MatchProtocol(proto). MatchCTMark(FromGatewayCTMark). MatchCTStateRpl(true).MatchCTStateTrk(true). Action().SetDstMAC(localGatewayMAC). - Action().GotoTable(l3FwdTable.GetNext()). + Action().GotoTable(L3ForwardingTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } @@ -1263,14 +1220,14 @@ func (c *client) l3FwdFlowToRemote( tunnelPeer net.IP, category cookie.Category) binding.Flow { ipProto := getIPProtocol(peerSubnet.IP) - return c.pipeline[l3ForwardingTable].BuildFlow(priorityNormal).MatchProtocol(ipProto). + return L3ForwardingTable.BuildFlow(priorityNormal).MatchProtocol(ipProto). MatchDstIPNet(peerSubnet). // Rewrite src MAC to local gateway MAC and rewrite dst MAC to virtual MAC. Action().SetSrcMAC(localGatewayMAC). Action().SetDstMAC(globalVirtualMAC). // Flow based tunnel. Set tunnel destination. Action().SetTunnelDst(tunnelPeer). - Action().GotoTable(l3DecTTLTable). + Action().GotoTable(L3DecTTLTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } @@ -1283,11 +1240,10 @@ func (c *client) l3FwdFlowToRemoteViaGW( peerSubnet net.IPNet, category cookie.Category) binding.Flow { ipProto := getIPProtocol(peerSubnet.IP) - l3FwdTable := c.pipeline[l3ForwardingTable] - return l3FwdTable.BuildFlow(priorityNormal).MatchProtocol(ipProto). + return L3ForwardingTable.BuildFlow(priorityNormal).MatchProtocol(ipProto). MatchDstIPNet(peerSubnet). Action().SetDstMAC(localGatewayMAC). - Action().GotoTable(l3FwdTable.GetNext()). + Action().GotoTable(L3ForwardingTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } @@ -1305,12 +1261,12 @@ func (c *client) l3FwdServiceDefaultFlowsViaGW(ipProto binding.Protocol, categor // - NodePort/LoadBalancer/ClusterIP response packets. // The matched packets should leave through Antrea gateway, however, they also enter through Antrea gateway. This // is hairpin traffic. - c.pipeline[l3ForwardingTable].BuildFlow(priorityLow).MatchProtocol(ipProto). + L3ForwardingTable.BuildFlow(priorityLow).MatchProtocol(ipProto). MatchCTMark(ServiceCTMark). MatchCTStateTrk(true). MatchRegMark(RewriteMACRegMark). Action().SetDstMAC(gatewayMAC). - Action().GotoTable(l3DecTTLTable). + Action().GotoTable(L3DecTTLTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), } @@ -1320,7 +1276,7 @@ func (c *client) l3FwdServiceDefaultFlowsViaGW(ipProto binding.Protocol, categor // arpResponderFlow generates the ARP responder flow entry that replies request comes from local gateway for peer // gateway MAC. func (c *client) arpResponderFlow(peerGatewayIP net.IP, category cookie.Category) binding.Flow { - return c.pipeline[arpResponderTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). + return arpResponderTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). MatchARPOp(arpOpRequest). MatchARPTpa(peerGatewayIP). Action().Move(binding.NxmFieldSrcMAC, binding.NxmFieldDstMAC). @@ -1338,7 +1294,7 @@ func (c *client) arpResponderFlow(peerGatewayIP net.IP, category cookie.Category // arpResponderStaticFlow generates ARP reply for any ARP request with the same global virtual MAC. // This flow is used in policy-only mode, where traffic are routed via IP not MAC. func (c *client) arpResponderStaticFlow(category cookie.Category) binding.Flow { - return c.pipeline[arpResponderTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). + return arpResponderTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). MatchARPOp(arpOpRequest). Action().Move(binding.NxmFieldSrcMAC, binding.NxmFieldDstMAC). Action().SetSrcMAC(globalVirtualMAC). @@ -1357,25 +1313,23 @@ func (c *client) arpResponderStaticFlow(category cookie.Category) binding.Flow { // podIPSpoofGuardFlow generates the flow to check IP traffic sent out from local pod. Traffic from host gateway interface // will not be checked, since it might be pod to service traffic or host namespace traffic. func (c *client) podIPSpoofGuardFlow(ifIPs []net.IP, ifMAC net.HardwareAddr, ifOFPort uint32, category cookie.Category) []binding.Flow { - ipPipeline := c.pipeline - ipSpoofGuardTable := ipPipeline[spoofGuardTable] var flows []binding.Flow for _, ifIP := range ifIPs { ipProtocol := getIPProtocol(ifIP) if ipProtocol == binding.ProtocolIP { - flows = append(flows, ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + flows = append(flows, SpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchInPort(ifOFPort). MatchSrcMAC(ifMAC). MatchSrcIP(ifIP). - Action().GotoTable(ipSpoofGuardTable.GetNext()). + Action().GotoTable(SpoofGuardTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } else if ipProtocol == binding.ProtocolIPv6 { - flows = append(flows, ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + flows = append(flows, SpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchInPort(ifOFPort). MatchSrcMAC(ifMAC). MatchSrcIP(ifIP). - Action().GotoTable(ipv6Table). + Action().GotoTable(IPv6Table.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } @@ -1404,12 +1358,11 @@ func (c *client) serviceHairpinResponseDNATFlow(ipProtocol binding.Protocol) bin from = binding.NxmFieldSrcIPv6 to = binding.NxmFieldDstIPv6 } - hairpinTable := c.pipeline[serviceHairpinTable] - return hairpinTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + return ServiceHairpinTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchDstIP(hpIP). Action().Move(from, to). Action().LoadRegMark(HairpinRegMark). - Action().GotoTable(hairpinTable.GetNext()). + Action().GotoTable(ServiceHairpinTable.GetNext()). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() } @@ -1418,62 +1371,60 @@ func (c *client) serviceHairpinResponseDNATFlow(ipProtocol binding.Protocol) bin // its output interface is also Antrea gateway. In table L2ForwardingOutTable #110, a packet with hairpin mark will be // sent out with action IN_PORT, otherwise the packet with action output will be dropped. func (c *client) serviceHairpinRegSetFlows(ipProtocol binding.Protocol) binding.Flow { - return c.pipeline[hairpinSNATTable].BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + return HairpinSNATTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchRegMark(FromGatewayRegMark). MatchRegMark(ToGatewayRegMark). Action().LoadRegMark(HairpinRegMark). - Action().GotoTable(L2ForwardingOutTable). + Action().GotoTable(L2ForwardingOutTable.GetID()). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() } // gatewayARPSpoofGuardFlow generates the flow to check ARP traffic sent out from the local gateway interface. func (c *client) gatewayARPSpoofGuardFlow(gatewayIP net.IP, gatewayMAC net.HardwareAddr, category cookie.Category) binding.Flow { - return c.pipeline[spoofGuardTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). + return SpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). MatchInPort(config.HostGatewayOFPort). MatchARPSha(gatewayMAC). MatchARPSpa(gatewayIP). - Action().GotoTable(arpResponderTable). + Action().GotoTable(arpResponderTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } // arpSpoofGuardFlow generates the flow to check ARP traffic sent out from local pods interfaces. func (c *client) arpSpoofGuardFlow(ifIP net.IP, ifMAC net.HardwareAddr, ifOFPort uint32, category cookie.Category) binding.Flow { - return c.pipeline[spoofGuardTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). + return SpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). MatchInPort(ifOFPort). MatchARPSha(ifMAC). MatchARPSpa(ifIP). - Action().GotoTable(arpResponderTable). + Action().GotoTable(arpResponderTable.GetID()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } // sessionAffinityReselectFlow generates the flow which resubmits the service accessing -// packet back to serviceLBTable if there is no endpointDNAT flow matched. This +// packet back to ServiceLBTable if there is no endpointDNAT flow matched. This // case will occur if an Endpoint is removed and is the learned Endpoint // selection of the Service. func (c *client) sessionAffinityReselectFlow() binding.Flow { - return c.pipeline[endpointDNATTable].BuildFlow(priorityLow). + return EndpointDNATTable.BuildFlow(priorityLow). MatchRegMark(EpSelectedRegMark). Action().LoadRegMark(EpToSelectRegMark). - Action().ResubmitToTable(serviceLBTable). + Action().ResubmitToTable(ServiceLBTable.GetID()). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() } // gatewayIPSpoofGuardFlow generates the flow to skip spoof guard checking for traffic sent from gateway interface. func (c *client) gatewayIPSpoofGuardFlows(category cookie.Category) []binding.Flow { - ipPipeline := c.pipeline - ipSpoofGuardTable := ipPipeline[spoofGuardTable] var flows []binding.Flow for _, proto := range c.ipProtocols { - nextTable := ipSpoofGuardTable.GetNext() + nextTable := SpoofGuardTable.GetNext() if proto == binding.ProtocolIPv6 { - nextTable = ipv6Table + nextTable = IPv6Table.GetID() } flows = append(flows, - ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(proto). + SpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(proto). MatchInPort(config.HostGatewayOFPort). Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(category).Raw()). @@ -1489,11 +1440,11 @@ func (c *client) serviceCIDRDNATFlows(serviceCIDRs []*net.IPNet) []binding.Flow for _, serviceCIDR := range serviceCIDRs { if serviceCIDR != nil { ipProto := getIPProtocol(serviceCIDR.IP) - flows = append(flows, c.pipeline[dnatTable].BuildFlow(priorityNormal).MatchProtocol(ipProto). + flows = append(flows, DNATTable.BuildFlow(priorityNormal).MatchProtocol(ipProto). MatchDstIPNet(*serviceCIDR). Action().LoadToRegField(TargetOFPortField, config.HostGatewayOFPort). Action().LoadRegMark(OFPortFoundRegMark). - Action().GotoTable(conntrackCommitTable). + Action().GotoTable(ConntrackCommitTable.GetID()). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done()) } @@ -1503,7 +1454,7 @@ func (c *client) serviceCIDRDNATFlows(serviceCIDRs []*net.IPNet) []binding.Flow // serviceNeedLBFlow generates flows to mark packets as LB needed. func (c *client) serviceNeedLBFlow() binding.Flow { - return c.pipeline[sessionAffinityTable].BuildFlow(priorityMiss). + return SessionAffinityTable.BuildFlow(priorityMiss). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Action().LoadRegMark(EpToSelectRegMark). Done() @@ -1511,29 +1462,29 @@ func (c *client) serviceNeedLBFlow() binding.Flow { // arpNormalFlow generates the flow to response arp in normal way if no flow in arpResponderTable is matched. func (c *client) arpNormalFlow(category cookie.Category) binding.Flow { - return c.pipeline[arpResponderTable].BuildFlow(priorityLow).MatchProtocol(binding.ProtocolARP). + return arpResponderTable.BuildFlow(priorityLow).MatchProtocol(binding.ProtocolARP). Action().Normal(). Cookie(c.cookieAllocator.Request(category).Raw()). Done() } func (c *client) allowRulesMetricFlows(conjunctionID uint32, ingress bool) []binding.Flow { - metricTableID := IngressMetricTable + metricTable := IngressMetricTable offset := 0 // We use the 0..31 bits of the ct_label to store the ingress rule ID and use the 32..63 bits to store the // egress rule ID. field := IngressRuleCTLabel if !ingress { - metricTableID = EgressMetricTable + metricTable = EgressMetricTable offset = 32 field = EgressRuleCTLabel } metricFlow := func(isCTNew bool, protocol binding.Protocol) binding.Flow { - return c.pipeline[metricTableID].BuildFlow(priorityNormal). + return metricTable.BuildFlow(priorityNormal). MatchProtocol(protocol). MatchCTStateNew(isCTNew). MatchCTLabelField(0, uint64(conjunctionID)<