blob: 6121d7b19edbab91beb120ed72640287f3e0892c [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
janani b36b1d772017-03-27 15:01:28 +0530183 private final DynamicConfigListener configListener = new
184 InternalConfigListener();
janani b35f6cbc2017-03-24 21:56:58 +0530185
Bharat saraswalcdfda202017-03-24 23:40:50 +0530186 private final InternalLeadershipListener leadershipEventListener =
187 new InternalLeadershipListener();
188
janani b35f6cbc2017-03-24 21:56:58 +0530189 private ModelRegistrationParam regParam;
190
191 private ExecutorService executor = Executors.newSingleThreadExecutor(
192 groupedThreads(ONOS_NET_L3VPN, EVENT_HANDLER, log));
193
194 private ResourceId id;
195 private ResourceId module;
196 private ResourceId sites;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530197 private boolean isElectedLeader = 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 saraswal5b5bd9a2017-03-27 18:59:55 +0530322 if (isElectedLeader) {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530323 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) {
Bharat saraswal5b5bd9a2017-03-27 18:59:55 +0530340 if (isElectedLeader) {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530341 //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);
janani b36b1d772017-03-27 15:01:28 +0530628 l3VpnStore.addVpnIns(inst.vpnName(), inst);
janani b35f6cbc2017-03-24 21:56:58 +0530629 return info;
630 }
631
632 /**
633 * Adds the resource data that is received from the driver, after
634 * converting from the model object data.
635 *
636 * @param resData resource data
637 */
638 private void addToStore(ResourceData resData) {
639 if (resData != null && resData.dataNodes() != null) {
640 List<DataNode> dataNodes = resData.dataNodes();
641 for (DataNode node : dataNodes) {
642 configService.createNodeRecursive(resData.resourceId(), node);
643 }
644 }
645 }
646
647 /**
648 * Generates RD and RT value for the VPN instance for the first time VPN
649 * instance creation.
650 *
651 * @param ins VPN instance
652 * @param role VPN site role
653 */
654 private void generateRdRt(VpnInstance ins, VpnSiteRole role) {
655 ins.type(role.role());
656 VpnConfig config = ins.vpnConfig();
657 String rd = null;
658 if (config == null) {
659 rd = getIdFromGen();
660 }
661 switch (ins.type()) {
662 case ANY_TO_ANY:
663 if (config == null) {
664 config = new FullMeshVpnConfig(rd);
665 config.rd(rd);
666 }
667 break;
668
669 case HUB:
670 case SPOKE:
671 if (config == null) {
672 config = new HubSpokeVpnConfig();
673 config.rd(rd);
674 }
675 createImpRtVal((HubSpokeVpnConfig) config, ins.type());
676 createExpRtVal((HubSpokeVpnConfig) config, ins.type());
677 break;
678
679 default:
680 throw new NetL3VpnException(VPN_TYPE_UNSUPPORTED);
681 }
682 ins.vpnConfig(config);
683 }
684
685 /**
686 * Creates import RT value for HUB and SPOKE, according to the type, if
687 * the values are not present.
688 *
689 * @param config VPN config
690 * @param type VPN type
691 */
692 private void createImpRtVal(HubSpokeVpnConfig config, VpnType type) {
693 if (type == HUB) {
694 if (config.hubImpRt() != null) {
695 return;
696 }
697 setHubImpRt(config);
698 } else {
699 if (config.spokeImpRt() != null) {
700 return;
701 }
702 config.spokeImpRt(config.rd());
703 }
704 }
705
706 /**
707 * Sets the HUB import RT, from the spoke export RT. If it is not
708 * available a new ID is generated.
709 *
710 * @param config VPN config
711 */
712 public void setHubImpRt(HubSpokeVpnConfig config) {
713 String hubImp;
714 if (config.spokeExpRt() != null) {
715 hubImp = config.spokeExpRt();
716 } else {
717 hubImp = getIdFromGen();
718 }
719 config.hubImpRt(hubImp);
720 }
721
722 /**
723 * Creates export RT value for HUB and SPOKE, according to the type, if
724 * the values are not present.
725 *
726 * @param config VPN config
727 * @param type VPN type
728 */
729 private void createExpRtVal(HubSpokeVpnConfig config, VpnType type) {
730 if (type == HUB) {
731 if (config.hubExpRt() != null) {
732 return;
733 }
734 config.hubExpRt(config.rd());
735 } else {
736 if (config.spokeExpRt() != null) {
737 return;
738 }
739 setSpokeExpRt(config);
740 }
741 }
742
743 /**
744 * Sets the SPOKE export RT, from the hub import RT. If it is not
745 * available a new ID is generated.
746 *
747 * @param config VPN config
748 */
749 public void setSpokeExpRt(HubSpokeVpnConfig config) {
750 String spokeExp;
751 if (config.hubImpRt() != null) {
752 spokeExp = config.hubImpRt();
753 } else {
754 spokeExp = getIdFromGen();
755 }
756 config.spokeExpRt(spokeExp);
757 }
758
759 /**
760 * Returns the interface name from the requested type service object.
761 *
762 * @param info device info
763 * @param reqType requested type
764 * @return interface name
765 */
766 private String getInterfaceName(DeviceInfo info, RequestedType reqType) {
767 DefaultAugmentedL3VpnRequestedType req =
768 ((DefaultRequestedType) reqType).augmentation(
769 DefaultAugmentedL3VpnRequestedType.class);
770 if (req == null || req.requestedTypeProfile() == null ||
771 req.requestedTypeProfile().requestedTypeChoice() == null) {
772 throw new NetL3VpnException(INT_INFO_NULL);
773 }
774 RequestedTypeChoice reqChoice = req.requestedTypeProfile()
775 .requestedTypeChoice();
776 return getNameFromChoice(reqChoice, info.deviceId());
777 }
778
779 /**
780 * Returns the interface name from the type choice provided.
781 *
782 * @param choice service choice
783 * @param id device id
784 * @return interface name
785 */
786 private String getNameFromChoice(RequestedTypeChoice choice, DeviceId id) {
787 if (choice == null) {
788 throw new NetL3VpnException(INT_INFO_NULL);
789 }
790 String intName;
791 if (choice instanceof DefaultDot1Qcase) {
792 if (((DefaultDot1Qcase) choice).dot1q() == null ||
793 ((DefaultDot1Qcase) choice).dot1q()
794 .physicalIf() == null) {
795 throw new NetL3VpnException(INT_INFO_NULL);
796 }
797 intName = ((DefaultDot1Qcase) choice).dot1q().physicalIf();
798 } else {
799 if (((DefaultPhysicalCase) choice).physical() == null ||
800 ((DefaultPhysicalCase) choice).physical()
801 .physicalIf() == null) {
802 throw new NetL3VpnException(INT_INFO_NULL);
803 }
804 intName = ((DefaultPhysicalCase) choice).physical().physicalIf();
805 }
806 return getPortName(intName, id);
807 }
808
809 /**
810 * Returns the port name when it the port is available in the device.
811 *
812 * @param intName interface name
813 * @param id device id
814 * @return port name
815 */
816 private String getPortName(String intName, DeviceId id) {
817 List<Port> ports = deviceService.getPorts(id);
818 for (Port port : ports) {
819 String pName = port.annotations().value(PORT_NAME);
820 if (pName.equals(intName)) {
821 return intName;
822 }
823 }
824 throw new NetL3VpnException(getIntNotAvailable(intName));
825 }
826
827 /**
828 * Builds the interface for the device binding with the VPN instance.
829 *
830 * @param info device info
831 * @param ins VPN instance
832 * @param connect IP connection
833 * @param pName port name
834 * @param access access info
835 */
836 private void buildDevVpnInt(DeviceInfo info, VpnInstance ins,
837 IpConnection connect, String pName,
838 AccessInfo access) {
839 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
840 info.addAccessInfo(access);
841 info.addIfName(pName);
842 Interfaces interfaces = createInterface(pName, ins.vpnName(),
843 connect);
844 ModelObjectData devMod = getIntCreateModObj(
845 intMap, interfaces, info.deviceId().toString());
846 ModelObjectData driMod = info.processCreateInterface(driverService,
847 devMod);
848 ResourceData resData = modelConverter.createDataNode(driMod);
849 addToStore(resData);
850 }
851
852 /**
853 * Builds the BGP information from the routes that are given from the
854 * service.
855 *
856 * @param routes routing protocol
857 * @param info device info
858 * @param name VPN name
859 * @param connect IP connection
860 * @param access access info
861 */
862 private void buildBgpInfo(List<RoutingProtocol> routes, DeviceInfo info,
863 String name, IpConnection connect,
864 AccessInfo access) {
865 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
866 BgpInfo intBgp = createBgpInfo(routes, info, name, connect, access);
867 if (intBgp != null) {
868 intBgp.vpnName(name);
869 BgpDriverInfo config = getBgpCreateConfigObj(
870 bgpMap, info.deviceId().toString());
871 ModelObjectData driData = info.processCreateBgpInfo(
872 driverService, intBgp, config);
873 l3VpnStore.addBgpInfo(info.bgpInfo(), info.deviceId());
874 ResourceData resData = modelConverter.createDataNode(driData);
875 addToStore(resData);
876 }
877 }
878
879 /**
880 * Representation of internal listener, listening for dynamic config event.
881 */
882 private class InternalConfigListener implements DynamicConfigListener {
883
884 @Override
885 public boolean isRelevant(DynamicConfigEvent event) {
886 return isSupported(event);
887 }
888
889 @Override
890 public void event(DynamicConfigEvent event) {
891 executor.execute(() -> {
892 try {
893 ResourceId rsId = event.subject();
894 switch (event.type()) {
895 case NODE_ADDED:
896 processCreateFromStore(rsId);
897 break;
898
899 case NODE_DELETED:
900 //TODO: To be committed.
901 break;
902
903 default:
904 throw new NetL3VpnException(EVENT_NOT_SUPPORTED);
905 }
906 } catch (Exception e) {
907 log.warn("Failed to process {}", event, e);
908 }
909 });
910 }
911 }
Bharat saraswalcdfda202017-03-24 23:40:50 +0530912
913 /**
914 * Signals that the leadership has changed.
915 *
916 * @param isLeader true if this instance is now the leader, otherwise false
917 */
918 private void leaderChanged(boolean isLeader) {
919 log.debug("Leader changed: {}", isLeader);
Bharat saraswal5b5bd9a2017-03-27 18:59:55 +0530920 isElectedLeader = isLeader;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530921 }
922
923 /**
924 * A listener for leadership events.
925 */
926 private class InternalLeadershipListener implements LeadershipEventListener {
927
928 @Override
929 public boolean isRelevant(LeadershipEvent event) {
930 return event.subject().topic().equals(appId.name());
931 }
932
933 @Override
934 public void event(LeadershipEvent event) {
935 switch (event.type()) {
936 case LEADER_CHANGED:
937 case LEADER_AND_CANDIDATES_CHANGED:
938 if (localNodeId.equals(event.subject().leaderNodeId())) {
939 log.info("Net l3vpn manager gained leadership");
940 leaderChanged(true);
941 } else {
942 log.info("Net l3vpn manager leader changed. New " +
943 "leader is {}", event.subject()
944 .leaderNodeId());
945 leaderChanged(false);
946 }
947 default:
948 break;
949 }
950 }
951 }
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530952}