diff options
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.java | 382 |
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 |