[ONOS-7951] Use Stateful SNAT to handle N-S traffic in openstack
Change-Id: Ife7284d2ebd3ade7ce968005a69dff98857a65f3
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 2fbc09a..212db1a 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
@@ -15,12 +15,14 @@
*/
package org.onosproject.openstacknetworking.impl;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.packet.Ethernet;
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;
@@ -89,6 +91,8 @@
import java.nio.ByteBuffer;
import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -97,7 +101,6 @@
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_EXTERNAL_ROUTER_MAC;
import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC;
import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
@@ -112,7 +115,9 @@
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.externalPeerRouterFromSubnet;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getExternalIp;
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;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
@@ -134,7 +139,7 @@
private static final String ERR_PACKET_IN = "Failed to handle packet in: ";
private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
private static final long TIME_OUT_SNAT_PORT_MS = 120L * 1000L;
- private static final int TP_PORT_MINIMUM_NUM = 30000;
+ private static final int TP_PORT_MINIMUM_NUM = 1025;
private static final int TP_PORT_MAXIMUM_NUM = 65535;
private static final int VM_PREFIX = 32;
@@ -211,18 +216,16 @@
allocatedPortNumMap = storageService.<Integer, Long>consistentMapBuilder()
.withSerializer(Serializer.using(NUMBER_SERIALIZER.build()))
- .withName("openstackrouting-allocatedportnummap")
+ .withName("openstackrouting-allocated-portnummap")
.withApplicationId(appId)
.build();
unUsedPortNumSet = storageService.<Integer>setBuilder()
- .withName("openstackrouting-unusedportnumset")
+ .withName("openstackrouting-unused-portnumset")
.withSerializer(Serializer.using(KryoNamespaces.API))
.build()
.asDistributedSet();
- initializeUnusedPortNumSet();
-
localNodeId = clusterService.getLocalNode().id();
leadershipService.runForLeadership(appId.name());
packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
@@ -232,6 +235,8 @@
osRouterService.addListener(osRouterListener);
osNodeService.addListener(osNodeListener);
+ eventExecutor.execute(this::initializeUnusedPortNumSet);
+
log.info("Started");
}
@@ -287,8 +292,8 @@
return;
}
- ExternalPeerRouter externalPeerRouter =
- externalPeerRouterFromSubnet(srcSubnet, osRouterService, osNetworkService);
+ ExternalPeerRouter externalPeerRouter = externalPeerRouterFromSubnet(
+ srcSubnet, osRouterService, osNetworkService);
if (externalPeerRouter == null) {
return;
}
@@ -325,11 +330,11 @@
if (osNet == null) {
final String error = String.format("%s network %s not found",
- ERR_PACKET_IN, srcInstPort.networkId());
+ ERR_PACKET_IN, srcInstPort.networkId());
throw new IllegalStateException(error);
}
- setDownstreamRules(srcInstPort,
+ setStatelessSnatDownstreamRules(srcInstPort,
osNet.getProviderSegID(),
netType,
externalIp,
@@ -337,7 +342,7 @@
patPort,
packetIn);
- setUpstreamRules(osNet.getProviderSegID(),
+ setStatelessSnatUpstreamRules(osNet.getProviderSegID(),
netType,
externalIp,
externalPeerRouter,
@@ -345,12 +350,13 @@
packetIn);
}
- private void setDownstreamRules(InstancePort srcInstPort, String segmentId,
- Type networkType,
- IpAddress externalIp,
- ExternalPeerRouter externalPeerRouter,
- TpPort patPort,
- InboundPacket packetIn) {
+ private void setStatelessSnatDownstreamRules(InstancePort srcInstPort,
+ String segmentId,
+ Type networkType,
+ IpAddress externalIp,
+ ExternalPeerRouter externalPeerRouter,
+ TpPort patPort,
+ InboundPacket packetIn) {
IPv4 iPacket = (IPv4) packetIn.parsed().getPayload();
IpAddress internalIp = IpAddress.valueOf(iPacket.getSourceAddress());
@@ -406,7 +412,7 @@
OpenstackNode srcNode = osNodeService.node(srcInstPort.deviceId());
osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
TrafficTreatment treatment =
- getDownStreamTreatment(networkType, tBuilder, gNode, srcNode);
+ getDownstreamTreatment(networkType, tBuilder, gNode, srcNode);
osFlowRuleService.setRule(
appId,
gNode.intgBridge(),
@@ -418,7 +424,7 @@
});
}
- private TrafficTreatment getDownStreamTreatment(Type networkType,
+ private TrafficTreatment getDownstreamTreatment(Type networkType,
TrafficTreatment.Builder tBuilder,
OpenstackNode gNode,
OpenstackNode srcNode) {
@@ -447,12 +453,12 @@
return tmpBuilder.build();
}
- private void setUpstreamRules(String segmentId,
- Type networkType,
- IpAddress externalIp,
- ExternalPeerRouter externalPeerRouter,
- TpPort patPort,
- InboundPacket packetIn) {
+ private void setStatelessSnatUpstreamRules(String segmentId,
+ Type networkType,
+ IpAddress externalIp,
+ ExternalPeerRouter externalPeerRouter,
+ TpPort patPort,
+ InboundPacket packetIn) {
IPv4 iPacket = (IPv4) packetIn.parsed().getPayload();
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
@@ -597,7 +603,8 @@
private void clearPortNumMap() {
allocatedPortNumMap.entrySet().forEach(e -> {
- if (System.currentTimeMillis() - e.getValue().value() > TIME_OUT_SNAT_PORT_MS) {
+ if (System.currentTimeMillis() -
+ e.getValue().value() > TIME_OUT_SNAT_PORT_MS) {
allocatedPortNumMap.remove(e.getKey());
unUsedPortNumSet.add(e.getKey());
}
@@ -637,8 +644,8 @@
IpPrefix srcSubnet,
Type networkType,
boolean install) {
- OpenstackNode sourceNatGateway =
- osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
+ OpenstackNode sourceNatGateway = osNodeService.completeNodes(GATEWAY)
+ .stream().findFirst().orElse(null);
if (sourceNatGateway == null) {
return;
@@ -704,7 +711,8 @@
ExternalPeerRouter externalPeerRouter =
osNetworkAdminService.externalPeerRouter(exGateway);
- VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.vlanId();
+ VlanId vlanId = externalPeerRouter == null ?
+ VlanId.NONE : externalPeerRouter.vlanId();
if (exGateway == null) {
deleteUnassociatedExternalPeerRouter();
@@ -794,36 +802,102 @@
log.error("Cannot find a router for router interface {} ", routerIface);
return;
}
- IpAddress natAddress = getGatewayIpAddress(osRouter.get());
+
+ IpAddress natAddress = getExternalIp(osRouter.get(), osNetworkService);
if (natAddress == null) {
return;
}
+
+ IpAddress extRouterAddress = getGatewayIpAddress(osRouter.get());
+ if (extRouterAddress == null) {
+ return;
+ }
+
+ ExternalPeerRouter externalPeerRouter =
+ osNetworkService.externalPeerRouter(extRouterAddress);
+ if (externalPeerRouter == null) {
+ return;
+ }
+
String netId = osNetworkAdminService.subnet(routerIface.getSubnetId()).getNetworkId();
+ Map<OpenstackNode, PortRange> gwPortRangeMap = getAssignedPortsForGateway(
+ ImmutableList.copyOf(osNodeService.completeNodes(GATEWAY)));
+
osNodeService.completeNodes(GATEWAY)
.forEach(gwNode -> {
instancePortService.instancePorts(netId)
.stream()
.filter(port -> port.state() == ACTIVE)
- .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
- Long.parseLong(osNet.getProviderSegID()),
- IpPrefix.valueOf(port.ipAddress(), VM_PREFIX),
- port.deviceId(),
- netType,
- install));
+ .forEach(port -> setGatewayToInstanceDownstreamRule(
+ gwNode, port, install));
- setOvsNatIngressRule(gwNode.intgBridge(),
- IpPrefix.valueOf(natAddress, VM_PREFIX),
- Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
+ setStatefulSnatDownstreamRule(gwNode.intgBridge(),
+ IpPrefix.valueOf(natAddress, VM_PREFIX), install);
- if (gwNode.patchPortNum() != null) {
- setOvsNatEgressRule(gwNode.intgBridge(),
- natAddress, Long.parseLong(osNet.getProviderSegID()),
- gwNode.patchPortNum(), install);
- }
+ PortRange gwPortRange = gwPortRangeMap.get(gwNode);
+
+ Map<String, PortRange> netPortRangeMap =
+ getAssignedPortsForNet(getNetIdByRouterId(routerIface.getId()),
+ gwPortRange.min(), gwPortRange.max());
+
+ PortRange netPortRange = netPortRangeMap.get(osNet.getId());
+
+ setStatefulSnatUpstreamRule(gwNode, natAddress,
+ Long.parseLong(osNet.getProviderSegID()),
+ externalPeerRouter, netPortRange.min(),
+ netPortRange.max(), install);
});
}
+ private List<String> getNetIdByRouterId(String routerId) {
+ return osRouterService.routerInterfaces(routerId)
+ .stream()
+ .filter(ri -> osRouterService.router(ri.getId())
+ .getExternalGatewayInfo().isEnableSnat())
+ .map(RouterInterface::getSubnetId)
+ .map(si -> osNetworkAdminService.subnet(si))
+ .map(Subnet::getNetworkId)
+ .collect(Collectors.toList());
+ }
+
+ private Map<OpenstackNode, PortRange>
+ getAssignedPortsForGateway(List<OpenstackNode> gateways) {
+
+ Map<OpenstackNode, PortRange> gwPortRangeMap = Maps.newConcurrentMap();
+
+ int portRangeNumPerGwNode =
+ (TP_PORT_MAXIMUM_NUM - TP_PORT_MINIMUM_NUM + 1) / gateways.size();
+
+ for (int i = 0; i < gateways.size(); i++) {
+ int gwPortRangeMin = TP_PORT_MINIMUM_NUM + i * portRangeNumPerGwNode;
+ int gwPortRangeMax = TP_PORT_MINIMUM_NUM + (i + 1) * portRangeNumPerGwNode - 1;
+
+ gwPortRangeMap.put(gateways.get(i),
+ new PortRange(gwPortRangeMin, gwPortRangeMax));
+ }
+
+ return gwPortRangeMap;
+ }
+
+ private Map<String, PortRange> getAssignedPortsForNet(List<String> netIds,
+ int min, int max) {
+
+ Map<String, PortRange> netPortRangeMap = Maps.newConcurrentMap();
+
+ int portRangeNumPerNet = (max - min + 1) / netIds.size();
+
+ for (int i = 0; i < netIds.size(); i++) {
+ int netPortRangeMin = min + i * portRangeNumPerNet;
+ int netPortRangeMax = min + (i + 1) * portRangeNumPerNet - 1;
+
+ netPortRangeMap.put(netIds.get(i),
+ new PortRange(netPortRangeMin, netPortRangeMax));
+ }
+
+ return netPortRangeMap;
+ }
+
private IpAddress getGatewayIpAddress(Router osRouter) {
if (osRouter.getExternalGatewayInfo() == null) {
@@ -836,7 +910,7 @@
.findAny();
if (!extSubnet.isPresent()) {
- log.error("Cannot find externel subnet for the router");
+ log.error("Cannot find external subnet for the router");
return null;
}
@@ -857,14 +931,55 @@
install));
}
- private void setOvsNatIngressRule(DeviceId deviceId,
- IpPrefix cidr,
- MacAddress dstMac,
- boolean install) {
+ private void setGatewayToInstanceDownstreamRule(OpenstackNode gwNode,
+ InstancePort instPort,
+ boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(cidr)
+ .matchIPDst(IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX))
+ .build();
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setEthDst(instPort.macAddress());
+
+ Type netType = osNetworkAdminService.networkType(instPort.networkId());
+ String segId = osNetworkAdminService.segmentId(instPort.networkId());
+
+ switch (netType) {
+ case VXLAN:
+ case GRE:
+ case GENEVE:
+ tBuilder.setTunnelId(Long.valueOf(segId));
+ break;
+ case VLAN:
+ default:
+ final String error = String.format("%s %s",
+ ERR_UNSUPPORTED_NET_TYPE, netType.name());
+ throw new IllegalStateException(error);
+ }
+
+ OpenstackNode srcNode = osNodeService.node(instPort.deviceId());
+ TrafficTreatment treatment =
+ getDownstreamTreatment(netType, tBuilder, gwNode, srcNode);
+
+ osFlowRuleService.setRule(
+ appId,
+ gwNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_STATEFUL_SNAT_RULE,
+ GW_COMMON_TABLE,
+ install);
+ }
+
+ private void setStatefulSnatDownstreamRule(DeviceId deviceId,
+ IpPrefix gatewayIp,
+ boolean install) {
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(gatewayIp)
.build();
ExtensionTreatment natTreatment = RulePopulatorUtil
@@ -875,7 +990,6 @@
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setEthDst(dstMac)
.extension(natTreatment, deviceId)
.build();
@@ -889,11 +1003,13 @@
install);
}
- private void setOvsNatEgressRule(DeviceId deviceId,
- IpAddress natAddress,
- long vni,
- PortNumber output,
- boolean install) {
+ private void setStatefulSnatUpstreamRule(OpenstackNode gwNode,
+ IpAddress gatewayIp,
+ long vni,
+ ExternalPeerRouter extPeerRouter,
+ int minPortNum,
+ int maxPortNum,
+ boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
@@ -902,22 +1018,25 @@
.build();
ExtensionTreatment natTreatment = RulePopulatorUtil
- .niciraConnTrackTreatmentBuilder(driverService, deviceId)
+ .niciraConnTrackTreatmentBuilder(driverService, gwNode.intgBridge())
.commit(true)
+ .natFlag(CT_NAT_SRC_FLAG)
.natAction(true)
- .natIp(natAddress)
+ .natIp(gatewayIp)
+ .natPortMin(TpPort.tpPort(minPortNum))
+ .natPortMax(TpPort.tpPort(maxPortNum))
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .extension(natTreatment, deviceId)
- .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
+ .extension(natTreatment, gwNode.intgBridge())
+ .setEthDst(extPeerRouter.macAddress())
.setEthSrc(DEFAULT_GATEWAY_MAC)
- .setOutput(output)
+ .setOutput(gwNode.uplinkPortNum())
.build();
osFlowRuleService.setRule(
appId,
- deviceId,
+ gwNode.intgBridge(),
selector,
treatment,
PRIORITY_STATEFUL_SNAT_RULE,
@@ -925,41 +1044,6 @@
install);
}
- private void setRulesForSnatIngressRule(DeviceId deviceId,
- Long vni,
- IpPrefix destVmIp,
- DeviceId dstDeviceId,
- Type networkType,
- boolean install) {
-
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(destVmIp)
- .build();
-
- PortNumber portNum = tunnelPortNumByNetType(networkType,
- osNodeService.node(deviceId));
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setTunnelId(vni)
- .extension(buildExtension(
- deviceService,
- deviceId,
- osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
- deviceId)
- .setOutput(portNum)
- .build();
-
- osFlowRuleService.setRule(
- appId,
- deviceId,
- selector,
- treatment,
- PRIORITY_EXTERNAL_ROUTING_RULE,
- Constants.GW_COMMON_TABLE,
- install);
- }
-
private void setRulesToController(DeviceId deviceId,
String segmentId,
IpPrefix srcSubnet,
@@ -1084,7 +1168,6 @@
}
private void instPortDetected(InstancePort instPort) {
- Network network = osNetworkAdminService.network(instPort.networkId());
Type netType = osNetworkAdminService.networkType(instPort.networkId());
if (netType == FLAT) {
@@ -1092,17 +1175,12 @@
}
if (useStatefulSnat) {
- osNodeService.completeNodes(GATEWAY)
- .forEach(gwNode -> setRulesForSnatIngressRule(
- gwNode.intgBridge(),
- Long.parseLong(network.getProviderSegID()),
- IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
- instPort.deviceId(), netType, true));
+ osNodeService.completeNodes(GATEWAY).forEach(gwNode ->
+ setGatewayToInstanceDownstreamRule(gwNode, instPort, true));
}
}
private void instPortRemoved(InstancePort instPort) {
- Network network = osNetworkAdminService.network(instPort.networkId());
Type netType = osNetworkAdminService.networkType(instPort.networkId());
if (netType == FLAT) {
@@ -1110,12 +1188,8 @@
}
if (useStatefulSnat) {
- osNodeService.completeNodes(GATEWAY)
- .forEach(gwNode -> setRulesForSnatIngressRule(
- gwNode.intgBridge(),
- Long.parseLong(network.getProviderSegID()),
- IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
- instPort.deviceId(), netType, false));
+ osNodeService.completeNodes(GATEWAY).forEach(gwNode ->
+ setGatewayToInstanceDownstreamRule(gwNode, instPort, false));
}
}
}
@@ -1259,15 +1333,14 @@
OpenstackNode osNode = event.subject();
switch (event.type()) {
case OPENSTACK_NODE_COMPLETE:
+ eventExecutor.execute(() -> processGatewayCompletion(osNode));
+ eventExecutor.execute(() -> reconfigureRouters(osNode));
+ break;
+ case OPENSTACK_NODE_REMOVED:
+ eventExecutor.execute(() -> processGatewayRemoval(osNode));
case OPENSTACK_NODE_INCOMPLETE:
case OPENSTACK_NODE_UPDATED:
- case OPENSTACK_NODE_REMOVED:
- eventExecutor.execute(() -> {
- if (!isRelevantHelper()) {
- return;
- }
- reconfigureRouters(osNode);
- });
+ eventExecutor.execute(() -> reconfigureRouters(osNode));
break;
case OPENSTACK_NODE_CREATED:
default:
@@ -1275,7 +1348,33 @@
}
}
+ private void processGatewayCompletion(OpenstackNode osNode) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ if (useStatefulSnat && osNode.type() == GATEWAY) {
+ instancePortService.instancePorts().forEach(instPort ->
+ setGatewayToInstanceDownstreamRule(osNode, instPort, true));
+ }
+ }
+
+ private void processGatewayRemoval(OpenstackNode osNode) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ if (useStatefulSnat && osNode.type() == GATEWAY) {
+ instancePortService.instancePorts().forEach(instPort ->
+ setGatewayToInstanceDownstreamRule(osNode, instPort, false));
+ }
+ }
+
private void reconfigureRouters(OpenstackNode osNode) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
osRouterService.routers().forEach(osRouter -> {
routerUpdated(osRouter);
osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
@@ -1285,4 +1384,64 @@
log.info("Reconfigure routers for {}", osNode.hostname());
}
}
+
+ private class PortRange {
+ private int min;
+ private int max;
+
+ /**
+ * A default constructor.
+ *
+ * @param min min port num
+ * @param max max port num
+ */
+ public PortRange(int min, int max) {
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ * Obtains min port num.
+ *
+ * @return min port num
+ */
+ int min() {
+ return min;
+ }
+
+ /**
+ * Obtains max port num.
+ *
+ * @return max port num
+ */
+ int max() {
+ return max;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("min", min)
+ .add("max", max)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ PortRange portRange = (PortRange) o;
+ return min == portRange.min &&
+ max == portRange.max;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(min, max);
+ }
+ }
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index e180d34..b94a2df 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -454,7 +454,7 @@
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
if (commit == CT_COMMIT || recircTable > 0) {
- RulePopulatorUtil.NiriraConnTrackTreatmentBuilder natTreatmentBuilder =
+ RulePopulatorUtil.NiciraConnTrackTreatmentBuilder natTreatmentBuilder =
niciraConnTrackTreatmentBuilder(driverService, deviceId);
natTreatmentBuilder.natAction(false);
if (commit == CT_COMMIT) {
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
index b5abaec..dace1ff 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
@@ -17,6 +17,7 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ExtensionSelectorResolver;
@@ -53,11 +54,22 @@
private static final String CT_PRESENT_FLAGS = "presentFlags";
private static final String CT_IPADDRESS_MIN = "ipAddressMin";
private static final String CT_IPADDRESS_MAX = "ipAddressMax";
+ private static final String CT_PORT_MIN = "portMin";
+ private static final String CT_PORT_MAX = "portMax";
+ private static final String CT_NESTED_ACTIONS = "nestedActions";
- private static final int ADDRESS_MIN_FLAG = 0;
- private static final int ADDRESS_MAX_FLAG = 1;
- private static final int PORT_MIN_FLAG = 2;
- private static final int PORT_MAX_FLAG = 3;
+ public static final int CT_NAT_SRC_FLAG = 0;
+ public static final int CT_NAT_DST_FLAG = 1;
+ public static final int CT_NAT_PERSISTENT_FLAG = 2;
+ public static final int CT_NAT_PROTO_HASH_FLAG = 3;
+ public static final int CT_NAT_PROTO_RANDOM_FLAG = 4;
+
+ private static final int ADDRESS_V4_MIN_FLAG = 0;
+ private static final int ADDRESS_V4_MAX_FLAG = 1;
+ private static final int ADDRESS_V6_MIN_FLAG = 2;
+ private static final int ADDRESS_V6_MAX_FLAG = 3;
+ private static final int PORT_MIN_FLAG = 4;
+ private static final int PORT_MAX_FLAG = 5;
// Refer to http://openvswitch.org/support/dist-docs/ovs-fields.7.txt for the values
public static final long CT_STATE_NONE = 0;
@@ -76,9 +88,9 @@
* @param id DeviceId
* @return a builder for OVS Connection Tracking feature actions
*/
- public static NiriraConnTrackTreatmentBuilder
+ public static NiciraConnTrackTreatmentBuilder
niciraConnTrackTreatmentBuilder(DriverService ds, DeviceId id) {
- return new NiriraConnTrackTreatmentBuilder(ds, id);
+ return new NiciraConnTrackTreatmentBuilder(ds, id);
}
/**
@@ -207,18 +219,21 @@
/**
* Builder class for OVS Connection Tracking feature actions.
*/
- public static final class NiriraConnTrackTreatmentBuilder {
+ public static final class NiciraConnTrackTreatmentBuilder {
private DriverService driverService;
private DeviceId deviceId;
private IpAddress natAddress = null;
+ private TpPort natPortMin = null;
+ private TpPort natPortMax = null;
private int zone;
private boolean commit;
private short table = -1;
private boolean natAction;
+ private int natFlag;
-
- private NiriraConnTrackTreatmentBuilder(DriverService driverService,
+ // private constructor
+ private NiciraConnTrackTreatmentBuilder(DriverService driverService,
DeviceId deviceId) {
this.driverService = driverService;
this.deviceId = deviceId;
@@ -230,7 +245,7 @@
* @param c true if commit, false if not.
* @return NiriraConnTrackTreatmentBuilder object
*/
- public NiriraConnTrackTreatmentBuilder commit(boolean c) {
+ public NiciraConnTrackTreatmentBuilder commit(boolean c) {
this.commit = c;
return this;
}
@@ -241,7 +256,7 @@
* @param z zone number
* @return NiriraConnTrackTreatmentBuilder object
*/
- public NiriraConnTrackTreatmentBuilder zone(int z) {
+ public NiciraConnTrackTreatmentBuilder zone(int z) {
this.zone = z;
return this;
}
@@ -252,7 +267,7 @@
* @param t table number to restart
* @return NiriraConnTrackTreatmentBuilder object
*/
- public NiriraConnTrackTreatmentBuilder table(short t) {
+ public NiciraConnTrackTreatmentBuilder table(short t) {
this.table = t;
return this;
}
@@ -263,18 +278,56 @@
* @param ip NAT IP address
* @return NiriraConnTrackTreatmentBuilder object
*/
- public NiriraConnTrackTreatmentBuilder natIp(IpAddress ip) {
+ public NiciraConnTrackTreatmentBuilder natIp(IpAddress ip) {
this.natAddress = ip;
return this;
}
/**
+ * Sets min port for NAT.
+ *
+ * @param port port number
+ * @return NiciraConnTrackTreatmentBuilder object
+ */
+ public NiciraConnTrackTreatmentBuilder natPortMin(TpPort port) {
+ this.natPortMin = port;
+ return this;
+ }
+
+ /**
+ * Sets max port for NAT.
+ *
+ * @param port port number
+ * @return NiciraConnTrackTreatmentBuilder object
+ */
+ public NiciraConnTrackTreatmentBuilder natPortMax(TpPort port) {
+ this.natPortMax = port;
+ return this;
+ }
+
+ /**
+ * Sets NAT flags.
+ * SRC NAT: 1 << 0
+ * DST NAT: 1 << 1
+ * PERSISTENT NAT: 1 << 2
+ * PROTO_HASH NAT: 1 << 3
+ * PROTO_RANDOM NAT : 1 << 4
+ *
+ * @param flag flag value
+ * @return NiciraConnTrackTreatmentBuilder object
+ */
+ public NiciraConnTrackTreatmentBuilder natFlag(int flag) {
+ this.natFlag = 1 << flag;
+ return this;
+ }
+
+ /**
* Sets the flag for NAT action.
*
* @param nat nat action is included if true, no nat action otherwise
* @return NiriraConnTrackTreatmentBuilder object
*/
- public NiriraConnTrackTreatmentBuilder natAction(boolean nat) {
+ public NiciraConnTrackTreatmentBuilder natAction(boolean nat) {
this.natAction = nat;
return this;
}
@@ -286,21 +339,37 @@
*/
public ExtensionTreatment build() {
DriverHandler handler = driverService.createHandler(deviceId);
- ExtensionTreatmentResolver etr = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatmentResolver etr =
+ handler.behaviour(ExtensionTreatmentResolver.class);
ExtensionTreatment natTreatment = etr.getExtensionInstruction(
ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type());
try {
- if (natAddress != null) {
- natTreatment.setPropertyValue(CT_FLAGS, 1);
- natTreatment.setPropertyValue(CT_PRESENT_FLAGS,
- buildPresentFlag(false, true));
- natTreatment.setPropertyValue(CT_IPADDRESS_MIN, natAddress);
- natTreatment.setPropertyValue(CT_IPADDRESS_MAX, natAddress);
- } else {
+
+ if (natAddress == null && natPortMin == null && natPortMax == null) {
natTreatment.setPropertyValue(CT_FLAGS, 0);
natTreatment.setPropertyValue(CT_PRESENT_FLAGS, 0);
+ } else {
+ natTreatment.setPropertyValue(CT_FLAGS, this.natFlag);
+
+ natTreatment.setPropertyValue(CT_PRESENT_FLAGS,
+ buildPresentFlag((natPortMin != null && natPortMax != null),
+ natAddress != null));
}
+
+ if (natAddress != null) {
+ natTreatment.setPropertyValue(CT_IPADDRESS_MIN, natAddress);
+ natTreatment.setPropertyValue(CT_IPADDRESS_MAX, natAddress);
+ }
+
+ if (natPortMin != null) {
+ natTreatment.setPropertyValue(CT_PORT_MIN, natPortMin.toInt());
+ }
+
+ if (natPortMax != null) {
+ natTreatment.setPropertyValue(CT_PORT_MAX, natPortMax.toInt());
+ }
+
} catch (Exception e) {
log.error("Failed to set NAT due to error : {}", e);
return null;
@@ -316,7 +385,7 @@
ctTreatment.setPropertyValue(CT_FLAGS, commit ? 1 : 0);
ctTreatment.setPropertyValue(CT_ZONE, zone);
ctTreatment.setPropertyValue(CT_TABLE, table > -1 ? table : 0xff);
- ctTreatment.setPropertyValue("nestedActions", nat);
+ ctTreatment.setPropertyValue(CT_NESTED_ACTIONS, nat);
} catch (Exception e) {
log.error("Failed to set CT due to error : {}", e);
return null;
@@ -330,11 +399,12 @@
int presentFlag = 0;
if (isPortPresent) {
- presentFlag = presentFlag | 1 << PORT_MIN_FLAG | 1 << PORT_MAX_FLAG;
+ presentFlag = 1 << PORT_MIN_FLAG | 1 << PORT_MAX_FLAG;
}
if (isAddressPresent) {
- presentFlag = 1 << ADDRESS_MIN_FLAG | 1 << ADDRESS_MAX_FLAG;
+ // TODO: need to support IPv6 address
+ presentFlag = presentFlag | 1 << ADDRESS_V4_MIN_FLAG | 1 << ADDRESS_V4_MAX_FLAG;
}
return presentFlag;