blob: 7c1ccf883b65692f15a13d0bdd4193ec4a42ba9e [file] [log] [blame]
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +05303 *
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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import org.osgi.service.component.annotations.Activate;
19import org.osgi.service.component.annotations.Component;
20import org.osgi.service.component.annotations.Deactivate;
21import org.osgi.service.component.annotations.Reference;
22import org.osgi.service.component.annotations.ReferenceCardinality;
janani b176905a2017-03-28 17:36:18 +053023import org.onlab.util.AbstractAccumulator;
24import org.onlab.util.Accumulator;
Bharat saraswalcdfda202017-03-24 23:40:50 +053025import org.onosproject.cluster.ClusterService;
26import org.onosproject.cluster.LeadershipEvent;
27import org.onosproject.cluster.LeadershipEventListener;
28import org.onosproject.cluster.LeadershipService;
29import org.onosproject.cluster.NodeId;
janani b35f6cbc2017-03-24 21:56:58 +053030import org.onosproject.config.DynamicConfigEvent;
31import org.onosproject.config.DynamicConfigListener;
32import org.onosproject.config.DynamicConfigService;
janani b176905a2017-03-28 17:36:18 +053033import org.onosproject.config.FailedException;
34import org.onosproject.config.Filter;
Bharat saraswalcdfda202017-03-24 23:40:50 +053035import org.onosproject.core.ApplicationId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053036import org.onosproject.core.CoreService;
janani b35f6cbc2017-03-24 21:56:58 +053037import org.onosproject.core.IdGenerator;
38import org.onosproject.l3vpn.netl3vpn.AccessInfo;
39import org.onosproject.l3vpn.netl3vpn.BgpDriverInfo;
40import org.onosproject.l3vpn.netl3vpn.BgpInfo;
41import org.onosproject.l3vpn.netl3vpn.DeviceInfo;
42import org.onosproject.l3vpn.netl3vpn.FullMeshVpnConfig;
43import org.onosproject.l3vpn.netl3vpn.HubSpokeVpnConfig;
44import org.onosproject.l3vpn.netl3vpn.InterfaceInfo;
45import org.onosproject.l3vpn.netl3vpn.NetL3VpnException;
46import org.onosproject.l3vpn.netl3vpn.NetL3VpnStore;
47import org.onosproject.l3vpn.netl3vpn.VpnConfig;
48import org.onosproject.l3vpn.netl3vpn.VpnInstance;
49import org.onosproject.l3vpn.netl3vpn.VpnSiteRole;
50import org.onosproject.l3vpn.netl3vpn.VpnType;
janani b35f6cbc2017-03-24 21:56:58 +053051import org.onosproject.net.DeviceId;
52import org.onosproject.net.Port;
53import org.onosproject.net.device.DeviceService;
54import org.onosproject.net.driver.DriverService;
janani b9ed76be2017-08-29 19:11:33 +053055import org.onosproject.pce.pceservice.api.PceService;
Vidyashree Rama04147ca2017-05-26 11:32:47 +053056import org.onosproject.yang.gen.v1.ietfinterfaces.rev20140508.ietfinterfaces.devices.device.Interfaces;
57import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.DefaultL3VpnSvc;
58import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.L3VpnSvc;
59import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.VpnAttachment;
60import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.AttachmentFlavor;
61import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.accessvpnpolicy.vpnattachment.attachmentflavor.DefaultVpnId;
62import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.DefaultSites;
63import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.Sites;
64import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.VpnServices;
65import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.Site;
66import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.SiteNetworkAccesses;
67import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.sitenetworkaccesses.SiteNetworkAccess;
68import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.vpnservices.VpnSvc;
69import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.Bearer;
Vidyashree Rama04147ca2017-05-26 11:32:47 +053070import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.RequestedType;
71import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentipconnection.IpConnection;
72import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siterouting.RoutingProtocols;
73import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siterouting.routingprotocols.RoutingProtocol;
74import org.onosproject.yang.gen.v1.ietfnetworkinstance.rev20160623.ietfnetworkinstance.devices.device.NetworkInstances;
75import org.onosproject.yang.gen.v1.l3vpnsvcext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.DefaultAugmentedL3VpnBearer;
76import org.onosproject.yang.gen.v1.l3vpnsvcext.rev20160730.l3vpnsvcext.l3vpnsvc.sites.site.sitenetworkaccesses.sitenetworkaccess.bearer.requestedtype.DefaultAugmentedL3VpnRequestedType;
77import org.onosproject.yang.gen.v1.l3vpnsvcext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.RequestedTypeChoice;
78import org.onosproject.yang.gen.v1.l3vpnsvcext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultDot1Qcase;
79import org.onosproject.yang.gen.v1.l3vpnsvcext.rev20160730.l3vpnsvcext.requestedtypegrouping.requestedtypeprofile.requestedtypechoice.DefaultPhysicalCase;
janani b35f6cbc2017-03-24 21:56:58 +053080import org.onosproject.yang.model.DataNode;
81import org.onosproject.yang.model.DefaultModelObjectData;
82import org.onosproject.yang.model.ModelConverter;
83import org.onosproject.yang.model.ModelObject;
84import org.onosproject.yang.model.ModelObjectData;
85import org.onosproject.yang.model.ModelObjectId;
86import org.onosproject.yang.model.NodeKey;
87import org.onosproject.yang.model.ResourceData;
88import org.onosproject.yang.model.ResourceId;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053089import org.slf4j.Logger;
90import org.slf4j.LoggerFactory;
91
92import java.util.Iterator;
janani b35f6cbc2017-03-24 21:56:58 +053093import java.util.List;
94import java.util.Map;
janani b176905a2017-03-28 17:36:18 +053095import java.util.Timer;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +053096
janani b176905a2017-03-28 17:36:18 +053097import static com.google.common.base.Preconditions.checkNotNull;
janani b35f6cbc2017-03-24 21:56:58 +053098import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
99import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
Bharat saraswalcdfda202017-03-24 23:40:50 +0530100import static org.onosproject.l3vpn.netl3vpn.VpnType.HUB;
janani b35f6cbc2017-03-24 21:56:58 +0530101import static org.onosproject.l3vpn.netl3vpn.impl.BgpConstructionUtil.createBgpInfo;
102import static org.onosproject.l3vpn.netl3vpn.impl.InsConstructionUtil.createInstance;
janani b176905a2017-03-28 17:36:18 +0530103import static org.onosproject.l3vpn.netl3vpn.impl.InsConstructionUtil.deleteInstance;
janani b35f6cbc2017-03-24 21:56:58 +0530104import 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;
janani b176905a2017-03-28 17:36:18 +0530108import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.EVENT_NULL;
janani b35f6cbc2017-03-24 21:56:58 +0530109import 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;
janani b176905a2017-03-28 17:36:18 +0530113import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_BATCH_MS;
114import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_EVENTS;
115import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_IDLE_MS;
janani b35f6cbc2017-03-24 21:56:58 +0530116import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.PORT_NAME;
117import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_ROLE_NULL;
118import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.SITE_VPN_MISMATCH;
janani b176905a2017-03-28 17:36:18 +0530119import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.TIMER;
120import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.UNKNOWN_EVENT;
janani b35f6cbc2017-03-24 21:56:58 +0530121import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_ATTACHMENT_NULL;
122import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_POLICY_NOT_SUPPORTED;
123import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_TYPE_UNSUPPORTED;
124import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getBgpCreateConfigObj;
janani b9ed76be2017-08-29 19:11:33 +0530125import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getId;
janani b35f6cbc2017-03-24 21:56:58 +0530126import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntCreateModObj;
127import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntNotAvailable;
janani b35f6cbc2017-03-24 21:56:58 +0530128import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForL3VpnSvc;
129import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForSites;
130import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getResourceData;
131import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getRole;
janani bd821b182017-03-30 16:34:49 +0530132import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnBgpDelModObj;
janani b35f6cbc2017-03-24 21:56:58 +0530133import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnCreateModObj;
janani bd821b182017-03-30 16:34:49 +0530134import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getVpnDelModObj;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530135
136/**
137 * The IETF net l3vpn manager implementation.
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530138 */
139@Component(immediate = true)
janani bd821b182017-03-30 16:34:49 +0530140public class NetL3VpnManager {
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530141
142 private static final String APP_ID = "org.onosproject.app.l3vpn";
janani b35f6cbc2017-03-24 21:56:58 +0530143 private static final String L3_VPN_ID_TOPIC = "l3vpn-id";
janani b9ed76be2017-08-29 19:11:33 +0530144 private static final String TNL_ID_TOPIC = "l3vpn-tnl-id";
janani b35f6cbc2017-03-24 21:56:58 +0530145
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530146 private final Logger log = LoggerFactory.getLogger(getClass());
147
janani b176905a2017-03-28 17:36:18 +0530148 private final DynamicConfigListener configListener =
149 new InternalConfigListener();
150
151 private final Accumulator<DynamicConfigEvent> accumulator =
152 new InternalEventAccumulator();
153
154 private final InternalLeadershipListener leadershipEventListener =
155 new InternalLeadershipListener();
156
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700157 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530158 protected CoreService coreService;
159
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700160 @Reference(cardinality = ReferenceCardinality.MANDATORY)
janani b35f6cbc2017-03-24 21:56:58 +0530161 protected DriverService driverService;
162
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700163 @Reference(cardinality = ReferenceCardinality.MANDATORY)
janani b35f6cbc2017-03-24 21:56:58 +0530164 protected DeviceService deviceService;
165
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700166 @Reference(cardinality = ReferenceCardinality.MANDATORY)
janani b35f6cbc2017-03-24 21:56:58 +0530167 protected ModelConverter modelConverter;
168
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700169 @Reference(cardinality = ReferenceCardinality.MANDATORY)
janani b35f6cbc2017-03-24 21:56:58 +0530170 protected DynamicConfigService configService;
171
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700172 @Reference(cardinality = ReferenceCardinality.MANDATORY)
janani b35f6cbc2017-03-24 21:56:58 +0530173 protected NetL3VpnStore l3VpnStore;
174
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700175 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Bharat saraswalcdfda202017-03-24 23:40:50 +0530176 protected LeadershipService leadershipService;
177
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700178 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Bharat saraswalcdfda202017-03-24 23:40:50 +0530179 protected ClusterService clusterService;
180
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700181 @Reference(cardinality = ReferenceCardinality.MANDATORY)
janani b9ed76be2017-08-29 19:11:33 +0530182 protected PceService pceService;
183
janani b35f6cbc2017-03-24 21:56:58 +0530184 protected IdGenerator l3VpnIdGen;
janani b176905a2017-03-28 17:36:18 +0530185
janani b9ed76be2017-08-29 19:11:33 +0530186 protected IdGenerator tnlIdGen;
187
Bharat saraswalcdfda202017-03-24 23:40:50 +0530188 private NodeId localNodeId;
janani b176905a2017-03-28 17:36:18 +0530189
Bharat saraswalcdfda202017-03-24 23:40:50 +0530190 private ApplicationId appId;
janani b35f6cbc2017-03-24 21:56:58 +0530191
janani b35f6cbc2017-03-24 21:56:58 +0530192 private ResourceId id;
janani b176905a2017-03-28 17:36:18 +0530193
janani b35f6cbc2017-03-24 21:56:58 +0530194 private ResourceId module;
janani b176905a2017-03-28 17:36:18 +0530195
janani b35f6cbc2017-03-24 21:56:58 +0530196 private ResourceId sites;
janani b176905a2017-03-28 17:36:18 +0530197
Gaurav Agrawal8dbd2732017-04-14 18:57:30 +0530198 private boolean isElectedLeader;
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530199
janani b9ed76be2017-08-29 19:11:33 +0530200 private NetL3VpnTunnelHandler tnlHandler;
201
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530202 @Activate
203 protected void activate() {
Bharat saraswalcdfda202017-03-24 23:40:50 +0530204 appId = coreService.registerApplication(APP_ID);
janani b35f6cbc2017-03-24 21:56:58 +0530205 l3VpnIdGen = coreService.getIdGenerator(L3_VPN_ID_TOPIC);
janani b9ed76be2017-08-29 19:11:33 +0530206 tnlIdGen = coreService.getIdGenerator(TNL_ID_TOPIC);
Bharat saraswalcdfda202017-03-24 23:40:50 +0530207 localNodeId = clusterService.getLocalNode().id();
Bharat saraswalcdfda202017-03-24 23:40:50 +0530208 leadershipService.addListener(leadershipEventListener);
209 leadershipService.runForLeadership(appId.name());
janani b35f6cbc2017-03-24 21:56:58 +0530210 getResourceId();
211 configService.addListener(configListener);
janani b9ed76be2017-08-29 19:11:33 +0530212 tnlHandler = new NetL3VpnTunnelHandler(
213 pceService, driverService, configService, l3VpnStore,
214 deviceService, tnlIdGen, modelConverter);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530215 log.info("Started");
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530216 }
217
218 @Deactivate
219 protected void deactivate() {
janani b35f6cbc2017-03-24 21:56:58 +0530220 configService.removeListener(configListener);
Bharat saraswalcdfda202017-03-24 23:40:50 +0530221 leadershipService.withdraw(appId.name());
222 leadershipService.removeListener(leadershipEventListener);
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +0530223 log.info("Stopped");
224 }
225
janani b35f6cbc2017-03-24 21:56:58 +0530226 /**
227 * Returns id as string. If the id is not in the freed list a new id is
228 * generated else the id from the freed list is used.
229 *
230 * @return id
231 */
232 private String getIdFromGen() {
233 Long value;
234 Iterable<Long> freeIds = l3VpnStore.getFreedIdList();
235 Iterator<Long> it = freeIds.iterator();
236 if (it.hasNext()) {
237 value = it.next();
238 l3VpnStore.removeIdFromFreeList(value);
239 } else {
240 value = l3VpnIdGen.getNewId();
241 }
242 if (value > ID_LIMIT) {
Ray Milkey986a47a2018-01-25 11:38:51 -0800243 throw new IllegalStateException(ID_LIMIT_EXCEEDED);
janani b35f6cbc2017-03-24 21:56:58 +0530244 }
245 return CONS_HUNDRED + String.valueOf(value);
246 }
247
248 /**
249 * Returns the resource id, after constructing model object id and
250 * converting it.
251 */
252 private void getResourceId() {
253
254 ModelObjectId moduleId = ModelObjectId.builder().build();
255 module = getResourceVal(moduleId);
256
257 ModelObjectId svcId = getModIdForL3VpnSvc();
258 id = getResourceVal(svcId);
259
260 ModelObjectId sitesId = getModIdForSites();
261 sites = getResourceVal(sitesId);
262 }
263
264 /**
265 * Returns resource id from model converter.
266 *
267 * @param modelId model object id
268 * @return resource id
269 */
270 private ResourceId getResourceVal(ModelObjectId modelId) {
271 DefaultModelObjectData.Builder data = DefaultModelObjectData.builder()
Thomas Vachuskad17bc732017-03-24 11:46:55 -0700272 .identifier(modelId);
janani b35f6cbc2017-03-24 21:56:58 +0530273 ResourceData resData = modelConverter.createDataNode(data.build());
janani b176905a2017-03-28 17:36:18 +0530274 return resData.resourceId();
janani b35f6cbc2017-03-24 21:56:58 +0530275 }
276
277 /**
278 * Processes create request from the store, by taking the root object.
279 * The root object is then used for l3VPN processing.
280 *
281 * @param storeId store resource id
janani b176905a2017-03-28 17:36:18 +0530282 * @param node data node
janani b35f6cbc2017-03-24 21:56:58 +0530283 */
janani b176905a2017-03-28 17:36:18 +0530284 private void processCreateFromStore(ResourceId storeId, DataNode node) {
Bharat saraswal5b5bd9a2017-03-27 18:59:55 +0530285 if (isElectedLeader) {
janani b176905a2017-03-28 17:36:18 +0530286 List<NodeKey> keys = storeId.nodeKeys();
287 List<ModelObject> objects = null;
288 if (keys.size() == 1) {
289 objects = getModelObjects(node, module);
290 } else if (keys.size() == 2) {
291 objects = getModelObjects(node, id);
292 }
293 if (objects != null) {
294 for (ModelObject obj : objects) {
295 if (obj instanceof DefaultL3VpnSvc) {
296 DefaultL3VpnSvc l3VpnSvc = (DefaultL3VpnSvc) obj;
297 createGlobalConfig(l3VpnSvc);
298 } else if (obj instanceof DefaultSites) {
299 DefaultSites sites = (DefaultSites) obj;
300 createInterfaceConfig(sites);
301 }
Bharat saraswalcdfda202017-03-24 23:40:50 +0530302 }
janani b35f6cbc2017-03-24 21:56:58 +0530303 }
304 }
305 }
306
307 /**
Bharat saraswalcdfda202017-03-24 23:40:50 +0530308 * Processes delete request from the store, by taking the root object.
janani b176905a2017-03-28 17:36:18 +0530309 * The root object would have got deleted from store. So all the
310 * configurations are removed.
Bharat saraswalcdfda202017-03-24 23:40:50 +0530311 *
janani b176905a2017-03-28 17:36:18 +0530312 * @param dataNode data node
Bharat saraswalcdfda202017-03-24 23:40:50 +0530313 */
janani b176905a2017-03-28 17:36:18 +0530314 private void processDeleteFromStore(DataNode dataNode) {
Bharat saraswal5b5bd9a2017-03-27 18:59:55 +0530315 if (isElectedLeader) {
janani b176905a2017-03-28 17:36:18 +0530316 if (dataNode == null) {
317 //TODO: Delete for inner nodes.
318 deleteGlobalConfig(null);
319 }
Bharat saraswalcdfda202017-03-24 23:40:50 +0530320 }
321 }
322
323 /**
janani b176905a2017-03-28 17:36:18 +0530324 * Returns model objects of the store. The data node read from store
325 * gives the particular node. So the node's parent resource id is taken
326 * and the data node is given to model converter.
janani b35f6cbc2017-03-24 21:56:58 +0530327 *
janani b176905a2017-03-28 17:36:18 +0530328 * @param dataNode data node from store
329 * @param appId parent resource id
janani b35f6cbc2017-03-24 21:56:58 +0530330 * @return model objects
331 */
janani b176905a2017-03-28 17:36:18 +0530332 public List<ModelObject> getModelObjects(DataNode dataNode,
janani b35f6cbc2017-03-24 21:56:58 +0530333 ResourceId appId) {
janani b35f6cbc2017-03-24 21:56:58 +0530334 ResourceData data = getResourceData(dataNode, appId);
335 ModelObjectData modelData = modelConverter.createModel(data);
336 return modelData.modelObjects();
337 }
338
339 /**
340 * Returns true if the event resource id points to the root level node
341 * only and event is for addition and deletion; false otherwise.
342 *
343 * @param event config event
344 * @return true if event is supported; false otherwise
345 */
346 public boolean isSupported(DynamicConfigEvent event) {
347 ResourceId rsId = event.subject();
348 List<NodeKey> storeKeys = rsId.nodeKeys();
349 List<NodeKey> regKeys = id.nodeKeys();
janani b176905a2017-03-28 17:36:18 +0530350 List<NodeKey> sitesKeys = sites.nodeKeys();
janani b35f6cbc2017-03-24 21:56:58 +0530351 if (storeKeys != null) {
janani b176905a2017-03-28 17:36:18 +0530352 int storeSize = storeKeys.size();
353 if (storeSize == 1) {
janani b35f6cbc2017-03-24 21:56:58 +0530354 return storeKeys.get(0).equals(regKeys.get(1)) &&
355 (event.type() == NODE_ADDED ||
356 event.type() == NODE_DELETED);
janani b176905a2017-03-28 17:36:18 +0530357 } else if (storeSize == 2) {
358 return (storeKeys.get(0).equals(sitesKeys.get(1))) &&
359 storeKeys.get(1).equals(sitesKeys.get(2)) &&
360 (event.type() == NODE_ADDED ||
361 event.type() == NODE_DELETED);
janani b35f6cbc2017-03-24 21:56:58 +0530362 }
363 }
364 return false;
365 }
366
367 /***
janani b176905a2017-03-28 17:36:18 +0530368 * Creates all configuration in the standard device model.
janani b35f6cbc2017-03-24 21:56:58 +0530369 *
370 * @param l3VpnSvc l3VPN service object
371 */
372 void createGlobalConfig(L3VpnSvc l3VpnSvc) {
373 if (l3VpnSvc.vpnServices() != null) {
374 createVpnServices(l3VpnSvc.vpnServices());
375 }
376 if (l3VpnSvc.sites() != null) {
377 createInterfaceConfig(l3VpnSvc.sites());
378 }
379 }
380
381 /**
382 * Creates the VPN instances from the VPN services object, if only that
383 * VPN instance is not already created.
384 *
385 * @param vpnSvcs VPN services object
386 */
387 private void createVpnServices(VpnServices vpnSvcs) {
388 if (vpnSvcs != null && vpnSvcs.vpnSvc() != null) {
389 List<VpnSvc> svcList = vpnSvcs.vpnSvc();
390 for (VpnSvc svc : svcList) {
391 String vpnName = svc.vpnId().string();
392 l3VpnStore.addVpnInsIfAbsent(vpnName, new VpnInstance(vpnName));
393 }
394 }
395 }
396
397 /**
398 * Creates interface configuration from the site network access if
399 * available.
400 *
401 * @param sites sites object
402 */
403 private void createInterfaceConfig(Sites sites) {
404 if (sites.site() != null) {
405 List<Site> sitesList = sites.site();
406 for (Site site : sitesList) {
407 if (site.siteNetworkAccesses() != null) {
408 SiteNetworkAccesses accesses = site.siteNetworkAccesses();
409 List<SiteNetworkAccess> accessList =
410 accesses.siteNetworkAccess();
411 for (SiteNetworkAccess access : accessList) {
412 createFromAccess(access, site.siteId().string());
413 }
414 }
415 }
416 }
417 }
418
419 /**
420 * Creates the interface and VPN related configurations from the access
421 * and site id value.
422 *
423 * @param access site network access
424 * @param siteId site id
425 */
426 private void createFromAccess(SiteNetworkAccess access, String siteId) {
427 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
428 Map<String, VpnInstance> insMap = l3VpnStore.getVpnInstances();
429 String accessId = access.siteNetworkAccessId().string();
430 AccessInfo info = new AccessInfo(siteId, accessId);
431
432 if (intMap.get(info) == null) {
433 VpnSiteRole siteRole = getSiteRole(access.vpnAttachment());
434 VpnInstance instance = insMap.get(siteRole.name());
435 if (instance == null) {
436 throw new NetL3VpnException(SITE_VPN_MISMATCH);
437 }
438 buildFromAccess(instance, info, access, siteRole);
439 }
440 }
441
442 /**
443 * Returns the VPN site role from the VPN attachment.
444 *
445 * @param attach VPN attachment
446 * @return VPN site role
447 */
448 private VpnSiteRole getSiteRole(VpnAttachment attach) {
449 if (attach == null || attach.attachmentFlavor() == null) {
450 throw new NetL3VpnException(VPN_ATTACHMENT_NULL);
451 }
452 AttachmentFlavor flavor = attach.attachmentFlavor();
453 if (!(flavor instanceof DefaultVpnId)) {
454 throw new NetL3VpnException(VPN_POLICY_NOT_SUPPORTED);
455 }
456 DefaultVpnId vpnId = (DefaultVpnId) flavor;
457 if (vpnId.siteRole() == null) {
458 throw new NetL3VpnException(SITE_ROLE_NULL);
459 }
460 VpnType role = getRole(vpnId.siteRole());
janani b176905a2017-03-28 17:36:18 +0530461 return new VpnSiteRole(String.valueOf(vpnId.vpnId()), role);
janani b35f6cbc2017-03-24 21:56:58 +0530462 }
463
464 /**
465 * Builds the required details for device standard model from the site
466 * network access info available.
467 *
468 * @param instance VPN instance
469 * @param info access info
470 * @param access network access
471 * @param role VPN site role
472 */
473 private void buildFromAccess(VpnInstance instance, AccessInfo info,
474 SiteNetworkAccess access, VpnSiteRole role) {
475 Bearer bearer = access.bearer();
476 if (bearer == null) {
477 throw new NetL3VpnException(BEARER_NULL);
478 }
479
480 RequestedType reqType = bearer.requestedType();
481 IpConnection connect = access.ipConnection();
482 RoutingProtocols pro = access.routingProtocols();
483
484 if (reqType == null || connect == null) {
485 throw new NetL3VpnException(IP_INT_INFO_NULL);
486 }
487 buildDeviceDetails(instance, info, role, bearer, connect,
488 reqType, pro);
489 }
490
491 /**
492 * Builds the device details such as, VPN instance value if it is for
493 * the first time, interface values and BGP info if available in service.
494 *
495 * @param instance VPN instance
496 * @param accInfo access info
497 * @param role VPN site role
498 * @param bearer bearer object
499 * @param connect ip connect object
500 * @param reqType requested type
501 * @param pro routing protocol
502 */
503 private void buildDeviceDetails(VpnInstance instance, AccessInfo accInfo,
504 VpnSiteRole role, Bearer bearer,
505 IpConnection connect, RequestedType reqType,
506 RoutingProtocols pro) {
507 Map<AccessInfo, InterfaceInfo> interMap = l3VpnStore.getInterfaceInfo();
508 InterfaceInfo intInfo = interMap.get(accInfo);
509 if (intInfo != null) {
510 return;
511 }
512
513 DeviceInfo info = buildDevVpnIns(bearer, instance, role, connect);
514 String portName = getInterfaceName(info, reqType);
515 buildDevVpnInt(info, instance, connect, portName, accInfo);
516
517 if (pro != null && pro.routingProtocol() != null) {
518 buildBgpInfo(pro.routingProtocol(), info,
519 role.name(), connect, accInfo);
520 }
521 InterfaceInfo interInfo = new InterfaceInfo(info, portName,
522 instance.vpnName());
523 l3VpnStore.addInterfaceInfo(accInfo, interInfo);
janani bd821b182017-03-30 16:34:49 +0530524 l3VpnStore.addVpnIns(instance.vpnName(), instance);
janani b35f6cbc2017-03-24 21:56:58 +0530525 }
526
527 /**
528 * Builds device VPN instance with the service objects. It returns
529 *
530 * @param bearer bearer object
531 * @param ins VPN instance
532 * @param role VPN site role
533 * @param connect ip connection
534 * @return return
535 */
536 private DeviceInfo buildDevVpnIns(Bearer bearer, VpnInstance ins,
537 VpnSiteRole role, IpConnection connect) {
janani b9ed76be2017-08-29 19:11:33 +0530538 DefaultAugmentedL3VpnBearer augBearer = bearer.augmentation(
539 DefaultAugmentedL3VpnBearer.class);
janani b35f6cbc2017-03-24 21:56:58 +0530540 DeviceId id = getDeviceId(augBearer);
541 Map<DeviceId, DeviceInfo> devices = ins.devInfo();
542 DeviceInfo info = null;
543 if (devices != null) {
544 info = devices.get(id);
545 }
546 if (info == null) {
547 info = createVpnInstance(id, role, ins, connect);
548 }
549 return info;
550 }
551
552 /**
553 * Returns the device id from the bearer augment attachment of service.
554 * If the attachment in augment is not available it throws error.
555 *
556 * @param attach augmented bearer
557 * @return device id
558 */
559 private DeviceId getDeviceId(DefaultAugmentedL3VpnBearer attach) {
560 if (attach == null || attach.bearerAttachment() == null ||
561 attach.bearerAttachment().peMgmtIp() == null ||
562 attach.bearerAttachment().peMgmtIp().string() == null) {
563 throw new NetL3VpnException(DEVICE_INFO_NULL);
564 }
565 String ip = attach.bearerAttachment().peMgmtIp().string();
janani b9ed76be2017-08-29 19:11:33 +0530566 return getId(ip, true, deviceService.getAvailableDevices());
janani b35f6cbc2017-03-24 21:56:58 +0530567 }
568
569 /**
570 * Creates the VPN instance by constructing standard device model of
571 * instances. It adds the RD and RT values to the VPN instance.
572 *
573 * @param id device id
574 * @param role VPN site role
575 * @param inst VPN instance
576 * @param ip ip connection
577 * @return device info
578 */
579 private DeviceInfo createVpnInstance(DeviceId id, VpnSiteRole role,
580 VpnInstance inst, IpConnection ip) {
581 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
582 generateRdRt(inst, role);
janani b9ed76be2017-08-29 19:11:33 +0530583 DeviceInfo info = new DeviceInfo(id, role.role());
janani b35f6cbc2017-03-24 21:56:58 +0530584
585 NetworkInstances instances = createInstance(inst, role, ip);
586 ModelObjectData devMod = getVpnCreateModObj(intMap, instances,
587 id.toString());
janani b9ed76be2017-08-29 19:11:33 +0530588 inst.addDevInfo(id, info);
589 l3VpnStore.addVpnIns(inst.vpnName(), inst);
590
janani b35f6cbc2017-03-24 21:56:58 +0530591 ModelObjectData driMod = info.processCreateInstance(driverService,
592 devMod);
593 ResourceData resData = modelConverter.createDataNode(driMod);
594 addToStore(resData);
Gaurav Agrawal42b11762017-11-15 11:16:17 +0530595 // TODO: Enable tunnel creation on-demand. Uncomment below after
596 // complete validation
597 //checkAndUpdateTunnel(inst, id);
janani b35f6cbc2017-03-24 21:56:58 +0530598 return info;
599 }
600
601 /**
janani b9ed76be2017-08-29 19:11:33 +0530602 * Checks if the tunnel can be established and creates the tunnel from
603 * source to destination.
604 *
605 * @param inst VPN instance
606 * @param id device id
607 */
608 private void checkAndUpdateTunnel(VpnInstance inst, DeviceId id) {
609 Map<DeviceId, DeviceInfo> devInfo = inst.devInfo();
610 int devSize = devInfo.size();
611 String vpnName = inst.vpnName();
612 if (devSize != 1) {
613 DeviceInfo info = devInfo.get(id);
614 tnlHandler.createSrcInfo(vpnName, info);
615 for (Map.Entry<DeviceId, DeviceInfo> device : devInfo.entrySet()) {
616 DeviceInfo val = device.getValue();
617 if (val != info) {
618 tnlHandler.createSrcDesTunnel(val);
619 }
620 }
621 }
622 }
623
624 /**
janani b35f6cbc2017-03-24 21:56:58 +0530625 * Adds the resource data that is received from the driver, after
626 * converting from the model object data.
627 *
628 * @param resData resource data
629 */
630 private void addToStore(ResourceData resData) {
631 if (resData != null && resData.dataNodes() != null) {
632 List<DataNode> dataNodes = resData.dataNodes();
633 for (DataNode node : dataNodes) {
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700634 configService.createNode(resData.resourceId(), node);
janani b35f6cbc2017-03-24 21:56:58 +0530635 }
636 }
637 }
638
639 /**
640 * Generates RD and RT value for the VPN instance for the first time VPN
641 * instance creation.
642 *
643 * @param ins VPN instance
644 * @param role VPN site role
645 */
646 private void generateRdRt(VpnInstance ins, VpnSiteRole role) {
647 ins.type(role.role());
648 VpnConfig config = ins.vpnConfig();
649 String rd = null;
650 if (config == null) {
651 rd = getIdFromGen();
652 }
653 switch (ins.type()) {
654 case ANY_TO_ANY:
655 if (config == null) {
656 config = new FullMeshVpnConfig(rd);
657 config.rd(rd);
658 }
659 break;
660
661 case HUB:
662 case SPOKE:
663 if (config == null) {
664 config = new HubSpokeVpnConfig();
665 config.rd(rd);
666 }
667 createImpRtVal((HubSpokeVpnConfig) config, ins.type());
668 createExpRtVal((HubSpokeVpnConfig) config, ins.type());
669 break;
670
671 default:
672 throw new NetL3VpnException(VPN_TYPE_UNSUPPORTED);
673 }
674 ins.vpnConfig(config);
675 }
676
677 /**
678 * Creates import RT value for HUB and SPOKE, according to the type, if
679 * the values are not present.
680 *
681 * @param config VPN config
682 * @param type VPN type
683 */
684 private void createImpRtVal(HubSpokeVpnConfig config, VpnType type) {
685 if (type == HUB) {
686 if (config.hubImpRt() != null) {
687 return;
688 }
689 setHubImpRt(config);
690 } else {
691 if (config.spokeImpRt() != null) {
692 return;
693 }
694 config.spokeImpRt(config.rd());
695 }
696 }
697
698 /**
699 * Sets the HUB import RT, from the spoke export RT. If it is not
700 * available a new ID is generated.
701 *
702 * @param config VPN config
703 */
704 public void setHubImpRt(HubSpokeVpnConfig config) {
705 String hubImp;
706 if (config.spokeExpRt() != null) {
707 hubImp = config.spokeExpRt();
708 } else {
709 hubImp = getIdFromGen();
710 }
711 config.hubImpRt(hubImp);
712 }
713
714 /**
715 * Creates export RT value for HUB and SPOKE, according to the type, if
716 * the values are not present.
717 *
718 * @param config VPN config
719 * @param type VPN type
720 */
721 private void createExpRtVal(HubSpokeVpnConfig config, VpnType type) {
722 if (type == HUB) {
723 if (config.hubExpRt() != null) {
724 return;
725 }
726 config.hubExpRt(config.rd());
727 } else {
728 if (config.spokeExpRt() != null) {
729 return;
730 }
731 setSpokeExpRt(config);
732 }
733 }
734
735 /**
736 * Sets the SPOKE export RT, from the hub import RT. If it is not
737 * available a new ID is generated.
738 *
739 * @param config VPN config
740 */
741 public void setSpokeExpRt(HubSpokeVpnConfig config) {
742 String spokeExp;
743 if (config.hubImpRt() != null) {
744 spokeExp = config.hubImpRt();
745 } else {
746 spokeExp = getIdFromGen();
747 }
748 config.spokeExpRt(spokeExp);
749 }
750
751 /**
752 * Returns the interface name from the requested type service object.
753 *
754 * @param info device info
755 * @param reqType requested type
756 * @return interface name
757 */
758 private String getInterfaceName(DeviceInfo info, RequestedType reqType) {
janani b9ed76be2017-08-29 19:11:33 +0530759 DefaultAugmentedL3VpnRequestedType req = reqType.augmentation(
760 DefaultAugmentedL3VpnRequestedType.class);
janani b35f6cbc2017-03-24 21:56:58 +0530761 if (req == null || req.requestedTypeProfile() == null ||
762 req.requestedTypeProfile().requestedTypeChoice() == null) {
763 throw new NetL3VpnException(INT_INFO_NULL);
764 }
765 RequestedTypeChoice reqChoice = req.requestedTypeProfile()
766 .requestedTypeChoice();
767 return getNameFromChoice(reqChoice, info.deviceId());
768 }
769
770 /**
771 * Returns the interface name from the type choice provided.
772 *
773 * @param choice service choice
774 * @param id device id
775 * @return interface name
776 */
777 private String getNameFromChoice(RequestedTypeChoice choice, DeviceId id) {
778 if (choice == null) {
779 throw new NetL3VpnException(INT_INFO_NULL);
780 }
781 String intName;
782 if (choice instanceof DefaultDot1Qcase) {
783 if (((DefaultDot1Qcase) choice).dot1q() == null ||
784 ((DefaultDot1Qcase) choice).dot1q()
785 .physicalIf() == null) {
786 throw new NetL3VpnException(INT_INFO_NULL);
787 }
788 intName = ((DefaultDot1Qcase) choice).dot1q().physicalIf();
789 } else {
790 if (((DefaultPhysicalCase) choice).physical() == null ||
791 ((DefaultPhysicalCase) choice).physical()
792 .physicalIf() == null) {
793 throw new NetL3VpnException(INT_INFO_NULL);
794 }
795 intName = ((DefaultPhysicalCase) choice).physical().physicalIf();
796 }
797 return getPortName(intName, id);
798 }
799
800 /**
801 * Returns the port name when it the port is available in the device.
802 *
803 * @param intName interface name
804 * @param id device id
805 * @return port name
806 */
807 private String getPortName(String intName, DeviceId id) {
808 List<Port> ports = deviceService.getPorts(id);
809 for (Port port : ports) {
810 String pName = port.annotations().value(PORT_NAME);
811 if (pName.equals(intName)) {
812 return intName;
813 }
814 }
815 throw new NetL3VpnException(getIntNotAvailable(intName));
816 }
817
818 /**
819 * Builds the interface for the device binding with the VPN instance.
820 *
821 * @param info device info
822 * @param ins VPN instance
823 * @param connect IP connection
824 * @param pName port name
825 * @param access access info
826 */
827 private void buildDevVpnInt(DeviceInfo info, VpnInstance ins,
828 IpConnection connect, String pName,
829 AccessInfo access) {
830 Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
831 info.addAccessInfo(access);
832 info.addIfName(pName);
833 Interfaces interfaces = createInterface(pName, ins.vpnName(),
834 connect);
835 ModelObjectData devMod = getIntCreateModObj(
janani bd821b182017-03-30 16:34:49 +0530836 info.ifNames(), interfaces, info.deviceId().toString());
janani b35f6cbc2017-03-24 21:56:58 +0530837 ModelObjectData driMod = info.processCreateInterface(driverService,
838 devMod);
839 ResourceData resData = modelConverter.createDataNode(driMod);
840 addToStore(resData);
841 }
842
843 /**
844 * Builds the BGP information from the routes that are given from the
845 * service.
846 *
847 * @param routes routing protocol
848 * @param info device info
849 * @param name VPN name
850 * @param connect IP connection
851 * @param access access info
852 */
853 private void buildBgpInfo(List<RoutingProtocol> routes, DeviceInfo info,
854 String name, IpConnection connect,
855 AccessInfo access) {
856 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
857 BgpInfo intBgp = createBgpInfo(routes, info, name, connect, access);
858 if (intBgp != null) {
859 intBgp.vpnName(name);
860 BgpDriverInfo config = getBgpCreateConfigObj(
janani bd821b182017-03-30 16:34:49 +0530861 bgpMap, info.deviceId().toString(), info.bgpInfo(), intBgp);
janani b35f6cbc2017-03-24 21:56:58 +0530862 ModelObjectData driData = info.processCreateBgpInfo(
863 driverService, intBgp, config);
864 l3VpnStore.addBgpInfo(info.bgpInfo(), info.deviceId());
865 ResourceData resData = modelConverter.createDataNode(driData);
866 addToStore(resData);
867 }
868 }
869
870 /**
janani b176905a2017-03-28 17:36:18 +0530871 * Creates all configuration in the standard device model.
872 *
873 * @param l3VpnSvc l3 VPN service
874 */
875 void deleteGlobalConfig(L3VpnSvc l3VpnSvc) {
876 deleteGlobalVpn(l3VpnSvc);
877 //TODO: Site and access deletion needs to be added.
878 }
879
880 /**
881 * Deletes the global VPN from the device model and delete from the device.
882 *
883 * @param l3VpnSvc L3 VPN service
884 */
885 private void deleteGlobalVpn(L3VpnSvc l3VpnSvc) {
886 Map<String, VpnInstance> insMap = l3VpnStore.getVpnInstances();
887 //TODO: check for VPN delete deleting interface from store.
888 if (l3VpnSvc == null || l3VpnSvc.vpnServices() == null ||
889 l3VpnSvc.vpnServices().vpnSvc() == null) {
890 for (Map.Entry<String, VpnInstance> vpnMap : insMap.entrySet()) {
891 deleteVpnInstance(vpnMap.getValue(), false);
892 }
893 return;
894 }
895 List<VpnSvc> vpnList = l3VpnSvc.vpnServices().vpnSvc();
896 for (Map.Entry<String, VpnInstance> vpnMap : insMap.entrySet()) {
897 boolean isPresent = isVpnPresent(vpnMap.getKey(), vpnList);
898 if (!isPresent) {
899 deleteVpnInstance(vpnMap.getValue(), false);
900 }
901 }
902 }
903
904 /**
905 * Returns true if the VPN in the distributed map is also present in the
906 * service; false otherwise.
907 *
908 * @param vpnName VPN name from store
909 * @param vpnList VPN list from service
910 * @return true if VPN available; false otherwise
911 */
912 private boolean isVpnPresent(String vpnName, List<VpnSvc> vpnList) {
913 for (VpnSvc svc : vpnList) {
914 if (svc.vpnId().string().equals(vpnName)) {
915 return true;
916 }
917 }
918 return false;
919 }
920
921 /**
922 * Deletes the VPN instance by constructing standard device model of
923 * instances.
924 *
925 * @param instance VPN instance
926 * @param isIntDeleted if interface already removed.
927 */
928 private void deleteVpnInstance(VpnInstance instance, boolean isIntDeleted) {
929 Map<DeviceId, DeviceInfo> devices = instance.devInfo();
janani bd821b182017-03-30 16:34:49 +0530930 if (devices != null) {
931 for (Map.Entry<DeviceId, DeviceInfo> device : devices.entrySet()) {
932 NetworkInstances ins = deleteInstance(instance.vpnName());
933 DeviceInfo dev = device.getValue();
934 if (!isIntDeleted) {
935 remVpnBgp(dev);
936 remInterfaceFromMap(dev);
937 }
938 Map<AccessInfo, InterfaceInfo> intMap =
939 l3VpnStore.getInterfaceInfo();
940 String id = dev.deviceId().toString();
941 ModelObjectData devMod = getVpnDelModObj(intMap, ins, id);
942 ModelObjectData driMod = dev.processDeleteInstance(
943 driverService, devMod);
944 ResourceData resData = modelConverter.createDataNode(driMod);
945 deleteFromStore(resData);
Gaurav Agrawal42b11762017-11-15 11:16:17 +0530946 // TODO: Enable tunnel creation on-demand. Uncomment below after
947 // complete validation
948 // tnlHandler.deleteTunnel(dev, instance.vpnName());
janani b176905a2017-03-28 17:36:18 +0530949 }
janani bd821b182017-03-30 16:34:49 +0530950 l3VpnStore.removeVpnInstance(instance.vpnName());
janani b176905a2017-03-28 17:36:18 +0530951 }
janani bd821b182017-03-30 16:34:49 +0530952 }
953
954 /**
955 * Removes the BGP information for that complete VPN instance.
956 *
957 * @param dev device info
958 */
959 private void remVpnBgp(DeviceInfo dev) {
960 BgpInfo devBgp = dev.bgpInfo();
961 if (devBgp != null) {
962 l3VpnStore.removeBgpInfo(devBgp);
963 BgpInfo delInfo = new BgpInfo();
964 delInfo.vpnName(devBgp.vpnName());
965 String id = dev.deviceId().toString();
966 Map<BgpInfo, DeviceId> bgpMap = l3VpnStore.getBgpInfo();
967 BgpDriverInfo driConfig = getVpnBgpDelModObj(bgpMap, id);
968 ModelObjectData driData = dev.processDeleteBgpInfo(
969 driverService, delInfo, driConfig);
970 ResourceData resData = modelConverter.createDataNode(driData);
971 deleteFromStore(resData);
972 l3VpnStore.removeBgpInfo(devBgp);
973 }
janani b176905a2017-03-28 17:36:18 +0530974 }
975
976 /**
977 * Deletes the resource data that is received from the driver, after
978 * converting from the model object data.
979 *
980 * @param resData resource data
981 */
982 private void deleteFromStore(ResourceData resData) {
983 if (resData != null) {
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700984 configService.deleteNode(resData.resourceId());
janani b176905a2017-03-28 17:36:18 +0530985 }
986 }
987
988 /**
989 * Removes the interface from the app distributed map, if the driver
990 * interfaces are already removed from the store.
991 *
992 * @param deviceInfo device info
993 */
994 private void remInterfaceFromMap(DeviceInfo deviceInfo) {
995 List<AccessInfo> accesses = deviceInfo.accesses();
janani bd821b182017-03-30 16:34:49 +0530996 if (accesses != null) {
997 for (AccessInfo access : accesses) {
998 l3VpnStore.removeInterfaceInfo(access);
999 }
janani b176905a2017-03-28 17:36:18 +05301000 }
1001 deviceInfo.ifNames(null);
1002 deviceInfo.accesses(null);
1003 }
1004
1005 /**
1006 * Signals that the leadership has changed.
1007 *
1008 * @param isLeader true if this instance is now the leader, otherwise false
1009 */
1010 private void leaderChanged(boolean isLeader) {
1011 log.debug("Leader changed: {}", isLeader);
1012 isElectedLeader = isLeader;
1013 }
1014
1015 /**
janani b35f6cbc2017-03-24 21:56:58 +05301016 * Representation of internal listener, listening for dynamic config event.
1017 */
1018 private class InternalConfigListener implements DynamicConfigListener {
1019
1020 @Override
1021 public boolean isRelevant(DynamicConfigEvent event) {
1022 return isSupported(event);
1023 }
1024
1025 @Override
1026 public void event(DynamicConfigEvent event) {
janani b176905a2017-03-28 17:36:18 +05301027 accumulator.add(event);
janani b35f6cbc2017-03-24 21:56:58 +05301028 }
1029 }
Bharat saraswalcdfda202017-03-24 23:40:50 +05301030
1031 /**
janani b176905a2017-03-28 17:36:18 +05301032 * Accumulates events to allow processing after a desired number of
1033 * events were accumulated.
Bharat saraswalcdfda202017-03-24 23:40:50 +05301034 */
janani b176905a2017-03-28 17:36:18 +05301035 private class InternalEventAccumulator extends
1036 AbstractAccumulator<DynamicConfigEvent> {
1037
1038 /**
1039 * Constructs the event accumulator with timer and event limit.
1040 */
1041 protected InternalEventAccumulator() {
1042 super(new Timer(TIMER), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
1043 }
1044
1045 @Override
1046 public void processItems(List<DynamicConfigEvent> events) {
1047 for (DynamicConfigEvent event : events) {
1048 checkNotNull(event, EVENT_NULL);
Yuta HIGUCHIac85ee12017-08-03 20:07:35 -07001049 Filter filter = Filter.builder().build();
janani b176905a2017-03-28 17:36:18 +05301050 DataNode node;
1051 try {
1052 node = configService.readNode(event.subject(), filter);
1053 } catch (FailedException e) {
1054 node = null;
1055 }
1056 switch (event.type()) {
1057 case NODE_ADDED:
1058 processCreateFromStore(event.subject(), node);
1059 break;
1060
1061 case NODE_DELETED:
1062 processDeleteFromStore(node);
1063 break;
1064
1065 default:
1066 log.warn(UNKNOWN_EVENT, event.type());
1067 break;
1068 }
1069 }
1070 }
Bharat saraswalcdfda202017-03-24 23:40:50 +05301071 }
1072
1073 /**
1074 * A listener for leadership events.
1075 */
1076 private class InternalLeadershipListener implements LeadershipEventListener {
1077
1078 @Override
1079 public boolean isRelevant(LeadershipEvent event) {
1080 return event.subject().topic().equals(appId.name());
1081 }
1082
1083 @Override
1084 public void event(LeadershipEvent event) {
1085 switch (event.type()) {
1086 case LEADER_CHANGED:
1087 case LEADER_AND_CANDIDATES_CHANGED:
1088 if (localNodeId.equals(event.subject().leaderNodeId())) {
1089 log.info("Net l3vpn manager gained leadership");
1090 leaderChanged(true);
1091 } else {
1092 log.info("Net l3vpn manager leader changed. New " +
1093 "leader is {}", event.subject()
1094 .leaderNodeId());
1095 leaderChanged(false);
1096 }
Ray Milkeyd6a67c32018-02-02 10:30:35 -08001097 break;
Bharat saraswalcdfda202017-03-24 23:40:50 +05301098 default:
1099 break;
1100 }
1101 }
1102 }
Gaurav Agrawalc6d536f2017-03-17 11:56:31 +05301103}