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 com.google.common.base.Optional;
13 import jline.internal.Log;
15 import java.math.BigInteger;
16 import java.util.Iterator;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Future;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
24 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.MefGlobal;
25 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.mef.global.Profiles;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.mef.global.bwp.flows.group.BwpFlow;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.mef.global.bwp.flows.group.BwpFlowKey;
28 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.global.rev150526.mef.global.profiles.IngressBwpFlows;
29 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
30 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.opendaylight.yangtools.yang.common.RpcResult;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 public class UniQosManager {
54 private static final Logger LOG = LoggerFactory.getLogger(UniQosManager.class);
55 private OdlInterfaceRpcService odlInterfaceRpcService;
56 private DataBroker dataBroker;
57 private final Long noLimit = 0l;
59 // key in first map is uniId, key in second map is logical portId
60 private ConcurrentHashMap<String, ConcurrentHashMap<String, BandwidthLimits>> uniPortBandwidthLimits;
62 // map of current values per uni
63 private ConcurrentHashMap<String, BandwidthLimits> uniBandwidthLimits;
65 private ConcurrentHashMap<String, BigInteger> uniToDpn;
67 public UniQosManager(final DataBroker dataBroker, OdlInterfaceRpcService odlInterfaceRpcService) {
68 this.dataBroker = dataBroker;
69 this.odlInterfaceRpcService = odlInterfaceRpcService;
70 this.uniPortBandwidthLimits = new ConcurrentHashMap<>();
71 this.uniBandwidthLimits = new ConcurrentHashMap<>();
72 this.uniToDpn = new ConcurrentHashMap<>();
75 public void mapUniPortBandwidthLimits(String uniId, String portId, Long maxKbps, Long maxBurstKb) {
76 Log.info("Record rate limits for Uni {} port {} maxKbps {} maxBurstKb {}", uniId, portId, maxKbps, maxBurstKb);
77 uniPortBandwidthLimits.putIfAbsent(uniId, new ConcurrentHashMap<>());
78 ConcurrentHashMap<String, BandwidthLimits> uniMap = uniPortBandwidthLimits.get(uniId);
79 uniMap.put(portId, new BandwidthLimits(maxKbps, maxBurstKb));
82 public void mapUniPortBandwidthLimits(String uniId, String portId, Identifier45 bwProfile) {
83 Long maxKbps = noLimit;
84 Long maxBurstKb = noLimit;
85 if (bwProfile != null) {
87 Optional<BwpFlow> bwFlowOp = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
88 getBwFlowInstanceIdentifier(bwProfile));
89 if (!bwFlowOp.isPresent()) {
90 Log.trace("Can't read bw profile {} for Uni {}", bwProfile, uniId);
94 maxKbps = bwFlowOp.get().getCir().getValue();
95 // burst in bytes, ovs requires in Kb
96 maxBurstKb = bwFlowOp.get().getCbs().getValue() * 8 / 1024;
97 Log.info("Record rate limits for Uni {} Profile {}", uniId, bwProfile);
99 mapUniPortBandwidthLimits(uniId, portId, maxKbps, maxBurstKb);
102 public void unMapUniPortBandwidthLimits(String uniId, String portId) {
103 Log.debug("Delete rate limits for Uni {} port {}", uniId, portId);
104 ConcurrentHashMap<String, BandwidthLimits> uniMap = uniPortBandwidthLimits.get(uniId);
105 if (uniMap == null) {
106 Log.error("Trying to delete limits for non-exsting uni {}", uniId);
109 uniMap.remove(portId);
110 if (uniMap.isEmpty()) {
111 uniMap.put(portId, new BandwidthLimits(noLimit, noLimit));
115 public void setUniBandwidthLimits(Identifier45 uniIden) {
116 String uniId = uniIden.getValue();
117 if (!uniPortBandwidthLimits.containsKey(uniId)) {
118 Log.debug("Uni {} doesn't have rate limits configured", uniId);
121 Iterator<String> uniPorts = uniPortBandwidthLimits.get(uniId).keySet().iterator();
122 if (uniPorts == null || !uniPorts.hasNext()) {
123 Log.debug("Uni {} doesn't have rate limits configured", uniId);
126 String logicalPort = uniPorts.next();
128 BandwidthLimits newLimits = recalculateLimitsForUni(uniId, uniPortBandwidthLimits.get(uniId));
129 if (newLimits.equals(uniBandwidthLimits.get(uniId))) {
130 Log.debug("Uni {} rate limits has not changed", uniId);
134 setPortBandwidthLimits(uniId, logicalPort, newLimits.getMaxKbps(), newLimits.getMaxBurstKb());
135 uniBandwidthLimits.put(uniId, newLimits);
138 private BandwidthLimits recalculateLimitsForUni(String uniId,
139 ConcurrentHashMap<String, BandwidthLimits> uniLimits) {
140 Long sumOfRate = noLimit;
141 Long sumOfBurst = noLimit;
142 Boolean hasNullRate = false;
143 Boolean hasNullBurst = false;
145 if (uniLimits == null || uniLimits.keySet() == null) {
146 return new BandwidthLimits(sumOfRate, sumOfBurst);
149 for (BandwidthLimits v : uniLimits.values()) {
150 if (v.maxKbps == null) {
154 if (v.maxBurstKb == null) {
157 sumOfRate = sumOfRate + v.maxKbps;
158 sumOfBurst = sumOfBurst + v.maxBurstKb;
163 sumOfBurst = noLimit;
164 } else if (hasNullBurst) {
165 sumOfBurst = noLimit;
167 return new BandwidthLimits(sumOfRate, sumOfBurst);
170 private void setPortBandwidthLimits(String uniId, String logicalPortId, Long maxKbps, Long maxBurstKb) {
171 LOG.trace("Setting bandwidth limits {} {} on Port {}", maxKbps, maxBurstKb, logicalPortId);
173 BigInteger dpId = BigInteger.ZERO;
174 if(uniToDpn.containsKey(uniId)) {
175 dpId = uniToDpn.get(uniId);
177 dpId = getDpnForInterface(odlInterfaceRpcService, logicalPortId);
178 uniToDpn.put(uniId, dpId);
180 if (dpId.equals(BigInteger.ZERO)) {
181 LOG.error("DPN ID for interface {} not found", logicalPortId);
185 OvsdbBridgeRef bridgeRefEntry = getBridgeRefEntryFromOperDS(dpId, dataBroker);
186 Optional<Node> bridgeNode = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL,
187 bridgeRefEntry.getValue().firstIdentifierOf(Node.class), dataBroker);
188 if (bridgeNode == null) {
189 LOG.error("Bridge ref for interface {} not found", logicalPortId);
193 String physicalPort = getPhysicalPortForUni(dataBroker, uniId);
194 if (physicalPort == null) {
195 LOG.error("Physical port for interface {} not found", logicalPortId);
199 TerminationPoint tp = getTerminationPoint(bridgeNode.get(), physicalPort);
201 LOG.error("Termination point for port {} not found", physicalPort);
205 OvsdbTerminationPointAugmentation ovsdbTp = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
206 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
207 tpAugmentationBuilder.setName(ovsdbTp.getName());
208 tpAugmentationBuilder.setIngressPolicingRate(maxKbps);
209 tpAugmentationBuilder.setIngressPolicingBurst(maxBurstKb);
211 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
212 tpBuilder.setKey(tp.getKey());
213 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
214 MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
215 InstanceIdentifier.create(NetworkTopology.class)
216 .child(Topology.class, new TopologyKey(SouthboundUtils.OVSDB_TOPOLOGY_ID))
217 .child(Node.class, bridgeNode.get().getKey())
218 .child(TerminationPoint.class, new TerminationPointKey(tp.getKey())),
222 private static TerminationPoint getTerminationPoint(Node bridgeNode, String portName) {
223 for (TerminationPoint tp : bridgeNode.getTerminationPoint()) {
224 String tpIdStr = tp.getTpId().getValue();
225 if (tpIdStr != null && tpIdStr.equals(portName))
231 private static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
232 BigInteger nodeId = BigInteger.ZERO;
234 GetDpidFromInterfaceInput dpIdInput = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
235 Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput = interfaceManagerRpcService
236 .getDpidFromInterface(dpIdInput);
237 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
238 if (dpIdResult.isSuccessful()) {
239 nodeId = dpIdResult.getResult().getDpid();
241 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
243 } catch (NullPointerException | InterruptedException | ExecutionException e) {
244 LOG.error("Exception when getting dpn for interface {}", ifName, e);
249 private static String getPhysicalPortForUni(DataBroker dataBroker, String uniId) {
250 String nodeId = null;
252 Link link = MefInterfaceUtils.getLink(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
253 String parentInterfaceName = MefInterfaceUtils.getTrunkParentName(link);
254 return parentInterfaceName.split(":")[1];
255 } catch (Exception e) {
256 LOG.error("Exception when getting physical port for Uni {}", uniId, e);
261 private static BridgeRefEntry getBridgeRefEntryFromOperDS(InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid,
262 DataBroker dataBroker) {
263 Optional<BridgeRefEntry> bridgeRefEntryOptional = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
265 if (!bridgeRefEntryOptional.isPresent()) {
268 return bridgeRefEntryOptional.get();
271 private static OvsdbBridgeRef getBridgeRefEntryFromOperDS(BigInteger dpId, DataBroker dataBroker) {
272 BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpId);
273 InstanceIdentifier<BridgeRefEntry> bridgeRefEntryIid = getBridgeRefEntryIdentifier(bridgeRefEntryKey);
274 BridgeRefEntry bridgeRefEntry = getBridgeRefEntryFromOperDS(bridgeRefEntryIid, dataBroker);
275 return (bridgeRefEntry != null) ? bridgeRefEntry.getBridgeReference() : null;
278 private static InstanceIdentifier<BridgeRefEntry> getBridgeRefEntryIdentifier(BridgeRefEntryKey bridgeRefEntryKey) {
279 InstanceIdentifier.InstanceIdentifierBuilder<BridgeRefEntry> bridgeRefEntryInstanceIdentifierBuilder = InstanceIdentifier
280 .builder(BridgeRefInfo.class).child(BridgeRefEntry.class, bridgeRefEntryKey);
281 return bridgeRefEntryInstanceIdentifierBuilder.build();
284 private static InstanceIdentifier<BwpFlow> getBwFlowInstanceIdentifier(Identifier45 bwProfile) {
285 InstanceIdentifier.InstanceIdentifierBuilder<BwpFlow> bwProfileInstanceIdentifierBuilder = InstanceIdentifier
286 .builder(MefGlobal.class).child(Profiles.class).child(IngressBwpFlows.class)
287 .child(BwpFlow.class, new BwpFlowKey(bwProfile));
288 return bwProfileInstanceIdentifierBuilder.build();
291 private class BandwidthLimits {
292 private final Long maxKbps;
293 private final Long maxBurstKb;
295 public BandwidthLimits(Long maxKbps, Long maxBurstKb) {
296 this.maxKbps = replaceNull(maxKbps);
297 this.maxBurstKb = replaceNull(maxBurstKb);
300 public Long getMaxKbps() {
304 public Long getMaxBurstKb() {
308 private Long replaceNull(Long value) {
309 return (value == null) ? Long.valueOf(0) : value;
313 public boolean equals(Object obj) {
318 if (getClass() != obj.getClass())
320 BandwidthLimits other = (BandwidthLimits) obj;
321 if (!getOuterType().equals(other.getOuterType()))
323 if (maxBurstKb == null) {
324 if (other.maxBurstKb != null)
326 } else if (!maxBurstKb.equals(other.maxBurstKb))
328 if (maxKbps == null) {
329 if (other.maxKbps != null)
331 } else if (!maxKbps.equals(other.maxKbps))
337 public String toString() {
338 return "BandwidthLimitsBandwidthLimitsalues [maxKbps=" + maxKbps + ", maxBurstKb=" + maxBurstKb + "]";
341 private UniQosManager getOuterType() {
342 return UniQosManager.this;