2 * Copyright 2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.vtnrsc.service.impl;
18 import static com.google.common.base.Preconditions.checkNotNull;
19 import static org.slf4j.LoggerFactory.getLogger;
21 import java.util.HashSet;
22 import java.util.Iterator;
25 import org.apache.felix.scr.annotations.Activate;
26 import org.apache.felix.scr.annotations.Component;
27 import org.apache.felix.scr.annotations.Deactivate;
28 import org.apache.felix.scr.annotations.Reference;
29 import org.apache.felix.scr.annotations.ReferenceCardinality;
30 import org.apache.felix.scr.annotations.Service;
31 import org.onlab.packet.IpAddress;
32 import org.onlab.packet.MacAddress;
33 import org.onlab.util.KryoNamespace;
34 import org.onosproject.core.CoreService;
35 import org.onosproject.net.Device;
36 import org.onosproject.net.DeviceId;
37 import org.onosproject.net.Host;
38 import org.onosproject.net.HostId;
39 import org.onosproject.net.host.HostEvent;
40 import org.onosproject.net.host.HostListener;
41 import org.onosproject.net.host.HostService;
42 import org.onosproject.net.device.DeviceService;
43 import org.onosproject.store.serializers.KryoNamespaces;
44 import org.onosproject.store.service.EventuallyConsistentMap;
45 import org.onosproject.store.service.LogicalClockService;
46 import org.onosproject.store.service.StorageService;
47 import org.onosproject.vtnrsc.FixedIp;
48 import org.onosproject.vtnrsc.FloatingIp;
49 import org.onosproject.vtnrsc.Router;
50 import org.onosproject.vtnrsc.RouterInterface;
51 import org.onosproject.vtnrsc.SegmentationId;
52 import org.onosproject.vtnrsc.Subnet;
53 import org.onosproject.vtnrsc.SubnetId;
54 import org.onosproject.vtnrsc.TenantId;
55 import org.onosproject.vtnrsc.VirtualPort;
56 import org.onosproject.vtnrsc.VirtualPortId;
57 import org.onosproject.vtnrsc.event.VtnRscEvent;
58 import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
59 import org.onosproject.vtnrsc.event.VtnRscListener;
60 import org.onosproject.vtnrsc.floatingip.FloatingIpEvent;
61 import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
62 import org.onosproject.vtnrsc.floatingip.FloatingIpService;
63 import org.onosproject.vtnrsc.router.RouterEvent;
64 import org.onosproject.vtnrsc.router.RouterListener;
65 import org.onosproject.vtnrsc.router.RouterService;
66 import org.onosproject.vtnrsc.routerinterface.RouterInterfaceEvent;
67 import org.onosproject.vtnrsc.routerinterface.RouterInterfaceListener;
68 import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
69 import org.onosproject.vtnrsc.service.VtnRscService;
70 import org.onosproject.vtnrsc.subnet.SubnetService;
71 import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
72 import org.onosproject.vtnrsc.virtualport.VirtualPortService;
73 import org.slf4j.Logger;
75 import com.google.common.collect.Sets;
78 * Provides implementation of the VtnRsc service.
80 @Component(immediate = true)
82 public class VtnRscManager implements VtnRscService {
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected CoreService coreService;
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected StorageService storageService;
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected LogicalClockService clockService;
90 private final Logger log = getLogger(getClass());
91 private final Set<VtnRscListener> listeners = Sets.newCopyOnWriteArraySet();
92 private HostListener hostListener = new InnerHostListener();
93 private FloatingIpListener floatingIpListener = new InnerFloatingIpListener();
94 private RouterListener routerListener = new InnerRouterListener();
95 private RouterInterfaceListener routerInterfaceListener = new InnerRouterInterfaceListener();
97 private EventuallyConsistentMap<TenantId, SegmentationId> l3vniMap;
98 private EventuallyConsistentMap<TenantId, Set<DeviceId>> classifierOvsMap;
99 private EventuallyConsistentMap<TenantId, Set<DeviceId>> sffOvsMap;
101 private static final String IFACEID = "ifaceid";
102 private static final String RUNNELOPTOPOIC = "tunnel-ops-ids";
103 private static final String LISTENER_NOT_NULL = "listener cannot be null";
104 private static final String EVENT_NOT_NULL = "event cannot be null";
105 private static final String TENANTID_NOT_NULL = "tenantId cannot be null";
106 private static final String DEVICEID_NOT_NULL = "deviceId cannot be null";
107 private static final String OVSMAP_NOT_NULL = "ovsMap cannot be null";
108 private static final String L3VNIMAP = "l3vniMap";
109 private static final String CLASSIFIEROVSMAP = "classifierOvsMap";
110 private static final String SFFOVSMAP = "sffOvsMap";
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected RouterService routerService;
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected FloatingIpService floatingIpService;
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected RouterInterfaceService routerInterfaceService;
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected VirtualPortService virtualPortService;
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected HostService hostService;
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected SubnetService subnetService;
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 protected TenantNetworkService tenantNetworkService;
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected DeviceService deviceService;
130 public void activate() {
131 hostService.addListener(hostListener);
132 floatingIpService.addListener(floatingIpListener);
133 routerService.addListener(routerListener);
134 routerInterfaceService.addListener(routerInterfaceListener);
136 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
137 .register(KryoNamespaces.API)
138 .register(TenantId.class, DeviceId.class);
139 l3vniMap = storageService
140 .<TenantId, SegmentationId>eventuallyConsistentMapBuilder()
141 .withName(L3VNIMAP).withSerializer(serializer)
142 .withTimestampProvider((k, v) -> clockService.getTimestamp())
145 classifierOvsMap = storageService
146 .<TenantId, Set<DeviceId>>eventuallyConsistentMapBuilder()
147 .withName(CLASSIFIEROVSMAP).withSerializer(serializer)
148 .withTimestampProvider((k, v) -> clockService.getTimestamp())
151 sffOvsMap = storageService
152 .<TenantId, Set<DeviceId>>eventuallyConsistentMapBuilder()
153 .withName(SFFOVSMAP).withSerializer(serializer)
154 .withTimestampProvider((k, v) -> clockService.getTimestamp())
159 public void deactivate() {
160 hostService.removeListener(hostListener);
161 floatingIpService.removeListener(floatingIpListener);
162 routerService.removeListener(routerListener);
163 routerInterfaceService.removeListener(routerInterfaceListener);
165 classifierOvsMap.destroy();
172 public void addListener(VtnRscListener listener) {
173 checkNotNull(listener, LISTENER_NOT_NULL);
174 listeners.add(listener);
178 public void removeListener(VtnRscListener listener) {
179 checkNotNull(listener, LISTENER_NOT_NULL);
180 listeners.add(listener);
184 public SegmentationId getL3vni(TenantId tenantId) {
185 checkNotNull(tenantId, "tenantId cannot be null");
186 SegmentationId l3vni = l3vniMap.get(tenantId);
188 long segmentationId = coreService.getIdGenerator(RUNNELOPTOPOIC)
190 l3vni = SegmentationId.segmentationId(String
191 .valueOf(segmentationId));
192 l3vniMap.put(tenantId, l3vni);
197 private class InnerHostListener implements HostListener {
200 public void event(HostEvent event) {
201 checkNotNull(event, EVENT_NOT_NULL);
202 Host host = event.subject();
203 String ifaceId = host.annotations().value(IFACEID);
204 VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
205 TenantId tenantId = virtualPortService.getPort(hPortId).tenantId();
206 DeviceId deviceId = host.location().deviceId();
207 if (HostEvent.Type.HOST_ADDED == event.type()) {
208 if (isServiceFunction(hPortId)) {
209 addDeviceIdOfOvsMap(tenantId, deviceId, sffOvsMap);
211 addDeviceIdOfOvsMap(tenantId, deviceId, classifierOvsMap);
213 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
214 if (isLastSFHostOfTenant(host, deviceId, tenantId)) {
215 removeDeviceIdOfOvsMap(tenantId, deviceId, sffOvsMap);
217 if (isLastClassifierHostOfTenant(host, deviceId, tenantId)) {
218 removeDeviceIdOfOvsMap(tenantId, deviceId, classifierOvsMap);
224 private class InnerFloatingIpListener implements FloatingIpListener {
227 public void event(FloatingIpEvent event) {
228 checkNotNull(event, EVENT_NOT_NULL);
229 FloatingIp floatingIp = event.subject();
230 if (FloatingIpEvent.Type.FLOATINGIP_PUT == event.type()) {
231 notifyListeners(new VtnRscEvent(
232 VtnRscEvent.Type.FLOATINGIP_PUT,
233 new VtnRscEventFeedback(
236 if (FloatingIpEvent.Type.FLOATINGIP_DELETE == event.type()) {
237 notifyListeners(new VtnRscEvent(
238 VtnRscEvent.Type.FLOATINGIP_DELETE,
239 new VtnRscEventFeedback(
245 private class InnerRouterListener implements RouterListener {
248 public void event(RouterEvent event) {
249 checkNotNull(event, EVENT_NOT_NULL);
250 Router router = event.subject();
251 if (RouterEvent.Type.ROUTER_PUT == event.type()) {
252 notifyListeners(new VtnRscEvent(VtnRscEvent.Type.ROUTER_PUT,
253 new VtnRscEventFeedback(router)));
255 if (RouterEvent.Type.ROUTER_DELETE == event.type()) {
256 notifyListeners(new VtnRscEvent(VtnRscEvent.Type.ROUTER_DELETE,
257 new VtnRscEventFeedback(router)));
262 private class InnerRouterInterfaceListener
263 implements RouterInterfaceListener {
266 public void event(RouterInterfaceEvent event) {
267 checkNotNull(event, EVENT_NOT_NULL);
268 RouterInterface routerInterface = event.subject();
269 if (RouterInterfaceEvent.Type.ROUTER_INTERFACE_PUT == event.type()) {
270 notifyListeners(new VtnRscEvent(
271 VtnRscEvent.Type.ROUTER_INTERFACE_PUT,
272 new VtnRscEventFeedback(
275 if (RouterInterfaceEvent.Type.ROUTER_INTERFACE_DELETE == event
277 notifyListeners(new VtnRscEvent(
278 VtnRscEvent.Type.ROUTER_INTERFACE_DELETE,
279 new VtnRscEventFeedback(
286 public Iterator<Device> getClassifierOfTenant(TenantId tenantId) {
287 checkNotNull(tenantId, TENANTID_NOT_NULL);
288 Set<DeviceId> deviceIdSet = classifierOvsMap.get(tenantId);
289 Set<Device> deviceSet = new HashSet<>();
290 if (deviceIdSet != null) {
291 for (DeviceId deviceId : deviceIdSet) {
292 deviceSet.add(deviceService.getDevice(deviceId));
295 return deviceSet.iterator();
299 public Iterator<Device> getSFFOfTenant(TenantId tenantId) {
300 checkNotNull(tenantId, TENANTID_NOT_NULL);
301 Set<DeviceId> deviceIdSet = sffOvsMap.get(tenantId);
302 Set<Device> deviceSet = new HashSet<>();
303 if (deviceIdSet != null) {
304 for (DeviceId deviceId : deviceIdSet) {
305 deviceSet.add(deviceService.getDevice(deviceId));
308 return deviceSet.iterator();
312 public MacAddress getGatewayMac(HostId hostId) {
313 checkNotNull(hostId, "hostId cannot be null");
314 Host host = hostService.getHost(hostId);
315 String ifaceId = host.annotations().value(IFACEID);
316 VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
317 VirtualPort hPort = virtualPortService.getPort(hPortId);
318 SubnetId subnetId = hPort.fixedIps().iterator().next().subnetId();
319 Subnet subnet = subnetService.getSubnet(subnetId);
320 IpAddress gatewayIp = subnet.gatewayIp();
321 Iterable<VirtualPort> virtualPorts = virtualPortService.getPorts();
322 MacAddress macAddress = null;
323 for (VirtualPort port : virtualPorts) {
324 Set<FixedIp> fixedIpSet = port.fixedIps();
325 for (FixedIp fixedIp : fixedIpSet) {
326 if (fixedIp.ip().equals(gatewayIp)) {
327 macAddress = port.macAddress();
335 public boolean isServiceFunction(VirtualPortId portId) {
336 // TODO Auto-generated method stub
341 public DeviceId getSFToSFFMaping(VirtualPortId portId) {
342 checkNotNull(portId, "portId cannot be null");
343 VirtualPort vmPort = virtualPortService.getPort(portId);
344 Set<Host> hostSet = hostService.getHostsByMac(vmPort.macAddress());
345 for (Host host : hostSet) {
346 if (host.annotations().value(IFACEID).equals(vmPort.portId())) {
347 return host.location().deviceId();
354 * Checks whether the last Service Function host of a specific tenant in
357 * @param host the host on device
358 * @param deviceId the device identifier
359 * @param tenantId the tenant identifier
360 * @return true or false
362 private boolean isLastSFHostOfTenant(Host host, DeviceId deviceId,
364 checkNotNull(host, "host cannot be null");
365 checkNotNull(deviceId, DEVICEID_NOT_NULL);
366 checkNotNull(tenantId, TENANTID_NOT_NULL);
367 Set<Host> hostSet = hostService.getConnectedHosts(deviceId);
368 for (Host h : hostSet) {
369 String ifaceId = h.annotations().value(IFACEID);
370 VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
371 if (virtualPortService.getPort(hPortId).tenantId() != tenantId) {
374 if (!isServiceFunction(hPortId)) {
379 if (hostSet.size() == 1 && hostSet.contains(host)) {
386 * Checks whether the last Classifier host of a specific tenant in this
389 * @param host the host on device
390 * @param deviceId the device identifier
391 * @param tenantId the tenant identifier
392 * @return true or false
394 private boolean isLastClassifierHostOfTenant(Host host, DeviceId deviceId,
396 checkNotNull(host, "host cannot be null");
397 checkNotNull(deviceId, DEVICEID_NOT_NULL);
398 checkNotNull(tenantId, TENANTID_NOT_NULL);
399 Set<Host> hostSet = hostService.getConnectedHosts(deviceId);
400 for (Host h : hostSet) {
401 String ifaceId = h.annotations().value(IFACEID);
402 VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
403 if (virtualPortService.getPort(hPortId).tenantId() != tenantId) {
406 if (isServiceFunction(hPortId)) {
411 if (hostSet.size() == 1 && hostSet.contains(host)) {
418 * Adds specify Device identifier to OvsMap.
420 * @param tenantId the tenant identifier
421 * @param deviceId the device identifier
422 * @param ovsMap the instance of map to store device identifier
424 private void addDeviceIdOfOvsMap(TenantId tenantId,
426 EventuallyConsistentMap<TenantId, Set<DeviceId>> ovsMap) {
427 checkNotNull(tenantId, TENANTID_NOT_NULL);
428 checkNotNull(deviceId, DEVICEID_NOT_NULL);
429 checkNotNull(ovsMap, OVSMAP_NOT_NULL);
430 if (ovsMap.containsKey(tenantId)) {
431 Set<DeviceId> deviceIdSet = ovsMap.get(tenantId);
432 deviceIdSet.add(deviceId);
433 ovsMap.put(tenantId, deviceIdSet);
435 Set<DeviceId> deviceIdSet = new HashSet<>();
436 deviceIdSet.add(deviceId);
437 ovsMap.put(tenantId, deviceIdSet);
442 * Removes specify Device identifier from OvsMap.
444 * @param tenantId the tenant identifier
445 * @param deviceId the device identifier
446 * @param ovsMap the instance of map to store device identifier
448 private void removeDeviceIdOfOvsMap(TenantId tenantId,
450 EventuallyConsistentMap<TenantId, Set<DeviceId>> ovsMap) {
451 checkNotNull(tenantId, TENANTID_NOT_NULL);
452 checkNotNull(deviceId, DEVICEID_NOT_NULL);
453 checkNotNull(ovsMap, OVSMAP_NOT_NULL);
454 Set<DeviceId> deviceIdSet = ovsMap.get(tenantId);
455 if (deviceIdSet.size() > 1) {
456 deviceIdSet.remove(deviceId);
457 ovsMap.put(tenantId, deviceIdSet);
459 ovsMap.remove(tenantId);
464 * Notifies specify event to all listeners.
466 * @param event VtnRsc event
468 private void notifyListeners(VtnRscEvent event) {
469 checkNotNull(event, EVENT_NOT_NULL);
470 listeners.forEach(listener -> listener.event(event));