From 2e4e7b0bc341e4c0b2f051d5117e5168e46a9ae7 Mon Sep 17 00:00:00 2001 From: Konsta Pozdeev Date: Sun, 8 Jan 2017 17:59:56 +0200 Subject: [PATCH] Update profile listener Change-Id: I9f1a7aa09320a1c03707c773606c2ba04ed87f5e Signed-off-by: Konsta Pozdeev --- .../unimgr/mef/netvirt/EvcListener.java | 18 +- .../unimgr/mef/netvirt/IpvcListener.java | 18 +- .../unimgr/mef/netvirt/UniQosManager.java | 206 +++++++++++++++--- 3 files changed, 202 insertions(+), 40 deletions(-) diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcListener.java index ee5dcab5..2a5ef802 100644 --- a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcListener.java +++ b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcListener.java @@ -30,6 +30,7 @@ import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.serv import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.EvcType; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.EvcUniRoleType; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType; import org.opendaylight.yangtools.concepts.ListenerRegistration; @@ -191,7 +192,8 @@ public class EvcListener extends UnimgrDataTreeChangeListener implements IU InstanceIdentifier evcId = newDataObject.getRootPath().getRootIdentifier(); synchronized (instanceName.intern()) { - NetvirtUtils.createElanInstance(dataBroker, instanceName, isEtree, data.getSegmentationId(), data.getMacTimeout()); + NetvirtUtils.createElanInstance(dataBroker, instanceName, isEtree, data.getSegmentationId(), + data.getMacTimeout()); // Create interfaces if (data.getUnis() == null) { @@ -247,8 +249,11 @@ public class EvcListener extends UnimgrDataTreeChangeListener implements IU List originalUni = original.getUnis() != null && original.getUnis().getUni() != null ? original.getUnis().getUni() : Collections.emptyList(); + List originalUniIds = originalUni.stream().map(u -> u.getUniId()) + .collect(Collectors.toList()); List updateUni = update.getUnis() != null && update.getUnis().getUni() != null ? update.getUnis().getUni() : Collections.emptyList(); + List updateUniIds = updateUni.stream().map(u -> u.getUniId()).collect(Collectors.toList()); synchronized (original.getEvcId().getValue().intern()) { @@ -258,18 +263,23 @@ public class EvcListener extends UnimgrDataTreeChangeListener implements IU // Changed Uni will be deleted / recreated List uniToRemove = new ArrayList<>(originalUni); - uniToRemove.removeAll(updateUni); + uniToRemove.removeIf(u -> updateUniIds.contains(u.getUniId())); for (Uni uni : uniToRemove) { removeUniElanInterfaces(evcId, instanceName, uni); } updateQos(uniToRemove); List uniToCreate = new ArrayList<>(updateUni); + uniToCreate.removeIf(u -> originalUniIds.contains(u.getUniId())); uniToCreate.removeAll(originalUni); for (Uni uni : uniToCreate) { createUniElanInterfaces(evcId, instanceName, uni, isEtree); } updateQos(uniToCreate); + + List uniToUpdate = new ArrayList<>(updateUni); + uniToUpdate.removeIf(u -> !originalUniIds.contains(u.getUniId())); + updateUnis(uniToUpdate); } } catch (final Exception e) { log.error("Update evc failed !", e); @@ -459,4 +469,8 @@ public class EvcListener extends UnimgrDataTreeChangeListener implements IU uniToUpdate.forEach(u -> uniQosManager.setUniBandwidthLimits(u.getUniId())); } + private void updateUnis(List uniToUpdate) { + uniToUpdate.forEach(u -> uniQosManager.updateUni(u.getUniId(), u.getIngressBwProfile())); + updateQos(uniToUpdate); + } } diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcListener.java index 9c8a773f..6e8a7fee 100644 --- a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcListener.java +++ b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcListener.java @@ -11,6 +11,7 @@ package org.opendaylight.unimgr.mef.netvirt; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; @@ -317,19 +318,27 @@ public class IpvcListener extends UnimgrDataTreeChangeListener implements String rd = waitForRd(vpnName); List originalUni = origIpvc.getUnis() != null && origIpvc.getUnis().getUni() != null ? origIpvc.getUnis().getUni() : Collections.emptyList(); + List originalUniIds = originalUni.stream().map(u -> u.getUniId()) + .collect(Collectors.toList()); List updateUni = updateIpvc.getUnis() != null && updateIpvc.getUnis().getUni() != null ? updateIpvc.getUnis().getUni() : Collections.emptyList(); + List updateUniIds = updateUni.stream().map(u -> u.getUniId()).collect(Collectors.toList()); synchronized (vpnName.intern()) { WriteTransaction txRemove = MdsalUtils.createTransaction(dataBroker); List uniToRemove = new ArrayList<>(originalUni); - uniToRemove.removeAll(updateUni); + uniToRemove.removeIf(u -> updateUniIds.contains(u.getUniId())); removeUnis(ipvcId, operIpvcVpn, uniToRemove, txRemove); MdsalUtils.commitTransaction(txRemove); } List uniToCreate = new ArrayList<>(updateUni); - uniToCreate.removeAll(originalUni); + uniToCreate.removeIf(u -> originalUniIds.contains(u.getUniId())); createUnis(vpnName, ipvcId, uniToCreate, rd); + + List uniToUpdate = new ArrayList<>(updateUni); + uniToUpdate.removeIf(u -> !originalUniIds.contains(u.getUniId())); + updateUnis(uniToUpdate); + } catch (final Exception e) { Log.error("Update ipvc failed !", e); } @@ -481,4 +490,9 @@ public class IpvcListener extends UnimgrDataTreeChangeListener implements private void updateQos(List uniToUpdate) { uniToUpdate.forEach(u -> uniQosManager.setUniBandwidthLimits(u.getUniId())); } + + private void updateUnis(List uniToUpdate) { + uniToUpdate.forEach(u -> uniQosManager.updateUni(u.getUniId(), u.getIngressBwProfile())); + updateQos(uniToUpdate); + } } diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniQosManager.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniQosManager.java index 511aeed5..19751bb1 100644 --- a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniQosManager.java +++ b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniQosManager.java @@ -10,17 +10,21 @@ package org.opendaylight.unimgr.mef.netvirt; import com.google.common.base.Optional; -import jline.internal.Log; - import java.math.BigInteger; import java.util.Iterator; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.stream.Collectors; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils; +import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.MefGlobal; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.mef.global.Profiles; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.mef.global.bwp.flows.group.BwpFlow; @@ -45,62 +49,142 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class UniQosManager { - private static final Logger LOG = LoggerFactory.getLogger(UniQosManager.class); +public class UniQosManager extends UnimgrDataTreeChangeListener { + private static final Logger Log = LoggerFactory.getLogger(UniQosManager.class); private OdlInterfaceRpcService odlInterfaceRpcService; private DataBroker dataBroker; private final Long noLimit = 0l; + private final static String noProfile = ""; + private ListenerRegistration bwListenerRegistration; + // key in first map is uniId, key in second map is logical portId private ConcurrentHashMap> uniPortBandwidthLimits; // map of current values per uni private ConcurrentHashMap uniBandwidthLimits; - + private ConcurrentHashMap uniToDpn; public UniQosManager(final DataBroker dataBroker, OdlInterfaceRpcService odlInterfaceRpcService) { + super(dataBroker); + this.dataBroker = dataBroker; this.odlInterfaceRpcService = odlInterfaceRpcService; this.uniPortBandwidthLimits = new ConcurrentHashMap<>(); this.uniBandwidthLimits = new ConcurrentHashMap<>(); this.uniToDpn = new ConcurrentHashMap<>(); + registerListener(); } - public void mapUniPortBandwidthLimits(String uniId, String portId, Long maxKbps, Long maxBurstKb) { - Log.info("Record rate limits for Uni {} port {} maxKbps {} maxBurstKb {}", uniId, portId, maxKbps, maxBurstKb); - uniPortBandwidthLimits.putIfAbsent(uniId, new ConcurrentHashMap<>()); - ConcurrentHashMap uniMap = uniPortBandwidthLimits.get(uniId); - uniMap.put(portId, new BandwidthLimits(maxKbps, maxBurstKb)); + public void registerListener() { + try { + final DataTreeIdentifier dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, + getBwFlowsInstanceIdentifier()); + bwListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this); + Log.info("UniQosManager created and registered"); + } catch (final Exception e) { + Log.error("UniQosManager DataChange listener registration failed !", e); + throw new IllegalStateException("UniQosManager registration Listener failed.", e); + } } - public void mapUniPortBandwidthLimits(String uniId, String portId, Identifier45 bwProfile) { + public synchronized void mapUniPortBandwidthLimits(String uniId, String portId, Identifier45 bwProfile) { Long maxKbps = noLimit; Long maxBurstKb = noLimit; if (bwProfile != null) { - Optional bwFlowOp = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, getBwFlowInstanceIdentifier(bwProfile)); if (!bwFlowOp.isPresent()) { Log.trace("Can't read bw profile {} for Uni {}", bwProfile, uniId); - return; + } else { + // Kb per second + maxKbps = bwFlowOp.get().getCir().getValue(); + // burst in bytes, ovs requires in Kb + maxBurstKb = bwFlowOp.get().getCbs().getValue() * 8 / 1024; + Log.info("Record rate limits for Uni {} Profile {}", uniId, bwProfile); } - // Kb per second - maxKbps = bwFlowOp.get().getCir().getValue(); - // burst in bytes, ovs requires in Kb - maxBurstKb = bwFlowOp.get().getCbs().getValue() * 8 / 1024; - Log.info("Record rate limits for Uni {} Profile {}", uniId, bwProfile); } - mapUniPortBandwidthLimits(uniId, portId, maxKbps, maxBurstKb); + + mapUniPortBandwidthLimits(uniId, portId, maxKbps, maxBurstKb, replaceNull(bwProfile)); } - public void unMapUniPortBandwidthLimits(String uniId, String portId) { - Log.debug("Delete rate limits for Uni {} port {}", uniId, portId); + private synchronized void mapUniPortBandwidthLimits(String uniId, String portId, Long maxKbps, Long maxBurstKb, + String profileName) { + Log.info("Record rate limits for Uni {} port {} maxKbps {} maxBurstKb {}", uniId, portId, maxKbps, maxBurstKb); + uniPortBandwidthLimits.putIfAbsent(uniId, new ConcurrentHashMap<>()); + ConcurrentHashMap uniMap = uniPortBandwidthLimits.get(uniId); + uniMap.put(portId, new BandwidthLimits(maxKbps, maxBurstKb, profileName)); + } + + public void updateUni(Identifier45 uniId, Identifier45 bwProfile) { + String bwProfileSafe = replaceNull(bwProfile); + Log.info("Update rate limits for Uni {}", uniId.getValue()); + ConcurrentHashMap uniMap = uniPortBandwidthLimits.get(uniId.getValue()); + if (uniMap == null) { + Log.error("Trying to update limits for non-exsting uni {}", uniId.getValue()); + return; + } + for (String portName : uniMap.keySet()) { + if (uniMap.get(portName).getProfileName().equals(bwProfileSafe)) { + continue; + } + if (bwProfile != null) { + mapUniPortBandwidthLimits(uniId.getValue(), portName, new Identifier45(bwProfileSafe)); + } else { + unMapUniPortBandwidthLimits(uniId.getValue(), portName); + } + } + } + + private void updateProfile(Identifier45 bwProfile) { + Log.info("Update rate limits for profile {}", bwProfile); + List unisWithProfile = uniBandwidthLimits.entrySet().stream() + .filter(m -> m.getValue().profileName.equals(bwProfile.getValue())).map(m -> m.getKey()) + .collect(Collectors.toList()); + + for (String uniId : unisWithProfile) { + ConcurrentHashMap uniMap = uniPortBandwidthLimits.get(uniId); + uniMap.forEach((k, v) -> { + mapUniPortBandwidthLimits(uniId, k, bwProfile); + }); + } + + for (String uniId : unisWithProfile) { + setUniBandwidthLimits(uniId); + } + } + + public void deleteProfile(Identifier45 bwProfile) { + Log.info("Delete rate limits for profile {}", bwProfile); + List unisWithProfile = uniBandwidthLimits.entrySet().stream() + .filter(m -> m.getValue().profileName.equals(bwProfile.getValue())).map(m -> m.getKey()) + .collect(Collectors.toList()); + + for (String uniId : unisWithProfile) { + ConcurrentHashMap uniMap = uniPortBandwidthLimits.get(uniId); + uniMap.forEach((k, v) -> { + unMapUniPortBandwidthLimits(uniId, k, bwProfile.getValue()); + }); + } + + for (String uniId : unisWithProfile) { + setUniBandwidthLimits(uniId); + } + } + + public synchronized void unMapUniPortBandwidthLimits(String uniId, String portId) { + unMapUniPortBandwidthLimits(uniId, portId, noProfile); + } + + public synchronized void unMapUniPortBandwidthLimits(String uniId, String portId, String profileTosave) { + Log.info("Delete rate limits for Uni {} port {}", uniId, portId); ConcurrentHashMap uniMap = uniPortBandwidthLimits.get(uniId); if (uniMap == null) { Log.error("Trying to delete limits for non-exsting uni {}", uniId); @@ -108,12 +192,16 @@ public class UniQosManager { } uniMap.remove(portId); if (uniMap.isEmpty()) { - uniMap.put(portId, new BandwidthLimits(noLimit, noLimit)); + uniMap.put(portId, new BandwidthLimits(noLimit, noLimit, profileTosave)); } } public void setUniBandwidthLimits(Identifier45 uniIden) { String uniId = uniIden.getValue(); + setUniBandwidthLimits(uniId); + } + + private synchronized void setUniBandwidthLimits(String uniId) { if (!uniPortBandwidthLimits.containsKey(uniId)) { Log.debug("Uni {} doesn't have rate limits configured", uniId); return; @@ -139,11 +227,12 @@ public class UniQosManager { ConcurrentHashMap uniLimits) { Long sumOfRate = noLimit; Long sumOfBurst = noLimit; + String profileName = noProfile; Boolean hasNullRate = false; Boolean hasNullBurst = false; if (uniLimits == null || uniLimits.keySet() == null) { - return new BandwidthLimits(sumOfRate, sumOfBurst); + return new BandwidthLimits(sumOfRate, sumOfBurst, profileName); } for (BandwidthLimits v : uniLimits.values()) { @@ -156,7 +245,7 @@ public class UniQosManager { } sumOfRate = sumOfRate + v.maxKbps; sumOfBurst = sumOfBurst + v.maxBurstKb; - + profileName = v.profileName; } if (hasNullRate) { sumOfRate = noLimit; @@ -164,21 +253,21 @@ public class UniQosManager { } else if (hasNullBurst) { sumOfBurst = noLimit; } - return new BandwidthLimits(sumOfRate, sumOfBurst); + return new BandwidthLimits(sumOfRate, sumOfBurst, profileName); } private void setPortBandwidthLimits(String uniId, String logicalPortId, Long maxKbps, Long maxBurstKb) { - LOG.trace("Setting bandwidth limits {} {} on Port {}", maxKbps, maxBurstKb, logicalPortId); + Log.info("Setting bandwidth limits {} {} on Port {}", maxKbps, maxBurstKb, logicalPortId); BigInteger dpId = BigInteger.ZERO; - if(uniToDpn.containsKey(uniId)) { + if (uniToDpn.containsKey(uniId)) { dpId = uniToDpn.get(uniId); - } else { + } else { dpId = getDpnForInterface(odlInterfaceRpcService, logicalPortId); uniToDpn.put(uniId, dpId); } if (dpId.equals(BigInteger.ZERO)) { - LOG.error("DPN ID for interface {} not found", logicalPortId); + Log.error("DPN ID for interface {} not found", logicalPortId); return; } @@ -186,19 +275,19 @@ public class UniQosManager { Optional bridgeNode = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, bridgeRefEntry.getValue().firstIdentifierOf(Node.class), dataBroker); if (bridgeNode == null) { - LOG.error("Bridge ref for interface {} not found", logicalPortId); + Log.error("Bridge ref for interface {} not found", logicalPortId); return; } String physicalPort = getPhysicalPortForUni(dataBroker, uniId); if (physicalPort == null) { - LOG.error("Physical port for interface {} not found", logicalPortId); + Log.error("Physical port for interface {} not found", logicalPortId); return; } TerminationPoint tp = getTerminationPoint(bridgeNode.get(), physicalPort); if (tp == null) { - LOG.error("Termination point for port {} not found", physicalPort); + Log.error("Termination point for port {} not found", physicalPort); return; } @@ -238,10 +327,10 @@ public class UniQosManager { if (dpIdResult.isSuccessful()) { nodeId = dpIdResult.getResult().getDpid(); } else { - LOG.error("Could not retrieve DPN Id for interface {}", ifName); + Log.error("Could not retrieve DPN Id for interface {}", ifName); } } catch (NullPointerException | InterruptedException | ExecutionException e) { - LOG.error("Exception when getting dpn for interface {}", ifName, e); + Log.error("Exception when getting dpn for interface {}", ifName, e); } return nodeId; } @@ -253,7 +342,7 @@ public class UniQosManager { String parentInterfaceName = MefInterfaceUtils.getTrunkParentName(link); return parentInterfaceName.split(":")[1]; } catch (Exception e) { - LOG.error("Exception when getting physical port for Uni {}", uniId, e); + Log.error("Exception when getting physical port for Uni {}", uniId, e); } return nodeId; } @@ -288,13 +377,21 @@ public class UniQosManager { return bwProfileInstanceIdentifierBuilder.build(); } + private static InstanceIdentifier getBwFlowsInstanceIdentifier() { + InstanceIdentifier.InstanceIdentifierBuilder bwProfileInstanceIdentifierBuilder = InstanceIdentifier + .builder(MefGlobal.class).child(Profiles.class).child(IngressBwpFlows.class).child(BwpFlow.class); + return bwProfileInstanceIdentifierBuilder.build(); + } + private class BandwidthLimits { private final Long maxKbps; private final Long maxBurstKb; + private final String profileName; - public BandwidthLimits(Long maxKbps, Long maxBurstKb) { + public BandwidthLimits(Long maxKbps, Long maxBurstKb, String profileName) { this.maxKbps = replaceNull(maxKbps); this.maxBurstKb = replaceNull(maxBurstKb); + this.profileName = profileName; } public Long getMaxKbps() { @@ -305,6 +402,10 @@ public class UniQosManager { return maxBurstKb; } + public String getProfileName() { + return profileName; + } + private Long replaceNull(Long value) { return (value == null) ? Long.valueOf(0) : value; } @@ -342,4 +443,37 @@ public class UniQosManager { return UniQosManager.this; } } + + private static String replaceNull(Identifier45 value) { + return (value == null) ? noProfile : value.getValue(); + } + + @Override + public void close() throws Exception { + bwListenerRegistration.close(); + } + + @Override + public void add(DataTreeModification newDataObject) { + if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) { + Log.info("bw profile {} created", newDataObject.getRootNode().getIdentifier()); + updateProfile(newDataObject.getRootNode().getDataAfter().getBwProfile()); + } + } + + @Override + public void remove(DataTreeModification removedDataObject) { + if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) { + Log.info("bw profile {} deleted", removedDataObject.getRootNode().getIdentifier()); + deleteProfile(removedDataObject.getRootNode().getDataBefore().getBwProfile()); + } + } + + @Override + public void update(DataTreeModification modifiedDataObject) { + if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) { + Log.info("bw profile {} modified", modifiedDataObject.getRootNode().getIdentifier()); + updateProfile(modifiedDataObject.getRootNode().getDataAfter().getBwProfile()); + } + } } -- 2.36.6