jiangrui
Committed by Gerrit Code Review

[ONOS-2818] add implementation of VtnRscService api

Change-Id: I0d5b87813cf0edb1fd5ebefe1eedf8b50fda7a5e
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.vtnrsc.service.impl;
17 +
18 +import static com.google.common.base.Preconditions.checkNotNull;
19 +import static org.slf4j.LoggerFactory.getLogger;
20 +
21 +import java.util.HashSet;
22 +import java.util.Iterator;
23 +import java.util.Set;
24 +
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;
74 +
75 +import com.google.common.collect.Sets;
76 +
77 +/**
78 + * Provides implementation of the VtnRsc service.
79 + */
80 +@Component(immediate = true)
81 +@Service
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;
89 +
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();
96 +
97 + private EventuallyConsistentMap<TenantId, SegmentationId> l3vniMap;
98 + private EventuallyConsistentMap<TenantId, Set<DeviceId>> classifierOvsMap;
99 + private EventuallyConsistentMap<TenantId, Set<DeviceId>> sffOvsMap;
100 +
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";
111 +
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;
128 +
129 + @Activate
130 + public void activate() {
131 + hostService.addListener(hostListener);
132 + floatingIpService.addListener(floatingIpListener);
133 + routerService.addListener(routerListener);
134 + routerInterfaceService.addListener(routerInterfaceListener);
135 +
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())
143 + .build();
144 +
145 + classifierOvsMap = storageService
146 + .<TenantId, Set<DeviceId>>eventuallyConsistentMapBuilder()
147 + .withName(CLASSIFIEROVSMAP).withSerializer(serializer)
148 + .withTimestampProvider((k, v) -> clockService.getTimestamp())
149 + .build();
150 +
151 + sffOvsMap = storageService
152 + .<TenantId, Set<DeviceId>>eventuallyConsistentMapBuilder()
153 + .withName(SFFOVSMAP).withSerializer(serializer)
154 + .withTimestampProvider((k, v) -> clockService.getTimestamp())
155 + .build();
156 + }
157 +
158 + @Deactivate
159 + public void deactivate() {
160 + hostService.removeListener(hostListener);
161 + floatingIpService.removeListener(floatingIpListener);
162 + routerService.removeListener(routerListener);
163 + routerInterfaceService.removeListener(routerInterfaceListener);
164 + l3vniMap.destroy();
165 + classifierOvsMap.destroy();
166 + sffOvsMap.destroy();
167 + listeners.clear();
168 + log.info("Stopped");
169 + }
170 +
171 + @Override
172 + public void addListener(VtnRscListener listener) {
173 + checkNotNull(listener, LISTENER_NOT_NULL);
174 + listeners.add(listener);
175 + }
176 +
177 + @Override
178 + public void removeListener(VtnRscListener listener) {
179 + checkNotNull(listener, LISTENER_NOT_NULL);
180 + listeners.add(listener);
181 + }
182 +
183 + @Override
184 + public SegmentationId getL3vni(TenantId tenantId) {
185 + checkNotNull(tenantId, "tenantId cannot be null");
186 + SegmentationId l3vni = l3vniMap.get(tenantId);
187 + if (l3vni == null) {
188 + long segmentationId = coreService.getIdGenerator(RUNNELOPTOPOIC)
189 + .getNewId();
190 + l3vni = SegmentationId.segmentationId(String
191 + .valueOf(segmentationId));
192 + l3vniMap.put(tenantId, l3vni);
193 + }
194 + return l3vni;
195 + }
196 +
197 + private class InnerHostListener implements HostListener {
198 +
199 + @Override
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);
210 + } else {
211 + addDeviceIdOfOvsMap(tenantId, deviceId, classifierOvsMap);
212 + }
213 + } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
214 + if (isLastSFHostOfTenant(host, deviceId, tenantId)) {
215 + removeDeviceIdOfOvsMap(tenantId, deviceId, sffOvsMap);
216 + }
217 + if (isLastClassifierHostOfTenant(host, deviceId, tenantId)) {
218 + removeDeviceIdOfOvsMap(tenantId, deviceId, classifierOvsMap);
219 + }
220 + }
221 + }
222 + }
223 +
224 + private class InnerFloatingIpListener implements FloatingIpListener {
225 +
226 + @Override
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(
234 + floatingIp)));
235 + }
236 + if (FloatingIpEvent.Type.FLOATINGIP_DELETE == event.type()) {
237 + notifyListeners(new VtnRscEvent(
238 + VtnRscEvent.Type.FLOATINGIP_DELETE,
239 + new VtnRscEventFeedback(
240 + floatingIp)));
241 + }
242 + }
243 + }
244 +
245 + private class InnerRouterListener implements RouterListener {
246 +
247 + @Override
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)));
254 + }
255 + if (RouterEvent.Type.ROUTER_DELETE == event.type()) {
256 + notifyListeners(new VtnRscEvent(VtnRscEvent.Type.ROUTER_DELETE,
257 + new VtnRscEventFeedback(router)));
258 + }
259 + }
260 + }
261 +
262 + private class InnerRouterInterfaceListener
263 + implements RouterInterfaceListener {
264 +
265 + @Override
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(
273 + routerInterface)));
274 + }
275 + if (RouterInterfaceEvent.Type.ROUTER_INTERFACE_DELETE == event
276 + .type()) {
277 + notifyListeners(new VtnRscEvent(
278 + VtnRscEvent.Type.ROUTER_INTERFACE_DELETE,
279 + new VtnRscEventFeedback(
280 + routerInterface)));
281 + }
282 + }
283 + }
284 +
285 + @Override
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));
293 + }
294 + }
295 + return deviceSet.iterator();
296 + }
297 +
298 + @Override
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));
306 + }
307 + }
308 + return deviceSet.iterator();
309 + }
310 +
311 + @Override
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();
328 + }
329 + }
330 + }
331 + return macAddress;
332 + }
333 +
334 + @Override
335 + public boolean isServiceFunction(VirtualPortId portId) {
336 + // TODO Auto-generated method stub
337 + return false;
338 + }
339 +
340 + @Override
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();
348 + }
349 + }
350 + return null;
351 + }
352 +
353 + /**
354 + * Checks whether the last Service Function host of a specific tenant in
355 + * this device.
356 + *
357 + * @param host the host on device
358 + * @param deviceId the device identifier
359 + * @param tenantId the tenant identifier
360 + * @return true or false
361 + */
362 + private boolean isLastSFHostOfTenant(Host host, DeviceId deviceId,
363 + TenantId tenantId) {
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) {
372 + hostSet.remove(h);
373 + } else {
374 + if (!isServiceFunction(hPortId)) {
375 + hostSet.remove(h);
376 + }
377 + }
378 + }
379 + if (hostSet.size() == 1 && hostSet.contains(host)) {
380 + return true;
381 + }
382 + return false;
383 + }
384 +
385 + /**
386 + * Checks whether the last Classifier host of a specific tenant in this
387 + * device.
388 + *
389 + * @param host the host on device
390 + * @param deviceId the device identifier
391 + * @param tenantId the tenant identifier
392 + * @return true or false
393 + */
394 + private boolean isLastClassifierHostOfTenant(Host host, DeviceId deviceId,
395 + TenantId tenantId) {
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) {
404 + hostSet.remove(h);
405 + } else {
406 + if (isServiceFunction(hPortId)) {
407 + hostSet.remove(h);
408 + }
409 + }
410 + }
411 + if (hostSet.size() == 1 && hostSet.contains(host)) {
412 + return true;
413 + }
414 + return false;
415 + }
416 +
417 + /**
418 + * Adds specify Device identifier to OvsMap.
419 + *
420 + * @param tenantId the tenant identifier
421 + * @param deviceId the device identifier
422 + * @param ovsMap the instance of map to store device identifier
423 + */
424 + private void addDeviceIdOfOvsMap(TenantId tenantId,
425 + DeviceId deviceId,
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);
434 + } else {
435 + Set<DeviceId> deviceIdSet = new HashSet<>();
436 + deviceIdSet.add(deviceId);
437 + ovsMap.put(tenantId, deviceIdSet);
438 + }
439 + }
440 +
441 + /**
442 + * Removes specify Device identifier from OvsMap.
443 + *
444 + * @param tenantId the tenant identifier
445 + * @param deviceId the device identifier
446 + * @param ovsMap the instance of map to store device identifier
447 + */
448 + private void removeDeviceIdOfOvsMap(TenantId tenantId,
449 + DeviceId deviceId,
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);
458 + } else {
459 + ovsMap.remove(tenantId);
460 + }
461 + }
462 +
463 + /**
464 + * Notifies specify event to all listeners.
465 + *
466 + * @param event VtnRsc event
467 + */
468 + private void notifyListeners(VtnRscEvent event) {
469 + checkNotNull(event, EVENT_NOT_NULL);
470 + listeners.forEach(listener -> listener.event(event));
471 + }
472 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +
17 +/**
18 + * Provides implementation of the VtnRsc service.
19 + */
20 +package org.onosproject.vtnrsc.service.impl;