blob: 8d797e7a7cc4186d974e514166ef7123e371fe11 [file] [log] [blame]
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -07001package net.onrc.onos.datagrid;
2
3import java.io.FileNotFoundException;
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.HashMap;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -07007import java.util.LinkedList;
Jonathan Hart18ad55c2013-11-11 22:49:55 -08008import java.util.List;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -07009import java.util.Map;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070010import java.util.Set;
Jonathan Hart18ad55c2013-11-11 22:49:55 -080011import java.util.concurrent.TimeUnit;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070012
13import net.floodlightcontroller.core.IFloodlightProviderService;
14import net.floodlightcontroller.core.module.FloodlightModuleContext;
15import net.floodlightcontroller.core.module.FloodlightModuleException;
16import net.floodlightcontroller.core.module.IFloodlightModule;
17import net.floodlightcontroller.core.module.IFloodlightService;
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -070018import net.floodlightcontroller.restserver.IRestApiService;
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -070019import net.onrc.onos.datagrid.web.DatagridWebRoutable;
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070020import net.onrc.onos.ofcontroller.flowmanager.IFlowEventHandlerService;
Jonathan Hart7804bea2014-01-07 10:50:52 -080021import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
22import net.onrc.onos.ofcontroller.proxyarp.IArpReplyEventHandler;
23import net.onrc.onos.ofcontroller.proxyarp.IPacketOutEventHandler;
24import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -070025import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -080026import net.onrc.onos.ofcontroller.util.Dpid;
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070027import net.onrc.onos.ofcontroller.util.FlowEntry;
28import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070029import net.onrc.onos.ofcontroller.util.FlowId;
30import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080031import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070032import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
33
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070034import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -080037import com.esotericsoftware.kryo.Kryo;
38import com.esotericsoftware.kryo.io.Input;
39import com.esotericsoftware.kryo.io.Output;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070040import com.hazelcast.config.Config;
41import com.hazelcast.config.FileSystemXmlConfig;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070042import com.hazelcast.core.EntryEvent;
43import com.hazelcast.core.EntryListener;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070044import com.hazelcast.core.Hazelcast;
45import com.hazelcast.core.HazelcastInstance;
Toshio Koide3738ee52014-02-12 14:57:39 -080046import com.hazelcast.core.IList;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070047import com.hazelcast.core.IMap;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070048import com.hazelcast.instance.GroupProperties;
Toshio Koide3738ee52014-02-12 14:57:39 -080049import net.onrc.onos.intent.Intent;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070050
Pavlin Radoslavove2497672014-01-12 18:03:35 -080051import net.onrc.onos.ofcontroller.flowmanager.PerformanceMonitor;
52
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070053/**
54 * A datagrid service that uses Hazelcast as a datagrid.
55 * The relevant data is stored in the Hazelcast datagrid and shared as
56 * appropriate in a multi-node cluster.
57 */
58public class HazelcastDatagrid implements IFloodlightModule, IDatagridService {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070059 private final static int MAX_BUFFER_SIZE = 64*1024;
60
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070061 protected final static Logger log = LoggerFactory.getLogger(HazelcastDatagrid.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070062 protected IFloodlightProviderService floodlightProvider;
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -070063 protected IRestApiService restApi;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070064
65 protected static final String HazelcastConfigFile = "datagridConfig";
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070066 private HazelcastInstance hazelcastInstance = null;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070067 private Config hazelcastConfig = null;
68
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070069 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070070 private IFlowEventHandlerService flowEventHandlerService = null;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070071
Pavlin Radoslavov7940b652014-02-13 19:42:05 -080072 private Map<String, IEventChannel<?, ?>> eventChannels =
73 new HashMap<String, IEventChannel<?, ?>>();
74
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070075 // State related to the Flow map
76 protected static final String mapFlowName = "mapFlow";
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070077 private IMap<Long, byte[]> mapFlow = null;
78 private MapFlowListener mapFlowListener = null;
79 private String mapFlowListenerId = null;
80
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070081 // State related to the Flow Entry map
82 protected static final String mapFlowEntryName = "mapFlowEntry";
83 private IMap<Long, byte[]> mapFlowEntry = null;
84 private MapFlowEntryListener mapFlowEntryListener = null;
85 private String mapFlowEntryListenerId = null;
86
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -080087 // State related to the Flow ID map
88 protected static final String mapFlowIdName = "mapFlowId";
89 private IMap<Long, byte[]> mapFlowId = null;
90 private MapFlowIdListener mapFlowIdListener = null;
91 private String mapFlowIdListenerId = null;
92
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -080093 // State related to the Flow Entry ID map
94 protected static final String mapFlowEntryIdName = "mapFlowEntryId";
95 private IMap<Long, byte[]> mapFlowEntryId = null;
96 private MapFlowEntryIdListener mapFlowEntryIdListener = null;
97 private String mapFlowEntryIdListenerId = null;
98
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -070099 // State related to the Network Topology map
100 protected static final String mapTopologyName = "mapTopology";
101 private IMap<String, byte[]> mapTopology = null;
102 private MapTopologyListener mapTopologyListener = null;
103 private String mapTopologyListenerId = null;
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800104
Jonathan Hart7804bea2014-01-07 10:50:52 -0800105 // State related to the packet out map
106 protected static final String packetOutMapName = "packetOutMap";
107 private IMap<PacketOutNotification, byte[]> packetOutMap = null;
108 private List<IPacketOutEventHandler> packetOutEventHandlers = new ArrayList<IPacketOutEventHandler>();
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800109
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800110 private final byte[] dummyByte = {0};
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700111
Jonathan Hart7804bea2014-01-07 10:50:52 -0800112 // State related to the ARP reply map
113 protected static final String arpReplyMapName = "arpReplyMap";
114 private IMap<ArpReplyNotification, byte[]> arpReplyMap = null;
115 private List<IArpReplyEventHandler> arpReplyEventHandlers = new ArrayList<IArpReplyEventHandler>();
Toshio Koide3738ee52014-02-12 14:57:39 -0800116
117
118 protected static final String intentListName = "intentList";
119 private IList<Intent> intentList = null;
120
121 @Override
122 public void registerIntent(Collection<Intent> intents) {
123 intentList.addAll(intents);
124 }
125
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700126
127 /**
128 * Class for receiving notifications for Flow state.
129 *
130 * The datagrid map is:
131 * - Key : Flow ID (Long)
Pavlin Radoslavov5367d212013-11-07 11:18:51 -0800132 * - Value : Serialized FlowPath (byte[])
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700133 */
134 class MapFlowListener implements EntryListener<Long, byte[]> {
135 /**
136 * Receive a notification that an entry is added.
137 *
138 * @param event the notification event for the entry.
139 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800140 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800141 public void entryAdded(EntryEvent<Long, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800142 byte[] valueBytes = event.getValue();
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700143
144 //
145 // Decode the value and deliver the notification
146 //
147 Kryo kryo = kryoFactory.newKryo();
148 Input input = new Input(valueBytes);
149 FlowPath flowPath = kryo.readObject(input, FlowPath.class);
150 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700151 flowEventHandlerService.notificationRecvFlowAdded(flowPath);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700152 }
153
154 /**
155 * Receive a notification that an entry is removed.
156 *
157 * @param event the notification event for the entry.
158 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800159 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800160 public void entryRemoved(EntryEvent<Long, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800161 byte[] valueBytes = event.getValue();
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700162
163 //
164 // Decode the value and deliver the notification
165 //
166 Kryo kryo = kryoFactory.newKryo();
167 Input input = new Input(valueBytes);
168 FlowPath flowPath = kryo.readObject(input, FlowPath.class);
169 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700170 flowEventHandlerService.notificationRecvFlowRemoved(flowPath);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700171 }
172
173 /**
174 * Receive a notification that an entry is updated.
175 *
176 * @param event the notification event for the entry.
177 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800178 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800179 public void entryUpdated(EntryEvent<Long, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800180 byte[] valueBytes = event.getValue();
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700181
182 //
183 // Decode the value and deliver the notification
184 //
185 Kryo kryo = kryoFactory.newKryo();
186 Input input = new Input(valueBytes);
187 FlowPath flowPath = kryo.readObject(input, FlowPath.class);
188 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700189 flowEventHandlerService.notificationRecvFlowUpdated(flowPath);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700190 }
191
192 /**
193 * Receive a notification that an entry is evicted.
194 *
195 * @param event the notification event for the entry.
196 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800197 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800198 public void entryEvicted(EntryEvent<Long, byte[]> event) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700199 // NOTE: We don't use eviction for this map
200 }
201 }
202
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700203 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700204 * Class for receiving notifications for FlowEntry state.
205 *
206 * The datagrid map is:
207 * - Key : FlowEntry ID (Long)
208 * - Value : Serialized FlowEntry (byte[])
209 */
210 class MapFlowEntryListener implements EntryListener<Long, byte[]> {
211 /**
212 * Receive a notification that an entry is added.
213 *
214 * @param event the notification event for the entry.
215 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800216 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800217 public void entryAdded(EntryEvent<Long, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800218 byte[] valueBytes = event.getValue();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700219
220 //
221 // Decode the value and deliver the notification
222 //
223 Kryo kryo = kryoFactory.newKryo();
224 Input input = new Input(valueBytes);
225 FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
226 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700227 flowEventHandlerService.notificationRecvFlowEntryAdded(flowEntry);
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700228 }
229
230 /**
231 * Receive a notification that an entry is removed.
232 *
233 * @param event the notification event for the entry.
234 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800235 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800236 public void entryRemoved(EntryEvent<Long, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800237 byte[] valueBytes = event.getValue();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700238
239 //
240 // Decode the value and deliver the notification
241 //
242 Kryo kryo = kryoFactory.newKryo();
243 Input input = new Input(valueBytes);
244 FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
245 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700246 flowEventHandlerService.notificationRecvFlowEntryRemoved(flowEntry);
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700247 }
248
249 /**
250 * Receive a notification that an entry is updated.
251 *
252 * @param event the notification event for the entry.
253 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800254 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800255 public void entryUpdated(EntryEvent<Long, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800256 byte[] valueBytes = event.getValue();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700257
258 //
259 // Decode the value and deliver the notification
260 //
261 Kryo kryo = kryoFactory.newKryo();
262 Input input = new Input(valueBytes);
263 FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
264 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700265 flowEventHandlerService.notificationRecvFlowEntryUpdated(flowEntry);
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700266 }
267
268 /**
269 * Receive a notification that an entry is evicted.
270 *
271 * @param event the notification event for the entry.
272 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800273 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800274 public void entryEvicted(EntryEvent<Long, byte[]> event) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700275 // NOTE: We don't use eviction for this map
276 }
277 }
278
279 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800280 * Class for receiving notifications for FlowId state.
281 *
282 * The datagrid map is:
283 * - Key : FlowId (Long)
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800284 * - Value : Serialized Switch Dpid (byte[])
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800285 */
286 class MapFlowIdListener implements EntryListener<Long, byte[]> {
287 /**
288 * Receive a notification that an entry is added.
289 *
290 * @param event the notification event for the entry.
291 */
292 public void entryAdded(EntryEvent<Long, byte[]> event) {
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800293 Long keyLong = event.getKey();
294 FlowId flowId = new FlowId(keyLong);
295
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800296 byte[] valueBytes = event.getValue();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800297
298 //
299 // Decode the value and deliver the notification
300 //
301 Kryo kryo = kryoFactory.newKryo();
302 Input input = new Input(valueBytes);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800303 Dpid dpid = kryo.readObject(input, Dpid.class);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800304 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800305 flowEventHandlerService.notificationRecvFlowIdAdded(flowId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800306 }
307
308 /**
309 * Receive a notification that an entry is removed.
310 *
311 * @param event the notification event for the entry.
312 */
313 public void entryRemoved(EntryEvent<Long, byte[]> event) {
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800314 Long keyLong = event.getKey();
315 FlowId flowId = new FlowId(keyLong);
316
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800317 byte[] valueBytes = event.getValue();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800318
319 //
320 // Decode the value and deliver the notification
321 //
322 Kryo kryo = kryoFactory.newKryo();
323 Input input = new Input(valueBytes);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800324 Dpid dpid = kryo.readObject(input, Dpid.class);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800325 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800326 flowEventHandlerService.notificationRecvFlowIdRemoved(flowId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800327 }
328
329 /**
330 * Receive a notification that an entry is updated.
331 *
332 * @param event the notification event for the entry.
333 */
334 public void entryUpdated(EntryEvent<Long, byte[]> event) {
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800335 Long keyLong = event.getKey();
336 FlowId flowId = new FlowId(keyLong);
337
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800338 byte[] valueBytes = event.getValue();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800339
340 //
341 // Decode the value and deliver the notification
342 //
343 Kryo kryo = kryoFactory.newKryo();
344 Input input = new Input(valueBytes);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800345 Dpid dpid = kryo.readObject(input, Dpid.class);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800346 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800347 flowEventHandlerService.notificationRecvFlowIdUpdated(flowId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800348 }
349
350 /**
351 * Receive a notification that an entry is evicted.
352 *
353 * @param event the notification event for the entry.
354 */
355 public void entryEvicted(EntryEvent<Long, byte[]> event) {
356 // NOTE: We don't use eviction for this map
357 }
358 }
359
360 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800361 * Class for receiving notifications for FlowEntryId state.
362 *
363 * The datagrid map is:
364 * - Key : FlowEntryId (Long)
365 * - Value : Serialized Switch Dpid (byte[])
366 */
367 class MapFlowEntryIdListener implements EntryListener<Long, byte[]> {
368 /**
369 * Receive a notification that an entry is added.
370 *
371 * @param event the notification event for the entry.
372 */
373 public void entryAdded(EntryEvent<Long, byte[]> event) {
374 Long keyLong = event.getKey();
375 FlowEntryId flowEntryId = new FlowEntryId(keyLong);
376
377 byte[] valueBytes = event.getValue();
378
379 //
380 // Decode the value and deliver the notification
381 //
382 Kryo kryo = kryoFactory.newKryo();
383 Input input = new Input(valueBytes);
384 Dpid dpid = kryo.readObject(input, Dpid.class);
385 kryoFactory.deleteKryo(kryo);
386 flowEventHandlerService.notificationRecvFlowEntryIdAdded(flowEntryId, dpid);
387 }
388
389 /**
390 * Receive a notification that an entry is removed.
391 *
392 * @param event the notification event for the entry.
393 */
394 public void entryRemoved(EntryEvent<Long, byte[]> event) {
395 Long keyLong = event.getKey();
396 FlowEntryId flowEntryId = new FlowEntryId(keyLong);
397
398 byte[] valueBytes = event.getValue();
399
400 //
401 // Decode the value and deliver the notification
402 //
403 Kryo kryo = kryoFactory.newKryo();
404 Input input = new Input(valueBytes);
405 Dpid dpid = kryo.readObject(input, Dpid.class);
406 kryoFactory.deleteKryo(kryo);
407 flowEventHandlerService.notificationRecvFlowEntryIdRemoved(flowEntryId, dpid);
408 }
409
410 /**
411 * Receive a notification that an entry is updated.
412 *
413 * @param event the notification event for the entry.
414 */
415 public void entryUpdated(EntryEvent<Long, byte[]> event) {
416 Long keyLong = event.getKey();
417 FlowEntryId flowEntryId = new FlowEntryId(keyLong);
418
419 byte[] valueBytes = event.getValue();
420
421 //
422 // Decode the value and deliver the notification
423 //
424 Kryo kryo = kryoFactory.newKryo();
425 Input input = new Input(valueBytes);
426 Dpid dpid = kryo.readObject(input, Dpid.class);
427 kryoFactory.deleteKryo(kryo);
428 flowEventHandlerService.notificationRecvFlowEntryIdUpdated(flowEntryId, dpid);
429 }
430
431 /**
432 * Receive a notification that an entry is evicted.
433 *
434 * @param event the notification event for the entry.
435 */
436 public void entryEvicted(EntryEvent<Long, byte[]> event) {
437 // NOTE: We don't use eviction for this map
438 }
439 }
440
441 /**
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700442 * Class for receiving notifications for Network Topology state.
443 *
444 * The datagrid map is:
445 * - Key: TopologyElement ID (String)
446 * - Value: Serialized TopologyElement (byte[])
447 */
448 class MapTopologyListener implements EntryListener<String, byte[]> {
449 /**
450 * Receive a notification that an entry is added.
451 *
452 * @param event the notification event for the entry.
453 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800454 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800455 public void entryAdded(EntryEvent<String, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800456 byte[] valueBytes = event.getValue();
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700457
458 //
459 // Decode the value and deliver the notification
460 //
461 Kryo kryo = kryoFactory.newKryo();
462 Input input = new Input(valueBytes);
463 TopologyElement topologyElement =
464 kryo.readObject(input, TopologyElement.class);
465 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700466 flowEventHandlerService.notificationRecvTopologyElementAdded(topologyElement);
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700467 }
468
469 /**
470 * Receive a notification that an entry is removed.
471 *
472 * @param event the notification event for the entry.
473 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800474 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800475 public void entryRemoved(EntryEvent<String, byte[]> event) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800476// String tag = "TopologyEntryRemoved.NotificationReceived." + event.getKey();
477 String tag = "TopologyEntryRemoved.NotificationReceived";
478 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800479 byte[] valueBytes = event.getValue();
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700480
481 //
482 // Decode the value and deliver the notification
483 //
484 Kryo kryo = kryoFactory.newKryo();
485 Input input = new Input(valueBytes);
486 TopologyElement topologyElement =
487 kryo.readObject(input, TopologyElement.class);
488 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700489 flowEventHandlerService.notificationRecvTopologyElementRemoved(topologyElement);
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800490// PerformanceMonitor.stop(tag);
491 m.stop();
492// PerformanceMonitor.report(tag);
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700493 }
494
495 /**
496 * Receive a notification that an entry is updated.
497 *
498 * @param event the notification event for the entry.
499 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800500 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800501 public void entryUpdated(EntryEvent<String, byte[]> event) {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800502 byte[] valueBytes = event.getValue();
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700503
504 //
505 // Decode the value and deliver the notification
506 //
507 Kryo kryo = kryoFactory.newKryo();
508 Input input = new Input(valueBytes);
509 TopologyElement topologyElement =
510 kryo.readObject(input, TopologyElement.class);
511 kryoFactory.deleteKryo(kryo);
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700512 flowEventHandlerService.notificationRecvTopologyElementUpdated(topologyElement);
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700513 }
514
515 /**
516 * Receive a notification that an entry is evicted.
517 *
518 * @param event the notification event for the entry.
519 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800520 @Override
Pavlin Radoslavov95e6e902013-12-11 12:03:29 -0800521 public void entryEvicted(EntryEvent<String, byte[]> event) {
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700522 // NOTE: We don't use eviction for this map
523 }
524 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800525
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800526 /**
Jonathan Hart7804bea2014-01-07 10:50:52 -0800527 * Class for receiving notifications for sending packet-outs.
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800528 *
529 * The datagrid map is:
Jonathan Hart7804bea2014-01-07 10:50:52 -0800530 * - Key: Packet-out to send (PacketOutNotification)
531 * - Value: dummy value (we only need the key) (byte[])
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800532 */
Jonathan Hart7804bea2014-01-07 10:50:52 -0800533 class PacketOutMapListener implements EntryListener<PacketOutNotification, byte[]> {
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800534 /**
535 * Receive a notification that an entry is added.
536 *
537 * @param event the notification event for the entry.
538 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800539 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800540 public void entryAdded(EntryEvent<PacketOutNotification, byte[]> event) {
541 for (IPacketOutEventHandler packetOutEventHandler : packetOutEventHandlers) {
542 packetOutEventHandler.packetOutNotification(event.getKey());
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800543 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800544 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800545
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800546 /**
547 * Receive a notification that an entry is removed.
548 *
549 * @param event the notification event for the entry.
550 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800551 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800552 public void entryRemoved(EntryEvent<PacketOutNotification, byte[]> event) {
Jonathan Hart799242b2013-11-12 12:57:29 -0800553 // Not used
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800554 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800555
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800556 /**
557 * Receive a notification that an entry is updated.
558 *
559 * @param event the notification event for the entry.
560 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800561 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800562 public void entryUpdated(EntryEvent<PacketOutNotification, byte[]> event) {
Jonathan Hart799242b2013-11-12 12:57:29 -0800563 // Not used
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800564 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800565
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800566 /**
567 * Receive a notification that an entry is evicted.
568 *
569 * @param event the notification event for the entry.
570 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800571 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800572 public void entryEvicted(EntryEvent<PacketOutNotification, byte[]> event) {
Jonathan Hart799242b2013-11-12 12:57:29 -0800573 // Not used
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800574 }
575 }
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700576
577 /**
Jonathan Hart7804bea2014-01-07 10:50:52 -0800578 * Class for receiving notifications for sending packet-outs.
579 *
580 * The datagrid map is:
581 * - Key: Packet-out to send (PacketOutNotification)
582 * - Value: dummy value (we only need the key) (byte[])
583 */
584 class ArpReplyMapListener implements EntryListener<ArpReplyNotification, byte[]> {
585 /**
586 * Receive a notification that an entry is added.
587 *
588 * @param event the notification event for the entry.
589 */
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800590 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800591 public void entryAdded(EntryEvent<ArpReplyNotification, byte[]> event) {
592 for (IArpReplyEventHandler arpReplyEventHandler : arpReplyEventHandlers) {
593 arpReplyEventHandler.arpReplyEvent(event.getKey());
594 }
595 }
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800596
Jonathan Hart7804bea2014-01-07 10:50:52 -0800597 // These methods aren't used for ARP replies
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800598 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800599 public void entryRemoved(EntryEvent<ArpReplyNotification, byte[]> event) {}
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800600 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800601 public void entryUpdated(EntryEvent<ArpReplyNotification, byte[]> event) {}
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800602 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800603 public void entryEvicted(EntryEvent<ArpReplyNotification, byte[]> event) {}
604 }
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700605
606 /**
607 * Initialize the Hazelcast Datagrid operation.
608 *
609 * @param conf the configuration filename.
610 */
611 public void init(String configFilename) {
612 /*
613 System.setProperty("hazelcast.socket.receive.buffer.size", "32");
614 System.setProperty("hazelcast.socket.send.buffer.size", "32");
615 */
616 // System.setProperty("hazelcast.heartbeat.interval.seconds", "100");
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800617
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700618 // Init from configuration file
619 try {
620 hazelcastConfig = new FileSystemXmlConfig(configFilename);
621 } catch (FileNotFoundException e) {
622 log.error("Error opening Hazelcast XML configuration. File not found: " + configFilename, e);
623 }
624 /*
625 hazelcastConfig.setProperty(GroupProperties.PROP_IO_THREAD_COUNT, "1");
626 hazelcastConfig.setProperty(GroupProperties.PROP_OPERATION_THREAD_COUNT, "1");
627 hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_THREAD_COUNT, "1");
628 */
629 //
630 hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_QUEUE_CAPACITY, "4000000");
631 hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_RECEIVE_BUFFER_SIZE, "4096");
632 hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_SEND_BUFFER_SIZE, "4096");
633 }
634
635 /**
636 * Shutdown the Hazelcast Datagrid operation.
637 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800638 @Override
639 protected void finalize() {
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700640 close();
641 }
642
643 /**
644 * Shutdown the Hazelcast Datagrid operation.
645 */
646 public void close() {
647 Hazelcast.shutdownAll();
648 }
649
650 /**
651 * Get the collection of offered module services.
652 *
653 * @return the collection of offered module services.
654 */
655 @Override
656 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800657 Collection<Class<? extends IFloodlightService>> l =
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700658 new ArrayList<Class<? extends IFloodlightService>>();
659 l.add(IDatagridService.class);
660 return l;
661 }
662
663 /**
664 * Get the collection of implemented services.
665 *
666 * @return the collection of implemented services.
667 */
668 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800669 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700670 getServiceImpls() {
671 Map<Class<? extends IFloodlightService>,
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800672 IFloodlightService> m =
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700673 new HashMap<Class<? extends IFloodlightService>,
674 IFloodlightService>();
675 m.put(IDatagridService.class, this);
676 return m;
677 }
678
679 /**
680 * Get the collection of modules this module depends on.
681 *
682 * @return the collection of modules this module depends on.
683 */
684 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800685 public Collection<Class<? extends IFloodlightService>>
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700686 getModuleDependencies() {
687 Collection<Class<? extends IFloodlightService>> l =
688 new ArrayList<Class<? extends IFloodlightService>>();
689 l.add(IFloodlightProviderService.class);
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -0700690 l.add(IRestApiService.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700691 return l;
692 }
693
694 /**
695 * Initialize the module.
696 *
697 * @param context the module context to use for the initialization.
698 */
699 @Override
700 public void init(FloodlightModuleContext context)
701 throws FloodlightModuleException {
702 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -0700703 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700704
705 // Get the configuration file name and configure the Datagrid
706 Map<String, String> configMap = context.getConfigParams(this);
707 String configFilename = configMap.get(HazelcastConfigFile);
708 this.init(configFilename);
709 }
710
711 /**
712 * Startup module operation.
713 *
714 * @param context the module context to use for the startup.
715 */
716 @Override
717 public void startUp(FloodlightModuleContext context) {
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700718 hazelcastInstance = Hazelcast.newHazelcastInstance(hazelcastConfig);
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -0700719
720 restApi.addRestletRoutable(new DatagridWebRoutable());
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800721
Jonathan Hart7804bea2014-01-07 10:50:52 -0800722 packetOutMap = hazelcastInstance.getMap(packetOutMapName);
723 packetOutMap.addEntryListener(new PacketOutMapListener(), true);
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800724
Jonathan Hart7804bea2014-01-07 10:50:52 -0800725 arpReplyMap = hazelcastInstance.getMap(arpReplyMapName);
726 arpReplyMap.addEntryListener(new ArpReplyMapListener(), true);
Toshio Koide3738ee52014-02-12 14:57:39 -0800727 intentList = hazelcastInstance.getList(intentListName);
728
729
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700730 }
731
732 /**
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800733 * Create an event channel.
734 *
735 * If the channel already exists, just return it.
736 * NOTE: The channel is started automatically.
737 *
738 * @param channelName the event channel name.
739 * @param typeK the type of the Key in the Key-Value store.
740 * @param typeV the type of the Value in the Key-Value store.
741 * @return the event channel for the channel name.
742 */
743 @Override
744 public <K, V> IEventChannel<K, V> createChannel(String channelName,
745 Class<K> typeK, Class<V> typeV) {
746 IEventChannel<K, V> eventChannel =
747 createChannelImpl(channelName, typeK, typeV);
748 eventChannel.startup();
749
750 return eventChannel;
751 }
752
753 /**
754 * Create an event channel implementation.
755 *
756 * If the channel already exists, just return it.
757 * NOTE: The caller must call IEventChannel.startup() to startup the
758 * channel operation.
759 *
760 * @param channelName the event channel name.
761 * @param typeK the type of the Key in the Key-Value store.
762 * @param typeV the type of the Value in the Key-Value store.
763 * @return the event channel for the channel name.
764 */
Pavlin Radoslavov1c8d8092014-02-14 15:47:24 -0800765 private synchronized <K, V> IEventChannel<K, V> createChannelImpl(
766 String channelName,
767 Class<K> typeK, Class<V> typeV) {
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800768 IEventChannel<K, V> castedEventChannel;
769 IEventChannel<?, ?> genericEventChannel =
770 eventChannels.get(channelName);
771
772 // Add the channel if the first listener
773 if (genericEventChannel == null) {
774 castedEventChannel =
775 new HazelcastEventChannel<K, V>(hazelcastInstance,
776 channelName, typeK, typeV);
777 eventChannels.put(channelName, castedEventChannel);
778 } else {
779 //
780 // TODO: Find if we can use Java internal support to check for
781 // type mismatch.
782 //
783 if (! genericEventChannel.verifyKeyValueTypes(typeK, typeV)) {
784 throw new ClassCastException("Key-value type mismatch for event channel " + channelName);
785 }
786 castedEventChannel = (IEventChannel<K, V>)genericEventChannel;
787 }
788
789 return castedEventChannel;
790 }
791
792 /**
793 * Add event channel listener.
794 *
795 * NOTE: The channel is started automatically right after the listener
796 * is added.
797 *
798 * @param channelName the event channel name.
799 * @param listener the listener to add.
800 * @param typeK the type of the Key in the Key-Value store.
801 * @param typeV the type of the Value in the Key-Value store.
802 * @return the event channel for the channel name.
803 */
804 @Override
805 public <K, V> IEventChannel<K, V> addListener(String channelName,
806 IEventChannelListener<K, V> listener,
807 Class<K> typeK, Class<V> typeV) {
808 IEventChannel<K, V> eventChannel =
809 createChannelImpl(channelName, typeK, typeV);
810 eventChannel.addListener(listener);
811 eventChannel.startup();
812
813 return eventChannel;
814 }
815
816 /**
817 * Remove event channel listener.
818 *
819 * @param channelName the event channel name.
820 * @param listener the listener to remove.
821 */
822 @Override
823 public <K, V> void removeListener(String channelName,
824 IEventChannelListener<K, V> listener) {
825 IEventChannel<K, V> castedEventChannel;
826 IEventChannel<?, ?> genericEventChannel =
827 eventChannels.get(channelName);
828
829 if (genericEventChannel != null) {
830 //
831 // TODO: Find if we can use Java internal support to check for
832 // type mismatch.
833 // NOTE: Using "ClassCastException" exception below doesn't work.
834 //
835 castedEventChannel = (IEventChannel<K, V>)genericEventChannel;
836 castedEventChannel.removeListener(listener);
837 }
838 }
839
840 /**
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700841 * Register Flow Event Handler Service for receiving Flow-related
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700842 * notifications.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700843 *
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700844 * NOTE: Only a single Flow Event Handler Service can be registered.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700845 *
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700846 * @param flowEventHandlerService the Flow Event Handler Service to register.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700847 */
848 @Override
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700849 public void registerFlowEventHandlerService(IFlowEventHandlerService flowEventHandlerService) {
850 this.flowEventHandlerService = flowEventHandlerService;
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700851
852 // Initialize the Flow-related map state
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700853 mapFlowListener = new MapFlowListener();
854 mapFlow = hazelcastInstance.getMap(mapFlowName);
855 mapFlowListenerId = mapFlow.addEntryListener(mapFlowListener, true);
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700856
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700857 // Initialize the FlowEntry-related map state
858 mapFlowEntryListener = new MapFlowEntryListener();
859 mapFlowEntry = hazelcastInstance.getMap(mapFlowEntryName);
860 mapFlowEntryListenerId = mapFlowEntry.addEntryListener(mapFlowEntryListener, true);
861
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800862 // Initialize the FlowId-related map state
863 mapFlowIdListener = new MapFlowIdListener();
864 mapFlowId = hazelcastInstance.getMap(mapFlowIdName);
865 mapFlowIdListenerId = mapFlowId.addEntryListener(mapFlowIdListener, true);
866
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800867 // Initialize the FlowEntryId-related map state
868 mapFlowEntryIdListener = new MapFlowEntryIdListener();
869 mapFlowEntryId = hazelcastInstance.getMap(mapFlowEntryIdName);
870 mapFlowEntryIdListenerId = mapFlowEntryId.addEntryListener(mapFlowEntryIdListener, true);
871
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700872 // Initialize the Topology-related map state
873 mapTopologyListener = new MapTopologyListener();
874 mapTopology = hazelcastInstance.getMap(mapTopologyName);
875 mapTopologyListenerId = mapTopology.addEntryListener(mapTopologyListener, true);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700876 }
877
878 /**
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700879 * De-register Flow Event Handler Service for receiving Flow-related
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700880 * notifications.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700881 *
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700882 * NOTE: Only a single Flow Event Handler Service can be registered.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700883 *
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700884 * @param flowEventHandlerService the Flow Event Handler Service to
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700885 * de-register.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700886 */
887 @Override
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700888 public void deregisterFlowEventHandlerService(IFlowEventHandlerService flowEventHandlerService) {
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700889 // Clear the Flow-related map state
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700890 mapFlow.removeEntryListener(mapFlowListenerId);
891 mapFlow = null;
892 mapFlowListener = null;
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700893
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700894 // Clear the FlowEntry-related map state
895 mapFlowEntry.removeEntryListener(mapFlowEntryListenerId);
896 mapFlowEntry = null;
897 mapFlowEntryListener = null;
898
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800899 // Clear the FlowId-related map state
900 mapFlowId.removeEntryListener(mapFlowIdListenerId);
901 mapFlowId = null;
902 mapFlowIdListener = null;
903
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800904 // Clear the FlowEntryId-related map state
905 mapFlowEntryId.removeEntryListener(mapFlowEntryIdListenerId);
906 mapFlowEntryId = null;
907 mapFlowEntryIdListener = null;
908
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700909 // Clear the Topology-related map state
910 mapTopology.removeEntryListener(mapTopologyListenerId);
911 mapTopology = null;
912 mapTopologyListener = null;
913
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700914 this.flowEventHandlerService = null;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700915 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800916
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800917 @Override
Jonathan Hartc6325622014-01-14 16:37:50 -0800918 public void registerPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
919 if (packetOutEventHandler != null) {
920 packetOutEventHandlers.add(packetOutEventHandler);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800921 }
922 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800923
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800924 @Override
Jonathan Hartc6325622014-01-14 16:37:50 -0800925 public void deregisterPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
926 packetOutEventHandlers.remove(packetOutEventHandler);
Jonathan Hart7804bea2014-01-07 10:50:52 -0800927 }
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800928
Jonathan Hart7804bea2014-01-07 10:50:52 -0800929 @Override
930 public void registerArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
931 if (arpReplyEventHandler != null) {
932 arpReplyEventHandlers.add(arpReplyEventHandler);
933 }
934 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800935
Jonathan Hart7804bea2014-01-07 10:50:52 -0800936 @Override
937 public void deregisterArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
938 arpReplyEventHandlers.remove(arpReplyEventHandler);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800939 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800940
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700941 /**
942 * Get all Flows that are currently in the datagrid.
943 *
944 * @return all Flows that are currently in the datagrid.
945 */
946 @Override
947 public Collection<FlowPath> getAllFlows() {
948 Collection<FlowPath> allFlows = new LinkedList<FlowPath>();
949
950 //
951 // Get all current entries
952 //
953 Collection<byte[]> values = mapFlow.values();
954 Kryo kryo = kryoFactory.newKryo();
955 for (byte[] valueBytes : values) {
956 //
957 // Decode the value
958 //
959 Input input = new Input(valueBytes);
960 FlowPath flowPath = kryo.readObject(input, FlowPath.class);
961 allFlows.add(flowPath);
962 }
963 kryoFactory.deleteKryo(kryo);
964
965 return allFlows;
966 }
967
968 /**
Pavlin Radoslavov379c9042013-11-26 15:40:49 -0800969 * Get a Flow for a given Flow ID.
970 *
971 * @param flowId the Flow ID of the Flow to get.
972 * @return the Flow if found, otherwise null.
973 */
974 @Override
975 public FlowPath getFlow(FlowId flowId) {
976 byte[] valueBytes = mapFlow.get(flowId.value());
977 if (valueBytes == null)
978 return null;
979
980 Kryo kryo = kryoFactory.newKryo();
981 //
982 // Decode the value
983 //
984 Input input = new Input(valueBytes);
985 FlowPath flowPath = kryo.readObject(input, FlowPath.class);
986 kryoFactory.deleteKryo(kryo);
987
988 return flowPath;
989 }
990
991 /**
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700992 * Send a notification that a Flow is added.
993 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700994 * @param flowPath the Flow that is added.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700995 */
996 @Override
997 public void notificationSendFlowAdded(FlowPath flowPath) {
998 //
999 // Encode the value
1000 //
1001 byte[] buffer = new byte[MAX_BUFFER_SIZE];
1002 Kryo kryo = kryoFactory.newKryo();
1003 Output output = new Output(buffer, -1);
1004 kryo.writeObject(output, flowPath);
1005 byte[] valueBytes = output.toBytes();
1006 kryoFactory.deleteKryo(kryo);
1007
1008 //
1009 // Put the entry:
1010 // - Key : Flow ID (Long)
1011 // - Value : Serialized Flow (byte[])
1012 //
1013 mapFlow.putAsync(flowPath.flowId().value(), valueBytes);
1014 }
1015
1016 /**
1017 * Send a notification that a Flow is removed.
1018 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001019 * @param flowId the Flow ID of the Flow that is removed.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -07001020 */
1021 @Override
1022 public void notificationSendFlowRemoved(FlowId flowId) {
1023 //
1024 // Remove the entry:
1025 // - Key : Flow ID (Long)
1026 // - Value : Serialized Flow (byte[])
1027 //
1028 mapFlow.removeAsync(flowId.value());
1029 }
1030
1031 /**
1032 * Send a notification that a Flow is updated.
1033 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001034 * @param flowPath the Flow that is updated.
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -07001035 */
1036 @Override
1037 public void notificationSendFlowUpdated(FlowPath flowPath) {
1038 // NOTE: Adding an entry with an existing key automatically updates it
1039 notificationSendFlowAdded(flowPath);
1040 }
1041
1042 /**
1043 * Send a notification that all Flows are removed.
1044 */
1045 @Override
1046 public void notificationSendAllFlowsRemoved() {
1047 //
1048 // Remove all entries
1049 // NOTE: We remove the entries one-by-one so the per-entry
1050 // notifications will be delivered.
1051 //
1052 // mapFlow.clear();
1053 Set<Long> keySet = mapFlow.keySet();
1054 for (Long key : keySet) {
1055 mapFlow.removeAsync(key);
1056 }
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -07001057 }
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -07001058
1059 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001060 * Get all Flow Entries that are currently in the datagrid.
1061 *
1062 * @return all Flow Entries that are currently in the datagrid.
1063 */
1064 @Override
1065 public Collection<FlowEntry> getAllFlowEntries() {
1066 Collection<FlowEntry> allFlowEntries = new LinkedList<FlowEntry>();
1067
1068 //
1069 // Get all current entries
1070 //
1071 Collection<byte[]> values = mapFlowEntry.values();
1072 Kryo kryo = kryoFactory.newKryo();
1073 for (byte[] valueBytes : values) {
1074 //
1075 // Decode the value
1076 //
1077 Input input = new Input(valueBytes);
1078 FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
1079 allFlowEntries.add(flowEntry);
1080 }
1081 kryoFactory.deleteKryo(kryo);
1082
1083 return allFlowEntries;
1084 }
1085
1086 /**
Pavlin Radoslavov379c9042013-11-26 15:40:49 -08001087 * Get a Flow Entry for a given Flow Entry ID.
1088 *
1089 * @param flowEntryId the Flow Entry ID of the Flow Entry to get.
1090 * @return the Flow Entry if found, otherwise null.
1091 */
1092 @Override
1093 public FlowEntry getFlowEntry(FlowEntryId flowEntryId) {
1094 byte[] valueBytes = mapFlowEntry.get(flowEntryId.value());
1095 if (valueBytes == null)
1096 return null;
1097
1098 Kryo kryo = kryoFactory.newKryo();
1099 //
1100 // Decode the value
1101 //
1102 Input input = new Input(valueBytes);
1103 FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
1104 kryoFactory.deleteKryo(kryo);
1105
1106 return flowEntry;
1107 }
1108
1109 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001110 * Send a notification that a FlowEntry is added.
1111 *
1112 * @param flowEntry the FlowEntry that is added.
1113 */
1114 @Override
1115 public void notificationSendFlowEntryAdded(FlowEntry flowEntry) {
1116 //
1117 // Encode the value
1118 //
1119 byte[] buffer = new byte[MAX_BUFFER_SIZE];
1120 Kryo kryo = kryoFactory.newKryo();
1121 Output output = new Output(buffer, -1);
1122 kryo.writeObject(output, flowEntry);
1123 byte[] valueBytes = output.toBytes();
1124 kryoFactory.deleteKryo(kryo);
1125
1126 //
1127 // Put the entry:
1128 // - Key : FlowEntry ID (Long)
1129 // - Value : Serialized FlowEntry (byte[])
1130 //
1131 mapFlowEntry.putAsync(flowEntry.flowEntryId().value(), valueBytes);
1132 }
1133
1134 /**
1135 * Send a notification that a FlowEntry is removed.
1136 *
1137 * @param flowEntryId the FlowEntry ID of the FlowEntry that is removed.
1138 */
1139 @Override
1140 public void notificationSendFlowEntryRemoved(FlowEntryId flowEntryId) {
1141 //
1142 // Remove the entry:
1143 // - Key : FlowEntry ID (Long)
1144 // - Value : Serialized FlowEntry (byte[])
1145 //
1146 mapFlowEntry.removeAsync(flowEntryId.value());
1147 }
1148
1149 /**
1150 * Send a notification that a FlowEntry is updated.
1151 *
1152 * @param flowEntry the FlowEntry that is updated.
1153 */
1154 @Override
1155 public void notificationSendFlowEntryUpdated(FlowEntry flowEntry) {
1156 // NOTE: Adding an entry with an existing key automatically updates it
1157 notificationSendFlowEntryAdded(flowEntry);
1158 }
1159
1160 /**
1161 * Send a notification that all Flow Entries are removed.
1162 */
1163 @Override
1164 public void notificationSendAllFlowEntriesRemoved() {
1165 //
1166 // Remove all entries
1167 // NOTE: We remove the entries one-by-one so the per-entry
1168 // notifications will be delivered.
1169 //
1170 // mapFlowEntry.clear();
1171 Set<Long> keySet = mapFlowEntry.keySet();
1172 for (Long key : keySet) {
1173 mapFlowEntry.removeAsync(key);
1174 }
1175 }
1176
1177 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001178 * Get all Flow IDs that are currently in the datagrid.
1179 *
1180 * @return all Flow IDs that are currently in the datagrid.
1181 */
1182 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001183 public Collection<Pair<FlowId, Dpid>> getAllFlowIds() {
1184 Collection<Pair<FlowId, Dpid>> allFlowIds =
1185 new LinkedList<Pair<FlowId, Dpid>>();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001186
1187 //
1188 // Get all current entries
1189 //
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001190 Kryo kryo = kryoFactory.newKryo();
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001191 for (Map.Entry<Long, byte[]> entry : mapFlowId.entrySet()) {
1192 Long key = entry.getKey();
1193 byte[] valueBytes = entry.getValue();
1194
1195 FlowId flowId = new FlowId(key);
1196
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001197 //
1198 // Decode the value
1199 //
1200 Input input = new Input(valueBytes);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001201 Dpid dpid = kryo.readObject(input, Dpid.class);
1202
1203 Pair<FlowId, Dpid> pair = new Pair(flowId, dpid);
1204 allFlowIds.add(pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001205 }
1206 kryoFactory.deleteKryo(kryo);
1207
1208 return allFlowIds;
1209 }
1210
1211 /**
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001212 * Get all Flow Entry IDs that are currently in the datagrid.
1213 *
1214 * @return all Flow Entry IDs that ae currently in the datagrid.
1215 */
1216 @Override
1217 public Collection<Pair<FlowEntryId, Dpid>> getAllFlowEntryIds() {
1218 Collection<Pair<FlowEntryId, Dpid>> allFlowEntryIds =
1219 new LinkedList<Pair<FlowEntryId, Dpid>>();
1220
1221 //
1222 // Get all current entries
1223 //
1224 Kryo kryo = kryoFactory.newKryo();
1225 for (Map.Entry<Long, byte[]> entry : mapFlowEntryId.entrySet()) {
1226 Long key = entry.getKey();
1227 byte[] valueBytes = entry.getValue();
1228
1229 FlowEntryId flowEntryId = new FlowEntryId(key);
1230
1231 //
1232 // Decode the value
1233 //
1234 Input input = new Input(valueBytes);
1235 Dpid dpid = kryo.readObject(input, Dpid.class);
1236
1237 Pair<FlowEntryId, Dpid> pair = new Pair(flowEntryId, dpid);
1238 allFlowEntryIds.add(pair);
1239 }
1240 kryoFactory.deleteKryo(kryo);
1241
1242 return allFlowEntryIds;
1243 }
1244
1245 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001246 * Send a notification that a FlowId is added.
1247 *
1248 * @param flowId the FlowId that is added.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001249 * @param dpid the Source Switch Dpid.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001250 */
1251 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001252 public void notificationSendFlowIdAdded(FlowId flowId, Dpid dpid) {
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001253 //
1254 // Encode the value
1255 //
1256 byte[] buffer = new byte[MAX_BUFFER_SIZE];
1257 Kryo kryo = kryoFactory.newKryo();
1258 Output output = new Output(buffer, -1);
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001259 kryo.writeObject(output, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001260 byte[] valueBytes = output.toBytes();
1261 kryoFactory.deleteKryo(kryo);
1262
1263 //
1264 // Put the entry:
1265 // - Key : FlowId (Long)
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001266 // - Value : Serialized Switch Dpid (byte[])
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001267 //
1268 mapFlowId.putAsync(flowId.value(), valueBytes);
1269 }
1270
1271 /**
1272 * Send a notification that a FlowId is removed.
1273 *
1274 * @param flowId the FlowId that is removed.
1275 */
1276 @Override
1277 public void notificationSendFlowIdRemoved(FlowId flowId) {
1278 //
1279 // Remove the entry:
1280 // - Key : FlowId (Long)
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001281 // - Value : Serialized Switch Dpid (byte[])
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001282 //
1283 mapFlowId.removeAsync(flowId.value());
1284 }
1285
1286 /**
1287 * Send a notification that a FlowId is updated.
1288 *
1289 * @param flowId the FlowId that is updated.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001290 * @param dpid the Source Switch Dpid.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001291 */
1292 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001293 public void notificationSendFlowIdUpdated(FlowId flowId, Dpid dpid) {
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001294 // NOTE: Adding an entry with an existing key automatically updates it
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001295 notificationSendFlowIdAdded(flowId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001296 }
1297
1298 /**
1299 * Send a notification that all Flow IDs are removed.
1300 */
1301 @Override
1302 public void notificationSendAllFlowIdsRemoved() {
1303 //
1304 // Remove all entries
1305 // NOTE: We remove the entries one-by-one so the per-entry
1306 // notifications will be delivered.
1307 //
1308 // mapFlowId.clear();
1309 Set<Long> keySet = mapFlowId.keySet();
1310 for (Long key : keySet) {
1311 mapFlowId.removeAsync(key);
1312 }
1313 }
1314
1315 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001316 * Send a notification that a FlowEntryId is added.
1317 *
1318 * @param flowEntryId the FlowEntryId that is added.
1319 * @param dpid the Switch Dpid.
1320 */
1321 @Override
1322 public void notificationSendFlowEntryIdAdded(FlowEntryId flowEntryId,
1323 Dpid dpid) {
1324 //
1325 // Encode the value
1326 //
1327 byte[] buffer = new byte[MAX_BUFFER_SIZE];
1328 Kryo kryo = kryoFactory.newKryo();
1329 Output output = new Output(buffer, -1);
1330 kryo.writeObject(output, dpid);
1331 byte[] valueBytes = output.toBytes();
1332 kryoFactory.deleteKryo(kryo);
1333
1334 //
1335 // Put the entry:
1336 // - Key : FlowEntryId (Long)
1337 // - Value : Serialized Switch Dpid (byte[])
1338 //
1339 mapFlowEntryId.putAsync(flowEntryId.value(), valueBytes);
1340 }
1341
1342 /**
1343 * Send a notification that a FlowEntryId is removed.
1344 *
1345 * @param flowEntryId the FlowEntryId that is removed.
1346 */
1347 @Override
1348 public void notificationSendFlowEntryIdRemoved(FlowEntryId flowEntryId) {
1349 //
1350 // Remove the entry:
1351 // - Key : FlowEntryId (Long)
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001352 // - Value : Serialized Switch Dpid (byte[])
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001353 //
1354 mapFlowEntryId.removeAsync(flowEntryId.value());
1355 }
1356
1357 /**
1358 * Send a notification that a FlowEntryId is updated.
1359 *
1360 * @param flowEntryId the FlowEntryId that is updated.
1361 * @param dpid the Switch Dpid.
1362 */
1363 @Override
1364 public void notificationSendFlowEntryIdUpdated(FlowEntryId flowEntryId,
1365 Dpid dpid) {
1366 // NOTE: Adding an entry with an existing key automatically updates it
1367 notificationSendFlowEntryIdAdded(flowEntryId, dpid);
1368 }
1369
1370 /**
1371 * Send a notification that all Flow Entry IDs are removed.
1372 */
1373 @Override
1374 public void notificationSendAllFlowEntryIdsRemoved() {
1375 //
1376 // Remove all entries
1377 // NOTE: We remove the entries one-by-one so the per-entry
1378 // notifications will be delivered.
1379 //
1380 // mapFlowEntryId.clear();
1381 Set<Long> keySet = mapFlowEntryId.keySet();
1382 for (Long key : keySet) {
1383 mapFlowEntryId.removeAsync(key);
1384 }
1385 }
1386
1387 /**
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -07001388 * Get all Topology Elements that are currently in the datagrid.
1389 *
1390 * @return all Topology Elements that are currently in the datagrid.
1391 */
1392 @Override
1393 public Collection<TopologyElement> getAllTopologyElements() {
1394 Collection<TopologyElement> allTopologyElements =
1395 new LinkedList<TopologyElement>();
1396
1397 //
1398 // Get all current entries
1399 //
1400 Collection<byte[]> values = mapTopology.values();
1401 Kryo kryo = kryoFactory.newKryo();
1402 for (byte[] valueBytes : values) {
1403 //
1404 // Decode the value
1405 //
1406 Input input = new Input(valueBytes);
1407 TopologyElement topologyElement =
1408 kryo.readObject(input, TopologyElement.class);
1409 allTopologyElements.add(topologyElement);
1410 }
1411 kryoFactory.deleteKryo(kryo);
1412
1413 return allTopologyElements;
1414 }
1415
1416 /**
1417 * Send a notification that a Topology Element is added.
1418 *
1419 * @param topologyElement the Topology Element that is added.
1420 */
1421 @Override
1422 public void notificationSendTopologyElementAdded(TopologyElement topologyElement) {
1423 //
1424 // Encode the value
1425 //
1426 byte[] buffer = new byte[MAX_BUFFER_SIZE];
1427 Kryo kryo = kryoFactory.newKryo();
1428 Output output = new Output(buffer, -1);
1429 kryo.writeObject(output, topologyElement);
1430 byte[] valueBytes = output.toBytes();
1431 kryoFactory.deleteKryo(kryo);
1432
1433 //
1434 // Put the entry:
1435 // - Key : TopologyElement ID (String)
1436 // - Value : Serialized TopologyElement (byte[])
1437 //
1438 mapTopology.putAsync(topologyElement.elementId(), valueBytes);
1439 }
1440
1441 /**
1442 * Send a notification that a Topology Element is removed.
1443 *
1444 * @param topologyElement the Topology Element that is removed.
1445 */
1446 @Override
1447 public void notificationSendTopologyElementRemoved(TopologyElement topologyElement) {
1448 //
1449 // Remove the entry:
1450 // - Key : TopologyElement ID (String)
1451 // - Value : Serialized TopologyElement (byte[])
1452 //
1453 mapTopology.removeAsync(topologyElement.elementId());
1454 }
1455
1456 /**
1457 * Send a notification that a Topology Element is updated.
1458 *
1459 * @param topologyElement the Topology Element that is updated.
1460 */
1461 @Override
1462 public void notificationSendTopologyElementUpdated(TopologyElement topologyElement) {
1463 // NOTE: Adding an entry with an existing key automatically updates it
1464 notificationSendTopologyElementAdded(topologyElement);
1465 }
1466
1467 /**
1468 * Send a notification that all Topology Elements are removed.
1469 */
1470 @Override
1471 public void notificationSendAllTopologyElementsRemoved() {
1472 //
1473 // Remove all entries
1474 // NOTE: We remove the entries one-by-one so the per-entry
1475 // notifications will be delivered.
1476 //
1477 // mapTopology.clear();
1478 Set<String> keySet = mapTopology.keySet();
1479 for (String key : keySet) {
1480 mapTopology.removeAsync(key);
1481 }
1482 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -08001483
Jonathan Hart18ad55c2013-11-11 22:49:55 -08001484 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -08001485 public void sendPacketOutNotification(PacketOutNotification packetOutNotification) {
1486 packetOutMap.putAsync(packetOutNotification, dummyByte, 1L, TimeUnit.MILLISECONDS);
Jonathan Hart18ad55c2013-11-11 22:49:55 -08001487 }
Jonathan Hart7804bea2014-01-07 10:50:52 -08001488
1489 @Override
1490 public void sendArpReplyNotification(ArpReplyNotification arpReply) {
1491 arpReplyMap.putAsync(arpReply, dummyByte, 1L, TimeUnit.MILLISECONDS);
1492 }
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -07001493}