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;
47 public UniPortManager(final DataBroker dataBroker) {
53 public void registerListener() {
55 final DataTreeIdentifier<Uni> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
56 getInstanceIdentifier());
57 uniListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
58 log.info("UniPortListener created and registered");
59 } catch (final Exception e) {
60 log.error("UniPortListener registration failed !", e);
61 throw new IllegalStateException("UniPortListener registration failed.", e);
65 private InstanceIdentifier<Uni> getInstanceIdentifier() {
66 return MefInterfaceUtils.getUniListInstanceIdentifier();
70 public void close() throws Exception {
71 uniListenerRegistration.close();
75 public void add(DataTreeModification<Uni> newDataObject) {
76 if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
77 log.info("uni node {} created", newDataObject.getRootNode().getIdentifier());
79 Uni confUni = newDataObject.getRootNode().getDataAfter();
80 String uniId = confUni.getUniId().getValue();
82 synchronized (uniId.intern()) {
83 if (!checkOperUni(uniId)) {
86 addCheckUniPorts(confUni);
91 public void remove(DataTreeModification<Uni> removedDataObject) {
92 if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
93 log.info("uni node {} deleted", removedDataObject.getRootNode().getIdentifier());
95 Uni confUni = removedDataObject.getRootNode().getDataBefore();
96 String uniId = confUni.getUniId().getValue();
97 synchronized (uniId.intern()) {
98 if (!checkOperUni(uniId)) {
101 removeUniPorts(confUni);
106 public void update(DataTreeModification<Uni> modifiedDataObject) {
107 if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
108 log.info("node connector {} updated", modifiedDataObject.getRootNode().getIdentifier());
110 Uni confUni = modifiedDataObject.getRootNode().getDataAfter();
111 String uniId = confUni.getUniId().getValue();
112 synchronized (uniId.intern()) {
113 if (!checkOperUni(uniId)) {
116 removeCheckUniPorts(confUni);
117 addCheckUniPorts(confUni);
122 public void updateOperUni(String uniId) {
123 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
124 if (confUni == null) {
125 log.debug("No UNI {} exists, nothing to update");
128 synchronized (uniId.intern()) {
129 if (!checkOperUni(uniId)) {
132 log.info("UNI {} ports updated", uniId);
134 removeCheckUniPorts(confUni);
135 addCheckUniPorts(confUni);
140 public void removeUniPorts(String uniId) {
141 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
142 if (confUni == null) {
143 log.debug("No UNI {} exists, nothing to update");
146 synchronized (uniId.intern()) {
147 if (!checkOperUni(uniId)) {
150 removeUniPorts(confUni);
154 private boolean checkOperUni(String uniId) {
155 Uni operUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
156 if (operUni == null) {
157 log.info("Uni {} is not operational", uniId);
163 private void addCheckUniPorts(Uni confUni) {
164 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
166 String uniId = confUni.getUniId().getValue();
167 Link link = MefInterfaceUtils.getLink(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
168 String trunkInterface = MefInterfaceUtils.getInterfaceNameForVlan(uniId, null);
169 String parentInterfaceName = MefInterfaceUtils.getTrunkParentName(link);
170 List<VlanToPort> operVlanInterfaces = getOperTrunkInterfaces(uniId);
171 if (!hasVlanPort(operVlanInterfaces, Long.valueOf(0))) {
172 VlanToPort newOperVlanInterface = addTrunkInterface(trunkInterface, parentInterfaceName, tx);
173 operVlanInterfaces.add(newOperVlanInterface);
176 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
177 : Collections.emptyList();
178 for (CeVlan ceVlan : ceVlans) {
179 Long vlan = ceVlan.getVid().getValue().longValue();
180 if (hasVlanPort(operVlanInterfaces, vlan)) {
184 String trunkMemberName = MefInterfaceUtils.getInterfaceNameForVlan(uniId, vlan);
185 VlanToPort newOperVlanInterface = addTrunkMemberInterface(trunkMemberName, trunkInterface, vlan, tx);
186 operVlanInterfaces.add(newOperVlanInterface);
188 // set VlanMapping to Uni
189 setOperTrunkInterfaces(uniId, operVlanInterfaces, tx);
191 MdsalUtils.commitTransaction(tx);
194 private void removeCheckUniPorts(Uni confUni) {
195 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
197 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
198 : Collections.emptyList();
199 List<Long> vlansValue = ceVlans.stream().map(x -> x.getVid().getValue()).collect(Collectors.toList());
201 String uniId = confUni.getUniId().getValue();
202 List<VlanToPort> operVlanInterfaces = getOperTrunkInterfaces(uniId);
204 for (VlanToPort oldPort : getOperTrunkInterfaces(uniId)) {
205 Long oldVlan = oldPort.getVlan().getValue();
206 if (!vlansValue.contains(oldVlan)) {
207 VlanToPort removedOperVlanInterface = removeTrunkInterface(oldPort.getVlanPortId(), oldVlan, tx);
208 operVlanInterfaces.remove(removedOperVlanInterface);
211 // set VlanMapping to Uni
212 setOperTrunkInterfaces(uniId, operVlanInterfaces, tx);
214 MdsalUtils.commitTransaction(tx);
217 private void removeUniPorts(Uni confUni) {
218 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
219 String uniId = confUni.getUniId().getValue();
221 for (VlanToPort oldPort : getOperTrunkInterfaces(uniId)) {
222 Long oldVlan = oldPort.getVlan().getValue();
223 removeTrunkInterface(oldPort.getVlanPortId(), oldVlan, tx);
225 setOperTrunkInterfaces(uniId, new ArrayList<>(), tx);
227 MdsalUtils.commitTransaction(tx);
230 private VlanToPort addTrunkInterface(String interfaceName, String parentInterfaceName, WriteTransaction tx) {
231 log.info("Adding VLAN trunk {} ParentRef {}", interfaceName, parentInterfaceName);
232 Interface trunkInterface = NetvirtUtils.createTrunkInterface(interfaceName, parentInterfaceName);
233 NetvirtUtils.writeInterface(trunkInterface, tx);
234 return createOperTrunkInterfaceMapping(Long.valueOf(0), trunkInterface.getName());
237 private VlanToPort addTrunkMemberInterface(String interfaceName, String parentInterfaceName, Long vlan,
238 WriteTransaction tx) {
239 log.info("Adding VLAN trunk member {} ParentRef {}", interfaceName, parentInterfaceName);
240 Interface trunkInterface = NetvirtUtils.createTrunkMemberInterface(interfaceName, parentInterfaceName,
242 NetvirtUtils.writeInterface(trunkInterface, tx);
243 return createOperTrunkInterfaceMapping(vlan, trunkInterface.getName());
246 private VlanToPort removeTrunkInterface(String interfaceName, Long vlan, WriteTransaction tx) {
247 log.info("Delete VLAN trunk {} ParentRef {}", interfaceName);
248 NetvirtUtils.deleteInterface(interfaceName, tx);
249 return createOperTrunkInterfaceMapping(vlan, interfaceName);
252 private List<VlanToPort> getOperTrunkInterfaces(String operUniId) {
253 InstanceIdentifier<Uni> identifier = MefInterfaceUtils.getUniInstanceIdentifier(operUniId);
254 InstanceIdentifier<PortVlanMapping> path = identifier.augmentation(PortVlanMapping.class);
255 Optional<PortVlanMapping> portVlanMapping = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
256 if (portVlanMapping.isPresent()) {
257 return portVlanMapping.get().getVlanToPort();
259 return new ArrayList<>();
263 private void setOperTrunkInterfaces(String operUniId, List<VlanToPort> vlanToPort, WriteTransaction tx) {
264 InstanceIdentifier<Uni> identifier = MefInterfaceUtils.getUniInstanceIdentifier(operUniId);
265 InstanceIdentifier<PortVlanMapping> path = identifier.augmentation(PortVlanMapping.class);
267 PortVlanMappingBuilder portVlanMappingB = new PortVlanMappingBuilder();
268 portVlanMappingB.setVlanToPort(vlanToPort);
270 tx.put(LogicalDatastoreType.OPERATIONAL, path, portVlanMappingB.build());
273 private VlanToPort createOperTrunkInterfaceMapping(Long vlan, String interfaceName) {
274 final Long vlanNotNull = replaceNull(vlan);
276 VlanToPortBuilder vlanToPortBuilder = new VlanToPortBuilder();
277 vlanToPortBuilder.setVlan(new VlanIdOrNoneType(vlanNotNull));
278 vlanToPortBuilder.setVlanPortId(interfaceName);
279 return vlanToPortBuilder.build();
282 private boolean hasVlanPort(List<VlanToPort> vlanInterfaces, Long vlan) {
283 if (vlanInterfaces == null) {
286 final Long vlanNotNull = replaceNull(vlan);
288 if (vlanInterfaces.stream().filter(x -> x.getVlan().getValue().equals(vlanNotNull)).findAny().isPresent()) {
294 private static final Long replaceNull(Long vlan) {
296 return Long.valueOf(0);
302 public void addCeVlan(String uniId, Long vlanId) {
303 if (getUniVlanInterfaceNoRetry(uniId, vlanId) != null) {
304 log.debug("UNI {} Port for vlan {} exists already, nothing to update", uniId, vlanId);
307 synchronized (uniId.intern()) {
308 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
309 if (confUni == null) {
310 log.debug("No UNI {} exists, nothing to update");
313 if (!checkOperUni(uniId)) {
316 log.info("UNI {} Vlan {} adding", uniId, vlanId);
317 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan() : new ArrayList<>();
318 CeVlanBuilder ceVlanBuilder = new CeVlanBuilder();
319 ceVlanBuilder.setVid(new VlanIdType(vlanId));
320 CeVlansBuilder ceVlansBuilder = confUni.getCeVlans() != null ? new CeVlansBuilder(confUni.getCeVlans())
321 : new CeVlansBuilder();
322 ceVlans.add(ceVlanBuilder.build());
323 ceVlansBuilder.setCeVlan(ceVlans);
324 UniBuilder uniBuilder = new UniBuilder();
325 uniBuilder.setUniId(confUni.getUniId());
326 uniBuilder.setCeVlans(ceVlansBuilder.build());
327 MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
328 MefInterfaceUtils.getUniInstanceIdentifier(uniId), uniBuilder.build());
333 public void removeCeVlan(String uniId, Long vlanId) {
334 if (getUniVlanInterfaceNoRetry(uniId, vlanId) == null) {
335 log.debug("No UNI {} Port for vlan {} exists already, nothing to delete", uniId, vlanId);
338 synchronized (uniId.intern()) {
339 Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
340 if (confUni == null) {
341 log.debug("No UNI {} exists, nothing to update");
344 if (!checkOperUni(uniId)) {
347 log.info("UNI {} Vlan {} deleting", uniId, vlanId);
348 UniBuilder uniBuilder = new UniBuilder(confUni);
350 if (vlanId != null && vlanId != 0l) {
351 List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
352 : Collections.emptyList();
353 CeVlanBuilder ceVlanBuilder = new CeVlanBuilder();
354 ceVlanBuilder.setVid(new VlanIdType(vlanId));
355 CeVlansBuilder ceVlansBuilder = new CeVlansBuilder(confUni.getCeVlans());
356 ceVlans.remove(ceVlanBuilder.build());
357 ceVlansBuilder.setCeVlan(ceVlans);
358 uniBuilder.setCeVlans(ceVlansBuilder.build());
360 uniBuilder.setCeVlans(null);
362 MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
363 MefInterfaceUtils.getUniInstanceIdentifier(uniId), uniBuilder.build());
369 public List<String> getUniVlanInterfaces(String uniId) {
370 synchronized (uniId.intern()) {
371 List<VlanToPort> vlanToPorts = getOperTrunkInterfaces(uniId);
372 return vlanToPorts.stream().map(port -> port.getVlanPortId()).collect(Collectors.toList());
377 public String getUniVlanInterface(String uniId, Long vlanId) {
378 Long vlanNotNull = replaceNull(vlanId);
379 return getUniVlanInterfaceRetry(uniId, vlanNotNull, 0);
382 public String getUniVlanInterfaceNoRetry(String uniId, Long vlanId) {
383 Long vlanNotNull = replaceNull(vlanId);
384 return getUniVlanInterfaceRetry(uniId, vlanNotNull, maxWaitRetries);
387 private String getUniVlanInterfaceRetry(String uniId, Long vlanId, int retries) {
388 log.trace("Retry {} to wait for uniId {} vlan {} interface", retries, uniId, vlanId);
389 List<VlanToPort> vlanToPorts = getOperTrunkInterfaces(uniId);
390 java.util.Optional<String> toReturn = vlanToPorts.stream()
391 .filter(port -> port.getVlan().getValue().equals(vlanId)).map(port -> port.getVlanPortId()).findFirst();
392 if (toReturn.isPresent()) {
393 return toReturn.get();
395 if (retries >= maxWaitRetries) {
398 NetvirtUtils.safeSleep();
399 return getUniVlanInterfaceRetry(uniId, vlanId, ++retries);