blob: b62d0340422ee314c37ac4e139f9529dffbb8f2b [file] [log] [blame]
Mohammad Shahid4c30ea32017-08-09 18:02:10 +05301/*
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.evpnopenflow.rsc.vpnport.impl;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.google.common.collect.Sets;
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053021import org.onlab.packet.IpAddress;
22import org.onlab.packet.IpPrefix;
23import org.onlab.packet.MacAddress;
24import org.onlab.util.KryoNamespace;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.evpnopenflow.rsc.BasePort;
28import org.onosproject.evpnopenflow.rsc.BasePortId;
29import org.onosproject.evpnopenflow.rsc.DefaultVpnPort;
30import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
31import org.onosproject.evpnopenflow.rsc.VpnPort;
32import org.onosproject.evpnopenflow.rsc.VpnPortId;
33import org.onosproject.evpnopenflow.rsc.baseport.BasePortService;
34import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortEvent;
35import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortListener;
36import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortService;
37import org.onosproject.net.DeviceId;
38import org.onosproject.store.serializers.KryoNamespaces;
39import org.onosproject.store.service.EventuallyConsistentMap;
40import org.onosproject.store.service.StorageService;
41import org.onosproject.store.service.WallClockTimestamp;
42import org.onosproject.vtnrsc.AllocationPool;
43import org.onosproject.vtnrsc.BindingHostId;
44import org.onosproject.vtnrsc.DefaultSubnet;
45import org.onosproject.vtnrsc.DefaultTenantNetwork;
46import org.onosproject.vtnrsc.DefaultVirtualPort;
47import org.onosproject.vtnrsc.FixedIp;
48import org.onosproject.vtnrsc.HostRoute;
49import org.onosproject.vtnrsc.PhysicalNetwork;
50import org.onosproject.vtnrsc.SegmentationId;
51import org.onosproject.vtnrsc.Subnet;
52import org.onosproject.vtnrsc.SubnetId;
53import org.onosproject.vtnrsc.TenantId;
54import org.onosproject.vtnrsc.TenantNetwork;
55import org.onosproject.vtnrsc.TenantNetworkId;
56import org.onosproject.vtnrsc.VirtualPort;
57import org.onosproject.vtnrsc.VirtualPortId;
58import org.onosproject.vtnrsc.subnet.SubnetService;
59import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
60import org.onosproject.vtnrsc.virtualport.VirtualPortService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070061import org.osgi.service.component.annotations.Activate;
62import org.osgi.service.component.annotations.Component;
63import org.osgi.service.component.annotations.Deactivate;
64import org.osgi.service.component.annotations.Reference;
65import org.osgi.service.component.annotations.ReferenceCardinality;
Mohammad Shahid4c30ea32017-08-09 18:02:10 +053066import org.slf4j.Logger;
67import org.slf4j.LoggerFactory;
68
69import java.util.Collection;
70import java.util.Collections;
71import java.util.HashMap;
72import java.util.HashSet;
73import java.util.Map;
74import java.util.Set;
75
76import static com.google.common.base.Preconditions.checkNotNull;
77import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
78import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
79import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVENT_NOT_NULL;
80import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_PORT_START;
81import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_PORT_STOP;
82import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INTERFACE_ID;
83import static org.onosproject.evpnopenflow.rsc.EvpnConstants.JSON_NOT_NULL;
84import static org.onosproject.evpnopenflow.rsc.EvpnConstants.LISTENER_NOT_NULL;
85import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
86import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
87import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
88import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
89import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE;
90import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_CREATION_FAILED;
91import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_DELETE_FAILED;
92import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_ID;
93import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_ID_NOT_NULL;
94import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_IS_NOT_EXIST;
95import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_NOT_NULL;
96import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_STORE;
97import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_UPDATE_FAILED;
98
99/**
100 * Provides implementation of the VpnPort service.
101 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700102@Component(immediate = true, service = VpnPortService.class)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530103public class VpnPortManager implements VpnPortService {
104
105 private final Logger log = LoggerFactory.getLogger(getClass());
106 private final Set<VpnPortListener> listeners = Sets
107 .newCopyOnWriteArraySet();
108
109 protected EventuallyConsistentMap<VpnPortId, VpnPort> vpnPortStore;
110 protected ApplicationId appId;
111
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700112 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530113 protected StorageService storageService;
114
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700115 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530116 protected CoreService coreService;
117
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700118 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530119 protected BasePortService basePortService;
120
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700121 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530122 protected VirtualPortService virtualPortService;
123
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700124 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530125 protected TenantNetworkService tenantNetworkService;
126
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700127 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530128 protected SubnetService subnetService;
129
130 @Activate
131
132 public void activate() {
133 appId = coreService.registerApplication(APP_ID);
134 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
135 .register(KryoNamespaces.API).register(VpnPort.class)
136 .register(VpnPortId.class);
137 vpnPortStore = storageService
138 .<VpnPortId, VpnPort>eventuallyConsistentMapBuilder()
139 .withName(VPN_PORT_STORE).withSerializer(serializer)
140 .withTimestampProvider((k, v) -> new WallClockTimestamp())
141 .build();
142 log.info(EVPN_VPN_PORT_START);
143 }
144
145 @Deactivate
146 public void deactivate() {
147 vpnPortStore.destroy();
148 log.info(EVPN_VPN_PORT_STOP);
149 }
150
151 @Override
152 public boolean exists(VpnPortId vpnPortId) {
153 checkNotNull(vpnPortId, VPN_PORT_ID_NOT_NULL);
154 return vpnPortStore.containsKey(vpnPortId);
155 }
156
157 @Override
158 public VpnPort getPort(VpnPortId vpnPortId) {
159 checkNotNull(vpnPortId, VPN_PORT_ID_NOT_NULL);
160 return vpnPortStore.get(vpnPortId);
161 }
162
163 @Override
164 public Collection<VpnPort> getPorts() {
165 return Collections.unmodifiableCollection(vpnPortStore.values());
166 }
167
168 @Override
169 public boolean createPorts(Iterable<VpnPort> vpnPorts) {
170 checkNotNull(vpnPorts, VPN_PORT_NOT_NULL);
171 for (VpnPort vpnPort : vpnPorts) {
172 log.info(VPN_PORT_ID, vpnPort.id().toString());
173 vpnPortStore.put(vpnPort.id(), vpnPort);
174 if (!vpnPortStore.containsKey(vpnPort.id())) {
175 log.info(VPN_PORT_CREATION_FAILED, vpnPort.id().toString());
176 return false;
177 }
178 notifyListeners(new VpnPortEvent(VpnPortEvent.Type.VPN_PORT_SET,
179 vpnPort));
180 }
181 return true;
182 }
183
184 @Override
185 public boolean updatePorts(Iterable<VpnPort> vpnPorts) {
186 checkNotNull(vpnPorts, VPN_PORT_NOT_NULL);
187 for (VpnPort vpnPort : vpnPorts) {
188 if (!vpnPortStore.containsKey(vpnPort.id())) {
189 log.info(VPN_PORT_IS_NOT_EXIST, vpnPort.id().toString());
190 return false;
191 }
192 vpnPortStore.put(vpnPort.id(), vpnPort);
193 if (!vpnPort.equals(vpnPortStore.get(vpnPort.id()))) {
194 log.info(VPN_PORT_UPDATE_FAILED, vpnPort.id().toString());
195 return false;
196 }
197 notifyListeners(new VpnPortEvent(VpnPortEvent.Type.VPN_PORT_UPDATE,
198 vpnPort));
199 }
200 return true;
201 }
202
203 @Override
204 public boolean removePorts(Iterable<VpnPortId> vpnPortIds) {
205 checkNotNull(vpnPortIds, VPN_PORT_NOT_NULL);
206 for (VpnPortId vpnPortid : vpnPortIds) {
207 VpnPort vpnPort = vpnPortStore.get(vpnPortid);
208 vpnPortStore.remove(vpnPortid);
209 if (vpnPortStore.containsKey(vpnPortid)) {
210 log.info(VPN_PORT_DELETE_FAILED, vpnPortid.toString());
211 return false;
212 }
213 notifyListeners(new VpnPortEvent(VpnPortEvent.Type.VPN_PORT_DELETE,
214 vpnPort));
215 }
216 return true;
217 }
218
219 @Override
220 public void processGluonConfig(String action, String key, JsonNode value) {
221 Collection<VpnPort> vpnPorts;
222 switch (action) {
223 case DELETE:
224 String[] list = key.split(SLASH);
225 VpnPortId vpnPortId
226 = VpnPortId.vpnPortId(list[list.length - 1]);
227 Set<VpnPortId> vpnPortIds = Sets.newHashSet(vpnPortId);
228 removePorts(vpnPortIds);
229 // After removing vpn port and also remove virtual port from vtn
230 VirtualPortId virtualPortId
231 = VirtualPortId.portId(list[list.length - 1]);
232 Set<VirtualPortId> virtualPortIds
233 = Sets.newHashSet(virtualPortId);
234 virtualPortService.removePorts(virtualPortIds);
235 break;
236 case SET:
237 checkNotNull(value, RESPONSE_NOT_NULL);
238 vpnPorts = changeJsonToSub(value);
239 createPorts(vpnPorts);
240 break;
241 case UPDATE:
242 checkNotNull(value, RESPONSE_NOT_NULL);
243 vpnPorts = changeJsonToSub(value);
244 updatePorts(vpnPorts);
245 break;
246 default:
247 log.info("Invalid action is received while processing VPN " +
248 "port configuration");
249 }
250 }
251
252 /**
253 * Creates dummy gluon network to the VTN.
254 *
255 * @param state the base port state
256 * @param adminStateUp the base port admin status
257 * @param tenantID the base port tenant ID
258 */
259 private void createDummyGluonNetwork(boolean adminStateUp, String state,
260 TenantId tenantID) {
261 String id = "11111111-1111-1111-1111-111111111111";
262 String name = "GluonNetwork";
263 String segmentationID = "50";
264 String physicalNetwork = "None";
265
266 TenantNetwork network = new DefaultTenantNetwork(TenantNetworkId.networkId(id), name,
267 adminStateUp,
268 TenantNetwork.State.valueOf(state),
269 false, tenantID,
270 false,
271 TenantNetwork.Type.LOCAL,
272 PhysicalNetwork.physicalNetwork(physicalNetwork),
273 SegmentationId.segmentationId(segmentationID));
274
275 Set<TenantNetwork> networksSet = Sets.newHashSet(network);
276 tenantNetworkService.createNetworks(networksSet);
277 }
278
279
280 /**
281 * Creates dummy gluon subnet to the VTN.
282 *
283 * @param tenantId the base port tenant ID
284 */
285 public void createDummySubnet(TenantId tenantId) {
286 String id = "22222222-2222-2222-2222-222222222222";
287 String subnetName = "GluonSubnet";
288 String cidr = "0.0.0.0/0";
289 String gatewayIp = "0.0.0.0";
290 Set<HostRoute> hostRoutes = Sets.newHashSet();
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530291 TenantNetworkId tenantNetworkId = null;
292 Set<AllocationPool> allocationPools = Sets.newHashSet();
293 Iterable<TenantNetwork> networks
294 = tenantNetworkService.getNetworks();
295
296 for (TenantNetwork tenantNetwork : networks) {
297 if (tenantNetwork.name().equals("GluonNetwork")) {
298 tenantNetworkId = tenantNetwork.id();
299 break;
300 }
301 }
302 Subnet subnet = new DefaultSubnet(SubnetId.subnetId(id), subnetName,
303 tenantNetworkId,
304 tenantId, IpAddress.Version.INET,
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800305 IpPrefix.valueOf(cidr),
306 IpAddress.valueOf(gatewayIp),
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530307 false, false, hostRoutes,
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800308 null,
309 null,
Mohammad Shahid4c30ea32017-08-09 18:02:10 +0530310 allocationPools);
311
312 Set<Subnet> subnetsSet = Sets.newHashSet(subnet);
313 subnetService.createSubnets(subnetsSet);
314 }
315
316 /**
317 * Returns a collection of vpnPort from subnetNodes.
318 *
319 * @param vpnPortNodes the vpnPort json node
320 * @return list of vpnports
321 */
322 private Collection<VpnPort> changeJsonToSub(JsonNode vpnPortNodes) {
323 checkNotNull(vpnPortNodes, JSON_NOT_NULL);
324 Map<VpnPortId, VpnPort> vpnPortMap = new HashMap<>();
325 String interfaceId = vpnPortNodes.get(INTERFACE_ID).asText();
326 VpnPortId vpnPortId = VpnPortId.vpnPortId(interfaceId);
327 VpnInstanceId vpnInstanceId = VpnInstanceId
328 .vpnInstanceId(vpnPortNodes.get(VPN_INSTANCE).asText());
329 VpnPort vpnPort = new DefaultVpnPort(vpnPortId, vpnInstanceId);
330 vpnPortMap.put(vpnPortId, vpnPort);
331 // update ip address and tenant network information in vtn
332 TenantNetworkId tenantNetworkId = null;
333 Map<VirtualPortId, VirtualPort> vPortMap = new HashMap<>();
334 BasePortId basePortId = BasePortId.portId(interfaceId);
335 VirtualPortId virtualPortId = VirtualPortId.portId(interfaceId);
336 BasePort bPort = basePortService.getPort(basePortId);
337 if (bPort != null) {
338 FixedIp fixedIp = FixedIp.fixedIp(SubnetId.subnetId(basePortId.toString()),
339 IpAddress.valueOf(vpnPortNodes
340 .get("ipaddress").asText()));
341 Set<FixedIp> fixedIps = new HashSet<>();
342 fixedIps.add(fixedIp);
343 Map<String, String> strMap = new HashMap<>();
344 boolean adminStateUp = bPort.adminStateUp();
345 strMap.put("name", bPort.name());
346 strMap.put("deviceOwner", bPort.deviceOwner());
347 strMap.put("bindingVnicType", bPort.bindingVnicType());
348 strMap.put("bindingVifType", bPort.bindingVifType());
349 strMap.put("bindingVifDetails", bPort.bindingVifDetails());
350 String state = bPort.state();
351 MacAddress macAddress = bPort.macAddress();
352 TenantId tenantId = bPort.tenantId();
353 DeviceId deviceId = bPort.deviceId();
354 BindingHostId bindingHostId = bPort.bindingHostId();
355 // Creates Dummy Gluon Network and Subnet
356 createDummyGluonNetwork(adminStateUp, state, tenantId);
357 createDummySubnet(tenantId);
358
359 Iterable<TenantNetwork> networks
360 = tenantNetworkService.getNetworks();
361
362 for (TenantNetwork tenantNetwork : networks) {
363 if (tenantNetwork.name().equals("GluonNetwork")) {
364 tenantNetworkId = tenantNetwork.id();
365 break;
366 }
367 }
368 if (tenantNetworkId != null) {
369
370 DefaultVirtualPort vPort = new DefaultVirtualPort(virtualPortId,
371 tenantNetworkId,
372 adminStateUp,
373 strMap, isState(state),
374 macAddress, tenantId,
375 deviceId, fixedIps,
376 bindingHostId,
377 null,
378 null);
379 vPortMap.put(virtualPortId, vPort);
380 Collection<VirtualPort> virtualPorts
381 = Collections.unmodifiableCollection(vPortMap.values());
382 virtualPortService.createPorts(virtualPorts);
383 }
384 }
385
386 return Collections.unmodifiableCollection(vpnPortMap.values());
387 }
388
389 /**
390 * Returns BasePort State.
391 *
392 * @param state the base port state
393 * @return the basePort state
394 */
395 private VirtualPort.State isState(String state) {
396 if (state.equals("ACTIVE")) {
397 return VirtualPort.State.ACTIVE;
398 } else {
399 return VirtualPort.State.DOWN;
400 }
401
402 }
403
404 @Override
405 public void addListener(VpnPortListener listener) {
406 checkNotNull(listener, LISTENER_NOT_NULL);
407 listeners.add(listener);
408 }
409
410 @Override
411 public void removeListener(VpnPortListener listener) {
412 checkNotNull(listener, LISTENER_NOT_NULL);
413 listeners.remove(listener);
414 }
415
416 /**
417 * Notifies specify event to all listeners.
418 *
419 * @param event Vpn Port event
420 */
421 private void notifyListeners(VpnPortEvent event) {
422 checkNotNull(event, EVENT_NOT_NULL);
423 listeners.forEach(listener -> {
424 listener.event(event);
425 });
426 }
427}