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