import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.qosalert.config.rev170301.QosalertConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.qosalert.config.rev170301.QosalertConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
private int pollInterval;
private final QosalertConfig defaultConfig;
private boolean statsPollThreadStart;
- private final DataBroker dataBroker;
- private final OpendaylightDirectStatisticsService odlDirectStatisticsService;
+ private static DataBroker dataBroker;
+ private static OpendaylightDirectStatisticsService odlDirectStatisticsService;
+ private static INeutronVpnManager neutronVpnManager;
private Thread thread;
+ private static OdlInterfaceRpcService odlInterfaceRpcService;
+ private static ConcurrentHashMap<BigInteger, ConcurrentHashMap<String, QosAlertPortData>>
+ qosAlertDpnPortNumberMap = new ConcurrentHashMap<>();
private static final Logger LOG = LoggerFactory.getLogger(QosAlertManager.class);
private static final FutureCallback<Void> DEFAULT_FUTURE_CALLBACK;
}
@Inject
- public QosAlertManager(final DataBroker dataBroker, OpendaylightDirectStatisticsService odlDirectStatisticsService,
- QosalertConfig defaultConfig) {
+ public QosAlertManager(final DataBroker dataBroker,
+ final OpendaylightDirectStatisticsService odlDirectStatisticsService,
+ final QosalertConfig defaultConfig,
+ final OdlInterfaceRpcService odlInterfaceRpcService,
+ final INeutronVpnManager neutronVpnManager) {
+
LOG.info("{} created", getClass().getSimpleName());
this.dataBroker = dataBroker;
this.odlDirectStatisticsService = odlDirectStatisticsService;
+ this.odlInterfaceRpcService = odlInterfaceRpcService;
+ this.neutronVpnManager = neutronVpnManager;
this.defaultConfig = defaultConfig;
thread = null;
LOG.info("QosAlert default config poll alertEnabled:{} threshold:{} pollInterval:{}",
writeConfigDataStore();
}
+ public static void addToQosAlertCache(Port port) {
+ LOG.trace("Adding port {} in cache", port.getUuid());
+
+ BigInteger dpnId = QosNeutronUtils.getDpnForInterface(odlInterfaceRpcService, port.getUuid().getValue());
+
+ if (dpnId.equals(BigInteger.ZERO)) {
+ LOG.debug("DPN ID for port {} not found", port.getUuid());
+ return;
+ }
+
+ String portNumber = QosNeutronUtils.getPortNumberForInterface(odlInterfaceRpcService,
+ port.getUuid().getValue());
+
+ if (qosAlertDpnPortNumberMap.containsKey(dpnId)) {
+ LOG.trace("Adding port {} port number {} in DPN {}", port.getUuid(), portNumber, dpnId);
+ qosAlertDpnPortNumberMap.get(dpnId).put(portNumber, new QosAlertPortData(port));
+ } else {
+ LOG.trace("Adding DPN ID {} with port {} port number {}", dpnId, port.getUuid(), portNumber);
+ ConcurrentHashMap<String, QosAlertPortData> portDataMap = new ConcurrentHashMap<>();
+ portDataMap.put(portNumber, new QosAlertPortData(port));
+ qosAlertDpnPortNumberMap.put(dpnId, portDataMap);
+ }
+ }
+
+ public static void addToQosAlertCache(Network network) {
+ LOG.trace("Adding network {} in cache", network.getUuid());
+
+ List<Uuid> subnetIds = QosNeutronUtils.getSubnetIdsFromNetworkId(dataBroker, network.getUuid());
+
+ if (subnetIds != null) {
+ for (Uuid subnetId : subnetIds) {
+ List<Uuid> portIds = QosNeutronUtils.getPortIdsFromSubnetId(dataBroker, subnetId);
+ if (portIds != null) {
+ for (Uuid portId : portIds) {
+ Port port = neutronVpnManager.getNeutronPort(portId);
+ if (port != null) {
+ if (!QosNeutronUtils.portHasQosPolicy(neutronVpnManager, port)) {
+ LOG.trace("Adding network {} port {} in cache", network.getUuid(), port.getUuid());
+ addToQosAlertCache(port);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static void removeFromQosAlertCache(Port port) {
+ LOG.trace("Removing port {} from cache", port.getUuid());
+
+ BigInteger dpnId = QosNeutronUtils.getDpnForInterface(odlInterfaceRpcService, port.getUuid().getValue());
+
+ if (dpnId.equals(BigInteger.ZERO)) {
+ LOG.debug("DPN ID for port {} not found", port.getUuid());
+ return;
+ }
+
+ String portNumber = QosNeutronUtils.getPortNumberForInterface(odlInterfaceRpcService,
+ port.getUuid().getValue());
+
+ if (qosAlertDpnPortNumberMap.containsKey(dpnId)
+ && qosAlertDpnPortNumberMap.get(dpnId).containsKey(portNumber)) {
+ qosAlertDpnPortNumberMap.get(dpnId).remove(portNumber);
+ LOG.trace("Removed DPN {} port {} port number {} from cache", dpnId, port.getUuid(), portNumber);
+ if (qosAlertDpnPortNumberMap.get(dpnId).isEmpty()) {
+ LOG.trace("DPN {} empty. Removing from cache", dpnId);
+ qosAlertDpnPortNumberMap.remove(dpnId);
+ }
+ } else {
+ LOG.trace("DPN {} port {} port number {} not found in cache", dpnId, port.getUuid(), portNumber);
+ }
+
+ }
+
+ public static void removeFromQosAlertCache(NodeConnectorId nodeConnectorId) {
+ LOG.trace("Removing node connector {} from cache", nodeConnectorId.getValue());
+
+ long nodeId = MDSALUtil.getDpnIdFromPortName(nodeConnectorId);
+
+ if (nodeId == -1) {
+ LOG.debug("Node ID for node connector {} not found", nodeConnectorId.getValue());
+ return;
+ }
+
+ BigInteger dpnId = new BigInteger(String.valueOf(nodeId));
+
+ long portId = MDSALUtil.getOfPortNumberFromPortName(nodeConnectorId);
+
+ String portNumber = String.valueOf(portId);
+
+ if (qosAlertDpnPortNumberMap.containsKey(dpnId)
+ && qosAlertDpnPortNumberMap.get(dpnId).containsKey(portNumber)) {
+ qosAlertDpnPortNumberMap.get(dpnId).remove(portNumber);
+ LOG.trace("Removed DPN {} port number {} from cache", dpnId, portNumber);
+ } else {
+ LOG.trace("DPN {} port number {} not found in cache", dpnId, portNumber);
+ }
+
+ }
+
+ public static void removeFromQosAlertCache(Network network) {
+ LOG.trace("Removing network {} from cache", network.getUuid());
+
+ List<Uuid> subnetIds = QosNeutronUtils.getSubnetIdsFromNetworkId(dataBroker, network.getUuid());
+
+ if (subnetIds != null) {
+ for (Uuid subnetId : subnetIds) {
+ List<Uuid> portIds = QosNeutronUtils.getPortIdsFromSubnetId(dataBroker, subnetId);
+ if (portIds != null) {
+ for (Uuid portId : portIds) {
+ Port port = neutronVpnManager.getNeutronPort(portId);
+ if (port != null) {
+ if (!QosNeutronUtils.portHasQosPolicy(neutronVpnManager, port)) {
+ LOG.trace("Removing network {} port {} from cache", network.getUuid(), port.getUuid());
+ removeFromQosAlertCache(port);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
private static <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
InstanceIdentifier<T> path, T data, DataBroker broker,
FutureCallback<Void> callback) {
}
private void pollDirectStatisticsForAllNodes() {
- LOG.debug("Polling direct statistics from all nodes");
- // TODO: Add all polling logic here
+ LOG.trace("Polling direct statistics from nodes");
+ // TODO: Add all polling logic here. At this moment just print the port cache
+ for (BigInteger dpn : qosAlertDpnPortNumberMap.keySet()) {
+ LOG.trace("Polling DPN ID {}", dpn);
+ for (String portNumber : qosAlertDpnPortNumberMap.get(dpn).keySet()) {
+ LOG.trace("DPN ID {} PortNumber {} Port uuid {}",
+ dpn, portNumber, qosAlertDpnPortNumberMap.get(dpn).get(portNumber).port.getUuid());
+ }
+ }
}
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.qosservice;
+
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+
+
+public class QosAlertPortData {
+ public Port port;
+
+ public QosAlertPortData(Port port) {
+ this.port = port;
+ }
+}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosNetworkExtension;
}
}
}
+ if (QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, port)) {
+ QosAlertManager.addToQosAlertCache(port);
+ }
});
}
} catch (Exception e) {
@Override
protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ if (!Tunnel.class.equals(intrf.getType())) {
+ LOG.trace("Qos Service : Received interface {} PORT DOWN event ", intrf.getName());
+ String lowerLayerIf = intrf.getLowerLayerIf().get(0);
+ LOG.trace("lowerLayerIf {}", lowerLayerIf);
+ QosAlertManager.removeFromQosAlertCache(new NodeConnectorId(lowerLayerIf));
+ }
}
@Override
@Override
protected void remove(InstanceIdentifier<Network> instanceIdentifier, Network network) {
+ if (QosNeutronUtils.hasBandwidthLimitRule(network)) {
+ QosAlertManager.removeFromQosAlertCache(network);
+ }
}
@Override
QosNeutronUtils.addToQosNetworksCache(updateQos.getQosPolicyId(), update);
QosNeutronUtils.handleNeutronNetworkQosUpdate(dataBroker, odlInterfaceRpcService,
neutronVpnManager, mdsalUtils, update, updateQos.getQosPolicyId());
+ if (QosNeutronUtils.hasBandwidthLimitRule(update)) {
+ QosAlertManager.addToQosAlertCache(update);
+ }
} else if (originalQos != null && updateQos != null
&& !originalQos.getQosPolicyId().equals(updateQos.getQosPolicyId())) {
+
// qosservice policy update
+
QosNeutronUtils.removeFromQosNetworksCache(originalQos.getQosPolicyId(), original);
QosNeutronUtils.addToQosNetworksCache(updateQos.getQosPolicyId(), update);
QosNeutronUtils.handleNeutronNetworkQosUpdate(dataBroker, odlInterfaceRpcService,
neutronVpnManager, mdsalUtils, update, updateQos.getQosPolicyId());
+
+ if (QosNeutronUtils.hasBandwidthLimitRule(original)
+ && !QosNeutronUtils.hasBandwidthLimitRule(update)) {
+ QosAlertManager.removeFromQosAlertCache(original);
+ } else if (!QosNeutronUtils.hasBandwidthLimitRule(original)
+ && QosNeutronUtils.hasBandwidthLimitRule(update)) {
+ QosAlertManager.addToQosAlertCache(update);
+ }
+
} else if (originalQos != null && updateQos == null) {
// qosservice policy delete
+ if (QosNeutronUtils.hasBandwidthLimitRule(original)) {
+ QosAlertManager.removeFromQosAlertCache(original);
+ }
QosNeutronUtils.handleNeutronNetworkQosRemove(dataBroker, odlInterfaceRpcService,
neutronVpnManager, mdsalUtils, original, originalQos.getQosPolicyId());
QosNeutronUtils.removeFromQosNetworksCache(originalQos.getQosPolicyId(), original);
QosNeutronUtils.addToQosNetworksCache(networkQos.getQosPolicyId(), network);
QosNeutronUtils.handleNeutronNetworkQosUpdate(dataBroker, odlInterfaceRpcService,
neutronVpnManager, mdsalUtils, network, networkQos.getQosPolicyId());
+ if (QosNeutronUtils.hasBandwidthLimitRule(network)) {
+ QosAlertManager.addToQosAlertCache(network);
+ }
+
}
}
}
@Override
protected void add(InstanceIdentifier<Port> instanceIdentifier, Port port) {
- //do nothing
+ if (QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, port)) {
+ QosAlertManager.addToQosAlertCache(port);
+ }
}
@Override
protected void remove(InstanceIdentifier<Port> instanceIdentifier, Port port) {
+ if (QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, port)) {
+ QosAlertManager.removeFromQosAlertCache(port);
+ }
//Remove DSCP Flow when the port is removed
//Qos Policy Deletion
QosPortExtension removeQos = port.getAugmentation(QosPortExtension.class);
update, updateQos.getQosPolicyId());
} else if (originalQos != null && updateQos != null
&& !originalQos.getQosPolicyId().equals(updateQos.getQosPolicyId())) {
+
// qosservice policy update
QosNeutronUtils.removeFromQosPortsCache(originalQos.getQosPolicyId(), original);
QosNeutronUtils.addToQosPortsCache(updateQos.getQosPolicyId(), update);
mdsalUtils, original, originalQos.getQosPolicyId());
QosNeutronUtils.removeFromQosPortsCache(originalQos.getQosPolicyId(), original);
}
+
+ if (QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, original)
+ && !QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, update)) {
+ QosAlertManager.removeFromQosAlertCache(original);
+ } else if (!QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, original)
+ && QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager,update)) {
+ QosAlertManager.addToQosAlertCache(update);
+ }
}
}
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
qosServiceConfiguredPorts.remove(port.getUuid());
}
- private static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+ public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
BigInteger nodeId = BigInteger.ZERO;
try {
GetDpidFromInterfaceInput
return new StringBuffer().append(tableId).append(dpId).append(lportTag).toString();
}
+ public static String getPortNumberForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+ GetPortFromInterfaceInput portNumberInput = new GetPortFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetPortFromInterfaceOutput>> portNumberOutput =
+ interfaceManagerRpcService.getPortFromInterface(portNumberInput);
+ try {
+ RpcResult<GetPortFromInterfaceOutput> portResult = portNumberOutput.get();
+ if (portResult.isSuccessful()) {
+ return portResult.getResult().getPortno().toString();
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting port for interface", e);
+ }
+ return null;
+ }
+
+ public static boolean portHasQosPolicy(INeutronVpnManager neutronVpnManager, Port port) {
+ Uuid qosUuid = null;
+ boolean isQosPolicy = false;
+
+ LOG.trace("checking qos policy for port: {}", port.getUuid());
+
+ if (port.getAugmentation(QosPortExtension.class) != null) {
+ qosUuid = port.getAugmentation(QosPortExtension.class).getQosPolicyId();
+ }
+ if (qosUuid != null) {
+ isQosPolicy = true;
+ }
+
+ LOG.trace("portHasQosPolicy for port: {} return value {}", port.getUuid(), isQosPolicy);
+ return (isQosPolicy);
+ }
+
+ public static boolean hasBandwidthLimitRule(INeutronVpnManager neutronVpnManager, Port port) {
+ Uuid qosUuid = null;
+ boolean bwLimitRule = false;
+
+ LOG.trace("checking bandwidth limit rule for port: {}", port.getUuid());
+
+ if (port.getAugmentation(QosPortExtension.class) != null) {
+ qosUuid = port.getAugmentation(QosPortExtension.class).getQosPolicyId();
+ } else {
+ Network network = neutronVpnManager.getNeutronNetwork(port.getNetworkId());
+
+ if (network.getAugmentation(QosNetworkExtension.class) != null) {
+ qosUuid = network.getAugmentation(QosNetworkExtension.class).getQosPolicyId();
+ }
+ }
+
+ if (qosUuid != null) {
+ QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
+ if (qosPolicy != null && qosPolicy.getBandwidthLimitRules() != null
+ && !qosPolicy.getBandwidthLimitRules().isEmpty()) {
+ bwLimitRule = true;
+ }
+ }
+
+ LOG.trace("Bandwidth limit rule for port: {} return value {}", port.getUuid(), bwLimitRule);
+ return (bwLimitRule);
+ }
+
+ public static boolean hasBandwidthLimitRule(Network network) {
+ boolean bwLimitRule = false;
+
+ LOG.trace("checking bandwidth limit rule for network: {}", network.getUuid());
+
+ if (network.getAugmentation(QosNetworkExtension.class) != null) {
+ Uuid qosUuid = network.getAugmentation(QosNetworkExtension.class).getQosPolicyId();
+
+ if (qosUuid != null) {
+ QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
+ if (qosPolicy != null && qosPolicy.getBandwidthLimitRules() != null
+ && !qosPolicy.getBandwidthLimitRules().isEmpty()) {
+ bwLimitRule = true;
+ }
+ }
+ }
+
+ LOG.trace("Bandwidth limit rule for network: {} return value {}", network.getUuid(), bwLimitRule);
+ return (bwLimitRule);
+ }
+
+
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
for (Network network : QosNeutronUtils.qosNetworksMap.get(qosUuid).values()) {
QosNeutronUtils.handleNeutronNetworkQosUpdate(dataBroker, odlInterfaceRpcService,
neutronVpnManager, mdsalUtils, network, qosUuid);
+ QosAlertManager.addToQosAlertCache(network);
}
}
if (QosNeutronUtils.qosPortsMap.get(qosUuid) != null
&& !QosNeutronUtils.qosPortsMap.get(qosUuid).isEmpty()) {
for (Port port : QosNeutronUtils.qosPortsMap.get(qosUuid).values()) {
+ QosAlertManager.addToQosAlertCache(port);
final DataStoreJobCoordinator portDataStoreCoordinator =
DataStoreJobCoordinator.getInstance();
portDataStoreCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
if (QosNeutronUtils.qosNetworksMap.get(qosUuid) != null
&& !QosNeutronUtils.qosNetworksMap.get(qosUuid).isEmpty()) {
for (Network network : QosNeutronUtils.qosNetworksMap.get(qosUuid).values()) {
+ QosAlertManager.removeFromQosAlertCache(network);
QosNeutronUtils.handleNeutronNetworkQosBwRuleRemove(dataBroker, odlInterfaceRpcService,
neutronVpnManager, network, zeroBwLimitRule);
}
if (QosNeutronUtils.qosPortsMap.get(qosUuid) != null
&& !QosNeutronUtils.qosPortsMap.get(qosUuid).isEmpty()) {
for (Port port : QosNeutronUtils.qosPortsMap.get(qosUuid).values()) {
+ QosAlertManager.removeFromQosAlertCache(port);
final DataStoreJobCoordinator portDataStoreCoordinator =
DataStoreJobCoordinator.getInstance();
portDataStoreCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {