Fix: obtain the correct external gateway NAT IP address
1. Add verbose message in stateful SNAT rules installation phase
2. Refactor openstack networking util
Change-Id: Ia74a529657bf0e7b34957053e1411786ba3fe0d5
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
index b6bde75..04e6b62 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
@@ -96,9 +96,9 @@
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.ARP_MODE_DEFAULT;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.GATEWAY_MAC_DEFAULT;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalGatewayIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterForNetwork;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.floatingIpByInstancePort;
-import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getExternalIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
@@ -539,7 +539,7 @@
private void setFakeGatewayArpRuleByRouter(Router router, boolean install) {
if (ARP_BROADCAST_MODE.equals(getArpMode())) {
- IpAddress externalIp = getExternalIp(router, osNetworkService);
+ IpAddress externalIp = externalGatewayIp(router, osNetworkService);
if (externalIp == null) {
log.debug("External IP is not found");
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
index d835cca..4a8dc7c 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
@@ -116,10 +116,10 @@
import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT_DEFAULT;
-import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalIpFromSubnet;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalGatewayIpSnatEnabled;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterFromSubnet;
-import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getExternalIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValueAsBoolean;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getRouterFromSubnet;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.CT_NAT_SRC_FLAG;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
@@ -298,8 +298,17 @@
IpAddress srcIp = IpAddress.valueOf(iPacket.getSourceAddress());
Subnet srcSubnet = getSourceSubnet(srcInstPort, srcIp);
+
+ Router osRouter = getRouterFromSubnet(srcSubnet, osRouterService);
+
+ if (osRouter == null || osRouter.getExternalGatewayInfo() == null) {
+ // this router does not have external connectivity
+ log.warn("No router is associated with the given subnet {}", srcSubnet);
+ return;
+ }
+
IpAddress externalGatewayIp =
- externalIpFromSubnet(srcSubnet, osRouterService, osNetworkService);
+ externalGatewayIpSnatEnabled(osRouter, osNetworkAdminService);
if (externalGatewayIp == null) {
return;
@@ -804,36 +813,38 @@
Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
if (netType == FLAT) {
+ log.warn("FLAT typed network does not need SNAT rules");
return;
}
Optional<Router> osRouter = osRouterService.routers().stream()
- .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
+ .filter(router -> routerIface.getId().equals(router.getId()))
.findAny();
if (!osRouter.isPresent()) {
- log.error("Cannot find a router for router interface {} ", routerIface);
+ log.warn("Cannot find a router attached with the given router interface {} ", routerIface);
return;
}
- IpAddress natAddress = getExternalIp(osRouter.get(), osNetworkService);
+ IpAddress natAddress = externalGatewayIpSnatEnabled(osRouter.get(), osNetworkAdminService);
if (natAddress == null) {
+ log.warn("NAT address is not found");
return;
}
IpAddress extRouterAddress = getGatewayIpAddress(osRouter.get());
if (extRouterAddress == null) {
+ log.warn("External router address is not found");
return;
}
ExternalPeerRouter externalPeerRouter =
osNetworkService.externalPeerRouter(extRouterAddress);
if (externalPeerRouter == null) {
+ log.warn("External peer router not found");
return;
}
- String netId = osNetworkAdminService.subnet(routerIface.getSubnetId()).getNetworkId();
-
Map<OpenstackNode, PortRange> gwPortRangeMap = getAssignedPortsForGateway(
ImmutableList.copyOf(osNodeService.nodes(GATEWAY)));
@@ -865,7 +876,7 @@
return;
}
- IpAddress natAddress = getExternalIp(osRouter, osNetworkAdminService);
+ IpAddress natAddress = externalGatewayIpSnatEnabled(osRouter, osNetworkAdminService);
if (natAddress == null) {
return;
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatIcmpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatIcmpHandler.java
index 5e89e4b..6b9adac 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatIcmpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatIcmpHandler.java
@@ -85,9 +85,10 @@
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
-import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalIpFromSubnet;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalGatewayIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterFromSubnet;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValueAsBoolean;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getRouterFromSubnet;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
import static org.slf4j.LoggerFactory.getLogger;
@@ -347,9 +348,17 @@
// this is a request to an external network
log.trace("Icmp request to external {} from {}", dstIp, srcIp);
- IpAddress externalIp = externalIpFromSubnet(srcSubnet,
- osRouterService, osNetworkService);
- if (externalIp == null) {
+ Router osRouter = getRouterFromSubnet(srcSubnet, osRouterService);
+
+ if (osRouter == null || osRouter.getExternalGatewayInfo() == null) {
+ // this router does not have external connectivity
+ log.warn("No router is associated with the given subnet {}", srcSubnet);
+ return false;
+ }
+
+ IpAddress externalGatewayIp = externalGatewayIp(osRouter, osNetworkService);
+
+ if (externalGatewayIp == null) {
log.warn(ERR_REQ + "failed to get external ip");
return false;
}
@@ -362,12 +371,11 @@
return false;
}
- String icmpInfoKey = icmpInfoKey(icmp,
- externalIp.toString(),
+ String icmpInfoKey = icmpInfoKey(icmp, externalGatewayIp.toString(),
IPv4.fromIPv4Address(ipPacket.getDestinationAddress()));
log.trace("Created icmpInfo key is {}", icmpInfoKey);
- sendRequestForExternal(ipPacket, srcDevice, externalIp, externalPeerRouter);
+ sendRequestForExternal(ipPacket, srcDevice, externalGatewayIp, externalPeerRouter);
try {
icmpInfoMap.compute(icmpInfoKey, (id, existing) -> {
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java
index b75e5fa..914a910 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java
@@ -72,7 +72,7 @@
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ICMP_RULE;
import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
-import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getExternalIp;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalGatewayIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValueAsBoolean;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
@@ -193,7 +193,7 @@
Router osRouter,
boolean install) {
- IpAddress natAddress = getExternalIp(osRouter, osNetworkService);
+ IpAddress natAddress = externalGatewayIp(osRouter, osNetworkService);
if (natAddress == null) {
return;
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index 003f01c..61ba3f8 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -1165,64 +1165,27 @@
}
/**
- * Returns the external ip address with specified router information.
- *
- * @param srcSubnet source subnet
- * @param osRouterService openstack router service
- * @param osNetworkService openstack network service
- * @return external ip address
- */
- public static IpAddress externalIpFromSubnet(Subnet srcSubnet,
- OpenstackRouterService
- osRouterService,
- OpenstackNetworkService
- osNetworkService) {
-
- Router osRouter = getRouterFromSubnet(srcSubnet, osRouterService);
-
- if (osRouter.getExternalGatewayInfo() == null) {
- // this router does not have external connectivity
- log.trace("router({}) has no external gateway",
- osRouter.getName());
- return null;
- }
-
- return getExternalIp(osRouter, osNetworkService);
- }
-
- /**
- * Returns the external ip address with specified router information.
+ * Returns the external gateway IP address with specified router information.
*
* @param router openstack router
* @param osNetworkService openstack network service
- * @return external ip address
+ * @return external IP address
*/
- public static IpAddress getExternalIp(Router router,
- OpenstackNetworkService osNetworkService) {
- if (router == null) {
- return null;
- }
+ public static IpAddress externalGatewayIp(Router router,
+ OpenstackNetworkService osNetworkService) {
+ return externalGatewayIpBase(router, false, osNetworkService);
+ }
- ExternalGateway externalGateway = router.getExternalGatewayInfo();
- if (externalGateway == null || !externalGateway.isEnableSnat()) {
- log.trace("Failed to get externalIp for router {} because " +
- "externalGateway is null or SNAT is disabled",
- router.getId());
- return null;
- }
-
- // TODO fix openstack4j for ExternalGateway provides external fixed IP list
- Port exGatewayPort = osNetworkService.ports(externalGateway.getNetworkId())
- .stream()
- .filter(port -> Objects.equals(port.getDeviceId(), router.getId()))
- .findAny().orElse(null);
-
- if (exGatewayPort == null) {
- return null;
- }
-
- return IpAddress.valueOf(exGatewayPort.getFixedIps().stream()
- .findAny().get().getIpAddress());
+ /**
+ * Returns the external gateway IP address (SNAT enabled) with specified router information.
+ *
+ * @param router openstack router
+ * @param osNetworkService openstack network service
+ * @return external IP address
+ */
+ public static IpAddress externalGatewayIpSnatEnabled(Router router,
+ OpenstackNetworkService osNetworkService) {
+ return externalGatewayIpBase(router, true, osNetworkService);
}
/**
@@ -1405,8 +1368,15 @@
return null;
}
- private static Router getRouterFromSubnet(Subnet subnet,
- OpenstackRouterService osRouterService) {
+ /**
+ * Return the router associated with the given subnet.
+ *
+ * @param subnet openstack subnet
+ * @param osRouterService openstack router service
+ * @return router
+ */
+ public static Router getRouterFromSubnet(Subnet subnet,
+ OpenstackRouterService osRouterService) {
RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
.filter(i -> Objects.equals(i.getSubnetId(), subnet.getId()))
.findAny().orElse(null);
@@ -1609,6 +1579,49 @@
return gw;
}
+ /**
+ * Returns the external gateway IP address with specified router information.
+ *
+ * @param router openstack router
+ * @param snatOnly true for only query SNAT enabled case, false otherwise
+ * @param osNetworkService openstack network service
+ * @return external IP address
+ */
+ private static IpAddress externalGatewayIpBase(Router router, boolean snatOnly,
+ OpenstackNetworkService osNetworkService) {
+ if (router == null) {
+ return null;
+ }
+
+ ExternalGateway externalGateway = router.getExternalGatewayInfo();
+ if (externalGateway == null) {
+ log.info("Failed to get external IP for router {} because no " +
+ "external gateway is associated with the router",
+ router.getId());
+ return null;
+ }
+
+ if (snatOnly) {
+ if (!externalGateway.isEnableSnat()) {
+ log.warn("The given router {} SNAT is configured as false", router.getId());
+ return null;
+ }
+ }
+
+ // TODO fix openstack4j for ExternalGateway provides external fixed IP list
+ Port exGatewayPort = osNetworkService.ports(externalGateway.getNetworkId())
+ .stream()
+ .filter(port -> Objects.equals(port.getDeviceId(), router.getId()))
+ .findAny().orElse(null);
+
+ if (exGatewayPort == null) {
+ return null;
+ }
+
+ return IpAddress.valueOf(exGatewayPort.getFixedIps().stream()
+ .findAny().get().getIpAddress());
+ }
+
private static void print(String format, Object... args) {
System.out.println(String.format(format, args));
}