Skip to content

Commit ab24f25

Browse files
committed
[gateway] cleanup: do some equivalent changes to simplify the code.
Move stuff evaluation closer to where it is used. Replace gatewayRouter with gw.gwRouterName (why would you use this indirection?) Rename logicalRouter to gwRouter Join 2 very similar loops for gwLRPIPs and gwLRPJoinIPs (they even had exactly the same comment) Remove deleting GatewayRouter LRP as the GatewayRouter itself is deleted a coupled lines below. Signed-off-by: Nadia Pinaeva <[email protected]>
1 parent 2edfdaf commit ab24f25

File tree

1 file changed

+65
-86
lines changed

1 file changed

+65
-86
lines changed

go-controller/pkg/ovn/gateway.go

Lines changed: 65 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -254,27 +254,7 @@ func (gw *GatewayManager) GatewayInit(
254254
enableGatewayMTU bool,
255255
) error {
256256

257-
gwLRPIPs := make([]net.IP, 0)
258-
for _, gwLRPJoinIP := range gwLRPJoinIPs {
259-
gwLRPIPs = append(gwLRPIPs, gwLRPJoinIP.IP)
260-
}
261-
if gw.netInfo.TopologyType() == types.Layer2Topology {
262-
// At layer2 GR LRP acts as the layer3 ovn_cluster_router so we need
263-
// to configure here the .1 address, this will work only for IC with
264-
// one node per zone, since ARPs for .1 will not go beyond local switch.
265-
// This is being done to add the ICMP SNATs for .1 podSubnet that OVN GR generates
266-
for _, subnet := range hostSubnets {
267-
gwLRPIPs = append(gwLRPIPs, util.GetNodeGatewayIfAddr(subnet).IP)
268-
}
269-
}
270-
271257
// Create a gateway router.
272-
gatewayRouter := gw.gwRouterName
273-
physicalIPs := make([]string, len(l3GatewayConfig.IPAddresses))
274-
for i, ip := range l3GatewayConfig.IPAddresses {
275-
physicalIPs[i] = ip.IP.String()
276-
}
277-
278258
dynamicNeighRouters := "true"
279259
if config.OVNKubernetesFeature.EnableInterconnect {
280260
dynamicNeighRouters = "false"
@@ -305,6 +285,10 @@ func (gw *GatewayManager) GatewayInit(
305285
}
306286
logicalRouterOptions["lb_force_snat_ip"] = strings.Join(joinIPDualStack, " ")
307287
}
288+
physicalIPs := make([]string, len(l3GatewayConfig.IPAddresses))
289+
for i, ip := range l3GatewayConfig.IPAddresses {
290+
physicalIPs[i] = ip.IP.String()
291+
}
308292
logicalRouterExternalIDs := map[string]string{
309293
"physical_ip": physicalIPs[0],
310294
"physical_ips": strings.Join(physicalIPs, ","),
@@ -314,27 +298,27 @@ func (gw *GatewayManager) GatewayInit(
314298
maps.Copy(logicalRouterExternalIDs, util.GenerateExternalIDsForSwitchOrRouter(gw.netInfo))
315299
}
316300

317-
logicalRouter := nbdb.LogicalRouter{
318-
Name: gatewayRouter,
301+
gwRouter := nbdb.LogicalRouter{
302+
Name: gw.gwRouterName,
319303
Options: logicalRouterOptions,
320304
ExternalIDs: logicalRouterExternalIDs,
321305
Copp: &gw.coppUUID,
322306
}
323307

324308
if gw.clusterLoadBalancerGroupUUID != "" {
325-
logicalRouter.LoadBalancerGroup = []string{gw.clusterLoadBalancerGroupUUID}
309+
gwRouter.LoadBalancerGroup = []string{gw.clusterLoadBalancerGroupUUID}
326310
if l3GatewayConfig.NodePortEnable && gw.routerLoadBalancerGroupUUID != "" {
327311
// add routerLoadBalancerGroupUUID to the gateway router only if nodePort is enabled
328-
logicalRouter.LoadBalancerGroup = append(logicalRouter.LoadBalancerGroup, gw.routerLoadBalancerGroupUUID)
312+
gwRouter.LoadBalancerGroup = append(gwRouter.LoadBalancerGroup, gw.routerLoadBalancerGroupUUID)
329313
}
330314
}
331315

332316
// If l3gatewayAnnotation.IPAddresses changed, we need to update the perPodSNATs,
333317
// so let's save the old value before we update the router for later use
334318
var oldExtIPs []net.IP
335-
oldLogicalRouter, err := libovsdbops.GetLogicalRouter(gw.nbClient, &logicalRouter)
319+
oldLogicalRouter, err := libovsdbops.GetLogicalRouter(gw.nbClient, &gwRouter)
336320
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
337-
return fmt.Errorf("failed in retrieving %s, error: %v", gatewayRouter, err)
321+
return fmt.Errorf("failed in retrieving %s, error: %v", gw.gwRouterName, err)
338322
}
339323

340324
if oldLogicalRouter != nil && oldLogicalRouter.ExternalIDs != nil {
@@ -352,14 +336,14 @@ func (gw *GatewayManager) GatewayInit(
352336
}
353337
}
354338

355-
err = libovsdbops.CreateOrUpdateLogicalRouter(gw.nbClient, &logicalRouter, &logicalRouter.Options,
356-
&logicalRouter.ExternalIDs, &logicalRouter.LoadBalancerGroup, &logicalRouter.Copp)
339+
err = libovsdbops.CreateOrUpdateLogicalRouter(gw.nbClient, &gwRouter, &gwRouter.Options,
340+
&gwRouter.ExternalIDs, &gwRouter.LoadBalancerGroup, &gwRouter.Copp)
357341
if err != nil {
358-
return fmt.Errorf("failed to create logical router %+v: %v", logicalRouter, err)
342+
return fmt.Errorf("failed to create logical router %+v: %v", gwRouter, err)
359343
}
360344

361-
gwSwitchPort := types.JoinSwitchToGWRouterPrefix + gatewayRouter
362-
gwRouterPort := types.GWRouterToJoinSwitchPrefix + gatewayRouter
345+
gwSwitchPort := types.JoinSwitchToGWRouterPrefix + gw.gwRouterName
346+
gwRouterPort := types.GWRouterToJoinSwitchPrefix + gw.gwRouterName
363347

364348
// In Layer2 networks there is no join switch and the gw.joinSwitchName points to the cluster switch.
365349
// Ensure that the ports are named appropriately, this is important for the logical router policies
@@ -383,43 +367,47 @@ func (gw *GatewayManager) GatewayInit(
383367
types.NetworkExternalID: gw.netInfo.GetNetworkName(),
384368
types.TopologyExternalID: gw.netInfo.TopologyType(),
385369
}
386-
if gw.netInfo.TopologyType() == types.Layer2Topology {
387-
node, err := gw.watchFactory.GetNode(nodeName)
388-
if err != nil {
389-
return fmt.Errorf("failed to fetch node %s from watch factory %w", node, err)
390-
}
391-
tunnelID, err := util.ParseUDNLayer2NodeGRLRPTunnelIDs(node, gw.netInfo.GetNetworkName())
392-
if err != nil {
393-
if util.IsAnnotationNotSetError(err) {
394-
// remote node may not have the annotation yet, suppress it
395-
return types.NewSuppressedError(err)
396-
}
397-
// Don't consider this node as cluster-manager has not allocated node id yet.
398-
return fmt.Errorf("failed to fetch tunnelID annotation from the node %s for network %s, err: %w",
399-
nodeName, gw.netInfo.GetNetworkName(), err)
370+
}
371+
if gw.netInfo.TopologyType() == types.Layer2Topology {
372+
node, err := gw.watchFactory.GetNode(nodeName)
373+
if err != nil {
374+
return fmt.Errorf("failed to fetch node %s from watch factory %w", node, err)
375+
}
376+
tunnelID, err := util.ParseUDNLayer2NodeGRLRPTunnelIDs(node, gw.netInfo.GetNetworkName())
377+
if err != nil {
378+
if util.IsAnnotationNotSetError(err) {
379+
// remote node may not have the annotation yet, suppress it
380+
return types.NewSuppressedError(err)
400381
}
401-
logicalSwitchPort.Options["requested-tnl-key"] = strconv.Itoa(tunnelID)
382+
// Don't consider this node as cluster-manager has not allocated node id yet.
383+
return fmt.Errorf("failed to fetch tunnelID annotation from the node %s for network %s, err: %w",
384+
nodeName, gw.netInfo.GetNetworkName(), err)
402385
}
386+
logicalSwitchPort.Options["requested-tnl-key"] = strconv.Itoa(tunnelID)
403387
}
404388
sw := nbdb.LogicalSwitch{Name: gw.joinSwitchName}
405389
err = libovsdbops.CreateOrUpdateLogicalSwitchPortsOnSwitch(gw.nbClient, &sw, &logicalSwitchPort)
406390
if err != nil {
407391
return fmt.Errorf("failed to create port %v on logical switch %q: %v", gwSwitchPort, sw.Name, err)
408392
}
409393

410-
gwLRPMAC := util.IPAddrToHWAddr(gwLRPIPs[0])
394+
gwLRPIPs := make([]net.IP, 0)
411395
gwLRPNetworks := []string{}
412396
for _, gwLRPJoinIP := range gwLRPJoinIPs {
397+
gwLRPIPs = append(gwLRPIPs, gwLRPJoinIP.IP)
413398
gwLRPNetworks = append(gwLRPNetworks, gwLRPJoinIP.String())
414399
}
415400
if gw.netInfo.TopologyType() == types.Layer2Topology {
416401
// At layer2 GR LRP acts as the layer3 ovn_cluster_router so we need
417402
// to configure here the .1 address, this will work only for IC with
418403
// one node per zone, since ARPs for .1 will not go beyond local switch.
404+
// This is being done to add the ICMP SNATs for .1 podSubnet that OVN GR generates
419405
for _, subnet := range hostSubnets {
406+
gwLRPIPs = append(gwLRPIPs, util.GetNodeGatewayIfAddr(subnet).IP)
420407
gwLRPNetworks = append(gwLRPNetworks, util.GetNodeGatewayIfAddr(subnet).String())
421408
}
422409
}
410+
gwLRPMAC := util.IPAddrToHWAddr(gwLRPIPs[0])
423411

424412
var options map[string]string
425413
if enableGatewayMTU {
@@ -453,19 +441,19 @@ func (gw *GatewayManager) GatewayInit(
453441
}
454442
}
455443

456-
err = libovsdbops.CreateOrUpdateLogicalRouterPort(gw.nbClient, &logicalRouter,
444+
err = libovsdbops.CreateOrUpdateLogicalRouterPort(gw.nbClient, &gwRouter,
457445
&logicalRouterPort, nil, &logicalRouterPort.MAC, &logicalRouterPort.Networks,
458446
&logicalRouterPort.Options)
459447
if err != nil {
460-
return fmt.Errorf("failed to create port %+v on router %+v: %v", logicalRouterPort, logicalRouter, err)
448+
return fmt.Errorf("failed to create port %+v on router %+v: %v", logicalRouterPort, gwRouter, err)
461449
}
462450
if len(drLRPIfAddrs) > 0 {
463451
for _, entry := range clusterIPSubnet {
464452
drLRPIfAddr, err := util.MatchFirstIPNetFamily(utilnet.IsIPv6CIDR(entry), drLRPIfAddrs)
465453
if err != nil {
466454
return fmt.Errorf("failed to add a static route in GR %s with distributed "+
467455
"router as the nexthop: %v",
468-
gatewayRouter, err)
456+
gw.gwRouterName, err)
469457
}
470458

471459
// TODO There has to be a better way to do this. It seems like the
@@ -476,9 +464,9 @@ func (gw *GatewayManager) GatewayInit(
476464
// a better way to do it. Adding support for indirection in ModelClients
477465
// opModel (being able to operate on thins pointed to from another model)
478466
// would be a great way to simplify this.
479-
updatedLogicalRouter, err := libovsdbops.GetLogicalRouter(gw.nbClient, &logicalRouter)
467+
updatedGWRouter, err := libovsdbops.GetLogicalRouter(gw.nbClient, &gwRouter)
480468
if err != nil {
481-
return fmt.Errorf("unable to retrieve logical router %+v: %v", logicalRouter, err)
469+
return fmt.Errorf("unable to retrieve logical router %+v: %v", gwRouter, err)
482470
}
483471

484472
lrsr := nbdb.LogicalRouterStaticRoute{
@@ -493,19 +481,19 @@ func (gw *GatewayManager) GatewayInit(
493481
}
494482
p := func(item *nbdb.LogicalRouterStaticRoute) bool {
495483
return item.IPPrefix == lrsr.IPPrefix && libovsdbops.PolicyEqualPredicate(item.Policy, lrsr.Policy) &&
496-
util.SliceHasStringItem(updatedLogicalRouter.StaticRoutes, item.UUID)
484+
util.SliceHasStringItem(updatedGWRouter.StaticRoutes, item.UUID)
497485
}
498-
err = libovsdbops.CreateOrReplaceLogicalRouterStaticRouteWithPredicate(gw.nbClient, gatewayRouter, &lrsr, p,
486+
err = libovsdbops.CreateOrReplaceLogicalRouterStaticRouteWithPredicate(gw.nbClient, gw.gwRouterName, &lrsr, p,
499487
&lrsr.Nexthop)
500488
if err != nil {
501-
return fmt.Errorf("failed to add a static route %+v in GR %s with distributed router as the nexthop, err: %v", lrsr, gatewayRouter, err)
489+
return fmt.Errorf("failed to add a static route %+v in GR %s with distributed router as the nexthop, err: %v", lrsr, gw.gwRouterName, err)
502490
}
503491
}
504492
}
505493

506494
if err := gw.addExternalSwitch("",
507495
l3GatewayConfig.InterfaceID,
508-
gatewayRouter,
496+
gw.gwRouterName,
509497
l3GatewayConfig.MACAddress.String(),
510498
physNetName(gw.netInfo),
511499
l3GatewayConfig.IPAddresses,
@@ -516,7 +504,7 @@ func (gw *GatewayManager) GatewayInit(
516504
if l3GatewayConfig.EgressGWInterfaceID != "" {
517505
if err := gw.addExternalSwitch(types.EgressGWSwitchPrefix,
518506
l3GatewayConfig.EgressGWInterfaceID,
519-
gatewayRouter,
507+
gw.gwRouterName,
520508
l3GatewayConfig.EgressGWMACAddress.String(),
521509
types.PhysicalNetworkExGwName,
522510
l3GatewayConfig.EgressGWIPAddresses,
@@ -525,16 +513,16 @@ func (gw *GatewayManager) GatewayInit(
525513
}
526514
}
527515

528-
externalRouterPort := types.GWRouterToExtSwitchPrefix + gatewayRouter
516+
externalRouterPort := types.GWRouterToExtSwitchPrefix + gw.gwRouterName
529517

530518
nextHops := l3GatewayConfig.NextHops
531519

532520
// Remove stale OVN resources with any old masquerade IP
533-
if err := deleteStaleMasqueradeResources(gw.nbClient, gatewayRouter, nodeName, gw.watchFactory); err != nil {
521+
if err := deleteStaleMasqueradeResources(gw.nbClient, gw.gwRouterName, nodeName, gw.watchFactory); err != nil {
534522
return fmt.Errorf("failed to remove stale masquerade resources from northbound database: %w", err)
535523
}
536524

537-
if err := gateway.CreateDummyGWMacBindings(gw.nbClient, gatewayRouter, gw.netInfo); err != nil {
525+
if err := gateway.CreateDummyGWMacBindings(gw.nbClient, gw.gwRouterName, gw.netInfo); err != nil {
538526
return err
539527
}
540528

@@ -560,10 +548,10 @@ func (gw *GatewayManager) GatewayInit(
560548
return item.OutputPort != nil && *item.OutputPort == *lrsr.OutputPort && item.IPPrefix == lrsr.IPPrefix &&
561549
libovsdbops.PolicyEqualPredicate(item.Policy, lrsr.Policy)
562550
}
563-
err = libovsdbops.CreateOrReplaceLogicalRouterStaticRouteWithPredicate(gw.nbClient, gatewayRouter, &lrsr, p,
551+
err = libovsdbops.CreateOrReplaceLogicalRouterStaticRouteWithPredicate(gw.nbClient, gw.gwRouterName, &lrsr, p,
564552
&lrsr.Nexthop)
565553
if err != nil {
566-
return fmt.Errorf("error creating service static route %+v in GR %s: %v", lrsr, gatewayRouter, err)
554+
return fmt.Errorf("error creating service static route %+v in GR %s: %v", lrsr, gw.gwRouterName, err)
567555
}
568556
}
569557
// Add default gateway routes in GR
@@ -590,10 +578,10 @@ func (gw *GatewayManager) GatewayInit(
590578
return item.OutputPort != nil && *item.OutputPort == *lrsr.OutputPort && item.IPPrefix == lrsr.IPPrefix &&
591579
libovsdbops.PolicyEqualPredicate(lrsr.Policy, item.Policy)
592580
}
593-
err := libovsdbops.CreateOrReplaceLogicalRouterStaticRouteWithPredicate(gw.nbClient, gatewayRouter, &lrsr,
581+
err := libovsdbops.CreateOrReplaceLogicalRouterStaticRouteWithPredicate(gw.nbClient, gw.gwRouterName, &lrsr,
594582
p, &lrsr.Nexthop)
595583
if err != nil {
596-
return fmt.Errorf("error creating static route %+v in GR %s: %v", lrsr, gatewayRouter, err)
584+
return fmt.Errorf("error creating static route %+v in GR %s: %v", lrsr, gw.gwRouterName, err)
597585
}
598586
}
599587

@@ -718,7 +706,7 @@ func (gw *GatewayManager) GatewayInit(
718706
for _, externalIP := range externalIPs {
719707
oldExternalIP, err := util.MatchFirstIPFamily(utilnet.IsIPv6(externalIP), oldExtIPs)
720708
if err != nil {
721-
return fmt.Errorf("failed to update GW SNAT rule for pods on router %s error: %v", gatewayRouter, err)
709+
return fmt.Errorf("failed to update GW SNAT rule for pods on router %s error: %v", gw.gwRouterName, err)
722710
}
723711
if externalIP.String() == oldExternalIP.String() {
724712
// no external ip change, skip
@@ -740,7 +728,7 @@ func (gw *GatewayManager) GatewayInit(
740728
joinIP, err := util.MatchFirstIPFamily(utilnet.IsIPv6(parsedLogicalIP), gwLRPIPs)
741729
if err != nil {
742730
return fmt.Errorf("failed to find valid IP family match for join subnet IP: %s on "+
743-
"gateway router: %s, provided IPs: %#v", parsedLogicalIP, gatewayRouter, gwLRPIPs)
731+
"gateway router: %s, provided IPs: %#v", parsedLogicalIP, gw.gwRouterName, gwLRPIPs)
744732
}
745733
if nat.LogicalIP != joinIP.String() {
746734
// needs to be updated
@@ -754,9 +742,9 @@ func (gw *GatewayManager) GatewayInit(
754742
}
755743

756744
if len(natsToUpdate) > 0 {
757-
err = libovsdbops.CreateOrUpdateNATs(gw.nbClient, &logicalRouter, natsToUpdate...)
745+
err = libovsdbops.CreateOrUpdateNATs(gw.nbClient, &gwRouter, natsToUpdate...)
758746
if err != nil {
759-
return fmt.Errorf("failed to update GW SNAT rule for pod on router %s error: %v", gatewayRouter, err)
747+
return fmt.Errorf("failed to update GW SNAT rule for pod on router %s error: %v", gw.gwRouterName, err)
760748
}
761749
}
762750

@@ -773,7 +761,7 @@ func (gw *GatewayManager) GatewayInit(
773761
externalIP, err := util.MatchIPFamily(utilnet.IsIPv6(gwLRPIP), externalIPs)
774762
if err != nil {
775763
return fmt.Errorf("failed to find valid external IP family match for join subnet IP: %s on "+
776-
"gateway router: %s", gwLRPIP, gatewayRouter)
764+
"gateway router: %s", gwLRPIP, gw.gwRouterName)
777765
}
778766
joinIPNet, err := util.GetIPNetFullMask(gwLRPIP.String())
779767
if err != nil {
@@ -782,9 +770,9 @@ func (gw *GatewayManager) GatewayInit(
782770
nat := libovsdbops.BuildSNAT(&externalIP[0], joinIPNet, "", extIDs)
783771
joinNATs = append(joinNATs, nat)
784772
}
785-
err = libovsdbops.CreateOrUpdateNATs(gw.nbClient, &logicalRouter, joinNATs...)
773+
err = libovsdbops.CreateOrUpdateNATs(gw.nbClient, &gwRouter, joinNATs...)
786774
if err != nil {
787-
return fmt.Errorf("failed to create SNAT rule for join subnet on router %s error: %v", gatewayRouter, err)
775+
return fmt.Errorf("failed to create SNAT rule for join subnet on router %s error: %v", gw.gwRouterName, err)
788776
}
789777

790778
nats := make([]*nbdb.NAT, 0, len(clusterIPSubnet))
@@ -796,25 +784,25 @@ func (gw *GatewayManager) GatewayInit(
796784
externalIP, err := util.MatchIPFamily(utilnet.IsIPv6CIDR(entry), externalIPs)
797785
if err != nil {
798786
return fmt.Errorf("failed to create default SNAT rules for gateway router %s: %v",
799-
gatewayRouter, err)
787+
gw.gwRouterName, err)
800788
}
801789

802790
nat = libovsdbops.BuildSNATWithMatch(&externalIP[0], entry, "", extIDs, gw.netInfo.GetNetworkScopedClusterSubnetSNATMatch(nodeName))
803791
nats = append(nats, nat)
804792
}
805-
err := libovsdbops.CreateOrUpdateNATs(gw.nbClient, &logicalRouter, nats...)
793+
err := libovsdbops.CreateOrUpdateNATs(gw.nbClient, &gwRouter, nats...)
806794
if err != nil {
807-
return fmt.Errorf("failed to update SNAT rule for pod on router %s error: %v", gatewayRouter, err)
795+
return fmt.Errorf("failed to update SNAT rule for pod on router %s error: %v", gw.gwRouterName, err)
808796
}
809797
} else {
810798
// ensure we do not have any leftover SNAT entries after an upgrade
811799
for _, logicalSubnet := range clusterIPSubnet {
812800
nat = libovsdbops.BuildSNATWithMatch(nil, logicalSubnet, "", extIDs, gw.netInfo.GetNetworkScopedClusterSubnetSNATMatch(nodeName))
813801
nats = append(nats, nat)
814802
}
815-
err := libovsdbops.DeleteNATs(gw.nbClient, &logicalRouter, nats...)
803+
err := libovsdbops.DeleteNATs(gw.nbClient, &gwRouter, nats...)
816804
if err != nil {
817-
return fmt.Errorf("failed to delete GW SNAT rule for pod on router %s error: %v", gatewayRouter, err)
805+
return fmt.Errorf("failed to delete GW SNAT rule for pod on router %s error: %v", gw.gwRouterName, err)
818806
}
819807
}
820808

@@ -1115,23 +1103,14 @@ func (gw *GatewayManager) Cleanup() error {
11151103
return fmt.Errorf("failed to delete logical switch port %s from switch %s: %w", portName, sw.Name, err)
11161104
}
11171105

1118-
// Remove the logical router port on the gateway router that connects to the join switch
1119-
logicalRouter := nbdb.LogicalRouter{Name: gw.gwRouterName}
1120-
logicalRouterPort := nbdb.LogicalRouterPort{
1121-
Name: gwRouterToJoinSwitchPortName,
1122-
}
1123-
err = libovsdbops.DeleteLogicalRouterPorts(gw.nbClient, &logicalRouter, &logicalRouterPort)
1124-
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
1125-
return fmt.Errorf("failed to delete port %s on router %s: %w", logicalRouterPort.Name, gw.gwRouterName, err)
1126-
}
1127-
11281106
// Remove the static mac bindings of the gateway router
11291107
err = gateway.DeleteDummyGWMacBindings(gw.nbClient, gw.gwRouterName, gw.netInfo)
11301108
if err != nil {
11311109
return fmt.Errorf("failed to delete GR dummy mac bindings for node %s: %w", gw.nodeName, err)
11321110
}
11331111

11341112
// Remove the gateway router associated with nodeName
1113+
logicalRouter := nbdb.LogicalRouter{Name: gw.gwRouterName}
11351114
err = libovsdbops.DeleteLogicalRouter(gw.nbClient, &logicalRouter)
11361115
if err != nil && !errors.Is(err, libovsdbclient.ErrNotFound) {
11371116
return fmt.Errorf("failed to delete gateway router %s: %w", gw.gwRouterName, err)

0 commit comments

Comments
 (0)