blob: 54b45e43b15c62ad6ca174565ed9e48eb582556e [file] [log] [blame]
Thomas Vachuskac40d4632015-04-09 16:55:03 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuskac40d4632015-04-09 16:55:03 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.provider.nil;
17
18import org.jboss.netty.util.HashedWheelTimer;
19import org.jboss.netty.util.Timeout;
20import org.jboss.netty.util.TimerTask;
21import org.onlab.packet.Ethernet;
22import org.onlab.packet.ICMP;
23import org.onlab.util.Timer;
24import org.onosproject.net.ConnectPoint;
25import org.onosproject.net.Device;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.device.DeviceAdminService;
28import org.onosproject.net.host.HostService;
29import org.onosproject.net.packet.DefaultInboundPacket;
30import org.onosproject.net.packet.DefaultPacketContext;
31import org.onosproject.net.packet.InboundPacket;
32import org.onosproject.net.packet.OutboundPacket;
33import org.onosproject.net.packet.PacketProvider;
34import org.onosproject.net.packet.PacketProviderService;
35import org.slf4j.Logger;
36
37import java.nio.ByteBuffer;
38import java.util.List;
39import java.util.concurrent.TimeUnit;
40import java.util.stream.Collectors;
41
42import static com.google.common.collect.ImmutableList.copyOf;
Thomas Vachuskac3cdf902016-04-13 13:44:09 -070043import static java.util.concurrent.TimeUnit.MILLISECONDS;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070044import static java.util.concurrent.TimeUnit.SECONDS;
45import static org.onosproject.net.MastershipRole.MASTER;
46import static org.slf4j.LoggerFactory.getLogger;
47
48/**
49 * Provider which generates simulated packets and acts as a sink for outbound
50 * packets. To be used for benchmarking only.
51 */
52class NullPacketProvider extends NullProviders.AbstractNullProvider
53 implements PacketProvider {
54
55 private static final int INITIAL_DELAY = 5;
56 private final Logger log = getLogger(getClass());
57
58 // Arbitrary host src/dst
59 private static final int SRC_HOST = 2;
60 private static final int DST_HOST = 5;
61
62 // Time between event firing, in milliseconds
63 private int delay;
64
65 // TODO: use host service to pick legitimate hosts connected to devices
66 private HostService hostService;
67 private PacketProviderService providerService;
68
69 private List<Device> devices;
70 private int currentDevice = 0;
71
72 private HashedWheelTimer timer = Timer.getTimer();
73 private Timeout timeout;
74
75 /**
76 * Starts the packet generation process.
77 *
78 * @param packetRate packets per second
79 * @param hostService host service
80 * @param deviceService device service
81 * @param providerService packet provider service
82 */
83 void start(int packetRate, HostService hostService,
84 DeviceAdminService deviceService,
85 PacketProviderService providerService) {
86 this.hostService = hostService;
87 this.providerService = providerService;
88
89 this.devices = copyOf(deviceService.getDevices()).stream()
90 .filter(d -> deviceService.getRole(d.id()) == MASTER)
91 .collect(Collectors.toList());
92
93 adjustRate(packetRate);
94 timeout = timer.newTimeout(new PacketDriverTask(), INITIAL_DELAY, SECONDS);
95 }
96
97 /**
98 * Adjusts packet rate.
99 *
100 * @param packetRate new packet rate
101 */
102 void adjustRate(int packetRate) {
Thomas Vachuskac3cdf902016-04-13 13:44:09 -0700103 boolean needsRestart = delay == 0 && packetRate > 0;
104 delay = packetRate > 0 ? 1000 / packetRate : 0;
105 if (needsRestart) {
106 timeout = timer.newTimeout(new PacketDriverTask(), 1, MILLISECONDS);
107 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700108 log.info("Settings: packetRate={}, delay={}", packetRate, delay);
109 }
110
111 /**
112 * Stops the packet generation process.
113 */
114 void stop() {
115 if (timeout != null) {
116 timeout.cancel();
117 }
118 }
119
120 @Override
121 public void emit(OutboundPacket packet) {
122 // We don't have a network to emit to. Keep a counter here, maybe?
123 }
124
125 /**
126 * Generates packet events at a given rate.
127 */
128 private class PacketDriverTask implements TimerTask {
129
130 // Filler echo request
131 ICMP icmp;
132 Ethernet eth;
133
Thomas Vachuskac3cdf902016-04-13 13:44:09 -0700134 PacketDriverTask() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700135 icmp = new ICMP();
136 icmp.setIcmpType((byte) 8).setIcmpCode((byte) 0).setChecksum((short) 0);
137 eth = new Ethernet();
138 eth.setEtherType(Ethernet.TYPE_IPV4);
139 eth.setPayload(icmp);
140 }
141
142 @Override
143 public void run(Timeout to) {
Thomas Vachuskac3cdf902016-04-13 13:44:09 -0700144 if (!devices.isEmpty() && !to.isCancelled() && delay > 0) {
Thomas Vachuska5c3fd702015-05-01 11:16:53 -0700145 sendEvent(devices.get(Math.min(currentDevice, devices.size() - 1)));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700146 currentDevice = (currentDevice + 1) % devices.size();
147 timeout = timer.newTimeout(to.getTask(), delay, TimeUnit.MILLISECONDS);
148 }
149 }
150
151 private void sendEvent(Device device) {
152 // Make it look like things came from ports attached to hosts
Thomas Vachuskac3cdf902016-04-13 13:44:09 -0700153 eth.setSourceMACAddress("00:00:00:10:00:0" + SRC_HOST)
154 .setDestinationMACAddress("00:00:00:10:00:0" + DST_HOST);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700155 InboundPacket inPkt = new DefaultInboundPacket(
156 new ConnectPoint(device.id(), PortNumber.portNumber(SRC_HOST)),
157 eth, ByteBuffer.wrap(eth.serialize()));
158 providerService.processPacket(new NullPacketContext(inPkt, null));
159 }
160 }
161
162 // Minimal PacketContext to make core and applications happy.
163 private final class NullPacketContext extends DefaultPacketContext {
164 private NullPacketContext(InboundPacket inPkt, OutboundPacket outPkt) {
165 super(System.currentTimeMillis(), inPkt, outPkt, false);
166 }
167
168 @Override
169 public void send() {
170 // We don't send anything out.
171 }
172 }
173
174}