blob: 470148b627f66bd9c2c55e1178760905944d31f5 [file] [log] [blame]
Lee Yongjae7c27bb42017-11-17 12:00:45 +09001/*
2 * Copyright 2017-present Open Networking Foundation
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
17package org.onosproject.simplefabric;
18
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
21import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
22import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
23import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
24import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.apache.felix.scr.annotations.Service;
30import org.onlab.packet.ARP;
31import org.onlab.packet.Ethernet;
32import org.onlab.packet.Ip4Address;
33import org.onlab.packet.Ip6Address;
34import org.onlab.packet.IpAddress;
35import org.onlab.packet.IpPrefix;
36import org.onlab.packet.IPv6;
37import org.onlab.packet.MacAddress;
38import org.onlab.packet.VlanId;
39import org.onlab.packet.ndp.NeighborSolicitation;
40import org.onosproject.app.ApplicationService;
41import org.onosproject.core.ApplicationId;
42import org.onosproject.core.CoreService;
43import org.onosproject.component.ComponentService;
44import org.onosproject.event.ListenerRegistry;
45import org.onosproject.net.intf.Interface;
46import org.onosproject.net.intf.InterfaceService;
47import org.onosproject.net.intf.InterfaceListener;
48import org.onosproject.net.intf.InterfaceEvent;
49import org.onosproject.net.config.ConfigFactory;
50import org.onosproject.net.config.NetworkConfigEvent;
51import org.onosproject.net.config.NetworkConfigListener;
52import org.onosproject.net.config.NetworkConfigRegistry;
53import org.onosproject.net.config.NetworkConfigService;
54import org.onosproject.net.config.basics.SubjectFactories;
55import org.onosproject.net.ConnectPoint;
56import org.onosproject.net.device.DeviceEvent;
57import org.onosproject.net.device.DeviceListener;
58import org.onosproject.net.device.DeviceService;
59import org.onosproject.net.flow.DefaultTrafficTreatment;
60import org.onosproject.net.flow.TrafficTreatment;
61import org.onosproject.net.Host;
62import org.onosproject.net.host.HostService;
63import org.onosproject.net.host.HostListener;
64import org.onosproject.net.host.HostEvent;
65import org.onosproject.net.packet.PacketService;
66import org.onosproject.net.packet.DefaultOutboundPacket;
67import org.onosproject.net.packet.OutboundPacket;
68import org.slf4j.Logger;
69import org.slf4j.LoggerFactory;
70
71import java.io.OutputStream;
72import java.io.PrintStream;
73import java.nio.ByteBuffer;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090074import java.util.HashSet;
75import java.util.Collection;
76import java.util.Set;
77import java.util.Map;
78
79import static org.onosproject.simplefabric.RouteTools.createBinaryString;
80
81
82/**
83 * Reactive routing configuration manager.
84 */
85@Component(immediate = true)
86@Service
87public class SimpleFabricManager extends ListenerRegistry<SimpleFabricEvent, SimpleFabricListener>
88 implements SimpleFabricService {
89
90 private final Logger log = LoggerFactory.getLogger(getClass());
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected CoreService coreService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected ApplicationService applicationService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected NetworkConfigService configService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected NetworkConfigRegistry registry;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected DeviceService deviceService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected InterfaceService interfaceService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected HostService hostService;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected PacketService packetService;
115
116 // compoents to be activated within SimpleFabric
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected ComponentService componentService;
119
120 // SimpleFabric variables
121 private ApplicationId appId = null;
122
123 // l2 broadcast networks
124 private Set<L2Network> l2Networks = new HashSet<>();
125 private Set<Interface> l2NetworkInterfaces = new HashSet<>();
126
127 // Subnet table
128 private Set<IpSubnet> ipSubnets = new HashSet<>();
129 private InvertedRadixTree<IpSubnet> ip4SubnetTable =
130 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
131 private InvertedRadixTree<IpSubnet> ip6SubnetTable =
132 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
133
134 // Border Route table
135 private Set<Route> borderRoutes = new HashSet<>();
136 private InvertedRadixTree<Route> ip4BorderRouteTable =
137 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
138 private InvertedRadixTree<Route> ip6BorderRouteTable =
139 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
140
141 // VirtialGateway
142 private Map<IpAddress, MacAddress> virtualGatewayIpMacMap = Maps.newConcurrentMap();
143
144 // Refresh monitor thread
145 private Object refreshMonitor = new Object();
146 private boolean doRefresh = false;
147 private boolean doFlush = false;
148 private InternalRefreshThread refreshThread;
149
150 // Listener for Service Events
151 private final InternalNetworkConfigListener configListener = new InternalNetworkConfigListener();
152 private final InternalDeviceListener deviceListener = new InternalDeviceListener();
153 private final InternalHostListener hostListener = new InternalHostListener();
154 private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
155
156 private ConfigFactory<ApplicationId, SimpleFabricConfig> simpleFabricConfigFactory =
157 new ConfigFactory<ApplicationId, SimpleFabricConfig>(
158 SubjectFactories.APP_SUBJECT_FACTORY,
159 SimpleFabricConfig.class, SimpleFabricConfig.KEY) {
160 @Override
161 public SimpleFabricConfig createConfig() {
162 return new SimpleFabricConfig();
163 }
164 };
165
166 @Activate
167 public void activate() {
168 log.info("simple fabric starting");
169
170 if (appId == null) {
171 appId = coreService.registerApplication(APP_ID);
172 }
173
174 // initial refresh
175 refresh();
176
177 configService.addListener(configListener);
178 registry.registerConfigFactory(simpleFabricConfigFactory);
179 deviceService.addListener(deviceListener);
180 hostService.addListener(hostListener);
181
182 componentService.activate(appId, SimpleFabricNeighbour.class.getName());
183 componentService.activate(appId, SimpleFabricReactiveRouting.class.getName());
184 if (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) {
185 componentService.activate(appId, SimpleFabricL2Forward.class.getName());
186 }
187
188 refreshThread = new InternalRefreshThread();
189 refreshThread.start();
190
191 log.info("simple fabric started");
192 }
193
194 @Deactivate
195 public void deactivate() {
196 log.info("simple fabric stopping");
197
198 componentService.deactivate(appId, SimpleFabricNeighbour.class.getName());
199 componentService.deactivate(appId, SimpleFabricReactiveRouting.class.getName());
200 if (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) {
201 componentService.deactivate(appId, SimpleFabricL2Forward.class.getName());
202 }
203
204 deviceService.removeListener(deviceListener);
205 hostService.removeListener(hostListener);
206 registry.unregisterConfigFactory(simpleFabricConfigFactory);
207 configService.removeListener(configListener);
208
209 refreshThread.stop();
210 refreshThread = null;
211
212 log.info("simple fabric stopped");
213 }
214
215 // Set up from configuration
216 // returns found dirty and refresh listners are called (true) or not (false)
217 private boolean refresh() {
218 log.debug("simple fabric refresh");
219 boolean dirty = false;
220
221 SimpleFabricConfig config = configService.getConfig(coreService.registerApplication(APP_ID),
222 SimpleFabricConfig.class);
223 if (config == null) {
224 log.debug("No reactive routing config available!");
225 return false;
226 }
227
228 // l2Networks
229 Set<L2Network> newL2Networks = new HashSet<>();
230 Set<Interface> newL2NetworkInterfaces = new HashSet<>();
231 for (L2Network newL2NetworkConfig : config.getL2Networks()) {
232 L2Network newL2Network = L2Network.of(newL2NetworkConfig);
233
234 // fill up interfaces and Hosts with active port only
235 for (String ifaceName : newL2NetworkConfig.interfaceNames()) {
236 Interface iface = getInterfaceByName(ifaceName);
237 if (iface != null && deviceService.isAvailable(iface.connectPoint().deviceId())) {
238 newL2Network.addInterface(iface);
239 newL2NetworkInterfaces.add(iface);
240 }
241 }
242 for (Host host : hostService.getHosts()) {
243 // consider host with ip only
244 if (!host.ipAddresses().isEmpty()) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900245 Interface iface = findAvailableDeviceHostInterface(host);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900246 if (iface != null && newL2Network.contains(iface)) {
247 newL2Network.addHost(host);
248 }
249 }
250 }
251 newL2Network.setDirty(true);
252
253 // update newL2Network's dirty flags if same entry already exists
254 for (L2Network prevL2Network : l2Networks) {
255 if (prevL2Network.equals(newL2Network)) {
256 newL2Network.setDirty(prevL2Network.dirty());
257 break;
258 }
259 }
260 newL2Networks.add(newL2Network);
261 }
262 if (!l2Networks.equals(newL2Networks)) {
263 l2Networks = newL2Networks;
264 dirty = true;
265 }
266 if (!l2NetworkInterfaces.equals(newL2NetworkInterfaces)) {
267 l2NetworkInterfaces = newL2NetworkInterfaces;
268 dirty = true;
269 }
270
271 // ipSubnets
272 Set<IpSubnet> newIpSubnets = config.ipSubnets();
273 InvertedRadixTree<IpSubnet> newIp4SubnetTable =
274 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
275 InvertedRadixTree<IpSubnet> newIp6SubnetTable =
276 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
277 Map<IpAddress, MacAddress> newVirtualGatewayIpMacMap = Maps.newConcurrentMap();
278 for (IpSubnet subnet : newIpSubnets) {
279 if (subnet.ipPrefix().isIp4()) {
280 newIp4SubnetTable.put(createBinaryString(subnet.ipPrefix()), subnet);
281 } else {
282 newIp6SubnetTable.put(createBinaryString(subnet.ipPrefix()), subnet);
283 }
284 newVirtualGatewayIpMacMap.put(subnet.gatewayIp(), subnet.gatewayMac());
285 }
286 if (!ipSubnets.equals(newIpSubnets)) {
287 ipSubnets = newIpSubnets;
288 ip4SubnetTable = newIp4SubnetTable;
289 ip6SubnetTable = newIp6SubnetTable;
290 dirty = true;
291 }
292 if (!virtualGatewayIpMacMap.equals(newVirtualGatewayIpMacMap)) {
293 virtualGatewayIpMacMap = newVirtualGatewayIpMacMap;
294 dirty = true;
295 }
296
297 // borderRoutes config handling
298 Set<Route> newBorderRoutes = config.borderRoutes();
299 if (!borderRoutes.equals(newBorderRoutes)) {
300 InvertedRadixTree<Route> newIp4BorderRouteTable =
301 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
302 InvertedRadixTree<Route> newIp6BorderRouteTable =
303 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
304 for (Route route : newBorderRoutes) {
305 if (route.prefix().isIp4()) {
306 newIp4BorderRouteTable.put(createBinaryString(route.prefix()), route);
307 } else {
308 newIp6BorderRouteTable.put(createBinaryString(route.prefix()), route);
309 }
310 }
311 borderRoutes = newBorderRoutes;
312 ip4BorderRouteTable = newIp4BorderRouteTable;
313 ip6BorderRouteTable = newIp6BorderRouteTable;
314 dirty = true;
315 }
316
317 // notify to SimpleFabric listeners
318 if (dirty) {
319 log.info("simple fabric refresh; notify events");
320 process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_UPDATED, "updated"));
321 }
322 return dirty;
323 }
324
325 private Interface getInterfaceByName(String interfaceName) {
326 Interface intf = interfaceService.getInterfaces().stream()
327 .filter(iface -> iface.name().equals(interfaceName))
328 .findFirst()
329 .orElse(null);
330 if (intf == null) {
331 log.warn("simple fabric unknown interface name: {}", interfaceName);
332 }
333 return intf;
334 }
335
336 @Override
337 public ApplicationId getAppId() {
338 if (appId == null) {
339 appId = coreService.registerApplication(APP_ID);
340 }
341 return appId;
342 }
343
344 @Override
345 public Collection<L2Network> getL2Networks() {
346 return ImmutableSet.copyOf(l2Networks);
347 }
348
349 @Override
350 public Set<IpSubnet> getIpSubnets() {
351 return ImmutableSet.copyOf(ipSubnets);
352 }
353
354 @Override
355 public Set<Route> getBorderRoutes() {
356 return ImmutableSet.copyOf(borderRoutes);
357 }
358
359 @Override
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900360 public boolean isVMac(MacAddress mac) {
361 return virtualGatewayIpMacMap.containsValue(mac);
362 }
363
364 @Override
365 public boolean isL2NetworkInterface(Interface intf) {
366 return l2NetworkInterfaces.contains(intf);
367 }
368
369 @Override
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900370 public MacAddress findVMacForIp(IpAddress ip) {
371 return virtualGatewayIpMacMap.get(ip);
372 }
373
374 @Override
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900375 public L2Network findL2Network(ConnectPoint port, VlanId vlanId) {
376 for (L2Network l2Network : l2Networks) {
377 if (l2Network.contains(port, vlanId)) {
378 return l2Network;
379 }
380 }
381 return null;
382 }
383
384 @Override
385 public L2Network findL2Network(String name) {
386 for (L2Network l2Network : l2Networks) {
387 if (l2Network.name().equals(name)) {
388 return l2Network;
389 }
390 }
391 return null;
392 }
393
394 @Override
395 public IpSubnet findIpSubnet(IpAddress ip) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900396 if (ip.isIp4()) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900397 return ip4SubnetTable.getValueForLongestKeyPrefixing(
398 createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900399 } else {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900400 return ip6SubnetTable.getValueForLongestKeyPrefixing(
401 createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900402 }
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900403 }
404
405 @Override
406 public Route findBorderRoute(IpAddress ip) {
407 // ASSUME: ipAddress is out of ipSubnet
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900408 if (ip.isIp4()) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900409 return ip4BorderRouteTable.getValueForLongestKeyPrefixing(
410 createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900411 } else {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900412 return ip6BorderRouteTable.getValueForLongestKeyPrefixing(
413 createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900414 }
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900415 }
416
417
418 @Override
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900419 public Interface findHostInterface(Host host) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900420 return interfaceService.getInterfaces().stream()
421 .filter(iface -> iface.connectPoint().equals(host.location()) &&
422 iface.vlan().equals(host.vlan()))
423 .findFirst()
424 .orElse(null);
425 }
426
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900427 private Interface findAvailableDeviceHostInterface(Host host) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900428 return interfaceService.getInterfaces().stream()
429 .filter(iface -> iface.connectPoint().equals(host.location()) &&
430 iface.vlan().equals(host.vlan()))
431 .filter(iface -> deviceService.isAvailable(iface.connectPoint().deviceId()))
432 .findFirst()
433 .orElse(null);
434 }
435
436 @Override
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900437 public boolean requestMac(IpAddress ip) {
438 IpSubnet ipSubnet = findIpSubnet(ip);
439 if (ipSubnet == null) {
440 log.warn("simple fabric request mac failed for unknown IpSubnet: {}", ip);
441 return false;
442 }
443 L2Network l2Network = findL2Network(ipSubnet.l2NetworkName());
444 if (l2Network == null) {
445 log.warn("simple fabric request mac failed for unknown l2Network name {}: {}",
446 ipSubnet.l2NetworkName(), ip);
447 return false;
448 }
449 log.debug("simple fabric send request mac L2Network {}: {}", l2Network.name(), ip);
450 for (Interface iface : l2Network.interfaces()) {
451 Ethernet neighbourReq;
452 if (ip.isIp4()) {
453 neighbourReq = ARP.buildArpRequest(ipSubnet.gatewayMac().toBytes(),
454 ipSubnet.gatewayIp().toOctets(),
455 ip.toOctets(),
456 iface.vlan().toShort());
457 } else {
458 byte[] soliciteIp = IPv6.getSolicitNodeAddress(ip.toOctets());
459 neighbourReq = NeighborSolicitation.buildNdpSolicit(
460 ip.toOctets(),
461 ipSubnet.gatewayIp().toOctets(),
462 soliciteIp,
463 ipSubnet.gatewayMac().toBytes(),
464 IPv6.getMCastMacAddress(soliciteIp),
465 iface.vlan());
466 }
467 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
468 .setOutput(iface.connectPoint().port()).build();
469 OutboundPacket packet = new DefaultOutboundPacket(iface.connectPoint().deviceId(),
470 treatment, ByteBuffer.wrap(neighbourReq.serialize()));
471 packetService.emit(packet);
472 }
473 return true;
474 }
475
476 @Override
477 public void dumpToStream(String subject, OutputStream out) {
478 SimpleFabricEvent event = new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_DUMP, subject, out);
479 dump(event.subject(), event.out()); // dump in itself
480 process(event); // dump in sub modules
481 }
482
483 // Dump handler
484 protected void dump(String subject, PrintStream out) {
Ray Milkey2ff67162018-01-22 10:14:19 -0800485 if ("show".equals(subject)) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900486 out.println("Static Configuration Flag:");
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900487 out.println(" ALLOW_IPV6="
488 + SimpleFabricService.ALLOW_IPV6);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900489 out.println(" ALLOW_ETH_ADDRESS_SELECTOR="
490 + SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR);
491 out.println(" REACTIVE_SINGLE_TO_SINGLE="
492 + SimpleFabricService.REACTIVE_SINGLE_TO_SINGLE);
493 out.println(" REACTIVE_ALLOW_LINK_CP="
494 + SimpleFabricService.REACTIVE_ALLOW_LINK_CP);
495 out.println(" REACTIVE_HASHED_PATH_SELECTION="
496 + SimpleFabricService.REACTIVE_HASHED_PATH_SELECTION);
497 out.println(" REACTIVE_MATCH_IP_PROTO="
498 + SimpleFabricService.REACTIVE_MATCH_IP_PROTO);
499 out.println("");
500 out.println("SimpleFabricAppId:");
501 out.println(" " + getAppId());
502 out.println("");
503 out.println("l2Networks:");
504 for (L2Network l2Network : getL2Networks()) {
505 out.println(" " + l2Network);
506 }
507 out.println("");
508 out.println("ipSubnets:");
509 for (IpSubnet ipSubnet : getIpSubnets()) {
510 out.println(" " + ipSubnet);
511 }
512 out.println("");
513 out.println("borderRoutes:");
514 for (Route route : getBorderRoutes()) {
515 out.println(" " + route);
516 }
517 }
518 }
519
520 // Refresh action thread and notifier
521
522 private class InternalRefreshThread extends Thread {
523 public void run() {
524 while (true) {
525 boolean doRefreshMarked = false;
526 boolean doFlushMarked = false;
527 synchronized (refreshMonitor) {
528 if (!doRefresh && !doFlush) {
529 try {
530 refreshMonitor.wait(IDLE_INTERVAL_MSEC);
531 } catch (InterruptedException e) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800532 log.warn("run thread interrupted", e);
533 Thread.currentThread().interrupt();
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900534 }
535 }
536 doRefreshMarked = doRefresh;
537 doRefresh = false;
538 doFlushMarked = doFlush;
539 doFlush = false;
540 }
541 if (doRefreshMarked) {
542 try {
543 refresh();
544 } catch (Exception e) {
545 log.warn("simple fabric refresh failed: exception={}", e);
546 }
547 }
548 if (doFlushMarked) {
549 try {
550 log.info("simple fabric flush execute");
551 process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_FLUSH, "flush"));
552 } catch (Exception e) {
553 log.warn("simple fabric flush failed: exception={}", e);
554 }
555 }
556 if (!doRefreshMarked && !doFlushMarked) {
557 try {
558 if (!refresh()) {
559 process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_IDLE, "idle"));
560 }
561 } catch (Exception e) {
562 log.warn("simple fabric idle failed: exception={}", e);
563 }
564 }
565 }
566 }
567 }
568
569 @Override
570 public void triggerRefresh() {
571 synchronized (refreshMonitor) {
572 doRefresh = true;
573 refreshMonitor.notifyAll();
574 }
575 }
576
577 @Override
578 public void triggerFlush() {
579 synchronized (refreshMonitor) {
580 doFlush = true;
581 refreshMonitor.notifyAll();
582 }
583 }
584
585 // Service Listeners
586
587 private class InternalNetworkConfigListener implements NetworkConfigListener {
588 @Override
589 public void event(NetworkConfigEvent event) {
590 switch (event.type()) {
591 case CONFIG_REGISTERED:
592 case CONFIG_UNREGISTERED:
593 case CONFIG_ADDED:
594 case CONFIG_UPDATED:
595 case CONFIG_REMOVED:
596 if (event.configClass().equals(SimpleFabricConfig.class)) {
597 triggerRefresh();
598 }
599 break;
600 default:
601 break;
602 }
603 }
604 }
605
606 private class InternalDeviceListener implements DeviceListener {
607 @Override
608 public void event(DeviceEvent event) {
609 switch (event.type()) {
610 case DEVICE_ADDED:
611 case DEVICE_AVAILABILITY_CHANGED:
612 case DEVICE_REMOVED:
613 case DEVICE_SUSPENDED:
614 case DEVICE_UPDATED:
615 case PORT_ADDED:
616 case PORT_REMOVED:
617 case PORT_UPDATED:
618 // case PORT_STATS_UPDATED: IGNORED
619 triggerRefresh();
620 break;
621 default:
622 break;
623 }
624 }
625 }
626
627 private class InternalHostListener implements HostListener {
628 @Override
629 public void event(HostEvent event) {
630 Host host = event.subject();
631 Host prevHost = event.prevSubject();
632 switch (event.type()) {
633 case HOST_MOVED:
634 case HOST_REMOVED:
635 case HOST_ADDED:
636 case HOST_UPDATED:
637 triggerRefresh();
638 break;
639 default:
640 break;
641 }
642 }
643 }
644
645 private class InternalInterfaceListener implements InterfaceListener {
646 @Override
647 public void event(InterfaceEvent event) {
648 Interface iface = event.subject();
649 Interface prevIface = event.prevSubject();
650 switch (event.type()) {
651 case INTERFACE_ADDED:
652 case INTERFACE_REMOVED:
653 case INTERFACE_UPDATED:
654 triggerRefresh();
655 break;
656 default:
657 break;
658 }
659 }
660 }
661
662}
663