Skip to content

Commit

Permalink
Add support for short-circuiting in AntreaProxy
Browse files Browse the repository at this point in the history
Before this PR, the implementation was that:

- Traffic from an internal or external client to an internal
  destination IP (ClusterIP) gets internalTrafficPolicy.
- Traffic from an internal or external client to an external
  destination IP (NodePort/LoadBalancer/ExternalIP) gets externalTrafficPolicy.

After this PR, the implementation is that:

- Traffic from an internal or external client to an internal
  destination IP (ClusterIP) gets internalTrafficPolicy.
- Traffic from an external client to an external destination
  IP (NodePort/LoadBalancer/ExternalIP) gets externalTrafficPolicy.
- Traffic from an internal client to an external destination
  IP (NodePort/LoadBalancer/ExternalIP) gets no policy; it
  always gets Cluster semantics and works (this is called
  short-circuiting).

Signed-off-by: Hongliang Liu <lhongliang@vmware.com>
  • Loading branch information
hongliangl committed Apr 16, 2023
1 parent 1ff93c4 commit 29a1a29
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 97 deletions.
27 changes: 26 additions & 1 deletion pkg/agent/openflow/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ type Client interface {
// UninstallServiceFlows removes flows installed by InstallServiceFlows.
UninstallServiceFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error

InstallServiceShortCircuitingFlows(groupID binding.GroupIDType, svcIP net.IP, svcPort uint16, protocol binding.Protocol, affinityTimeout uint16, svcType v1.ServiceType) error

UninstallServiceShortCircuitingFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error

// GetFlowTableStatus should return an array of flow table status, all existing flow tables should be included in the list.
GetFlowTableStatus() []binding.TableStatus

Expand Down Expand Up @@ -714,6 +718,10 @@ func generateServicePortFlowCacheKey(svcIP net.IP, svcPort uint16, protocol bind
return fmt.Sprintf("S%s%s%x", svcIP, protocol, svcPort)
}

func generateServicePortShortCircuitingFlowCacheKey(svcIP net.IP, svcPort uint16, protocol binding.Protocol) string {
return fmt.Sprintf("S%s%s%x_short_circuiting", svcIP, protocol, svcPort)
}

func (c *client) InstallEndpointFlows(protocol binding.Protocol, endpoints []proxy.Endpoint) error {
c.replayMutex.RLock()
defer c.replayMutex.RUnlock()
Expand Down Expand Up @@ -758,7 +766,7 @@ func (c *client) InstallServiceFlows(groupID binding.GroupIDType, svcIP net.IP,
c.replayMutex.RLock()
defer c.replayMutex.RUnlock()
var flows []binding.Flow
flows = append(flows, c.featureService.serviceLBFlow(groupID, svcIP, svcPort, protocol, affinityTimeout != 0, nodeLocalExternal, svcType, nested))
flows = append(flows, c.featureService.serviceLBFlow(groupID, svcIP, svcPort, protocol, affinityTimeout != 0, nodeLocalExternal, svcType, nested, false))
if affinityTimeout != 0 {
flows = append(flows, c.featureService.serviceLearnFlow(groupID, svcIP, svcPort, protocol, affinityTimeout, nodeLocalExternal, svcType))
}
Expand All @@ -776,9 +784,26 @@ func (c *client) UninstallServiceFlows(svcIP net.IP, svcPort uint16, protocol bi
return c.deleteFlows(c.featureService.cachedFlows, cacheKey)
}

func (c *client) InstallServiceShortCircuitingFlows(groupID binding.GroupIDType, svcIP net.IP, svcPort uint16, protocol binding.Protocol, affinityTimeout uint16, svcType v1.ServiceType) error {
c.replayMutex.RLock()
defer c.replayMutex.RUnlock()
flows := []binding.Flow{c.featureService.serviceLBFlow(groupID, svcIP, svcPort, protocol, affinityTimeout != 0, true, svcType, false, true)}
cacheKey := generateServicePortShortCircuitingFlowCacheKey(svcIP, svcPort, protocol)
return c.addFlows(c.featureService.cachedFlows, cacheKey, flows)
}

func (c *client) UninstallServiceShortCircuitingFlows(svcIP net.IP, svcPort uint16, protocol binding.Protocol) error {
c.replayMutex.RLock()
defer c.replayMutex.RUnlock()
cacheKey := generateServicePortShortCircuitingFlowCacheKey(svcIP, svcPort, protocol)
return c.deleteFlows(c.featureService.cachedFlows, cacheKey)
}

func (c *client) GetServiceFlowKeys(svcIP net.IP, svcPort uint16, protocol binding.Protocol, endpoints []proxy.Endpoint) []string {
cacheKey := generateServicePortFlowCacheKey(svcIP, svcPort, protocol)
flowKeys := c.getFlowKeysFromCache(c.featureService.cachedFlows, cacheKey)
cacheKey = generateServicePortShortCircuitingFlowCacheKey(svcIP, svcPort, protocol)
flowKeys = append(flowKeys, c.getFlowKeysFromCache(c.featureService.cachedFlows, cacheKey)...)
for _, ep := range endpoints {
epPort, _ := ep.Port()
cacheKey = generateEndpointFlowCacheKey(ep.IP(), epPort, protocol)
Expand Down
16 changes: 8 additions & 8 deletions pkg/agent/openflow/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
svcType: corev1.ServiceTypeClusterIP,
expectedFlows: []string{
"cookie=0x1030000000000, table=EndpointDNAT, priority=210,tcp,reg3=0xa600064,reg4=0x1020050/0x107ffff actions=group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x20000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x20000/0x70000->reg4,set_field:0x64->reg7,group:100",
},
},
{
Expand All @@ -1099,7 +1099,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
svcIP: svcIPv4,
svcType: corev1.ServiceTypeClusterIP,
expectedFlows: []string{
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x20000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x64->reg7,set_field:0x1000000/0x1000000->reg4,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x1000000/0x1000000->reg4,set_field:0x20000/0x70000->reg4,set_field:0x64->reg7,group:100",
},
nested: true,
},
Expand All @@ -1111,7 +1111,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
svcType: corev1.ServiceTypeClusterIP,
expectedFlows: []string{
"cookie=0x1030000000000, table=EndpointDNAT, priority=210,tcp,reg3=0xa600064,reg4=0x1020050/0x107ffff actions=group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x30000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x30000/0x70000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000064, table=ServiceLB, priority=190,tcp,reg4=0x30000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=learn(table=SessionAffinity,hard_timeout=100,priority=200,delete_learned,cookie=0x1030000000064,load:0x800->NXM_OF_ETH_TYPE[],load:0x6->NXM_OF_IP_PROTO[],load:OXM_OF_TCP_DST[]->OXM_OF_TCP_DST[],load:NXM_OF_IP_DST[]->NXM_OF_IP_DST[],load:NXM_OF_IP_SRC[]->NXM_OF_IP_SRC[],NXM_NX_REG3[],NXM_NX_REG4[0..15],reg4=0x2,reg0=0x1),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT",
},
},
Expand All @@ -1123,7 +1123,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
svcType: corev1.ServiceTypeClusterIP,
expectedFlows: []string{
"cookie=0x1030000000000, table=EndpointDNAT, priority=210,tcp6,reg4=0x1020050/0x107ffff actions=group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp6,reg4=0x10000/0x70000,ipv6_dst=fec0:10:96::100,tp_dst=80 actions=set_field:0x30000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,tcp6,reg4=0x10000/0x70000,ipv6_dst=fec0:10:96::100,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x30000/0x70000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000064, table=ServiceLB, priority=190,tcp6,reg4=0x30000/0x70000,ipv6_dst=fec0:10:96::100,tp_dst=80 actions=learn(table=SessionAffinity,hard_timeout=100,priority=200,delete_learned,cookie=0x1030000000064,load:0x86dd->NXM_OF_ETH_TYPE[],load:0x6->NXM_OF_IP_PROTO[],load:OXM_OF_TCP_DST[]->OXM_OF_TCP_DST[],load:NXM_NX_IPV6_DST[]->NXM_NX_IPV6_DST[],load:NXM_NX_IPV6_SRC[]->NXM_NX_IPV6_SRC[],NXM_NX_XXREG3[],NXM_NX_REG4[0..15],reg4=0x2,reg0=0x1),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT",
},
},
Expand All @@ -1134,7 +1134,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
affinityTimeout: uint16(100),
svcType: corev1.ServiceTypeNodePort,
expectedFlows: []string{
"cookie=0x1030000000000, table=ServiceLB, priority=200,udp,reg4=0x90000/0xf0000,tp_dst=80 actions=set_field:0x30000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,udp,reg4=0x90000/0xf0000,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x30000/0x70000->reg4,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000064, table=ServiceLB, priority=190,udp,reg4=0xb0000/0xf0000,tp_dst=80 actions=learn(table=SessionAffinity,hard_timeout=100,priority=200,delete_learned,cookie=0x1030000000064,load:0x800->NXM_OF_ETH_TYPE[],load:0x11->NXM_OF_IP_PROTO[],load:OXM_OF_UDP_DST[]->OXM_OF_UDP_DST[],reg4=0x1,load:NXM_OF_IP_DST[]->NXM_OF_IP_DST[],load:NXM_OF_IP_SRC[]->NXM_OF_IP_SRC[],NXM_NX_REG3[],NXM_NX_REG4[0..15],reg4=0x2,reg0=0x1),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT",
},
},
Expand All @@ -1145,7 +1145,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
affinityTimeout: uint16(100),
svcType: corev1.ServiceTypeNodePort,
expectedFlows: []string{
"cookie=0x1030000000000, table=ServiceLB, priority=200,udp6,reg4=0x90000/0xf0000,tp_dst=80 actions=set_field:0x30000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,udp6,reg4=0x90000/0xf0000,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x30000/0x70000->reg4,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000064, table=ServiceLB, priority=190,udp6,reg4=0xb0000/0xf0000,tp_dst=80 actions=learn(table=SessionAffinity,hard_timeout=100,priority=200,delete_learned,cookie=0x1030000000064,load:0x86dd->NXM_OF_ETH_TYPE[],load:0x11->NXM_OF_IP_PROTO[],load:OXM_OF_UDP_DST[]->OXM_OF_UDP_DST[],reg4=0x1,load:NXM_NX_IPV6_DST[]->NXM_NX_IPV6_DST[],load:NXM_NX_IPV6_SRC[]->NXM_NX_IPV6_SRC[],NXM_NX_XXREG3[],NXM_NX_REG4[0..15],reg4=0x2,reg0=0x1),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT",
},
},
Expand All @@ -1156,7 +1156,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
affinityTimeout: uint16(100),
svcType: corev1.ServiceTypeLoadBalancer,
expectedFlows: []string{
"cookie=0x1030000000000, table=ServiceLB, priority=200,sctp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x30000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,sctp,reg4=0x10000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x30000/0x70000->reg4,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000064, table=ServiceLB, priority=190,sctp,reg4=0x30000/0x70000,nw_dst=10.96.0.100,tp_dst=80 actions=learn(table=SessionAffinity,hard_timeout=100,priority=200,delete_learned,cookie=0x1030000000064,load:0x800->NXM_OF_ETH_TYPE[],load:0x84->NXM_OF_IP_PROTO[],load:OXM_OF_SCTP_DST[]->OXM_OF_SCTP_DST[],reg4=0x1,load:NXM_OF_IP_DST[]->NXM_OF_IP_DST[],load:NXM_OF_IP_SRC[]->NXM_OF_IP_SRC[],NXM_NX_REG3[],NXM_NX_REG4[0..15],reg4=0x2,reg0=0x1),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT",
},
},
Expand All @@ -1167,7 +1167,7 @@ func Test_client_InstallServiceFlows(t *testing.T) {
affinityTimeout: uint16(100),
svcType: corev1.ServiceTypeLoadBalancer,
expectedFlows: []string{
"cookie=0x1030000000000, table=ServiceLB, priority=200,sctp6,reg4=0x10000/0x70000,ipv6_dst=fec0:10:96::100,tp_dst=80 actions=set_field:0x30000/0x70000->reg4,set_field:0x200/0x200->reg0,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000000, table=ServiceLB, priority=200,sctp6,reg4=0x10000/0x70000,ipv6_dst=fec0:10:96::100,tp_dst=80 actions=set_field:0x200/0x200->reg0,set_field:0x30000/0x70000->reg4,set_field:0x200000/0x200000->reg4,set_field:0x64->reg7,group:100",
"cookie=0x1030000000064, table=ServiceLB, priority=190,sctp6,reg4=0x30000/0x70000,ipv6_dst=fec0:10:96::100,tp_dst=80 actions=learn(table=SessionAffinity,hard_timeout=100,priority=200,delete_learned,cookie=0x1030000000064,load:0x86dd->NXM_OF_ETH_TYPE[],load:0x84->NXM_OF_IP_PROTO[],load:OXM_OF_SCTP_DST[]->OXM_OF_SCTP_DST[],reg4=0x1,load:NXM_NX_IPV6_DST[]->NXM_NX_IPV6_DST[],load:NXM_NX_IPV6_SRC[]->NXM_NX_IPV6_SRC[],NXM_NX_XXREG3[],NXM_NX_REG4[0..15],reg4=0x2,reg0=0x1),set_field:0x20000/0x70000->reg4,goto_table:EndpointDNAT",
},
},
Expand Down
76 changes: 39 additions & 37 deletions pkg/agent/openflow/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -2375,52 +2375,54 @@ func (f *featureService) serviceLBFlow(groupID binding.GroupIDType,
withSessionAffinity,
nodeLocalExternal bool,
serviceType v1.ServiceType,
nested bool) binding.Flow {
nested bool,
isShortCircuiting bool) binding.Flow {
cookieID := f.cookieAllocator.Request(f.category).Raw()
var lbResultMark *binding.RegMark
regMarksToLoad := []*binding.RegMark{RewriteMACRegMark}
regMarksToMatch := []*binding.RegMark{EpToSelectRegMark}
priority := priorityNormal
// For flow for short-circuiting, priority should be higher since an extra match condition is added.
if isShortCircuiting {
priority = priorityHigh
}
if nested {
regMarksToLoad = append(regMarksToLoad, NestedServiceRegMark)
}
flowBuilder := ServiceLBTable.ofTable.BuildFlow(priority).
Cookie(cookieID).
MatchProtocol(protocol).
MatchDstPort(svcPort, nil)
// For flow for short-circuiting, an extra match condition matching packet from local Pod CIDR is added.
if isShortCircuiting {
flowBuilder = flowBuilder.MatchSrcIPNet(f.localCIDRs[protocol])
}
// The session affinity is set, load EpToLearnRegMark to indicate that service selection is done and the selection result
// needs to be cached, otherwise load EpSelectedRegMark to indicate that service selection is done.
if withSessionAffinity {
lbResultMark = EpToLearnRegMark
regMarksToLoad = append(regMarksToLoad, EpToLearnRegMark)
} else {
lbResultMark = EpSelectedRegMark
regMarksToLoad = append(regMarksToLoad, EpSelectedRegMark)
}
regMarksToLoad := []*binding.RegMark{lbResultMark, RewriteMACRegMark}
var flowBuilder binding.FlowBuilder
// When Service type is NodePort, use ToNodePortAddressRegMark to match, otherwise use Service IP to match.
if serviceType == v1.ServiceTypeNodePort {
unionVal := (ToNodePortAddressRegMark.GetValue() << ServiceEPStateField.GetRange().Length()) + EpToSelectRegMark.GetValue()
// If externalTrafficPolicy of a NodePort Service is Cluster (nodeLocalExternal=false), it loads
// ToClusterServiceRegMark to indicate it. The mark will be checked later when determining if SNAT is required
// or not.
if !nodeLocalExternal {
regMarksToLoad = append(regMarksToLoad, ToClusterServiceRegMark)
}
flowBuilder = ServiceLBTable.ofTable.BuildFlow(priorityNormal).
Cookie(cookieID).
MatchProtocol(protocol).
MatchRegFieldWithValue(NodePortUnionField, unionVal).
MatchDstPort(svcPort, nil).
Action().LoadRegMark(regMarksToLoad...)
regMarksToMatch = append(regMarksToMatch, ToNodePortAddressRegMark)
} else {
// If externalTrafficPolicy of a LoadBalancer/ExternalIP Service is Cluster (nodeLocalExternal=false), it loads
// ToClusterServiceRegMark to indicate it. The mark will be checked later when determining if SNAT is required
// or not.
if (serviceType == v1.ServiceTypeLoadBalancer || serviceType == config.ServiceTypeExternalIP) && !nodeLocalExternal {
regMarksToLoad = append(regMarksToLoad, ToClusterServiceRegMark)
}
flowBuilder = ServiceLBTable.ofTable.BuildFlow(priorityNormal).
Cookie(cookieID).
MatchProtocol(protocol).
MatchDstPort(svcPort, nil).
MatchDstIP(svcIP).
MatchRegMark(EpToSelectRegMark).
Action().LoadRegMark(regMarksToLoad...)
flowBuilder = flowBuilder.MatchDstIP(svcIP)
}
if f.enableAntreaPolicy {
flowBuilder = flowBuilder.Action().LoadToRegField(ServiceGroupIDField, uint32(groupID))
// If externalTrafficPolicy of a NodePort/LoadBalancer/ExternalIP Service is Cluster (nodeLocalExternal=false), it loads
// ToClusterServiceRegMark to indicate it. The mark will be checked later when determining if SNAT is required
// or not.
if !nodeLocalExternal && (serviceType == v1.ServiceTypeNodePort || serviceType == v1.ServiceTypeLoadBalancer || serviceType == config.ServiceTypeExternalIP) {
regMarksToLoad = append(regMarksToLoad, ToClusterServiceRegMark)
}
if nested {
flowBuilder = flowBuilder.Action().LoadRegMark(NestedServiceRegMark)
if f.enableAntreaPolicy {
regMarksToLoad = append(regMarksToLoad, binding.NewRegMark(ServiceGroupIDField, uint32(groupID)))
}
return flowBuilder.Action().Group(groupID).Done()

return flowBuilder.MatchRegMark(regMarksToMatch...).
Action().LoadRegMark(regMarksToLoad...).
Action().Group(groupID).
Done()
}

// endpointRedirectFlowForServiceIP generates the flow which uses the specific group for a Service's ClusterIP
Expand Down
9 changes: 9 additions & 0 deletions pkg/agent/openflow/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type featureService struct {
gatewayMAC net.HardwareAddr
nodePortAddresses map[binding.Protocol][]net.IP
serviceCIDRs map[binding.Protocol]net.IPNet
localCIDRs map[binding.Protocol]net.IPNet
networkConfig *config.NetworkConfig
gatewayPort uint32

Expand Down Expand Up @@ -75,6 +76,7 @@ func newFeatureService(
snatCtZones := make(map[binding.Protocol]int)
nodePortAddresses := make(map[binding.Protocol][]net.IP)
serviceCIDRs := make(map[binding.Protocol]net.IPNet)
localCIDRs := make(map[binding.Protocol]net.IPNet)
for _, ipProtocol := range ipProtocols {
if ipProtocol == binding.ProtocolIP {
gatewayIPs[ipProtocol] = nodeConfig.GatewayConfig.IPv4
Expand All @@ -86,6 +88,9 @@ func newFeatureService(
if serviceConfig.ServiceCIDR != nil {
serviceCIDRs[ipProtocol] = *serviceConfig.ServiceCIDR
}
if nodeConfig.PodIPv4CIDR != nil {
localCIDRs[ipProtocol] = *nodeConfig.PodIPv4CIDR
}
} else if ipProtocol == binding.ProtocolIPv6 {
gatewayIPs[ipProtocol] = nodeConfig.GatewayConfig.IPv6
virtualIPs[ipProtocol] = config.VirtualServiceIPv6
Expand All @@ -96,6 +101,9 @@ func newFeatureService(
if serviceConfig.ServiceCIDRv6 != nil {
serviceCIDRs[ipProtocol] = *serviceConfig.ServiceCIDRv6
}
if nodeConfig.PodIPv6CIDR != nil {
localCIDRs[ipProtocol] = *nodeConfig.PodIPv6CIDR
}
}
}

Expand All @@ -112,6 +120,7 @@ func newFeatureService(
snatCtZones: snatCtZones,
nodePortAddresses: nodePortAddresses,
serviceCIDRs: serviceCIDRs,
localCIDRs: localCIDRs,
gatewayMAC: nodeConfig.GatewayConfig.MAC,
gatewayPort: nodeConfig.GatewayConfig.OFPort,
networkConfig: networkConfig,
Expand Down
Loading

0 comments on commit 29a1a29

Please sign in to comment.