2 * Copyright (c) 2017 Intel Corporation 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
8 package org.opendaylight.netvirt.qosservice;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.List;
16 import java.util.Map.Entry;
17 import javax.annotation.PostConstruct;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
25 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
26 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
27 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
28 import org.opendaylight.netvirt.neutronvpn.api.utils.ChangeUtils;
29 import org.opendaylight.netvirt.qosservice.recovery.QosServiceRecoveryHandler;
30 import org.opendaylight.serviceutils.srm.RecoverableListener;
31 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosPolicies;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypes;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypesBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.QosPolicy;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRules;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRulesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.DscpmarkingRules;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.rule.types.RuleTypes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.rule.types.RuleTypesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 public class QosPolicyChangeListener extends AsyncClusteredDataTreeChangeListenerBase<QosPolicy,
51 QosPolicyChangeListener> implements RecoverableListener {
52 private static final Logger LOG = LoggerFactory.getLogger(QosPolicyChangeListener.class);
53 private final DataBroker dataBroker;
54 private final ManagedNewTransactionRunner txRunner;
55 private final QosNeutronUtils qosNeutronUtils;
56 private final JobCoordinator jobCoordinator;
59 public QosPolicyChangeListener(final DataBroker dataBroker,
60 final QosNeutronUtils qosNeutronUtils, final JobCoordinator jobCoordinator,
61 final ServiceRecoveryRegistry serviceRecoveryRegistry,
62 final QosServiceRecoveryHandler qosServiceRecoveryHandler) {
63 super(QosPolicy.class, QosPolicyChangeListener.class);
64 this.dataBroker = dataBroker;
65 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
66 this.qosNeutronUtils = qosNeutronUtils;
67 this.jobCoordinator = jobCoordinator;
68 serviceRecoveryRegistry.addRecoverableListener(qosServiceRecoveryHandler.buildServiceRegistryKey(),
70 LOG.trace("{} created", getClass().getSimpleName());
76 supportedQoSRuleTypes();
77 LOG.trace("{} init and registerListener done", getClass().getSimpleName());
81 public void registerListener() {
82 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
86 protected InstanceIdentifier<QosPolicy> getWildCardPath() {
87 return InstanceIdentifier.create(Neutron.class).child(QosPolicies.class).child(QosPolicy.class);
91 public void onDataTreeChanged(Collection<DataTreeModification<QosPolicy>> changes) {
92 handleQosPolicyChanges(changes);
93 handleBandwidthLimitRulesChanges(changes);
94 handleDscpMarkingRulesChanges(changes);
98 protected QosPolicyChangeListener getDataTreeChangeListener() {
99 return QosPolicyChangeListener.this;
102 private void handleQosPolicyChanges(Collection<DataTreeModification<QosPolicy>> changes) {
103 Map<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyOriginalMap =
104 ChangeUtils.extractOriginal(changes, QosPolicy.class);
106 for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
107 ChangeUtils.extractCreated(changes, QosPolicy.class).entrySet()) {
108 add(qosPolicyMapEntry.getKey(), qosPolicyMapEntry.getValue());
110 for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
111 ChangeUtils.extractUpdated(changes, QosPolicy.class).entrySet()) {
112 update(qosPolicyMapEntry.getKey(), qosPolicyOriginalMap.get(qosPolicyMapEntry.getKey()),
113 qosPolicyMapEntry.getValue());
115 for (InstanceIdentifier<QosPolicy> qosPolicyIid : ChangeUtils.extractRemoved(changes, QosPolicy.class)) {
116 remove(qosPolicyIid, qosPolicyOriginalMap.get(qosPolicyIid));
120 private void handleBandwidthLimitRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
121 Map<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitOriginalMap =
122 ChangeUtils.extractOriginal(changes, BandwidthLimitRules.class);
124 for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
125 ChangeUtils.extractCreated(changes, BandwidthLimitRules.class).entrySet()) {
126 add(bwLimitMapEntry.getKey(), bwLimitMapEntry.getValue());
128 for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
129 ChangeUtils.extractUpdated(changes, BandwidthLimitRules.class).entrySet()) {
130 update(bwLimitMapEntry.getKey(), bwLimitOriginalMap.get(bwLimitMapEntry.getKey()),
131 bwLimitMapEntry.getValue());
133 for (InstanceIdentifier<BandwidthLimitRules> bwLimitIid :
134 ChangeUtils.extractRemoved(changes, BandwidthLimitRules.class)) {
135 remove(bwLimitIid, bwLimitOriginalMap.get(bwLimitIid));
139 private void handleDscpMarkingRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
140 Map<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkOriginalMap =
141 ChangeUtils.extractOriginal(changes, DscpmarkingRules.class);
143 for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
144 ChangeUtils.extractCreated(changes, DscpmarkingRules.class).entrySet()) {
145 add(dscpMarkMapEntry.getKey(), dscpMarkMapEntry.getValue());
147 for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
148 ChangeUtils.extractUpdated(changes, DscpmarkingRules.class).entrySet()) {
149 update(dscpMarkMapEntry.getKey(), dscpMarkOriginalMap.get(dscpMarkMapEntry.getKey()),
150 dscpMarkMapEntry.getValue());
152 for (InstanceIdentifier<DscpmarkingRules> dscpMarkIid :
153 ChangeUtils.extractRemoved(changes, DscpmarkingRules.class)) {
154 remove(dscpMarkIid, dscpMarkOriginalMap.get(dscpMarkIid));
159 protected void add(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
160 LOG.debug("Adding QosPolicy : key: {}, value={}",
161 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(),input);
162 qosNeutronUtils.addToQosPolicyCache(input);
165 protected void add(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
166 LOG.debug("Adding BandwidthlimitRules : key: {}, value={}",
167 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
169 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
170 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
171 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
174 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
175 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
176 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
177 tx -> qosNeutronUtils.setPortBandwidthLimits(port, input, tx))));
181 private void add(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules input) {
182 LOG.debug("Adding DscpMarkingRules : key: {}, value={}",
183 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
185 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
187 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
188 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
191 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
192 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
193 qosNeutronUtils.setPortDscpMarking(port, input);
194 return Collections.emptyList();
200 protected void remove(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
201 LOG.debug("Removing QosPolicy : key: {}, value={}",
202 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
203 qosNeutronUtils.removeFromQosPolicyCache(input);
206 private void remove(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
207 LOG.debug("Removing BandwidthLimitRules : key: {}, value={}",
208 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
210 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
211 BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
212 BandwidthLimitRules zeroBwLimitRule =
213 bwLimitBuilder.setMaxBurstKbps(BigInteger.ZERO).setMaxKbps(BigInteger.ZERO).build();
215 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
216 qosNeutronUtils.handleNeutronNetworkQosBwRuleRemove(network, zeroBwLimitRule);
219 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
220 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
221 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
222 tx -> qosNeutronUtils.setPortBandwidthLimits(port, zeroBwLimitRule, tx))));
226 private void remove(InstanceIdentifier<DscpmarkingRules> identifier,DscpmarkingRules input) {
227 LOG.debug("Removing DscpMarkingRules : key: {}, value={}",
228 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
230 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
232 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
233 qosNeutronUtils.handleNeutronNetworkQosDscpRuleRemove(network);
236 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
237 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
238 qosNeutronUtils.unsetPortDscpMark(port);
239 return Collections.emptyList();
244 public void reapplyPolicy(String entityid) {
245 Uuid policyUuid = Uuid.getDefaultInstance(entityid);
246 if (qosNeutronUtils.getQosPolicyMap().get(policyUuid) == null) {
247 LOG.debug("Policy with Uuid: {} does not exist", entityid);
251 if (!qosNeutronUtils.getQosPolicyMap().get(policyUuid).getBandwidthLimitRules().isEmpty()) {
252 BandwidthLimitRules bandwidthLimitRules =
253 qosNeutronUtils.getQosPolicyMap().get(policyUuid).getBandwidthLimitRules().get(0);
254 update(policyUuid, bandwidthLimitRules);
257 if (!qosNeutronUtils.getQosPolicyMap().get(policyUuid).getDscpmarkingRules().isEmpty()) {
258 DscpmarkingRules dscpmarkingRules =
259 qosNeutronUtils.getQosPolicyMap().get(policyUuid).getDscpmarkingRules().get(0);
260 update(policyUuid, dscpmarkingRules);
265 protected void update(InstanceIdentifier<QosPolicy> identifier, QosPolicy original, QosPolicy update) {
266 LOG.debug("Updating QosPolicy : key: {}, original value={}, update value={}",
267 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original, update);
268 qosNeutronUtils.addToQosPolicyCache(update);
271 private void update(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules original,
272 BandwidthLimitRules update) {
273 LOG.debug("Updating BandwidthLimitRules : key: {}, original value={}, update value={}",
274 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original,
276 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
277 update(qosUuid, update);
280 private void update(Uuid qosUuid, BandwidthLimitRules update) {
281 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
282 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
285 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
286 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
287 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
288 tx -> qosNeutronUtils.setPortBandwidthLimits(port, update, tx))));
292 private void update(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules original,
293 DscpmarkingRules update) {
294 LOG.debug("Updating DscpMarkingRules : key: {}, original value={}, update value={}",
295 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original, update);
296 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
297 update(qosUuid, update);
300 private void update(Uuid qosUuid, DscpmarkingRules update) {
301 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
302 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
305 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
306 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
307 qosNeutronUtils.setPortDscpMarking(port, update);
308 return Collections.emptyList();
313 private void supportedQoSRuleTypes() {
314 QosRuleTypesBuilder qrtBuilder = new QosRuleTypesBuilder();
315 List<RuleTypes> value = new ArrayList<>();
317 value.add(getRuleTypes("bandwidth_limit_rules"));
318 value.add(getRuleTypes("dscp_marking_rules"));
320 qrtBuilder.setRuleTypes(value);
322 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
323 InstanceIdentifier instanceIdentifier = InstanceIdentifier.create(Neutron.class).child(QosRuleTypes.class);
324 tx.merge(LogicalDatastoreType.OPERATIONAL, instanceIdentifier, qrtBuilder.build());
325 }), LOG, "Error setting up supported QoS rule types");
328 private RuleTypes getRuleTypes(String ruleType) {
329 RuleTypesBuilder rtBuilder = new RuleTypesBuilder();
330 rtBuilder.setRuleType(ruleType);
331 return rtBuilder.build();