blob: 15bd6714ca24a4442f8134bd34e1e45cecc99ccd [file] [log] [blame]
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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.packet.impl;
17
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -080018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onlab.packet.Ethernet;
26import org.onlab.packet.ICMP;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070027import org.onosproject.cfg.ComponentConfigService;
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -080028import org.onosproject.net.ConnectPoint;
29import org.onosproject.net.Device;
30import org.onosproject.net.PortNumber;
31import org.onosproject.net.device.DeviceService;
32import org.onosproject.net.packet.DefaultInboundPacket;
33import org.onosproject.net.packet.DefaultPacketContext;
34import org.onosproject.net.packet.InboundPacket;
35import org.onosproject.net.packet.OutboundPacket;
36import org.onosproject.net.packet.PacketContext;
37import org.onosproject.net.packet.PacketProvider;
38import org.onosproject.net.packet.PacketProviderRegistry;
39import org.onosproject.net.packet.PacketProviderService;
40import org.onosproject.net.provider.AbstractProvider;
41import org.onosproject.net.provider.ProviderId;
42import org.osgi.service.component.ComponentContext;
43import org.slf4j.Logger;
44
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080045import java.nio.ByteBuffer;
46import java.util.Dictionary;
47import java.util.concurrent.ExecutorService;
48import java.util.concurrent.Executors;
49import java.util.concurrent.TimeUnit;
50
51import static com.google.common.base.Strings.isNullOrEmpty;
52import static org.onlab.util.Tools.delay;
53import static org.onlab.util.Tools.groupedThreads;
54import static org.slf4j.LoggerFactory.getLogger;
55
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -080056/**
57 * Provider which 1) intercepts network-bound messages from the core, and 2)
58 * generates PacketEvents at some tunable rate. To be used for benchmarking
59 * only.
60 */
61@Component(immediate = true)
62public class NullPacketProvider extends AbstractProvider implements
63 PacketProvider {
64
65 private final Logger log = getLogger(getClass());
66
67 // Default packetEvent generation rate (in packets/sec)
68 // If 0, we are just a sink for network-bound packets
69 private static final int DEFAULT_RATE = 5;
70 // arbitrary host "destination"
71 private static final int DESTHOST = 5;
72
73 private PacketProviderService providerService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected PacketProviderRegistry providerRegistry;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected DeviceService deviceService;
80
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected ComponentConfigService cfgService;
83
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -080084 // Rate to generate PacketEvents, per second
85 @Property(name = "pktRate", intValue = DEFAULT_RATE,
86 label = "Rate of PacketEvent generation")
87 private int pktRate = DEFAULT_RATE;
88
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080089 private ExecutorService packetDriver =
90 Executors.newFixedThreadPool(1, groupedThreads("onos/null", "packet-driver"));
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -080091
92 public NullPacketProvider() {
93 super(new ProviderId("null", "org.onosproject.provider.nil"));
94 }
95
96 @Activate
97 public void activate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070098 cfgService.registerProperties(getClass());
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -080099 providerService = providerRegistry.register(this);
100 if (!modified(context)) {
101 packetDriver.submit(new PacketDriver());
102 }
103 log.info("started");
104 }
105
106 @Deactivate
107 public void deactivate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700108 cfgService.unregisterProperties(getClass(), false);
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -0800109 try {
110 packetDriver.awaitTermination(1000, TimeUnit.MILLISECONDS);
111 } catch (InterruptedException e) {
112 log.error("PacketDriver did not terminate");
113 }
114 packetDriver.shutdownNow();
115 providerRegistry.unregister(this);
116 log.info("stopped");
117 }
118
119 @Modified
120 public boolean modified(ComponentContext context) {
121 if (context == null) {
122 log.info("No configuration change, using defaults: pktRate={}",
123 DEFAULT_RATE);
124 return false;
125 }
126 Dictionary<?, ?> properties = context.getProperties();
127
128 int newRate;
129 try {
130 String s = String.valueOf(properties.get("pktRate"));
Yuta HIGUCHIdd9228d2015-02-10 22:26:59 -0800131 newRate = isNullOrEmpty(s) ? pktRate : Integer.parseInt(s.trim());
Pavlin Radoslavovb9e50df2015-02-20 20:01:26 -0800132 } catch (NumberFormatException | ClassCastException e) {
Ayaka Koshibe7dc1d042015-01-21 15:28:03 -0800133 log.warn(e.getMessage());
134 newRate = pktRate;
135 }
136
137 if (newRate != pktRate) {
138 pktRate = newRate;
139 packetDriver.submit(new PacketDriver());
140 log.info("Using new settings: pktRate={}", pktRate);
141 return true;
142 }
143 return false;
144 }
145
146 @Override
147 public void emit(OutboundPacket packet) {
148 // We don't have a network to emit to. Keep a counter here, maybe?
149 }
150
151 /**
152 * Generates packet events at a given rate.
153 */
154 private class PacketDriver implements Runnable {
155
156 // time between event firing, in milliseconds
157 int pktInterval;
158 // filler echo request
159 ICMP icmp;
160 Ethernet eth;
161
162 public PacketDriver() {
163 pktInterval = 1000 / pktRate;
164 icmp = new ICMP();
165 icmp.setIcmpType((byte) 8).setIcmpCode((byte) 0)
166 .setChecksum((short) 0);
167 eth = new Ethernet();
168 eth.setEtherType(Ethernet.TYPE_IPV4);
169 eth.setPayload(icmp);
170 }
171
172 @Override
173 public void run() {
174 log.info("PacketDriver started");
175 while (!packetDriver.isShutdown()) {
176 for (Device dev : deviceService.getDevices()) {
177 sendEvents(dev);
178 }
179 }
180 }
181
182 private void sendEvents(Device dev) {
183 // make it look like things came from ports attached to hosts
184 for (int i = 0; i < 4; i++) {
185 eth.setSourceMACAddress("00:00:10:00:00:0" + i)
186 .setDestinationMACAddress("00:00:10:00:00:0" + DESTHOST);
187 InboundPacket inPkt = new DefaultInboundPacket(
188 new ConnectPoint(dev.id(), PortNumber.portNumber(i)),
189 eth, ByteBuffer.wrap(eth.serialize()));
190 PacketContext pctx = new NullPacketContext(
191 System.currentTimeMillis(), inPkt, null, false);
192 providerService.processPacket(pctx);
193 delay(pktInterval);
194 }
195 }
196
197 }
198
199 /**
200 * Minimal PacketContext to make core + applications happy.
201 */
202 private class NullPacketContext extends DefaultPacketContext {
203
204 public NullPacketContext(long time, InboundPacket inPkt,
205 OutboundPacket outPkt, boolean block) {
206 super(time, inPkt, outPkt, block);
207 }
208
209 @Override
210 public void send() {
211 // We don't send anything out.
212 }
213
214 }
215
216}