blob: 7a4e5d88acdc2f910e93da1b4993ad0933d697c1 [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;
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;
Jian Lie2d87512018-08-23 17:33:05 +090067import org.onosproject.simplefabric.api.FabricNetwork;
68import org.onosproject.simplefabric.api.FabricRoute;
69import org.onosproject.simplefabric.api.FabricSubnet;
Jian Lic7efc1d2018-08-23 16:37:34 +090070import org.onosproject.simplefabric.api.SimpleFabricEvent;
71import org.onosproject.simplefabric.api.SimpleFabricListener;
72import org.onosproject.simplefabric.api.SimpleFabricService;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090073import org.slf4j.Logger;
74import org.slf4j.LoggerFactory;
75
76import java.io.OutputStream;
77import java.io.PrintStream;
78import java.nio.ByteBuffer;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090079import java.util.Collection;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080import java.util.HashSet;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090081import java.util.Map;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082import java.util.Set;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090083
Jian Li8df54a92018-08-23 17:01:31 +090084import static org.onosproject.simplefabric.api.Constants.ALLOW_ETH_ADDRESS_SELECTOR;
85import static org.onosproject.simplefabric.api.Constants.ALLOW_IPV6;
86import static org.onosproject.simplefabric.api.Constants.APP_ID;
87import static org.onosproject.simplefabric.api.Constants.IDLE_INTERVAL_MSEC;
88import static org.onosproject.simplefabric.api.Constants.REACTIVE_ALLOW_LINK_CP;
89import static org.onosproject.simplefabric.api.Constants.REACTIVE_HASHED_PATH_SELECTION;
90import static org.onosproject.simplefabric.api.Constants.REACTIVE_MATCH_IP_PROTO;
91import static org.onosproject.simplefabric.api.Constants.REACTIVE_SINGLE_TO_SINGLE;
Jian Lie2d87512018-08-23 17:33:05 +090092import static org.onosproject.simplefabric.util.RouteTools.createBinaryString;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090093
94
95/**
96 * Reactive routing configuration manager.
97 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070098@Component(immediate = true, service = SimpleFabricService.class)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090099public class SimpleFabricManager extends ListenerRegistry<SimpleFabricEvent, SimpleFabricListener>
100 implements SimpleFabricService {
101
102 private final Logger log = LoggerFactory.getLogger(getClass());
103
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900105 protected CoreService coreService;
106
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900108 protected ApplicationService applicationService;
109
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700110 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900111 protected NetworkConfigService configService;
112
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700113 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900114 protected NetworkConfigRegistry registry;
115
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900117 protected DeviceService deviceService;
118
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900120 protected InterfaceService interfaceService;
121
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900123 protected HostService hostService;
124
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900126 protected PacketService packetService;
127
128 // compoents to be activated within SimpleFabric
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700129 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900130 protected ComponentService componentService;
131
132 // SimpleFabric variables
133 private ApplicationId appId = null;
134
Jian Lie2d87512018-08-23 17:33:05 +0900135 // fabric networks
136 private Set<FabricNetwork> fabricNetworks = new HashSet<>();
137 private Set<Interface> networkInterfaces = new HashSet<>();
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900138
139 // Subnet table
Jian Lie2d87512018-08-23 17:33:05 +0900140 private Set<FabricSubnet> fabricSubnets = new HashSet<>();
141 private InvertedRadixTree<FabricSubnet> ip4SubnetTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900142 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
Jian Lie2d87512018-08-23 17:33:05 +0900143 private InvertedRadixTree<FabricSubnet> ip6SubnetTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900144 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
145
Jian Lie2d87512018-08-23 17:33:05 +0900146 // Fabric Route table
147 private Set<FabricRoute> fabricRoutes = new HashSet<>();
148 private InvertedRadixTree<FabricRoute> ip4BorderRouteTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900149 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
Jian Lie2d87512018-08-23 17:33:05 +0900150 private InvertedRadixTree<FabricRoute> ip6BorderRouteTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900151 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
152
Jian Lie2d87512018-08-23 17:33:05 +0900153 // Virtual gateway
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900154 private Map<IpAddress, MacAddress> virtualGatewayIpMacMap = Maps.newConcurrentMap();
155
156 // Refresh monitor thread
157 private Object refreshMonitor = new Object();
158 private boolean doRefresh = false;
159 private boolean doFlush = false;
160 private InternalRefreshThread refreshThread;
161
162 // Listener for Service Events
163 private final InternalNetworkConfigListener configListener = new InternalNetworkConfigListener();
164 private final InternalDeviceListener deviceListener = new InternalDeviceListener();
165 private final InternalHostListener hostListener = new InternalHostListener();
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900166
167 private ConfigFactory<ApplicationId, SimpleFabricConfig> simpleFabricConfigFactory =
168 new ConfigFactory<ApplicationId, SimpleFabricConfig>(
169 SubjectFactories.APP_SUBJECT_FACTORY,
170 SimpleFabricConfig.class, SimpleFabricConfig.KEY) {
171 @Override
172 public SimpleFabricConfig createConfig() {
173 return new SimpleFabricConfig();
174 }
175 };
176
177 @Activate
178 public void activate() {
179 log.info("simple fabric starting");
180
181 if (appId == null) {
182 appId = coreService.registerApplication(APP_ID);
183 }
184
185 // initial refresh
186 refresh();
187
188 configService.addListener(configListener);
189 registry.registerConfigFactory(simpleFabricConfigFactory);
190 deviceService.addListener(deviceListener);
191 hostService.addListener(hostListener);
192
193 componentService.activate(appId, SimpleFabricNeighbour.class.getName());
Jian Lie2d87512018-08-23 17:33:05 +0900194 componentService.activate(appId, SimpleFabricRouting.class.getName());
Jian Li8df54a92018-08-23 17:01:31 +0900195 if (ALLOW_ETH_ADDRESS_SELECTOR) {
Jian Lie2d87512018-08-23 17:33:05 +0900196 componentService.activate(appId, SimpleFabricForwarding.class.getName());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900197 }
198
199 refreshThread = new InternalRefreshThread();
200 refreshThread.start();
201
202 log.info("simple fabric started");
203 }
204
205 @Deactivate
206 public void deactivate() {
207 log.info("simple fabric stopping");
208
209 componentService.deactivate(appId, SimpleFabricNeighbour.class.getName());
Jian Lie2d87512018-08-23 17:33:05 +0900210 componentService.deactivate(appId, SimpleFabricRouting.class.getName());
Jian Li8df54a92018-08-23 17:01:31 +0900211 if (ALLOW_ETH_ADDRESS_SELECTOR) {
Jian Lie2d87512018-08-23 17:33:05 +0900212 componentService.deactivate(appId, SimpleFabricForwarding.class.getName());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900213 }
214
215 deviceService.removeListener(deviceListener);
216 hostService.removeListener(hostListener);
217 registry.unregisterConfigFactory(simpleFabricConfigFactory);
218 configService.removeListener(configListener);
219
220 refreshThread.stop();
221 refreshThread = null;
222
223 log.info("simple fabric stopped");
224 }
225
226 // Set up from configuration
Jian Lie2d87512018-08-23 17:33:05 +0900227 // returns found isDirty and refresh listeners are called (true) or not (false)
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900228 private boolean refresh() {
229 log.debug("simple fabric refresh");
230 boolean dirty = false;
231
232 SimpleFabricConfig config = configService.getConfig(coreService.registerApplication(APP_ID),
233 SimpleFabricConfig.class);
234 if (config == null) {
Yuta HIGUCHIc2bf02a2018-03-29 08:40:35 -0700235 log.debug("No simple fabric config available!");
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900236 return false;
237 }
238
Jian Lie2d87512018-08-23 17:33:05 +0900239 // fabricNetworks
240 Set<FabricNetwork> newFabricNetworks = new HashSet<>();
241 Set<Interface> newInterfaces = new HashSet<>();
242 for (FabricNetwork newFabricNetworkConfig : config.fabricNetworks()) {
243 FabricNetwork newFabricNetwork = DefaultFabricNetwork.of(newFabricNetworkConfig);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900244
245 // fill up interfaces and Hosts with active port only
Jian Lie2d87512018-08-23 17:33:05 +0900246 for (String ifaceName : newFabricNetworkConfig.interfaceNames()) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900247 Interface iface = getInterfaceByName(ifaceName);
248 if (iface != null && deviceService.isAvailable(iface.connectPoint().deviceId())) {
Jian Lie2d87512018-08-23 17:33:05 +0900249 newFabricNetwork.addInterface(iface);
250 newInterfaces.add(iface);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900251 }
252 }
253 for (Host host : hostService.getHosts()) {
254 // consider host with ip only
255 if (!host.ipAddresses().isEmpty()) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900256 Interface iface = findAvailableDeviceHostInterface(host);
Jian Lie2d87512018-08-23 17:33:05 +0900257 if (iface != null && newFabricNetwork.contains(iface)) {
258 newFabricNetwork.addHost(host);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900259 }
260 }
261 }
Jian Lie2d87512018-08-23 17:33:05 +0900262 newFabricNetwork.setDirty(true);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900263
Jian Lie2d87512018-08-23 17:33:05 +0900264 // update newFabricNetwork's isDirty flags if same entry already exists
265 for (FabricNetwork prevFabricNetwork : fabricNetworks) {
266 if (prevFabricNetwork.equals(newFabricNetwork)) {
267 newFabricNetwork.setDirty(prevFabricNetwork.isDirty());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900268 break;
269 }
270 }
Jian Lie2d87512018-08-23 17:33:05 +0900271 newFabricNetworks.add(newFabricNetwork);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900272 }
Jian Lie2d87512018-08-23 17:33:05 +0900273 if (!fabricNetworks.equals(newFabricNetworks)) {
274 fabricNetworks = newFabricNetworks;
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900275 dirty = true;
276 }
Jian Lie2d87512018-08-23 17:33:05 +0900277 if (!networkInterfaces.equals(newInterfaces)) {
278 networkInterfaces = newInterfaces;
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900279 dirty = true;
280 }
281
Jian Lie2d87512018-08-23 17:33:05 +0900282 // default Fabric Subnets
283 Set<FabricSubnet> newFabricSubnets = config.fabricSubnets();
284 InvertedRadixTree<FabricSubnet> newIp4SubnetTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900285 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
Jian Lie2d87512018-08-23 17:33:05 +0900286 InvertedRadixTree<FabricSubnet> newIp6SubnetTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900287 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
288 Map<IpAddress, MacAddress> newVirtualGatewayIpMacMap = Maps.newConcurrentMap();
Jian Lie2d87512018-08-23 17:33:05 +0900289 for (FabricSubnet subnet : newFabricSubnets) {
290 if (subnet.prefix().isIp4()) {
291 newIp4SubnetTable.put(createBinaryString(subnet.prefix()), subnet);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900292 } else {
Jian Lie2d87512018-08-23 17:33:05 +0900293 newIp6SubnetTable.put(createBinaryString(subnet.prefix()), subnet);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900294 }
295 newVirtualGatewayIpMacMap.put(subnet.gatewayIp(), subnet.gatewayMac());
296 }
Jian Lie2d87512018-08-23 17:33:05 +0900297 if (!fabricSubnets.equals(newFabricSubnets)) {
298 fabricSubnets = newFabricSubnets;
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900299 ip4SubnetTable = newIp4SubnetTable;
300 ip6SubnetTable = newIp6SubnetTable;
301 dirty = true;
302 }
303 if (!virtualGatewayIpMacMap.equals(newVirtualGatewayIpMacMap)) {
304 virtualGatewayIpMacMap = newVirtualGatewayIpMacMap;
305 dirty = true;
306 }
307
Jian Lie2d87512018-08-23 17:33:05 +0900308 // fabricRoutes config handling
309 Set<FabricRoute> newFabricRoutes = config.fabricRoutes();
310 if (!fabricRoutes.equals(newFabricRoutes)) {
311 InvertedRadixTree<FabricRoute> newIp4BorderRouteTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900312 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
Jian Lie2d87512018-08-23 17:33:05 +0900313 InvertedRadixTree<FabricRoute> newIp6BorderRouteTable =
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900314 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
Jian Lie2d87512018-08-23 17:33:05 +0900315 for (FabricRoute route : newFabricRoutes) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900316 if (route.prefix().isIp4()) {
317 newIp4BorderRouteTable.put(createBinaryString(route.prefix()), route);
318 } else {
319 newIp6BorderRouteTable.put(createBinaryString(route.prefix()), route);
320 }
321 }
Jian Lie2d87512018-08-23 17:33:05 +0900322 fabricRoutes = newFabricRoutes;
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900323 ip4BorderRouteTable = newIp4BorderRouteTable;
324 ip6BorderRouteTable = newIp6BorderRouteTable;
325 dirty = true;
326 }
327
328 // notify to SimpleFabric listeners
329 if (dirty) {
330 log.info("simple fabric refresh; notify events");
331 process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_UPDATED, "updated"));
332 }
333 return dirty;
334 }
335
336 private Interface getInterfaceByName(String interfaceName) {
337 Interface intf = interfaceService.getInterfaces().stream()
338 .filter(iface -> iface.name().equals(interfaceName))
339 .findFirst()
340 .orElse(null);
341 if (intf == null) {
342 log.warn("simple fabric unknown interface name: {}", interfaceName);
343 }
344 return intf;
345 }
346
347 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900348 public ApplicationId appId() {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900349 if (appId == null) {
350 appId = coreService.registerApplication(APP_ID);
351 }
352 return appId;
353 }
354
355 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900356 public Collection<FabricNetwork> fabricNetworks() {
357 return ImmutableSet.copyOf(fabricNetworks);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900358 }
359
360 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900361 public Set<FabricSubnet> defaultFabricSubnets() {
362 return ImmutableSet.copyOf(fabricSubnets);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900363 }
364
365 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900366 public Set<FabricRoute> fabricRoutes() {
367 return ImmutableSet.copyOf(fabricRoutes);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900368 }
369
370 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900371 public boolean isVirtualGatewayMac(MacAddress mac) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900372 return virtualGatewayIpMacMap.containsValue(mac);
373 }
374
375 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900376 public boolean isFabricNetworkInterface(Interface intf) {
377 return networkInterfaces.contains(intf);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900378 }
379
380 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900381 public MacAddress vMacForIp(IpAddress ip) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900382 return virtualGatewayIpMacMap.get(ip);
383 }
384
385 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900386 public FabricNetwork fabricNetwork(ConnectPoint port, VlanId vlanId) {
387 for (FabricNetwork fabricNetwork : fabricNetworks) {
388 if (fabricNetwork.contains(port, vlanId)) {
389 return fabricNetwork;
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900390 }
391 }
392 return null;
393 }
394
395 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900396 public FabricNetwork fabricNetwork(String name) {
397 for (FabricNetwork fabricNetwork : fabricNetworks) {
398 if (fabricNetwork.name().equals(name)) {
399 return fabricNetwork;
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900400 }
401 }
402 return null;
403 }
404
405 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900406 public FabricSubnet fabricSubnet(IpAddress ip) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900407 if (ip.isIp4()) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900408 return ip4SubnetTable.getValueForLongestKeyPrefixing(
409 createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900410 } else {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900411 return ip6SubnetTable.getValueForLongestKeyPrefixing(
412 createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900413 }
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900414 }
415
416 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900417 public FabricRoute fabricRoute(IpAddress ip) {
418 // ASSUME: ipAddress is out of fabricSubnet
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900419 if (ip.isIp4()) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900420 return ip4BorderRouteTable.getValueForLongestKeyPrefixing(
421 createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900422 } else {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900423 return ip6BorderRouteTable.getValueForLongestKeyPrefixing(
424 createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900425 }
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900426 }
427
428
429 @Override
Jian Lie2d87512018-08-23 17:33:05 +0900430 public Interface hostInterface(Host host) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900431 return interfaceService.getInterfaces().stream()
432 .filter(iface -> iface.connectPoint().equals(host.location()) &&
433 iface.vlan().equals(host.vlan()))
434 .findFirst()
435 .orElse(null);
436 }
437
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900438 private Interface findAvailableDeviceHostInterface(Host host) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900439 return interfaceService.getInterfaces().stream()
440 .filter(iface -> iface.connectPoint().equals(host.location()) &&
441 iface.vlan().equals(host.vlan()))
442 .filter(iface -> deviceService.isAvailable(iface.connectPoint().deviceId()))
443 .findFirst()
444 .orElse(null);
445 }
446
447 @Override
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900448 public boolean requestMac(IpAddress ip) {
Jian Lie2d87512018-08-23 17:33:05 +0900449 FabricSubnet fabricSubnet = fabricSubnet(ip);
450 if (fabricSubnet == null) {
451 log.warn("simple fabric request mac failed for unknown fabricSubnet: {}", ip);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900452 return false;
453 }
Jian Lida0b4852018-08-29 20:40:44 +0900454 FabricNetwork fabricNetwork = fabricNetwork(fabricSubnet.networkName());
Jian Lie2d87512018-08-23 17:33:05 +0900455 if (fabricNetwork == null) {
456 log.warn("simple fabric request mac failed for unknown fabricNetwork name {}: {}",
Jian Lida0b4852018-08-29 20:40:44 +0900457 fabricSubnet.networkName(), ip);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900458 return false;
459 }
Jian Lie2d87512018-08-23 17:33:05 +0900460 log.debug("simple fabric send request mac fabricNetwork {}: {}", fabricNetwork.name(), ip);
461 for (Interface iface : fabricNetwork.interfaces()) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900462 Ethernet neighbourReq;
463 if (ip.isIp4()) {
Jian Lie2d87512018-08-23 17:33:05 +0900464 neighbourReq = ARP.buildArpRequest(fabricSubnet.gatewayMac().toBytes(),
465 fabricSubnet.gatewayIp().toOctets(),
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900466 ip.toOctets(),
467 iface.vlan().toShort());
468 } else {
469 byte[] soliciteIp = IPv6.getSolicitNodeAddress(ip.toOctets());
470 neighbourReq = NeighborSolicitation.buildNdpSolicit(
471 ip.toOctets(),
Jian Lie2d87512018-08-23 17:33:05 +0900472 fabricSubnet.gatewayIp().toOctets(),
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900473 soliciteIp,
Jian Lie2d87512018-08-23 17:33:05 +0900474 fabricSubnet.gatewayMac().toBytes(),
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900475 IPv6.getMCastMacAddress(soliciteIp),
476 iface.vlan());
477 }
478 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
479 .setOutput(iface.connectPoint().port()).build();
480 OutboundPacket packet = new DefaultOutboundPacket(iface.connectPoint().deviceId(),
481 treatment, ByteBuffer.wrap(neighbourReq.serialize()));
482 packetService.emit(packet);
483 }
484 return true;
485 }
486
487 @Override
488 public void dumpToStream(String subject, OutputStream out) {
489 SimpleFabricEvent event = new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_DUMP, subject, out);
490 dump(event.subject(), event.out()); // dump in itself
491 process(event); // dump in sub modules
492 }
493
494 // Dump handler
495 protected void dump(String subject, PrintStream out) {
Ray Milkey2ff67162018-01-22 10:14:19 -0800496 if ("show".equals(subject)) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900497 out.println("Static Configuration Flag:");
Jian Li8df54a92018-08-23 17:01:31 +0900498 out.println(" ALLOW_IPV6=" + ALLOW_IPV6);
499 out.println(" ALLOW_ETH_ADDRESS_SELECTOR=" + ALLOW_ETH_ADDRESS_SELECTOR);
500 out.println(" REACTIVE_SINGLE_TO_SINGLE=" + REACTIVE_SINGLE_TO_SINGLE);
501 out.println(" REACTIVE_ALLOW_LINK_CP=" + REACTIVE_ALLOW_LINK_CP);
502 out.println(" REACTIVE_HASHED_PATH_SELECTION=" + REACTIVE_HASHED_PATH_SELECTION);
503 out.println(" REACTIVE_MATCH_IP_PROTO=" + REACTIVE_MATCH_IP_PROTO);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900504 out.println("");
505 out.println("SimpleFabricAppId:");
Jian Lie2d87512018-08-23 17:33:05 +0900506 out.println(" " + appId());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900507 out.println("");
Jian Lie2d87512018-08-23 17:33:05 +0900508 out.println("fabricNetworks:");
509 for (FabricNetwork fabricNetwork : fabricNetworks()) {
510 out.println(" " + fabricNetwork);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900511 }
512 out.println("");
Jian Lie2d87512018-08-23 17:33:05 +0900513 out.println("fabricSubnets:");
514 for (FabricSubnet fabricIpSubnet : defaultFabricSubnets()) {
515 out.println(" " + fabricIpSubnet);
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900516 }
517 out.println("");
Jian Lie2d87512018-08-23 17:33:05 +0900518 out.println("fabricRoutes:");
519 for (FabricRoute route : fabricRoutes()) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900520 out.println(" " + route);
521 }
522 }
523 }
524
525 // Refresh action thread and notifier
526
527 private class InternalRefreshThread extends Thread {
Yuta HIGUCHIc2bf02a2018-03-29 08:40:35 -0700528 @Override
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900529 public void run() {
530 while (true) {
531 boolean doRefreshMarked = false;
532 boolean doFlushMarked = false;
533 synchronized (refreshMonitor) {
534 if (!doRefresh && !doFlush) {
535 try {
536 refreshMonitor.wait(IDLE_INTERVAL_MSEC);
537 } catch (InterruptedException e) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800538 log.warn("run thread interrupted", e);
539 Thread.currentThread().interrupt();
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900540 }
541 }
542 doRefreshMarked = doRefresh;
543 doRefresh = false;
544 doFlushMarked = doFlush;
545 doFlush = false;
546 }
547 if (doRefreshMarked) {
548 try {
549 refresh();
550 } catch (Exception e) {
551 log.warn("simple fabric refresh failed: exception={}", e);
552 }
553 }
554 if (doFlushMarked) {
555 try {
556 log.info("simple fabric flush execute");
557 process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_FLUSH, "flush"));
558 } catch (Exception e) {
559 log.warn("simple fabric flush failed: exception={}", e);
560 }
561 }
562 if (!doRefreshMarked && !doFlushMarked) {
563 try {
564 if (!refresh()) {
565 process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_IDLE, "idle"));
566 }
567 } catch (Exception e) {
568 log.warn("simple fabric idle failed: exception={}", e);
569 }
570 }
571 }
572 }
573 }
574
575 @Override
576 public void triggerRefresh() {
577 synchronized (refreshMonitor) {
578 doRefresh = true;
579 refreshMonitor.notifyAll();
580 }
581 }
582
583 @Override
584 public void triggerFlush() {
585 synchronized (refreshMonitor) {
586 doFlush = true;
587 refreshMonitor.notifyAll();
588 }
589 }
590
591 // Service Listeners
592
593 private class InternalNetworkConfigListener implements NetworkConfigListener {
594 @Override
595 public void event(NetworkConfigEvent event) {
596 switch (event.type()) {
597 case CONFIG_REGISTERED:
598 case CONFIG_UNREGISTERED:
599 case CONFIG_ADDED:
600 case CONFIG_UPDATED:
601 case CONFIG_REMOVED:
602 if (event.configClass().equals(SimpleFabricConfig.class)) {
603 triggerRefresh();
604 }
605 break;
606 default:
607 break;
608 }
609 }
610 }
611
612 private class InternalDeviceListener implements DeviceListener {
613 @Override
614 public void event(DeviceEvent event) {
615 switch (event.type()) {
616 case DEVICE_ADDED:
617 case DEVICE_AVAILABILITY_CHANGED:
618 case DEVICE_REMOVED:
619 case DEVICE_SUSPENDED:
620 case DEVICE_UPDATED:
621 case PORT_ADDED:
622 case PORT_REMOVED:
623 case PORT_UPDATED:
624 // case PORT_STATS_UPDATED: IGNORED
625 triggerRefresh();
626 break;
627 default:
628 break;
629 }
630 }
631 }
632
633 private class InternalHostListener implements HostListener {
634 @Override
635 public void event(HostEvent event) {
636 Host host = event.subject();
637 Host prevHost = event.prevSubject();
638 switch (event.type()) {
639 case HOST_MOVED:
640 case HOST_REMOVED:
641 case HOST_ADDED:
642 case HOST_UPDATED:
643 triggerRefresh();
644 break;
645 default:
646 break;
647 }
648 }
649 }
650
651 private class InternalInterfaceListener implements InterfaceListener {
652 @Override
653 public void event(InterfaceEvent event) {
654 Interface iface = event.subject();
655 Interface prevIface = event.prevSubject();
656 switch (event.type()) {
657 case INTERFACE_ADDED:
658 case INTERFACE_REMOVED:
659 case INTERFACE_UPDATED:
660 triggerRefresh();
661 break;
662 default:
663 break;
664 }
665 }
666 }
667
668}
669