for (Uuid subnetId : subnetIds) {
List<Uuid> portIds = qosNeutronUtils.getPortIdsFromSubnetId(subnetId);
for (Uuid portId : portIds) {
- Port port = neutronVpnManager.getNeutronPort(portId);
+ Port port = qosNeutronUtils.getNeutronPort(portId);
if (port != null && !qosNeutronUtils.portHasQosPolicy(port)) {
LOG.trace("Adding network {} port {} in cache", network.getUuid(), port.getUuid());
addToQosAlertCache(port);
for (Uuid subnetId : subnetIds) {
List<Uuid> portIds = qosNeutronUtils.getPortIdsFromSubnetId(subnetId);
for (Uuid portId : portIds) {
- Port port = neutronVpnManager.getNeutronPort(portId);
+ Port port = qosNeutronUtils.getNeutronPort(portId);
if (port != null && !qosNeutronUtils.portHasQosPolicy(port)) {
LOG.trace("Removing network {} port {} from cache", network.getUuid(), port.getUuid());
removeFromQosAlertCache(port);
if (L2vlan.class.equals(intrf.getType())) {
final String interfaceName = intrf.getName();
getNeutronPort(interfaceName).ifPresent(port -> {
- Network network = neutronVpnManager.getNeutronNetwork(port.getNetworkId());
+ Network network = qosNeutronUtils.getNeutronNetwork(port.getNetworkId());
LOG.trace("Qos Service : Received interface {} PORT UP event ", interfaceName);
if (port.getAugmentation(QosPortExtension.class) != null) {
Uuid portQosUuid = port.getAugmentation(QosPortExtension.class).getQosPolicyId();
if (portQosUuid != null) {
qosNeutronUtils.addToQosPortsCache(portQosUuid, port);
- qosNeutronUtils.handleNeutronPortQosAdd(port, portQosUuid);
+ qosNeutronUtils.handleQosInterfaceAdd(port, portQosUuid);
}
-
} else {
if (network.getAugmentation(QosNetworkExtension.class) != null) {
Uuid networkQosUuid = network.getAugmentation(QosNetworkExtension.class).getQosPolicyId();
if (networkQosUuid != null) {
- qosNeutronUtils.handleNeutronPortQosAdd(port, networkQosUuid);
+ qosNeutronUtils.handleQosInterfaceAdd(port, networkQosUuid);
}
}
}
private java.util.Optional<Port> getNeutronPort(String portName) {
return uuidUtil.newUuidIfValidPattern(portName)
.toJavaUtil()
- .map(neutronVpnManager::getNeutronPort);
+ .map(qosNeutronUtils::getNeutronPort);
}
private Optional<Port> getNeutronPortForRemove(Interface intrf) {
final String portName = intrf.getName();
Optional<Uuid> uuid = uuidUtil.newUuidIfValidPattern(portName);
if (uuid.isPresent()) {
- Port port = neutronVpnManager.getNeutronPort(portName);
+ Port port = qosNeutronUtils.getNeutronPort(portName);
if (port != null) {
- return Optional.fromJavaUtil(uuid.toJavaUtil().map(neutronVpnManager::getNeutronPort));
+ return Optional.fromJavaUtil(uuid.toJavaUtil().map(qosNeutronUtils::getNeutronPort));
}
LOG.trace("Qos Service : interface {} clearing stale flow entries if any", portName);
qosNeutronUtils.removeStaleFlowEntry(intrf);
qosNeutronUtils.handleNeutronPortRemove(port, removeQos.getQosPolicyId(), intrf);
qosNeutronUtils.removeFromQosPortsCache(removeQos.getQosPolicyId(), port);
} else {
- Network network = neutronVpnManager.getNeutronNetwork(port.getNetworkId());
+ Network network = qosNeutronUtils.getNeutronNetwork(port.getNetworkId());
if (network != null && network.getAugmentation(QosNetworkExtension.class) != null) {
Uuid networkQosUuid = network.getAugmentation(QosNetworkExtension.class).getQosPolicyId();
if (networkQosUuid != null) {
@Override
protected void remove(InstanceIdentifier<Network> instanceIdentifier, Network network) {
+ qosNeutronUtils.removeFromNetworkCache(network);
if (qosNeutronUtils.hasBandwidthLimitRule(network)) {
qosAlertManager.removeFromQosAlertCache(network);
}
@Override
protected void update(InstanceIdentifier<Network> instanceIdentifier, Network original, Network update) {
+ qosNeutronUtils.addToNetworkCache(update);
+
QosNetworkExtension updateQos = update.getAugmentation(QosNetworkExtension.class);
QosNetworkExtension originalQos = original.getAugmentation(QosNetworkExtension.class);
if (originalQos == null && updateQos != null) {
@Override
protected void add(InstanceIdentifier<Network> instanceIdentifier, Network network) {
+ qosNeutronUtils.addToNetworkCache(network);
+
QosNetworkExtension networkQos = network.getAugmentation(QosNetworkExtension.class);
if (networkQos != null) {
qosNeutronUtils.addToQosNetworksCache(networkQos.getQosPolicyId(), network);
@Override
protected void add(InstanceIdentifier<Port> instanceIdentifier, Port port) {
+ qosNeutronUtils.addToPortCache(port);
if (qosNeutronUtils.hasBandwidthLimitRule(port)) {
qosAlertManager.addToQosAlertCache(port);
}
@Override
protected void remove(InstanceIdentifier<Port> instanceIdentifier, Port port) {
+ qosNeutronUtils.removeFromPortCache(port);
if (qosNeutronUtils.hasBandwidthLimitRule(port)) {
qosAlertManager.removeFromQosAlertCache(port);
}
@Override
protected void update(InstanceIdentifier<Port> instanceIdentifier, Port original, Port update) {
+ qosNeutronUtils.addToPortCache(update);
// check for QoS updates
QosPortExtension updateQos = update.getAugmentation(QosPortExtension.class);
QosPortExtension originalQos = original.getAugmentation(QosPortExtension.class);
private final ConcurrentMap<Uuid, ConcurrentMap<Uuid, Port>> qosPortsMap = new ConcurrentHashMap<>();
private final ConcurrentMap<Uuid, ConcurrentMap<Uuid, Network>> qosNetworksMap = new ConcurrentHashMap<>();
private final CopyOnWriteArraySet<Uuid> qosServiceConfiguredPorts = new CopyOnWriteArraySet<>();
+ private final ConcurrentHashMap<Uuid, Port> neutronPortMap = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<Uuid, Network> neutronNetworkMap = new ConcurrentHashMap<>();
private final QosEosHandler qosEosHandler;
private final INeutronVpnManager neutronVpnManager;
})));
}
+ public void handleQosInterfaceAdd(Port port, Uuid qosUuid) {
+ LOG.trace("Handling Port add and QoS associated: port: {} qos: {}", port.getUuid(), qosUuid);
+
+ QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
+
+ jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () ->
+ Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ // handle DSCP Mark Rules update
+ if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
+ && !qosPolicy.getDscpmarkingRules().isEmpty()) {
+ setPortDscpMarking(port, qosPolicy.getDscpmarkingRules().get(0));
+ }
+ })));
+ }
+
public void handleNeutronPortQosUpdate(Port port, Uuid qosUuidNew, Uuid qosUuidOld) {
LOG.trace("Handling Port QoS update: port: {} qosservice: {}", port.getUuid(), qosUuidNew);
for (Uuid subnetId : subnetIds) {
List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
for (Uuid portId : portIds) {
- Port port = neutronVpnManager.getNeutronPort(portId);
+ Port port = getNeutronPort(portId);
if (port != null && (port.getAugmentation(QosPortExtension.class) == null
|| port.getAugmentation(QosPortExtension.class).getQosPolicyId() == null)) {
jobCoordinator.enqueueJob("QosPort-" + portId.getValue(),
for (Uuid subnetId : subnetIds) {
List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
for (Uuid portId : portIds) {
- Port port = neutronVpnManager.getNeutronPort(portId);
+ Port port = getNeutronPort(portId);
if (port != null && (port.getAugmentation(QosPortExtension.class) == null
|| port.getAugmentation(QosPortExtension.class).getQosPolicyId() == null)) {
jobCoordinator.enqueueJob("QosPort-" + portId.getValue(),
for (Uuid subnetId: subnetIds) {
List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
for (Uuid portId : portIds) {
- Port port = neutronVpnManager.getNeutronPort(portId);
+ Port port = getNeutronPort(portId);
if (port != null && (port.getAugmentation(QosPortExtension.class) == null
|| port.getAugmentation(QosPortExtension.class).getQosPolicyId() == null)) {
jobCoordinator.enqueueJob("QosPort-" + portId.getValue(), () -> Collections.singletonList(
for (Uuid subnetId: subnetIds) {
List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
for (Uuid portId : portIds) {
- Port port = neutronVpnManager.getNeutronPort(portId);
+ Port port = getNeutronPort(portId);
if (port != null && (port.getAugmentation(QosPortExtension.class) == null
|| port.getAugmentation(QosPortExtension.class).getQosPolicyId() == null)) {
jobCoordinator.enqueueJob("QosPort-" + portId.getValue(), () -> {
return qosPolicy;
}
+ public void addToPortCache(Port port) {
+ neutronPortMap.put(port.getUuid(), port);
+ }
+
+ public void removeFromPortCache(Port port) {
+ neutronPortMap.remove(port.getUuid());
+ }
+
+ public Port getNeutronPort(Uuid portUuid) {
+ return neutronPortMap.get(portUuid);
+ }
+
+ public Port getNeutronPort(String portName) {
+ return getNeutronPort(new Uuid(portName));
+ }
+
+ public void addToNetworkCache(Network network) {
+ neutronNetworkMap.put(network.getUuid(), network);
+ }
+
+ public void removeFromNetworkCache(Network network) {
+ neutronNetworkMap.remove(network.getUuid());
+ }
+
+ public Network getNeutronNetwork(Uuid networkUuid) {
+ return neutronNetworkMap.get(networkUuid);
+ }
}
--- /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 java.util.Collections;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
+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.rev160613.qos.attributes.qos.policies.QosPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRules;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class QosTerminationPointListener extends
+ AsyncClusteredDataTreeChangeListenerBase<OvsdbTerminationPointAugmentation, QosTerminationPointListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(QosTerminationPointListener.class);
+ private static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
+ private final DataBroker dataBroker;
+ private final QosNeutronUtils qosNeutronUtils;
+ private final QosEosHandler qosEosHandler;
+ private final ManagedNewTransactionRunner txRunner;
+ private final JobCoordinator jobCoordinator;
+
+ @Inject
+ public QosTerminationPointListener(final DataBroker dataBroker,
+ final QosNeutronUtils qosNeutronUtils,
+ final QosEosHandler qosEosHandler,
+ final JobCoordinator jobCoordinator) {
+ super(OvsdbTerminationPointAugmentation.class, QosTerminationPointListener.class);
+ this.dataBroker = dataBroker;
+ this.qosNeutronUtils = qosNeutronUtils;
+ this.qosEosHandler = qosEosHandler;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+ this.jobCoordinator = jobCoordinator;
+ }
+
+ @PostConstruct
+ public void init() {
+ registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+ }
+
+ @Override
+ protected InstanceIdentifier<OvsdbTerminationPointAugmentation> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(SouthboundUtils.OVSDB_TOPOLOGY_ID))
+ .child(Node.class).child(TerminationPoint.class)
+ .augmentation(OvsdbTerminationPointAugmentation.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<OvsdbTerminationPointAugmentation> instanceIdentifier,
+ OvsdbTerminationPointAugmentation tp) {
+
+ }
+
+ private boolean isBandwidthRuleCleared(OvsdbTerminationPointAugmentation original,
+ OvsdbTerminationPointAugmentation update) {
+ if ((update.getIngressPolicingRate() == 0 && update.getIngressPolicingBurst() == 0)
+ && (original.getIngressPolicingRate() != 0 || original.getIngressPolicingBurst() != 0)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<OvsdbTerminationPointAugmentation> instanceIdentifier,
+ OvsdbTerminationPointAugmentation original,
+ OvsdbTerminationPointAugmentation update) {
+ if (!qosEosHandler.isQosClusterOwner()) {
+ return;
+ }
+ String ifaceId = getIfaceId(update);
+
+ // switch restart scenario with openstack newton onwards results in deletion and addition
+ // of vhu ports with ovs-dpdk and as a side effect of that, qos parameters for rate limiting
+ // get cleared from the port.
+ // To resolve the issue, in TP update event, check is done to see if old port configuration
+ // has qos parameters set but cleared in updated port configuration and qos policy with
+ // bandwidth rules is present for the port, then reapply the qos policy configuration.
+
+ if (ifaceId != null && isBandwidthRuleCleared(original, update)) {
+ LOG.debug("update tp augment: iface-id: {}, name: {}, old bw rate, burst = {}, {}, "
+ + "updated bw rate, burst = {}, {}", ifaceId, update.getName(),
+ original.getIngressPolicingRate(), original.getIngressPolicingBurst(),
+ update.getIngressPolicingRate(), update.getIngressPolicingBurst());
+ Port port = qosNeutronUtils.getNeutronPort(ifaceId);
+ if (port != null) {
+ setPortBandwidthRule(instanceIdentifier, update, port);
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<OvsdbTerminationPointAugmentation> instanceIdentifier,
+ OvsdbTerminationPointAugmentation tpAugment) {
+ if (!qosEosHandler.isQosClusterOwner()) {
+ return;
+ }
+ String ifaceId = getIfaceId(tpAugment);
+ if (ifaceId != null) {
+ Port port = qosNeutronUtils.getNeutronPort(ifaceId);
+ if (port != null) {
+ LOG.debug("add tp augmentation: iface-id: {}, name: {} ", ifaceId, tpAugment.getName());
+ setPortBandwidthRule(instanceIdentifier, tpAugment, port);
+ }
+ }
+ }
+
+ @Override
+ protected QosTerminationPointListener getDataTreeChangeListener() {
+ return QosTerminationPointListener.this;
+ }
+
+ private void setPortBandwidthRule(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
+ OvsdbTerminationPointAugmentation update, Port port) {
+ QosPolicy qosPolicy = qosNeutronUtils.getQosPolicy(port);
+ if (qosPolicy == null || qosPolicy.getBandwidthLimitRules() == null
+ || qosPolicy.getBandwidthLimitRules().isEmpty()) {
+ return;
+ }
+ LOG.debug("setting bandwidth rule for port: {}, {}, qos policy: {}",
+ port.getUuid(), update.getName(), qosPolicy.getName());
+
+ jobCoordinator.enqueueJob("QosPort-" + port.getUuid(), () ->
+ Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ BandwidthLimitRules bwRule = qosPolicy.getBandwidthLimitRules().get(0);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
+ new OvsdbTerminationPointAugmentationBuilder();
+ tpAugmentationBuilder.setName(update.getName());
+ tpAugmentationBuilder.setIngressPolicingRate(bwRule.getMaxKbps().longValue());
+ tpAugmentationBuilder.setIngressPolicingBurst(bwRule.getMaxBurstKbps().longValue());
+
+ tx.merge(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(SouthboundUtils.OVSDB_TOPOLOGY_ID))
+ .child(Node.class, identifier.firstKeyOf(Node.class))
+ .child(TerminationPoint.class, identifier.firstKeyOf(TerminationPoint.class))
+ .augmentation(OvsdbTerminationPointAugmentation.class),
+ tpAugmentationBuilder.build(), true);
+
+ })));
+ }
+
+ private String getIfaceId(OvsdbTerminationPointAugmentation tpAugmentation) {
+ if (tpAugmentation.getInterfaceExternalIds() != null) {
+ for (InterfaceExternalIds entry: tpAugmentation.getInterfaceExternalIds()) {
+ if (entry.getExternalIdKey().equals(EXTERNAL_ID_INTERFACE_ID)) {
+ return entry.getExternalIdValue();
+ }
+ }
+ }
+ return null;
+ }
+}