diff --git a/docs/antctl.md b/docs/antctl.md index 2cb7700d3a2..bfff9ec60c7 100644 --- a/docs/antctl.md +++ b/docs/antctl.md @@ -282,10 +282,10 @@ Example outputs of dumping Pod and NetworkPolicy OVS flows: # Dump OVS flows of Pod "coredns-6955765f44-zcbwj" $ antctl get of -p coredns-6955765f44-zcbwj -n kube-system FLOW -table=classification, n_packets=513122, n_bytes=42615080, priority=190,in_port="coredns--d0c58e" actions=load:0x2->NXM_NX_REG0[0..15],resubmit(,10) +table=classification, n_packets=513122, n_bytes=42615080, priority=190,in_port="coredns--d0c58e" actions=set_field:0x2/0xffff->reg0,resubmit(,10) table=10, n_packets=513122, n_bytes=42615080, priority=200,ip,in_port="coredns--d0c58e",dl_src=52:bd:c6:e0:eb:c1,nw_src=172.100.1.7 actions=resubmit(,30) table=10, n_packets=0, n_bytes=0, priority=200,arp,in_port="coredns--d0c58e",arp_spa=172.100.1.7,arp_sha=52:bd:c6:e0:eb:c1 actions=resubmit(,20) -table=80, n_packets=556468, n_bytes=166477824, priority=200,dl_dst=52:bd:c6:e0:eb:c1 actions=load:0x5->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],resubmit(,90) +table=80, n_packets=556468, n_bytes=166477824, priority=200,dl_dst=52:bd:c6:e0:eb:c1 actions=load:0x5->NXM_NX_REG1[],set_field:0x10000/0x10000->reg0,resubmit(,90) table=70, n_packets=0, n_bytes=0, priority=200,ip,dl_dst=aa:bb:cc:dd:ee:ff,nw_dst=172.100.1.7 actions=set_field:62:39:b4:e8:05:76->eth_src,set_field:52:bd:c6:e0:eb:c1->eth_dst,dec_ttl,resubmit(,80) # Get NetworkPolicies applied to Pod "coredns-6955765f44-zcbwj" @@ -378,8 +378,8 @@ result: | dec_ttl resubmit(,80) 80. dl_dst=52:bd:c6:e0:eb:c1, priority 200, cookie 0x5e030000000000 - load:0x5->NXM_NX_REG1[] - load:0x1->NXM_NX_REG0[16] + set_field:0x5->reg1 + set_field:0x10000/0x10000->reg0 resubmit(,90) 90. conj_id=2,ip, priority 190, cookie 0x5e050000000000 resubmit(,105) diff --git a/docs/design/ovs-pipeline.md b/docs/design/ovs-pipeline.md index 30e78058f6a..9d6a434fa9c 100644 --- a/docs/design/ovs-pipeline.md +++ b/docs/design/ovs-pipeline.md @@ -234,10 +234,10 @@ should be performed for the packet in [L3ForwardingTable]. If you dump the flows for this table, you may see the following: ```text -1. table=0, priority=200,in_port=2 actions=load:0x1->NXM_NX_REG0[0..3],resubmit(,10) -2. table=0, priority=200,in_port=1 actions=load:0->NXM_NX_REG0[0..3],load:0x1->NXM_NX_REG0[19],resubmit(,30) -3. table=0, priority=190,in_port=4 actions=load:0x2->NXM_NX_REG0[0..3],resubmit(,10) -4. table=0, priority=190,in_port=3 actions=load:0x2->NXM_NX_REG0[0..3],resubmit(,10) +1. table=0, priority=200,in_port=2 actions=set_field:0x1/0xf->reg0,resubmit(,10) +2. table=0, priority=200,in_port=1 actions=set_field:0/0xf->reg0,load:0x1->NXM_NX_REG0[19],resubmit(,30) +3. table=0, priority=190,in_port=4 actions=set_field:0x2/0xf->reg0,resubmit(,10) +4. table=0, priority=190,in_port=3 actions=set_field:0x2/0xf->reg0,resubmit(,10) 5. table=0, priority=0 actions=drop ``` @@ -305,7 +305,7 @@ address for all the traffic being tunnelled. If you dump the flows for this table, you may see the following: ```text -1. table=20, priority=200,arp,arp_tpa=10.10.1.1,arp_op=1 actions=move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],mod_dl_src:aa:bb:cc:dd:ee:ff,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],load:0xaabbccddeeff->NXM_NX_ARP_SHA[],move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],load:0xa0a0101->NXM_OF_ARP_SPA[],IN_PORT +1. table=20, priority=200,arp,arp_tpa=10.10.1.1,arp_op=1 actions=move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],mod_dl_src:aa:bb:cc:dd:ee:ff,set_field:2->arp_op,move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],load:0xaabbccddeeff->NXM_NX_ARP_SHA[],move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],load:0xa0a0101->NXM_OF_ARP_SPA[],IN_PORT 2. table=20, priority=190,arp actions=NORMAL 3. table=20, priority=0 actions=drop ``` @@ -781,7 +781,7 @@ table=70, priority=210,ct_state=+rpl+trk,ct_mark=0x20,ip actions=mod_dl_dst:e2:e For a given peer Node, the flow may look like this: ```text -table=70, priority=200,ip,nw_dst=10.10.1.0/24 actions=mod_dl_src:e2:e5:a4:9b:1c:b1,mod_dl_dst:aa:bb:cc:dd:ee:ff,load:0x1->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],load:0xc0a80102->NXM_NX_TUN_IPV4_DST[],goto_table:72 +table=70, priority=200,ip,nw_dst=10.10.1.0/24 actions=mod_dl_src:e2:e5:a4:9b:1c:b1,mod_dl_dst:aa:bb:cc:dd:ee:ff,load:0x1->NXM_NX_REG1[],set_field:0x10000/0x10000->reg0,load:0xc0a80102->NXM_NX_TUN_IPV4_DST[],goto_table:72 ``` If none of the flows described above are hit, traffic goes directly to @@ -842,7 +842,7 @@ the right SNAT IP (Antrea Agent adds an iptables SNAT rule for each local SNAT IP that matches the ID). ```text -table=71, priority=200,ct_state=+new+trk,ip,in_port="pod1-7e503a" actions=load:0x1->NXM_NX_PKT_MARK[0..7],goto_table:80 +table=71, priority=200,ct_state=+new+trk,ip,in_port="pod1-7e503a" actions=set_field:0x1/0xff->pkt_mark,goto_table:80 ``` When the SNAT IP of the Egress is on a remote Node, the flow will tunnel the @@ -853,7 +853,7 @@ destination MAC addresses, load the SNAT IP to NXM_NX_TUN_IPV4_DST, and send the packets to [L3DecTTLTable]. ```text -table=71, priority=200,ct_state=+new+trk,ip,in_port="pod2-357c21" actions=mod_dl_src:e2:e5:a4:9b:1c:b1,mod_dl_dst:aa:bb:cc:dd:ee:ff,load:0x1->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],load:0xc0a80a66->NXM_NX_TUN_IPV4_DST[],goto_table:72 +table=71, priority=200,ct_state=+new+trk,ip,in_port="pod2-357c21" actions=mod_dl_src:e2:e5:a4:9b:1c:b1,mod_dl_dst:aa:bb:cc:dd:ee:ff,load:0x1->NXM_NX_REG1[],set_field:0x10000/0x10000->reg0,load:0xc0a80a66->NXM_NX_TUN_IPV4_DST[],goto_table:72 ``` Last, when a SNAT IP configured for Egresses is on the local Node, an additional @@ -862,7 +862,7 @@ use the SNAT IP. The flow matches the tunnel destination IP (which should be equal to the SNAT IP), and sets the 8 bits ID of the SNAT IP to pkt_mark. ```text -table=71, priority=200,ct_state=+new+trk,ip,tun_dst="192.168.10.101" actions=load:0x1->NXM_NX_PKT_MARK[0..7],goto_table:80 +table=71, priority=200,ct_state=+new+trk,ip,tun_dst="192.168.10.101" actions=set_field:0x1/0xff->pkt_mark,goto_table:80 ``` ### L3DecTTLTable (72) @@ -891,10 +891,10 @@ port (tunnel port, gateway port, and local Pod ports), as you can see if you dump the flows: ```text -1. table=80, priority=200,dl_dst=aa:bb:cc:dd:ee:ff actions=load:0x1->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],goto_table:105 -2. table=80, priority=200,dl_dst=e2:e5:a4:9b:1c:b1 actions=load:0x2->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],goto_table:105 -3. table=80, priority=200,dl_dst=12:9e:a6:47:d0:70 actions=load:0x3->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],goto_table:90 -4. table=80, priority=200,dl_dst=ba:a8:13:ca:ed:cf actions=load:0x4->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],goto_table:90 +1. table=80, priority=200,dl_dst=aa:bb:cc:dd:ee:ff actions=set_field:0x1->reg1,set_field:0x10000/0x10000->reg0,goto_table:105 +2. table=80, priority=200,dl_dst=e2:e5:a4:9b:1c:b1 actions=set_field:0x2->reg1,set_field:0x10000/0x10000->reg0,goto_table:105 +3. table=80, priority=200,dl_dst=12:9e:a6:47:d0:70 actions=set_field:0x3->reg1,set_field:0x10000/0x10000->reg0,goto_table:90 +4. table=80, priority=200,dl_dst=ba:a8:13:ca:ed:cf actions=set_field:0x4->reg1,set_field:0x10000/0x10000->reg0,goto_table:90 5. table=80, priority=0 actions=goto_table:105 ``` @@ -1149,7 +1149,7 @@ across the different backends for each Service. If you dump the flows for this table, you should see something like this: ```text -1. table=40, priority=200,ip,nw_dst=10.96.0.0/12 actions=load:0x2->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],goto_table:105 +1. table=40, priority=200,ip,nw_dst=10.96.0.0/12 actions=set_field:0x2->reg1,load:0x1->NXM_NX_REG0[16],goto_table:105 2. table=40, priority=0 actions=goto_table:45 ``` diff --git a/docs/design/windows-design.md b/docs/design/windows-design.md index 0c935f991c2..1fb1cc0847a 100644 --- a/docs/design/windows-design.md +++ b/docs/design/windows-design.md @@ -160,7 +160,7 @@ table=70, priority=200,ip,nw_dst=$peerPodSubnet actions=mod_dl_dst:$peerNodeMAC, table=70, priority=200,ct_state=+rpl+trk,ip,nw_dst=$peerNodeIP actions=mod_dl_dst:$peerNodeMAC,resubmit(,80) L2ForwardingCalcTable: 80 -table=80, priority=200,dl_dst=$peerNodeMAC actions=load:$uplink->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],resubmit(,105) +table=80, priority=200,dl_dst=$peerNodeMAC actions=load:$uplink->NXM_NX_REG1[],set_field:0x10000/0x10000->reg0,resubmit(,105) ``` ### SNAT configuration diff --git a/go.mod b/go.mod index 2fa8263a3a1..cafc7a3b16f 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module antrea.io/antrea go 1.17 require ( - antrea.io/libOpenflow v0.6.2 - antrea.io/ofnet v0.5.7 + antrea.io/libOpenflow v0.8.0 + antrea.io/ofnet v0.6.0 github.com/ClickHouse/clickhouse-go v1.5.4 github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/Mellanox/sriovnet v1.1.0 diff --git a/go.sum b/go.sum index 11a4d536b82..c8c0d45da63 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -antrea.io/libOpenflow v0.6.2 h1:1JMSJ7Lp7yOhKybHey9VDtRI6JuIgkhUWJBX5GIFY9I= -antrea.io/libOpenflow v0.6.2/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o= -antrea.io/ofnet v0.5.7 h1:x0q0lZqp05wu01gk1+S5S15FmIpmTGPhi/z/aIDmuMw= -antrea.io/ofnet v0.5.7/go.mod h1:8TJVF6MLe9/gZ/KbhGUvULs9/TxssepEaYEe+o1SEgs= +antrea.io/libOpenflow v0.8.0 h1:Xm6mlSqdXtDD418nf1lndoDvMi8scqUan8pkEUZ2oas= +antrea.io/libOpenflow v0.8.0/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o= +antrea.io/ofnet v0.6.0 h1:XuZ1WjOd0R8nIdRG7bfCF1AryLLlaroFjrgnIDfR1Vg= +antrea.io/ofnet v0.6.0/go.mod h1:qWqi11pI3kBYcS9SYWm92ZOiOPBx04Jx21cDmJlJhOg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= diff --git a/pkg/agent/controller/networkpolicy/fqdn.go b/pkg/agent/controller/networkpolicy/fqdn.go index 1d9bbfa49ad..48a7eb3b70e 100644 --- a/pkg/agent/controller/networkpolicy/fqdn.go +++ b/pkg/agent/controller/networkpolicy/fqdn.go @@ -756,7 +756,11 @@ func (f *fqdnController) handlePacketIn(pktIn *ofctrl.PacketIn) error { f.onDNSResponseMsg(&dnsMsg, time.Now(), waitCh) } go func() { - switch ipPkt := pktIn.Data.Data.(type) { + ethernetPkt, err := getEthernetPacket(pktIn) + if err != nil { + return + } + switch ipPkt := ethernetPkt.Data.(type) { case *protocol.IPv4: switch dnsPkt := ipPkt.Data.(type) { case *protocol.UDP: @@ -789,7 +793,11 @@ func (f *fqdnController) sendDNSPacketout(pktIn *ofctrl.PacketIn) error { prot uint8 isIPv6 bool ) - switch ipPkt := pktIn.Data.Data.(type) { + ethernetPkt, err := getEthernetPacket(pktIn) + if err != nil { + return err + } + switch ipPkt := ethernetPkt.Data.(type) { case *protocol.IPv4: srcIP = ipPkt.NWSrc.String() dstIP = ipPkt.NWDst.String() @@ -820,7 +828,7 @@ func (f *fqdnController) sendDNSPacketout(pktIn *ofctrl.PacketIn) error { inPort = inPortField.GetValue().(uint32) } } - udpSrcPort, udpDstPort, err := binding.GetUDPHeaderData(pktIn.Data.Data) + udpSrcPort, udpDstPort, err := binding.GetUDPHeaderData(ethernetPkt.Data) if err != nil { klog.ErrorS(err, "Failed to get UDP header data") return err @@ -829,8 +837,8 @@ func (f *fqdnController) sendDNSPacketout(pktIn *ofctrl.PacketIn) error { return packetOutBuilder.AddLoadRegMark(openflow.CustomReasonDNSRegMark) } return f.ofClient.SendUDPPacketOut( - pktIn.Data.HWSrc.String(), - pktIn.Data.HWDst.String(), + ethernetPkt.HWSrc.String(), + ethernetPkt.HWDst.String(), srcIP, dstIP, inPort, diff --git a/pkg/agent/controller/networkpolicy/packetin.go b/pkg/agent/controller/networkpolicy/packetin.go index 634520f3c75..b14942149d3 100644 --- a/pkg/agent/controller/networkpolicy/packetin.go +++ b/pkg/agent/controller/networkpolicy/packetin.go @@ -20,7 +20,9 @@ import ( "net" "time" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" + "antrea.io/libOpenflow/protocol" + "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" "github.com/vmware/go-ipfix/pkg/registry" "k8s.io/klog/v2" @@ -70,7 +72,7 @@ func (c *Controller) HandlePacketIn(pktIn *ofctrl.PacketIn) error { // getMatchRegField returns match to the regNum register. func getMatchRegField(matchers *ofctrl.Matchers, field *binding.RegField) *ofctrl.MatchField { - return matchers.GetMatchByName(field.GetNXFieldName()) + return openflow.GetMatchFieldByRegID(matchers, field.GetRegID()) } // getMatch receives ofctrl matchers and table id, match field. @@ -95,7 +97,7 @@ func getMatch(matchers *ofctrl.Matchers, tableID uint8, disposition uint32) *ofc } // getInfoInReg unloads and returns data stored in the match field. -func getInfoInReg(regMatch *ofctrl.MatchField, rng *openflow13.NXRange) (uint32, error) { +func getInfoInReg(regMatch *ofctrl.MatchField, rng *openflow15.NXRange) (uint32, error) { regValue, ok := regMatch.GetValue().(*ofctrl.NXRegister) if !ok { return 0, errors.New("register value cannot be retrieved") @@ -208,3 +210,11 @@ func isAntreaPolicyEgressTable(tableID uint8) bool { } return false } + +func getEthernetPacket(pktIn *ofctrl.PacketIn) (*protocol.Ethernet, error) { + ethernetPkt := new(protocol.Ethernet) + if err := ethernetPkt.UnmarshalBinary(pktIn.Data.(*util.Buffer).Bytes()); err != nil { + return nil, fmt.Errorf("failed to parse ethernet packet from packet-in message: %v", err) + } + return ethernetPkt, nil +} diff --git a/pkg/agent/controller/networkpolicy/reject.go b/pkg/agent/controller/networkpolicy/reject.go index 5c5e4690b18..687a166f465 100644 --- a/pkg/agent/controller/networkpolicy/reject.go +++ b/pkg/agent/controller/networkpolicy/reject.go @@ -18,7 +18,7 @@ import ( "encoding/binary" "fmt" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" "antrea.io/ofnet/ofctrl" @@ -83,8 +83,12 @@ const ( // packet-in message. func (c *Controller) rejectRequest(pktIn *ofctrl.PacketIn) error { // Get ethernet data. - srcMAC := pktIn.Data.HWDst.String() - dstMAC := pktIn.Data.HWSrc.String() + ethernetPkt, err := getEthernetPacket(pktIn) + if err != nil { + return err + } + srcMAC := ethernetPkt.HWDst.String() + dstMAC := ethernetPkt.HWSrc.String() var ( srcIP string @@ -92,7 +96,7 @@ func (c *Controller) rejectRequest(pktIn *ofctrl.PacketIn) error { proto uint8 isIPv6 bool ) - switch ipPkt := pktIn.Data.Data.(type) { + switch ipPkt := ethernetPkt.Data.(type) { case *protocol.IPv4: // Get IP data. srcIP = ipPkt.NWDst.String() @@ -152,17 +156,17 @@ func (c *Controller) rejectRequest(pktIn *ofctrl.PacketIn) error { } tunPort := c.tunPort if tunPort == 0 { - // openflow13.P_CONTROLLER is used with noEncap mode when tunnel interface is not found. - // It won't cause a loop with openflow13.P_CONTROLLER because it is used as the input port but not output port + // openflow15.P_CONTROLLER is used with noEncap mode when tunnel interface is not found. + // It won't cause a loop with openflow15.P_CONTROLLER because it is used as the input port but not output port // in the packet out message. - tunPort = uint32(openflow13.P_CONTROLLER) + tunPort = uint32(openflow15.P_CONTROLLER) } inPort, outPort := getRejectOFPorts(packetOutType, sIface, dIface, c.gwPort, tunPort) mutateFunc := getRejectPacketOutMutateFunc(packetOutType) if proto == protocol.Type_TCP { // Get TCP data. - oriTCPSrcPort, oriTCPDstPort, oriTCPSeqNum, _, _, err := binding.GetTCPHeaderData(pktIn.Data.Data) + oriTCPSrcPort, oriTCPDstPort, oriTCPSeqNum, _, _, err := binding.GetTCPHeaderData(ethernetPkt.Data) if err != nil { return err } @@ -191,7 +195,7 @@ func (c *Controller) rejectRequest(pktIn *ofctrl.PacketIn) error { icmpCode = ICMPv6DstAdminProhibitedCode ipHdrLen = IPv6HdrLen } - ipHdr, _ := pktIn.Data.Data.MarshalBinary() + ipHdr, _ := ethernetPkt.Data.MarshalBinary() icmpData := make([]byte, int(ICMPUnusedHdrLen+ipHdrLen+8)) // Put ICMP unused header in Data prop and set it to zero. binary.BigEndian.PutUint32(icmpData[:ICMPUnusedHdrLen], 0) diff --git a/pkg/agent/controller/traceflow/packetin.go b/pkg/agent/controller/traceflow/packetin.go index 5ce9ef931c3..f60bca25def 100644 --- a/pkg/agent/controller/traceflow/packetin.go +++ b/pkg/agent/controller/traceflow/packetin.go @@ -21,8 +21,9 @@ import ( "net" "time" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" + "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/util/retry" @@ -39,8 +40,7 @@ func (c *Controller) HandlePacketIn(pktIn *ofctrl.PacketIn) error { } oldTf, nodeResult, packet, err := c.parsePacketIn(pktIn) if err != nil { - klog.Errorf("parsePacketIn error: %+v", err) - return err + return fmt.Errorf("parsePacketIn error: %v", err) } // Retry when update CRD conflict which caused by multiple agents updating one CRD at same time. @@ -64,9 +64,9 @@ func (c *Controller) HandlePacketIn(pktIn *ofctrl.PacketIn) error { return nil }) if err != nil { - klog.Errorf("Update traceflow error: %+v", err) + return fmt.Errorf("update traceflow error: %v", err) } - return err + return nil } func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Traceflow, *crdv1alpha1.NodeResult, *crdv1alpha1.Packet, error) { @@ -77,8 +77,12 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl var err error var tag uint8 var ctNwDst, ctNwSrc, ipDst, ipSrc string - if pktIn.Data.Ethertype == protocol.IPv4_MSG { - ipPacket, ok := pktIn.Data.Data.(*protocol.IPv4) + etherData := new(protocol.Ethernet) + if err := etherData.UnmarshalBinary(pktIn.Data.(*util.Buffer).Bytes()); err != nil { + return nil, nil, nil, fmt.Errorf("failed to parse Ethernet packet from packet-in message: %v", err) + } + if etherData.Ethertype == protocol.IPv4_MSG { + ipPacket, ok := etherData.Data.(*protocol.IPv4) if !ok { return nil, nil, nil, errors.New("invalid traceflow IPv4 packet") } @@ -93,8 +97,8 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } ipDst = ipPacket.NWDst.String() ipSrc = ipPacket.NWSrc.String() - } else if pktIn.Data.Ethertype == protocol.IPv6_MSG { - ipv6Packet, ok := pktIn.Data.Data.(*protocol.IPv6) + } else if etherData.Ethertype == protocol.IPv6_MSG { + ipv6Packet, ok := etherData.Data.(*protocol.IPv6) if !ok { return nil, nil, nil, errors.New("invalid traceflow IPv6 packet") } @@ -110,7 +114,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl ipDst = ipv6Packet.NWDst.String() ipSrc = ipv6Packet.NWSrc.String() } else { - return nil, nil, nil, fmt.Errorf("unsupported traceflow packet Ethertype: %d", pktIn.Data.Ethertype) + return nil, nil, nil, fmt.Errorf("unsupported traceflow packet Ethertype: %d", etherData.Ethertype) } firstPacket := false @@ -246,7 +250,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } } gatewayIP := c.nodeConfig.GatewayConfig.IPv4 - if pktIn.Data.Ethertype == protocol.IPv6_MSG { + if etherData.Ethertype == protocol.IPv6_MSG { gatewayIP = c.nodeConfig.GatewayConfig.IPv6 } gwPort := c.nodeConfig.GatewayConfig.OFPort @@ -274,7 +278,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl } func getMatchRegField(matchers *ofctrl.Matchers, field *binding.RegField) *ofctrl.MatchField { - return matchers.GetMatchByName(field.GetNXFieldName()) + return openflow.GetMatchFieldByRegID(matchers, field.GetRegID()) } func getMatchTunnelDstField(matchers *ofctrl.Matchers, isIPv6 bool) *ofctrl.MatchField { @@ -284,7 +288,7 @@ func getMatchTunnelDstField(matchers *ofctrl.Matchers, isIPv6 bool) *ofctrl.Matc return matchers.GetMatchByName("NXM_NX_TUN_IPV4_DST") } -func getRegValue(regMatch *ofctrl.MatchField, rng *openflow13.NXRange) (uint32, error) { +func getRegValue(regMatch *ofctrl.MatchField, rng *openflow15.NXRange) (uint32, error) { regValue, ok := regMatch.GetValue().(*ofctrl.NXRegister) if !ok { return 0, errors.New("register value cannot be got") diff --git a/pkg/agent/controller/traceflow/packetin_test.go b/pkg/agent/controller/traceflow/packetin_test.go index 8f01e33524d..c2a5eb92870 100644 --- a/pkg/agent/controller/traceflow/packetin_test.go +++ b/pkg/agent/controller/traceflow/packetin_test.go @@ -171,7 +171,11 @@ func TestParseCapturedPacket(t *testing.T) { if tt.isIPv6 { ethType = uint16(protocol.IPv6_MSG) } - pktIn := ofctrl.PacketIn{Data: protocol.Ethernet{Ethertype: ethType, Data: tt.pktInData}} + etherPkt := protocol.NewEthernet() + etherPkt.Ethertype = ethType + etherPkt.Data = tt.pktInData + pktBytes, _ := etherPkt.MarshalBinary() + pktIn := ofctrl.PacketIn{Data: util.NewBuffer(pktBytes)} packet := parseCapturedPacket(&pktIn) assert.True(t, reflect.DeepEqual(packet, tt.pktCap), "parsed packet does not match the expected") }) diff --git a/pkg/agent/multicast/mcast_discovery.go b/pkg/agent/multicast/mcast_discovery.go index 648163dd367..240b8b66b72 100644 --- a/pkg/agent/multicast/mcast_discovery.go +++ b/pkg/agent/multicast/mcast_discovery.go @@ -21,7 +21,7 @@ import ( "sync" "time" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" @@ -73,9 +73,9 @@ type IGMPSnooper struct { } func (s *IGMPSnooper) HandlePacketIn(pktIn *ofctrl.PacketIn) error { - matches := pktIn.GetMatches() + matchers := pktIn.GetMatches() // Get custom reasons in this packet-in. - match := matches.GetMatchByName(openflow.CustomReasonField.GetNXFieldName()) + match := openflow.GetMatchFieldByRegID(matchers, openflow.CustomReasonField.GetRegID()) customReasons, err := getInfoInReg(match, openflow.CustomReasonField.GetRange().ToNXRange()) if err != nil { klog.ErrorS(err, "Received error while unloading customReason from OVS reg", "regField", openflow.CustomReasonField.GetName()) @@ -87,7 +87,7 @@ func (s *IGMPSnooper) HandlePacketIn(pktIn *ofctrl.PacketIn) error { return nil } -func getInfoInReg(regMatch *ofctrl.MatchField, rng *openflow13.NXRange) (uint32, error) { +func getInfoInReg(regMatch *ofctrl.MatchField, rng *openflow15.NXRange) (uint32, error) { regValue, ok := regMatch.GetValue().(*ofctrl.NXRegister) if !ok { return 0, errors.New("register value cannot be retrieved") @@ -268,7 +268,11 @@ func (s *IGMPSnooper) processPacketIn(pktIn *ofctrl.PacketIn) error { return err } } - igmp, err := parseIGMPPacket(pktIn.Data) + pktData := new(protocol.Ethernet) + if err := pktData.UnmarshalBinary(pktIn.Data.(*util.Buffer).Bytes()); err != nil { + return fmt.Errorf("failed to parse ethernet packet from packet-in message: %v", err) + } + igmp, err := parseIGMPPacket(*pktData) if err != nil { return err } @@ -285,7 +289,7 @@ func (s *IGMPSnooper) processPacketIn(pktIn *ofctrl.PacketIn) error { time: now, iface: iface, } - s.validatePacketAndNotify(event, igmpType, pktIn.Data) + s.validatePacketAndNotify(event, igmpType, *pktData) case protocol.IGMPv3Report: msg := igmp.(*protocol.IGMPv3MembershipReport) for _, gr := range msg.GroupRecords { @@ -302,7 +306,7 @@ func (s *IGMPSnooper) processPacketIn(pktIn *ofctrl.PacketIn) error { iface: iface, srcNode: srcNode, } - s.validatePacketAndNotify(event, igmpType, pktIn.Data) + s.validatePacketAndNotify(event, igmpType, *pktData) } case protocol.IGMPv2LeaveGroup: mgroup := igmp.(*protocol.IGMPv1or2).GroupAddress diff --git a/pkg/agent/multicast/mcast_discovery_test.go b/pkg/agent/multicast/mcast_discovery_test.go index 3af352277f3..620b69d7c34 100644 --- a/pkg/agent/multicast/mcast_discovery_test.go +++ b/pkg/agent/multicast/mcast_discovery_test.go @@ -19,7 +19,7 @@ import ( "sync" "testing" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" @@ -149,11 +149,11 @@ func TestIGMPRemoteReport(t *testing.T) { } func generatePacket(m util.Message, ofport uint32, srcNodeIP net.IP) ofctrl.PacketIn { - pkt := openflow13.NewPacketIn() - matchInport := openflow13.NewInPortField(ofport) + pkt := openflow15.NewPacketIn() + matchInport := openflow15.NewInPortField(ofport) pkt.Match.AddField(*matchInport) if srcNodeIP != nil { - matchTunSrc := openflow13.NewTunnelIpv4SrcField(srcNodeIP, nil) + matchTunSrc := openflow15.NewTunnelIpv4SrcField(srcNodeIP, nil) pkt.Match.AddField(*matchTunSrc) } ipPacket := &protocol.IPv4{ @@ -163,12 +163,13 @@ func generatePacket(m util.Message, ofport uint32, srcNodeIP net.IP) ofctrl.Pack Length: 20 + m.Len(), Data: m, } - pkt.Data = protocol.Ethernet{ - HWDst: pktInDstMAC, - HWSrc: pktInSrcMAC, - Ethertype: protocol.IPv4_MSG, - Data: ipPacket, - } + ethernetPkt := protocol.NewEthernet() + ethernetPkt.HWDst = pktInDstMAC + ethernetPkt.HWSrc = pktInSrcMAC + ethernetPkt.Ethertype = protocol.IPv4_MSG + ethernetPkt.Data = ipPacket + pktBytes, _ := ethernetPkt.MarshalBinary() + pkt.Data = util.NewBuffer(pktBytes) return ofctrl.PacketIn(*pkt) } diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go index 1f5fe3be0ab..648fcf0ceb4 100644 --- a/pkg/agent/openflow/client.go +++ b/pkg/agent/openflow/client.go @@ -19,7 +19,7 @@ import ( "math/rand" "net" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" ofutil "antrea.io/libOpenflow/util" v1 "k8s.io/api/core/v1" @@ -996,8 +996,7 @@ func (c *client) SendTraceflowPacket(dataplaneTag uint8, packet *binding.Packet, if outPort != -1 { packetOutBuilder = packetOutBuilder.SetOutport(uint32(outPort)) } - packetOutBuilder = packetOutBuilder.AddLoadAction(binding.NxmFieldIPToS, uint64(dataplaneTag), traceflowTagToSRange) - + packetOutBuilder = packetOutBuilder.AddSetIPTOSAction(dataplaneTag) packetOutObj := packetOutBuilder.Done() return c.bridge.SendPacketOut(packetOutObj) } @@ -1023,7 +1022,7 @@ func (c *client) UninstallTraceflowFlows(dataplaneTag uint8) error { return c.deleteFlows(c.featureTraceflow.cachedFlows, cacheKey) } -// Add TLV map optClass 0x0104, optType 0x80 optLength 4 tunMetadataIndex 0 to store data plane tag +// InitialTLVMap adds TLV map optClass 0x0104, optType 0x80 optLength 4 tunMetadataIndex 0 to store data plane tag // in tunnel. Data plane tag will be stored to NXM_NX_TUN_METADATA0[28..31] when packet get encapsulated // into geneve, and will be stored back to NXM_NX_REG9[28..31] when packet get decapsulated. func (c *client) InitialTLVMap() error { @@ -1272,7 +1271,7 @@ func (c *client) SendIGMPRemoteReportPacketOut( srcIP := c.nodeConfig.NodeTransportIPv4Addr.IP.String() dstMACStr := dstMAC.String() dstIPStr := dstIP.String() - packetOutBuilder, err := setBasePacketOutBuilder(c.bridge.BuildPacketOut(), srcMAC, dstMACStr, srcIP, dstIPStr, openflow13.P_CONTROLLER, 0) + packetOutBuilder, err := setBasePacketOutBuilder(c.bridge.BuildPacketOut(), srcMAC, dstMACStr, srcIP, dstIPStr, openflow15.P_CONTROLLER, 0) if err != nil { return err } diff --git a/pkg/agent/openflow/multicast.go b/pkg/agent/openflow/multicast.go index 5d3de4bd05f..f8f9cd2db30 100644 --- a/pkg/agent/openflow/multicast.go +++ b/pkg/agent/openflow/multicast.go @@ -19,7 +19,7 @@ import ( "net" "sync" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "k8s.io/klog/v2" "antrea.io/antrea/pkg/agent/config" @@ -194,14 +194,14 @@ func (f *featureMulticast) multicastRemoteReportFlows(groupID binding.GroupIDTyp MulticastRoutingTable.ofTable.BuildFlow(priorityHigh). Cookie(f.cookieAllocator.Request(f.category).Raw()). MatchProtocol(binding.ProtocolIGMP). - MatchInPort(openflow13.P_CONTROLLER). + MatchInPort(openflow15.P_CONTROLLER). Action().LoadRegMark(CustomReasonIGMPRegMark). Action().Group(groupID). Done(), // This flow ensures the IGMP report message sent from Antrea Agent to bypass the check in SpoofGuardTable. ClassifierTable.ofTable.BuildFlow(priorityNormal). Cookie(f.cookieAllocator.Request(f.category).Raw()). - MatchInPort(openflow13.P_CONTROLLER). + MatchInPort(openflow15.P_CONTROLLER). Action().GotoTable(SpoofGuardTable.GetNext()). Done(), // This flow ensures the multicast packet sent from a different Node via the tunnel port to enter Multicast diff --git a/pkg/agent/openflow/packetin.go b/pkg/agent/openflow/packetin.go index f157f8c3909..c0b88bfa5dc 100644 --- a/pkg/agent/openflow/packetin.go +++ b/pkg/agent/openflow/packetin.go @@ -15,8 +15,10 @@ package openflow import ( + "encoding/binary" "fmt" + "antrea.io/libOpenflow/openflow15" "antrea.io/ofnet/ofctrl" "golang.org/x/time/rate" "k8s.io/klog/v2" @@ -127,3 +129,23 @@ func (c *client) parsePacketIn(featurePacketIn *featureStartPacketIn) { } } } + +func GetMatchFieldByRegID(matchers *ofctrl.Matchers, regID int) *ofctrl.MatchField { + xregID := uint8(regID / 2) + startBit := 4 * (regID % 2) + f := matchers.GetMatch(openflow15.OXM_CLASS_PACKET_REGS, xregID) + if f == nil { + return nil + } + dataBytes := f.Value.(*openflow15.ByteArrayField).Data + data := binary.BigEndian.Uint32(dataBytes[startBit : startBit+4]) + var mask uint32 + if f.HasMask { + maskBytes, _ := f.Mask.MarshalBinary() + mask = binary.BigEndian.Uint32(maskBytes[startBit : startBit+4]) + } + if data == 0 && mask == 0 { + return nil + } + return &ofctrl.MatchField{MatchField: openflow15.NewRegMatchFieldWithMask(regID, data, mask)} +} diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go index b928ea13bef..bbfb4fab092 100644 --- a/pkg/agent/openflow/pipeline.go +++ b/pkg/agent/openflow/pipeline.go @@ -22,7 +22,7 @@ import ( "sync" "time" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" "antrea.io/ofnet/ofctrl" v1 "k8s.io/api/core/v1" @@ -370,10 +370,6 @@ var DispositionToString = map[uint32]string{ } var ( - // traceflowTagToSRange stores Traceflow dataplane tag to DSCP bits of - // IP header ToS field. - traceflowTagToSRange = binding.IPDSCPToSRange - // 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} @@ -2869,7 +2865,7 @@ func (f *featurePodConnectivity) hostBridgeLocalFlows() []binding.Flow { // hostBridgeUplinkVLANFlows generates the flows to match VLAN packets from uplink port. func (f *featurePodConnectivity) hostBridgeUplinkVLANFlows() []binding.Flow { - vlanMask := uint16(openflow13.OFPVID_PRESENT) + vlanMask := uint16(openflow15.OFPVID_PRESENT) return []binding.Flow{ VLANTable.ofTable.BuildFlow(priorityLow). Cookie(f.cookieAllocator.Request(f.category).Raw()). diff --git a/pkg/ovs/openflow/interfaces.go b/pkg/ovs/openflow/interfaces.go index e55ceb2df47..2a9076f3ea8 100644 --- a/pkg/ovs/openflow/interfaces.go +++ b/pkg/ovs/openflow/interfaces.go @@ -210,6 +210,7 @@ type Action interface { LoadRange(name string, addr uint64, to *Range) FlowBuilder Move(from, to string) FlowBuilder MoveRange(fromName, toName string, from, to Range) FlowBuilder + MoveFromTunMetadata(fromTunMetadataID int, toField string, fromRange, toRange Range, tlvLength uint8) FlowBuilder Resubmit(port uint16, table uint8) FlowBuilder ResubmitToTables(tables ...uint8) FlowBuilder CT(commit bool, tableID uint8, zone int, zoneSrcField *RegField) CTAction @@ -364,6 +365,9 @@ type MeterBandBuilder interface { type CTAction interface { LoadToMark(value uint32) CTAction LoadToCtMark(marks ...*CtMark) CTAction + // LoadToLabelField loads a data into ct_label field. If the expected label is larger than the max value of uint64 + // (0xffffffffffffffff), call this function twice: one is to set the low 64 bits, and the other is to set the high + // 64 bits. LoadToLabelField(value uint64, labelField *CtLabel) CTAction MoveToLabel(fromName string, fromRng, labelRng *Range) CTAction MoveToCtMarkField(fromRegField *RegField, ctMark *CtMarkField) CTAction @@ -406,7 +410,9 @@ type PacketOutBuilder interface { SetICMPData(data []byte) PacketOutBuilder SetInport(inPort uint32) PacketOutBuilder SetOutport(outport uint32) PacketOutBuilder - AddLoadAction(name string, data uint64, rng *Range) PacketOutBuilder + // AddSetIPTOSAction sets the IP_TOS field in the packet-out message. The action clears the two ECN bits as 0, + // and only 2-7 bits of the DSCP field in IP header is set. + AddSetIPTOSAction(data uint8) PacketOutBuilder AddLoadRegMark(mark *RegMark) PacketOutBuilder AddResubmitAction(inPort *uint16, table *uint8) PacketOutBuilder SetL4Packet(packet util.Message) PacketOutBuilder diff --git a/pkg/ovs/openflow/ofctrl_action.go b/pkg/ovs/openflow/ofctrl_action.go index e4ec8cc7769..14df04e5ed3 100644 --- a/pkg/ovs/openflow/ofctrl_action.go +++ b/pkg/ovs/openflow/ofctrl_action.go @@ -20,10 +20,10 @@ import ( "net" "strings" - utilnet "k8s.io/utils/net" - - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" + "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" + utilnet "k8s.io/utils/net" ) type ofFlowAction struct { @@ -83,59 +83,80 @@ func (a *ofFlowAction) CT(commit bool, tableID uint8, zone int, zoneSrcField *Re // ofCTAction is a struct to implement CTAction. type ofCTAction struct { ctBase - actions []openflow13.Action + actions []openflow15.Action builder *ofFlowBuilder } // LoadToMark is an action to load data into ct_mark. func (a *ofCTAction) LoadToMark(value uint32) CTAction { - field, rng, _ := getFieldRange(NxmFieldCtMark) - a.load(field, uint64(value), &rng) + ctMarkField := openflow15.NewCTMarkMatchField(value, nil) + action := openflow15.NewActionSetField(*ctMarkField) + a.actions = append(a.actions, action) return a } func (a *ofCTAction) LoadToCtMark(marks ...*CtMark) CTAction { - field, _, _ := getFieldRange(NxmFieldCtMark) for _, mark := range marks { - a.load(field, uint64(mark.value), mark.field.rng) + var mask *uint32 + maskData := uint32(0) + valueData := mark.value + if mark.field.rng != nil { + maskData = ^maskData >> (32 - mark.field.rng.Length()) << mark.field.rng.Offset() + mask = &maskData + valueData = valueData << mark.field.rng.Offset() + } + ctMarkField := openflow15.NewCTMarkMatchField(valueData, mask) + action := openflow15.NewActionSetField(*ctMarkField) + a.actions = append(a.actions, action) } return a } func (a *ofCTAction) LoadToLabelField(value uint64, labelField *CtLabel) CTAction { - field, _, _ := getFieldRange(NxmFieldCtLabel) - a.load(field, value, labelField.rng) - return a -} - -func (a *ofCTAction) load(field *openflow13.MatchField, value uint64, rng *Range) { - action := openflow13.NewNXActionRegLoad(rng.ToNXRange().ToOfsBits(), field, value) + var labelBytes, maskBytes [16]byte + valueData := value + if labelField.rng != nil { + mask := ^uint64(0) >> (64 - labelField.rng.Length()) << labelField.rng.Offset() + valueData = valueData << (labelField.rng.Offset() % 64) + if labelField.rng.Offset() > 64 { + binary.BigEndian.PutUint64(maskBytes[0:8], mask) + binary.BigEndian.PutUint64(labelBytes[0:8], valueData) + } else { + binary.BigEndian.PutUint64(maskBytes[8:], mask) + binary.BigEndian.PutUint64(labelBytes[8:], valueData) + } + } else { + binary.BigEndian.PutUint64(labelBytes[0:8], valueData) + } + ctLabelField := openflow15.NewCTLabelMatchField(labelBytes, &maskBytes) + action := openflow15.NewActionSetField(*ctLabelField) a.actions = append(a.actions, action) + return a } // MoveToLabel is an action to move data into ct_label. func (a *ofCTAction) MoveToLabel(fromName string, fromRng, labelRng *Range) CTAction { - fromField, _ := openflow13.FindFieldHeaderByName(fromName, false) - toField, _ := openflow13.FindFieldHeaderByName(NxmFieldCtLabel, false) + fromField, _ := openflow15.FindOxmIdByName(fromName, false) + toField, _ := openflow15.FindOxmIdByName(NxmFieldCtLabel, false) a.move(fromField, toField, uint16(fromRng.Length()), uint16(fromRng[0]), uint16(labelRng[0])) return a } // MoveToCtMarkField is an action to move data into ct_mark. func (a *ofCTAction) MoveToCtMarkField(fromRegField *RegField, ctMarkField *CtMarkField) CTAction { - fromField, _ := openflow13.FindFieldHeaderByName(fromRegField.GetNXFieldName(), false) - toField, _ := openflow13.FindFieldHeaderByName(NxmFieldCtMark, false) + fromField, _ := openflow15.FindOxmIdByName(fromRegField.GetNXFieldName(), false) + toField, _ := openflow15.FindOxmIdByName(NxmFieldCtMark, false) a.move(fromField, toField, uint16(fromRegField.GetRange().Length()), uint16(fromRegField.GetRange()[0]), uint16(ctMarkField.rng[0])) return a } -func (a *ofCTAction) move(fromField *openflow13.MatchField, toField *openflow13.MatchField, nBits, fromStart, toStart uint16) { - action := openflow13.NewNXActionRegMove(nBits, fromStart, toStart, fromField, toField) +func (a *ofCTAction) move(fromField *openflow15.OxmId, toField *openflow15.OxmId, nBits, fromStart, toStart uint16) { + action := openflow15.NewActionCopyField(nBits, fromStart, toStart, *fromField, *toField) a.actions = append(a.actions, action) } func (a *ofCTAction) natAction(isSNAT bool, ipRange *IPRange, portRange *PortRange) CTAction { - action := openflow13.NewNXActionCTNAT() + action := openflow15.NewNXActionCTNAT() if isSNAT { action.SetSNAT() } else { @@ -169,7 +190,7 @@ func (a *ofCTAction) DNAT(ipRange *IPRange, portRange *PortRange) CTAction { } func (a *ofCTAction) NAT() CTAction { - action := openflow13.NewNXActionCTNAT() + action := openflow15.NewNXActionCTNAT() a.actions = append(a.actions, action) return a } @@ -272,25 +293,38 @@ func (a *ofFlowAction) SetVLAN(vlanID uint16) FlowBuilder { // LoadARPOperation is an action to load data to NXM_OF_ARP_OP field. func (a *ofFlowAction) LoadARPOperation(value uint16) FlowBuilder { - loadAct, _ := ofctrl.NewNXLoadAction(NxmFieldARPOp, uint64(value), openflow13.NewNXRange(0, 15)) + loadAct := &ofctrl.SetARPOpAction{Value: value} a.builder.ApplyAction(loadAct) return a.builder } // 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 { - 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) + hasMask := rng != nil + field, _ := openflow15.FindFieldHeaderByName(name, hasMask) + var valueBytes, maskBytes []byte + valueData := value + if hasMask { + mask := ^uint64(0) >> (64 - rng.Length()) << rng.Offset() + binary.BigEndian.PutUint64(maskBytes, mask) + field.Mask = util.NewBuffer(maskBytes) + valueData = valueData << rng.Offset() } - a.builder.ApplyAction(loadAct) - return a.builder + binary.BigEndian.PutUint64(valueBytes, valueData) + field.Value = util.NewBuffer(valueBytes) + return a.setField(field) } 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) + valueData := value + mask := uint32(0) + if field.rng != nil { + mask = ^mask >> (32 - field.rng.Length()) << field.rng.Offset() + valueData = valueData << field.rng.Offset() + } + f := openflow15.NewRegMatchFieldWithMask(field.regID, valueData, mask) + act := ofctrl.NewSetFieldAction(f) + a.builder.ApplyAction(act) return a.builder } @@ -303,14 +337,35 @@ func (a *ofFlowAction) LoadRegMark(marks ...*RegMark) FlowBuilder { return fb } -// LoadToPktMarkRange is an action to load data into pkt_mark at specified range. +// LoadPktMarkRange is an action to load data into pkt_mark at specified range. func (a *ofFlowAction) LoadPktMarkRange(value uint32, rng *Range) FlowBuilder { - return a.LoadRange(NxmFieldPktMark, uint64(value), rng) + pktMarkField, _ := openflow15.FindFieldHeaderByName(NxmFieldPktMark, true) + var valueBytes, maskBytes [4]byte + valueData := value + mask := uint32(0) + if rng != nil { + mask = ^mask >> (32 - rng.Length()) << rng.Offset() + binary.BigEndian.PutUint32(maskBytes[:], mask) + pktMarkField.Mask = util.NewBuffer(maskBytes[:]) + valueData = valueData << rng.Offset() + } + binary.BigEndian.PutUint32(valueBytes[:], valueData) + pktMarkField.Value = util.NewBuffer(valueBytes[:]) + return a.setField(pktMarkField) } // LoadIPDSCP is an action to load data to IP DSCP bits. func (a *ofFlowAction) LoadIPDSCP(value uint8) FlowBuilder { - return a.LoadRange(NxmFieldIPToS, uint64(value), IPDSCPToSRange) + field, _ := openflow15.FindFieldHeaderByName(NxmFieldIPToS, true) + field.Value = &openflow15.IpDscpField{Dscp: value << IPDSCPToSRange.Offset()} + field.Mask = &openflow15.IpDscpField{Dscp: uint8(0xff) >> (8 - IPDSCPToSRange.Length()) << IPDSCPToSRange.Offset()} + return a.setField(field) +} + +func (a *ofFlowAction) setField(field *openflow15.MatchField) FlowBuilder { + loadAct := ofctrl.NewSetFieldAction(field) + a.builder.ApplyAction(loadAct) + return a.builder } // Move is an action to copy all data from "fromField" to "toField". Fields with name "fromField" and "fromField" should @@ -323,14 +378,26 @@ func (a *ofFlowAction) Move(fromField, toField string) FlowBuilder { // MoveRange is an action to move data from "fromField" at "fromRange" to "toField" at "toRange". func (a *ofFlowAction) MoveRange(fromField, toField string, fromRange, toRange Range) FlowBuilder { - moveAct, _ := ofctrl.NewNXMoveAction(fromField, toField, fromRange.ToNXRange(), toRange.ToNXRange()) - if a.builder.ofFlow.Table != nil && a.builder.ofFlow.Table.Switch != nil { - moveAct.ResetFieldsLength(a.builder.ofFlow.Table.Switch) - } + srcOxmId, _ := openflow15.FindOxmIdByName(fromField, false) + dstOxmId, _ := openflow15.FindOxmIdByName(toField, false) + return a.copyField(srcOxmId, dstOxmId, fromRange, toRange) +} + +func (a *ofFlowAction) copyField(srcOxmId, dstOxmId *openflow15.OxmId, fromRange, toRange Range) FlowBuilder { + nBits := fromRange.ToNXRange().GetNbits() + srcOffset := fromRange.ToNXRange().GetOfs() + dstOffset := toRange.ToNXRange().GetOfs() + moveAct := ofctrl.NewCopyFieldAction(nBits, srcOffset, dstOffset, srcOxmId, dstOxmId) a.builder.ApplyAction(moveAct) return a.builder } +func (a *ofFlowAction) MoveFromTunMetadata(fromTunMetadataID int, toField string, fromRange, toRange Range, tlvLength uint8) FlowBuilder { + dstOxmID, _ := openflow15.FindOxmIdByName(toField, false) + srcOxmID := getTunMetadataOxmId(fromTunMetadataID, tlvLength) + return a.copyField(srcOxmID, dstOxmID, fromRange, toRange) +} + // Resubmit is an action to resubmit packet to the specified table with the port as new in_port. If port is empty string, // the in_port field is not changed. func (a *ofFlowAction) Resubmit(ofPort uint16, tableID uint8) FlowBuilder { @@ -343,7 +410,7 @@ func (a *ofFlowAction) Resubmit(ofPort uint16, tableID uint8) FlowBuilder { func (a *ofFlowAction) ResubmitToTables(tables ...uint8) FlowBuilder { var fb FlowBuilder for _, t := range tables { - fb = a.Resubmit(openflow13.OFPP_IN_PORT, t) + fb = a.Resubmit(openflow15.OFPP_IN_PORT, t) } return fb } @@ -399,11 +466,12 @@ func (a *ofFlowAction) SendToController(reason uint8) FlowBuilder { } func (a *ofFlowAction) Meter(meterID uint32) FlowBuilder { - a.builder.ofFlow.Meter(meterID) + meterAction := ofctrl.NewMeterAction(meterID) + a.builder.ApplyAction(meterAction) return a.builder } -// Learn is an action which adds or modifies a flow in an OpenFlow table. +// Learn is an action which adds or modifies a flow in an OpenFlow table. func (a *ofFlowAction) Learn(id uint8, priority uint16, idleTimeout, hardTimeout uint16, cookieID uint64) LearnAction { la := &ofLearnAction{ flowBuilder: a.builder, @@ -600,8 +668,8 @@ func (a *ofLearnAction) Done() FlowBuilder { return a.flowBuilder } -func getFieldRange(name string) (*openflow13.MatchField, Range, error) { - field, err := openflow13.FindFieldHeaderByName(name, false) +func getFieldRange(name string) (*openflow15.MatchField, Range, error) { + field, err := openflow15.FindFieldHeaderByName(name, false) if err != nil { return field, Range{0, 0}, err } @@ -626,3 +694,10 @@ func (a *ofFlowAction) GotoStage(stage StageID) FlowBuilder { a.builder.ofFlow.Goto(table.GetID()) return a.builder } + +func getTunMetadataOxmId(id int, tlvLength uint8) *openflow15.OxmId { + field := fmt.Sprintf("%s%d", NxmFieldTunMetadata, id) + oxmID, _ := openflow15.FindOxmIdByName(field, false) + oxmID.Length = tlvLength + return oxmID +} diff --git a/pkg/ovs/openflow/ofctrl_bridge.go b/pkg/ovs/openflow/ofctrl_bridge.go index e5b2b886cfc..225e8f9a4e5 100644 --- a/pkg/ovs/openflow/ofctrl_bridge.go +++ b/pkg/ovs/openflow/ofctrl_bridge.go @@ -21,7 +21,7 @@ import ( "sync" "time" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/ofnet/ofctrl" "golang.org/x/time/rate" "k8s.io/klog/v2" @@ -138,17 +138,31 @@ func (t *ofTable) DumpFlows(cookieID, cookieMask uint64) (map[uint64]*FlowStates if ofStats == nil { return nil, nil } + return parseFlowStats(ofStats), nil +} + +func parseFlowStats(ofStats []*openflow15.FlowDesc) map[uint64]*FlowStates { flowStats := make(map[uint64]*FlowStates) for _, stat := range ofStats { cookie := stat.Cookie s := &FlowStates{ - TableID: stat.TableId, - PacketCount: stat.PacketCount, - DurationNSecond: stat.DurationNSec, + TableID: stat.TableId, + } + for _, field := range stat.Stats.Fields { + switch count := field.(type) { + case *openflow15.PBCountStatField: + if count.Header.Field == openflow15.XST_OFB_PACKET_COUNT { + s.PacketCount = count.Count + } + case *openflow15.TimeStatField: + if count.Header.Field == openflow15.XST_OFB_DURATION { + s.DurationNSecond = count.NSec + } + } } flowStats[cookie] = s } - return flowStats, nil + return flowStats } func NewOFTable(id uint8, name string, stageID StageID, pipelineID PipelineID, missAction MissActionType) Table { @@ -186,7 +200,10 @@ type OFBridge struct { connected chan bool // pktConsumers is a map from PacketIn reason to the channel that is used to publish the PacketIn message. pktConsumers sync.Map - multipartReplyChs map[uint32]chan *openflow13.MultipartReply + multipartReplyChs map[uint32]chan *openflow15.MultipartReply + // tunMetadataLengthMap is used to store the tlv-map settings on the OVS bridge. Key is the index of tunnel metedata, + // and value is the length configured in this tunnel metadata. + tunMetadataLengthMap map[uint16]uint8 } func (b *OFBridge) CreateGroupTypeAll(id GroupIDType) Group { @@ -242,9 +259,9 @@ func (b *OFBridge) DeleteMeterAll() error { // Clear all existing meter entries // TODO: this should be defined in libOpenflow const OFPM_ALL = 0xffffffff // Represents all meters - meterMod := openflow13.NewMeterMod() + meterMod := openflow15.NewMeterMod() meterMod.MeterId = OFPM_ALL - meterMod.Command = openflow13.OFPMC_DELETE + meterMod.Command = openflow15.MC_DELETE if err := b.ofSwitch.Send(meterMod); err != nil { return err } @@ -320,7 +337,7 @@ func (b *OFBridge) SwitchConnected(sw *ofctrl.OFSwitch) { // MultipartReply is a callback when multipartReply message is received on ofctrl.OFSwitch is connected. // Client uses this method to handle the reply message if it has customized MultipartRequest message. -func (b *OFBridge) MultipartReply(sw *ofctrl.OFSwitch, rep *openflow13.MultipartReply) { +func (b *OFBridge) MultipartReply(sw *ofctrl.OFSwitch, rep *openflow15.MultipartReply) { if ch, ok := b.multipartReplyChs[rep.Xid]; ok { ch <- rep } @@ -396,28 +413,18 @@ func (b *OFBridge) DumpFlows(cookieID, cookieMask uint64) (map[uint64]*FlowState if ofStats == nil { return nil, nil } - flowStats := make(map[uint64]*FlowStates) - for _, stat := range ofStats { - cookie := stat.Cookie - s := &FlowStates{ - TableID: stat.TableId, - PacketCount: stat.PacketCount, - DurationNSecond: stat.DurationNSec, - } - flowStats[cookie] = s - } - return flowStats, nil + return parseFlowStats(ofStats), nil } // DeleteFlowsByCookie removes Openflow entries from OFSwitch. The removed Openflow entries use the specific CookieID. func (b *OFBridge) DeleteFlowsByCookie(cookieID, cookieMask uint64) error { - flowMod := openflow13.NewFlowMod() - flowMod.Command = openflow13.FC_DELETE + flowMod := openflow15.NewFlowMod() + flowMod.Command = openflow15.FC_DELETE flowMod.Cookie = cookieID flowMod.CookieMask = cookieMask - flowMod.OutPort = openflow13.P_ANY - flowMod.OutGroup = openflow13.OFPG_ANY - flowMod.TableId = openflow13.OFPTT_ALL + flowMod.OutPort = openflow15.P_ANY + flowMod.OutGroup = openflow15.OFPG_ANY + flowMod.TableId = openflow15.OFPTT_ALL return b.ofSwitch.Send(flowMod) } @@ -462,15 +469,15 @@ func (b *OFBridge) AddFlowsInBundle(addflows []Flow, modFlows []Flow, delFlows [ } // Install new Openflow entries with the opened bundle. - if err := syncFlows(addflows, openflow13.FC_ADD); err != nil { + if err := syncFlows(addflows, openflow15.FC_ADD); err != nil { return err } // Modify existing Openflow entries with the opened bundle. - if err := syncFlows(modFlows, openflow13.FC_MODIFY_STRICT); err != nil { + if err := syncFlows(modFlows, openflow15.FC_MODIFY_STRICT); err != nil { return err } // Delete Openflow entries with the opened bundle. - if err := syncFlows(delFlows, openflow13.FC_DELETE_STRICT); err != nil { + if err := syncFlows(delFlows, openflow15.FC_DELETE_STRICT); err != nil { return err } @@ -662,6 +669,7 @@ func (b *OFBridge) AddTLVMap(optClass uint16, optType uint8, optLength uint8, tu if err := b.ofSwitch.AddTunnelTLVMap(optClass, optType, optLength, tunMetadataIndex); err != nil { return err } + b.tunMetadataLengthMap[tunMetadataIndex] = optLength return nil } @@ -687,17 +695,17 @@ func (b *OFBridge) RetryInterval() time.Duration { } func (b *OFBridge) queryTableFeatures() { - mpartRequest := &openflow13.MultipartRequest{ - Header: openflow13.NewOfp13Header(), - Type: openflow13.MultipartType_TableFeatures, + mpartRequest := &openflow15.MultipartRequest{ + Header: openflow15.NewOfp15Header(), + Type: openflow15.MultipartType_TableFeatures, Flags: 0, } - mpartRequest.Header.Type = openflow13.Type_MultiPartRequest + mpartRequest.Header.Type = openflow15.Type_MultiPartRequest mpartRequest.Header.Length = mpartRequest.Len() // Use a buffer for the channel to avoid blocking the OpenFlow connection inbound channel, since it takes time when // sending the Multipart Request messages to modify the tables' names. The buffer size "20" is the observed number // of the Multipart Reply messages sent from OVS. - tableFeatureCh := make(chan *openflow13.MultipartReply, 20) + tableFeatureCh := make(chan *openflow15.MultipartReply, 20) b.multipartReplyChs[mpartRequest.Xid] = tableFeatureCh go func() { // Delete the channel which is used to receive the MultipartReply message after all tables' features are received. @@ -709,24 +717,24 @@ func (b *OFBridge) queryTableFeatures() { b.ofSwitch.Send(mpartRequest) } -func (b *OFBridge) processTableFeatures(ch chan *openflow13.MultipartReply) { - header := openflow13.NewOfp13Header() - header.Type = openflow13.Type_MultiPartRequest +func (b *OFBridge) processTableFeatures(ch chan *openflow15.MultipartReply) { + header := openflow15.NewOfp15Header() + header.Type = openflow15.Type_MultiPartRequest // Since the initial MultipartRequest doesn't specify any table ID, OVS will reply all tables' (except the hidden one) // features in the reply. Here we complete the loop after we receive all the reply messages, while the reply message // is configured with Flags=0. for { select { case rpl := <-ch: - request := &openflow13.MultipartRequest{ + request := &openflow15.MultipartRequest{ Header: header, - Type: openflow13.MultipartType_TableFeatures, + Type: openflow15.MultipartType_TableFeatures, Flags: rpl.Flags, } // A MultipartReply message may have one or many OFPTableFeatures messages, and MultipartReply.Body is a // slice of these messages. for _, body := range rpl.Body { - tableFeature := body.(*openflow13.OFPTableFeatures) + tableFeature := body.(*openflow15.TableFeatures) // Modify table name if the table is in the pipeline, otherwise use the default table features. // OVS doesn't allow to skip any table except the hidden table (always the last table) in a table_features // request. So use the existing table features for the tables that Antrea doesn't define in the pipeline. @@ -749,12 +757,13 @@ func (b *OFBridge) processTableFeatures(ch chan *openflow13.MultipartReply) { func NewOFBridge(br string, mgmtAddr string) Bridge { s := &OFBridge{ - bridgeName: br, - mgmtAddr: mgmtAddr, - tableCache: make(map[uint8]*ofTable), - retryInterval: 1 * time.Second, - pktConsumers: sync.Map{}, - multipartReplyChs: make(map[uint32]chan *openflow13.MultipartReply), + bridgeName: br, + mgmtAddr: mgmtAddr, + tableCache: make(map[uint8]*ofTable), + retryInterval: 1 * time.Second, + pktConsumers: sync.Map{}, + multipartReplyChs: make(map[uint32]chan *openflow15.MultipartReply), + tunMetadataLengthMap: make(map[uint16]uint8), } s.controller = ofctrl.NewController(s) return s diff --git a/pkg/ovs/openflow/ofctrl_builder.go b/pkg/ovs/openflow/ofctrl_builder.go index b6b36f52dff..3135b967431 100644 --- a/pkg/ovs/openflow/ofctrl_builder.go +++ b/pkg/ovs/openflow/ofctrl_builder.go @@ -19,7 +19,7 @@ import ( "net" "strings" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/ofnet/ofctrl" ) @@ -28,7 +28,7 @@ type ofFlowBuilder struct { } func (b *ofFlowBuilder) MatchTunMetadata(index int, data uint32) FlowBuilder { - rng := openflow13.NewNXRange(0, 31) + rng := openflow15.NewNXRange(0, 31) tm := &ofctrl.NXTunMetadata{ ID: index, Data: data, @@ -133,7 +133,7 @@ func (b *ofFlowBuilder) addCTStateString(value string) { func (b *ofFlowBuilder) MatchCTStateNew(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetNew() @@ -147,7 +147,7 @@ func (b *ofFlowBuilder) MatchCTStateNew(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateRel(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetRel() @@ -161,7 +161,7 @@ func (b *ofFlowBuilder) MatchCTStateRel(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateRpl(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetRpl() @@ -175,7 +175,7 @@ func (b *ofFlowBuilder) MatchCTStateRpl(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateEst(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetEst() @@ -189,7 +189,7 @@ func (b *ofFlowBuilder) MatchCTStateEst(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateTrk(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetTrk() @@ -203,7 +203,7 @@ func (b *ofFlowBuilder) MatchCTStateTrk(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateInv(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetInv() @@ -217,7 +217,7 @@ func (b *ofFlowBuilder) MatchCTStateInv(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateDNAT(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetDNAT() @@ -231,7 +231,7 @@ func (b *ofFlowBuilder) MatchCTStateDNAT(set bool) FlowBuilder { func (b *ofFlowBuilder) MatchCTStateSNAT(set bool) FlowBuilder { if b.ctStates == nil { - b.ctStates = openflow13.NewCTStates() + b.ctStates = openflow15.NewCTStates() } if set { b.ctStates.SetSNAT() diff --git a/pkg/ovs/openflow/ofctrl_flow.go b/pkg/ovs/openflow/ofctrl_flow.go index b3a1dc60033..5428bb423ef 100644 --- a/pkg/ovs/openflow/ofctrl_flow.go +++ b/pkg/ovs/openflow/ofctrl_flow.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/ofnet/ofctrl" ) @@ -42,9 +42,9 @@ type ofFlow struct { // ctStateString is a temporary variable for the readable ct_state configuration. Its value is changed when the client // updates the matching condition of "ct_states". When FlowBuilder.Done is called, its value is added into the matchers. ctStateString string - // ctStates is a temporary variable to maintain openflow13.CTStates. When FlowBuilder.Done is called, it is used to + // ctStates is a temporary variable to maintain openflow15.CTStates. When FlowBuilder.Done is called, it is used to // set the CtStates field in ofctrl.Flow.Match. - ctStates *openflow13.CTStates + ctStates *openflow15.CTStates // isDropFlow is true if this flow actions contain "drop" isDropFlow bool } @@ -69,7 +69,7 @@ func (f *ofFlow) Reset() { } func (f *ofFlow) Add() error { - err := f.Flow.Send(openflow13.FC_ADD) + err := f.Flow.Send(openflow15.FC_ADD) if err != nil { return err } @@ -78,7 +78,7 @@ func (f *ofFlow) Add() error { } func (f *ofFlow) Modify() error { - err := f.Flow.Send(openflow13.FC_MODIFY_STRICT) + err := f.Flow.Send(openflow15.FC_MODIFY_STRICT) if err != nil { return err } @@ -88,7 +88,7 @@ func (f *ofFlow) Modify() error { func (f *ofFlow) Delete() error { f.Flow.UpdateInstallStatus(true) - err := f.Flow.Send(openflow13.FC_DELETE_STRICT) + err := f.Flow.Send(openflow15.FC_DELETE_STRICT) if err != nil { return err } @@ -128,11 +128,11 @@ func (f *ofFlow) GetBundleMessage(entryOper OFOperation) (ofctrl.OpenFlowModMess var operation int switch entryOper { case AddMessage: - operation = openflow13.FC_ADD + operation = openflow15.FC_ADD case ModifyMessage: - operation = openflow13.FC_MODIFY_STRICT + operation = openflow15.FC_MODIFY_STRICT case DeleteMessage: - operation = openflow13.FC_DELETE_STRICT + operation = openflow15.FC_DELETE_STRICT } message, err := f.Flow.GetBundleMessage(operation) if err != nil { @@ -175,8 +175,8 @@ func (f *ofFlow) IsDropFlow() bool { return f.isDropFlow } -func (r *Range) ToNXRange() *openflow13.NXRange { - return openflow13.NewNXRange(int(r[0]), int(r[1])) +func (r *Range) ToNXRange() *openflow15.NXRange { + return openflow15.NewNXRange(int(r[0]), int(r[1])) } func (r *Range) Length() uint32 { diff --git a/pkg/ovs/openflow/ofctrl_group.go b/pkg/ovs/openflow/ofctrl_group.go index b16495b0c4a..7402aa8e638 100644 --- a/pkg/ovs/openflow/ofctrl_group.go +++ b/pkg/ovs/openflow/ofctrl_group.go @@ -18,13 +18,15 @@ import ( "fmt" "net" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" + "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" ) type ofGroup struct { - ofctrl *ofctrl.Group - bridge *OFBridge + ofctrl *ofctrl.Group + bridge *OFBridge + bucketsCount int } // Reset creates a new ofctrl.Group object for the updated ofSwitch. The @@ -62,9 +64,10 @@ func (g *ofGroup) KeyString() string { } func (g *ofGroup) Bucket() BucketBuilder { + id := uint32(len(g.ofctrl.Buckets)) return &bucketBuilder{ group: g, - bucket: openflow13.NewBucket(), + bucket: openflow15.NewBucket(id), } } @@ -72,11 +75,11 @@ func (g *ofGroup) GetBundleMessage(entryOper OFOperation) (ofctrl.OpenFlowModMes var operation int switch entryOper { case AddMessage: - operation = openflow13.OFPGC_ADD + operation = openflow15.OFPGC_ADD case ModifyMessage: - operation = openflow13.OFPGC_MODIFY + operation = openflow15.OFPGC_MODIFY case DeleteMessage: - operation = openflow13.OFPGC_DELETE + operation = openflow15.OFPGC_DELETE } message := g.ofctrl.GetBundleMessage(operation) return message, nil @@ -89,7 +92,7 @@ func (g *ofGroup) ResetBuckets() Group { type bucketBuilder struct { group *ofGroup - bucket *openflow13.Bucket + bucket *openflow15.Bucket } // LoadReg makes the learned flow to load data to reg[regID] with specific range. @@ -99,23 +102,34 @@ func (b *bucketBuilder) LoadReg(regID int, data uint32) BucketBuilder { // LoadXXReg makes the learned flow to load data to xxreg[regID] with specific range. func (b *bucketBuilder) LoadXXReg(regID int, data []byte) BucketBuilder { - regAction := &ofctrl.NXLoadXXRegAction{FieldNumber: uint8(regID), Value: data, Mask: nil} - b.bucket.AddAction(regAction.GetActionMessage()) + field, _ := openflow15.FindFieldHeaderByName(fmt.Sprintf("NXM_NX_XXREG%d", regID), false) + field.Value = util.NewBuffer(data) + b.bucket.AddAction(openflow15.NewActionSetField(*field)) return b } // 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 { - reg := fmt.Sprintf("%s%d", NxmFieldReg, regID) - regField, _ := openflow13.FindFieldHeaderByName(reg, true) - b.bucket.AddAction(openflow13.NewNXActionRegLoad(rng.ToNXRange().ToOfsBits(), regField, uint64(data))) + valueData := data + mask := uint32(0) + if rng != nil { + mask = ^mask >> (32 - rng.Length()) << rng.Offset() + valueData = valueData << rng.Offset() + } + tgtField := openflow15.NewRegMatchFieldWithMask(regID, valueData, mask) + b.bucket.AddAction(openflow15.NewActionSetField(*tgtField)) 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))) + valueData := data + mask := uint32(0) + if field.rng != nil { + mask = ^mask >> (32 - field.rng.Length()) << field.rng.Offset() + valueData = valueData << field.rng.Offset() + } + tgtField := openflow15.NewRegMatchFieldWithMask(field.regID, valueData, mask) + b.bucket.AddAction(openflow15.NewActionSetField(*tgtField)) return b } @@ -125,7 +139,7 @@ func (b *bucketBuilder) LoadRegMark(mark *RegMark) BucketBuilder { // ResubmitToTable is an action to resubmit packet to the specified table when the bucket is selected. func (b *bucketBuilder) ResubmitToTable(tableID uint8) BucketBuilder { - b.bucket.AddAction(openflow13.NewNXActionResubmitTableAction(openflow13.OFPP_IN_PORT, tableID)) + b.bucket.AddAction(openflow15.NewNXActionResubmitTableAction(openflow15.OFPP_IN_PORT, tableID)) return b } @@ -138,7 +152,8 @@ func (b *bucketBuilder) SetTunnelDst(addr net.IP) BucketBuilder { // Weight sets the weight of a bucket. func (b *bucketBuilder) Weight(val uint16) BucketBuilder { - b.bucket.Weight = val + weight := openflow15.NewGroupBucketPropWeight(val) + b.bucket.AddProperty(weight) return b } diff --git a/pkg/ovs/openflow/ofctrl_meter.go b/pkg/ovs/openflow/ofctrl_meter.go index cca0a53cb95..a6af7e46f3e 100644 --- a/pkg/ovs/openflow/ofctrl_meter.go +++ b/pkg/ovs/openflow/ofctrl_meter.go @@ -17,7 +17,7 @@ package openflow import ( "fmt" - "antrea.io/libOpenflow/openflow13" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" ) @@ -55,11 +55,11 @@ func (m *ofMeter) GetBundleMessage(entryOper OFOperation) (ofctrl.OpenFlowModMes var operation int switch entryOper { case AddMessage: - operation = openflow13.OFPMC_ADD + operation = openflow15.MC_ADD case ModifyMessage: - operation = openflow13.OFPMC_MODIFY + operation = openflow15.MC_MODIFY case DeleteMessage: - operation = openflow13.OFPMC_DELETE + operation = openflow15.MC_DELETE } message := m.ofctrl.GetBundleMessage(operation) return message, nil @@ -73,7 +73,7 @@ func (m *ofMeter) ResetMeterBands() Meter { func (m *ofMeter) MeterBand() MeterBandBuilder { return &meterBandBuilder{ meter: m, - meterBandHeader: openflow13.NewMeterBandHeader(), + meterBandHeader: openflow15.NewMeterBandHeader(), prevLevel: 0, experimenter: 0, } @@ -81,7 +81,7 @@ func (m *ofMeter) MeterBand() MeterBandBuilder { type meterBandBuilder struct { meter *ofMeter - meterBandHeader *openflow13.MeterBandHeader + meterBandHeader *openflow15.MeterBandHeader prevLevel uint8 experimenter uint32 } @@ -115,16 +115,16 @@ func (m *meterBandBuilder) Done() Meter { var mb util.Message switch m.meterBandHeader.Type { case uint16(ofctrl.MeterDrop): - mbDrop := new(openflow13.MeterBandDrop) + mbDrop := new(openflow15.MeterBandDrop) mbDrop.MeterBandHeader = *m.meterBandHeader mb = mbDrop case uint16(ofctrl.MeterDSCPRemark): - mbDscp := new(openflow13.MeterBandDSCP) + mbDscp := new(openflow15.MeterBandDSCP) mbDscp.MeterBandHeader = *m.meterBandHeader mbDscp.PrecLevel = m.prevLevel mb = mbDscp case uint16(ofctrl.MeterExperimenter): - mbExp := new(openflow13.MeterBandExperimenter) + mbExp := new(openflow15.MeterBandExperimenter) mbExp.MeterBandHeader = *m.meterBandHeader mbExp.Experimenter = m.experimenter } diff --git a/pkg/ovs/openflow/ofctrl_packetin.go b/pkg/ovs/openflow/ofctrl_packetin.go index 50e49717e47..61ae8199b0a 100644 --- a/pkg/ovs/openflow/ofctrl_packetin.go +++ b/pkg/ovs/openflow/ofctrl_packetin.go @@ -63,39 +63,50 @@ func GetUDPHeaderData(ipPkt util.Message) (udpSrcPort, udpDstPort uint16, err er } func getICMPHeaderData(ipPkt util.Message) (icmpType, icmpCode uint8, icmpEchoID, icmpEchoSeq uint16, err error) { - var icmpIn *protocol.ICMP switch typedIPPkt := ipPkt.(type) { case *protocol.IPv4: - icmpIn = typedIPPkt.Data.(*protocol.ICMP) + icmpIn := typedIPPkt.Data.(*protocol.ICMP) + if icmpIn.Type == icmpEchoRequestType { + if len(icmpIn.Data) < 4 { + return 0, 0, 0, 0, errors.New("ICMP payload is too short to unmarshal an ICMP echo message") + } + icmpEchoID = binary.BigEndian.Uint16(icmpIn.Data[:2]) + icmpEchoSeq = binary.BigEndian.Uint16(icmpIn.Data[2:4]) + } + icmpType = icmpIn.Type + icmpCode = icmpIn.Code case *protocol.IPv6: - icmpIn = typedIPPkt.Data.(*protocol.ICMP) - } - - if icmpIn.Type == icmpEchoRequestType || icmpIn.Type == icmp6EchoRequestType { - if len(icmpIn.Data) < 4 { - return 0, 0, 0, 0, errors.New("ICMP payload is too short to unmarshal an ICMP echo message") + icmpIn := typedIPPkt.Data.(*protocol.ICMPv6EchoReqRpl) + if icmpIn.Type == icmp6EchoRequestType { + icmpEchoID = icmpIn.Identifier + icmpEchoSeq = icmpIn.SeqNum } - icmpEchoID = binary.BigEndian.Uint16(icmpIn.Data[:2]) - icmpEchoSeq = binary.BigEndian.Uint16(icmpIn.Data[2:4]) + icmpType = icmpIn.Type + icmpCode = icmpIn.Code } - return icmpIn.Type, icmpIn.Code, icmpEchoID, icmpEchoSeq, nil + + return icmpType, icmpCode, icmpEchoID, icmpEchoSeq, nil } func ParsePacketIn(pktIn *ofctrl.PacketIn) (*Packet, error) { packet := Packet{} - packet.DestinationMAC = pktIn.Data.HWDst - packet.SourceMAC = pktIn.Data.HWSrc + ethernetData := new(protocol.Ethernet) + if err := ethernetData.UnmarshalBinary(pktIn.Data.(*util.Buffer).Bytes()); err != nil { + return nil, err + } + packet.DestinationMAC = ethernetData.HWDst + packet.SourceMAC = ethernetData.HWSrc - if pktIn.Data.Ethertype == protocol.IPv4_MSG { - ipPkt := pktIn.Data.Data.(*protocol.IPv4) + if ethernetData.Ethertype == protocol.IPv4_MSG { + ipPkt := ethernetData.Data.(*protocol.IPv4) packet.DestinationIP = ipPkt.NWDst packet.SourceIP = ipPkt.NWSrc packet.TTL = ipPkt.TTL packet.IPProto = ipPkt.Protocol packet.IPFlags = ipPkt.Flags packet.IPLength = ipPkt.Length - } else if pktIn.Data.Ethertype == protocol.IPv6_MSG { - ipPkt := pktIn.Data.Data.(*protocol.IPv6) + } else if ethernetData.Ethertype == protocol.IPv6_MSG { + ipPkt := ethernetData.Data.(*protocol.IPv6) packet.DestinationIP = ipPkt.NWDst packet.SourceIP = ipPkt.NWSrc packet.TTL = ipPkt.HopLimit @@ -111,11 +122,11 @@ func ParsePacketIn(pktIn *ofctrl.PacketIn) (*Packet, error) { var err error if packet.IPProto == protocol.Type_TCP { - packet.SourcePort, packet.DestinationPort, _, _, packet.TCPFlags, err = GetTCPHeaderData(pktIn.Data.Data) + packet.SourcePort, packet.DestinationPort, _, _, packet.TCPFlags, err = GetTCPHeaderData(ethernetData.Data) } else if packet.IPProto == protocol.Type_UDP { - packet.SourcePort, packet.DestinationPort, err = GetUDPHeaderData(pktIn.Data.Data) + packet.SourcePort, packet.DestinationPort, err = GetUDPHeaderData(ethernetData.Data) } else if packet.IPProto == protocol.Type_ICMP || packet.IPProto == protocol.Type_IPv6ICMP { - _, _, packet.ICMPEchoID, packet.ICMPEchoSeq, err = getICMPHeaderData(pktIn.Data.Data) + _, _, packet.ICMPEchoID, packet.ICMPEchoSeq, err = getICMPHeaderData(ethernetData.Data) } if err != nil { return nil, err diff --git a/pkg/ovs/openflow/ofctrl_packetin_test.go b/pkg/ovs/openflow/ofctrl_packetin_test.go index b4d82de2195..536f0fb8174 100644 --- a/pkg/ovs/openflow/ofctrl_packetin_test.go +++ b/pkg/ovs/openflow/ofctrl_packetin_test.go @@ -168,6 +168,19 @@ func TestParsePacketIn(t *testing.T) { testBytes, _ := testTCP.MarshalBinary() testBuffer := new(util.Buffer) testBuffer.UnmarshalBinary(testBytes) + ethPkt := protocol.NewEthernet() + ethPkt.HWDst = testMac1 + ethPkt.HWSrc = testMac2 + ethPkt.Ethertype = protocol.IPv6_MSG + ethPkt.Data = util.Message(&protocol.IPv6{ + Length: 1, + NextHeader: protocol.Type_TCP, + HopLimit: 0, + NWSrc: testIP1, + NWDst: testIP2, + Data: testBuffer, + }) + pktBytes, _ := ethPkt.MarshalBinary() tests := []struct { name string pktIn *ofctrl.PacketIn @@ -178,19 +191,7 @@ func TestParsePacketIn(t *testing.T) { "ParsePacketIn-ipv6", &ofctrl.PacketIn{ Reason: 1, - Data: protocol.Ethernet{ - Ethertype: protocol.IPv6_MSG, - HWDst: testMac1, - HWSrc: testMac2, - Data: util.Message(&protocol.IPv6{ - Length: 1, - NextHeader: protocol.Type_TCP, - HopLimit: 0, - NWSrc: testIP1, - NWDst: testIP2, - Data: testBuffer, - }), - }, + Data: util.NewBuffer(pktBytes), }, &Packet{ IsIPv6: true, diff --git a/pkg/ovs/openflow/ofctrl_packetout.go b/pkg/ovs/openflow/ofctrl_packetout.go index 7ad37c20c78..29ebd396cac 100644 --- a/pkg/ovs/openflow/ofctrl_packetout.go +++ b/pkg/ovs/openflow/ofctrl_packetout.go @@ -19,6 +19,7 @@ import ( "math/rand" "net" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" "antrea.io/libOpenflow/util" "antrea.io/ofnet/ofctrl" @@ -112,7 +113,7 @@ func (b *ofPacketOutBuilder) SetIPProtocol(proto Protocol) PacketOutBuilder { return b } -// ofPacketOutBuilder sets IP protocol in the packet's IP header with the +// SetIPProtocolValue sets IP protocol in the packet's IP header with the // intetger protocol value. func (b *ofPacketOutBuilder) SetIPProtocolValue(isIPv6 bool, protoValue uint8) PacketOutBuilder { if isIPv6 { @@ -153,7 +154,7 @@ func (b *ofPacketOutBuilder) SetIPFlags(flags uint16) PacketOutBuilder { return b } -// SetIPFlags sets flags in the packet's IP header. IPv4 only. +// SetIPHeaderID sets identifier field in the packet's IP header. IPv4 only. func (b *ofPacketOutBuilder) SetIPHeaderID(id uint16) PacketOutBuilder { if b.pktOut.IPv6Header == nil { if b.pktOut.IPHeader == nil { @@ -242,7 +243,7 @@ func (b *ofPacketOutBuilder) SetICMPCode(icmpCode uint8) PacketOutBuilder { return b } -// SetICMs sets the identifier in the packet's ICMP header. +// SetICMPID sets the identifier in the packet's ICMP header. func (b *ofPacketOutBuilder) SetICMPID(id uint16) PacketOutBuilder { if b.pktOut.ICMPHeader == nil { b.pktOut.ICMPHeader = new(protocol.ICMP) @@ -283,7 +284,7 @@ func (b *ofPacketOutBuilder) SetInport(inPort uint32) PacketOutBuilder { } // SetOutport sets the output port of the packetOut message. If the message is expected to go through OVS pipeline -// from table0, use openflow13.P_TABLE, which is also the default value. +// from table0, use openflow15.P_TABLE, which is also the default value. func (b *ofPacketOutBuilder) SetOutport(outport uint32) PacketOutBuilder { b.pktOut.OutPort = outport return b @@ -296,16 +297,28 @@ func (b *ofPacketOutBuilder) SetL4Packet(packet util.Message) PacketOutBuilder { return b } -// 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 { - act, _ := ofctrl.NewNXLoadAction(name, data, rng.ToNXRange()) +// AddSetIPToSAction sets the IP_TOS field in the packet-out message. The action clears the two ECN bits as 0, +// and only 2-7 bits of the DSCP field in IP header is set. +func (b *ofPacketOutBuilder) AddSetIPTOSAction(data uint8) PacketOutBuilder { + field, _ := openflow15.FindFieldHeaderByName(NxmFieldIPToS, true) + field.Value = &openflow15.IpDscpField{Dscp: data << IPDSCPToSRange.Offset()} + field.Mask = &openflow15.IpDscpField{Dscp: uint8(0xff) >> (8 - IPDSCPToSRange.Length()) << IPDSCPToSRange.Offset()} + act := ofctrl.NewSetFieldAction(field) 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) + valueData := mark.value + mask := uint32(0) + if mark.field.rng != nil { + mask = ^mask >> (32 - mark.field.rng.Length()) << mark.field.rng.Offset() + valueData = valueData << mark.field.rng.Offset() + } + tgtField := openflow15.NewRegMatchFieldWithMask(mark.field.regID, valueData, mask) + act := ofctrl.NewSetFieldAction(tgtField) + b.pktOut.Actions = append(b.pktOut.Actions, act) + return b } func (b *ofPacketOutBuilder) AddResubmitAction(inPort *uint16, table *uint8) PacketOutBuilder { @@ -319,6 +332,9 @@ func (b *ofPacketOutBuilder) Done() *ofctrl.PacketOut { klog.Errorf("Invalid PacketOutBuilder: IP header and IPv6 header are not allowed to exist at the same time") return nil } + if b.pktOut.InPort == 0 { + b.pktOut.InPort = openflow15.P_CONTROLLER + } if b.pktOut.IPv6Header == nil { if b.pktOut.ICMPHeader != nil { if len(b.pktOut.ICMPHeader.Data) == 0 { diff --git a/pkg/ovs/openflow/ofctrl_packetout_test.go b/pkg/ovs/openflow/ofctrl_packetout_test.go index 64001df1008..1e2653a0f8b 100644 --- a/pkg/ovs/openflow/ofctrl_packetout_test.go +++ b/pkg/ovs/openflow/ofctrl_packetout_test.go @@ -19,6 +19,7 @@ import ( "reflect" "testing" + "antrea.io/libOpenflow/openflow15" "antrea.io/libOpenflow/protocol" "antrea.io/ofnet/ofctrl" ) @@ -782,6 +783,9 @@ func Test_ofPacketOutBuilder_Done(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + if tt.want != nil && tt.want.InPort == 0 { + tt.want.InPort = openflow15.P_CONTROLLER + } b := &ofPacketOutBuilder{ pktOut: tt.fields.pktOut, icmpID: tt.fields.icmpID, @@ -805,7 +809,7 @@ func Test_ofPacketOutBuilder_Done(t *testing.T) { t.Errorf("Done() = %v, want %v", got.ICMPHeader, tt.want.ICMPHeader) } if !reflect.DeepEqual(got.TCPHeader, tt.want.TCPHeader) { - t.Errorf("Done() = %v, want %v", got.TCPHeader, tt.want.TCPHeader) + t.Errorf("Done() = %+v, want %+v", got.TCPHeader, tt.want.TCPHeader) } if !reflect.DeepEqual(got.UDPHeader, tt.want.UDPHeader) { t.Errorf("Done() = %v, want %v", got.UDPHeader, tt.want.UDPHeader) @@ -817,7 +821,7 @@ func Test_ofPacketOutBuilder_Done(t *testing.T) { t.Errorf("Done() = %v, want %v", got.IPv6Header, tt.want.IPv6Header) } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Done() = %v, want %v", got, tt.want) + t.Errorf("Done() = %+v, want %+v", got, tt.want) } }) } diff --git a/pkg/ovs/openflow/testing/mock_openflow.go b/pkg/ovs/openflow/testing/mock_openflow.go index 45a1e3f474c..6f1b6ef6ed7 100644 --- a/pkg/ovs/openflow/testing/mock_openflow.go +++ b/pkg/ovs/openflow/testing/mock_openflow.go @@ -917,6 +917,20 @@ func (mr *MockActionMockRecorder) Move(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Move", reflect.TypeOf((*MockAction)(nil).Move), arg0, arg1) } +// MoveFromTunMetadata mocks base method +func (m *MockAction) MoveFromTunMetadata(arg0 int, arg1 string, arg2, arg3 openflow.Range, arg4 byte) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MoveFromTunMetadata", arg0, arg1, arg2, arg3, arg4) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// MoveFromTunMetadata indicates an expected call of MoveFromTunMetadata +func (mr *MockActionMockRecorder) MoveFromTunMetadata(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MoveFromTunMetadata", reflect.TypeOf((*MockAction)(nil).MoveFromTunMetadata), arg0, arg1, arg2, arg3, arg4) +} + // MoveRange mocks base method func (m *MockAction) MoveRange(arg0, arg1 string, arg2, arg3 openflow.Range) openflow.FlowBuilder { m.ctrl.T.Helper() diff --git a/pkg/ovs/ovsconfig/ovs_client.go b/pkg/ovs/ovsconfig/ovs_client.go index 67f784f3d2c..69dbf108e97 100644 --- a/pkg/ovs/ovsconfig/ovs_client.go +++ b/pkg/ovs/ovsconfig/ovs_client.go @@ -54,8 +54,8 @@ const ( openvSwitchSchema = "Open_vSwitch" // Openflow protocol version 1.0. openflowProtoVersion10 = "OpenFlow10" - // Openflow protocol version 1.3. - openflowProtoVersion13 = "OpenFlow13" + // Openflow protocol version 1.5. + openflowProtoVersion15 = "OpenFlow15" // Maximum allowed value of ofPortRequest. ofPortRequestMax = 65279 hardwareOffload = "hw-offload" @@ -102,7 +102,7 @@ func NewOVSBridge(bridgeName string, ovsDatapathType OVSDatapathType, ovsdb *ovs } // Create looks up or creates the bridge. If the bridge with name bridgeName -// does not exist, it will be created. Openflow protocol version 1.0 and 1.3 +// does not exist, it will be created. Openflow protocol version 1.0 and 1.5 // will be enabled for the bridge. func (br *OVSBridge) Create() Error { var err Error @@ -150,13 +150,13 @@ func (br *OVSBridge) lookupByName() (bool, Error) { func (br *OVSBridge) updateBridgeConfiguration() Error { tx := br.ovsdb.Transaction(openvSwitchSchema) - // Use Openflow protocol version 1.0 and 1.3. + // Use Openflow protocol version 1.0 and 1.5. tx.Update(dbtransaction.Update{ Table: "Bridge", Where: [][]interface{}{{"name", "==", br.name}}, Row: map[string]interface{}{ "protocols": makeOVSDBSetFromList([]string{openflowProtoVersion10, - openflowProtoVersion13}), + openflowProtoVersion15}), "datapath_type": br.datapathType, }, }) @@ -172,9 +172,9 @@ func (br *OVSBridge) create() Error { tx := br.ovsdb.Transaction(openvSwitchSchema) bridge := Bridge{ Name: br.name, - // Use Openflow protocol version 1.0 and 1.3. + // Use Openflow protocol version 1.0 and 1.5. Protocols: makeOVSDBSetFromList([]string{openflowProtoVersion10, - openflowProtoVersion13}), + openflowProtoVersion15}), DatapathType: string(br.datapathType), } namedUUID := tx.Insert(dbtransaction.Insert{ diff --git a/pkg/ovs/ovsctl/ofctl.go b/pkg/ovs/ovsctl/ofctl.go index abe50a53211..7f7fb6a79e0 100644 --- a/pkg/ovs/ovsctl/ofctl.go +++ b/pkg/ovs/ovsctl/ofctl.go @@ -84,7 +84,7 @@ func (c *ovsCtlClient) DumpGroup(groupID uint32) (string, error) { // versions of OpenFlow always dump all groups. But when OpenFlow // version is not specified, ovs-ofctl defaults to use OpenFlow10 but // with the Nicira extensions enabled, which can support dumping a - // single group too. So here, we do not specify Openflow13 to run the + // single group too. So here, we do not specify Openflow15 to run the // command. groupDump, err := c.runOfctlCmd(false, "dump-groups", strconv.FormatUint(uint64(groupID), 10)) if err != nil { @@ -163,11 +163,11 @@ func (c *ovsCtlClient) SetPortNoFlood(ofport int) error { return nil } -func (c *ovsCtlClient) runOfctlCmd(openflow13 bool, cmd string, args ...string) ([]byte, error) { +func (c *ovsCtlClient) runOfctlCmd(openflow15 bool, cmd string, args ...string) ([]byte, error) { cmdStr := fmt.Sprintf("ovs-ofctl %s %s", cmd, c.bridge) cmdStr = cmdStr + " " + strings.Join(args, " ") - if openflow13 { - cmdStr += " -O Openflow13" + if openflow15 { + cmdStr += " -O Openflow15" } out, err := getOVSCommand(cmdStr).Output() if err != nil { @@ -177,7 +177,7 @@ func (c *ovsCtlClient) runOfctlCmd(openflow13 bool, cmd string, args ...string) } func (c *ovsCtlClient) RunOfctlCmd(cmd string, args ...string) ([]byte, error) { - // Default to use Openflow13. + // Default to use Openflow15. return c.runOfctlCmd(true, cmd, args...) } diff --git a/plugins/octant/go.sum b/plugins/octant/go.sum index 29d86dc1950..6865440baf0 100644 --- a/plugins/octant/go.sum +++ b/plugins/octant/go.sum @@ -1,5 +1,5 @@ -antrea.io/libOpenflow v0.6.2/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o= -antrea.io/ofnet v0.5.7/go.mod h1:8TJVF6MLe9/gZ/KbhGUvULs9/TxssepEaYEe+o1SEgs= +antrea.io/libOpenflow v0.8.0/go.mod h1:CzEJZxDNAupiGxeL5VOw92PsxfyvehEAvE3PiC6gr8o= +antrea.io/ofnet v0.6.0/go.mod h1:qWqi11pI3kBYcS9SYWm92ZOiOPBx04Jx21cDmJlJhOg= bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= diff --git a/test/e2e/proxy_test.go b/test/e2e/proxy_test.go index db9ac888078..fba471b11db 100644 --- a/test/e2e/proxy_test.go +++ b/test/e2e/proxy_test.go @@ -941,9 +941,10 @@ func testProxyEndpointLifeCycle(ipFamily *corev1.IPFamily, data *TestData, t *te var groupKeywords []string if *ipFamily == corev1.IPv6Protocol { - groupKeywords = append(groupKeywords, fmt.Sprintf("set_field:0x%s->xxreg3", strings.TrimPrefix(hex.EncodeToString(*nginxIPs.ipv6), "0"))) + groupKeywords = append(groupKeywords, + fmt.Sprintf("load:0x%s->NXM_NX_XXREG3[0..63],load:0x%s->NXM_NX_XXREG3[64..127]", strings.TrimLeft(hex.EncodeToString((*nginxIPs.ipv6)[8:16]), "0"), strings.TrimLeft(hex.EncodeToString((*nginxIPs.ipv6)[:8]), "0"))) } else { - groupKeywords = append(groupKeywords, fmt.Sprintf("0x%s->NXM_NX_REG3[]", strings.TrimPrefix(hex.EncodeToString(nginxIPs.ipv4.To4()), "0"))) + groupKeywords = append(groupKeywords, fmt.Sprintf("0x%s->NXM_NX_REG3[]", strings.TrimLeft(hex.EncodeToString(nginxIPs.ipv4.To4()), "0"))) } for tableName, keyword := range keywords { @@ -1063,7 +1064,10 @@ func testProxyServiceLifeCycle(ipFamily *corev1.IPFamily, ingressIPs []string, d var groupKeyword string if *ipFamily == corev1.IPv6Protocol { - groupKeyword = fmt.Sprintf("set_field:0x%s->xxreg3,load:0x%x->NXM_NX_REG4[0..15]", strings.TrimLeft(hex.EncodeToString(nginxIPs.ipv6.To16()), "0"), 80) + groupKeyword = fmt.Sprintf("load:0x%s->NXM_NX_XXREG3[0..63],load:0x%s->NXM_NX_XXREG3[64..127],load:0x%x->NXM_NX_REG4[0..15]", + strings.TrimLeft(hex.EncodeToString(nginxIPs.ipv6.To16()[8:16]), "0"), + strings.TrimLeft(hex.EncodeToString(nginxIPs.ipv6.To16()[:8]), "0"), + 80) } else { groupKeyword = fmt.Sprintf("load:0x%s->NXM_NX_REG3[],load:0x%x->NXM_NX_REG4[0..15]", strings.TrimLeft(hex.EncodeToString(nginxIPs.ipv4.To4()), "0"), 80) } diff --git a/test/integration/agent/openflow_test.go b/test/integration/agent/openflow_test.go index b3fdc916206..12cbd83be34 100644 --- a/test/integration/agent/openflow_test.go +++ b/test/integration/agent/openflow_test.go @@ -733,11 +733,11 @@ func expectedProxyServiceGroupAndFlows(gid uint32, svc svcConfig, endpointList [ svcFlows := expectTableFlows{tableName: "ServiceLB", flows: []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,%s,reg4=0x10000/0x70000,nw_dst=%s,tp_dst=%d", string(svc.protocol), svc.ip.String(), svc.port), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG4[16..18],load:0x1->NXM_NX_REG0[9],load:0x%x->NXM_NX_REG7[],group:%d", serviceLearnReg, gid, gid), + ActStr: fmt.Sprintf("set_field:0x%x/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x%x->reg7,group:%d", serviceLearnReg<<16, gid, gid), }, { MatchStr: fmt.Sprintf("priority=190,%s,reg4=0x30000/0x70000,nw_dst=%s,tp_dst=%d", string(svc.protocol), svc.ip.String(), svc.port), - ActStr: fmt.Sprintf("learn(table=SessionAffinity,hard_timeout=%d,priority=200,delete_learned,cookie=0x%x,eth_type=0x800,nw_proto=%d,%s,NXM_OF_IP_DST[],NXM_OF_IP_SRC[],load:NXM_NX_REG3[]->NXM_NX_REG3[],load:NXM_NX_REG4[0..15]->NXM_NX_REG4[0..15],load:0x2->NXM_NX_REG4[16..18],load:0x1->NXM_NX_REG0[9]),load:0x2->NXM_NX_REG4[16..18],goto_table:EndpointDNAT", stickyAge, cookieAllocator.RequestWithObjectID(cookie.Service, gid).Raw(), nw_proto, learnProtoField), + ActStr: fmt.Sprintf("learn(table=SessionAffinity,hard_timeout=%d,priority=200,delete_learned,cookie=0x%x,eth_type=0x800,nw_proto=%d,%s,NXM_OF_IP_DST[],NXM_OF_IP_SRC[],load:NXM_NX_REG3[]->NXM_NX_REG3[],load:NXM_NX_REG4[0..15]->NXM_NX_REG4[0..15],load:0x2->NXM_NX_REG4[16..18],load:0x1->NXM_NX_REG0[9]),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT", stickyAge, cookieAllocator.RequestWithObjectID(cookie.Service, gid).Raw(), nw_proto, learnProtoField), }, }} epDNATFlows := expectTableFlows{tableName: "EndpointDNAT", flows: []*ofTestUtils.ExpectFlow{}} @@ -746,19 +746,19 @@ func expectedProxyServiceGroupAndFlows(gid uint32, svc svcConfig, endpointList [ for _, ep := range endpointList { epIP := ipToHexString(net.ParseIP(ep.IP())) epPort, _ := ep.Port() - bucket := fmt.Sprintf("weight:100,actions=load:%s->NXM_NX_REG3[],load:0x%x->NXM_NX_REG4[0..15],resubmit(,%d)", epIP, epPort, ofClient.EndpointDNATTable.GetID()) + bucket := fmt.Sprintf("weight:100,actions=set_field:%s->reg3,set_field:0x%x/0xffff->reg4,resubmit(,%d)", epIP, epPort, ofClient.EndpointDNATTable.GetID()) groupBuckets = append(groupBuckets, bucket) unionVal := (0b010 << 16) + uint32(epPort) epDNATFlows.flows = append(epDNATFlows.flows, &ofTestUtils.ExpectFlow{ MatchStr: fmt.Sprintf("priority=200,%s,reg3=%s,reg4=0x%x/0x7ffff", string(svc.protocol), epIP, unionVal), - ActStr: fmt.Sprintf("ct(commit,table=EgressRule,zone=65520,nat(dst=%s:%d),exec(load:0x1->NXM_NX_CT_MARK[4],move:NXM_NX_REG0[0..3]->NXM_NX_CT_MARK[0..3])", ep.IP(), epPort), + ActStr: fmt.Sprintf("ct(commit,table=EgressRule,zone=65520,nat(dst=%s:%d),exec(set_field:0x10/0x10->ct_mark,move:NXM_NX_REG0[0..3]->NXM_NX_CT_MARK[0..3])", ep.IP(), epPort), }) if ep.GetIsLocal() { hairpinFlows.flows = append(hairpinFlows.flows, &ofTestUtils.ExpectFlow{ MatchStr: fmt.Sprintf("priority=190,ct_state=+new+trk,ip,nw_src=%s,nw_dst=%s", ep.IP(), ep.IP()), - ActStr: "ct(commit,table=SNAT,zone=65520,exec(load:0x1->NXM_NX_CT_MARK[5],load:0x1->NXM_NX_CT_MARK[6]))", + ActStr: "ct(commit,table=SNAT,zone=65520,exec(set_field:0x20/0x20->ct_mark,set_field:0x40/0x40->ct_mark))", }) } } @@ -861,9 +861,8 @@ func checkConjunctionFlows(t *testing.T, ruleTable string, priority int, ruleID nextTable = ofClient.EgressMetricTable.GetName() } - flow := &ofTestUtils.ExpectFlow{MatchStr: conjunctionActionMatch, ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG%d[],ct(commit,table=%s,zone=65520,exec(load:0x%x->NXM_NX_CT_LABEL[0..31])", ruleID, conjReg, nextTable, ruleID)} + flow := &ofTestUtils.ExpectFlow{MatchStr: conjunctionActionMatch, ActStr: fmt.Sprintf("set_field:0x%x->reg%d,ct(commit,table=%s,zone=65520,exec(set_field:0x%x/0xffffffff->ct_label)", ruleID, conjReg, nextTable, ruleID)} testFunc(t, ofTestUtils.OfctlFlowMatch(flowList, ruleTable, flow), "Failed to update conjunction action flow") - useIPv4 := false useIPv6 := false @@ -1027,7 +1026,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, actionNotAntreaFlexibleIPAMString := "" matchRewriteMACMarkString := ",reg0=0x200/0x200" if isAntreaFlexibleIPAM { - actionNotAntreaFlexibleIPAMString = ",load:0x1->NXM_NX_REG4[20],load:0x1->NXM_NX_REG0[9]" + actionNotAntreaFlexibleIPAMString = ",set_field:0x100000/0x100000->reg4,set_field:0x200/0x200->reg0" matchRewriteMACMarkString = "" } flows := []expectTableFlows{ @@ -1036,7 +1035,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=190,in_port=%d", podOFPort), - ActStr: fmt.Sprintf("load:0x3->NXM_NX_REG0[0..3]%s,goto_table:SpoofGuard", actionNotAntreaFlexibleIPAMString), + ActStr: fmt.Sprintf("set_field:0x3/0xf->reg0%s,goto_table:SpoofGuard", actionNotAntreaFlexibleIPAMString), }, }, }, @@ -1045,7 +1044,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,dl_dst=%s", podMAC.String()), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[8],goto_table:IngressSecurityClassifier", podOFPort), + ActStr: fmt.Sprintf("set_field:0x%x->reg1,set_field:0x100/0x100->reg0,goto_table:IngressSecurityClassifier", podOFPort), }, }, }, @@ -1070,7 +1069,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=210,ip,in_port=%d%s,dl_dst=%s", 3, matchVlanVIDString, podMAC.String()), - ActStr: fmt.Sprintf("load:0x1->NXM_NX_REG8[12..15],load:0x4->NXM_NX_REG0[0..3],load:%s->NXM_NX_REG8[0..11],goto_table:UnSNAT", vlanVIDString), + ActStr: fmt.Sprintf("set_field:0x1000/0xf000->reg8,set_field:0x4/0xf->reg0,set_field:%s/0xfff->reg8,goto_table:UnSNAT", vlanVIDString), }, }, }}...) @@ -1080,7 +1079,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=210,ip,in_port=LOCAL,vlan_tci=0x0000/0x1fff,dl_dst=%s", podMAC.String()), - ActStr: fmt.Sprintf("load:0x1->NXM_NX_REG8[12..15],load:0x5->NXM_NX_REG0[0..3],goto_table:UnSNAT"), + ActStr: fmt.Sprintf("set_field:0x1000/0xf000->reg8,set_field:0x5/0xf->reg0,goto_table:UnSNAT"), }, }, }}...) @@ -1129,7 +1128,7 @@ func preparePodFlows(podIPs []net.IP, podMAC net.HardwareAddr, podOFPort uint32, vlanType = 3 } if isAntreaFlexibleIPAM { - actionSetCtZoneField = fmt.Sprintf("load:0x%x->NXM_NX_REG8[12..15],load:%s->NXM_NX_REG8[0..11],", vlanType, vlanVIDString) + actionSetCtZoneField = fmt.Sprintf("set_field:0x%x/0xf000->reg8,set_field:%s/0xfff->reg8,", vlanType<<12, vlanVIDString) } flows = append(flows, expectTableFlows{ @@ -1163,7 +1162,7 @@ func prepareGatewayFlows(gwIPs []net.IP, gwMAC net.HardwareAddr, vMAC net.Hardwa []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,in_port=%d", agentconfig.HostGatewayOFPort), - ActStr: "load:0x2->NXM_NX_REG0[0..3],goto_table:SpoofGuard", + ActStr: "set_field:0x2/0xf->reg0,goto_table:SpoofGuard", }, }, }, @@ -1172,7 +1171,7 @@ func prepareGatewayFlows(gwIPs []net.IP, gwMAC net.HardwareAddr, vMAC net.Hardwa []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,dl_dst=%s", gwMAC.String()), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[8],goto_table:IngressSecurityClassifier", agentconfig.HostGatewayOFPort), + ActStr: fmt.Sprintf("set_field:0x%x->reg1,set_field:0x100/0x100->reg0,goto_table:IngressSecurityClassifier", agentconfig.HostGatewayOFPort), }, }, }, @@ -1183,7 +1182,7 @@ func prepareGatewayFlows(gwIPs []net.IP, gwMAC net.HardwareAddr, vMAC net.Hardwa actionSetCtZoneField := "" vlanType := uint16(1) if connectUplinkToBridge { - actionSetCtZoneField = fmt.Sprintf("load:0x%x->NXM_NX_REG8[12..15],", vlanType) + actionSetCtZoneField = fmt.Sprintf("set_field:0x%x/0xf000->reg8,", vlanType<<12) } if gwIP.To4() != nil { ipProtoStr = "ip" @@ -1235,11 +1234,11 @@ func prepareGatewayFlows(gwIPs []net.IP, gwMAC net.HardwareAddr, vMAC net.Hardwa []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=210,ct_state=+rpl+trk,ct_mark=0x2/0xf,%s", ipProtoStr), - ActStr: fmt.Sprintf("set_field:%s->eth_dst,load:0x2->NXM_NX_REG0[4..7],goto_table:L3DecTTL", gwMAC.String()), + ActStr: fmt.Sprintf("set_field:%s->eth_dst,set_field:0x20/0xf0->reg0,goto_table:L3DecTTL", gwMAC.String()), }, { MatchStr: fmt.Sprintf("priority=210,%s,%s=%s", ipProtoStr, nwDstStr, gwIP.String()), - ActStr: fmt.Sprintf("set_field:%s->eth_dst,load:0x2->NXM_NX_REG0[4..7],goto_table:L3DecTTL", gwMAC.String()), + ActStr: fmt.Sprintf("set_field:%s->eth_dst,set_field:0x20/0xf0->reg0,goto_table:L3DecTTL", gwMAC.String()), }, }, }, @@ -1256,7 +1255,7 @@ func prepareTunnelFlows(tunnelPort uint32, vMAC net.HardwareAddr) []expectTableF []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,in_port=%d", tunnelPort), - ActStr: "load:0x1->NXM_NX_REG0[0..3],load:0x1->NXM_NX_REG0[9],goto_table:UnSNAT", + ActStr: "set_field:0x1/0xf->reg0,set_field:0x200/0x200->reg0,goto_table:UnSNAT", }, }, }, @@ -1265,7 +1264,7 @@ func prepareTunnelFlows(tunnelPort uint32, vMAC net.HardwareAddr) []expectTableF []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,dl_dst=%s", vMAC.String()), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[8],goto_table:IngressSecurityClassifier", agentconfig.DefaultTunOFPort), + ActStr: fmt.Sprintf("set_field:0x%x->reg1,set_field:0x100/0x100->reg0,goto_table:IngressSecurityClassifier", agentconfig.DefaultTunOFPort), }, }, }, @@ -1283,7 +1282,7 @@ func prepareNodeFlows(peerSubnet net.IPNet, peerGwIP, peerNodeIP net.IP, vMAC, l []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,arp,arp_tpa=%s,arp_op=1", peerGwIP.String()), - ActStr: fmt.Sprintf("move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],set_field:%s->eth_src,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],set_field:%s->arp_sha,move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],set_field:%s->arp_spa,IN_PORT", vMAC.String(), vMAC.String(), peerGwIP.String()), + ActStr: fmt.Sprintf("move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],set_field:%s->eth_src,set_field:2->arp_op,move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],set_field:%s->arp_sha,move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],set_field:%s->arp_spa,IN_PORT", vMAC.String(), vMAC.String(), peerGwIP.String()), }, }, }) @@ -1296,7 +1295,7 @@ func prepareNodeFlows(peerSubnet net.IPNet, peerGwIP, peerNodeIP net.IP, vMAC, l []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,%s,%s=%s", ipProtoStr, nwDstFieldName, peerSubnet.String()), - ActStr: fmt.Sprintf("set_field:%s->eth_src,set_field:%s->eth_dst,set_field:%s->tun_dst,load:0x1->NXM_NX_REG0[4..7],goto_table:L3DecTTL", localGwMAC.String(), vMAC.String(), peerNodeIP.String()), + ActStr: fmt.Sprintf("set_field:%s->eth_src,set_field:%s->eth_dst,set_field:%s->tun_dst,set_field:0x10/0xf0->reg0,goto_table:L3DecTTL", localGwMAC.String(), vMAC.String(), peerNodeIP.String()), }, }, }) @@ -1306,7 +1305,7 @@ func prepareNodeFlows(peerSubnet net.IPNet, peerGwIP, peerNodeIP net.IP, vMAC, l []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,%s,reg4=0x100000/0x100000,reg8=0/0xfff,%s=%s", ipProtoStr, nwDstFieldName, peerSubnet.String()), - ActStr: fmt.Sprintf("set_field:%s->eth_dst,load:0x4->NXM_NX_REG0[4..7],goto_table:L3DecTTL", peerNodeMAC.String()), + ActStr: fmt.Sprintf("set_field:%s->eth_dst,set_field:0x40/0xf0->reg0,goto_table:L3DecTTL", peerNodeMAC.String()), }, }, }) @@ -1322,7 +1321,7 @@ func prepareServiceHelperFlows() []expectTableFlows { []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprint("priority=0"), - ActStr: fmt.Sprint("load:0x1->NXM_NX_REG4[16..18]"), + ActStr: fmt.Sprint("set_field:0x10000/0x70000->reg4"), }, }, }, @@ -1359,7 +1358,7 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { } tableL3ForwardingFlows := expectTableFlows{ "L3Forwarding", - []*ofTestUtils.ExpectFlow{{MatchStr: "priority=0", ActStr: "load:0x2->NXM_NX_REG0[4..7],goto_table:L2ForwardingCalc"}}, + []*ofTestUtils.ExpectFlow{{MatchStr: "priority=0", ActStr: "set_field:0x20/0xf0->reg0,goto_table:L2ForwardingCalc"}}, } tableL3DecTTLFlows := expectTableFlows{ tableName: "L3DecTTL", @@ -1398,15 +1397,15 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { tableSNATFlows.flows = append(tableSNATFlows.flows, &ofTestUtils.ExpectFlow{ MatchStr: "priority=200,ct_state=+new+trk,ct_mark=0x40/0x40,ip,reg0=0x2/0xf", - ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65521,nat(src=%s),exec(load:0x1->NXM_NX_CT_MARK[4],load:0x1->NXM_NX_CT_MARK[6]))", agentconfig.VirtualServiceIPv4), + ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65521,nat(src=%s),exec(set_field:0x10/0x10->ct_mark,set_field:0x40/0x40->ct_mark))", agentconfig.VirtualServiceIPv4), }, &ofTestUtils.ExpectFlow{ MatchStr: "priority=200,ct_state=+new+trk,ct_mark=0x40/0x40,ip,reg0=0x3/0xf", - ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65521,nat(src=%s),exec(load:0x1->NXM_NX_CT_MARK[4],load:0x1->NXM_NX_CT_MARK[6]))", config.nodeConfig.GatewayConfig.IPv4), + ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65521,nat(src=%s),exec(set_field:0x10/0x10->ct_mark,set_field:0x40/0x40->ct_mark))", config.nodeConfig.GatewayConfig.IPv4), }, &ofTestUtils.ExpectFlow{ MatchStr: "priority=190,ct_state=+new+trk,ct_mark=0x20/0x20,ip,reg0=0x2/0xf", - ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65521,nat(src=%s),exec(load:0x1->NXM_NX_CT_MARK[4]))", config.nodeConfig.GatewayConfig.IPv4), + ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65521,nat(src=%s),exec(set_field:0x10/0x10->ct_mark))", config.nodeConfig.GatewayConfig.IPv4), }, &ofTestUtils.ExpectFlow{ MatchStr: "priority=200,ct_state=-new-rpl+trk,ct_mark=0x20/0x20,ip", @@ -1418,8 +1417,8 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { &ofTestUtils.ExpectFlow{MatchStr: fmt.Sprintf("priority=200,ip,reg0=0/0x200%s,nw_dst=%s", matchVLANString, podCIDR), ActStr: "goto_table:L2ForwardingCalc"}, ) tableSNATMarkFlows.flows = append(tableSNATMarkFlows.flows, - &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ip,reg0=0x22/0xff", ActStr: fmt.Sprintf("ct(commit,table=SNAT,zone=%s,exec(load:0x1->NXM_NX_CT_MARK[5],load:0x1->NXM_NX_CT_MARK[6]))", ctZone)}, - &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ip,reg0=0x12/0xff,reg4=0x200000/0x200000", ActStr: fmt.Sprintf("ct(commit,table=SNAT,zone=%s,exec(load:0x1->NXM_NX_CT_MARK[5]))", ctZone)}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ip,reg0=0x22/0xff", ActStr: fmt.Sprintf("ct(commit,table=SNAT,zone=%s,exec(set_field:0x20/0x20->ct_mark,set_field:0x40/0x40->ct_mark))", ctZone)}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ip,reg0=0x12/0xff,reg4=0x200000/0x200000", ActStr: fmt.Sprintf("ct(commit,table=SNAT,zone=%s,exec(set_field:0x20/0x20->ct_mark))", ctZone)}, ) tableL3DecTTLFlows.flows = append(tableL3DecTTLFlows.flows, &ofTestUtils.ExpectFlow{MatchStr: "priority=210,ip,reg0=0x2/0xf", ActStr: "goto_table:SNATMark"}, @@ -1443,15 +1442,15 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { tableSNATFlows.flows = append(tableSNATFlows.flows, &ofTestUtils.ExpectFlow{ MatchStr: "priority=200,ct_state=+new+trk,ct_mark=0x40/0x40,ipv6,reg0=0x2/0xf", - ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65511,nat(src=%s),exec(load:0x1->NXM_NX_CT_MARK[4],load:0x1->NXM_NX_CT_MARK[6]))", agentconfig.VirtualServiceIPv6), + ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65511,nat(src=%s),exec(set_field:0x10/0x10->ct_mark,set_field:0x40/0x40->ct_mark))", agentconfig.VirtualServiceIPv6), }, &ofTestUtils.ExpectFlow{ MatchStr: "priority=200,ct_state=+new+trk,ct_mark=0x40/0x40,ipv6,reg0=0x3/0xf", - ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65511,nat(src=%s),exec(load:0x1->NXM_NX_CT_MARK[4],load:0x1->NXM_NX_CT_MARK[6]))", config.nodeConfig.GatewayConfig.IPv6), + ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65511,nat(src=%s),exec(set_field:0x10/0x10->ct_mark,set_field:0x40/0x40->ct_mark))", config.nodeConfig.GatewayConfig.IPv6), }, &ofTestUtils.ExpectFlow{ MatchStr: "priority=190,ct_state=+new+trk,ct_mark=0x20/0x20,ipv6,reg0=0x2/0xf", - ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65511,nat(src=%s),exec(load:0x1->NXM_NX_CT_MARK[4]))", config.nodeConfig.GatewayConfig.IPv6), + ActStr: fmt.Sprintf("ct(commit,table=L2ForwardingCalc,zone=65511,nat(src=%s),exec(set_field:0x10/0x10->ct_mark))", config.nodeConfig.GatewayConfig.IPv6), }, &ofTestUtils.ExpectFlow{ MatchStr: "priority=200,ct_state=-new-rpl+trk,ct_mark=0x20/0x20,ipv6", @@ -1463,8 +1462,8 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { &ofTestUtils.ExpectFlow{MatchStr: fmt.Sprintf("priority=200,ipv6,reg0=0/0x200,ipv6_dst=%s", podCIDR), ActStr: "goto_table:L2ForwardingCalc"}, ) tableSNATMarkFlows.flows = append(tableSNATMarkFlows.flows, - &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ipv6,reg0=0x22/0xff", ActStr: "ct(commit,table=SNAT,zone=65510,exec(load:0x1->NXM_NX_CT_MARK[5],load:0x1->NXM_NX_CT_MARK[6]))"}, - &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ipv6,reg0=0x12/0xff,reg4=0x200000/0x200000", ActStr: "ct(commit,table=SNAT,zone=65510,exec(load:0x1->NXM_NX_CT_MARK[5]))"}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ipv6,reg0=0x22/0xff", ActStr: "ct(commit,table=SNAT,zone=65510,exec(set_field:0x20/0x20->ct_mark,set_field:0x40/0x40->ct_mark))"}, + &ofTestUtils.ExpectFlow{MatchStr: "priority=200,ct_state=+new+trk,ipv6,reg0=0x12/0xff,reg4=0x200000/0x200000", ActStr: "ct(commit,table=SNAT,zone=65510,exec(set_field:0x20/0x20->ct_mark))"}, ) tableL3DecTTLFlows.flows = append(tableL3DecTTLFlows.flows, &ofTestUtils.ExpectFlow{MatchStr: "priority=210,ipv6,reg0=0x2/0xf", ActStr: "goto_table:SNATMark"}, @@ -1475,7 +1474,7 @@ func prepareDefaultFlows(config *testConfig) []expectTableFlows { tableARPResponderFlows.flows = append(tableARPResponderFlows.flows, &ofTestUtils.ExpectFlow{ MatchStr: fmt.Sprintf("priority=200,arp,arp_tpa=%s,arp_op=1", config.nodeConfig.GatewayConfig.IPv4.String()), - ActStr: fmt.Sprintf("move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],set_field:%s->eth_src,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],set_field:%s->arp_sha,move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],set_field:%s->arp_spa,IN_PORT", config.nodeConfig.GatewayConfig.MAC.String(), config.nodeConfig.GatewayConfig.MAC.String(), config.nodeConfig.GatewayConfig.IPv4.String()), + ActStr: fmt.Sprintf("move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],set_field:%s->eth_src,set_field:2->arp_op,move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],set_field:%s->arp_sha,move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],set_field:%s->arp_spa,IN_PORT", config.nodeConfig.GatewayConfig.MAC.String(), config.nodeConfig.GatewayConfig.MAC.String(), config.nodeConfig.GatewayConfig.IPv4.String()), }, ) } @@ -1593,7 +1592,7 @@ func expectedExternalFlows(ipProtoStr, gwMACStr string) []expectTableFlows { }, { MatchStr: "priority=0", - ActStr: "load:0x2->NXM_NX_REG0[4..7],goto_table:L2ForwardingCalc", + ActStr: "set_field:0x20/0xf0->reg0,goto_table:L2ForwardingCalc", }, }, }, @@ -1615,15 +1614,15 @@ func prepareEgressMarkFlows(snatIP net.IP, mark, podOFPort, podOFPortRemote uint []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,ct_state=+new+trk,%s,%s=%s", ipProtoStr, tunDstFieldName, snatIP), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_PKT_MARK[0..7],load:0x2->NXM_NX_REG0[4..7],goto_table:L2ForwardingCalc", mark), + ActStr: fmt.Sprintf("set_field:0x%x/0xff->pkt_mark,set_field:0x20/0xf0->reg0,goto_table:L2ForwardingCalc", mark), }, { MatchStr: fmt.Sprintf("priority=200,ct_state=+new+trk,%s,in_port=%d", ipProtoStr, podOFPort), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_PKT_MARK[0..7],load:0x2->NXM_NX_REG0[4..7],goto_table:L2ForwardingCalc", mark), + ActStr: fmt.Sprintf("set_field:0x%x/0xff->pkt_mark,set_field:0x20/0xf0->reg0,goto_table:L2ForwardingCalc", mark), }, { MatchStr: fmt.Sprintf("priority=200,%s,in_port=%d", ipProtoStr, podOFPortRemote), - ActStr: fmt.Sprintf("set_field:%s->eth_src,set_field:%s->eth_dst,set_field:%s->%s,load:0x1->NXM_NX_REG0[4..7],goto_table:L2ForwardingCalc", localGwMAC.String(), vMAC.String(), snatIP, tunDstFieldName), + ActStr: fmt.Sprintf("set_field:%s->eth_src,set_field:%s->eth_dst,set_field:%s->%s,set_field:0x10/0xf0->reg0,goto_table:L2ForwardingCalc", localGwMAC.String(), vMAC.String(), snatIP, tunDstFieldName), }, }, }, @@ -1637,7 +1636,7 @@ func prepareTrafficControlFlows(sourceOFPorts []uint32, targetOFPort, returnOFPo []*ofTestUtils.ExpectFlow{ { MatchStr: fmt.Sprintf("priority=200,in_port=%d", returnOFPort), - ActStr: "load:0x6->NXM_NX_REG0[0..3],goto_table:L3Forwarding", + ActStr: "set_field:0x6/0xf->reg0,goto_table:L3Forwarding", }, }, }, @@ -1668,11 +1667,11 @@ func prepareTrafficControlFlows(sourceOFPorts []uint32, targetOFPort, returnOFPo trafficControlTableFlows.flows = append(trafficControlTableFlows.flows, &ofTestUtils.ExpectFlow{ MatchStr: fmt.Sprintf("priority=200,reg1=0x%x", port), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG9[],load:0x2->NXM_NX_REG4[22..23],goto_table:IngressSecurityClassifier", targetOFPort), + ActStr: fmt.Sprintf("set_field:0x%x->reg9,set_field:0x800000/0xc00000->reg4,goto_table:IngressSecurityClassifier", targetOFPort), }, &ofTestUtils.ExpectFlow{ MatchStr: fmt.Sprintf("priority=200,in_port=%d", port), - ActStr: fmt.Sprintf("load:0x%x->NXM_NX_REG9[],load:0x2->NXM_NX_REG4[22..23],goto_table:IngressSecurityClassifier", targetOFPort), + ActStr: fmt.Sprintf("set_field:0x%x->reg9,set_field:0x800000/0xc00000->reg4,goto_table:IngressSecurityClassifier", targetOFPort), }, ) } diff --git a/test/integration/ovs/ofctrl_test.go b/test/integration/ovs/ofctrl_test.go index e70bcd976da..908703eb73e 100644 --- a/test/integration/ovs/ofctrl_test.go +++ b/test/integration/ovs/ofctrl_test.go @@ -17,7 +17,6 @@ package ovs import ( "fmt" "net" - "strconv" "strings" "sync" "sync/atomic" @@ -30,6 +29,7 @@ import ( "golang.org/x/time/rate" "k8s.io/apimachinery/pkg/util/wait" + "antrea.io/antrea/pkg/agent/openflow" binding "antrea.io/antrea/pkg/ovs/openflow" "antrea.io/antrea/pkg/ovs/ovsconfig" "antrea.io/antrea/pkg/ovs/ovsctl" @@ -324,11 +324,15 @@ func TestOFctrlGroup(t *testing.T) { assert.True(t, strings.Contains(dumpedGroup[i+1], fmt.Sprintf("weight:%d", bucket.weight))) } for _, loading := range bucket.reg2reg { - rngStr := "[]" + rngStr := "" + data := loading[1] if !(loading[2] == 0 && loading[3] == 31) { - rngStr = fmt.Sprintf("[%d..%d]", loading[2], loading[3]) + length := loading[3] - loading[2] + 1 + mask := ^uint32(0) >> (32 - length) << loading[2] + rngStr = fmt.Sprintf("/0x%x", mask) + data = data << loading[2] } - loadStr := fmt.Sprintf("load:0x%x->NXM_NX_REG%d%s", loading[1], loading[0], rngStr) + loadStr := fmt.Sprintf("set_field:0x%x%s->reg%d", data, rngStr, loading[0]) assert.Contains(t, dumpedGroup[i+1], loadStr) } if bucket.resubmitTable != 0 { @@ -575,8 +579,8 @@ func TestBundleWithGroupAndFlow(t *testing.T) { }, } - bucket0 := "weight:100,actions=load:0xa0a0002->NXM_NX_REG1[],load:0x35->NXM_NX_REG2[],load:0xfff1->NXM_NX_REG3[],resubmit(,3)" - bucket1 := "weight:100,actions=load:0xa0a0202->NXM_NX_REG1[],load:0x35->NXM_NX_REG2[],load:0xfff1->NXM_NX_REG3[],resubmit(,3)" + bucket0 := "weight:100,actions=set_field:0xa0a0002->reg1,set_field:0x35->reg2,set_field:0xfff1->reg3,resubmit(,3)" + bucket1 := "weight:100,actions=set_field:0xa0a0202->reg1,set_field:0x35->reg2,set_field:0xfff1->reg3,resubmit(,3)" expectedGroupBuckets := []string{bucket0, bucket1} err = bridge.AddOFEntriesInBundle([]binding.OFEntry{flow, group}, nil, nil) require.Nil(t, err) @@ -625,7 +629,7 @@ func TestPacketOutIn(t *testing.T) { pktIn := pktInQueue.GetRateLimited(make(chan struct{})) matchers := pktIn.GetMatches() - reg2Match := matchers.GetMatchByName("NXM_NX_REG2") + reg2Match := openflow.GetMatchFieldByRegID(matchers, 2) assert.NotNil(t, reg2Match) reg2Value := reg2Match.GetValue() assert.NotNil(t, reg2Value) @@ -633,7 +637,7 @@ func TestPacketOutIn(t *testing.T) { assert.True(t, ok2) assert.Equal(t, reg2Data, ofctrl.GetUint32ValueWithRange(value2.Data, reg2Field.GetRange().ToNXRange())) - reg3Match := matchers.GetMatchByName("NXM_NX_REG3") + reg3Match := openflow.GetMatchFieldByRegID(matchers, 3) assert.NotNil(t, reg3Match) reg3Value := reg3Match.GetValue() assert.NotNil(t, reg3Value) @@ -654,10 +658,11 @@ func TestPacketOutIn(t *testing.T) { pktBuilder := bridge.BuildPacketOut() regField := binding.NewRegField(0, 18, 18, "field") + mark := binding.NewRegMark(regField, 0x1) pkt := pktBuilder.SetSrcMAC(srcMAC).SetDstMAC(dstcMAC). SetDstIP(dstIP).SetSrcIP(srcIP).SetIPProtocol(binding.ProtocolTCP). SetTCPSrcPort(srcPort).SetTCPDstPort(dstPort). - AddLoadAction(regField.GetNXFieldName(), uint64(0x1), regField.GetRange()). + AddLoadRegMark(mark). Done() require.Nil(t, err) flow0 := table0.BuildFlow(100). @@ -736,7 +741,7 @@ func TestMoveTunMetadata(t *testing.T) { time.Sleep(1 * time.Second) flow1 := table.BuildFlow(100). MatchProtocol(binding.ProtocolIP).MatchTunMetadata(0, 0x1234). - Action().MoveRange("NXM_NX_TUN_METADATA0", "NXM_NX_REG0", binding.Range{28, 31}, binding.Range{28, 31}). + Action().MoveFromTunMetadata(0, "NXM_NX_REG0", binding.Range{28, 31}, binding.Range{28, 31}, 4). Action().NextTable(). Done() err = bridge.AddFlowsInBundle([]binding.Flow{flow1}, nil, nil) @@ -866,7 +871,6 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { var flows []binding.Flow _, AllIPs, _ := net.ParseCIDR("0.0.0.0/0") _, conjSrcIPNet, _ := net.ParseCIDR("192.168.3.0/24") - 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, "field0") @@ -944,7 +948,7 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { Cookie(getCookieID()). MatchCTMark(gatewayCTMark). MatchCTStateNew(false).MatchCTStateTrk(true). - Action().LoadRange(binding.NxmFieldDstMAC, gwMACData, &binding.Range{0, 47}). + Action().SetDstMAC(gwMAC). Action().NextTable(). Done(), table.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). @@ -1033,23 +1037,23 @@ func prepareFlows(table binding.Table) ([]binding.Flow, []*ExpectFlow) { gotoTableAction := fmt.Sprintf("goto_table:%d", table.GetNext()) var flowStrs []*ExpectFlow flowStrs = append(flowStrs, - &ExpectFlow{"priority=190,in_port=3", fmt.Sprintf("load:0x2->NXM_NX_REG0[0..15],%s", gotoTableAction)}, + &ExpectFlow{"priority=190,in_port=3", fmt.Sprintf("set_field:0x2/0xffff->reg0,%s", gotoTableAction)}, &ExpectFlow{"priority=200,arp,in_port=3,arp_spa=192.168.1.3,arp_sha=aa:aa:aa:aa:aa:13", gotoTableAction}, &ExpectFlow{"priority=200,ip,in_port=3,dl_src=aa:aa:aa:aa:aa:13,nw_src=192.168.1.3", gotoTableAction}, - &ExpectFlow{"priority=200,arp,arp_tpa=192.168.2.1,arp_op=1", "move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],set_field:aa:bb:cc:dd:ee:ff->eth_src,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],set_field:aa:bb:cc:dd:ee:ff->arp_sha,move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],set_field:192.168.2.1->arp_spa,IN_PORT"}, + &ExpectFlow{"priority=200,arp,arp_tpa=192.168.2.1,arp_op=1", "move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],set_field:aa:bb:cc:dd:ee:ff->eth_src,set_field:2->arp_op,move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],set_field:aa:bb:cc:dd:ee:ff->arp_sha,move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],set_field:192.168.2.1->arp_spa,IN_PORT"}, &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]),goto_table:%d", table.GetID(), table.GetNext())}, &ExpectFlow{"priority=200,ip", fmt.Sprintf("ct(table=%d,zone=65520)", table.GetNext())}, &ExpectFlow{"priority=210,ct_state=-new+trk,ct_mark=0x2/0x2,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:0x1->NXM_NX_CT_MARK[1])", table.GetNext())}, - &ExpectFlow{"priority=200,ct_state=-new+trk,ct_mark=0x2/0x2,ip", fmt.Sprintf("load:0xaaaaaaaaaa11->NXM_OF_ETH_DST[],%s", gotoTableAction)}, + &ExpectFlow{"priority=200,ct_state=+new+trk,ip,reg0=0x1/0xffff", fmt.Sprintf("ct(commit,table=%d,zone=65520,exec(set_field:0x2/0x2->ct_mark)", table.GetNext())}, + &ExpectFlow{"priority=200,ct_state=-new+trk,ct_mark=0x2/0x2,ip", fmt.Sprintf("set_field:aa:aa:aa:aa:aa:11->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)}, &ExpectFlow{"priority=200,ip,nw_dst=192.168.2.0/24", fmt.Sprintf("dec_ttl,set_field:aa:aa:aa:aa:aa:11->eth_src,set_field:aa:bb:cc:dd:ee:ff->eth_dst,set_field:10.1.1.2->tun_dst,%s", gotoTableAction)}, &ExpectFlow{"priority=200,ipv6,ipv6_dst=fd74:ca9b:172:21::/64", fmt.Sprintf("dec_ttl,set_field:aa:aa:aa:aa:aa:11->eth_src,set_field:aa:bb:cc:dd:ee:ff->eth_dst,set_field:20:ca9b:172:35::3->tun_ipv6_dst,%s", gotoTableAction)}, &ExpectFlow{"priority=200,ip,nw_dst=192.168.1.1", fmt.Sprintf("set_field:aa:aa:aa:aa:aa:11->eth_dst,%s", gotoTableAction)}, - &ExpectFlow{"priority=200,dl_dst=aa:aa:aa:aa:aa:13", fmt.Sprintf("load:0x3->NXM_NX_REG1[],load:0x1->NXM_NX_REG0[16],%s", gotoTableAction)}, + &ExpectFlow{"priority=200,dl_dst=aa:aa:aa:aa:aa:13", fmt.Sprintf("set_field:0x3->reg1,set_field:0x10000/0x10000->reg0,%s", gotoTableAction)}, &ExpectFlow{"priority=200,ip,reg0=0x10000/0x10000", "output:NXM_NX_REG1[]"}, &ExpectFlow{"priority=200,ip,nw_dst=172.16.0.0/16", "output:1"}, &ExpectFlow{fmt.Sprintf("priority=200,ip,nw_src=192.168.1.3,nw_tos=%d", ipDSCP<<2), gotoTableAction}, @@ -1117,19 +1121,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[0..7]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(src=%s),exec(set_field:0x40/0xff->ct_mark))", 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[0..7]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(src=%s-%s),exec(set_field:0x40/0xff->ct_mark))", 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[0..7]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(dst=%s),exec(set_field:0x40/0xff->ct_mark))", 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[0..7]))", + fmt.Sprintf("ct(commit,table=%d,zone=65520,nat(dst=%s-%s),exec(set_field:0x40/0xff->ct_mark))", table.GetNext(), natedIP1.String(), natedIP2.String()), }, } diff --git a/test/integration/ovs/openflow_test_utils.go b/test/integration/ovs/openflow_test_utils.go index bc48ab4e31d..a5d88c7b777 100644 --- a/test/integration/ovs/openflow_test_utils.go +++ b/test/integration/ovs/openflow_test_utils.go @@ -37,7 +37,7 @@ func PrepareOVSBridge(brName string) error { // using the netdev datapath type does not impact test coverage but // ensures that the integration tests can be run with Docker Desktop on // macOS. - cmdStr := fmt.Sprintf("ovs-vsctl --may-exist add-br %s -- set Bridge %s protocols='OpenFlow10,OpenFlow13' datapath_type=netdev", brName, brName) + cmdStr := fmt.Sprintf("ovs-vsctl --may-exist add-br %s -- set Bridge %s protocols='OpenFlow10,OpenFlow15' datapath_type=netdev", brName, brName) err := exec.Command("/bin/sh", "-c", cmdStr).Run() if err != nil { return err @@ -114,7 +114,12 @@ func CheckGroupExists(t *testing.T, ovsCtlClient ovsctl.OVSCtlClient, groupID bi found := false for _, groupElems := range groupList { groupEntry := fmt.Sprintf("%s,bucket=", groupElems[0]) - groupEntry = fmt.Sprintf("%s%s", groupEntry, strings.Join(groupElems[1:], ",bucket=")) + var groupElemStrs []string + for _, elem := range groupElems[1:] { + elemStr := strings.Join(strings.Split(elem, ",")[1:], ",") + groupElemStrs = append(groupElemStrs, elemStr) + } + groupEntry = fmt.Sprintf("%s%s", groupEntry, strings.Join(groupElemStrs, ",bucket=")) if strings.Contains(groupEntry, groupStr) { found = true break @@ -148,7 +153,7 @@ func formatFlowDump(rawFlows []string) []string { for _, flow := range rawFlows { felem := strings.Fields(flow) if len(felem) > 2 { - felem = append(felem[:1], felem[3:]...) + felem = append(felem[:1], felem[4:]...) fstr := strings.Join(felem, " ") flowList = append(flowList, fstr) }