From 28647de6f0b5cbc20aef6fba160f9258b3d5ed94 Mon Sep 17 00:00:00 2001 From: Mengdie Song Date: Wed, 12 Aug 2020 10:32:18 +0800 Subject: [PATCH] [IPv6] Change openflow pipeline for L2 Pod networking (#1040) 1. Add a new table named IPv6 to handle IPv6 ND Solicitation, ND advertisement and IPv6 Multicast traffic. 2. Add flows in openflow tables (spoofGuardTable, IPv6, conntrackTable, conntrackStateTable, conntrackCommitTable, L2ForwardingOutTable) for handling IPv6 L2 Pod networking. --- pkg/agent/config/node_config.go | 2 +- pkg/agent/openflow/client.go | 8 +- pkg/agent/openflow/pipeline.go | 167 +++++++++++++++++----- pkg/agent/util/net.go | 9 ++ pkg/ovs/openflow/interfaces.go | 2 + pkg/ovs/openflow/ofctrl_builder.go | 48 +++++-- pkg/ovs/openflow/testing/mock_openflow.go | 28 ++++ plugins/octant/go.mod | 2 +- plugins/octant/go.sum | 4 +- 9 files changed, 217 insertions(+), 53 deletions(-) diff --git a/pkg/agent/config/node_config.go b/pkg/agent/config/node_config.go index 08570c51c14..74f16f37edb 100644 --- a/pkg/agent/config/node_config.go +++ b/pkg/agent/config/node_config.go @@ -93,7 +93,7 @@ type NodeConfig struct { } func (n *NodeConfig) String() string { - return fmt.Sprintf("NodeName: %s, OVSBridge: %s, PodIPv4CIDR %s, PodIPv6CIDR: %s, NodeIP: %s, Gateway: %s", + return fmt.Sprintf("NodeName: %s, OVSBridge: %s, PodIPv4CIDR: %s, PodIPv6CIDR: %s, NodeIP: %s, Gateway: %s", n.Name, n.OVSBridge, n.PodIPv4CIDR, n.PodIPv6CIDR, n.NodeIPAddr, n.GatewayConfig) } diff --git a/pkg/agent/openflow/client.go b/pkg/agent/openflow/client.go index 435e62deba5..19854d7b5b8 100644 --- a/pkg/agent/openflow/client.go +++ b/pkg/agent/openflow/client.go @@ -476,10 +476,11 @@ func (c *client) InstallClusterServiceCIDRFlows(serviceNet *net.IPNet, gatewayOF func (c *client) InstallGatewayFlows(gatewayAddrs []net.IP, gatewayMAC net.HardwareAddr, gatewayOFPort uint32) error { flows := []binding.Flow{ c.gatewayClassifierFlow(gatewayOFPort, cookie.Default), - c.gatewayIPSpoofGuardFlow(gatewayOFPort, cookie.Default), c.ctRewriteDstMACFlow(gatewayMAC, cookie.Default), c.l2ForwardCalcFlow(gatewayMAC, gatewayOFPort, cookie.Default), } + hasIPv6Addr := util.ContainIPv6Addr(gatewayAddrs) + flows = append(flows, c.gatewayIPSpoofGuardFlows(gatewayOFPort, hasIPv6Addr, cookie.Default)...) // Add ARP SpoofGuard flow for local gateway interface. gwIPv4 := util.GetIPv4Addr(gatewayAddrs) @@ -527,7 +528,10 @@ func (c *client) initialize() error { if err := c.ofEntryOperations.Add(c.arpNormalFlow(cookie.Default)); err != nil { return fmt.Errorf("failed to install arp normal flow: %v", err) } - if err := c.ofEntryOperations.Add(c.l2ForwardOutputFlow(cookie.Default)); err != nil { + if err := c.ofEntryOperations.AddAll(c.ipv6Flows(cookie.Default)); err != nil { + return fmt.Errorf("failed to install ipv6 flows: %v", err) + } + if err := c.ofEntryOperations.AddAll(c.l2ForwardOutputFlows(cookie.Default)); err != nil { return fmt.Errorf("failed to install L2 forward output flows: %v", err) } if err := c.ofEntryOperations.AddAll(c.connectionTrackFlows(cookie.Default)); err != nil { diff --git a/pkg/agent/openflow/pipeline.go b/pkg/agent/openflow/pipeline.go index d9391174187..923623a7887 100644 --- a/pkg/agent/openflow/pipeline.go +++ b/pkg/agent/openflow/pipeline.go @@ -40,6 +40,7 @@ const ( uplinkTable binding.TableIDType = 5 spoofGuardTable binding.TableIDType = 10 arpResponderTable binding.TableIDType = 20 + ipv6Table binding.TableIDType = 21 serviceHairpinTable binding.TableIDType = 29 conntrackTable binding.TableIDType = 30 conntrackStateTable binding.TableIDType = 31 @@ -79,6 +80,11 @@ const ( markTrafficFromGateway = 1 markTrafficFromLocal = 2 markTrafficFromUplink = 4 + + // IPv6 multicast prefix + ipv6MulticastAddr = "FF00::/8" + // IPv6 link-local prefix + ipv6LinkLocalAddr = "FE80::/10" ) var ( @@ -99,6 +105,7 @@ var ( {uplinkTable, "Uplink"}, {spoofGuardTable, "SpoofGuard"}, {arpResponderTable, "ARPResponder"}, + {ipv6Table, "IPv6"}, {serviceHairpinTable, "ServiceHairpin"}, {conntrackTable, "ConntrackZone"}, {conntrackStateTable, "ConntrackState"}, @@ -212,7 +219,8 @@ const ( // the selection result needs to be cached. marksRegServiceNeedLearn uint32 = 0b011 - CtZone = 0xfff0 + CtZone = 0xfff0 + CtZoneV6 = 0xffe6 portFoundMark = 0b1 snatRequiredMark = 0b1 @@ -533,6 +541,10 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { Action().CT(false, connectionTrackTable.GetNext(), CtZone).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), + connectionTrackTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). + Action().CT(false, connectionTrackTable.GetNext(), CtZoneV6).CTDone(). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), ) } return append(flows, @@ -548,6 +560,11 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { Action().Drop(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), + connectionTrackStateTable.BuildFlow(priorityLow).MatchProtocol(binding.ProtocolIPv6). + MatchCTStateInv(true).MatchCTStateTrk(true). + Action().Drop(). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), connectionTrackCommitTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). MatchRegRange(int(marksReg), markTrafficFromGateway, binding.Range{0, 15}). MatchCTStateNew(true).MatchCTStateTrk(true). @@ -559,6 +576,11 @@ func (c *client) connectionTrackFlows(category cookie.Category) []binding.Flow { Action().CT(true, connectionTrackCommitTable.GetNext(), CtZone).CTDone(). Cookie(c.cookieAllocator.Request(category).Raw()). Done(), + connectionTrackCommitTable.BuildFlow(priorityLow).MatchProtocol(binding.ProtocolIPv6). + MatchCTStateNew(true).MatchCTStateTrk(true). + Action().CT(true, connectionTrackCommitTable.GetNext(), CtZoneV6).CTDone(). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), ) } @@ -620,15 +642,6 @@ func (c *client) l2ForwardCalcFlow(dstMAC net.HardwareAddr, ofPort uint32, categ Done() } -// l2ForwardOutputFlow generates the flow that outputs packets to OVS port after L2 forwarding calculation. -func (c *client) l2ForwardOutputFlow(category cookie.Category) binding.Flow { - return c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). - MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). - Action().OutputRegRange(int(portCacheReg), ofPortRegRange). - Cookie(c.cookieAllocator.Request(category).Raw()). - Done() -} - // traceflowL2ForwardOutputFlow generates Traceflow specific flow that outputs traceflow packets to OVS port and Antrea // Agent after L2forwarding calculation. func (c *client) traceflowL2ForwardOutputFlow(dataplaneTag uint8, category cookie.Category) binding.Flow { @@ -656,6 +669,24 @@ func (c *client) l2ForwardOutputServiceHairpinFlow() binding.Flow { Done() } +// l2ForwardOutputFlows generates the flow that outputs packets to OVS port after L2 forwarding calculation. +func (c *client) l2ForwardOutputFlows(category cookie.Category) []binding.Flow { + var flows []binding.Flow + flows = append(flows, + c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). + MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + Action().OutputRegRange(int(portCacheReg), ofPortRegRange). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), + c.pipeline[L2ForwardingOutTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). + MatchRegRange(int(marksReg), portFoundMark, ofPortMarkRange). + Action().OutputRegRange(int(portCacheReg), ofPortRegRange). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), + ) + return flows +} + // l3FlowsToPod generates the flow to rewrite MAC if the packet is received from tunnel port and destined for local Pods. func (c *client) l3FlowsToPod(localGatewayMAC net.HardwareAddr, podInterfaceIPs []net.IP, podInterfaceMAC net.HardwareAddr, category cookie.Category) []binding.Flow { l3FwdTable := c.pipeline[l3ForwardingTable] @@ -813,14 +844,23 @@ func (c *client) podIPSpoofGuardFlow(ifIPs []net.IP, ifMAC net.HardwareAddr, ifO var flows []binding.Flow for _, ifIP := range ifIPs { ipProtocol := parseIPProtocol(ifIP) - flow := ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). - MatchInPort(ifOFPort). - MatchSrcMAC(ifMAC). - MatchSrcIP(ifIP). - Action().GotoTable(ipSpoofGuardTable.GetNext()). - Cookie(c.cookieAllocator.Request(category).Raw()). - Done() - flows = append(flows, flow) + if ipProtocol == binding.ProtocolIP { + flows = append(flows, ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + MatchInPort(ifOFPort). + MatchSrcMAC(ifMAC). + MatchSrcIP(ifIP). + Action().GotoTable(ipSpoofGuardTable.GetNext()). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done()) + } else if ipProtocol == binding.ProtocolIPv6 { + flows = append(flows, ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(ipProtocol). + MatchInPort(ifOFPort). + MatchSrcMAC(ifMAC). + MatchSrcIP(ifIP). + Action().GotoTable(ipv6Table). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done()) + } } return flows } @@ -869,17 +909,6 @@ func (c *client) arpSpoofGuardFlow(ifIP net.IP, ifMAC net.HardwareAddr, ifOFPort Done() } -// gatewayIPSpoofGuardFlow generates the flow to skip spoof guard checking for traffic sent from gateway interface. -func (c *client) gatewayIPSpoofGuardFlow(gatewayOFPort uint32, category cookie.Category) binding.Flow { - ipPipeline := c.pipeline - ipSpoofGuardTable := ipPipeline[spoofGuardTable] - return ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). - MatchInPort(gatewayOFPort). - Action().GotoTable(ipSpoofGuardTable.GetNext()). - Cookie(c.cookieAllocator.Request(category).Raw()). - Done() -} - // sessionAffinityReselectFlow generates the flow which resubmits the service accessing // packet back to serviceLBTable if there is no endpointDNAT flow matched. This // case will occur if an Endpoint is removed and is the learned Endpoint @@ -893,6 +922,26 @@ func (c *client) sessionAffinityReselectFlow() binding.Flow { Done() } +// gatewayIPSpoofGuardFlow generates the flow to skip spoof guard checking for traffic sent from gateway interface. +func (c *client) gatewayIPSpoofGuardFlows(gatewayOFPort uint32, hasIPv6Addr bool, category cookie.Category) []binding.Flow { + ipPipeline := c.pipeline + ipSpoofGuardTable := ipPipeline[spoofGuardTable] + var flows []binding.Flow + flows = append(flows, ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). + MatchInPort(gatewayOFPort). + Action().GotoTable(ipSpoofGuardTable.GetNext()). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done()) + if hasIPv6Addr { + flows = append(flows, ipSpoofGuardTable.BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). + MatchInPort(gatewayOFPort). + Action().GotoTable(ipv6Table). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done()) + } + return flows +} + // serviceCIDRDNATFlow generates flows to match dst IP in service CIDR and output to host gateway interface directly. func (c *client) serviceCIDRDNATFlow(serviceCIDR *net.IPNet, gatewayOFPort uint32) binding.Flow { return c.pipeline[dnatTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIP). @@ -967,6 +1016,47 @@ func (c *client) dropRuleMetricFlow(conjunctionID uint32, ingress bool) binding. Done() } +// ipv6Flows generates the flows to allow IPv6 packets from link-local addresses and +// handle multicast packets, Neighbor Solicitation and ND Advertisement packets properly. +func (c *client) ipv6Flows(category cookie.Category) []binding.Flow { + var flows []binding.Flow + // TODO: Remove the flag after finishing Antrea Proxy changes + if !c.enableProxy { + _, ipv6LinkLocalIpnet, _ := net.ParseCIDR(ipv6LinkLocalAddr) + _, ipv6MulticastIpnet, _ := net.ParseCIDR(ipv6MulticastAddr) + flows = append(flows, + // Allow IPv6 packets (e.g. Multicast Listener Report Message V2) which are sent from link-local addresses in spoofGuardTable, + // so that these packets will not be dropped. + c.pipeline[spoofGuardTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). + MatchSrcIPNet(*ipv6LinkLocalIpnet). + Action().GotoTable(ipv6Table). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), + // Handle IPv6 Neighbor Solicitation and Neighbor Advertisement as a regular L2 learning Switch by using normal. + c.pipeline[ipv6Table].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolICMPv6). + MatchICMPv6Type(135). + MatchICMPv6Code(0). + Action().Normal(). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), + c.pipeline[ipv6Table].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolICMPv6). + MatchICMPv6Type(136). + MatchICMPv6Code(0). + Action().Normal(). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), + // Handle IPv6 multicast packets as a regular L2 learning Switch by using normal. + // It is used to ensure that all kinds of IPv6 multicast packets are properly handled (e.g. Multicast Listener Report Message V2). + c.pipeline[ipv6Table].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolIPv6). + MatchDstIPNet(*ipv6MulticastIpnet). + Action().Normal(). + Cookie(c.cookieAllocator.Request(category).Raw()). + Done(), + ) + } + return flows +} + // conjunctionActionFlow generates the flow to jump to a specific table if policyRuleConjunction ID is matched. Priority of // conjunctionActionFlow is created at priorityLow for k8s network policies, and *priority assigned by PriorityAssigner for AntreaPolicy. func (c *client) conjunctionActionFlow(conjunctionID uint32, tableID binding.TableIDType, nextTable binding.TableIDType, priority *uint16) binding.Flow { @@ -1436,6 +1526,7 @@ func generatePipeline(bridge binding.Bridge, enableProxy, enableAntreaNP bool) m uplinkTable: bridge.CreateTable(uplinkTable, spoofGuardTable, binding.TableMissActionNone), spoofGuardTable: bridge.CreateTable(spoofGuardTable, serviceHairpinTable, binding.TableMissActionDrop), arpResponderTable: bridge.CreateTable(arpResponderTable, binding.LastTableID, binding.TableMissActionDrop), + ipv6Table: bridge.CreateTable(ipv6Table, serviceHairpinTable, binding.TableMissActionNext), serviceHairpinTable: bridge.CreateTable(serviceHairpinTable, conntrackTable, binding.TableMissActionNext), conntrackTable: bridge.CreateTable(conntrackTable, conntrackStateTable, binding.TableMissActionNone), conntrackStateTable: bridge.CreateTable(conntrackStateTable, endpointDNATTable, binding.TableMissActionNext), @@ -1456,15 +1547,17 @@ func generatePipeline(bridge binding.Bridge, enableProxy, enableAntreaNP bool) m } } else { pipeline = map[binding.TableIDType]binding.Table{ - ClassifierTable: bridge.CreateTable(ClassifierTable, spoofGuardTable, binding.TableMissActionDrop), - spoofGuardTable: bridge.CreateTable(spoofGuardTable, conntrackTable, binding.TableMissActionDrop), - arpResponderTable: bridge.CreateTable(arpResponderTable, binding.LastTableID, binding.TableMissActionDrop), - conntrackTable: bridge.CreateTable(conntrackTable, conntrackStateTable, binding.TableMissActionNone), - conntrackStateTable: bridge.CreateTable(conntrackStateTable, dnatTable, binding.TableMissActionNext), - dnatTable: bridge.CreateTable(dnatTable, egressEntryTable, binding.TableMissActionNext), - EgressRuleTable: bridge.CreateTable(EgressRuleTable, EgressDefaultTable, binding.TableMissActionNext), + ClassifierTable: bridge.CreateTable(ClassifierTable, spoofGuardTable, binding.TableMissActionDrop), + spoofGuardTable: bridge.CreateTable(spoofGuardTable, conntrackTable, binding.TableMissActionDrop), + arpResponderTable: bridge.CreateTable(arpResponderTable, binding.LastTableID, binding.TableMissActionDrop), + ipv6Table: bridge.CreateTable(ipv6Table, conntrackTable, binding.TableMissActionNext), + conntrackTable: bridge.CreateTable(conntrackTable, conntrackStateTable, binding.TableMissActionNone), + conntrackStateTable: bridge.CreateTable(conntrackStateTable, dnatTable, binding.TableMissActionNext), + dnatTable: bridge.CreateTable(dnatTable, egressEntryTable, binding.TableMissActionNext), + EgressRuleTable: bridge.CreateTable(EgressRuleTable, EgressDefaultTable, binding.TableMissActionNext), EgressDefaultTable: bridge.CreateTable(EgressDefaultTable, EgressMetricTable, binding.TableMissActionNext), - EgressMetricTable: bridge.CreateTable(EgressMetricTable, l3ForwardingTable, binding.TableMissActionNext), l3ForwardingTable: bridge.CreateTable(l3ForwardingTable, l2ForwardingCalcTable, binding.TableMissActionNext), + EgressMetricTable: bridge.CreateTable(EgressMetricTable, l3ForwardingTable, binding.TableMissActionNext), + l3ForwardingTable: bridge.CreateTable(l3ForwardingTable, l2ForwardingCalcTable, binding.TableMissActionNext), l2ForwardingCalcTable: bridge.CreateTable(l2ForwardingCalcTable, IngressEntryTable, binding.TableMissActionNext), IngressRuleTable: bridge.CreateTable(IngressRuleTable, IngressDefaultTable, binding.TableMissActionNext), IngressDefaultTable: bridge.CreateTable(IngressDefaultTable, IngressMetricTable, binding.TableMissActionNext), diff --git a/pkg/agent/util/net.go b/pkg/agent/util/net.go index d1bf14dc0a2..c7743775a12 100644 --- a/pkg/agent/util/net.go +++ b/pkg/agent/util/net.go @@ -127,3 +127,12 @@ func GetIPv4Addr(ips []net.IP) net.IP { } return nil } + +func ContainIPv6Addr(ips []net.IP) bool { + for _, ip := range ips { + if ip.To4() == nil { + return true + } + } + return false +} diff --git a/pkg/ovs/openflow/interfaces.go b/pkg/ovs/openflow/interfaces.go index 562eb119612..4e5db2f727f 100644 --- a/pkg/ovs/openflow/interfaces.go +++ b/pkg/ovs/openflow/interfaces.go @@ -224,6 +224,8 @@ type FlowBuilder interface { MatchCTLabelRange(high, low uint64, bitRange Range) FlowBuilder MatchConjID(value uint32) FlowBuilder MatchDstPort(port uint16, portMask *uint16) FlowBuilder + MatchICMPv6Type(icmp6Type byte) FlowBuilder + MatchICMPv6Code(icmp6Code byte) FlowBuilder MatchTunMetadata(index int, data uint32) FlowBuilder // MatchCTSrcIP matches the source IPv4 address of the connection tracker original direction tuple. MatchCTSrcIP(ip net.IP) FlowBuilder diff --git a/pkg/ovs/openflow/ofctrl_builder.go b/pkg/ovs/openflow/ofctrl_builder.go index 204bdf353bd..ed7d0d97b09 100644 --- a/pkg/ovs/openflow/ofctrl_builder.go +++ b/pkg/ovs/openflow/ofctrl_builder.go @@ -244,36 +244,64 @@ func (b *ofFlowBuilder) MatchInPort(inPort uint32) FlowBuilder { // MatchDstIP adds match condition for matching destination IP address. func (b *ofFlowBuilder) MatchDstIP(ip net.IP) FlowBuilder { - b.matchers = append(b.matchers, fmt.Sprintf("nw_dst=%s", ip.String())) + if ip.To4() != nil { + b.matchers = append(b.matchers, fmt.Sprintf("nw_dst=%s", ip.String())) + } else { + b.matchers = append(b.matchers, fmt.Sprintf("ipv6_dst=%s", ip.String())) + } b.Match.IpDa = &ip return b } // MatchDstIPNet adds match condition for matching destination IP CIDR. func (b *ofFlowBuilder) MatchDstIPNet(ipnet net.IPNet) FlowBuilder { - b.matchers = append(b.matchers, fmt.Sprintf("nw_dst=%s", ipnet.String())) + if ipnet.IP.To4() != nil { + b.matchers = append(b.matchers, fmt.Sprintf("nw_dst=%s", ipnet.String())) + } else { + b.matchers = append(b.matchers, fmt.Sprintf("ipv6_dst=%s", ipnet.String())) + } b.Match.IpDa = &ipnet.IP - b.Match.IpDaMask = maskToIPv4(ipnet.Mask) + b.Match.IpDaMask = maskToIP(ipnet.Mask) + return b +} + +func (b *ofFlowBuilder) MatchICMPv6Type(icmp6Type byte) FlowBuilder { + b.matchers = append(b.matchers, fmt.Sprintf("icmp_type=%d", icmp6Type)) + b.Match.Icmp6Type = &icmp6Type return b } -func maskToIPv4(mask net.IPMask) *net.IP { - ip := net.IPv4(mask[0], mask[1], mask[2], mask[3]) +func (b *ofFlowBuilder) MatchICMPv6Code(icmp6Code byte) FlowBuilder { + b.matchers = append(b.matchers, fmt.Sprintf("icmp_code=%d", icmp6Code)) + b.Match.Icmp6Code = &icmp6Code + return b +} + +func maskToIP(mask net.IPMask) *net.IP { + ip := net.IP(mask) return &ip } // MatchSrcIP adds match condition for matching source IP address. func (b *ofFlowBuilder) MatchSrcIP(ip net.IP) FlowBuilder { - b.matchers = append(b.matchers, fmt.Sprintf("nw_src=%s", ip.String())) + if ip.To4() != nil { + b.matchers = append(b.matchers, fmt.Sprintf("nw_src=%s", ip.String())) + } else { + b.matchers = append(b.matchers, fmt.Sprintf("ipv6_src=%s", ip.String())) + } b.Match.IpSa = &ip return b } // MatchSrcIPNet adds match condition for matching source IP CIDR. func (b *ofFlowBuilder) MatchSrcIPNet(ipnet net.IPNet) FlowBuilder { - b.matchers = append(b.matchers, fmt.Sprintf("nw_src=%s", ipnet.String())) + if ipnet.IP.To4() != nil { + b.matchers = append(b.matchers, fmt.Sprintf("nw_src=%s", ipnet.String())) + } else { + b.matchers = append(b.matchers, fmt.Sprintf("ipv6_src=%s", ipnet.String())) + } b.Match.IpSa = &ipnet.IP - b.Match.IpSaMask = maskToIPv4(ipnet.Mask) + b.Match.IpSaMask = maskToIP(ipnet.Mask) return b } @@ -411,7 +439,7 @@ func (b *ofFlowBuilder) MatchCTSrcIP(ip net.IP) FlowBuilder { func (b *ofFlowBuilder) MatchCTSrcIPNet(ipNet net.IPNet) FlowBuilder { b.matchers = append(b.matchers, fmt.Sprintf("nw_dst=%s", ipNet.String())) b.Match.CtIpSa = &ipNet.IP - b.Match.CtIpSaMask = maskToIPv4(ipNet.Mask) + b.Match.CtIpSaMask = maskToIP(ipNet.Mask) return b } @@ -427,7 +455,7 @@ func (b *ofFlowBuilder) MatchCTDstIP(ip net.IP) FlowBuilder { // MatchCTDstIPNet is the same as MatchCTDstIP but supports IP masking. func (b *ofFlowBuilder) MatchCTDstIPNet(ipNet net.IPNet) FlowBuilder { b.Match.CtIpDa = &ipNet.IP - b.Match.CtIpDaMask = maskToIPv4(ipNet.Mask) + b.Match.CtIpDaMask = maskToIP(ipNet.Mask) b.matchers = append(b.matchers, fmt.Sprintf("ct_nw_dst=%s", ipNet.String())) return b } diff --git a/pkg/ovs/openflow/testing/mock_openflow.go b/pkg/ovs/openflow/testing/mock_openflow.go index f74c570b9f5..b65afd8caae 100644 --- a/pkg/ovs/openflow/testing/mock_openflow.go +++ b/pkg/ovs/openflow/testing/mock_openflow.go @@ -1509,6 +1509,34 @@ func (mr *MockFlowBuilderMockRecorder) MatchDstPort(arg0, arg1 interface{}) *gom return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchDstPort", reflect.TypeOf((*MockFlowBuilder)(nil).MatchDstPort), arg0, arg1) } +// MatchICMPv6Code mocks base method +func (m *MockFlowBuilder) MatchICMPv6Code(arg0 byte) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MatchICMPv6Code", arg0) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// MatchICMPv6Code indicates an expected call of MatchICMPv6Code +func (mr *MockFlowBuilderMockRecorder) MatchICMPv6Code(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchICMPv6Code", reflect.TypeOf((*MockFlowBuilder)(nil).MatchICMPv6Code), arg0) +} + +// MatchICMPv6Type mocks base method +func (m *MockFlowBuilder) MatchICMPv6Type(arg0 byte) openflow.FlowBuilder { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MatchICMPv6Type", arg0) + ret0, _ := ret[0].(openflow.FlowBuilder) + return ret0 +} + +// MatchICMPv6Type indicates an expected call of MatchICMPv6Type +func (mr *MockFlowBuilderMockRecorder) MatchICMPv6Type(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MatchICMPv6Type", reflect.TypeOf((*MockFlowBuilder)(nil).MatchICMPv6Type), arg0) +} + // MatchIPDscp mocks base method func (m *MockFlowBuilder) MatchIPDscp(arg0 byte) openflow.FlowBuilder { m.ctrl.T.Helper() diff --git a/plugins/octant/go.mod b/plugins/octant/go.mod index d652c557659..7f298e00fbf 100644 --- a/plugins/octant/go.mod +++ b/plugins/octant/go.mod @@ -10,7 +10,7 @@ require ( ) replace ( - github.com/contiv/ofnet => github.com/wenyingd/ofnet v0.0.0-20200601065543-2c7a62482f16 + github.com/contiv/ofnet => github.com/wenyingd/ofnet v0.0.0-20200728094531-d5b4d75f2cc3 github.com/vmware-tanzu/antrea => ../../ // Octant v0.13.1 and Antrea use different versions of github.com/googleapis/gnostic. // Octant v0.13.1 uses v0.4.1 and Antrea uses v0.1.0. diff --git a/plugins/octant/go.sum b/plugins/octant/go.sum index da9c89d54f1..1d581e1702e 100644 --- a/plugins/octant/go.sum +++ b/plugins/octant/go.sum @@ -89,7 +89,7 @@ github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kw github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.2-0.20190724153215-ded2f1757770/go.mod h1:AlmXjbiLJBqvZ4vxkWAqjx1CKHVEoQf0/Ugrvc6Cv70= -github.com/contiv/libOpenflow v0.0.0-20200424005919-3a6722c98962/go.mod h1:DtsPlJOByJZ+MO9YITEGUlbJ/jfh/ef0qeNyBYaeNR4= +github.com/contiv/libOpenflow v0.0.0-20200728044739-7c6534390721/go.mod h1:DtsPlJOByJZ+MO9YITEGUlbJ/jfh/ef0qeNyBYaeNR4= github.com/contiv/libOpenflow v0.0.0-20201014051314-c1702744526c/go.mod h1:DtsPlJOByJZ+MO9YITEGUlbJ/jfh/ef0qeNyBYaeNR4= github.com/contiv/libovsdb v0.0.0-20170227191248-d0061a53e358/go.mod h1:+qKEHaNVPj+wrn5st7TEFH9wcUWCJq5ZBvVKPQwzAeg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -467,7 +467,7 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17 github.com/vmware-tanzu/octant v0.13.1 h1:hz4JDnAA7xDkFjF4VEbt5SrSRrG26FCxKXXBGapf6Nc= github.com/vmware-tanzu/octant v0.13.1/go.mod h1:4q+wrV4tmUwAdMjvYOujSTtZbE4+zm0n5mb7FjvN0I0= github.com/vmware/go-ipfix v0.2.1/go.mod h1:8suqePBGCX20vEh/4/ekuRjX4BsZ2zYWcD22NpAWHVU= -github.com/wenyingd/ofnet v0.0.0-20200601065543-2c7a62482f16/go.mod h1:+g6SfqhTVqeGEmUJ0l4WtCgsL4dflTUJE4k+TPCKqXo= +github.com/wenyingd/ofnet v0.0.0-20200728094531-d5b4d75f2cc3/go.mod h1:oF9872TvzJqLzLKDGVMItRLWJHlnwXluuIuNbOP5WKM= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=