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.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.stream.Collectors;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
19 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
22 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.PortVlanMapping;
23 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.PortVlanMappingBuilder;
24 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
25 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.CeVlansBuilder;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.VlanToPort;
28 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.VlanToPortBuilder;
29 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ce.vlans.CeVlan;
30 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ce.vlans.CeVlanBuilder;
31 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
32 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.VlanIdOrNoneType;
33 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.VlanIdType;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import com.google.common.base.Optional;
41 public class UniPortManager extends UnimgrDataTreeChangeListener<Uni> implements IUniPortManager {
43 private static final Logger log = LoggerFactory.getLogger(UniPortManager.class);
44 private ListenerRegistration<UniPortManager> uniListenerRegistration;
45 private static int maxWaitRetries = 3;
46 private static long noVlan = 0l;
48 public UniPortManager(final DataBroker dataBroker) {
54 public void registerListener() {
56 final DataTreeIdentifier<Uni> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
57 getInstanceIdentifier());
58 uniListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
59 log.info("UniPortListener created and registered");
60 } catch (final Exception e) {
61 log.error("UniPortListener registration failed !", e);
62 throw new IllegalStateException("UniPortListener registration failed.", e);
66 private InstanceIdentifier<Uni> getInstanceIdentifier() {
67 return MefInterfaceUtils.getUniListInstanceIdentifier();
71 public void close() throws Exception {
72 uniListenerRegistration.close();
76 public void add(DataTreeModification<Uni> newDataObject) {
77 if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
78 log.info("uni node {} created", newDataObject.getRootNode().getIdentifier());
80 Uni confUni = newDataObject.getRootNode().getDataAfter();
81 String uniId = confUni.getUniId().getValue();
83 synchronized (uniId.intern()) {
84 if (!checkOperUni(uniId)) {
87 addCheckUniPorts(confUni);
92 public void remove(DataTreeModification<Uni> removedDataObject) {
93 if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
94 log.info("uni node {} deleted", removedDataObject.getRootNode().getIdentifier());
96 Uni confUni = removedDataObject.getRootNode().getDataBefore();
97 String uniId = confUni.getUniId().getValue();
98 synchronized (uniId.intern()) {
99 if (!checkOperUni(uniId)) {
102 removeUniPorts(confUni);
107 public void update(DataTreeModification<Uni> modifiedDataObject) {
108 if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
109 log.info("node connector {} updated", modifiedDataObject.getRootNode().getIdentifier());
111 Uni confUni = modifiedDataObject.getRootNode().getDataAfter();
112 String uniId = confUni.getUniId().getValue();
113 synchronized (uniId.intern()) {
114 if (!checkOperUni(uniId)) {
117 removeCheckUniPorts(confUni);
118 addCheckUniPorts(confUni);
123 public void updateOperUni(String uniId) {
124 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
125 if (confUni == null) {
126 log.debug("No UNI {} exists, nothing to update");
129 synchronized (uniId.intern()) {
130 if (!checkOperUni(uniId)) {
133 log.info("UNI {} ports updated", uniId);
135 removeCheckUniPorts(confUni);
136 addCheckUniPorts(confUni);
141 public void removeUniPorts(String uniId) {
142 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
143 if (confUni == null) {
144 log.debug("No UNI {} exists, nothing to update");
147 synchronized (uniId.intern()) {
148 if (!checkOperUni(uniId)) {
151 removeUniPorts(confUni);
155 private boolean checkOperUni(String uniId) {
156 Uni operUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
157 if (operUni == null) {
158 log.info("Uni {} is not operational", uniId);
164 private void addCheckUniPorts(Uni confUni) {
165 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
167 String uniId = confUni.getUniId().getValue();
168 Link link = MefInterfaceUtils.getLink(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
169 String trunkInterface = MefInterfaceUtils.getInterfaceNameForVlan(uniId, null);
170 String parentInterfaceName = MefInterfaceUtils.getTrunkParentName(link);
171 List<VlanToPort> operVlanInterfaces = getOperTrunkInterfaces(uniId);
172 if (!hasVlanPort(operVlanInterfaces, Long.valueOf(0))) {
173 VlanToPort newOperVlanInterface = addTrunkInterface(trunkInterface, parentInterfaceName, tx);
174 operVlanInterfaces.add(newOperVlanInterface);
177 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
178 : Collections.emptyList();
179 for (CeVlan ceVlan : ceVlans) {
180 Long vlan = ceVlan.getVid().getValue().longValue();
181 if (hasVlanPort(operVlanInterfaces, vlan)) {
185 String trunkMemberName = MefInterfaceUtils.getInterfaceNameForVlan(uniId, vlan);
186 VlanToPort newOperVlanInterface = addTrunkMemberInterface(trunkMemberName, trunkInterface, vlan, tx);
187 operVlanInterfaces.add(newOperVlanInterface);
189 // set VlanMapping to Uni
190 setOperTrunkInterfaces(uniId, operVlanInterfaces, tx);
192 MdsalUtils.commitTransaction(tx);
195 private void removeCheckUniPorts(Uni confUni) {
196 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
198 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
199 : Collections.emptyList();
200 List<Long> vlansValue = ceVlans.stream().map(x -> x.getVid().getValue()).collect(Collectors.toList());
202 String uniId = confUni.getUniId().getValue();
203 List<VlanToPort> operVlanInterfaces = getOperTrunkInterfaces(uniId);
205 for (VlanToPort oldPort : getOperTrunkInterfaces(uniId)) {
206 Long oldVlan = oldPort.getVlan().getValue();
207 if (!vlansValue.contains(oldVlan) && oldVlan != noVlan) {
208 VlanToPort removedOperVlanInterface = removeTrunkInterface(oldPort.getVlanPortId(), oldVlan, tx);
209 operVlanInterfaces.remove(removedOperVlanInterface);
212 // set VlanMapping to Uni
213 setOperTrunkInterfaces(uniId, operVlanInterfaces, tx);
215 MdsalUtils.commitTransaction(tx);
218 private void removeUniPorts(Uni confUni) {
219 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
220 String uniId = confUni.getUniId().getValue();
222 for (VlanToPort oldPort : getOperTrunkInterfaces(uniId)) {
223 Long oldVlan = oldPort.getVlan().getValue();
224 removeTrunkInterface(oldPort.getVlanPortId(), oldVlan, tx);
226 setOperTrunkInterfaces(uniId, new ArrayList<>(), tx);
228 MdsalUtils.commitTransaction(tx);
231 private VlanToPort addTrunkInterface(String interfaceName, String parentInterfaceName, WriteTransaction tx) {
232 log.info("Adding VLAN trunk {} ParentRef {}", interfaceName, parentInterfaceName);
233 Interface trunkInterface = NetvirtUtils.createTrunkInterface(interfaceName, parentInterfaceName);
234 NetvirtUtils.writeInterface(trunkInterface, tx);
235 return createOperTrunkInterfaceMapping(Long.valueOf(0), trunkInterface.getName());
238 private VlanToPort addTrunkMemberInterface(String interfaceName, String parentInterfaceName, Long vlan,
239 WriteTransaction tx) {
240 log.info("Adding VLAN trunk member {} ParentRef {}", interfaceName, parentInterfaceName);
241 Interface trunkInterface = NetvirtUtils.createTrunkMemberInterface(interfaceName, parentInterfaceName,
243 NetvirtUtils.writeInterface(trunkInterface, tx);
244 return createOperTrunkInterfaceMapping(vlan, trunkInterface.getName());
247 private VlanToPort removeTrunkInterface(String interfaceName, Long vlan, WriteTransaction tx) {
248 log.info("Delete VLAN trunk {}", interfaceName);
249 NetvirtUtils.deleteInterface(interfaceName, tx);
250 return createOperTrunkInterfaceMapping(vlan, interfaceName);
253 private List<VlanToPort> getOperTrunkInterfaces(String operUniId) {
254 InstanceIdentifier<Uni> identifier = MefInterfaceUtils.getUniInstanceIdentifier(operUniId);
255 InstanceIdentifier<PortVlanMapping> path = identifier.augmentation(PortVlanMapping.class);
256 Optional<PortVlanMapping> portVlanMapping = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
257 if (portVlanMapping.isPresent()) {
258 return portVlanMapping.get().getVlanToPort();
260 return new ArrayList<>();
264 private void setOperTrunkInterfaces(String operUniId, List<VlanToPort> vlanToPort, WriteTransaction tx) {
265 InstanceIdentifier<Uni> identifier = MefInterfaceUtils.getUniInstanceIdentifier(operUniId);
266 InstanceIdentifier<PortVlanMapping> path = identifier.augmentation(PortVlanMapping.class);
268 PortVlanMappingBuilder portVlanMappingB = new PortVlanMappingBuilder();
269 portVlanMappingB.setVlanToPort(vlanToPort);
271 tx.put(LogicalDatastoreType.OPERATIONAL, path, portVlanMappingB.build());
274 private VlanToPort createOperTrunkInterfaceMapping(Long vlan, String interfaceName) {
275 final Long vlanNotNull = replaceNull(vlan);
277 VlanToPortBuilder vlanToPortBuilder = new VlanToPortBuilder();
278 vlanToPortBuilder.setVlan(new VlanIdOrNoneType(vlanNotNull));
279 vlanToPortBuilder.setVlanPortId(interfaceName);
280 return vlanToPortBuilder.build();
283 private boolean hasVlanPort(List<VlanToPort> vlanInterfaces, Long vlan) {
284 if (vlanInterfaces == null) {
287 final Long vlanNotNull = replaceNull(vlan);
289 if (vlanInterfaces.stream().filter(x -> x.getVlan().getValue().equals(vlanNotNull)).findAny().isPresent()) {
295 private static final Long replaceNull(Long vlan) {
297 return Long.valueOf(0);
303 public void addCeVlan(String uniId, Long vlanId) {
304 if (getUniVlanInterfaceNoRetry(uniId, vlanId) != null) {
305 log.debug("UNI {} Port for vlan {} exists already, nothing to update", uniId, vlanId);
308 synchronized (uniId.intern()) {
309 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
310 if (confUni == null) {
311 log.debug("No UNI {} exists, nothing to update");
314 if (!checkOperUni(uniId)) {
317 log.info("UNI {} Vlan {} adding", uniId, vlanId);
318 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan() : new ArrayList<>();
319 CeVlanBuilder ceVlanBuilder = new CeVlanBuilder();
320 ceVlanBuilder.setVid(new VlanIdType(vlanId));
321 CeVlansBuilder ceVlansBuilder = confUni.getCeVlans() != null ? new CeVlansBuilder(confUni.getCeVlans())
322 : new CeVlansBuilder();
323 ceVlans.add(ceVlanBuilder.build());
324 ceVlansBuilder.setCeVlan(ceVlans);
325 UniBuilder uniBuilder = new UniBuilder();
326 uniBuilder.setUniId(confUni.getUniId());
327 uniBuilder.setCeVlans(ceVlansBuilder.build());
328 MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
329 MefInterfaceUtils.getUniInstanceIdentifier(uniId), uniBuilder.build());
334 public void removeCeVlan(String uniId, Long vlanId) {
335 if (getUniVlanInterfaceNoRetry(uniId, vlanId) == null) {
336 log.debug("No UNI {} Port for vlan {} exists already, nothing to delete", uniId, vlanId);
339 synchronized (uniId.intern()) {
340 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
341 if (confUni == null) {
342 log.debug("No UNI {} exists, nothing to update");
345 if (!checkOperUni(uniId)) {
348 log.info("UNI {} Vlan {} deleting", uniId, vlanId);
349 UniBuilder uniBuilder = new UniBuilder(confUni);
351 if (vlanId != null && vlanId != noVlan) {
352 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
353 : Collections.emptyList();
354 CeVlanBuilder ceVlanBuilder = new CeVlanBuilder();
355 ceVlanBuilder.setVid(new VlanIdType(vlanId));
356 CeVlansBuilder ceVlansBuilder = new CeVlansBuilder(confUni.getCeVlans());
357 ceVlans.remove(ceVlanBuilder.build());
358 ceVlansBuilder.setCeVlan(ceVlans);
359 uniBuilder.setCeVlans(ceVlansBuilder.build());
361 uniBuilder.setCeVlans(null);
363 MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
364 MefInterfaceUtils.getUniInstanceIdentifier(uniId), uniBuilder.build());
370 public List<String> getUniVlanInterfaces(String uniId) {
371 synchronized (uniId.intern()) {
372 List<VlanToPort> vlanToPorts = getOperTrunkInterfaces(uniId);
373 return vlanToPorts.stream().map(port -> port.getVlanPortId()).collect(Collectors.toList());
378 public String getUniVlanInterface(String uniId, Long vlanId) {
379 Long vlanNotNull = replaceNull(vlanId);
380 return getUniVlanInterfaceRetry(uniId, vlanNotNull, 0);
383 public String getUniVlanInterfaceNoRetry(String uniId, Long vlanId) {
384 Long vlanNotNull = replaceNull(vlanId);
385 return getUniVlanInterfaceRetry(uniId, vlanNotNull, maxWaitRetries);
388 private String getUniVlanInterfaceRetry(String uniId, Long vlanId, int retries) {
389 log.trace("Retry {} to wait for uniId {} vlan {} interface", retries, uniId, vlanId);
390 List<VlanToPort> vlanToPorts = getOperTrunkInterfaces(uniId);
391 java.util.Optional<String> toReturn = vlanToPorts.stream()
392 .filter(port -> port.getVlan().getValue().equals(vlanId)).map(port -> port.getVlanPortId()).findFirst();
393 if (toReturn.isPresent()) {
394 return toReturn.get();
396 if (retries >= maxWaitRetries) {
399 NetvirtUtils.safeSleep();
400 return getUniVlanInterfaceRetry(uniId, vlanId, ++retries);