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