blob: 4ccf0a1d86474880bc53bdc6059b5318cdcac9f6 [file] [log] [blame]
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +05301/*
2 * Copyright 2017-present 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 */
janani bf41dec32017-03-24 18:44:07 +053016package org.onosproject.l3vpn.netl3vpn.impl;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053017
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
janani b35f6cbc2017-03-24 21:56:58 +053023import org.onosproject.config.DynamicConfigEvent;
24import org.onosproject.config.DynamicConfigListener;
25import org.onosproject.config.DynamicConfigService;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053026import org.onosproject.core.CoreService;
janani b35f6cbc2017-03-24 21:56:58 +053027import org.onosproject.core.IdGenerator;
28import org.onosproject.l3vpn.netl3vpn.AccessInfo;
29import org.onosproject.l3vpn.netl3vpn.BgpDriverInfo;
30import org.onosproject.l3vpn.netl3vpn.BgpInfo;
31import org.onosproject.l3vpn.netl3vpn.DeviceInfo;
32import org.onosproject.l3vpn.netl3vpn.FullMeshVpnConfig;
33import org.onosproject.l3vpn.netl3vpn.HubSpokeVpnConfig;
34import org.onosproject.l3vpn.netl3vpn.InterfaceInfo;
35import org.onosproject.l3vpn.netl3vpn.NetL3VpnException;
36import org.onosproject.l3vpn.netl3vpn.NetL3VpnStore;
37import org.onosproject.l3vpn.netl3vpn.VpnConfig;
38import org.onosproject.l3vpn.netl3vpn.VpnInstance;
39import org.onosproject.l3vpn.netl3vpn.VpnSiteRole;
40import org.onosproject.l3vpn.netl3vpn.VpnType;
41import org.onosproject.net.Device;
42import org.onosproject.net.DeviceId;
43import org.onosproject.net.Port;
44import org.onosproject.net.device.DeviceService;
45import org.onosproject.net.driver.DriverService;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053046import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev20130715.IetfInetTypes;
janani b35f6cbc2017-03-24 21:56:58 +053047import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.devices.device.Interfaces;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053048import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.IetfL3VpnSvc;
janani b35f6cbc2017-03-24 21:56:58 +053049import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.DefaultL3VpnSvc;
50import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.L3VpnSvc;
51import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.VpnAttachment;
52import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.AttachmentFlavor;
53import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.attachmentflavor.DefaultVpnId;
54import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.Sites;
55import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.VpnServices;
56import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.Site;
57import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.SiteNetworkAccesses;
58import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.sitenetworkaccesses.SiteNetworkAccess;
59import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.l3vpnsvc.vpnservices.VpnSvc;
60import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.Bearer;
61import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.DefaultBearer;
62import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.DefaultRequestedType;
63import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.RequestedType;
64import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentipconnection.IpConnection;
65import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siterouting.RoutingProtocols;
66import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siterouting.routingprotocols.RoutingProtocol;
67import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.NetworkInstances;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053068import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715.IetfYangTypes;
69import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.L3VpnSvcExt;
janani b35f6cbc2017-03-24 21:56:58 +053070import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.DefaultAugmentedL3VpnBearer;
71import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.requestedtype.DefaultAugmentedL3VpnRequestedType;
72import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.RequestedTypeChoice;
73import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultDot1Qcase;
74import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.l3vpn.svc.ext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultPhysicalCase;
75import org.onosproject.yang.model.DataNode;
76import org.onosproject.yang.model.DefaultModelObjectData;
77import org.onosproject.yang.model.ModelConverter;
78import org.onosproject.yang.model.ModelObject;
79import org.onosproject.yang.model.ModelObjectData;
80import org.onosproject.yang.model.ModelObjectId;
81import org.onosproject.yang.model.NodeKey;
82import org.onosproject.yang.model.ResourceData;
83import org.onosproject.yang.model.ResourceId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053084import org.onosproject.yang.model.YangModel;
85import org.onosproject.yang.model.YangModuleId;
86import org.onosproject.yang.runtime.DefaultAppModuleInfo;
87import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
88import org.onosproject.yang.runtime.ModelRegistrationParam;
89import org.onosproject.yang.runtime.YangModelRegistry;
90import org.slf4j.Logger;
91import org.slf4j.LoggerFactory;
92
93import java.util.Iterator;
janani b35f6cbc2017-03-24 21:56:58 +053094import java.util.List;
95import java.util.Map;
96import java.util.concurrent.ExecutorService;
97import java.util.concurrent.Executors;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053098
janani b35f6cbc2017-03-24 21:56:58 +053099import static org.onlab.util.Tools.groupedThreads;
100import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
101import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
102import static org.onosproject.l3vpn.netl3vpn.impl.BgpConstructionUtil.createBgpInfo;
103import static org.onosproject.l3vpn.netl3vpn.impl.InsConstructionUtil.createInstance;
104import static org.onosproject.l3vpn.netl3vpn.impl.IntConstructionUtil.createInterface;
105import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.BEARER_NULL;
106import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.CONS_HUNDRED;
107import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.DEVICE_INFO_NULL;
108import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.EVENT_NOT_SUPPORTED;
109import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT;
110import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT_EXCEEDED;
111import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.INT_INFO_NULL;
112import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.IP_INT_INFO_NULL;
113import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MG_MT_ADD;
114import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.PORT_NAME;
115import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_ROLE_NULL;
116import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_VPN_MISMATCH;
117import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_ATTACHMENT_NULL;
118import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_POLICY_NOT_SUPPORTED;
119import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_TYPE_UNSUPPORTED;
120import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getBgpCreateConfigObj;
121import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntCreateModObj;
122import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntNotAvailable;
123import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getMgmtIpUnAvailErr;
124import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForL3VpnSvc;
125import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForSites;
126import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getResourceData;
127import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getRole;
128import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnCreateModObj;
129import static org.onosproject.l3vpn.netl3vpn.VpnType.HUB;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530130import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.getYangModel;
131
132/**
133 * The IETF net l3vpn manager implementation.
janani bf41dec32017-03-24 18:44:07 +0530134 * // TODO: Implementation of the manager class.
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530135 */
136@Component(immediate = true)
137public class NetL3vpnManager {
138
139 private static final String APP_ID = "org.onosproject.app.l3vpn";
janani b35f6cbc2017-03-24 21:56:58 +0530140 private static final String L3_VPN_ID_TOPIC = "l3vpn-id";
141 private static final String ONOS_NET_L3VPN = "onos/netl3vpn";
142 private static final String EVENT_HANDLER = "event-handler-%d";
143
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530144 private final Logger log = LoggerFactory.getLogger(getClass());
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected CoreService coreService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
janani b35f6cbc2017-03-24 21:56:58 +0530150 protected DriverService driverService;
151
152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 protected DeviceService deviceService;
154
155 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530156 protected YangModelRegistry modelRegistry;
157
janani b35f6cbc2017-03-24 21:56:58 +0530158 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
159 protected ModelConverter modelConverter;
160
161 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
162 protected DynamicConfigService configService;
163
164 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
165 protected NetL3VpnStore l3VpnStore;
166
167 protected IdGenerator l3VpnIdGen;
168
169 private DynamicConfigListener configListener = new InternalConfigListener();
170
171 private ModelRegistrationParam regParam;
172
173 private ExecutorService executor = Executors.newSingleThreadExecutor(
174 groupedThreads(ONOS_NET_L3VPN, EVENT_HANDLER, log));
175
176 private ResourceId id;
177 private ResourceId module;
178 private ResourceId sites;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530179
180 @Activate
181 protected void activate() {
182 coreService.registerApplication(APP_ID);
janani b35f6cbc2017-03-24 21:56:58 +0530183 l3VpnIdGen = coreService.getIdGenerator(L3_VPN_ID_TOPIC);
184 registerModel();
185 getResourceId();
186 configService.addListener(configListener);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530187 log.info("Started");
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530188 }
189
190 @Deactivate
191 protected void deactivate() {
192 modelRegistry.unregisterModel(regParam);
janani b35f6cbc2017-03-24 21:56:58 +0530193 configService.removeListener(configListener);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530194 log.info("Stopped");
195 }
196
197 private void registerModel() {
198 YangModel model = getYangModel(getClass());
199 Iterator<YangModuleId> it = model.getYangModulesId().iterator();
200
201 //Create model registration param.
202 ModelRegistrationParam.Builder b =
203 DefaultModelRegistrationParam.builder().setYangModel(model);
204
205 YangModuleId id;
206 while (it.hasNext()) {
207 id = it.next();
208 switch (id.moduleName()) {
209 case "ietf-inet-types":
210 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
211 IetfInetTypes.class, null));
212 break;
213 case "ietf-l3vpn-svc":
214 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
215 IetfL3VpnSvc.class, null));
216 break;
217 case "ietf-yang-types":
218 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
219 IetfYangTypes.class, null));
220 break;
221 case "l3vpn-svc-ext":
222 b.addAppModuleInfo(id, new DefaultAppModuleInfo(
223 L3VpnSvcExt.class, null));
224 break;
225 default:
226 break;
227 }
228 }
229 regParam = b.build();
230 modelRegistry.registerModel(regParam);
231 }
janani b35f6cbc2017-03-24 21:56:58 +0530232
233 /**
234 * Returns id as string. If the id is not in the freed list a new id is
235 * generated else the id from the freed list is used.
236 *
237 * @return id
238 */
239 private String getIdFromGen() {
240 Long value;
241 Iterable<Long> freeIds = l3VpnStore.getFreedIdList();
242 Iterator<Long> it = freeIds.iterator();
243 if (it.hasNext()) {
244 value = it.next();
245 l3VpnStore.removeIdFromFreeList(value);
246 } else {
247 value = l3VpnIdGen.getNewId();
248 }
249 if (value > ID_LIMIT) {
250 throw new RuntimeException(ID_LIMIT_EXCEEDED);
251 }
252 return CONS_HUNDRED + String.valueOf(value);
253 }
254
255 /**
256 * Returns the resource id, after constructing model object id and
257 * converting it.
258 */
259 private void getResourceId() {
260
261 ModelObjectId moduleId = ModelObjectId.builder().build();
262 module = getResourceVal(moduleId);
263
264 ModelObjectId svcId = getModIdForL3VpnSvc();
265 id = getResourceVal(svcId);
266
267 ModelObjectId sitesId = getModIdForSites();
268 sites = getResourceVal(sitesId);
269 }
270
271 /**
272 * Returns resource id from model converter.
273 *
274 * @param modelId model object id
275 * @return resource id
276 */
277 private ResourceId getResourceVal(ModelObjectId modelId) {
278 DefaultModelObjectData.Builder data = DefaultModelObjectData.builder()
279 .identifer(modelId);
280 ResourceData resData = modelConverter.createDataNode(data.build());
281 return resData.resourceId();
282 }
283
284 /**
285 * Processes create request from the store, by taking the root object.
286 * The root object is then used for l3VPN processing.
287 *
288 * @param storeId store resource id
289 */
290 private void processCreateFromStore(ResourceId storeId) {
291 List<ModelObject> objects = getModelObjects(storeId, module);
292 for (ModelObject obj : objects) {
293 if (obj instanceof DefaultL3VpnSvc) {
294 DefaultL3VpnSvc l3VpnSvc = (DefaultL3VpnSvc) obj;
295 createGlobalConfig(l3VpnSvc);
296 }
297 }
298 }
299
300 /**
301 * Returns model objects of the store. The data node is read from the
302 * config store. This returns the resource id's node. So the node's
303 * parent resource id is taken and the data node is given to model
304 * converter.
305 *
306 * @param storeId store resource id
307 * @param appId parent resource id
308 * @return model objects
309 */
310 public List<ModelObject> getModelObjects(ResourceId storeId,
311 ResourceId appId) {
312 DataNode dataNode = configService.readNode(storeId, null);
313 ResourceData data = getResourceData(dataNode, appId);
314 ModelObjectData modelData = modelConverter.createModel(data);
315 return modelData.modelObjects();
316 }
317
318 /**
319 * Returns true if the event resource id points to the root level node
320 * only and event is for addition and deletion; false otherwise.
321 *
322 * @param event config event
323 * @return true if event is supported; false otherwise
324 */
325 public boolean isSupported(DynamicConfigEvent event) {
326 ResourceId rsId = event.subject();
327 List<NodeKey> storeKeys = rsId.nodeKeys();
328 List<NodeKey> regKeys = id.nodeKeys();
329 if (storeKeys != null) {
330 if (storeKeys.size() == 1) {
331 return storeKeys.get(0).equals(regKeys.get(1)) &&
332 (event.type() == NODE_ADDED ||
333 event.type() == NODE_DELETED);
334 }
335 }
336 return false;
337 }
338
339 /***
340 * Creation of all configuration in standard device model.
341 *
342 * @param l3VpnSvc l3VPN service object
343 */
344 void createGlobalConfig(L3VpnSvc l3VpnSvc) {
345 if (l3VpnSvc.vpnServices() != null) {
346 createVpnServices(l3VpnSvc.vpnServices());
347 }
348 if (l3VpnSvc.sites() != null) {
349 createInterfaceConfig(l3VpnSvc.sites());
350 }
351 }
352
353 /**
354 * Creates the VPN instances from the VPN services object, if only that
355 * VPN instance is not already created.
356 *
357 * @param vpnSvcs VPN services object
358 */
359 private void createVpnServices(VpnServices vpnSvcs) {
360 if (vpnSvcs != null && vpnSvcs.vpnSvc() != null) {
361 List<VpnSvc> svcList = vpnSvcs.vpnSvc();
362 for (VpnSvc svc : svcList) {
363 String vpnName = svc.vpnId().string();
364 l3VpnStore.addVpnInsIfAbsent(vpnName, new VpnInstance(vpnName));
365 }
366 }
367 }
368
369 /**
370 * Creates interface configuration from the site network access if
371 * available.
372 *
373 * @param sites sites object
374 */
375 private void createInterfaceConfig(Sites sites) {
376 if (sites.site() != null) {
377 List<Site> sitesList = sites.site();
378 for (Site site : sitesList) {
379 if (site.siteNetworkAccesses() != null) {
380 SiteNetworkAccesses accesses = site.siteNetworkAccesses();
381 List<SiteNetworkAccess> accessList =
382 accesses.siteNetworkAccess();
383 for (SiteNetworkAccess access : accessList) {
384 createFromAccess(access, site.siteId().string());
385 }
386 }
387 }
388 }
389 }
390
391 /**
392 * Creates the interface and VPN related configurations from the access
393 * and site id value.
394 *
395 * @param access site network access
396 * @param siteId site id
397 */
398 private void createFromAccess(SiteNetworkAccess access, String siteId) {
399 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
400 Map<String, VpnInstance> insMap = l3VpnStore.getVpnInstances();
401 String accessId = access.siteNetworkAccessId().string();
402 AccessInfo info = new AccessInfo(siteId, accessId);
403
404 if (intMap.get(info) == null) {
405 VpnSiteRole siteRole = getSiteRole(access.vpnAttachment());
406 VpnInstance instance = insMap.get(siteRole.name());
407 if (instance == null) {
408 throw new NetL3VpnException(SITE_VPN_MISMATCH);
409 }
410 buildFromAccess(instance, info, access, siteRole);
411 }
412 }
413
414 /**
415 * Returns the VPN site role from the VPN attachment.
416 *
417 * @param attach VPN attachment
418 * @return VPN site role
419 */
420 private VpnSiteRole getSiteRole(VpnAttachment attach) {
421 if (attach == null || attach.attachmentFlavor() == null) {
422 throw new NetL3VpnException(VPN_ATTACHMENT_NULL);
423 }
424 AttachmentFlavor flavor = attach.attachmentFlavor();
425 if (!(flavor instanceof DefaultVpnId)) {
426 throw new NetL3VpnException(VPN_POLICY_NOT_SUPPORTED);
427 }
428 DefaultVpnId vpnId = (DefaultVpnId) flavor;
429 if (vpnId.siteRole() == null) {
430 throw new NetL3VpnException(SITE_ROLE_NULL);
431 }
432 VpnType role = getRole(vpnId.siteRole());
433 VpnSiteRole vpnRole = new VpnSiteRole(
434 String.valueOf(vpnId.vpnId()), role);
435 return vpnRole;
436 }
437
438 /**
439 * Builds the required details for device standard model from the site
440 * network access info available.
441 *
442 * @param instance VPN instance
443 * @param info access info
444 * @param access network access
445 * @param role VPN site role
446 */
447 private void buildFromAccess(VpnInstance instance, AccessInfo info,
448 SiteNetworkAccess access, VpnSiteRole role) {
449 Bearer bearer = access.bearer();
450 if (bearer == null) {
451 throw new NetL3VpnException(BEARER_NULL);
452 }
453
454 RequestedType reqType = bearer.requestedType();
455 IpConnection connect = access.ipConnection();
456 RoutingProtocols pro = access.routingProtocols();
457
458 if (reqType == null || connect == null) {
459 throw new NetL3VpnException(IP_INT_INFO_NULL);
460 }
461 buildDeviceDetails(instance, info, role, bearer, connect,
462 reqType, pro);
463 }
464
465 /**
466 * Builds the device details such as, VPN instance value if it is for
467 * the first time, interface values and BGP info if available in service.
468 *
469 * @param instance VPN instance
470 * @param accInfo access info
471 * @param role VPN site role
472 * @param bearer bearer object
473 * @param connect ip connect object
474 * @param reqType requested type
475 * @param pro routing protocol
476 */
477 private void buildDeviceDetails(VpnInstance instance, AccessInfo accInfo,
478 VpnSiteRole role, Bearer bearer,
479 IpConnection connect, RequestedType reqType,
480 RoutingProtocols pro) {
481 Map<AccessInfo, InterfaceInfo> interMap = l3VpnStore.getInterfaceInfo();
482 InterfaceInfo intInfo = interMap.get(accInfo);
483 if (intInfo != null) {
484 return;
485 }
486
487 DeviceInfo info = buildDevVpnIns(bearer, instance, role, connect);
488 String portName = getInterfaceName(info, reqType);
489 buildDevVpnInt(info, instance, connect, portName, accInfo);
490
491 if (pro != null && pro.routingProtocol() != null) {
492 buildBgpInfo(pro.routingProtocol(), info,
493 role.name(), connect, accInfo);
494 }
495 InterfaceInfo interInfo = new InterfaceInfo(info, portName,
496 instance.vpnName());
497 l3VpnStore.addInterfaceInfo(accInfo, interInfo);
498 }
499
500 /**
501 * Builds device VPN instance with the service objects. It returns
502 *
503 * @param bearer bearer object
504 * @param ins VPN instance
505 * @param role VPN site role
506 * @param connect ip connection
507 * @return return
508 */
509 private DeviceInfo buildDevVpnIns(Bearer bearer, VpnInstance ins,
510 VpnSiteRole role, IpConnection connect) {
511 DefaultAugmentedL3VpnBearer augBearer = ((DefaultBearer) bearer)
512 .augmentation(DefaultAugmentedL3VpnBearer.class);
513 DeviceId id = getDeviceId(augBearer);
514 Map<DeviceId, DeviceInfo> devices = ins.devInfo();
515 DeviceInfo info = null;
516 if (devices != null) {
517 info = devices.get(id);
518 }
519 if (info == null) {
520 info = createVpnInstance(id, role, ins, connect);
521 }
522 return info;
523 }
524
525 /**
526 * Returns the device id from the bearer augment attachment of service.
527 * If the attachment in augment is not available it throws error.
528 *
529 * @param attach augmented bearer
530 * @return device id
531 */
532 private DeviceId getDeviceId(DefaultAugmentedL3VpnBearer attach) {
533 if (attach == null || attach.bearerAttachment() == null ||
534 attach.bearerAttachment().peMgmtIp() == null ||
535 attach.bearerAttachment().peMgmtIp().string() == null) {
536 throw new NetL3VpnException(DEVICE_INFO_NULL);
537 }
538 String ip = attach.bearerAttachment().peMgmtIp().string();
539 return getId(ip);
540 }
541
542 /**
543 * Returns the device id whose management ip address matches with the ip
544 * received.
545 *
546 * @param ip ip address
547 * @return device id
548 */
549 public DeviceId getId(String ip) {
550 for (Device device : deviceService.getAvailableDevices()) {
551 String val = device.annotations().value(MG_MT_ADD);
552 if (ip.equals(val)) {
553 return device.id();
554 }
555 }
556 throw new NetL3VpnException(getMgmtIpUnAvailErr(ip));
557 }
558
559 /**
560 * Creates the VPN instance by constructing standard device model of
561 * instances. It adds the RD and RT values to the VPN instance.
562 *
563 * @param id device id
564 * @param role VPN site role
565 * @param inst VPN instance
566 * @param ip ip connection
567 * @return device info
568 */
569 private DeviceInfo createVpnInstance(DeviceId id, VpnSiteRole role,
570 VpnInstance inst, IpConnection ip) {
571 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
572 generateRdRt(inst, role);
573 DeviceInfo info = new DeviceInfo(id);
574 inst.addDevInfo(id, info);
575
576 NetworkInstances instances = createInstance(inst, role, ip);
577 ModelObjectData devMod = getVpnCreateModObj(intMap, instances,
578 id.toString());
579 ModelObjectData driMod = info.processCreateInstance(driverService,
580 devMod);
581 ResourceData resData = modelConverter.createDataNode(driMod);
582 addToStore(resData);
583 return info;
584 }
585
586 /**
587 * Adds the resource data that is received from the driver, after
588 * converting from the model object data.
589 *
590 * @param resData resource data
591 */
592 private void addToStore(ResourceData resData) {
593 if (resData != null && resData.dataNodes() != null) {
594 List<DataNode> dataNodes = resData.dataNodes();
595 for (DataNode node : dataNodes) {
596 configService.createNodeRecursive(resData.resourceId(), node);
597 }
598 }
599 }
600
601 /**
602 * Generates RD and RT value for the VPN instance for the first time VPN
603 * instance creation.
604 *
605 * @param ins VPN instance
606 * @param role VPN site role
607 */
608 private void generateRdRt(VpnInstance ins, VpnSiteRole role) {
609 ins.type(role.role());
610 VpnConfig config = ins.vpnConfig();
611 String rd = null;
612 if (config == null) {
613 rd = getIdFromGen();
614 }
615 switch (ins.type()) {
616 case ANY_TO_ANY:
617 if (config == null) {
618 config = new FullMeshVpnConfig(rd);
619 config.rd(rd);
620 }
621 break;
622
623 case HUB:
624 case SPOKE:
625 if (config == null) {
626 config = new HubSpokeVpnConfig();
627 config.rd(rd);
628 }
629 createImpRtVal((HubSpokeVpnConfig) config, ins.type());
630 createExpRtVal((HubSpokeVpnConfig) config, ins.type());
631 break;
632
633 default:
634 throw new NetL3VpnException(VPN_TYPE_UNSUPPORTED);
635 }
636 ins.vpnConfig(config);
637 }
638
639 /**
640 * Creates import RT value for HUB and SPOKE, according to the type, if
641 * the values are not present.
642 *
643 * @param config VPN config
644 * @param type VPN type
645 */
646 private void createImpRtVal(HubSpokeVpnConfig config, VpnType type) {
647 if (type == HUB) {
648 if (config.hubImpRt() != null) {
649 return;
650 }
651 setHubImpRt(config);
652 } else {
653 if (config.spokeImpRt() != null) {
654 return;
655 }
656 config.spokeImpRt(config.rd());
657 }
658 }
659
660 /**
661 * Sets the HUB import RT, from the spoke export RT. If it is not
662 * available a new ID is generated.
663 *
664 * @param config VPN config
665 */
666 public void setHubImpRt(HubSpokeVpnConfig config) {
667 String hubImp;
668 if (config.spokeExpRt() != null) {
669 hubImp = config.spokeExpRt();
670 } else {
671 hubImp = getIdFromGen();
672 }
673 config.hubImpRt(hubImp);
674 }
675
676 /**
677 * Creates export RT value for HUB and SPOKE, according to the type, if
678 * the values are not present.
679 *
680 * @param config VPN config
681 * @param type VPN type
682 */
683 private void createExpRtVal(HubSpokeVpnConfig config, VpnType type) {
684 if (type == HUB) {
685 if (config.hubExpRt() != null) {
686 return;
687 }
688 config.hubExpRt(config.rd());
689 } else {
690 if (config.spokeExpRt() != null) {
691 return;
692 }
693 setSpokeExpRt(config);
694 }
695 }
696
697 /**
698 * Sets the SPOKE export RT, from the hub import RT. If it is not
699 * available a new ID is generated.
700 *
701 * @param config VPN config
702 */
703 public void setSpokeExpRt(HubSpokeVpnConfig config) {
704 String spokeExp;
705 if (config.hubImpRt() != null) {
706 spokeExp = config.hubImpRt();
707 } else {
708 spokeExp = getIdFromGen();
709 }
710 config.spokeExpRt(spokeExp);
711 }
712
713 /**
714 * Returns the interface name from the requested type service object.
715 *
716 * @param info device info
717 * @param reqType requested type
718 * @return interface name
719 */
720 private String getInterfaceName(DeviceInfo info, RequestedType reqType) {
721 DefaultAugmentedL3VpnRequestedType req =
722 ((DefaultRequestedType) reqType).augmentation(
723 DefaultAugmentedL3VpnRequestedType.class);
724 if (req == null || req.requestedTypeProfile() == null ||
725 req.requestedTypeProfile().requestedTypeChoice() == null) {
726 throw new NetL3VpnException(INT_INFO_NULL);
727 }
728 RequestedTypeChoice reqChoice = req.requestedTypeProfile()
729 .requestedTypeChoice();
730 return getNameFromChoice(reqChoice, info.deviceId());
731 }
732
733 /**
734 * Returns the interface name from the type choice provided.
735 *
736 * @param choice service choice
737 * @param id device id
738 * @return interface name
739 */
740 private String getNameFromChoice(RequestedTypeChoice choice, DeviceId id) {
741 if (choice == null) {
742 throw new NetL3VpnException(INT_INFO_NULL);
743 }
744 String intName;
745 if (choice instanceof DefaultDot1Qcase) {
746 if (((DefaultDot1Qcase) choice).dot1q() == null ||
747 ((DefaultDot1Qcase) choice).dot1q()
748 .physicalIf() == null) {
749 throw new NetL3VpnException(INT_INFO_NULL);
750 }
751 intName = ((DefaultDot1Qcase) choice).dot1q().physicalIf();
752 } else {
753 if (((DefaultPhysicalCase) choice).physical() == null ||
754 ((DefaultPhysicalCase) choice).physical()
755 .physicalIf() == null) {
756 throw new NetL3VpnException(INT_INFO_NULL);
757 }
758 intName = ((DefaultPhysicalCase) choice).physical().physicalIf();
759 }
760 return getPortName(intName, id);
761 }
762
763 /**
764 * Returns the port name when it the port is available in the device.
765 *
766 * @param intName interface name
767 * @param id device id
768 * @return port name
769 */
770 private String getPortName(String intName, DeviceId id) {
771 List<Port> ports = deviceService.getPorts(id);
772 for (Port port : ports) {
773 String pName = port.annotations().value(PORT_NAME);
774 if (pName.equals(intName)) {
775 return intName;
776 }
777 }
778 throw new NetL3VpnException(getIntNotAvailable(intName));
779 }
780
781 /**
782 * Builds the interface for the device binding with the VPN instance.
783 *
784 * @param info device info
785 * @param ins VPN instance
786 * @param connect IP connection
787 * @param pName port name
788 * @param access access info
789 */
790 private void buildDevVpnInt(DeviceInfo info, VpnInstance ins,
791 IpConnection connect, String pName,
792 AccessInfo access) {
793 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
794 info.addAccessInfo(access);
795 info.addIfName(pName);
796 Interfaces interfaces = createInterface(pName, ins.vpnName(),
797 connect);
798 ModelObjectData devMod = getIntCreateModObj(
799 intMap, interfaces, info.deviceId().toString());
800 ModelObjectData driMod = info.processCreateInterface(driverService,
801 devMod);
802 ResourceData resData = modelConverter.createDataNode(driMod);
803 addToStore(resData);
804 }
805
806 /**
807 * Builds the BGP information from the routes that are given from the
808 * service.
809 *
810 * @param routes routing protocol
811 * @param info device info
812 * @param name VPN name
813 * @param connect IP connection
814 * @param access access info
815 */
816 private void buildBgpInfo(List<RoutingProtocol> routes, DeviceInfo info,
817 String name, IpConnection connect,
818 AccessInfo access) {
819 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
820 BgpInfo intBgp = createBgpInfo(routes, info, name, connect, access);
821 if (intBgp != null) {
822 intBgp.vpnName(name);
823 BgpDriverInfo config = getBgpCreateConfigObj(
824 bgpMap, info.deviceId().toString());
825 ModelObjectData driData = info.processCreateBgpInfo(
826 driverService, intBgp, config);
827 l3VpnStore.addBgpInfo(info.bgpInfo(), info.deviceId());
828 ResourceData resData = modelConverter.createDataNode(driData);
829 addToStore(resData);
830 }
831 }
832
833 /**
834 * Representation of internal listener, listening for dynamic config event.
835 */
836 private class InternalConfigListener implements DynamicConfigListener {
837
838 @Override
839 public boolean isRelevant(DynamicConfigEvent event) {
840 return isSupported(event);
841 }
842
843 @Override
844 public void event(DynamicConfigEvent event) {
845 executor.execute(() -> {
846 try {
847 ResourceId rsId = event.subject();
848 switch (event.type()) {
849 case NODE_ADDED:
850 processCreateFromStore(rsId);
851 break;
852
853 case NODE_DELETED:
854 //TODO: To be committed.
855 break;
856
857 default:
858 throw new NetL3VpnException(EVENT_NOT_SUPPORTED);
859 }
860 } catch (Exception e) {
861 log.warn("Failed to process {}", event, e);
862 }
863 });
864 }
865 }
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530866}