diff --git a/docs/design/ovs-pipeline.md b/docs/design/ovs-pipeline.md index 95607f832df..44b5c0e6c9a 100644 --- a/docs/design/ovs-pipeline.md +++ b/docs/design/ovs-pipeline.md @@ -66,7 +66,7 @@ that Node and `` is the name of the bridge created by Antrea We use 2 32-bit OVS registers to carry information throughout the pipeline: * reg0 (NXM_NX_REG0): - - bits [0..15] are used to store the traffic source (from tunnel: 0, from + - bits [0..3] are used to store the traffic source (from tunnel: 0, from local gateway: 1, from local Pod: 2). It is set in the [ClassifierTable]. - bit 16 is used to indicate whether the destination MAC address of a packet is "known", i.e. corresponds to an entry in [L2ForwardingCalcTable], which @@ -621,8 +621,8 @@ be SNAT'd with a SNAT IP configured on the Node. In the latter case, the flow also rewrites the destination MAC to the local gateway interface MAC. ```text -table=70, priority=190,ip,reg0=0x2/0xffff actions=goto_table:71 -table=70, priority=190,ip,reg0=0/0xffff actions=mod_dl_dst:e2:e5:a4:9b:1c:b1,goto_table:71 +table=70, priority=190,ip,reg0=0x2/0xf actions=goto_table:71 +table=70, priority=190,ip,reg0=0/0xf actions=mod_dl_dst:e2:e5:a4:9b:1c:b1,goto_table:71 ``` ### SNATTable (71) @@ -639,7 +639,7 @@ Egress applied, to [L2ForwardingCalcTable]. Such traffic will be SNAT'd with the default SNAT IP (by an iptables masquerade rule). ```text -table=71, priority=190,ct_state=+new+trk,ip,reg0=0/0xffff actions=drop +table=71, priority=190,ct_state=+new+trk,ip,reg0=0/0xf actions=drop table=71, priority=0 actions=goto_table:80 ``` @@ -685,7 +685,7 @@ IP stack should have already decremented TTL if that is needed. If you dump the flows for this table, you should see flows like the following: ```text -1. table=72, priority=210,ip,reg0=0x1/0xffff, actions=goto_table:80 +1. table=72, priority=210,ip,reg0=0x1/0xf, actions=goto_table:80 2. table=72, priority=200,ip, actions=dec_ttl,goto_table:80 3. table=72, priority=0, actions=goto_table:80 ``` @@ -884,7 +884,7 @@ which are not dropped because of Network Policies. If you dump the flows for thi table, you should see something like this: ```text -1. table=105, priority=200,ct_state=+new+trk,ip,reg0=0x1/0xffff actions=ct(commit,table=110,zone=65520,exec(load:0x20->NXM_NX_CT_MARK[])) +1. table=105, priority=200,ct_state=+new+trk,ip,reg0=0x1/0xf actions=ct(commit,table=110,zone=65520,exec(load:0x20->NXM_NX_CT_MARK[])) 2. table=105, priority=190,ct_state=+new+trk,ip actions=ct(commit,table=110,zone=65520) 3. table=105, priority=0 actions=goto_table:110 ``` diff --git a/docs/design/windows-design.md b/docs/design/windows-design.md index 488d3ed384c..7e832f7a5c5 100644 --- a/docs/design/windows-design.md +++ b/docs/design/windows-design.md @@ -173,24 +173,24 @@ Classifier Table: 0 table=0, priority=200, in_port=$uplink,ip actions=load:0x4->NXM_NX_REG0[0..15],goto_table:5 Uplink Table: 5 -table=5, priority=200, ip,reg0=0x4/0xffff actions=goto_table:30 +table=5, priority=200, ip,reg0=0x4/0xf actions=goto_table:30 Conntrack Table: 30 table=30, priority=200, ip actions=ct(table=31,zone=65520,nat) ConntrackState Table: 31 -table=31, priority=210, ct_state=-new+trk,ct_mark=0x40,ip,reg0=0x4/0xffff actions=load:0x1->NXM_NX_REG0[19],goto_table:40 -table=31, priority=200, ip,reg0=0x4/0xffff actions=output:br-int +table=31, priority=210, ct_state=-new+trk,ct_mark=0x40,ip,reg0=0x4/0xf actions=load:0x1->NXM_NX_REG0[19],goto_table:40 +table=31, priority=200, ip,reg0=0x4/0xf actions=output:br-int L3Forwarding Table: 70 // Forward the packet to L2ForwardingCalculation table if it is traffic to the local Pods and doesn't require MAC rewriting. table=70, priority=200, ip,reg0=0/0x80000,nw_dst=10.10.0.0/24 actions=goto_table:80 // Forward the packet to L2ForwardingCalculation table if it is Pod-to-Node traffic. -table=70, priority=200, ip,reg0=0x2/0xffff,nw_dst=$local_nodeIP actions=goto_table:80 +table=70, priority=200, ip,reg0=0x2/0xf,nw_dst=$local_nodeIP actions=goto_table:80 // Forward the packet to L2ForwardingCalculation table if it is return traffic of an external-to-Pod connection. table=70, priority=210, ct_state=+rpl+trk,ct_mark=0x20,ip actions=mod_dl_dst:0e:6d:42:66:92:46,resubmit(,80) // Add SNAT mark if it is Pod-to-external traffic. -table=70, priority=190, ct_state=+new+trk,ip,reg0=0x2/0xffff actions=load:0x1->NXM_NX_REG0[17], goto_table:80 +table=70, priority=190, ct_state=+new+trk,ip,reg0=0x2/0xf actions=load:0x1->NXM_NX_REG0[17], goto_table:80 ConntrackCommit Table: 105 table=105, priority=200, ct_state=+new+trk,ip,reg0=0x20000/0x20000, actions=ct(commit,table=110,zone=65520,nat(src=${nodeIP}:10000-20000),exec(load:0x40->NXM_NX_CT_MARK[]))) diff --git a/pkg/agent/controller/networkpolicy/packetin.go b/pkg/agent/controller/networkpolicy/packetin.go index 233a4dc386a..9872e35f2e7 100644 --- a/pkg/agent/controller/networkpolicy/packetin.go +++ b/pkg/agent/controller/networkpolicy/packetin.go @@ -105,24 +105,27 @@ func (c *Controller) HandlePacketIn(pktIn *ofctrl.PacketIn) error { matches := pktIn.GetMatches() // Get custom reasons in this packet-in. - match := getMatchRegField(matches, uint32(openflow.CustomReasonMarkReg)) - customReasons, err := getInfoInReg(match, openflow.CustomReasonMarkRange.ToNXRange()) + match := getMatchRegField(matches, openflow.CustomReasonField) + customReasons, err := getInfoInReg(match, openflow.CustomReasonField.GetRange().ToNXRange()) if err != nil { return fmt.Errorf("received error while unloading customReason from reg: %v", err) } // Use reasons to choose operations. - if customReasons&openflow.CustomReasonLogging == openflow.CustomReasonLogging { + var checkCustomReason = func(customReasonMark *binding.RegMark) bool { + return customReasons&customReasonMark.GetValue() == customReasonMark.GetValue() + } + if checkCustomReason(openflow.MarkCustomReasonLogging) { if err := c.logPacket(pktIn); err != nil { return err } } - if customReasons&openflow.CustomReasonReject == openflow.CustomReasonReject { + if checkCustomReason(openflow.MarkCustomReasonReject) { if err := c.rejectRequest(pktIn); err != nil { return err } } - if customReasons&openflow.CustomReasonDeny == openflow.CustomReasonDeny { + if checkCustomReason(openflow.MarkCustomReasonDeny) { if err := c.storeDenyConnection(pktIn); err != nil { return err } @@ -152,9 +155,9 @@ func (c *Controller) logPacket(pktIn *ofctrl.PacketIn) error { return nil } -// getMatchRegField returns match to the regNum register. -func getMatchRegField(matchers *ofctrl.Matchers, regNum uint32) *ofctrl.MatchField { - return matchers.GetMatchByName(fmt.Sprintf("NXM_NX_REG%d", regNum)) +// getMatchRegField returns the match register according to the specified RegField. +func getMatchRegField(matchers *ofctrl.Matchers, field *binding.RegField) *ofctrl.MatchField { + return matchers.GetMatchByName(field.GetNXFieldName()) } // getMatch receives ofctrl matchers and table id, match field. @@ -162,17 +165,17 @@ func getMatchRegField(matchers *ofctrl.Matchers, regNum uint32) *ofctrl.MatchFie func getMatch(matchers *ofctrl.Matchers, tableID binding.TableIDType, disposition uint32) *ofctrl.MatchField { // Get match from CNPDenyConjIDReg if disposition is not allow. if disposition != openflow.DispositionAllow { - return getMatchRegField(matchers, uint32(openflow.CNPDenyConjIDReg)) + 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 { - return getMatchRegField(matchers, uint32(openflow.EgressReg)) + return getMatchRegField(matchers, openflow.TFEgressConjIDField) } } for _, table := range append(openflow.GetAntreaPolicyIngressTables(), openflow.IngressRuleTable) { if tableID == table { - return getMatchRegField(matchers, uint32(openflow.IngressReg)) + return getMatchRegField(matchers, openflow.TFIngressConjIDField) } } return nil @@ -199,8 +202,8 @@ func getNetworkPolicyInfo(pktIn *ofctrl.PacketIn, c *Controller, ob *logInfo) er ob.tableName = openflow.GetFlowTableName(tableID) // Get disposition Allow or Drop - match = getMatchRegField(matchers, uint32(openflow.DispositionMarkReg)) - info, err := getInfoInReg(match, openflow.APDispositionMarkRange.ToNXRange()) + match = getMatchRegField(matchers, openflow.APDispositionField) + info, err := getInfoInReg(match, openflow.APDispositionField.GetRange().ToNXRange()) if err != nil { return fmt.Errorf("received error while unloading disposition from reg: %v", err) } @@ -372,8 +375,8 @@ func (c *Controller) storeDenyConnection(pktIn *ofctrl.PacketIn) error { // Get table ID tableID := binding.TableIDType(pktIn.TableId) // Get disposition Allow, Drop or Reject - match = getMatchRegField(matchers, uint32(openflow.DispositionMarkReg)) - id, err := getInfoInReg(match, openflow.APDispositionMarkRange.ToNXRange()) + match = getMatchRegField(matchers, openflow.APDispositionField) + id, err := getInfoInReg(match, openflow.APDispositionField.GetRange().ToNXRange()) if err != nil { return fmt.Errorf("error when getting disposition from reg: %v", err) } diff --git a/pkg/agent/controller/traceflow/packetin.go b/pkg/agent/controller/traceflow/packetin.go index 474baecde6f..03b0964ded2 100644 --- a/pkg/agent/controller/traceflow/packetin.go +++ b/pkg/agent/controller/traceflow/packetin.go @@ -176,7 +176,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl obs = append(obs, *ob) } // Collect egress conjunctionID and get NetworkPolicy from cache. - if match := getMatchRegField(matchers, uint32(openflow.EgressReg)); match != nil { + if match := getMatchRegField(matchers, openflow.TFEgressConjIDField); match != nil { egressInfo, err := getRegValue(match, nil) if err != nil { return nil, nil, nil, err @@ -191,7 +191,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } // Collect ingress conjunctionID and get NetworkPolicy from cache. - if match := getMatchRegField(matchers, uint32(openflow.IngressReg)); match != nil { + if match := getMatchRegField(matchers, openflow.TFIngressConjIDField); match != nil { ingressInfo, err := getRegValue(match, nil) if err != nil { return nil, nil, nil, err @@ -207,7 +207,7 @@ 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 match := getMatchRegField(matchers, uint32(openflow.CNPDenyConjIDReg)); match != nil { + if match := getMatchRegField(matchers, openflow.CNPDenyConjIDField); match != nil { notAllowConjInfo, err := getRegValue(match, nil) if err != nil { return nil, nil, nil, err @@ -239,7 +239,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } } var outputPort uint32 - if match := getMatchRegField(matchers, uint32(openflow.PortCacheReg)); match != nil { + if match := getMatchRegField(matchers, openflow.TargetOFPortField); match != nil { outputPort, err = getRegValue(match, nil) if err != nil { return nil, nil, nil, err @@ -271,8 +271,8 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl return tf, &nodeResult, capturedPacket, nil } -func getMatchRegField(matchers *ofctrl.Matchers, regNum uint32) *ofctrl.MatchField { - return matchers.GetMatchByName(fmt.Sprintf("NXM_NX_REG%d", regNum)) +func getMatchRegField(matchers *ofctrl.Matchers, field *binding.RegField) *ofctrl.MatchField { + return matchers.GetMatchByName(field.GetNXFieldName()) } func getMatchTunnelDstField(matchers *ofctrl.Matchers, isIPv6 bool) *ofctrl.MatchField { diff --git a/pkg/agent/flowexporter/connections/conntrack_connections.go b/pkg/agent/flowexporter/connections/conntrack_connections.go index 9a6b2a61d11..227d086518e 100644 --- a/pkg/agent/flowexporter/connections/conntrack_connections.go +++ b/pkg/agent/flowexporter/connections/conntrack_connections.go @@ -214,7 +214,7 @@ func (cs *ConntrackConnectionStore) AddOrUpdateConn(conn *flowexporter.Connectio klog.V(4).Infof("Antrea flow updated: %v", existingConn) } else { cs.fillPodInfo(conn) - if conn.Mark == openflow.ServiceCTMark { + if conn.Mark == openflow.ServiceCTMark.GetValue() { clusterIP := conn.DestinationServiceAddress.String() svcPort := conn.DestinationServicePort protocol, err := lookupServiceProtocol(conn.FlowKey.Protocol) diff --git a/pkg/agent/flowexporter/connections/conntrack_connections_test.go b/pkg/agent/flowexporter/connections/conntrack_connections_test.go index d33998d82d8..051ddd25338 100644 --- a/pkg/agent/flowexporter/connections/conntrack_connections_test.go +++ b/pkg/agent/flowexporter/connections/conntrack_connections_test.go @@ -140,7 +140,7 @@ func TestConntrackConnectionStore_AddOrUpdateConn(t *testing.T) { StartTime: refTime.Add(-(time.Second * 50)), StopTime: refTime, FlowKey: tuple4, - Mark: openflow.ServiceCTMark, + Mark: openflow.ServiceCTMark.GetValue(), IsPresent: true, } // Create copy of old conntrack flow for testing purposes. diff --git a/pkg/agent/flowexporter/exporter/exporter.go b/pkg/agent/flowexporter/exporter/exporter.go index dd364c1f337..6d363f72121 100644 --- a/pkg/agent/flowexporter/exporter/exporter.go +++ b/pkg/agent/flowexporter/exporter/exporter.go @@ -710,7 +710,7 @@ func (exp *flowExporter) findFlowType(conn flowexporter.Connection) uint8 { return 0 } if exp.nodeRouteController.IPInPodSubnets(conn.FlowKey.SourceAddress) { - if conn.Mark == openflow.ServiceCTMark || exp.nodeRouteController.IPInPodSubnets(conn.FlowKey.DestinationAddress) { + if conn.Mark == openflow.ServiceCTMark.GetValue() || exp.nodeRouteController.IPInPodSubnets(conn.FlowKey.DestinationAddress) { if conn.SourcePodName == "" || conn.DestinationPodName == "" { return ipfixregistry.FlowTypeInterNode } diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go index 7e7970a176d..6994b42eff3 100644 --- a/pkg/agent/openflow/client.go +++ b/pkg/agent/openflow/client.go @@ -1021,8 +1021,7 @@ func (c *client) SendTCPPacketOut( // Reject response packet should bypass ConnTrack if isReject { - name := fmt.Sprintf("%s%d", binding.NxmFieldReg, marksReg) - packetOutBuilder = packetOutBuilder.AddLoadAction(name, uint64(CustomReasonReject), CustomReasonMarkRange) + packetOutBuilder = packetOutBuilder.AddLoadRegMark(MarkCustomReasonReject) } packetOutObj := packetOutBuilder.Done() @@ -1060,8 +1059,7 @@ func (c *client) SendICMPPacketOut( // Reject response packet should bypass ConnTrack if isReject { - name := fmt.Sprintf("%s%d", binding.NxmFieldReg, marksReg) - packetOutBuilder = packetOutBuilder.AddLoadAction(name, uint64(CustomReasonReject), CustomReasonMarkRange) + packetOutBuilder = packetOutBuilder.AddLoadRegMark(MarkCustomReasonReject) } packetOutObj := packetOutBuilder.Done() diff --git a/pkg/agent/openflow/network_policy_test.go b/pkg/agent/openflow/network_policy_test.go index 468f75c3ffe..9ee750349b0 100644 --- a/pkg/agent/openflow/network_policy_test.go +++ b/pkg/agent/openflow/network_policy_test.go @@ -676,7 +676,7 @@ func newMockRuleFlowBuilder(ctrl *gomock.Controller) *mocks.MockFlowBuilder { ruleCtAction.EXPECT().CTDone().Return(ruleFlowBuilder).AnyTimes() ruleAction.EXPECT().CT(true, gomock.Any(), gomock.Any()).Return(ruleCtAction).AnyTimes() ruleAction.EXPECT().GotoTable(gomock.Any()).Return(ruleFlowBuilder).AnyTimes() - ruleAction.EXPECT().LoadRegRange(gomock.Any(), gomock.Any(), gomock.Any()).Return(ruleFlowBuilder).AnyTimes() + ruleAction.EXPECT().LoadToRegField(gomock.Any(), gomock.Any()).Return(ruleFlowBuilder).AnyTimes() ruleFlowBuilder.EXPECT().Action().Return(ruleAction).AnyTimes() ruleFlow = mocks.NewMockFlow(ctrl) ruleFlowBuilder.EXPECT().Done().Return(ruleFlow).AnyTimes() @@ -696,7 +696,7 @@ func newMockMetricFlowBuilder(ctrl *gomock.Controller) *mocks.MockFlowBuilder { metricFlowBuilder.EXPECT().MatchCTLabelRange(gomock.Any(), gomock.Any(), gomock.Any()).Return(metricFlowBuilder).AnyTimes() metricAction = mocks.NewMockAction(ctrl) metricAction.EXPECT().GotoTable(gomock.Any()).Return(metricFlowBuilder).AnyTimes() - metricAction.EXPECT().LoadRegRange(gomock.Any(), gomock.Any(), gomock.Any()).Return(metricFlowBuilder).AnyTimes() + metricAction.EXPECT().LoadToRegField(gomock.Any(), gomock.Any()).Return(metricFlowBuilder).AnyTimes() metricAction.EXPECT().Drop().Return(metricFlowBuilder).AnyTimes() metricFlowBuilder.EXPECT().Action().Return(metricAction).AnyTimes() metricFlow = mocks.NewMockFlow(ctrl) diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go index a29113d2a51..c9b19143865 100644 --- a/pkg/agent/openflow/pipeline.go +++ b/pkg/agent/openflow/pipeline.go @@ -81,12 +81,6 @@ const ( // Index for priority cache priorityIndex = "priority" - // Traffic marks - markTrafficFromTunnel = 0 - markTrafficFromGateway = 1 - markTrafficFromLocal = 2 - markTrafficFromUplink = 4 - // IPv6 multicast prefix ipv6MulticastAddr = "FF00::/8" // IPv6 link-local prefix @@ -223,60 +217,14 @@ func (rt regType) reg() string { } const ( - // marksReg stores traffic-source mark and pod-found mark. - // traffic-source resides in [0..15], pod-found resides in [16], Antrea Policy disposition in [21-22], Custom Reasons in [24-26] - marksReg regType = 0 - PortCacheReg regType = 1 - swapReg regType = 2 - endpointIPReg regType = 3 // Use reg3 to store endpoint IP - endpointPortReg regType = 4 // Use reg4[0..15] to store endpoint port - serviceLearnReg = endpointPortReg // Use reg4[16..18] to store endpoint selection states. - EgressReg regType = 5 - IngressReg regType = 6 - TraceflowReg regType = 9 // Use reg9[28..31] to store traceflow dataplaneTag. - // CNPDenyConjIDReg reuses reg3 which will also be used for storing endpoint IP to store the rule ID. Since - // the service selection will finish when a packet hitting NetworkPolicy related rules, there is no conflict. - CNPDenyConjIDReg regType = 3 - endpointIPv6XXReg regType = 3 // xxReg3 will occupy reg12-reg15 - // marksRegServiceNeedLB indicates a packet need to do service selection. - marksRegServiceNeedLB uint32 = 0b001 - // marksRegServiceSelected indicates a packet has done service selection. - marksRegServiceSelected uint32 = 0b010 - // marksRegServiceNeedLearn indicates a packet has done service selection and - // the selection result needs to be cached. - marksRegServiceNeedLearn uint32 = 0b011 - CtZone = 0xfff0 CtZoneV6 = 0xffe6 - portFoundMark = 0b1 - hairpinMark = 0b1 - // macRewriteMark indicates the destination and source MACs of the - // packet should be rewritten in the l3ForwardingTable. - macRewriteMark = 0b1 - // cnpDenyMark indicates the packet is denied(Drop/Reject). - cnpDenyMark = 0b1 - - // gatewayCTMark is used to to mark connections initiated through the host gateway interface - // (i.e. for which the first packet of the connection was received through the gateway). - gatewayCTMark = 0x20 - ServiceCTMark = 0x21 - - // disposition is loaded in marksReg [21-22] - DispositionMarkReg regType = 0 - // disposition marks the flow action + // disposition values used in AP DispositionAllow = 0b00 DispositionDrop = 0b01 DispositionRej = 0b10 - // custom reason is loaded in marksReg [24-26] - // The custom reason mark is used to indicate the reason(s) for sending the packet - // to the controller. Reasons can be or-ed to indicate that the packets was sent - // for multiple reasons. - // For example, a value of 0b11 (CustomReasonLogging | CustomReasonReject) means - // that the packet is sent to the controller both for NetworkPolicy logging and - // because of a Reject action. - CustomReasonMarkReg regType = 0 // CustomReasonLogging is used when send packet-in to controller indicating this // packet need logging. CustomReasonLogging = 0b01 @@ -299,43 +247,6 @@ var DispositionToString = map[uint32]string{ } var ( - // ofPortMarkRange takes the 16th bit of register marksReg to indicate if the ofPort - // number of an interface. - // is found or not. Its value is 0x1 if yes. - ofPortMarkRange = binding.Range{16, 16} - // ofPortRegRange takes a 32-bit range of register PortCacheReg to cache the ofPort - // number of the interface. - ofPortRegRange = binding.Range{0, 31} - // hairpinMarkRange takes the 18th bit of register marksReg to indicate - // if the packet needs DNAT to virtual IP or not. Its value is 0x1 if yes. - hairpinMarkRange = binding.Range{18, 18} - // macRewriteMarkRange takes the 19th bit of register marksReg to indicate - // if the packet's MAC addresses need to be rewritten. Its value is 0x1 if yes. - macRewriteMarkRange = binding.Range{19, 19} - // cnpDenyMarkRange takes the 20th bit of register marksReg to indicate - // if the packet is denied(Drop/Reject). Its value is 0x1 if yes. - cnpDenyMarkRange = binding.Range{20, 20} - // APDispositionMarkRange takes the 21 to 22 bits of register marksReg to indicate - // disposition of Antrea Policy. It could have more bits to support more disposition - // that Antrea policy support in the future. - APDispositionMarkRange = binding.Range{21, 22} - // CustomReasonMarkRange takes the 24 to 26 bits of register marksReg to indicate - // the reason of sending packet to the controller. It could have more bits to - // support more customReason in the future. - CustomReasonMarkRange = binding.Range{24, 26} - // endpointIPRegRange takes a 32-bit range of register endpointIPReg to store - // the selected Service Endpoint IP. - endpointIPRegRange = binding.Range{0, 31} - // the selected Service Endpoint IPv6. - endpointIPv6XXRegRange = binding.Range{0, 127} - // endpointPortRegRange takes a 16-bit range of register endpointPortReg to store - // the selected Service Endpoint port. - endpointPortRegRange = binding.Range{0, 15} - // serviceLearnRegRange takes a 3-bit range of register serviceLearnReg to - // indicate if the packet accessing a Service has already selected the Service - // Endpoint, still needs to select an Endpoint, or if an Endpoint has already - // been selected and the selection decision needs to be learned. - serviceLearnRegRange = binding.Range{16, 18} // metricIngressRuleIDRange takes 0..31 range of ct_label to store the ingress rule ID. metricIngressRuleIDRange = binding.Range{0, 31} // metricEgressRuleIDRange takes 32..63 range of ct_label to store the egress rule ID. @@ -347,7 +258,7 @@ var ( // snatPktMarkRange takes an 8-bit range of pkt_mark to store the ID of // a SNAT IP. The bit range must match SNATIPMarkMask. - snatPktMarkRange = binding.Range{0, 7} + snatPktMarkRange = &binding.Range{0, 7} globalVirtualMAC, _ = net.ParseMAC("aa:bb:cc:dd:ee:ff") hairpinIP = net.ParseIP("169.254.169.252").To4() @@ -548,8 +459,8 @@ func (c *client) defaultFlows() (flows []binding.Flow) { func (c *client) tunnelClassifierFlow(tunnelOFPort uint32, category cookie.Category) binding.Flow { return c.pipeline[ClassifierTable].BuildFlow(priorityNormal). MatchInPort(tunnelOFPort). - Action().LoadRegRange(int(marksReg), markTrafficFromTunnel, binding.Range{0, 15}). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + Action().LoadRegMark(FromTunnelMark). + Action().LoadRegMark(RewriteMACMark). Action().GotoTable(conntrackTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done() @@ -560,7 +471,7 @@ func (c *client) gatewayClassifierFlow(category cookie.Category) binding.Flow { classifierTable := c.pipeline[ClassifierTable] return classifierTable.BuildFlow(priorityNormal). MatchInPort(config.HostGatewayOFPort). - Action().LoadRegRange(int(marksReg), markTrafficFromGateway, binding.Range{0, 15}). + Action().LoadRegMark(FromGatewayMark). Action().GotoTable(classifierTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() @@ -571,7 +482,7 @@ func (c *client) podClassifierFlow(podOFPort uint32, category cookie.Category) b classifierTable := c.pipeline[ClassifierTable] return classifierTable.BuildFlow(priorityLow). MatchInPort(podOFPort). - Action().LoadRegRange(int(marksReg), markTrafficFromLocal, binding.Range{0, 15}). + Action().LoadRegMark(FromLocalMark). Action().GotoTable(classifierTable.GetNext()). Cookie(c.cookieAllocator.Request(category).Raw()). Done() @@ -611,15 +522,15 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { Done(), connectionTrackCommitTable.BuildFlow(priorityLow).MatchProtocol(binding.ProtocolIP). MatchCTStateTrk(true). - MatchCTMark(ServiceCTMark, nil). - MatchRegRange(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). + MatchCTMarkData(ServiceCTMark). + MatchRegMark(EpSelectedMark). Cookie(c.cookieAllocator.Request(category).Raw()). Action().GotoTable(connectionTrackCommitTable.GetNext()). Done(), connectionTrackCommitTable.BuildFlow(priorityLow).MatchProtocol(binding.ProtocolIPv6). MatchCTStateTrk(true). - MatchCTMark(ServiceCTMark, nil). - MatchRegRange(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). + MatchCTMarkData(ServiceCTMark). + MatchRegMark(EpSelectedMark). Cookie(c.cookieAllocator.Request(category).Raw()). Action().GotoTable(connectionTrackCommitTable.GetNext()). Done(), @@ -638,9 +549,9 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { flows = append(flows, // Connections initiated through the gateway are marked with gatewayCTMark. connectionTrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(proto). - MatchRegRange(int(marksReg), markTrafficFromGateway, binding.Range{0, 15}). + MatchRegMark(FromGatewayMark). MatchCTStateNew(true).MatchCTStateTrk(true). - Action().CT(true, connectionTrackCommitTable.GetNext(), ctZone).LoadToMark(gatewayCTMark).CTDone(). + Action().CT(true, connectionTrackCommitTable.GetNext(), ctZone).LoadToCtMark(gatewayCTMark).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), // Add reject response packet bypass flow. @@ -656,7 +567,7 @@ func (c *client) conntrackBypassRejectFlow(proto binding.Protocol) binding.Flow connectionTrackStateTable := c.pipeline[conntrackStateTable] return connectionTrackStateTable.BuildFlow(priorityHigh). MatchProtocol(proto). - MatchRegRange(int(marksReg), CustomReasonReject, CustomReasonMarkRange). + MatchRegMark(MarkCustomReasonReject). Cookie(c.cookieAllocator.Request(cookie.Default).Raw()). Action().ResubmitToTable(connectionTrackStateTable.GetNext()). Done() @@ -770,8 +681,8 @@ func (c *client) traceflowConnectionTrackFlows(dataplaneTag uint8, receiverOnly nextTable := c.ingressEntryTable flowBuilder = l2FwdCalcTable.BuildFlow(priorityHigh). MatchDstMAC(packet.DestinationMAC). - Action().LoadRegRange(int(PortCacheReg), ofPort, ofPortRegRange). - Action().LoadRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + Action().LoadToRegField(TargetOFPortField, ofPort). + Action().LoadRegMark(OFPortFoundMark). Action().LoadIPDSCP(dataplaneTag). Action().GotoTable(nextTable) if packet.SourceIP != nil { @@ -891,9 +802,9 @@ func (c *client) serviceLBBypassFlows(ipProtocol binding.Protocol) []binding.Flo // Tracked connections with the ServiceCTMark (load-balanced by AntreaProxy) receive // the macRewriteMark and are sent to egressRuleTable. connectionTrackStateTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). - MatchCTMark(ServiceCTMark, nil). + MatchCTMarkData(ServiceCTMark). MatchCTStateNew(false).MatchCTStateTrk(true). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + Action().LoadRegMark(RewriteMACMark). Action().GotoTable(EgressRuleTable). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done(), @@ -918,9 +829,9 @@ func (c *client) serviceLBBypassFlows(ipProtocol binding.Protocol) []binding.Flo flows = append(flows, c.pipeline[conntrackStateTable].BuildFlow(priorityHigh). MatchProtocol(ipProtocol). MatchCTStateNew(false).MatchCTStateTrk(true). - MatchCTMark(ServiceCTMark, nil). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + MatchCTMarkData(ServiceCTMark). + MatchRegMark(FromUplinkMark). + Action().LoadRegMark(RewriteMACMark). Action().GotoTable(EgressRuleTable). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done()) @@ -938,8 +849,8 @@ func (c *client) l2ForwardCalcFlow(dstMAC net.HardwareAddr, ofPort uint32, skipI } return l2FwdCalcTable.BuildFlow(priorityNormal). MatchDstMAC(dstMAC). - Action().LoadRegRange(int(PortCacheReg), ofPort, ofPortRegRange). - Action().LoadRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + Action().LoadToRegField(TargetOFPortField, ofPort). + Action().LoadRegMark(OFPortFoundMark). Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done() @@ -956,23 +867,23 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, if c.encapMode.SupportsEncap() { // SendToController and Output if output port is tunnel port. fb1 := l2FwdOutTable.BuildFlow(priorityNormal+3). - MatchReg(int(PortCacheReg), config.DefaultTunOFPort). + MatchRegFieldWithValue(TargetOFPortField, config.DefaultTunOFPort). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange). + MatchRegMark(OFPortFoundMark). + Action().OutputToRegField(TargetOFPortField). Cookie(c.cookieAllocator.Request(category).Raw()) // For injected packets, only SendToController if output port is local // 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). - MatchReg(int(PortCacheReg), config.HostGatewayOFPort). + MatchRegFieldWithValue(TargetOFPortField, config.HostGatewayOFPort). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + MatchRegMark(OFPortFoundMark). Cookie(c.cookieAllocator.Request(category).Raw()) // Do not send to controller if captures only dropped packet. @@ -987,7 +898,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, if liveTraffic { // Clear the loaded DSCP bits before output. fb2 = fb2.Action().LoadIPDSCP(0). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange) + Action().OutputToRegField(TargetOFPortField) } flows = append(flows, fb1.Done(), fb2.Done()) } else { @@ -995,12 +906,12 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, // 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). - MatchReg(int(PortCacheReg), config.HostGatewayOFPort). + MatchRegFieldWithValue(TargetOFPortField, config.HostGatewayOFPort). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange). + MatchRegMark(OFPortFoundMark). + Action().OutputToRegField(TargetOFPortField). Cookie(c.cookieAllocator.Request(category).Raw()) if !droppedOnly { if c.ovsMetersAreSupported { @@ -1017,12 +928,12 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, } if gatewayIP != nil { fb := l2FwdOutTable.BuildFlow(priorityNormal+3). - MatchReg(int(PortCacheReg), config.HostGatewayOFPort). + MatchRegFieldWithValue(TargetOFPortField, config.HostGatewayOFPort). MatchDstIP(gatewayIP). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + MatchRegMark(OFPortFoundMark). Cookie(c.cookieAllocator.Request(category).Raw()) if !droppedOnly { if c.ovsMetersAreSupported { @@ -1032,16 +943,16 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, } if liveTraffic { fb = fb.Action().LoadIPDSCP(0). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange) + Action().OutputToRegField(TargetOFPortField) } flows = append(flows, fb.Done()) } // Only SendToController if output port is Pod port. - fb := l2FwdOutTable.BuildFlow(priorityNormal+2). + fb := l2FwdOutTable.BuildFlow(priorityNormal + 2). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + MatchRegMark(OFPortFoundMark). Cookie(c.cookieAllocator.Request(category).Raw()) if !droppedOnly { if c.ovsMetersAreSupported { @@ -1051,17 +962,17 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, } if liveTraffic { fb = fb.Action().LoadIPDSCP(0). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange) + Action().OutputToRegField(TargetOFPortField) } flows = append(flows, fb.Done()) 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 := l2FwdOutTable.BuildFlow(priorityHigh + 2). MatchIPDSCP(dataplaneTag). SetHardTimeout(timeout). MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), hairpinMark, hairpinMarkRange). + MatchRegMark(markHairpin). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()) if !droppedOnly { if c.ovsMetersAreSupported { @@ -1083,7 +994,7 @@ func (c *client) traceflowL2ForwardOutputFlows(dataplaneTag uint8, liveTraffic, // hairpin packets to avoid packets from being dropped by OVS. func (c *client) l2ForwardOutputServiceHairpinFlow() binding.Flow { return c.pipeline[L2ForwardingOutTable].BuildFlow(priorityHigh). - MatchRegRange(int(marksReg), hairpinMark, hairpinMarkRange). + MatchRegMark(markHairpin). Action().OutputInPort(). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() @@ -1094,13 +1005,13 @@ func (c *client) l2ForwardOutputFlows(category cookie.Category) []binding.Flow { var flows []binding.Flow flows = append(flows, c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange). + MatchRegMark(OFPortFoundMark). + Action().OutputToRegField(TargetOFPortField). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). - Action().OutputRegRange(int(PortCacheReg), ofPortRegRange). + MatchRegMark(OFPortFoundMark). + Action().OutputToRegField(TargetOFPortField). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), ) @@ -1117,7 +1028,7 @@ func (c *client) l3FwdFlowToPod(localGatewayMAC net.HardwareAddr, podInterfaceIP for _, ip := range podInterfaceIPs { ipProtocol := getIPProtocol(ip) flows = append(flows, l3FwdTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + MatchRegMark(RewriteMACMark). MatchDstIP(ip). Action().SetSrcMAC(localGatewayMAC). // Rewrite src MAC to local gateway MAC, and rewrite dst MAC to pod MAC @@ -1174,7 +1085,7 @@ func (c *client) l3FwdFlowToGateway(localGatewayIPs []net.IP, localGatewayMAC ne for _, ip := range localGatewayIPs { ipProtocol := getIPProtocol(ip) flows = append(flows, l3FwdTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). - MatchRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + MatchRegMark(RewriteMACMark). MatchDstIP(ip). Action().SetDstMAC(localGatewayMAC). Action().GotoTable(l3FwdTable.GetNext()). @@ -1195,7 +1106,7 @@ func (c *client) l3FwdFlowToGateway(localGatewayIPs []net.IP, localGatewayMAC ne // 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). - MatchCTMark(gatewayCTMark, nil). + MatchCTMarkData(gatewayCTMark). MatchCTStateRpl(true).MatchCTStateTrk(true). Action().SetDstMAC(localGatewayMAC). Action().GotoTable(l3FwdTable.GetNext()). @@ -1270,9 +1181,9 @@ func (c *client) arpResponderStaticFlow(category cookie.Category) binding.Flow { Action().LoadARPOperation(2). Action().Move(binding.NxmFieldARPSha, binding.NxmFieldARPTha). Action().SetARPSha(globalVirtualMAC). - Action().Move(binding.NxmFieldARPTpa, swapReg.nxm()). + Action().Move(binding.NxmFieldARPTpa, SwapField.GetNXFieldName()). Action().Move(binding.NxmFieldARPSpa, binding.NxmFieldARPTpa). - Action().Move(swapReg.nxm(), binding.NxmFieldARPSpa). + Action().Move(SwapField.GetNXFieldName(), binding.NxmFieldARPSpa). Action().OutputInPort(). Cookie(c.cookieAllocator.Request(category).Raw()). Done() @@ -1332,7 +1243,7 @@ func (c *client) serviceHairpinResponseDNATFlow(ipProtocol binding.Protocol) bin return c.pipeline[serviceHairpinTable].BuildFlow(priorityNormal).MatchProtocol(ipProtocol). MatchDstIP(hpIP). Action().Move(from, to). - Action().LoadRegRange(int(marksReg), hairpinMark, hairpinMarkRange). + Action().LoadRegMark(markHairpin). Action().GotoTable(conntrackTable). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() @@ -1366,8 +1277,8 @@ func (c *client) arpSpoofGuardFlow(ifIP net.IP, ifMAC net.HardwareAddr, ifOFPort // selection of the Service. func (c *client) sessionAffinityReselectFlow() binding.Flow { return c.pipeline[endpointDNATTable].BuildFlow(priorityLow). - MatchRegRange(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). - Action().LoadRegRange(int(serviceLearnReg), marksRegServiceNeedLB, serviceLearnRegRange). + MatchRegMark(EpSelectedMark). + Action().LoadRegMark(EpToSelectMark). Action().ResubmitToTable(serviceLBTable). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() @@ -1402,8 +1313,8 @@ func (c *client) serviceCIDRDNATFlows(serviceCIDRs []*net.IPNet) []binding.Flow ipProto := getIPProtocol(serviceCIDR.IP) flows = append(flows, c.pipeline[dnatTable].BuildFlow(priorityNormal).MatchProtocol(ipProto). MatchDstIPNet(*serviceCIDR). - Action().LoadRegRange(int(PortCacheReg), config.HostGatewayOFPort, ofPortRegRange). - Action().LoadRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + Action().LoadToRegField(TargetOFPortField, config.HostGatewayOFPort). + Action().LoadRegMark(OFPortFoundMark). Action().GotoTable(conntrackCommitTable). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done()) @@ -1416,7 +1327,7 @@ func (c *client) serviceCIDRDNATFlows(serviceCIDRs []*net.IPNet) []binding.Flow func (c *client) serviceNeedLBFlow() binding.Flow { return c.pipeline[sessionAffinityTable].BuildFlow(priorityMiss). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). - Action().LoadRegRange(int(serviceLearnReg), marksRegServiceNeedLB, serviceLearnRegRange). + Action().LoadRegMark(EpToSelectMark). Done() } @@ -1465,8 +1376,8 @@ func (c *client) denyRuleMetricFlow(conjunctionID uint32, ingress bool) binding. metricTableID = EgressMetricTable } return c.pipeline[metricTableID].BuildFlow(priorityNormal). - MatchRegRange(int(marksReg), cnpDenyMark, cnpDenyMarkRange). - MatchReg(int(CNPDenyConjIDReg), conjunctionID). + MatchRegMark(CnpDenyMark). + MatchRegFieldWithValue(CNPDenyConjIDField, conjunctionID). Action().Drop(). Cookie(c.cookieAllocator.Request(cookie.Policy).Raw()). Done() @@ -1520,10 +1431,10 @@ func (c *client) conjunctionActionFlow(conjunctionID uint32, tableID binding.Tab } else { ofPriority = *priority } - conjReg := IngressReg + conjReg := TFIngressConjIDField labelRange := metricIngressRuleIDRange if _, ok := egressTables[tableID]; ok { - conjReg = EgressReg + conjReg = TFEgressConjIDField labelRange = metricEgressRuleIDRange } conjActionFlow := func(proto binding.Protocol) binding.Flow { @@ -1538,9 +1449,9 @@ func (c *client) conjunctionActionFlow(conjunctionID uint32, tableID binding.Tab fb = fb.Action().Meter(PacketInMeterIDNP) } return fb. - Action().LoadRegRange(int(conjReg), conjunctionID, binding.Range{0, 31}). // Traceflow. - Action().LoadRegRange(int(marksReg), DispositionAllow, APDispositionMarkRange). // AntreaPolicy. - Action().LoadRegRange(int(marksReg), CustomReasonLogging, CustomReasonMarkRange). // Enable logging. + Action().LoadToRegField(conjReg, conjunctionID). // Traceflow. + Action().LoadRegMark(DispositionAllowMark). // AntreaPolicy. + Action().LoadRegMark(MarkCustomReasonLogging). // Enable logging. Action().SendToController(uint8(PacketInReasonNP)). Action().CT(true, nextTable, ctZone). // CT action requires commit flag if actions other than NAT without arguments are specified. LoadToLabelRange(uint64(conjunctionID), &labelRange). @@ -1550,8 +1461,8 @@ func (c *client) conjunctionActionFlow(conjunctionID uint32, tableID binding.Tab } else { return c.pipeline[tableID].BuildFlow(ofPriority).MatchProtocol(proto). MatchConjID(conjunctionID). - Action().LoadRegRange(int(conjReg), conjunctionID, binding.Range{0, 31}). // Traceflow. - Action().CT(true, nextTable, ctZone). // CT action requires commit flag if actions other than NAT without arguments are specified. + Action().LoadToRegField(conjReg, conjunctionID). // Traceflow. + Action().CT(true, nextTable, ctZone). // CT action requires commit flag if actions other than NAT without arguments are specified. LoadToLabelRange(uint64(conjunctionID), &labelRange). CTDone(). Cookie(c.cookieAllocator.Request(cookie.Policy).Raw()). @@ -1577,19 +1488,19 @@ func (c *client) conjunctionActionDenyFlow(conjunctionID uint32, tableID binding flowBuilder := c.pipeline[tableID].BuildFlow(ofPriority). MatchConjID(conjunctionID). - Action().LoadRegRange(int(CNPDenyConjIDReg), conjunctionID, binding.Range{0, 31}). - Action().LoadRegRange(int(marksReg), cnpDenyMark, cnpDenyMarkRange) + Action().LoadToRegField(CNPDenyConjIDField, conjunctionID). + Action().LoadRegMark(CnpDenyMark) var customReason int if c.enableDenyTracking { customReason += CustomReasonDeny flowBuilder = flowBuilder. - Action().LoadRegRange(int(marksReg), disposition, APDispositionMarkRange) + Action().LoadToRegField(APDispositionField, disposition) } if enableLogging { customReason += CustomReasonLogging flowBuilder = flowBuilder. - Action().LoadRegRange(int(marksReg), disposition, APDispositionMarkRange) + Action().LoadToRegField(APDispositionField, disposition) } if disposition == DispositionRej { customReason += CustomReasonReject @@ -1600,7 +1511,7 @@ func (c *client) conjunctionActionDenyFlow(conjunctionID uint32, tableID binding flowBuilder = flowBuilder.Action().Meter(PacketInMeterIDNP) } flowBuilder = flowBuilder. - Action().LoadRegRange(int(marksReg), uint32(customReason), CustomReasonMarkRange). + Action().LoadToRegField(CustomReasonField, uint32(customReason)). Action().SendToController(uint8(PacketInReasonNP)) } @@ -1676,7 +1587,7 @@ func (c *client) addFlowMatch(fb binding.FlowBuilder, matchKey *types.MatchKey, switch matchKey { case MatchDstOFPort: // ofport number in NXM_NX_REG1 is used in ingress rule to match packets sent to local Pod. - fb = fb.MatchReg(int(PortCacheReg), uint32(matchValue.(int32))) + fb = fb.MatchRegFieldWithValue(TargetOFPortField, uint32(matchValue.(int32))) case MatchSrcOFPort: fb = fb.MatchInPort(uint32(matchValue.(int32))) case MatchDstIP: @@ -1718,13 +1629,13 @@ func (c *client) addFlowMatch(fb binding.FlowBuilder, matchKey *types.MatchKey, // conjunctionExceptionFlow generates the flow to jump to a specific table if both policyRuleConjunction ID and except address are matched. // Keeping this for reference to generic exception flow. func (c *client) conjunctionExceptionFlow(conjunctionID uint32, tableID binding.TableIDType, nextTable binding.TableIDType, matchKey *types.MatchKey, matchValue interface{}) binding.Flow { - conjReg := IngressReg + conjReg := TFIngressConjIDField if tableID == EgressRuleTable { - conjReg = EgressReg + conjReg = TFEgressConjIDField } fb := c.pipeline[tableID].BuildFlow(priorityNormal).MatchConjID(conjunctionID) return c.addFlowMatch(fb, matchKey, matchValue). - Action().LoadRegRange(int(conjReg), conjunctionID, binding.Range{0, 31}). // Traceflow. + Action().LoadToRegField(conjReg, conjunctionID). // Traceflow. Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(cookie.Policy).Raw()). Done() @@ -1752,8 +1663,8 @@ func (c *client) defaultDropFlow(tableID binding.TableIDType, matchKey *types.Ma if c.enableDenyTracking { return c.addFlowMatch(fb, matchKey, matchValue). Action().Drop(). - Action().LoadRegRange(int(marksReg), DispositionDrop, APDispositionMarkRange). - Action().LoadRegRange(int(marksReg), CustomReasonDeny, CustomReasonMarkRange). + Action().LoadRegMark(DispositionDropMark). + Action().LoadRegMark(MarkCustomReasonDeny). Action().SendToController(uint8(PacketInReasonNP)). Cookie(c.cookieAllocator.Request(cookie.Default).Raw()). Done() @@ -1809,7 +1720,7 @@ func (c *client) snatCommonFlows(nodeIP net.IP, localSubnet net.IPNet, localGate // traffic to the local Pod subnet will be handled by L3 forwarding rules. l3FwdTable.BuildFlow(priorityNormal). MatchProtocol(ipProto). - MatchRegRange(int(marksReg), 0, macRewriteMarkRange). + MatchRegFieldWithValue(RewriteMACMark.GetField(), 0). MatchDstIPNet(localSubnet). Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(category).Raw()). @@ -1817,7 +1728,7 @@ func (c *client) snatCommonFlows(nodeIP net.IP, localSubnet net.IPNet, localGate // This flow is for the traffic to the local Node IP. l3FwdTable.BuildFlow(priorityNormal). MatchProtocol(ipProto). - MatchRegRange(int(marksReg), markTrafficFromLocal, binding.Range{0, 15}). + MatchRegMark(FromLocalMark). MatchDstIP(nodeIP). Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(category).Raw()). @@ -1829,7 +1740,7 @@ func (c *client) snatCommonFlows(nodeIP net.IP, localSubnet net.IPNet, localGate // Send the traffic to external to snatTable. l3FwdTable.BuildFlow(priorityLow). MatchProtocol(ipProto). - MatchRegRange(int(marksReg), markTrafficFromLocal, binding.Range{0, 15}). + MatchRegMark(FromLocalMark). Action().GotoTable(snatTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -1837,7 +1748,7 @@ func (c *client) snatCommonFlows(nodeIP net.IP, localSubnet net.IPNet, localGate // destination MAC to the gateway interface MAC. l3FwdTable.BuildFlow(priorityLow). MatchProtocol(ipProto). - MatchRegRange(int(marksReg), markTrafficFromTunnel, binding.Range{0, 15}). + MatchRegMark(FromTunnelMark). Action().SetDstMAC(localGatewayMAC). Action().GotoTable(snatTable). Cookie(c.cookieAllocator.Request(category).Raw()). @@ -1847,7 +1758,7 @@ func (c *client) snatCommonFlows(nodeIP net.IP, localSubnet net.IPNet, localGate c.pipeline[snatTable].BuildFlow(priorityLow). MatchProtocol(ipProto). MatchCTStateNew(true).MatchCTStateTrk(true). - MatchRegRange(int(marksReg), markTrafficFromTunnel, binding.Range{0, 15}). + MatchRegMark(FromTunnelMark). Action().Drop(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -1908,7 +1819,7 @@ func (c *client) loadBalancerServiceFromOutsideFlow(svcIP net.IP, svcPort uint16 return c.pipeline[uplinkTable].BuildFlow(priorityHigh). MatchProtocol(protocol). MatchDstPort(svcPort, nil). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + MatchRegMark(FromUplinkMark). MatchDstIP(svcIP). Action().Output(config.HostGatewayOFPort). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). @@ -1921,7 +1832,7 @@ func (c *client) serviceLearnFlow(groupID binding.GroupIDType, svcIP net.IP, svc // Using unique cookie ID here to avoid learned flow cascade deletion. cookieID := c.cookieAllocator.RequestWithObjectID(cookie.Service, uint32(groupID)).Raw() learnFlowBuilder := c.pipeline[serviceLBTable].BuildFlow(priorityLow). - MatchRegRange(int(serviceLearnReg), marksRegServiceNeedLearn, serviceLearnRegRange). + MatchRegMark(EpToLearnMark). MatchDstIP(svcIP). MatchProtocol(protocol). MatchDstPort(svcPort, nil). @@ -1955,24 +1866,24 @@ func (c *client) serviceLearnFlow(groupID binding.GroupIDType, svcIP net.IP, svc return learnFlowBuilderLearnAction. MatchLearnedDstIP(). MatchLearnedSrcIP(). - LoadRegToReg(int(endpointIPReg), int(endpointIPReg), endpointIPRegRange, endpointIPRegRange). - LoadRegToReg(int(endpointPortReg), int(endpointPortReg), endpointPortRegRange, endpointPortRegRange). - LoadReg(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). - LoadReg(int(marksReg), macRewriteMark, macRewriteMarkRange). + LoadFieldToField(EndpointIPField, EndpointIPField). + LoadFieldToField(EndpointPortField, EndpointPortField). + LoadRegMark(EpSelectedMark). + LoadRegMark(RewriteMACMark). Done(). - Action().LoadRegRange(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). + Action().LoadRegMark(EpSelectedMark). Action().GotoTable(endpointDNATTable). Done() } else if ipProtocol == binding.ProtocolIPv6 { return learnFlowBuilderLearnAction. MatchLearnedDstIPv6(). MatchLearnedSrcIPv6(). - LoadXXRegToXXReg(int(endpointIPv6XXReg), int(endpointIPv6XXReg), endpointIPv6XXRegRange, endpointIPv6XXRegRange). - LoadRegToReg(int(endpointPortReg), int(endpointPortReg), endpointPortRegRange, endpointPortRegRange). - LoadReg(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). - LoadReg(int(marksReg), macRewriteMark, macRewriteMarkRange). + LoadXXRegToXXReg(EndpointIP6Field, EndpointIP6Field). + LoadFieldToField(EndpointPortField, EndpointPortField). + LoadRegMark(EpSelectedMark). + LoadRegMark(RewriteMACMark). Done(). - Action().LoadRegRange(int(serviceLearnReg), marksRegServiceSelected, serviceLearnRegRange). + Action().LoadRegMark(EpSelectedMark). Action().GotoTable(endpointDNATTable). Done() } @@ -1982,20 +1893,20 @@ func (c *client) serviceLearnFlow(groupID binding.GroupIDType, svcIP net.IP, svc // serviceLBFlow generates the flow which uses the specific group to do Endpoint // selection. func (c *client) serviceLBFlow(groupID binding.GroupIDType, svcIP net.IP, svcPort uint16, protocol binding.Protocol, withSessionAffinity bool) binding.Flow { - var lbResultMark uint32 + var lbResultMark *binding.RegMark if withSessionAffinity { - lbResultMark = marksRegServiceNeedLearn + lbResultMark = EpToLearnMark } else { - lbResultMark = marksRegServiceSelected + lbResultMark = EpSelectedMark } return c.pipeline[serviceLBTable].BuildFlow(priorityNormal). MatchProtocol(protocol). MatchDstPort(svcPort, nil). MatchDstIP(svcIP). - MatchRegRange(int(serviceLearnReg), marksRegServiceNeedLB, serviceLearnRegRange). - Action().LoadRegRange(int(serviceLearnReg), lbResultMark, serviceLearnRegRange). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + MatchRegMark(EpToSelectMark). + Action().LoadRegMark(lbResultMark). + Action().LoadRegMark(RewriteMACMark). Action().Group(groupID). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). Done() @@ -2006,30 +1917,28 @@ func (c *client) serviceLBFlow(groupID binding.GroupIDType, svcIP net.IP, svcPor // in regs. func (c *client) endpointDNATFlow(endpointIP net.IP, endpointPort uint16, protocol binding.Protocol) binding.Flow { ipProtocol := getIPProtocol(endpointIP) - unionVal := (marksRegServiceSelected << endpointPortRegRange.Length()) + uint32(endpointPort) + unionVal := (EpSelectedMark.GetValue() << EndpointPortField.GetRange().Length()) + uint32(endpointPort) table := c.pipeline[endpointDNATTable] flowBuilder := table.BuildFlow(priorityNormal). Cookie(c.cookieAllocator.Request(cookie.Service).Raw()). - MatchRegRange(int(endpointPortReg), unionVal, binding.Range{0, 18}). + MatchRegFieldWithValue(EpUnionField, unionVal). MatchProtocol(protocol) ctZone := CtZone if ipProtocol == binding.ProtocolIP { ipVal := binary.BigEndian.Uint32(endpointIP.To4()) - flowBuilder = flowBuilder.MatchReg(int(endpointIPReg), ipVal). - MatchRegRange(int(endpointPortReg), unionVal, binding.Range{0, 18}) + flowBuilder = flowBuilder.MatchRegFieldWithValue(EndpointIPField, ipVal) } else { ctZone = CtZoneV6 ipVal := []byte(endpointIP) - flowBuilder = flowBuilder.MatchXXReg(int(endpointIPv6XXReg), ipVal). - MatchRegRange(int(endpointPortReg), unionVal, binding.Range{0, 18}) + flowBuilder = flowBuilder.MatchXXReg(EndpointIP6Field.GetRegID(), ipVal) } return flowBuilder.Action().CT(true, table.GetNext(), ctZone). DNAT( &binding.IPRange{StartIP: endpointIP, EndIP: endpointIP}, &binding.PortRange{StartPort: endpointPort, EndPort: endpointPort}, ). - LoadToMark(ServiceCTMark). + LoadToCtMark(ServiceCTMark). CTDone(). Done() } @@ -2048,7 +1957,7 @@ func (c *client) hairpinSNATFlow(endpointIP net.IP) binding.Flow { MatchDstIP(endpointIP). MatchSrcIP(endpointIP). Action().SetSrcIP(hpIP). - Action().LoadRegRange(int(marksReg), hairpinMark, hairpinMarkRange). + Action().LoadRegMark(markHairpin). Action().GotoTable(L2ForwardingOutTable). Done() } @@ -2075,15 +1984,15 @@ func (c *client) serviceEndpointGroup(groupID binding.GroupIDType, withSessionAf if ipProtocol == binding.ProtocolIP { ipVal := binary.BigEndian.Uint32(endpointIP.To4()) group = group.Bucket().Weight(100). - LoadReg(int(endpointIPReg), ipVal). - LoadRegRange(int(endpointPortReg), uint32(portVal), endpointPortRegRange). + LoadToRegField(EndpointIPField, ipVal). + LoadToRegField(EndpointPortField, uint32(portVal)). ResubmitToTable(resubmitTableID). Done() } else if ipProtocol == binding.ProtocolIPv6 { ipVal := []byte(endpointIP) group = group.Bucket().Weight(100). - LoadXXReg(int(endpointIPv6XXReg), ipVal). - LoadRegRange(int(endpointPortReg), uint32(portVal), endpointPortRegRange). + LoadXXReg(EndpointIP6Field.GetRegID(), ipVal). + LoadToRegField(EndpointPortField, uint32(portVal)). ResubmitToTable(resubmitTableID). Done() } @@ -2104,7 +2013,7 @@ func (c *client) decTTLFlows(category cookie.Category) []binding.Flow { decTTLTable.BuildFlow(priorityHigh). Cookie(c.cookieAllocator.Request(category).Raw()). MatchProtocol(proto). - MatchRegRange(int(marksReg), markTrafficFromGateway, binding.Range{0, 15}). + MatchRegMark(FromGatewayMark). Action().GotoTable(decTTLTable.GetNext()). Done(), decTTLTable.BuildFlow(priorityNormal). diff --git a/pkg/agent/openflow/pipeline_windows.go b/pkg/agent/openflow/pipeline_windows.go index 395268196b4..02b2539cef5 100644 --- a/pkg/agent/openflow/pipeline_windows.go +++ b/pkg/agent/openflow/pipeline_windows.go @@ -26,8 +26,6 @@ import ( ) const ( - markTrafficFromBridge = 5 - // ctZoneSNAT is only used on Windows and only when AntreaProxy is enabled. // When a Pod access a ClusterIP Service, and the IP of the selected endpoint // is not in "cluster-cidr". The request packets need to be SNAT'd(set src IP to local Node IP) @@ -41,19 +39,11 @@ const ( // Pod --> DNAT(CtZone) --> SNAT(ctZoneSNAT) --> Endpoint(API server NodeIP) // Pod <-- unDNAT(CtZone) <-- unSNAT(ctZoneSNAT) <-- Endpoint(API server NodeIP) ctZoneSNAT = 0xffdc - - // snatDefaultMark indicates the packet should be SNAT'd with the default - // SNAT IP (the Node IP). - snatDefaultMark = 0b1 - - // snatCTMark indicates SNAT is performed for packets of the connection. - snatCTMark = 0x40 ) var ( - // snatMarkRange takes the 17th bit of register marksReg to indicate if - // the packet needs to be SNATed with Node's IP or not. - snatMarkRange = binding.Range{17, 17} + // Mark to indicate SNAT is performed on the connection, it is only used on Windows now. + snatCTMark = binding.NewCtMark(0x40, 0, 31) ) // uplinkSNATFlows installs flows for traffic from the uplink port that help @@ -71,9 +61,9 @@ func (c *client) uplinkSNATFlows(localSubnet net.IPNet, category cookie.Category c.pipeline[conntrackStateTable].BuildFlow(priorityHigh). MatchProtocol(binding.ProtocolIP). MatchCTStateNew(false).MatchCTStateTrk(true). - MatchCTMark(snatCTMark, nil). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + MatchCTMarkData(snatCTMark). + MatchRegMark(FromUplinkMark). + Action().LoadRegMark(RewriteMACMark). Cookie(c.cookieAllocator.Request(category).Raw()). Action().GotoTable(ctStateNext). Done(), @@ -81,7 +71,7 @@ func (c *client) uplinkSNATFlows(localSubnet net.IPNet, category cookie.Category // if it is received from the uplink interface. c.pipeline[conntrackStateTable].BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + MatchRegMark(FromUplinkMark). Action().Output(int(bridgeOFPort)). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -97,14 +87,14 @@ func (c *client) uplinkSNATFlows(localSubnet net.IPNet, category cookie.Category // Pod <-- unDNAT(CtZone) <-- unSNAT(ctZoneSNAT) <-- ExternalServer flows = append(flows, c.pipeline[uplinkTable].BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + MatchRegMark(FromUplinkMark). Action().CT(false, conntrackTable, ctZoneSNAT).NAT().CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) } else { flows = append(flows, c.pipeline[uplinkTable].BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + MatchRegMark(FromUplinkMark). Action().GotoTable(conntrackTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) @@ -124,8 +114,8 @@ func (c *client) snatImplementationFlows(nodeIP net.IP, category cookie.Category c.pipeline[snatTable].BuildFlow(priorityLow). MatchProtocol(binding.ProtocolIP). MatchCTStateNew(true).MatchCTStateTrk(true). - MatchRegRange(int(marksReg), markTrafficFromLocal, binding.Range{0, 15}). - Action().LoadRegRange(int(marksReg), snatDefaultMark, snatMarkRange). + MatchRegMark(FromLocalMark). + Action().LoadRegMark(SNATNodeIPMark). Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -142,10 +132,10 @@ func (c *client) snatImplementationFlows(nodeIP net.IP, category cookie.Category ctCommitTable.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). MatchCTStateNew(true).MatchCTStateTrk(true).MatchCTStateDNAT(false). - MatchRegRange(int(marksReg), snatDefaultMark, snatMarkRange). + MatchRegMark(SNATNodeIPMark). Action().CT(true, ccNextTable, CtZone). SNAT(snatIPRange, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), } @@ -161,8 +151,8 @@ func (c *client) snatImplementationFlows(nodeIP net.IP, category cookie.Category l3FwdTable.BuildFlow(priorityLow). MatchProtocol(binding.ProtocolIP). MatchCTStateNew(false).MatchCTStateTrk(true).MatchCTStateDNAT(true). - MatchRegRange(int(marksReg), markTrafficFromLocal, binding.Range{0, 15}). - Action().LoadRegRange(int(marksReg), snatDefaultMark, snatMarkRange). + MatchRegMark(FromLocalMark). + Action().LoadRegMark(SNATNodeIPMark). Action().GotoTable(nextTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -172,16 +162,16 @@ func (c *client) snatImplementationFlows(nodeIP net.IP, category cookie.Category ctCommitTable.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). MatchCTStateNew(true).MatchCTStateTrk(true).MatchCTStateDNAT(true). - MatchRegRange(int(marksReg), snatDefaultMark, snatMarkRange). + MatchRegMark(SNATNodeIPMark). Action().CT(true, ccNextTable, ctZoneSNAT). SNAT(snatIPRange, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), ctCommitTable.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). MatchCTStateNew(false).MatchCTStateTrk(true).MatchCTStateDNAT(true). - MatchRegRange(int(marksReg), snatDefaultMark, snatMarkRange). + MatchRegMark(SNATNodeIPMark). Action().CT(false, ccNextTable, ctZoneSNAT).NAT().CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -210,7 +200,7 @@ func (c *client) snatMarkFlows(snatIP net.IP, mark uint32) []binding.Flow { MatchPktMark(mark, &types.SNATIPMarkMask). Action().CT(true, nextTable, CtZone). SNAT(snatIPRange, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(c.cookieAllocator.Request(cookie.SNAT).Raw()). Done(), } @@ -222,7 +212,7 @@ func (c *client) snatMarkFlows(snatIP net.IP, mark uint32) []binding.Flow { MatchPktMark(mark, &types.SNATIPMarkMask). Action().CT(true, nextTable, ctZoneSNAT). SNAT(snatIPRange, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(c.cookieAllocator.Request(cookie.SNAT).Raw()). Done()) } @@ -237,13 +227,13 @@ func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Ca flows = []binding.Flow{ c.pipeline[ClassifierTable].BuildFlow(priorityNormal). MatchInPort(config.UplinkOFPort). - Action().LoadRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + Action().LoadRegMark(FromUplinkMark). Action().GotoTable(uplinkTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), c.pipeline[ClassifierTable].BuildFlow(priorityNormal). MatchInPort(config.BridgeOFPort). - Action().LoadRegRange(int(marksReg), markTrafficFromBridge, binding.Range{0, 15}). + Action().LoadRegMark(FromBridgeMark). Action().GotoTable(uplinkTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -251,7 +241,7 @@ func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Ca // are redirected to conntrackTable in uplinkSNATFlows() (in // case they need unSNAT). c.pipeline[uplinkTable].BuildFlow(priorityLow). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + MatchRegMark(FromUplinkMark). Action().Output(int(bridgeOFPort)). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -267,16 +257,16 @@ func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Ca // interface). c.pipeline[uplinkTable].BuildFlow(priorityHigh). MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), markTrafficFromBridge, binding.Range{0, 15}). + MatchRegMark(FromBridgeMark). MatchDstIPNet(localSubnet). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + Action().LoadRegMark(RewriteMACMark). Action().GotoTable(conntrackTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), // Output other packets from the bridge port to the uplink port // directly. c.pipeline[uplinkTable].BuildFlow(priorityLow). - MatchRegRange(int(marksReg), markTrafficFromBridge, binding.Range{0, 15}). + MatchRegMark(FromBridgeMark). Action().Output(config.UplinkOFPort). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), @@ -285,9 +275,9 @@ func (c *client) hostBridgeUplinkFlows(localSubnet net.IPNet, category cookie.Ca // If NoEncap is enabled, the reply packets from remote Pod can be forwarded to local Pod directly. // by explicitly resubmitting them to endpointDNATTable and marking "macRewriteMark" at same time. flows = append(flows, c.pipeline[conntrackStateTable].BuildFlow(priorityHigh).MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), markTrafficFromUplink, binding.Range{0, 15}). + MatchRegMark(FromUplinkMark). MatchDstIPNet(localSubnet). - Action().LoadRegRange(int(marksReg), macRewriteMark, macRewriteMarkRange). + Action().LoadRegMark(RewriteMACMark). Action().GotoTable(endpointDNATTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done()) @@ -301,8 +291,8 @@ func (c *client) l3FwdFlowToRemoteViaRouting(localGatewayMAC net.HardwareAddr, r // It enhances Windows Noencap mode performance by bypassing host network. flows := []binding.Flow{c.pipeline[l2ForwardingCalcTable].BuildFlow(priorityNormal). MatchDstMAC(remoteGatewayMAC). - Action().LoadRegRange(int(PortCacheReg), config.UplinkOFPort, ofPortRegRange). - Action().LoadRegRange(int(marksReg), macRewriteMark, ofPortMarkRange). + Action().LoadToRegField(TargetOFPortField, config.UplinkOFPort). + Action().LoadRegMark(OFPortFoundMark). Action().GotoTable(conntrackCommitTable). Cookie(c.cookieAllocator.Request(category).Raw()). Done()} diff --git a/pkg/agent/openflow/regmarks.go b/pkg/agent/openflow/regmarks.go new file mode 100644 index 00000000000..eafc268240e --- /dev/null +++ b/pkg/agent/openflow/regmarks.go @@ -0,0 +1,105 @@ +package openflow + +import binding "antrea.io/antrea/pkg/ovs/openflow" + +// Fields used reg. +var ( + // reg0 (NXM_NX_REG0) + // reg0[0..3]: Field to mark the packet source. Marks in this field include, + // - 0: from the tunnel port + // - 1: from antrea-gw0 + // - 2: from the local Pods + // - 4: from the Bridge interface + // - 5: from the uplink interface + PktSourceField = binding.NewRegField(0, 0, 3, "PacketSource") + FromTunnelMark = binding.NewRegMarkWithField(PktSourceField, 0) + FromGatewayMark = binding.NewRegMarkWithField(PktSourceField, 1) + FromLocalMark = binding.NewRegMarkWithField(PktSourceField, 2) + FromUplinkMark = binding.NewRegMarkWithField(PktSourceField, 4) + FromBridgeMark = binding.NewRegMarkWithField(PktSourceField, 5) + // reg0[16]: Mark to indicate the ofPort number of an interface is found. + OFPortFoundMark = binding.NewOneBitRegMark(0, 16, "OFPortFound") + // reg0[17]: Mark to indicate the packet needs to be SNATed with Node's IP. + SNATNodeIPMark = binding.NewOneBitRegMark(0, 17, "SNATWithNodeIP") + // reg0[18]: Mark to indicate the packet needs DNAT to virtual IP. + // If a packet uses markHairpin, it will be output to the port where it enters OVS pipeline in L2ForwardingOutTable. + markHairpin = binding.NewOneBitRegMark(0, 18, "Hairpin") + // reg0[19]: Mark to indicate the packet's MAC address needs to be rewritten. + RewriteMACMark = binding.NewOneBitRegMark(0, 19, "RewriteMAC") + // reg0[20]: Mark to indicate the packet is denied(Drop/Reject). + CnpDenyMark = binding.NewOneBitRegMark(0, 20, "CNPDeny") + // reg0[21..22]: Field to indicate disposition of Antrea Policy. It could have more bits to support more disposition + // that Antrea policy support in the future. + // Marks in this field include, + // - 0b00: allow + // - 0b01: drop + // - 0b10: reject + APDispositionField = binding.NewRegField(0, 21, 22, "APDisposition") + DispositionAllowMark = binding.NewRegMarkWithField(APDispositionField, DispositionAllow) + DispositionDropMark = binding.NewRegMarkWithField(APDispositionField, DispositionDrop) + DispositionRejMark = binding.NewRegMarkWithField(APDispositionField, DispositionRej) + // reg0[24..26]: Field to indicate the reasons of sending packet to the controller. + // Marks in this field include, + // - 0b00: logging + // - 0b01: reject + // - 0b10: drop + CustomReasonField = binding.NewRegField(0, 24, 26, "PacketInReason") + MarkCustomReasonLogging = binding.NewRegMarkWithField(CustomReasonField, CustomReasonLogging) + MarkCustomReasonReject = binding.NewRegMarkWithField(CustomReasonField, CustomReasonReject) + MarkCustomReasonDeny = binding.NewRegMarkWithField(CustomReasonField, CustomReasonDeny) + + // reg1(NXM_NX_REG1) + // Field to cache the ofPort of the OVS interface where to output packet. + TargetOFPortField = binding.NewRegField(1, 0, 31, "TargetOFPort") + + // reg2(NXM_NX_REG2) + // Field to help swap values in two different flow fields in the OpenFlow actions. This field is only used in func + // `arpResponderStaticFlow`. + SwapField = binding.NewRegField(2, 0, 31, "SwapValue") + + // reg3(NXM_NX_REG3) + // Field to store the selected Service Endpoint IP + EndpointIPField = binding.NewRegField(3, 0, 31, "EndpointIP") + // Field to store the conjunction ID which is for "deny" rule in CNP. It shares the same register with EndpointIPField, + // since the service selection will finish when a packet hitting NetworkPolicy related rules. + CNPDenyConjIDField = binding.NewRegField(3, 0, 31, "CNPDenyConjunctionID") + + // reg4(NXM_NX_REG4) + // reg4[0..15]: Field to store the selected Service Endpoint port. + EndpointPortField = binding.NewRegField(4, 0, 15, "EndpointPort") + // reg4[16..18]: Field to store the state of a packet accessing a Service. Marks in this field include, + // - 0b001: packet need to do service selection. + // - 0b010: packet has done service selection. + // - 0b011: packet has done service selection and the selection result needs to be cached. + ServiceEPStateField = binding.NewRegField(4, 16, 18, "EndpointState") + EpToSelectMark = binding.NewRegMarkWithField(ServiceEPStateField, 0b001) + EpSelectedMark = binding.NewRegMarkWithField(ServiceEPStateField, 0b010) + EpToLearnMark = binding.NewRegMarkWithField(ServiceEPStateField, 0b011) + // reg4[0..18]: Field to store the union value of Endpoint port and Endpoint status. It is used as a single match + // when needed. + EpUnionField = binding.NewRegField(4, 0, 18, "EndpointUnion") + + // reg5(NXM_NX_REG5) + // Field to cache the Egress conjunction ID hit by TraceFlow packet. + TFEgressConjIDField = binding.NewRegField(5, 0, 31, "TFEgressConjunctionID") + + // reg(N6XM_NX_REG6) + // Field to store the Ingress conjunction ID hit by TraceFlow packet. + TFIngressConjIDField = binding.NewRegField(6, 0, 31, "TFIngressConjunctionID") +) + +// Fields used xxreg. +var ( + // xxreg3(NXM_NX_XXREG3) + // xxreg3: Field to cache Endpoint IPv6 address. It occupies reg12-reg15 in the meanwhile. + EndpointIP6Field = binding.NewXXRegField(3, 0, 127) +) + +// Marks used in conntrack +var ( + // Mark to indicate the connection is initiated through the host gateway interface + // (i.e. for which the first packet of the connection was received through the gateway). + gatewayCTMark = binding.NewCtMark(0x20, 0, 31) + // Mark to indicate DNAT is performed on the connection for Service. + ServiceCTMark = binding.NewCtMark(0x21, 0, 31) +) diff --git a/pkg/ovs/openflow/interfaces.go b/pkg/ovs/openflow/interfaces.go index 6a4e2af1a31..158c60010df 100644 --- a/pkg/ovs/openflow/interfaces.go +++ b/pkg/ovs/openflow/interfaces.go @@ -80,7 +80,7 @@ const ( ) // IPDSCPToSRange stores the DSCP bits in ToS field of IP header. -var IPDSCPToSRange = Range{2, 7} +var IPDSCPToSRange = &Range{2, 7} // Bridge defines operations on an openflow bridge. type Bridge interface { @@ -178,10 +178,13 @@ type Flow interface { type Action interface { LoadARPOperation(value uint16) FlowBuilder - LoadRegRange(regID int, value uint32, to Range) FlowBuilder - LoadPktMarkRange(value uint32, to Range) FlowBuilder + // Deprecated. + LoadRegRange(regID int, value uint32, to *Range) FlowBuilder + LoadToRegField(field *RegField, value uint32) FlowBuilder + LoadRegMark(mark *RegMark) FlowBuilder + LoadPktMarkRange(value uint32, to *Range) FlowBuilder LoadIPDSCP(value uint8) FlowBuilder - LoadRange(name string, addr uint64, to Range) FlowBuilder + LoadRange(name string, addr uint64, to *Range) FlowBuilder Move(from, to string) FlowBuilder MoveRange(fromName, toName string, from, to Range) FlowBuilder Resubmit(port uint16, table TableIDType) FlowBuilder @@ -189,8 +192,10 @@ type Action interface { CT(commit bool, tableID TableIDType, zone int) CTAction Drop() FlowBuilder Output(port int) FlowBuilder - OutputFieldRange(from string, rng Range) FlowBuilder - OutputRegRange(regID int, rng Range) FlowBuilder + OutputFieldRange(from string, rng *Range) FlowBuilder + // Deprecated. + OutputRegRange(regID int, rng *Range) FlowBuilder + OutputToRegField(field *RegField) FlowBuilder OutputInPort() FlowBuilder SetDstMAC(addr net.HardwareAddr) FlowBuilder SetSrcMAC(addr net.HardwareAddr) FlowBuilder @@ -216,9 +221,13 @@ type FlowBuilder interface { MatchPriority(uint16) FlowBuilder MatchProtocol(name Protocol) FlowBuilder MatchIPProtocolValue(isIPv6 bool, protoValue uint8) FlowBuilder + // Deprecated. MatchReg(regID int, data uint32) FlowBuilder MatchXXReg(regID int, data []byte) FlowBuilder - MatchRegRange(regID int, data uint32, rng Range) FlowBuilder + // Deprecated. + MatchRegRange(regID int, data uint32, rng *Range) FlowBuilder + MatchRegMark(mark *RegMark) FlowBuilder + MatchRegFieldWithValue(field *RegField, data uint32) FlowBuilder MatchInPort(inPort uint32) FlowBuilder MatchDstIP(ip net.IP) FlowBuilder MatchDstIPNet(ipNet net.IPNet) FlowBuilder @@ -240,7 +249,9 @@ type FlowBuilder interface { MatchCTStateInv(isSet bool) FlowBuilder MatchCTStateDNAT(isSet bool) FlowBuilder MatchCTStateSNAT(isSet bool) FlowBuilder + // Deprecated MatchCTMark(value uint32, mask *uint32) FlowBuilder + MatchCTMarkData(mark *CtMark) FlowBuilder MatchCTLabelRange(high, low uint64, bitRange Range) FlowBuilder MatchPktMark(value uint32, mask *uint32) FlowBuilder MatchConjID(value uint32) FlowBuilder @@ -285,10 +296,16 @@ type LearnAction interface { MatchLearnedDstIP() LearnAction MatchLearnedSrcIPv6() LearnAction MatchLearnedDstIPv6() LearnAction - MatchReg(regID int, data uint32, rng Range) LearnAction - LoadReg(regID int, data uint32, rng Range) LearnAction - LoadRegToReg(fromRegID, toRegID int, fromRng, toRng Range) LearnAction - LoadXXRegToXXReg(fromRegID, toRegID int, fromRng, toRng Range) LearnAction + // Deprecated. + MatchReg(regID int, data uint32, rng *Range) LearnAction + MatchRegMark(mark *RegMark) LearnAction + // Deprecated. + LoadReg(regID int, data uint32, rng *Range) LearnAction + LoadRegMark(mark *RegMark) LearnAction + // Deprecated. + LoadRegToReg(fromRegID, toRegID int, fromRng, toRng *Range) LearnAction + LoadFieldToField(fromField, toField *RegField) LearnAction + LoadXXRegToXXReg(fromXXField, toXXField *XXRegField) LearnAction SetDstMAC(mac net.HardwareAddr) LearnAction Done() FlowBuilder } @@ -301,9 +318,12 @@ type Group interface { type BucketBuilder interface { Weight(val uint16) BucketBuilder + // Deprecated. LoadReg(regID int, data uint32) BucketBuilder LoadXXReg(regID int, data []byte) BucketBuilder - LoadRegRange(regID int, data uint32, rng Range) BucketBuilder + // Deprecated. + LoadRegRange(regID int, data uint32, rng *Range) BucketBuilder + LoadToRegField(field *RegField, data uint32) BucketBuilder ResubmitToTable(tableID TableIDType) BucketBuilder Done() Group } @@ -325,6 +345,7 @@ type MeterBandBuilder interface { type CTAction interface { LoadToMark(value uint32) CTAction + LoadToCtMark(mark *CtMark) CTAction LoadToLabelRange(value uint64, rng *Range) CTAction MoveToLabel(fromName string, fromRng, labelRng *Range) CTAction // NAT action translates the packet in the way that the connection was committed into the conntrack zone, e.g., if @@ -364,7 +385,8 @@ type PacketOutBuilder interface { SetICMPData(data []byte) PacketOutBuilder SetInport(inPort uint32) PacketOutBuilder SetOutport(outport uint32) PacketOutBuilder - AddLoadAction(name string, data uint64, rng Range) PacketOutBuilder + AddLoadAction(name string, data uint64, rng *Range) PacketOutBuilder + AddLoadRegMark(mark *RegMark) PacketOutBuilder Done() *ofctrl.PacketOut } @@ -403,3 +425,27 @@ type Packet struct { ICMPEchoID uint16 ICMPEchoSeq uint16 } + +// RegField specifies a register with a required bit range. regID is the register number, and rng is the range of bits +// taken by the field. The OF client could use a RegField to cache or match varied value. +type RegField struct { + regID int + rng *Range + name string +} + +// RegMark uses a RegField to cache a fixed value or value enumeration. The RegMark is used to indicate the traffic +// has some expected characteristic. +type RegMark struct { + field *RegField + value uint32 +} + +// XXRegField specifies a xxreg with a required bit range. +type XXRegField RegField + +// CtMark is used to indicate the connection characteristic. +type CtMark struct { + rng *Range + value uint32 +} diff --git a/pkg/ovs/openflow/ofctrl_action.go b/pkg/ovs/openflow/ofctrl_action.go index 9f19f7f1fdf..0daed837d13 100644 --- a/pkg/ovs/openflow/ofctrl_action.go +++ b/pkg/ovs/openflow/ofctrl_action.go @@ -31,18 +31,23 @@ func (a *ofFlowAction) Output(port int) FlowBuilder { } // OutputFieldRange is an action to output packets to the port located in the specified NXM field with rng. -func (a *ofFlowAction) OutputFieldRange(name string, rng Range) FlowBuilder { +func (a *ofFlowAction) OutputFieldRange(name string, rng *Range) FlowBuilder { outputAction, _ := ofctrl.NewNXOutput(name, int(rng[0]), int(rng[1])) a.builder.ApplyAction(outputAction) return a.builder } // OutputFieldRange is an action to output packets to a port which is located in the specified NXM register[rng[0]..rng[1]]. -func (a *ofFlowAction) OutputRegRange(regID int, rng Range) FlowBuilder { +func (a *ofFlowAction) OutputRegRange(regID int, rng *Range) FlowBuilder { name := fmt.Sprintf("%s%d", NxmFieldReg, regID) return a.OutputFieldRange(name, rng) } +func (a *ofFlowAction) OutputToRegField(field *RegField) FlowBuilder { + name := field.GetNXFieldName() + return a.OutputFieldRange(name, field.rng) +} + // OutputInPort is an action to output packets to the ofport from where the packet enters the OFSwitch. func (a *ofFlowAction) OutputInPort() FlowBuilder { outputAction := ofctrl.NewOutputInPort() @@ -79,6 +84,12 @@ func (a *ofCTAction) LoadToMark(value uint32) CTAction { return a } +func (a *ofCTAction) LoadToCtMark(mark *CtMark) CTAction { + field, _, _ := getFieldRange(NxmFieldCtMark) + a.load(field, uint64(mark.value), mark.rng) + return a +} + // LoadToLabelRange is an action to load data into ct_label at specified range. func (a *ofCTAction) LoadToLabelRange(value uint64, rng *Range) CTAction { field, _, _ := getFieldRange(NxmFieldCtLabel) @@ -222,7 +233,7 @@ func (a *ofFlowAction) LoadARPOperation(value uint16) FlowBuilder { } // LoadRange is an action to Load data to the target field at specified range. -func (a *ofFlowAction) LoadRange(name string, value uint64, rng Range) FlowBuilder { +func (a *ofFlowAction) LoadRange(name string, value uint64, rng *Range) FlowBuilder { loadAct, _ := ofctrl.NewNXLoadAction(name, value, rng.ToNXRange()) if a.builder.ofFlow.Table != nil && a.builder.ofFlow.Table.Switch != nil { loadAct.ResetFieldLength(a.builder.ofFlow.Table.Switch) @@ -232,15 +243,26 @@ func (a *ofFlowAction) LoadRange(name string, value uint64, rng Range) FlowBuild } // LoadRegRange is an action to Load data to the target register at specified range. -func (a *ofFlowAction) LoadRegRange(regID int, value uint32, rng Range) FlowBuilder { +func (a *ofFlowAction) LoadRegRange(regID int, value uint32, rng *Range) FlowBuilder { name := fmt.Sprintf("%s%d", NxmFieldReg, regID) loadAct, _ := ofctrl.NewNXLoadAction(name, uint64(value), rng.ToNXRange()) a.builder.ApplyAction(loadAct) return a.builder } +func (a *ofFlowAction) LoadToRegField(field *RegField, value uint32) FlowBuilder { + name := field.GetNXFieldName() + loadAct, _ := ofctrl.NewNXLoadAction(name, uint64(value), field.rng.ToNXRange()) + a.builder.ApplyAction(loadAct) + return a.builder +} + +func (a *ofFlowAction) LoadRegMark(mark *RegMark) FlowBuilder { + return a.LoadToRegField(mark.field, mark.value) +} + // LoadToPktMarkRange is an action to load data into pkt_mark at specified range. -func (a *ofFlowAction) LoadPktMarkRange(value uint32, rng Range) FlowBuilder { +func (a *ofFlowAction) LoadPktMarkRange(value uint32, rng *Range) FlowBuilder { return a.LoadRange(NxmFieldPktMark, uint64(value), rng) } @@ -470,7 +492,7 @@ func (a *ofLearnAction) MatchLearnedDstIPv6() LearnAction { } // MatchReg makes the learned flow to match the data in the reg of specific range. -func (a *ofLearnAction) MatchReg(regID int, data uint32, rng Range) LearnAction { +func (a *ofLearnAction) MatchReg(regID int, data uint32, rng *Range) LearnAction { toField := &ofctrl.LearnField{Name: fmt.Sprintf("NXM_NX_REG%d", regID), Start: uint16(rng[0])} valBuf := make([]byte, 4) binary.BigEndian.PutUint32(valBuf, data) @@ -482,6 +504,18 @@ func (a *ofLearnAction) MatchReg(regID int, data uint32, rng Range) LearnAction return a } +func (a *ofLearnAction) MatchRegMark(mark *RegMark) LearnAction { + toField := &ofctrl.LearnField{Name: mark.field.GetNXFieldName(), Start: uint16(mark.field.rng[0])} + valBuf := make([]byte, 4) + binary.BigEndian.PutUint32(valBuf, mark.value) + offset := (mark.field.rng.Length()-1)/8 + 1 + if offset < 2 { + offset = 2 + } + a.nxLearn.AddMatch(toField, uint16(mark.field.rng.Length()), nil, valBuf[4-offset:]) + return a +} + // MatchXXReg makes the learned flow to match the data in the xxreg of specific range. func (a *ofLearnAction) MatchXXReg(regID int, data []byte, rng Range) LearnAction { s := fmt.Sprintf("%s%d", NxmFieldXXReg, regID) @@ -496,24 +530,31 @@ func (a *ofLearnAction) MatchXXReg(regID int, data []byte, rng Range) LearnActio // LoadRegToReg makes the learned flow to load reg[fromRegID] to reg[toRegID] // with specific ranges. -func (a *ofLearnAction) LoadRegToReg(fromRegID, toRegID int, fromRng, toRng Range) LearnAction { +func (a *ofLearnAction) LoadRegToReg(fromRegID, toRegID int, fromRng, toRng *Range) LearnAction { fromField := &ofctrl.LearnField{Name: fmt.Sprintf("NXM_NX_REG%d", fromRegID), Start: uint16(fromRng[0])} toField := &ofctrl.LearnField{Name: fmt.Sprintf("NXM_NX_REG%d", toRegID), Start: uint16(toRng[0])} a.nxLearn.AddLoadAction(toField, uint16(toRng.Length()), fromField, nil) return a } -// LoadXXRegToXXReg makes the learned flow to load reg[fromXxRegID] to reg[toXxRegID] +func (a *ofLearnAction) LoadFieldToField(fromField, toField *RegField) LearnAction { + from := &ofctrl.LearnField{Name: fromField.GetNXFieldName(), Start: uint16(fromField.rng[0])} + to := &ofctrl.LearnField{Name: toField.GetNXFieldName(), Start: uint16(toField.rng[0])} + a.nxLearn.AddLoadAction(to, uint16(toField.rng.Length()), from, nil) + return a +} + +// LoadXXRegToXXReg makes the learned flow to load reg[fromXXField.regID] to reg[toXXField.regID] // with specific ranges. -func (a *ofLearnAction) LoadXXRegToXXReg(fromXxRegID, toXxRegID int, fromRng, toRng Range) LearnAction { - fromField := &ofctrl.LearnField{Name: fmt.Sprintf("%s%d", NxmFieldXXReg, fromXxRegID), Start: uint16(fromRng[0])} - toField := &ofctrl.LearnField{Name: fmt.Sprintf("%s%d", NxmFieldXXReg, toXxRegID), Start: uint16(toRng[0])} - a.nxLearn.AddLoadAction(toField, uint16(toRng.Length()), fromField, nil) +func (a *ofLearnAction) LoadXXRegToXXReg(fromXXField, toXXField *XXRegField) LearnAction { + from := &ofctrl.LearnField{Name: fromXXField.GetNXFieldName(), Start: uint16(fromXXField.rng[0])} + to := &ofctrl.LearnField{Name: toXXField.GetNXFieldName(), Start: uint16(toXXField.rng[0])} + a.nxLearn.AddLoadAction(to, uint16(toXXField.rng.Length()), from, nil) return a } // LoadReg makes the learned flow to load data to reg[regID] with specific range. -func (a *ofLearnAction) LoadReg(regID int, data uint32, rng Range) LearnAction { +func (a *ofLearnAction) LoadReg(regID int, data uint32, rng *Range) LearnAction { toField := &ofctrl.LearnField{Name: fmt.Sprintf("NXM_NX_REG%d", regID), Start: uint16(rng[0])} valBuf := make([]byte, 4) binary.BigEndian.PutUint32(valBuf, data) @@ -525,6 +566,18 @@ func (a *ofLearnAction) LoadReg(regID int, data uint32, rng Range) LearnAction { return a } +func (a *ofLearnAction) LoadRegMark(mark *RegMark) LearnAction { + toField := &ofctrl.LearnField{Name: mark.field.GetNXFieldName(), Start: uint16(mark.field.rng[0])} + valBuf := make([]byte, 4) + binary.BigEndian.PutUint32(valBuf, mark.value) + offset := (mark.field.rng.Length()-1)/8 + 1 + if offset < 2 { + offset = 2 + } + a.nxLearn.AddLoadAction(toField, uint16(mark.field.rng.Length()), nil, valBuf[4-offset:]) + return a +} + func (a *ofLearnAction) SetDstMAC(mac net.HardwareAddr) LearnAction { toField := &ofctrl.LearnField{Name: "NXM_OF_ETH_DST"} a.nxLearn.AddLoadAction(toField, 48, nil, mac) diff --git a/pkg/ovs/openflow/ofctrl_builder.go b/pkg/ovs/openflow/ofctrl_builder.go index 073a6146441..955f16c07bc 100644 --- a/pkg/ovs/openflow/ofctrl_builder.go +++ b/pkg/ovs/openflow/ofctrl_builder.go @@ -84,7 +84,7 @@ func (b *ofFlowBuilder) MatchXXReg(regID int, data []byte) FlowBuilder { } // MatchRegRange adds match condition for matching data in the target register at specified range. -func (b *ofFlowBuilder) MatchRegRange(regID int, data uint32, rng Range) FlowBuilder { +func (b *ofFlowBuilder) MatchRegRange(regID int, data uint32, rng *Range) FlowBuilder { s := fmt.Sprintf("reg%d[%d..%d]=0x%x", regID, rng[0], rng[1], data) b.matchers = append(b.matchers, s) if rng[0] > 0 { @@ -99,6 +99,17 @@ func (b *ofFlowBuilder) MatchRegRange(regID int, data uint32, rng Range) FlowBui return b } +func (b *ofFlowBuilder) MatchRegMark(mark *RegMark) FlowBuilder { + return b.MatchRegFieldWithValue(mark.field, mark.value) +} + +func (b *ofFlowBuilder) MatchRegFieldWithValue(field *RegField, data uint32) FlowBuilder { + if field.isFullRange() { + return b.MatchReg(field.regID, data) + } + return b.MatchRegRange(field.regID, data, field.rng) +} + func (b *ofFlowBuilder) addCTStateString(value string) { if b.ctStateString == "" { b.ctStateString = fmt.Sprintf("ct_state=%s", value) @@ -228,6 +239,20 @@ func (b *ofFlowBuilder) MatchCTMark(value uint32, mask *uint32) FlowBuilder { return b } +func (b *ofFlowBuilder) MatchCTMarkData(mark *CtMark) FlowBuilder { + ctmarkKey := fmt.Sprintf("ct_mark=0x%x", mark.value) + b.ofFlow.Match.CtMark = mark.value + if mark.isFullRange() { + b.ofFlow.Match.CtMarkMask = nil + } else { + mask := mark.rng.ToNXRange().ToUint32Mask() + ctmarkKey = fmt.Sprintf("%s/0x%x", ctmarkKey, mask) + b.ofFlow.Match.CtMarkMask = &mask + } + b.matchers = append(b.matchers, ctmarkKey) + return b +} + // MatchCTMarkMask sets the mask of ct_mark. The mask is used only if ct_mark is set. func (b *ofFlowBuilder) MatchCTMarkMask(mask uint32) FlowBuilder { if b.Flow.Match.CtMark > 0 { diff --git a/pkg/ovs/openflow/ofctrl_flow_test.go b/pkg/ovs/openflow/ofctrl_flow_test.go index 4bc23da6633..f4b433aff32 100644 --- a/pkg/ovs/openflow/ofctrl_flow_test.go +++ b/pkg/ovs/openflow/ofctrl_flow_test.go @@ -6,20 +6,23 @@ import ( "github.com/stretchr/testify/assert" ) +var testField = NewRegField(1, 0, 15) + func TestCopyToBuilder(t *testing.T) { table := &ofTable{ id: 0, next: 1, } + mark := NewCtMark(12345, 0, 31) oriFlow := table.BuildFlow(uint16(100)).MatchProtocol(ProtocolIP). Cookie(uint64(1004)). - MatchRegRange(1, 0x101, Range{0, 15}). + MatchRegFieldWithValue(testField, 0x101). MatchCTStateNew(true).MatchCTStateTrk(true). Action().CT( true, 1, 0x1234). - LoadToMark(uint32(12345)). + LoadToCtMark(mark). MoveToLabel(NxmFieldSrcMAC, &Range{0, 47}, &Range{0, 47}).CTDone(). Done() newFlow := oriFlow.CopyToBuilder(0, false) @@ -37,7 +40,7 @@ func TestCopyToBuilder_Drop(t *testing.T) { } oriFlow := table.BuildFlow(uint16(100)).MatchProtocol(ProtocolIP). Cookie(uint64(1004)). - MatchRegRange(1, 0x101, Range{0, 15}). + MatchRegFieldWithValue(testField, 0x101). MatchCTStateNew(true).MatchCTStateTrk(true). Action().Drop(). Done() diff --git a/pkg/ovs/openflow/ofctrl_group.go b/pkg/ovs/openflow/ofctrl_group.go index c5e3ffff162..27004ff7709 100644 --- a/pkg/ovs/openflow/ofctrl_group.go +++ b/pkg/ovs/openflow/ofctrl_group.go @@ -93,7 +93,7 @@ type bucketBuilder struct { // LoadReg makes the learned flow to load data to reg[regID] with specific range. func (b *bucketBuilder) LoadReg(regID int, data uint32) BucketBuilder { - return b.LoadRegRange(regID, data, Range{0, 31}) + return b.LoadRegRange(regID, data, &Range{0, 31}) } // LoadXXReg makes the learned flow to load data to xxreg[regID] with specific range. @@ -104,13 +104,24 @@ func (b *bucketBuilder) LoadXXReg(regID int, data []byte) BucketBuilder { } // LoadRegRange is an action to Load data to the target register at specified range. -func (b *bucketBuilder) LoadRegRange(regID int, data uint32, rng Range) BucketBuilder { +func (b *bucketBuilder) LoadRegRange(regID int, data uint32, rng *Range) BucketBuilder { reg := fmt.Sprintf("%s%d", NxmFieldReg, regID) regField, _ := openflow13.FindFieldHeaderByName(reg, true) b.bucket.AddAction(openflow13.NewNXActionRegLoad(rng.ToNXRange().ToOfsBits(), regField, uint64(data))) return b } +func (b *bucketBuilder) LoadToRegField(field *RegField, data uint32) BucketBuilder { + reg := field.GetNXFieldName() + regField, _ := openflow13.FindFieldHeaderByName(reg, true) + b.bucket.AddAction(openflow13.NewNXActionRegLoad(field.rng.ToNXRange().ToOfsBits(), regField, uint64(data))) + return b +} + +func (b *bucketBuilder) LoadRegMark(mark *RegMark) BucketBuilder { + return b.LoadToRegField(mark.field, mark.value) +} + // ResubmitToTable is an action to resubmit packet to the specified table when the bucket is selected. func (b *bucketBuilder) ResubmitToTable(tableID TableIDType) BucketBuilder { b.bucket.AddAction(openflow13.NewNXActionResubmitTableAction(openflow13.OFPP_IN_PORT, uint8(tableID))) diff --git a/pkg/ovs/openflow/ofctrl_nxfields.go b/pkg/ovs/openflow/ofctrl_nxfields.go new file mode 100644 index 00000000000..729fd59e341 --- /dev/null +++ b/pkg/ovs/openflow/ofctrl_nxfields.go @@ -0,0 +1,98 @@ +// Copyright 2021 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openflow + +import "fmt" + +func (f *RegField) GetRegID() int { + return f.regID +} + +func (f *RegField) GetRange() *Range { + return f.rng +} + +func (f *RegField) GetNXFieldName() string { + return fmt.Sprintf("%s%d", NxmFieldReg, f.regID) +} + +func (f *RegField) GetName() string { + return f.name +} + +func (f *RegField) isFullRange() bool { + return f.rng.Length() == 32 +} + +func NewRegField(id int, start, end uint32, name string) *RegField { + return &RegField{regID: id, rng: &Range{start, end}, name: name} +} + +func NewRegMark(id int, value, start, end uint32, name string) *RegMark { + field := NewRegField(id, start, end, name) + return &RegMark{value: value, field: field} +} + +func NewOneBitRegMark(regID int, bit uint32, name string) *RegMark { + return NewRegMark(regID, 1, bit, bit, name) +} + +func NewRegMarkWithField(field *RegField, value uint32) *RegMark { + return &RegMark{value: value, field: field} +} + +func (m *RegMark) GetValue() uint32 { + return m.value +} + +func (m *RegMark) GetField() *RegField { + return m.field +} + +func (f *XXRegField) GetRegID() int { + return f.regID +} + +func (f *XXRegField) GetRange() *Range { + return f.rng +} + +func (f *XXRegField) GetNXFieldName() string { + return fmt.Sprintf("%s%d", NxmFieldXXReg, f.regID) +} + +func (f *XXRegField) isFullRange() bool { + return f.rng.Length() == 128 +} + +func NewXXRegField(id int, start, end uint32) *XXRegField { + return &XXRegField{regID: id, rng: &Range{start, end}} +} + +func (m *CtMark) GetRange() *Range { + return m.rng +} + +func (m *CtMark) GetValue() uint32 { + return m.value +} + +func (m *CtMark) isFullRange() bool { + return m.rng.Length() == 32 +} + +func NewCtMark(value uint32, start, end uint32) *CtMark { + return &CtMark{value: value, rng: &Range{start, end}} +} diff --git a/pkg/ovs/openflow/ofctrl_packetout.go b/pkg/ovs/openflow/ofctrl_packetout.go index be99618bfff..18eb6846c94 100644 --- a/pkg/ovs/openflow/ofctrl_packetout.go +++ b/pkg/ovs/openflow/ofctrl_packetout.go @@ -268,12 +268,17 @@ func (b *ofPacketOutBuilder) SetOutport(outport uint32) PacketOutBuilder { } // AddLoadAction loads the data to the target field at specified range when the packet is received by OVS Switch. -func (b *ofPacketOutBuilder) AddLoadAction(name string, data uint64, rng Range) PacketOutBuilder { +func (b *ofPacketOutBuilder) AddLoadAction(name string, data uint64, rng *Range) PacketOutBuilder { act, _ := ofctrl.NewNXLoadAction(name, data, rng.ToNXRange()) b.pktOut.Actions = append(b.pktOut.Actions, act) return b } +func (b *ofPacketOutBuilder) AddLoadRegMark(mark *RegMark) PacketOutBuilder { + name := mark.field.GetNXFieldName() + return b.AddLoadAction(name, uint64(mark.value), mark.field.rng) +} + func (b *ofPacketOutBuilder) Done() *ofctrl.PacketOut { if b.pktOut.IPHeader != nil && b.pktOut.IPv6Header != nil { klog.Errorf("Invalid PacketOutBuilder: IP header and IPv6 header are not allowed to exist at the same time") diff --git a/pkg/ovs/openflow/testing/mock_openflow.go b/pkg/ovs/openflow/testing/mock_openflow.go index f641eb944d7..068926e8952 100644 --- a/pkg/ovs/openflow/testing/mock_openflow.go +++ b/pkg/ovs/openflow/testing/mock_openflow.go @@ -750,7 +750,7 @@ func (mr *MockActionMockRecorder) LoadIPDSCP(arg0 interface{}) *gomock.Call { } // LoadPktMarkRange mocks base method -func (m *MockAction) LoadPktMarkRange(arg0 uint32, arg1 openflow.Range) openflow.FlowBuilder { +func (m *MockAction) LoadPktMarkRange(arg0 uint32, arg1 *openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LoadPktMarkRange", arg0, arg1) ret0, _ := ret[0].(openflow.FlowBuilder) @@ -764,7 +764,7 @@ func (mr *MockActionMockRecorder) LoadPktMarkRange(arg0, arg1 interface{}) *gomo } // LoadRange mocks base method -func (m *MockAction) LoadRange(arg0 string, arg1 uint64, arg2 openflow.Range) openflow.FlowBuilder { +func (m *MockAction) LoadRange(arg0 string, arg1 uint64, arg2 *openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LoadRange", arg0, arg1, arg2) ret0, _ := ret[0].(openflow.FlowBuilder) @@ -777,8 +777,22 @@ func (mr *MockActionMockRecorder) LoadRange(arg0, arg1, arg2 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadRange", reflect.TypeOf((*MockAction)(nil).LoadRange), arg0, arg1, arg2) } +// LoadRegMark mocks base method +func (m *MockAction) LoadRegMark(arg0 *openflow.RegMark) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadRegMark", arg0) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// LoadRegMark indicates an expected call of LoadRegMark +func (mr *MockActionMockRecorder) LoadRegMark(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadRegMark", reflect.TypeOf((*MockAction)(nil).LoadRegMark), arg0) +} + // LoadRegRange mocks base method -func (m *MockAction) LoadRegRange(arg0 int, arg1 uint32, arg2 openflow.Range) openflow.FlowBuilder { +func (m *MockAction) LoadRegRange(arg0 int, arg1 uint32, arg2 *openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LoadRegRange", arg0, arg1, arg2) ret0, _ := ret[0].(openflow.FlowBuilder) @@ -791,6 +805,20 @@ func (mr *MockActionMockRecorder) LoadRegRange(arg0, arg1, arg2 interface{}) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadRegRange", reflect.TypeOf((*MockAction)(nil).LoadRegRange), arg0, arg1, arg2) } +// LoadToRegField mocks base method +func (m *MockAction) LoadToRegField(arg0 *openflow.RegField, arg1 uint32) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadToRegField", arg0, arg1) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// LoadToRegField indicates an expected call of LoadToRegField +func (mr *MockActionMockRecorder) LoadToRegField(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadToRegField", reflect.TypeOf((*MockAction)(nil).LoadToRegField), arg0, arg1) +} + // Meter mocks base method func (m *MockAction) Meter(arg0 uint32) openflow.FlowBuilder { m.ctrl.T.Helper() @@ -876,7 +904,7 @@ func (mr *MockActionMockRecorder) Output(arg0 interface{}) *gomock.Call { } // OutputFieldRange mocks base method -func (m *MockAction) OutputFieldRange(arg0 string, arg1 openflow.Range) openflow.FlowBuilder { +func (m *MockAction) OutputFieldRange(arg0 string, arg1 *openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OutputFieldRange", arg0, arg1) ret0, _ := ret[0].(openflow.FlowBuilder) @@ -904,7 +932,7 @@ func (mr *MockActionMockRecorder) OutputInPort() *gomock.Call { } // OutputRegRange mocks base method -func (m *MockAction) OutputRegRange(arg0 int, arg1 openflow.Range) openflow.FlowBuilder { +func (m *MockAction) OutputRegRange(arg0 int, arg1 *openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OutputRegRange", arg0, arg1) ret0, _ := ret[0].(openflow.FlowBuilder) @@ -917,6 +945,20 @@ func (mr *MockActionMockRecorder) OutputRegRange(arg0, arg1 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OutputRegRange", reflect.TypeOf((*MockAction)(nil).OutputRegRange), arg0, arg1) } +// OutputToRegField mocks base method +func (m *MockAction) OutputToRegField(arg0 *openflow.RegField) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "OutputToRegField", arg0) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// OutputToRegField indicates an expected call of OutputToRegField +func (mr *MockActionMockRecorder) OutputToRegField(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OutputToRegField", reflect.TypeOf((*MockAction)(nil).OutputToRegField), arg0) +} + // Resubmit mocks base method func (m *MockAction) Resubmit(arg0 uint16, arg1 openflow.TableIDType) openflow.FlowBuilder { m.ctrl.T.Helper() @@ -1136,6 +1178,20 @@ func (mr *MockCTActionMockRecorder) DNAT(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DNAT", reflect.TypeOf((*MockCTAction)(nil).DNAT), arg0, arg1) } +// LoadToCtMark mocks base method +func (m *MockCTAction) LoadToCtMark(arg0 *openflow.CtMark) openflow.CTAction { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadToCtMark", arg0) + ret0, _ := ret[0].(openflow.CTAction) + return ret0 +} + +// LoadToCtMark indicates an expected call of LoadToCtMark +func (mr *MockCTActionMockRecorder) LoadToCtMark(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadToCtMark", reflect.TypeOf((*MockCTAction)(nil).LoadToCtMark), arg0) +} + // LoadToLabelRange mocks base method func (m *MockCTAction) LoadToLabelRange(arg0 uint64, arg1 *openflow.Range) openflow.CTAction { m.ctrl.T.Helper() @@ -1411,6 +1467,20 @@ func (mr *MockFlowBuilderMockRecorder) MatchCTMark(arg0, arg1 interface{}) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchCTMark", reflect.TypeOf((*MockFlowBuilder)(nil).MatchCTMark), arg0, arg1) } +// MatchCTMarkData mocks base method +func (m *MockFlowBuilder) MatchCTMarkData(arg0 *openflow.CtMark) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MatchCTMarkData", arg0) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// MatchCTMarkData indicates an expected call of MatchCTMarkData +func (mr *MockFlowBuilderMockRecorder) MatchCTMarkData(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchCTMarkData", reflect.TypeOf((*MockFlowBuilder)(nil).MatchCTMarkData), arg0) +} + // MatchCTProtocol mocks base method func (m *MockFlowBuilder) MatchCTProtocol(arg0 openflow.Protocol) openflow.FlowBuilder { m.ctrl.T.Helper() @@ -1775,8 +1845,36 @@ func (mr *MockFlowBuilderMockRecorder) MatchReg(arg0, arg1 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchReg", reflect.TypeOf((*MockFlowBuilder)(nil).MatchReg), arg0, arg1) } +// MatchRegFieldWithValue mocks base method +func (m *MockFlowBuilder) MatchRegFieldWithValue(arg0 *openflow.RegField, arg1 uint32) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MatchRegFieldWithValue", arg0, arg1) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// MatchRegFieldWithValue indicates an expected call of MatchRegFieldWithValue +func (mr *MockFlowBuilderMockRecorder) MatchRegFieldWithValue(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchRegFieldWithValue", reflect.TypeOf((*MockFlowBuilder)(nil).MatchRegFieldWithValue), arg0, arg1) +} + +// MatchRegMark mocks base method +func (m *MockFlowBuilder) MatchRegMark(arg0 *openflow.RegMark) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MatchRegMark", arg0) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// MatchRegMark indicates an expected call of MatchRegMark +func (mr *MockFlowBuilderMockRecorder) MatchRegMark(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchRegMark", reflect.TypeOf((*MockFlowBuilder)(nil).MatchRegMark), arg0) +} + // MatchRegRange mocks base method -func (m *MockFlowBuilder) MatchRegRange(arg0 int, arg1 uint32, arg2 openflow.Range) openflow.FlowBuilder { +func (m *MockFlowBuilder) MatchRegRange(arg0 int, arg1 uint32, arg2 *openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MatchRegRange", arg0, arg1, arg2) ret0, _ := ret[0].(openflow.FlowBuilder) diff --git a/test/integration/agent/openflow_test.go b/test/integration/agent/openflow_test.go index 8adc762d2d6..ad771160ef9 100644 --- a/test/integration/agent/openflow_test.go +++ b/test/integration/agent/openflow_test.go @@ -941,7 +941,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=190,in_port=%d", podOFPort), - ActStr: "load:0x2->NXM_NX_REG0[0..15],goto_table:10", + ActStr: "load:0x2->NXM_NX_REG0[0..3],goto_table:10", }, }, }, @@ -1012,7 +1012,7 @@ func prepareGatewayFlows(gwIPs []net.IP, gwMAC net.HardwareAddr, vMAC net.Hardwa []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,in_port=%d", config1.HostGatewayOFPort), - ActStr: "load:0x1->NXM_NX_REG0[0..15],goto_table:10", + ActStr: "load:0x1->NXM_NX_REG0[0..3],goto_table:10", }, }, }, @@ -1093,7 +1093,7 @@ func prepareTunnelFlows(tunnelPort uint32, vMAC net.HardwareAddr) []expectTableF []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,in_port=%d", tunnelPort), - ActStr: "load:0->NXM_NX_REG0[0..15],load:0x1->NXM_NX_REG0[19],goto_table:30", + ActStr: "load:0->NXM_NX_REG0[0..3],load:0x1->NXM_NX_REG0[19],goto_table:30", }, }, }, @@ -1173,11 +1173,11 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { &ofTestUtils.ExpectFlow{MatchStr: "priority=190,ct_state=+inv+trk,ip", ActStr: "drop"}, ) table105Flows.flows = append(table105Flows.flows, - &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ip,reg0=0x1/0xffff", ActStr: "ct(commit,table=106,zone=65520,exec(load:0x20->NXM_NX_CT_MARK[])"}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ip,reg0=0x1/0xf", ActStr: "ct(commit,table=106,zone=65520,exec(load:0x20->NXM_NX_CT_MARK[])"}, &ofTestUtils.ExpectFlow{MatchStr: "priority=190,ct_state=+new+trk,ip", ActStr: "ct(commit,table=106,zone=65520)"}, ) table72Flows.flows = append(table72Flows.flows, - &ofTestUtils.ExpectFlow{MatchStr: "priority=210,ip,reg0=0x1/0xffff", ActStr: "goto_table:80"}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=210,ip,reg0=0x1/0xf", ActStr: "goto_table:80"}, &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ip", ActStr: "dec_ttl,goto_table:80"}, ) } @@ -1186,11 +1186,11 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { &ofTestUtils.ExpectFlow{MatchStr: "priority=190,ct_state=+inv+trk,ipv6", ActStr: "drop"}, ) table105Flows.flows = append(table105Flows.flows, - &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ipv6,reg0=0x1/0xffff", ActStr: "ct(commit,table=106,zone=65510,exec(load:0x20->NXM_NX_CT_MARK[])"}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ipv6,reg0=0x1/0xf", ActStr: "ct(commit,table=106,zone=65510,exec(load:0x20->NXM_NX_CT_MARK[])"}, &ofTestUtils.ExpectFlow{MatchStr: "priority=190,ct_state=+new+trk,ipv6", ActStr: "ct(commit,table=106,zone=65510)"}, ) table72Flows.flows = append(table72Flows.flows, - &ofTestUtils.ExpectFlow{MatchStr: "priority=210,ipv6,reg0=0x1/0xffff", ActStr: "goto_table:80"}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=210,ipv6,reg0=0x1/0xf", ActStr: "goto_table:80"}, &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ipv6", ActStr: "dec_ttl,goto_table:80"}, ) } @@ -1299,15 +1299,15 @@ func prepareExternalFlows(nodeIP net.IP, localSubnet *net.IPNet, gwMAC net.Hardw ActStr: "goto_table:80", }, { - MatchStr: fmt.Sprintf("priority=200,%s,reg0=0x2/0xffff,%s=%s", ipProtoStr, nwDstFieldName, nodeIP.String()), + MatchStr: fmt.Sprintf("priority=200,%s,reg0=0x2/0xf,%s=%s", ipProtoStr, nwDstFieldName, nodeIP.String()), ActStr: "goto_table:80", }, { - MatchStr: fmt.Sprintf("priority=190,%s,reg0=0x2/0xffff", ipProtoStr), + MatchStr: fmt.Sprintf("priority=190,%s,reg0=0x2/0xf", ipProtoStr), ActStr: "goto_table:71", }, { - MatchStr: fmt.Sprintf("priority=190,%s,reg0=0/0xffff", ipProtoStr), + MatchStr: fmt.Sprintf("priority=190,%s,reg0=0/0xf", ipProtoStr), ActStr: fmt.Sprintf("set_field:%s->eth_dst,goto_table:71", gwMAC.String()), }, }, @@ -1316,7 +1316,7 @@ func prepareExternalFlows(nodeIP net.IP, localSubnet *net.IPNet, gwMAC net.Hardw uint8(71), []*ofTestUtils.ExpectFlow{ { - MatchStr: fmt.Sprintf("priority=190,ct_state=+new+trk,%s,reg0=0/0xffff", ipProtoStr), + MatchStr: fmt.Sprintf("priority=190,ct_state=+new+trk,%s,reg0=0/0xf", ipProtoStr), ActStr: "drop", }, { diff --git a/test/integration/ovs/ofctrl_test.go b/test/integration/ovs/ofctrl_test.go index 6f9cbbdd491..292cb08c837 100644 --- a/test/integration/ovs/ofctrl_test.go +++ b/test/integration/ovs/ofctrl_test.go @@ -41,17 +41,14 @@ var ( priorityNormal = uint16(200) - portFoundMark = uint32(0x1) - portCacheReg = 1 + portFoundMark = binding.NewRegMark(0, 1, 16, 16) + portCacheField = binding.NewRegField(1, 0, 31) + fromLocalMark = binding.NewRegMark(0, 2, 0, 15) + fromGatewayMark = binding.NewRegMark(0, 1, 0, 15) - marksReg = 0 - markTrafficFromLocal = uint32(2) - markTrafficFromGateway = uint32(1) - gatewayCTMark = uint32(0x20) - ctZone = 0xfff0 - - ofportRegRange = binding.Range{0, 31} - ofportMarkRange = binding.Range{16, 16} + marksReg = 0 + gatewayCTMark = binding.NewCtMark(0x20, 0, 7) + ctZone = 0xfff0 count uint64 @@ -284,7 +281,8 @@ func TestOFctrlGroup(t *testing.T) { bucketBuilder = bucketBuilder.ResubmitToTable(bucket.resubmitTable) } for _, loading := range bucket.reg2reg { - bucketBuilder = bucketBuilder.LoadRegRange(int(loading[0]), loading[1], [2]uint32{loading[2], loading[3]}) + regField := binding.NewRegField(int(loading[0]), loading[2], loading[3]) + bucketBuilder = bucketBuilder.LoadToRegField(regField, loading[1]) } group = bucketBuilder.Done() } @@ -516,24 +514,28 @@ func TestBundleWithGroupAndFlow(t *testing.T) { ovsCtlClient := ovsctl.NewClient(br) groupID := binding.GroupIDType(4) + field1 := binding.NewRegField(1, 0, 31) + field2 := binding.NewRegField(2, 0, 31) + field3 := binding.NewRegField(3, 0, 31) group := bridge.CreateGroup(groupID). Bucket().Weight(100). - LoadReg(1, uint32(0xa0a0002)). - LoadReg(2, uint32(0x35)). - LoadReg(3, uint32(0xfff1)). + LoadToRegField(field1, uint32(0xa0a0002)). + LoadToRegField(field2, uint32(0x35)). + LoadToRegField(field3, uint32(0xfff1)). ResubmitToTable(table.GetNext()).Done(). Bucket().Weight(100). - LoadReg(1, uint32(0xa0a0202)). - LoadReg(2, uint32(0x35)). - LoadReg(3, uint32(0xfff1)). + LoadToRegField(field1, uint32(0xa0a0202)). + LoadToRegField(field2, uint32(0x35)). + LoadToRegField(field3, uint32(0xfff1)). ResubmitToTable(table.GetNext()).Done() + reg3Field := binding.NewRegField(3, 0, 31) flow := table.BuildFlow(priorityNormal). Cookie(getCookieID()). MatchProtocol(binding.ProtocolTCP). MatchDstIP(net.ParseIP("10.96.0.10")). MatchDstPort(uint16(53), nil). - MatchReg(3, uint32(0xfff2)). + MatchRegFieldWithValue(reg3Field, uint32(0xfff2)). Action().Group(groupID).Done() expectedFlows := []*ExpectFlow{ { @@ -583,9 +585,9 @@ func TestPacketOutIn(t *testing.T) { srcPort := uint16(10001) dstPort := uint16(8080) reg2Data := uint32(0x1234) - reg2Range := binding.Range{0, 15} + reg2Field := binding.NewRegField(2, 0, 15) reg3Data := uint32(0x1234) - reg3Range := binding.Range{0, 31} + reg3Field := binding.NewRegField(3, 0, 31) stopCh := make(chan struct{}) go func() { @@ -598,7 +600,7 @@ func TestPacketOutIn(t *testing.T) { assert.NotNil(t, reg2Value) value2, ok2 := reg2Value.(*ofctrl.NXRegister) assert.True(t, ok2) - assert.Equal(t, reg2Data, ofctrl.GetUint32ValueWithRange(value2.Data, reg2Range.ToNXRange())) + assert.Equal(t, reg2Data, ofctrl.GetUint32ValueWithRange(value2.Data, reg2Field.GetRange().ToNXRange())) reg3Match := matchers.GetMatchByName("NXM_NX_REG3") assert.NotNil(t, reg3Match) @@ -620,25 +622,26 @@ func TestPacketOutIn(t *testing.T) { }() pktBuilder := bridge.BuildPacketOut() + regField := binding.NewRegField(0, 18, 18) pkt := pktBuilder.SetSrcMAC(srcMAC).SetDstMAC(dstcMAC). SetDstIP(dstIP).SetSrcIP(srcIP).SetIPProtocol(binding.ProtocolTCP). SetTCPSrcPort(srcPort).SetTCPDstPort(dstPort). - AddLoadAction("NXM_NX_REG0", uint64(0x1), binding.Range{18, 18}). + AddLoadAction(regField.GetNXFieldName(), uint64(0x1), regField.GetRange()). Done() require.Nil(t, err) flow0 := table0.BuildFlow(100). MatchSrcMAC(srcMAC).MatchDstMAC(dstcMAC). MatchSrcIP(srcIP).MatchDstIP(dstIP).MatchProtocol(binding.ProtocolTCP). - MatchRegRange(0, 0x1, binding.Range{18, 18}). - Action().LoadRegRange(2, reg2Data, reg2Range). - Action().LoadRegRange(3, reg3Data, reg3Range). + MatchRegFieldWithValue(regField, 0x1). + Action().LoadToRegField(reg2Field, reg2Data). + Action().LoadToRegField(reg3Field, reg3Data). Action().SetTunnelDst(tunDst). Action().ResubmitToTable(table0.GetNext()). Done() flow1 := table1.BuildFlow(100). MatchSrcMAC(srcMAC).MatchDstMAC(dstcMAC). MatchSrcIP(srcIP).MatchDstIP(dstIP).MatchProtocol(binding.ProtocolTCP). - MatchRegRange(0, 0x1, binding.Range{18, 18}). + MatchRegFieldWithValue(regField, 0x1). Action().SendToController(0x1). Done() err = bridge.AddFlowsInBundle([]binding.Flow{flow0, flow1}, nil, nil) @@ -835,11 +838,16 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { gwMACData, _ := strconv.ParseUint(strings.Replace(gwMAC.String(), ":", "", -1), 16, 64) _, peerSubnetIPv6, _ := net.ParseCIDR("fd74:ca9b:172:21::/64") tunnelPeerIPv6 := net.ParseIP("20:ca9b:172:35::3") + regField0 := binding.NewRegField(0, 0, 15) + mark0 := binding.NewRegMarkWithField(regField0, 0x0fff) + regField1 := binding.NewRegField(0, 16, 31) + mark1 := binding.NewRegMarkWithField(regField1, 0x0ffe) + //gatewayCTMark := binding.NewCtMark() flows = append(flows, table.BuildFlow(priorityNormal-10). Cookie(getCookieID()). MatchInPort(podOFport). - Action().LoadRegRange(int(marksReg), markTrafficFromLocal, binding.Range{0, 15}). + Action().LoadRegMark(fromLocalMark). Action().GotoTable(table.GetNext()). Done(), table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). @@ -877,9 +885,9 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { Action().Learn(table.GetID(), priorityNormal-10, 10, 0, 1). DeleteLearned(). MatchLearnedTCPDstPort(). - MatchReg(0, 0x0fff, binding.Range{0, 15}). - LoadRegToReg(0, 0, binding.Range{0, 15}, binding.Range{0, 15}). - LoadReg(0, 0x0ffe, binding.Range{16, 31}). + MatchRegMark(mark0). + LoadFieldToField(regField0, regField0). + LoadRegMark(mark1). Done(). // Finish learn action. Action().ResubmitToTable(table.GetID()). Done(), @@ -889,26 +897,26 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { Done(), table.BuildFlow(priorityNormal+10).MatchProtocol(binding.ProtocolIP). Cookie(getCookieID()). - MatchRegRange(int(marksReg), markTrafficFromGateway, binding.Range{0, 15}). - MatchCTMark(gatewayCTMark, nil). + MatchRegMark(fromGatewayMark). + MatchCTMarkData(gatewayCTMark). MatchCTStateNew(false).MatchCTStateTrk(true). Action().GotoTable(table.GetNext()). Done(), table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). Cookie(getCookieID()). - MatchRegRange(int(marksReg), markTrafficFromGateway, binding.Range{0, 15}). + MatchRegMark(fromGatewayMark). MatchCTStateNew(true).MatchCTStateTrk(true). Action().CT( true, table.GetNext(), ctZone). - LoadToMark(uint32(gatewayCTMark)).CTDone(). + LoadToCtMark(gatewayCTMark).CTDone(). Done(), table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). Cookie(getCookieID()). - MatchCTMark(gatewayCTMark, nil). + MatchCTMarkData(gatewayCTMark). MatchCTStateNew(false).MatchCTStateTrk(true). - Action().LoadRange(binding.NxmFieldDstMAC, gwMACData, binding.Range{0, 47}). + Action().LoadRange(binding.NxmFieldDstMAC, gwMACData, &binding.Range{0, 47}). Action().GotoTable(table.GetNext()). Done(), table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). @@ -957,15 +965,15 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { table.BuildFlow(priorityNormal). Cookie(getCookieID()). MatchDstMAC(podMAC). - Action().LoadRegRange(portCacheReg, podOFport, ofportRegRange). - Action().LoadRegRange(int(marksReg), portFoundMark, ofportMarkRange). + Action().LoadToRegField(portCacheField, podOFport). + Action().LoadRegMark(portFoundMark). Action().GotoTable(table.GetNext()). Done(), table.BuildFlow(priorityNormal). Cookie(getCookieID()). MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), portFoundMark, ofportMarkRange). - Action().OutputRegRange(int(portCacheReg), ofportRegRange). + MatchRegMark(portFoundMark). + Action().OutputToRegField(portCacheField). Done(), table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). Cookie(getCookieID()). MatchDstIPNet(*serviceCIDR). @@ -986,7 +994,7 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { Action().Conjunction(uint32(1001), uint8(2), uint8(3)).Done(), table.BuildFlow(priorityNormal+20).MatchProtocol(binding.ProtocolIP).Cookie(getCookieID()).MatchSrcIPNet(*AllIPs). Action().Conjunction(uint32(1001), uint8(1), uint8(3)).Done(), - table.BuildFlow(priorityNormal+20).MatchProtocol(binding.ProtocolIP).Cookie(getCookieID()).MatchRegRange(int(portCacheReg), podOFport, ofportRegRange). + table.BuildFlow(priorityNormal+20).MatchProtocol(binding.ProtocolIP).Cookie(getCookieID()).MatchRegFieldWithValue(portCacheField, podOFport). Action().Conjunction(uint32(1001), uint8(2), uint8(3)).Done(), table.BuildFlow(priorityNormal+20).MatchProtocol(binding.ProtocolIP).Cookie(getCookieID()).MatchConjID(1001). Action().GotoTable(table.GetNext()).Done(), @@ -1004,9 +1012,9 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { &ExpectFlow{"priority=190,arp", "NORMAL"}, &ExpectFlow{"priority=200,tcp", fmt.Sprintf("learn(table=%d,idle_timeout=10,priority=190,delete_learned,cookie=0x1,eth_type=0x800,nw_proto=6,NXM_OF_TCP_DST[],NXM_NX_REG0[0..15]=0xfff,load:NXM_NX_REG0[0..15]->NXM_NX_REG0[0..15],load:0xffe->NXM_NX_REG0[16..31]),resubmit(,%d)", table.GetID(), table.GetID())}, &ExpectFlow{"priority=200,ip", fmt.Sprintf("ct(table=%d,zone=65520)", table.GetNext())}, - &ExpectFlow{"priority=210,ct_state=-new+trk,ct_mark=0x20,ip,reg0=0x1/0xffff", gotoTableAction}, - &ExpectFlow{"priority=200,ct_state=+new+trk,ip,reg0=0x1/0xffff", fmt.Sprintf("ct(commit,table=%d,zone=65520,exec(load:0x20->NXM_NX_CT_MARK[])", table.GetNext())}, - &ExpectFlow{"priority=200,ct_state=-new+trk,ct_mark=0x20,ip", fmt.Sprintf("load:0xaaaaaaaaaa11->NXM_OF_ETH_DST[],%s", gotoTableAction)}, + &ExpectFlow{"priority=210,ct_state=-new+trk,ct_mark=0x20/0xff,ip,reg0=0x1/0xffff", gotoTableAction}, + &ExpectFlow{"priority=200,ct_state=+new+trk,ip,reg0=0x1/0xffff", fmt.Sprintf("ct(commit,table=%d,zone=65520,exec(load:0x20->NXM_NX_CT_MARK[0..7])", table.GetNext())}, + &ExpectFlow{"priority=200,ct_state=-new+trk,ct_mark=0x20/0xff,ip", fmt.Sprintf("load:0xaaaaaaaaaa11->NXM_OF_ETH_DST[],%s", gotoTableAction)}, &ExpectFlow{"priority=200,ct_state=+new+inv,ip", "drop"}, &ExpectFlow{"priority=190,ct_state=+new+trk,ip", fmt.Sprintf("ct(commit,table=%d,zone=65520)", table.GetNext())}, &ExpectFlow{"priority=200,ip,dl_dst=aa:bb:cc:dd:ee:ff,nw_dst=192.168.1.3", fmt.Sprintf("set_field:aa:aa:aa:aa:aa:11->eth_src,set_field:aa:aa:aa:aa:aa:13->eth_dst,dec_ttl,%s", gotoTableAction)}, @@ -1034,12 +1042,11 @@ func prepareNATflows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { natedIP2 := net.ParseIP("10.10.0.10") natIPRange1 := &binding.IPRange{StartIP: natedIP1, EndIP: natedIP1} natIPRange2 := &binding.IPRange{StartIP: natedIP1, EndIP: natedIP2} - snatCTMark := uint32(0x40) - natRequireMark := uint32(0x1) - snatMarkRange1 := binding.Range{17, 17} - snatMarkRange2 := binding.Range{18, 18} - dnatMarkRange1 := binding.Range{19, 19} - dnatMarkRange2 := binding.Range{20, 20} + snatCTMark := binding.NewCtMark(0x40, 0, 7) + snatMark1 := binding.NewRegMark(marksReg, 1, 17, 17) + snatMark2 := binding.NewRegMark(marksReg, 1, 18, 18) + dnatMark1 := binding.NewRegMark(marksReg, 1, 19, 19) + dnatMark2 := binding.NewRegMark(marksReg, 1, 20, 20) flows := []binding.Flow{ table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). Action().CT(false, table.GetNext(), ctZone).NAT().CTDone(). @@ -1047,34 +1054,34 @@ func prepareNATflows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { Done(), table.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(marksReg, natRequireMark, snatMarkRange1). + MatchRegMark(snatMark1). Action().CT(true, table.GetNext(), ctZone). SNAT(natIPRange1, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(getCookieID()). Done(), table.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(marksReg, natRequireMark, snatMarkRange2). + MatchRegMark(snatMark2). Action().CT(true, table.GetNext(), ctZone). SNAT(natIPRange2, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(getCookieID()). Done(), table.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(marksReg, natRequireMark, dnatMarkRange1). + MatchRegMark(dnatMark1). Action().CT(true, table.GetNext(), ctZone). DNAT(natIPRange1, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(getCookieID()). Done(), table.BuildFlow(priorityNormal). MatchProtocol(binding.ProtocolIP). - MatchRegRange(marksReg, natRequireMark, dnatMarkRange2). + MatchRegMark(dnatMark2). Action().CT(true, table.GetNext(), ctZone). DNAT(natIPRange2, nil). - LoadToMark(snatCTMark).CTDone(). + LoadToCtMark(snatCTMark).CTDone(). Cookie(getCookieID()). Done(), } @@ -1082,19 +1089,19 @@ func prepareNATflows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { flowStrs := []*ExpectFlow{ {"priority=200,ip", fmt.Sprintf("ct(table=%d,zone=65520,nat)", table.GetNext())}, {"priority=200,ip,reg0=0x20000/0x20000", - fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(src=%s),exec(load:0x40->NXM_NX_CT_MARK[]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(src=%s),exec(load:0x40->NXM_NX_CT_MARK[0..7]))", table.GetNext(), natedIP1.String()), }, {"priority=200,ip,reg0=0x40000/0x40000", - fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(src=%s-%s),exec(load:0x40->NXM_NX_CT_MARK[]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(src=%s-%s),exec(load:0x40->NXM_NX_CT_MARK[0..7]))", table.GetNext(), natedIP1.String(), natedIP2.String()), }, {"priority=200,ip,reg0=0x80000/0x80000", - fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(dst=%s),exec(load:0x40->NXM_NX_CT_MARK[]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(dst=%s),exec(load:0x40->NXM_NX_CT_MARK[0..7]))", table.GetNext(), natedIP1.String()), }, {"priority=200,ip,reg0=0x100000/0x100000", - fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(dst=%s-%s),exec(load:0x40->NXM_NX_CT_MARK[]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(dst=%s-%s),exec(load:0x40->NXM_NX_CT_MARK[0..7]))", table.GetNext(), natedIP1.String(), natedIP2.String()), }, }