[ONOS-7444] Optimize SONA gw doesn't use vrouter app and quagga anymore
- Done: Deriving MAC address from external peer router and simple SNAT functionality
- Todo: SNAT, Floating IP-based routing
Change-Id: Ib1a5784a7304c44b28d7b2c9891b98fd13000db1
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
index a07cdef..7beb11d 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
@@ -24,6 +24,7 @@
import org.onlab.packet.IPv4;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.TCP;
import org.onlab.packet.TpPort;
import org.onlab.packet.UDP;
@@ -183,19 +184,25 @@
IpAddress srcIp = IpAddress.valueOf(iPacket.getSourceAddress());
Subnet srcSubnet = getSourceSubnet(srcInstPort, srcIp);
IpAddress externalGatewayIp = getExternalIp(srcSubnet);
+
if (externalGatewayIp == null) {
return;
}
+ MacAddress externalPeerRouterMac = getExternalPeerRouterMac(srcSubnet);
+ if (externalPeerRouterMac == null) {
+ return;
+ }
+
populateSnatFlowRules(context.inPacket(),
srcInstPort,
TpPort.tpPort(patPort),
- externalGatewayIp);
+ externalGatewayIp, externalPeerRouterMac);
packetOut(eth.duplicate(),
packetIn.receivedFrom().deviceId(),
patPort,
- externalGatewayIp);
+ externalGatewayIp, externalPeerRouterMac);
}
private Subnet getSourceSubnet(InstancePort instance, IpAddress srcIp) {
@@ -209,6 +216,32 @@
return osNetworkService.subnet(fixedIp.getSubnetId());
}
+ private MacAddress getExternalPeerRouterMac(Subnet srcSubnet) {
+ RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
+ .filter(i -> Objects.equals(i.getSubnetId(), srcSubnet.getId()))
+ .findAny().orElse(null);
+ if (osRouterIface == null) {
+ // this subnet is not connected to the router
+ log.trace(ERR_PACKETIN + "source subnet(ID:{}, CIDR:{}) has no router",
+ srcSubnet.getId(), srcSubnet.getCidr());
+ return null;
+ }
+
+ Router osRouter = osRouterService.router(osRouterIface.getId());
+ if (osRouter == null) {
+ return null;
+ }
+ if (osRouter.getExternalGatewayInfo() == null) {
+ // this router does not have external connectivity
+ log.trace(ERR_PACKETIN + "router({}) has no external gateway",
+ osRouter.getName());
+ return null;
+ }
+
+ ExternalGateway exGatewayInfo = osRouter.getExternalGatewayInfo();
+
+ return osNetworkService.externalPeerRouterMac(exGatewayInfo);
+ }
private IpAddress getExternalIp(Subnet srcSubnet) {
RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
.filter(i -> Objects.equals(i.getSubnetId(), srcSubnet.getId()))
@@ -251,7 +284,7 @@
}
private void populateSnatFlowRules(InboundPacket packetIn, InstancePort srcInstPort,
- TpPort patPort, IpAddress externalIp) {
+ TpPort patPort, IpAddress externalIp, MacAddress externalPeerRouterMac) {
Network osNet = osNetworkService.network(srcInstPort.networkId());
if (osNet == null) {
final String error = String.format(ERR_PACKETIN + "network %s not found",
@@ -269,13 +302,15 @@
setUpstreamRules(osNet.getProviderSegID(),
osNet.getNetworkType(),
externalIp,
+ externalPeerRouterMac,
patPort,
packetIn);
}
private void setDownstreamRules(InstancePort srcInstPort, String segmentId,
NetworkType networkType,
- IpAddress externalIp, TpPort patPort,
+ IpAddress externalIp,
+ TpPort patPort,
InboundPacket packetIn) {
IPv4 iPacket = (IPv4) packetIn.parsed().getPayload();
IpAddress internalIp = IpAddress.valueOf(iPacket.getSourceAddress());
@@ -357,7 +392,8 @@
}
private void setUpstreamRules(String segmentId, NetworkType networkType,
- IpAddress externalIp, TpPort patPort,
+ IpAddress externalIp, MacAddress externalPeerRouterMac,
+ TpPort patPort,
InboundPacket packetIn) {
IPv4 iPacket = (IPv4) packetIn.parsed().getPayload();
@@ -389,14 +425,14 @@
sBuilder.matchTcpSrc(TpPort.tpPort(tcpPacket.getSourcePort()))
.matchTcpDst(TpPort.tpPort(tcpPacket.getDestinationPort()));
tBuilder.setTcpSrc(patPort)
- .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC);
+ .setEthDst(externalPeerRouterMac);
break;
case IPv4.PROTOCOL_UDP:
UDP udpPacket = (UDP) iPacket.getPayload();
sBuilder.matchUdpSrc(TpPort.tpPort(udpPacket.getSourcePort()))
.matchUdpDst(TpPort.tpPort(udpPacket.getDestinationPort()));
tBuilder.setUdpSrc(patPort)
- .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC);
+ .setEthDst(externalPeerRouterMac);
break;
default:
log.debug("Unsupported IPv4 protocol {}");
@@ -407,7 +443,7 @@
osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
TrafficTreatment.Builder tmpBuilder =
DefaultTrafficTreatment.builder(tBuilder.build());
- tmpBuilder.setOutput(gNode.patchPortNum());
+ tmpBuilder.setOutput(gNode.uplinkPortNum());
osFlowRuleService.setRule(
appId,
@@ -421,7 +457,7 @@
}
private void packetOut(Ethernet ethPacketIn, DeviceId srcDevice, int patPort,
- IpAddress externalIp) {
+ IpAddress externalIp, MacAddress externalPeerRouterMac) {
IPv4 iPacket = (IPv4) ethPacketIn.getPayload();
switch (iPacket.getProtocol()) {
case IPv4.PROTOCOL_TCP:
@@ -446,7 +482,7 @@
iPacket.setSourceAddress(externalIp.toString());
iPacket.resetChecksum();
iPacket.setParent(ethPacketIn);
- ethPacketIn.setDestinationMACAddress(DEFAULT_EXTERNAL_ROUTER_MAC);
+ ethPacketIn.setDestinationMACAddress(externalPeerRouterMac);
ethPacketIn.setPayload(iPacket);
ethPacketIn.resetChecksum();
@@ -458,7 +494,7 @@
}
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(srcNode.patchPortNum()).build();
+ .setOutput(srcNode.uplinkPortNum()).build();
packetService.emit(new DefaultOutboundPacket(
srcDevice,
treatment,