Consolidating null providers and making them fully configurable and integrated with the ConfigProvider to allow arbitrary topologies.
Change-Id: I899e27a9771af4013a3ce6da7f683a4927ffb438
diff --git a/providers/null/src/main/java/org/onosproject/provider/nil/NullPacketProvider.java b/providers/null/src/main/java/org/onosproject/provider/nil/NullPacketProvider.java
new file mode 100644
index 0000000..a1baec9
--- /dev/null
+++ b/providers/null/src/main/java/org/onosproject/provider/nil/NullPacketProvider.java
@@ -0,0 +1,169 @@
+/*
+ * 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 org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.TimerTask;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP;
+import org.onlab.util.Timer;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceAdminService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.packet.DefaultInboundPacket;
+import org.onosproject.net.packet.DefaultPacketContext;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketProvider;
+import org.onosproject.net.packet.PacketProviderService;
+import org.slf4j.Logger;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import static com.google.common.collect.ImmutableList.copyOf;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.onosproject.net.MastershipRole.MASTER;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provider which generates simulated packets and acts as a sink for outbound
+ * packets. To be used for benchmarking only.
+ */
+class NullPacketProvider extends NullProviders.AbstractNullProvider
+ implements PacketProvider {
+
+ private static final int INITIAL_DELAY = 5;
+ private final Logger log = getLogger(getClass());
+
+ // Arbitrary host src/dst
+ private static final int SRC_HOST = 2;
+ private static final int DST_HOST = 5;
+
+ // Time between event firing, in milliseconds
+ private int delay;
+
+ // TODO: use host service to pick legitimate hosts connected to devices
+ private HostService hostService;
+ private PacketProviderService providerService;
+
+ private List<Device> devices;
+ private int currentDevice = 0;
+
+ private HashedWheelTimer timer = Timer.getTimer();
+ private Timeout timeout;
+
+ /**
+ * Starts the packet generation process.
+ *
+ * @param packetRate packets per second
+ * @param hostService host service
+ * @param deviceService device service
+ * @param providerService packet provider service
+ */
+ void start(int packetRate, HostService hostService,
+ DeviceAdminService deviceService,
+ PacketProviderService providerService) {
+ this.hostService = hostService;
+ this.providerService = providerService;
+
+ this.devices = copyOf(deviceService.getDevices()).stream()
+ .filter(d -> deviceService.getRole(d.id()) == MASTER)
+ .collect(Collectors.toList());
+
+ adjustRate(packetRate);
+ timeout = timer.newTimeout(new PacketDriverTask(), INITIAL_DELAY, SECONDS);
+ }
+
+ /**
+ * Adjusts packet rate.
+ *
+ * @param packetRate new packet rate
+ */
+ void adjustRate(int packetRate) {
+ delay = 1000 / packetRate;
+ log.info("Settings: packetRate={}, delay={}", packetRate, delay);
+ }
+
+ /**
+ * Stops the packet generation process.
+ */
+ void stop() {
+ if (timeout != null) {
+ timeout.cancel();
+ }
+ }
+
+ @Override
+ public void emit(OutboundPacket packet) {
+ // We don't have a network to emit to. Keep a counter here, maybe?
+ }
+
+ /**
+ * Generates packet events at a given rate.
+ */
+ private class PacketDriverTask implements TimerTask {
+
+ // Filler echo request
+ ICMP icmp;
+ Ethernet eth;
+
+ public PacketDriverTask() {
+ icmp = new ICMP();
+ icmp.setIcmpType((byte) 8).setIcmpCode((byte) 0).setChecksum((short) 0);
+ eth = new Ethernet();
+ eth.setEtherType(Ethernet.TYPE_IPV4);
+ eth.setPayload(icmp);
+ }
+
+ @Override
+ public void run(Timeout to) {
+ if (!devices.isEmpty()) {
+ sendEvent(devices.get(currentDevice));
+ currentDevice = (currentDevice + 1) % devices.size();
+ timeout = timer.newTimeout(to.getTask(), delay, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ private void sendEvent(Device device) {
+ // Make it look like things came from ports attached to hosts
+ eth.setSourceMACAddress("00:00:10:00:00:0" + SRC_HOST)
+ .setDestinationMACAddress("00:00:10:00:00:0" + DST_HOST);
+ InboundPacket inPkt = new DefaultInboundPacket(
+ new ConnectPoint(device.id(), PortNumber.portNumber(SRC_HOST)),
+ eth, ByteBuffer.wrap(eth.serialize()));
+ providerService.processPacket(new NullPacketContext(inPkt, null));
+ }
+ }
+
+ // Minimal PacketContext to make core and applications happy.
+ private final class NullPacketContext extends DefaultPacketContext {
+ private NullPacketContext(InboundPacket inPkt, OutboundPacket outPkt) {
+ super(System.currentTimeMillis(), inPkt, outPkt, false);
+ }
+
+ @Override
+ public void send() {
+ // We don't send anything out.
+ }
+ }
+
+}