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