Ayaka Koshibe
Committed by Gerrit Code Review

NullPacketProvider that generates PacketEvents at a specified rate

and behaves as a sink for network-bound events.

Reference: ONOS-665

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