2 * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.unimgr.mef.netvirt;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.stream.Collectors;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
20 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
21 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
25 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.SubnetBuilder;
28 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
29 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn;
30 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
31 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans;
32 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.Uni;
33 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.UniKey;
34 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
35 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
51 import org.opendaylight.yangtools.concepts.ListenerRegistration;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 import com.google.common.base.Optional;
58 public class IpvcListener extends UnimgrDataTreeChangeListener<Ipvc> implements IUniAwareService {
59 private static final Logger Log = LoggerFactory.getLogger(IpvcListener.class);
60 private final IUniPortManager uniPortManager;
61 private final ISubnetManager subnetManager;
62 private final UniQosManager uniQosManager;
63 private ListenerRegistration<IpvcListener> ipvcListenerRegistration;
64 @SuppressWarnings("unused")
65 private final UniAwareListener uniAwareListener;
66 private OdlInterfaceRpcService odlInterfaceRpcService;
67 private final SouthboundUtils southBoundUtils;
68 private final org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils mdsalUtils;
69 private final NotificationPublishService notificationPublishService;
71 private static final String LOCAL_IP = "local_ip";
73 // TODO: make it as service
74 private ConcurrentHashMap<String, BigInteger> portToDpn;
76 public IpvcListener(final DataBroker dataBroker, final IUniPortManager uniPortManager,
77 final ISubnetManager subnetManager, final UniQosManager uniQosManager,
78 final OdlInterfaceRpcService odlInterfaceRpcService, final NotificationPublishService notPublishService) {
80 this.uniPortManager = uniPortManager;
81 this.subnetManager = subnetManager;
82 this.uniQosManager = uniQosManager;
83 this.uniAwareListener = new UniAwareListener(dataBroker, this);
84 this.odlInterfaceRpcService = odlInterfaceRpcService;
85 this.mdsalUtils = new org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils(dataBroker);
86 this.southBoundUtils = new SouthboundUtils(mdsalUtils);
87 this.portToDpn = new ConcurrentHashMap<>();
88 this.notificationPublishService = notPublishService;
93 public void registerListener() {
95 final DataTreeIdentifier<Ipvc> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
96 MefServicesUtils.getIpvcsInstanceIdentifier());
97 ipvcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
98 Log.info("IpvcDataTreeChangeListener created and registered");
99 } catch (final Exception e) {
100 Log.error("Ipvc DataChange listener registration failed !", e);
101 throw new IllegalStateException("Ipvc registration Listener failed.", e);
106 public void close() throws Exception {
107 ipvcListenerRegistration.close();
111 public void add(DataTreeModification<Ipvc> newDataObject) {
112 if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
113 Log.info("ipvc {} created", newDataObject.getRootNode().getIdentifier());
114 addIpvc(newDataObject);
119 public void remove(DataTreeModification<Ipvc> removedDataObject) {
120 if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
121 Log.info("ipvc {} deleted", removedDataObject.getRootNode().getIdentifier());
122 removeIpvc(removedDataObject);
127 public void update(DataTreeModification<Ipvc> modifiedDataObject) {
128 if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
129 Log.info("ipvc {} updated", modifiedDataObject.getRootNode().getIdentifier());
130 updateIpvc(modifiedDataObject);
135 public void connectUni(String uniId) {
136 List<RetailSvcIdType> allIpvcs = MefServicesUtils.getAllIpvcsServiceIds(dataBroker);
137 allIpvcs = allIpvcs != null ? allIpvcs : Collections.emptyList();
139 for (RetailSvcIdType ipvcSerId : allIpvcs) {
140 InstanceIdentifier<Ipvc> ipvcId = MefServicesUtils.getIpvcInstanceIdentifier(ipvcSerId);
141 Ipvc ipvc = MefServicesUtils.getIpvc(dataBroker, ipvcId);
143 Log.error("Inconsistent data for svcId {}", ipvcSerId);
146 List<Uni> toConnect = new ArrayList<>();
148 List<Uni> unis = ipvc.getUnis() != null ? ipvc.getUnis().getUni() : null;
149 unis = unis != null ? unis : Collections.emptyList();
150 for (Uni uni : unis) {
151 if (uni.getUniId().getValue().equals(uniId)) {
152 Log.info("Connecting Uni {} to svc id {}", uniId, ipvcSerId);
158 IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
159 if (operIpvcVpn == null) {
160 String instanceName = ipvc.getIpvcId().getValue();
161 final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
162 createVpnInstance(vpnName, ipvcId);
163 operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
164 if (operIpvcVpn == null) {
165 Log.error("Ipvc {} hasn't been created as required, Nothing to reconnect", ipvcSerId);
169 String vpnName = operIpvcVpn.getVpnId();
170 String rd = waitForRd(vpnName);
171 createUnis(vpnName, ipvcId, toConnect, rd);
176 public void disconnectUni(String uniId) {
178 List<RetailSvcIdType> allIpvcs = MefServicesUtils.getAllIpvcsServiceIds(dataBroker);
179 allIpvcs = allIpvcs != null ? allIpvcs : Collections.emptyList();
181 for (RetailSvcIdType ipvcSerId : allIpvcs) {
182 InstanceIdentifier<Ipvc> ipvcId = MefServicesUtils.getIpvcInstanceIdentifier(ipvcSerId);
183 Ipvc ipvc = MefServicesUtils.getIpvc(dataBroker, ipvcId);
185 Log.error("Inconsistent data for svcId {}", ipvcSerId);
188 List<Uni> toRemove = new ArrayList<>();
190 List<Uni> unis = ipvc.getUnis() != null ? ipvc.getUnis().getUni() : null;
191 unis = unis != null ? unis : Collections.emptyList();
192 for (Uni uni : unis) {
193 if (uni.getUniId().getValue().equals(uniId)) {
194 Log.info("Disconnecting Uni {} from svc id {}", uniId, ipvcSerId);
200 IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
201 if (operIpvcVpn == null) {
202 Log.error("Ipvc {} hasn't been created as required, Nothing to disconnect", ipvcSerId);
206 removeUnis(ipvcId, operIpvcVpn, toRemove);
211 private void addIpvc(DataTreeModification<Ipvc> newDataObject) {
213 Ipvc ipvc = newDataObject.getRootNode().getDataAfter();
214 String instanceName = ipvc.getIpvcId().getValue();
215 final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
216 InstanceIdentifier<Ipvc> ipvcId = newDataObject.getRootPath().getRootIdentifier();
217 createVpnInstance(vpnName, ipvcId);
218 String rd = waitForRd(vpnName);
220 updateOperationalDataStoreWithVrfId(ipvcId, vpnName, rd);
222 List<Uni> unis = new ArrayList<>();
223 if (ipvc.getUnis() != null && ipvc.getUnis() != null) {
224 unis = ipvc.getUnis().getUni();
226 Log.info("Number of UNI's: " + unis.size());
228 createUnis(vpnName, ipvcId, unis, rd);
229 } catch (final Exception e) {
230 Log.error("Add ipvc failed !", e);
234 private void updateOperationalDataStoreWithVrfId(InstanceIdentifier<Ipvc> ipvcId, String vpnName, String vrfId) {
235 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
236 MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, vrfId, tx);
237 MdsalUtils.commitTransaction(tx);
240 private void createVpnInstance(final String vpnName, InstanceIdentifier<Ipvc> ipvcId) {
241 synchronized (vpnName.intern()) {
242 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
243 Log.info("Adding vpn instance: " + vpnName);
244 NetvirtVpnUtils.createVpnInstance(vpnName, tx);
245 MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, tx);
246 MdsalUtils.commitTransaction(tx);
250 private String waitForRd(final String vpnName) {
251 InstanceIdentifier<VpnInstance> vpnId = NetvirtVpnUtils.getVpnInstanceToVpnIdIdentifier(vpnName);
252 @SuppressWarnings("resource")
253 DataWaitListener<VpnInstance> vpnInstanceWaiter = new DataWaitListener<VpnInstance>(dataBroker, vpnId, 5,
254 LogicalDatastoreType.CONFIGURATION, vpn -> vpn.getVrfId());
255 if (!vpnInstanceWaiter.waitForData()) {
256 String errorMessage = String.format("Fail to wait for vrfId for vpn %s", vpnName);
257 Log.error(errorMessage);
258 throw new UnsupportedOperationException(errorMessage);
260 String rd = (String) vpnInstanceWaiter.getData();
264 private void removeIpvc(DataTreeModification<Ipvc> removedDataObject) {
266 Ipvc ipvc = removedDataObject.getRootNode().getDataBefore();
267 InstanceIdentifier<Ipvc> ipvcId = removedDataObject.getRootPath().getRootIdentifier();
268 IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
269 if (operIpvcVpn == null) {
270 Log.error("Ipvc {} hasn't been created as required", ipvc.getIpvcId());
273 removeUnis(ipvcId, operIpvcVpn, ipvc.getUnis().getUni());
274 NetvirtUtils.safeSleep();
276 String vpnId = operIpvcVpn.getVpnId();
277 synchronized (vpnId.intern()) {
278 WriteTransaction txvpn = MdsalUtils.createTransaction(dataBroker);
279 NetvirtVpnUtils.removeVpnInstance(operIpvcVpn.getVpnId(), txvpn);
280 MefServicesUtils.removeOperIpvcVpn(ipvcId, txvpn);
281 MdsalUtils.commitTransaction(txvpn);
283 } catch (final Exception e) {
284 Log.error("Remove ipvc failed !", e);
288 private void removeUnis(InstanceIdentifier<Ipvc> ipvcId, IpvcVpn operIpvcVpn, List<Uni> uniToRemove) {
289 if (uniToRemove == null) {
290 Log.trace("No UNI's to remove");
292 for (Uni uni : uniToRemove) {
293 Identifier45 uniId = uni.getUniId();
294 Identifier45 ipUniId = uni.getIpUniId();
295 IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uniId, ipUniId, LogicalDatastoreType.CONFIGURATION);
297 String errorMessage = String.format("Couldn't find ipuni %s for uni %s", ipUniId, uniId);
298 Log.error(errorMessage);
299 throw new UnsupportedOperationException(errorMessage);
302 removeDirectSubnet(uni, ipUni);
303 subnetManager.unAssignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
304 removeInterfaces(ipvcId, operIpvcVpn, uni, ipUni);
306 updateQos(uniToRemove);
309 private void createUnis(String vpnName, InstanceIdentifier<Ipvc> ipvcId, List<Uni> uniToCreate, String rd) {
310 // Create elan/vpn interfaces
311 for (Uni uni : uniToCreate) {
312 createInterfaces(vpnName, uni, ipvcId, rd);
315 for (Uni uni : uniToCreate) {
316 IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uni.getUniId(), uni.getIpUniId(),
317 LogicalDatastoreType.CONFIGURATION);
318 createDirectSubnet(uni, ipUni);
319 subnetManager.assignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
321 updateQos(uniToCreate);
325 private void updateIpvc(DataTreeModification<Ipvc> modifiedDataObject) {
327 Ipvc origIpvc = modifiedDataObject.getRootNode().getDataBefore();
328 Ipvc updateIpvc = modifiedDataObject.getRootNode().getDataAfter();
329 InstanceIdentifier<Ipvc> ipvcId = modifiedDataObject.getRootPath().getRootIdentifier();
330 IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
331 if (operIpvcVpn == null) {
332 Log.error("Ipvc {} hasn't been created as required", origIpvc.getIpvcId());
335 String vpnName = operIpvcVpn.getVpnId();
336 String rd = waitForRd(vpnName);
337 List<Uni> originalUni = origIpvc.getUnis() != null && origIpvc.getUnis().getUni() != null
338 ? origIpvc.getUnis().getUni() : Collections.emptyList();
339 List<UniKey> originalUniIds = originalUni.stream().map(u -> u.getKey()).collect(Collectors.toList());
340 List<Uni> updateUni = updateIpvc.getUnis() != null && updateIpvc.getUnis().getUni() != null
341 ? updateIpvc.getUnis().getUni() : Collections.emptyList();
342 List<UniKey> updateUniIds = updateUni.stream().map(u -> u.getKey()).collect(Collectors.toList());
344 List<Uni> uniToRemove = new ArrayList<>(originalUni);
345 uniToRemove.removeIf(u -> updateUniIds.contains(u.getKey()));
346 removeUnis(ipvcId, operIpvcVpn, uniToRemove);
348 List<Uni> uniToCreate = new ArrayList<>(updateUni);
349 uniToCreate.removeIf(u -> originalUniIds.contains(u.getKey()));
350 createUnis(vpnName, ipvcId, uniToCreate, rd);
352 List<Uni> uniToUpdate = new ArrayList<>(updateUni);
353 uniToUpdate.removeIf(u -> !originalUniIds.contains(u.getKey()));
354 updateUnis(uniToUpdate);
356 } catch (final Exception e) {
357 Log.error("Update ipvc failed !", e);
361 private void createInterfaces(String vpnName, Uni uniInService, InstanceIdentifier<Ipvc> ipvcId, String rd) {
362 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
363 String uniId = uniInService.getUniId().getValue();
364 String ipUniId = uniInService.getIpUniId().getValue();
365 org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = MefInterfaceUtils
366 .getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
368 String errorMessage = String.format("Couldn't find uni %s for ipvc", uniId);
369 Log.error(errorMessage);
370 throw new UnsupportedOperationException(errorMessage);
372 IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uniInService.getUniId(), uniInService.getIpUniId(),
373 LogicalDatastoreType.CONFIGURATION);
375 String errorMessage = String.format("Couldn't find ipuni %s for uni %s", ipUniId, uniId);
376 Log.error(errorMessage);
377 throw new UnsupportedOperationException(errorMessage);
380 String interfaceName = null;
381 String elanName = NetvirtVpnUtils.getElanNameForVpnPort(uniId, ipUniId);
383 synchronized (vpnName.intern()) {
384 Long vlan = ipUni.getVlan() != null ? Long.valueOf(ipUni.getVlan().getValue()) : null;
386 interfaceName = createElanInterface(vpnName, ipvcId, uniId, elanName, vlan, ipUni.getSegmentationId());
388 String portMacAddress = uni.getMacAddress().getValue();
389 NetvirtVpnUtils.registerDirectSubnetForVpn(dataBroker, vpnName, new Uuid(elanName), ipUni.getIpAddress(),
390 interfaceName, portMacAddress);
392 uniQosManager.mapUniPortBandwidthLimits(uniId, interfaceName, uniInService.getIngressBwProfile());
393 createVpnInterface(vpnName, uni, ipUni, interfaceName, elanName, tx);
394 NetvirtVpnUtils.createVpnPortFixedIp(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
395 uni.getMacAddress(), tx);
396 MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, uniInService.getUniId(), uniInService.getIpUniId(),
397 elanName, interfaceName, null, tx);
398 MdsalUtils.commitTransaction(tx);
402 private String createElanInterface(String vpnName, InstanceIdentifier<Ipvc> ipvcId, String uniId, String elanName,
403 Long vlan, Long segmentationId) {
404 Log.info("Adding elan instance: " + elanName);
405 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
406 NetvirtUtils.updateElanInstance(elanName, tx, segmentationId);
408 Log.info("Added trunk interface for uni {} vlan: {}", uniId, vlan);
410 uniPortManager.addCeVlan(uniId, vlan);
412 String interfaceName = uniPortManager.getUniVlanInterface(uniId, vlan);
413 if (interfaceName == null) {
414 String errorMessage = String.format("Couldn't create uni %s vlan interface %s", uniId, vlan);
415 Log.error(errorMessage);
416 throw new UnsupportedOperationException(errorMessage);
419 Log.info("Adding elan interface: " + interfaceName);
420 NetvirtUtils.createElanInterface(elanName, interfaceName, EtreeInterfaceType.Root, false, tx);
421 MdsalUtils.commitTransaction(tx);
422 return interfaceName;
425 private void createVpnInterface(String vpnName,
426 org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni,
427 IpUni ipUni, String interfaceName, String elanName, WriteTransaction tx) {
429 Log.info("Adding vpn interface: " + interfaceName);
430 BigInteger dpId = getPortDpId(interfaceName);
431 IpAddress nextHop = getNodeIP(dpId);
432 NetvirtVpnUtils.createUpdateVpnInterface(vpnName, interfaceName, nextHop, ipUni.getIpAddress(),
433 uni.getMacAddress().getValue(), true, null, elanName, tx);
434 Log.info("Finished working on vpn instance {} interface () ", vpnName, interfaceName);
437 private void createDirectSubnet(Uni uni, IpUni ipUni) {
438 IpPrefix uniIpPrefix = ipUni.getIpAddress();
439 String subnetIp = NetvirtVpnUtils.getSubnetFromPrefix(uniIpPrefix);
440 IpPrefix subnetPrefix = new IpPrefix(new Ipv4Prefix(subnetIp));
441 InstanceIdentifier<Subnet> path = MefInterfaceUtils.getSubnetInstanceIdentifier(uni.getUniId(),
442 ipUni.getIpUniId(), subnetPrefix);
443 SubnetBuilder subnet = new SubnetBuilder();
444 subnet.setUniId(uni.getUniId());
445 subnet.setIpUniId(ipUni.getIpUniId());
446 subnet.setSubnet(subnetPrefix);
447 MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, subnet.build());
450 private void removeInterfaces(InstanceIdentifier<Ipvc> ipvcId, IpvcVpn ipvcVpn, Uni uniInService, IpUni ipUni) {
451 String uniId = uniInService.getUniId().getValue();
452 String vpnName = ipvcVpn.getVpnId();
453 VpnElans vpnElans = MefServicesUtils.findVpnElanForNetwork(new Identifier45(uniId), ipUni.getIpUniId(),
455 if (vpnElans == null) {
456 Log.error("Trying to remove non-operational vpn/elan for Uni {} Ip-UNi {}", uniId, ipUni.getIpUniId());
460 synchronized (vpnName.intern()) {
461 NetvirtVpnUtils.unregisterDirectSubnetForVpn(dataBroker, vpnName, new Uuid(vpnElans.getElanId()),
462 vpnElans.getElanPort());
463 uniQosManager.unMapUniPortBandwidthLimits(uniId, vpnElans.getElanPort());
464 NetvirtVpnUtils.removeLearnedVpnVipToPort(dataBroker, vpnName, vpnElans.getElanPort());
465 removeVpnInterface(vpnName, vpnElans, uniId, ipUni);
467 waitForInterfaceDpnClean(vpnName, ipvcVpn.getVrfId(), vpnElans.getElanPort());
469 synchronized (vpnName.intern()) {
470 removeElan(vpnElans, uniId, ipUni);
471 MefServicesUtils.removeOperIpvcElan(dataBroker, ipvcId, ipvcVpn.getVpnId(), uniInService.getUniId(),
472 uniInService.getIpUniId(), vpnElans.getElanId(), vpnElans.getElanPort());
477 private void waitForInterfaceDpnClean(String vpnName, String rd, String interfaceName) {
478 InstanceIdentifier<VpnInstanceOpDataEntry> vpnId = NetvirtVpnUtils.getVpnInstanceOpDataIdentifier(rd);
479 DataWaitGetter<VpnInstanceOpDataEntry> getInterfByName = (vpn) -> {
480 if (vpn.getVpnToDpnList() == null)
482 for (VpnToDpnList is : vpn.getVpnToDpnList()) {
483 if (is.getVpnInterfaces() == null)
485 for (VpnInterfaces i : is.getVpnInterfaces()) {
486 if (i.getInterfaceName().equals(interfaceName)) {
487 Log.info("Waiting for deletion vpn interface from vpn to dpn list vpn : {} interface: {}",
488 vpnName, interfaceName);
489 return interfaceName;
493 Log.info("Deleted vpn interface from vpn to dpn list vpn : {} interface: {}", vpnName, interfaceName);
498 Optional<VpnInstanceOpDataEntry> vpnOper = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, vpnId);
499 if (vpnOper.isPresent() && vpnOper.get().getVpnToDpnList() != null) {
500 for (VpnToDpnList vpnList : vpnOper.get().getVpnToDpnList()) {
501 if (vpnList.getVpnInterfaces() != null) {
502 retryCount = retryCount + 2 * vpnList.getVpnInterfaces().size();
507 @SuppressWarnings("resource")
508 DataWaitListener<VpnInstanceOpDataEntry> vpnInstanceWaiter = new DataWaitListener<>(dataBroker, vpnId,
509 retryCount, LogicalDatastoreType.OPERATIONAL, getInterfByName);
510 if (!vpnInstanceWaiter.waitForClean()) {
511 String errorMessage = String.format("Fail to wait for vpn to dpn list clean-up vpn : %s interface: %s",
512 vpnName, interfaceName);
513 Log.error(errorMessage);
514 throw new UnsupportedOperationException(errorMessage);
518 private void removeElan(VpnElans vpnElans, String uniId, IpUni ipUni) {
519 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
521 Long vlan = ipUni.getVlan() != null ? Long.valueOf(ipUni.getVlan().getValue()) : 0;
522 Log.info("Removing trunk interface for uni {} vlan: {}", uniId, vlan);
523 uniPortManager.removeCeVlan(uniId, vlan);
525 String elanName = vpnElans.getElanId();
526 String interfaceName = vpnElans.getElanPort();
528 Log.info("Removing elan instance {} and interface {}: ", elanName, interfaceName);
529 NetvirtUtils.deleteElanInterface(interfaceName, tx);
530 NetvirtUtils.deleteElanInstance(elanName, tx);
531 MdsalUtils.commitTransaction(tx);
534 private void removeVpnInterface(String vpnName, VpnElans vpnElans, String uniId, IpUni ipUni, WriteTransaction tx) {
535 String interfaceName = vpnElans.getElanPort();
536 NetvirtVpnUtils.removeVpnInterface(interfaceName, tx);
537 NetvirtVpnUtils.removeVpnPortFixedIp(vpnName, ipUni.getIpAddress(), tx);
540 private void removeVpnInterface(String vpnName, VpnElans vpnElans, String uniId, IpUni ipUni) {
541 Log.info("Removing vpn interface: " + vpnElans.getElanPort());
542 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
543 removeVpnInterface(vpnName, vpnElans, uniId, ipUni, tx);
544 MdsalUtils.commitTransaction(tx);
545 Log.info("Finished working on vpn interface: " + vpnElans.getElanPort());
548 private void removeDirectSubnet(Uni uni, IpUni ipUni) {
549 IpPrefix uniIpPrefix = ipUni.getIpAddress();
550 String subnetIp = NetvirtVpnUtils.getSubnetFromPrefix(uniIpPrefix);
551 IpPrefix subnetPrefix = new IpPrefix(new Ipv4Prefix(subnetIp));
552 InstanceIdentifier<Subnet> path = MefInterfaceUtils.getSubnetInstanceIdentifier(uni.getUniId(),
553 ipUni.getIpUniId(), subnetPrefix);
554 MdsalUtils.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
557 private void updateQos(List<Uni> uniToUpdate) {
558 uniToUpdate.forEach(u -> uniQosManager.setUniBandwidthLimits(u.getUniId()));
561 private void updateUnis(List<Uni> uniToUpdate) {
562 uniToUpdate.forEach(u -> uniQosManager.updateUni(u.getUniId(), u.getIngressBwProfile()));
563 updateQos(uniToUpdate);
566 private IpAddress getNodeIP(BigInteger dpId) {
567 Node node = getPortsNode(dpId);
568 String localIp = southBoundUtils.getOpenvswitchOtherConfig(node, LOCAL_IP);
569 if (localIp == null) {
570 throw new UnsupportedOperationException(
571 "missing local_ip key in ovsdb:openvswitch-other-configs in operational"
572 + " network-topology for node: " + node.getNodeId().getValue());
575 return new IpAddress(localIp.toCharArray());
578 @SuppressWarnings("unchecked")
579 private Node getPortsNode(BigInteger dpnId) {
580 InstanceIdentifier<BridgeRefEntry> bridgeRefInfoPath = InstanceIdentifier.create(BridgeRefInfo.class)
581 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId));
582 BridgeRefEntry bridgeRefEntry = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeRefInfoPath);
583 if (bridgeRefEntry == null) {
584 throw new UnsupportedOperationException("no bridge ref entry found for dpnId: " + dpnId);
587 InstanceIdentifier<Node> nodeId = ((InstanceIdentifier<OvsdbBridgeAugmentation>) bridgeRefEntry
588 .getBridgeReference().getValue()).firstIdentifierOf(Node.class);
589 Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodeId);
592 throw new UnsupportedOperationException("missing node for dpnId: " + dpnId);
598 private BigInteger getPortDpId(String logicalPortId) {
599 BigInteger dpId = BigInteger.ZERO;
600 if (portToDpn.containsKey(logicalPortId)) {
601 dpId = portToDpn.get(logicalPortId);
603 dpId = NetvirtUtils.getDpnForInterface(odlInterfaceRpcService, logicalPortId);
604 portToDpn.put(logicalPortId, dpId);