[ONOS-6168, ONOS-6436] Implement multiple gateway nodes support for VLAN mode and implement VLAN based Logical Routing
Change-Id: Ifd1c26375abdf84603f28184e9cb9ad6c88648dd
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java
index b4074f7..8bb75a1 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/Constants.java
@@ -26,6 +26,7 @@
public static final String INTEGRATION_BRIDGE = "br-int";
public static final String ROUTER_BRIDGE = "br-router";
public static final String DEFAULT_TUNNEL = "vxlan";
+ public static final String VLAN = "vlan";
public static final String PATCH_INTG_BRIDGE = "patch-intg";
public static final String PATCH_ROUT_BRIDGE = "patch-rout";
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
index 4f3e5e7..bea3a41 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
@@ -297,7 +297,7 @@
process(new OpenstackNodeEvent(COMPLETE, node));
switch (node.type()) {
case COMPUTE:
- selectGroupHandler.createGatewayGroup(node.intBridge(), gatewayNodes());
+ selectGroupHandler.createGatewayGroup(node, gatewayNodes());
break;
case GATEWAY:
updateGatewayGroup(node, true);
@@ -386,12 +386,15 @@
}
@Override
- public synchronized GroupId gatewayGroupId(DeviceId srcDeviceId) {
- GroupKey groupKey = selectGroupHandler.getGroupKey(srcDeviceId);
+ public synchronized GroupId gatewayGroupId(DeviceId srcDeviceId, NetworkMode networkMode) {
+ GroupKey groupKey = selectGroupHandler.groupKey(srcDeviceId, networkMode);
Group group = groupService.getGroup(srcDeviceId, groupKey);
+
if (group == null) {
log.info("Created gateway group for {}", srcDeviceId);
- return selectGroupHandler.createGatewayGroup(srcDeviceId, gatewayNodes());
+ selectGroupHandler.createGatewayGroup(nodeByDeviceId(srcDeviceId), gatewayNodes());
+
+ return groupService.getGroup(srcDeviceId, selectGroupHandler.groupKey(srcDeviceId, networkMode)).id();
} else {
return group.id();
}
@@ -425,13 +428,26 @@
.stream()
.map(Versioned::value)
.filter(node -> node.type().equals(NodeType.COMPUTE))
+ .filter(node -> node.dataIp().isPresent())
.filter(node -> node.state().equals(COMPLETE))
- .forEach(node -> {
- selectGroupHandler.updateGatewayGroupBuckets(node.intBridge(),
- ImmutableList.of(gatewayNode),
- isInsert);
- log.trace("Updated gateway group on {}", node.intBridge());
+ .forEach(computeNode -> {
+ selectGroupHandler.updateGatewayGroupBuckets(computeNode,
+ ImmutableList.of(gatewayNode), NetworkMode.VXLAN, isInsert);
+ log.trace("Updated gateway group on {} for vxlan mode", computeNode.intBridge());
});
+
+ nodeStore.values()
+ .stream()
+ .map(Versioned::value)
+ .filter(node -> node.type().equals(NodeType.COMPUTE))
+ .filter(node -> node.vlanPort().isPresent())
+ .filter(node -> node.state().equals(COMPLETE))
+ .forEach(computeNode -> {
+ selectGroupHandler.updateGatewayGroupBuckets(computeNode,
+ ImmutableList.of(gatewayNode), NetworkMode.VLAN, isInsert);
+ log.trace("Updated gateway group on {} for vlan mode", computeNode.intBridge());
+ });
+
}
private void initNode(OpenstackNode node) {
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeService.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeService.java
index 7362893..9600280 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeService.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeService.java
@@ -39,6 +39,14 @@
GATEWAY
}
+ enum NetworkMode {
+ /**
+ * VxLAN or VLAN mode.
+ */
+ VXLAN,
+ VLAN
+ }
+
/**
* Adds or updates a new node to the service.
*
@@ -150,9 +158,10 @@
* If the group does not exist in the supplied source device, creates one.
*
* @param srcDeviceId source device id
- * @return The group id
+ * @param networkMode network mode
+ * @return group id
*/
- GroupId gatewayGroupId(DeviceId srcDeviceId);
+ GroupId gatewayGroupId(DeviceId srcDeviceId, NetworkMode networkMode);
/**
* Returns the list of gateway node information with the given device identifier.
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/SelectGroupHandler.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/SelectGroupHandler.java
index df963db..5f8e065 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/SelectGroupHandler.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/SelectGroupHandler.java
@@ -18,8 +18,10 @@
import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.GroupId;
+import org.onosproject.openstacknode.OpenstackNodeService.NetworkMode;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
@@ -47,7 +49,9 @@
import java.util.List;
+import static org.onosproject.net.AnnotationKeys.PORT_MAC;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknode.Constants.*;
import static org.onosproject.net.group.DefaultGroupBucket.createSelectGroupBucket;
/**
@@ -57,7 +61,7 @@
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String TUNNEL_DESTINATION = "tunnelDst";
- private static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
+ private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
private final GroupService groupService;
private final DeviceService deviceService;
@@ -83,81 +87,139 @@
/**
* Creates select type group description according to given deviceId.
*
- * @param srcDeviceId target device id for group description
+ * @param computeNode target device id for group description
* @param gatewayNodeList gateway node list for bucket action
- * @return created select type group description
*/
- public GroupId createGatewayGroup(DeviceId srcDeviceId, List<OpenstackNode> gatewayNodeList) {
- List<GroupBucket> bucketList = generateBucketsForSelectGroup(srcDeviceId, gatewayNodeList);
- GroupId groupId = getGroupId(srcDeviceId);
- GroupDescription groupDescription = new DefaultGroupDescription(
- srcDeviceId,
- GroupDescription.Type.SELECT,
- new GroupBuckets(bucketList),
- getGroupKey(srcDeviceId),
- groupId.id(),
- appId);
+ public void createGatewayGroup(OpenstackNode computeNode, List<OpenstackNode> gatewayNodeList) {
+ List<GroupBucket> bucketList;
+ GroupId groupId;
- groupService.addGroup(groupDescription);
- return groupId;
+ if (computeNode.dataIp().isPresent()) {
+ bucketList = generateBucketsForSelectGroup(computeNode, gatewayNodeList, NetworkMode.VXLAN);
+ groupId = groupId(computeNode.intBridge(), NetworkMode.VXLAN);
+
+ GroupDescription groupDescription = new DefaultGroupDescription(
+ computeNode.intBridge(),
+ GroupDescription.Type.SELECT,
+ new GroupBuckets(bucketList),
+ groupKey(computeNode.intBridge(), NetworkMode.VXLAN),
+ groupId.id(),
+ appId);
+
+ groupService.addGroup(groupDescription);
+ }
+
+ if (computeNode.vlanPort().isPresent()) {
+ bucketList = generateBucketsForSelectGroup(computeNode, gatewayNodeList, NetworkMode.VLAN);
+ groupId = groupId(computeNode.intBridge(), NetworkMode.VLAN);
+
+ GroupDescription groupDescription = new DefaultGroupDescription(
+ computeNode.intBridge(),
+ GroupDescription.Type.SELECT,
+ new GroupBuckets(bucketList),
+ groupKey(computeNode.intBridge(), NetworkMode.VLAN),
+ groupId.id(),
+ appId);
+
+ groupService.addGroup(groupDescription);
+ }
}
/**
- * Returns unique group key with supplied source device ID as a hash.
- *
+ * Returns unique group key with supplied source device ID and network mode as a hash.
* @param srcDeviceId source device id
+ * @param networkMode network mode
* @return group key
*/
- public GroupKey getGroupKey(DeviceId srcDeviceId) {
- return new DefaultGroupKey(srcDeviceId.toString().getBytes());
+ public GroupKey groupKey(DeviceId srcDeviceId, NetworkMode networkMode) {
+ if (networkMode.equals(NetworkMode.VXLAN)) {
+ return new DefaultGroupKey(srcDeviceId.toString().concat(DEFAULT_TUNNEL).getBytes());
+ } else {
+ return new DefaultGroupKey(srcDeviceId.toString().concat(VLAN).getBytes());
+ }
}
- private GroupId getGroupId(DeviceId srcDeviceId) {
- return new GroupId(srcDeviceId.toString().hashCode());
+ private GroupId groupId(DeviceId srcDeviceId, NetworkMode networkMode) {
+ if (networkMode.equals(NetworkMode.VXLAN)) {
+ return new GroupId(srcDeviceId.toString().concat(DEFAULT_TUNNEL).hashCode());
+ } else {
+ return new GroupId(srcDeviceId.toString().concat(VLAN).hashCode());
+ }
}
+
/**
* Updates groupBuckets in select type group.
*
- * @param deviceId target device id to update the group
+ * @param computeNode compute node
* @param gatewayNodeList updated gateway node list for bucket action
+ * @param networkMode network mode
* @param isInsert update type(add or remove)
*/
- public void updateGatewayGroupBuckets(DeviceId deviceId,
+ public void updateGatewayGroupBuckets(OpenstackNode computeNode,
List<OpenstackNode> gatewayNodeList,
+ NetworkMode networkMode,
boolean isInsert) {
- List<GroupBucket> bucketList = generateBucketsForSelectGroup(deviceId, gatewayNodeList);
- GroupKey groupKey = getGroupKey(deviceId);
- if (groupService.getGroup(deviceId, groupKey) == null) {
- log.error("There's no group in compute node {}", deviceId);
+ List<GroupBucket> bucketList = generateBucketsForSelectGroup(computeNode, gatewayNodeList, networkMode);
+ GroupKey groupKey = groupKey(computeNode.intBridge(), networkMode);
+ if (groupService.getGroup(computeNode.intBridge(), groupKey) == null) {
+ log.error("There's no group in compute node {}", computeNode.intBridge());
return;
}
if (isInsert) {
groupService.addBucketsToGroup(
- deviceId,
+ computeNode.intBridge(),
groupKey,
new GroupBuckets(bucketList),
groupKey, appId);
} else {
groupService.removeBucketsFromGroup(
- deviceId,
+ computeNode.intBridge(),
groupKey,
new GroupBuckets(bucketList),
groupKey, appId);
}
}
- private List<GroupBucket> generateBucketsForSelectGroup(DeviceId deviceId, List<OpenstackNode> gatewayNodeList) {
+
+
+ private List<GroupBucket> generateBucketsForSelectGroup(OpenstackNode computeNode,
+ List<OpenstackNode> gatewayNodeList,
+ NetworkMode networkMode) {
List<GroupBucket> bucketList = Lists.newArrayList();
- gatewayNodeList.forEach(node -> {
- TrafficTreatment tBuilder = DefaultTrafficTreatment.builder()
- .extension(buildNiciraExtenstion(deviceId, node.dataIp().get().getIp4Address()), deviceId)
- .setOutput(getTunnelPort(deviceId))
- .build();
- bucketList.add(createSelectGroupBucket(tBuilder));
- });
- return bucketList;
+
+ switch (networkMode) {
+ case VXLAN:
+ gatewayNodeList.stream()
+ .filter(node -> node.dataIp().isPresent())
+ .forEach(node -> {
+ TrafficTreatment tBuilder = DefaultTrafficTreatment.builder()
+ .extension(buildNiciraExtenstion(computeNode.intBridge(),
+ node.dataIp().get().getIp4Address()),
+ computeNode.intBridge())
+ .setOutput(getTunnelPort(computeNode.intBridge()))
+ .build();
+ bucketList.add(createSelectGroupBucket(tBuilder));
+ });
+ return bucketList;
+ case VLAN:
+ gatewayNodeList.stream()
+ .filter(node -> node.vlanPort().isPresent())
+ .forEach(node -> {
+ TrafficTreatment tBuilder = DefaultTrafficTreatment.builder()
+ .setEthDst(MacAddress.valueOf(vlanPortMac(node)))
+ .setOutput(vlanPortNum(computeNode))
+ .build();
+ bucketList.add(createSelectGroupBucket(tBuilder));
+ });
+ return bucketList;
+ default:
+ final String error = String.format(
+ ERR_UNSUPPORTED_NET_TYPE + "%s",
+ networkMode.toString());
+ throw new IllegalStateException(error);
+ }
}
/**
@@ -193,7 +255,7 @@
*/
private PortNumber getTunnelPort(DeviceId deviceId) {
Port port = deviceService.getPorts(deviceId).stream()
- .filter(p -> p.annotations().value(PORT_NAME).equals(PORTNAME_PREFIX_TUNNEL))
+ .filter(p -> p.annotations().value(PORT_NAME).equals(DEFAULT_TUNNEL))
.findAny().orElse(null);
if (port == null) {
@@ -201,6 +263,18 @@
return null;
}
return port.number();
+ }
+ private PortNumber vlanPortNum(OpenstackNode node) {
+ return deviceService.getPorts(node.intBridge()).stream()
+ .filter(p -> p.annotations().value(PORT_NAME).equals(node.vlanPort().get()) &&
+ p.isEnabled())
+ .map(Port::number).findFirst().get();
+
+ }
+ private String vlanPortMac(OpenstackNode node) {
+ return deviceService.getPorts(node.intBridge()).stream()
+ .filter(p -> p.annotations().value(PORT_NAME).equals(node.vlanPort().get()) && p.isEnabled())
+ .findFirst().get().annotations().value(PORT_MAC);
}
}