Skip to content

Commit

Permalink
[IPv6] Change openflow pipeline for L2 Pod networking (#1040)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mengdie-song authored and lzhecheng committed Nov 10, 2020
1 parent d9b0b96 commit c2bc4a0
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 65 deletions.
2 changes: 1 addition & 1 deletion pkg/agent/config/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
8 changes: 6 additions & 2 deletions pkg/agent/openflow/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,10 +479,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)
Expand Down Expand Up @@ -530,7 +531,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 {
Expand Down
207 changes: 155 additions & 52 deletions pkg/agent/openflow/pipeline.go

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions pkg/agent/util/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 2 additions & 0 deletions pkg/ovs/openflow/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,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
Expand Down
48 changes: 38 additions & 10 deletions pkg/ovs/openflow/ofctrl_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}

Expand All @@ -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
}
Expand Down
28 changes: 28 additions & 0 deletions pkg/ovs/openflow/testing/mock_openflow.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions plugins/octant/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ require (
)

replace (
<<<<<<< HEAD
github.com/contiv/ofnet => github.com/wenyingd/ofnet v0.0.0-20201109024835-6fd225d8c8d1
=======
github.com/contiv/ofnet => github.com/wenyingd/ofnet v0.0.0-20200728094531-d5b4d75f2cc3
>>>>>>> 964affb ([IPv6] Change openflow pipeline for L2 Pod networking (#1040))
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.
Expand Down

0 comments on commit c2bc4a0

Please sign in to comment.