aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/TopologySimulator.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/TopologySimulator.java')
-rw-r--r--framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/TopologySimulator.java382
1 files changed, 382 insertions, 0 deletions
diff --git a/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/TopologySimulator.java b/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/TopologySimulator.java
new file mode 100644
index 00000000..9f2320ed
--- /dev/null
+++ b/framework/src/onos/providers/null/src/main/java/org/onosproject/provider/nil/TopologySimulator.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.nil;
+
+import com.google.common.collect.Lists;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.ChassisId;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Link;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.DeviceAdminService;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.host.DefaultHostDescription;
+import org.onosproject.net.host.HostDescription;
+import org.onosproject.net.host.HostProviderService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.link.DefaultLinkDescription;
+import org.onosproject.net.link.LinkProviderService;
+import org.onosproject.net.link.LinkService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.onlab.util.Tools.toHex;
+import static org.onosproject.net.HostId.hostId;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.PortNumber.portNumber;
+import static org.onosproject.net.device.DeviceEvent.Type.*;
+import static org.onosproject.provider.nil.NullProviders.SCHEME;
+
+/**
+ * Abstraction of a provider capable to simulate some network topology.
+ */
+public abstract class TopologySimulator {
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ protected String[] topoShape;
+ protected int deviceCount;
+ protected int hostCount;
+
+ protected ServiceDirectory directory;
+ protected NodeId localNode;
+
+ protected ClusterService clusterService;
+ protected MastershipService mastershipService;
+
+ protected DeviceAdminService deviceService;
+ protected HostService hostService;
+ protected LinkService linkService;
+
+ protected DeviceProviderService deviceProviderService;
+ protected HostProviderService hostProviderService;
+ protected LinkProviderService linkProviderService;
+
+ protected int maxWaitSeconds = 1;
+ protected int infrastructurePorts = 2;
+ protected CountDownLatch deviceLatch;
+
+ protected final List<DeviceId> deviceIds = Lists.newArrayList();
+
+ private DeviceListener deviceEventCounter = new DeviceEventCounter();
+
+ /**
+ * Initializes a new topology simulator with access to the specified service
+ * directory and various provider services.
+ *
+ * @param topoShape topology shape specifier
+ * @param deviceCount number of devices in the topology
+ * @param hostCount number of hosts per device
+ * @param directory service directory
+ * @param deviceProviderService device provider service
+ * @param hostProviderService host provider service
+ * @param linkProviderService link provider service
+ */
+ protected void init(String topoShape, int deviceCount, int hostCount,
+ ServiceDirectory directory,
+ DeviceProviderService deviceProviderService,
+ HostProviderService hostProviderService,
+ LinkProviderService linkProviderService) {
+ this.deviceCount = deviceCount;
+ this.hostCount = hostCount;
+ this.directory = directory;
+
+ this.clusterService = directory.get(ClusterService.class);
+ this.mastershipService = directory.get(MastershipService.class);
+
+ this.deviceService = directory.get(DeviceAdminService.class);
+ this.hostService = directory.get(HostService.class);
+ this.linkService = directory.get(LinkService.class);
+ this.deviceProviderService = deviceProviderService;
+ this.hostProviderService = hostProviderService;
+ this.linkProviderService = linkProviderService;
+
+ localNode = clusterService.getLocalNode().id();
+
+ processTopoShape(topoShape);
+ }
+
+ /**
+ * Processes the topology shape specifier.
+ *
+ * @param shape topology shape specifier
+ */
+ protected void processTopoShape(String shape) {
+ this.topoShape = shape.split(",");
+ }
+
+ /**
+ * Sets up network topology simulation.
+ */
+ public void setUpTopology() {
+ prepareForDeviceEvents(deviceCount);
+ createDevices();
+ waitForDeviceEvents();
+
+ createLinks();
+ createHosts();
+ }
+
+ /**
+ * Creates simulated devices.
+ */
+ protected void createDevices() {
+ for (int i = 0; i < deviceCount; i++) {
+ createDevice(i + 1);
+ }
+ }
+
+ /**
+ * Creates simulated links.
+ */
+ protected abstract void createLinks();
+
+ /**
+ * Creates simulated hosts.
+ */
+ protected abstract void createHosts();
+
+ /**
+ * Creates simulated device.
+ *
+ * @param i index of the device id in the list.
+ */
+ protected void createDevice(int i) {
+ DeviceId id = DeviceId.deviceId(SCHEME + ":" + toHex(i));
+ DeviceDescription desc =
+ new DefaultDeviceDescription(id.uri(), Device.Type.SWITCH,
+ "ON.Lab", "0.1", "0.1", "1234",
+ new ChassisId(i));
+ deviceIds.add(id);
+ deviceProviderService.deviceConnected(id, desc);
+ deviceProviderService.updatePorts(id, buildPorts(hostCount + infrastructurePorts));
+ }
+
+// /**
+// * Creates simulated link between two devices on port 1 and port 2.
+// *
+// * @param i index of one simulated device
+// * @param j index of another simulated device
+// */
+// protected void createLink(int i, int j) {
+// createLink(i, j, 1, 2);
+// }
+
+ /**
+ * Creates simulated link between two devices.
+ *
+ * @param i index of one simulated device
+ * @param j index of another simulated device
+ * @param pi port number of i-th device
+ * @param pj port number of j-th device
+ */
+ protected void createLink(int i, int j, int pi, int pj) {
+ ConnectPoint one = new ConnectPoint(deviceIds.get(i), PortNumber.portNumber(pi));
+ ConnectPoint two = new ConnectPoint(deviceIds.get(j), PortNumber.portNumber(pj));
+ linkProviderService.linkDetected(new DefaultLinkDescription(one, two, DIRECT));
+ linkProviderService.linkDetected(new DefaultLinkDescription(two, one, DIRECT));
+ }
+
+ /**
+ * Creates simularted hosts for the specified device.
+ *
+ * @param deviceId device identifier
+ * @param portOffset port offset where to start attaching hosts
+ */
+ protected void createHosts(DeviceId deviceId, int portOffset) {
+ String s = deviceId.toString();
+ byte dByte = Byte.parseByte(s.substring(s.length() - 1), 16);
+ // TODO: this limits the simulation to 256 devices & 256 hosts/device.
+ byte[] macBytes = new byte[]{0, 0, 0, 0, dByte, 0};
+ byte[] ipBytes = new byte[]{(byte) 192, (byte) 168, dByte, 0};
+
+ for (int i = 0; i < hostCount; i++) {
+ int port = portOffset + i + 1;
+ macBytes[5] = (byte) (i + 1);
+ ipBytes[3] = (byte) (i + 1);
+ HostId id = hostId(MacAddress.valueOf(macBytes), VlanId.NONE);
+ IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, ipBytes);
+ hostProviderService.hostDetected(id, description(id, ip, deviceId, port));
+ }
+ }
+
+ /**
+ * Prepares to count device added/available/removed events.
+ *
+ * @param count number of events to count
+ */
+ protected void prepareForDeviceEvents(int count) {
+ deviceLatch = new CountDownLatch(count);
+ deviceService.addListener(deviceEventCounter);
+ }
+
+ /**
+ * Waits for all expected device added/available/removed events.
+ */
+ protected void waitForDeviceEvents() {
+ try {
+ deviceLatch.await(maxWaitSeconds, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ log.warn("Device events did not arrive in time");
+ }
+ deviceService.removeListener(deviceEventCounter);
+ }
+
+
+ /**
+ * Tears down network topology simulation.
+ */
+ public void tearDownTopology() {
+ removeHosts();
+ removeLinks();
+ removeDevices();
+ }
+
+ /**
+ * Removes any hosts previously advertised by this provider.
+ */
+ protected void removeHosts() {
+ hostService.getHosts()
+ .forEach(host -> hostProviderService.hostVanished(host.id()));
+ }
+
+ /**
+ * Removes any links previously advertised by this provider.
+ */
+ protected void removeLinks() {
+ linkService.getLinks()
+ .forEach(link -> linkProviderService.linkVanished(description(link)));
+ }
+
+ /**
+ * Removes any devices previously advertised by this provider.
+ */
+ protected void removeDevices() {
+ prepareForDeviceEvents(deviceIds.size());
+ deviceIds.forEach(deviceProviderService::deviceDisconnected);
+ waitForDeviceEvents();
+ deviceIds.clear();
+ }
+
+
+ /**
+ * Produces a device description from the given device.
+ *
+ * @param device device to copy
+ * @return device description
+ */
+ static DeviceDescription description(Device device) {
+ return new DefaultDeviceDescription(device.id().uri(), device.type(),
+ device.manufacturer(),
+ device.hwVersion(), device.swVersion(),
+ device.serialNumber(), device.chassisId());
+ }
+
+ /**
+ * Produces a link description from the given link.
+ *
+ * @param link link to copy
+ * @return link description
+ */
+ static DefaultLinkDescription description(Link link) {
+ return new DefaultLinkDescription(link.src(), link.dst(), link.type());
+ }
+
+ /**
+ * Produces a host description from the given host.
+ *
+ * @param host host to copy
+ * @return host description
+ */
+ static DefaultHostDescription description(Host host) {
+ return new DefaultHostDescription(host.mac(), host.vlan(), host.location(),
+ host.ipAddresses());
+ }
+
+ /**
+ * Generates a host description from the given id and location information.
+ *
+ * @param hostId host identifier
+ * @param ip host IP
+ * @param deviceId edge device
+ * @param port edge port
+ * @return host description
+ */
+ static HostDescription description(HostId hostId, IpAddress ip,
+ DeviceId deviceId, int port) {
+ HostLocation location = new HostLocation(deviceId, portNumber(port), 0L);
+ return new DefaultHostDescription(hostId.mac(), hostId.vlanId(), location, ip);
+ }
+
+ /**
+ * Generates a list of a configured number of ports.
+ *
+ * @param portCount number of ports
+ * @return list of ports
+ */
+ protected List<PortDescription> buildPorts(int portCount) {
+ List<PortDescription> ports = Lists.newArrayList();
+ for (int i = 0; i < portCount; i++) {
+ ports.add(new DefaultPortDescription(PortNumber.portNumber(i), true,
+ Port.Type.COPPER, 0));
+ }
+ return ports;
+ }
+
+ /**
+ * Indicates whether or not the simulation knows of this device.
+ *
+ * @param deviceId device identifier
+ * @return true if device is known
+ */
+ public boolean contains(DeviceId deviceId) {
+ return deviceIds.contains(deviceId);
+ }
+
+ // Counts down number of device added/available/removed events.
+ private class DeviceEventCounter implements DeviceListener {
+ @Override
+ public void event(DeviceEvent event) {
+ DeviceEvent.Type type = event.type();
+ if (type == DEVICE_ADDED || type == DEVICE_REMOVED ||
+ type == DEVICE_AVAILABILITY_CHANGED) {
+ deviceLatch.countDown();
+ }
+ }
+ }
+} \ No newline at end of file