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 com.google.common.util.concurrent.ListenableFuture;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collection;
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.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
25 import org.opendaylight.genius.srm.RecoverableListener;
26 import org.opendaylight.genius.srm.ServiceRecoveryRegistry;
27 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
28 import org.opendaylight.netvirt.neutronvpn.api.utils.ChangeUtils;
29 import org.opendaylight.netvirt.qosservice.recovery.QosServiceRecoveryHandler;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosPolicies;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.QosPolicy;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRules;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRulesBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.DscpmarkingRules;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.rule.types.RuleTypes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.rule.types.RuleTypesBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 public class QosPolicyChangeListener extends AsyncClusteredDataTreeChangeListenerBase<QosPolicy,
49 QosPolicyChangeListener> implements RecoverableListener {
50 private static final Logger LOG = LoggerFactory.getLogger(QosPolicyChangeListener.class);
51 private final DataBroker dataBroker;
52 private final QosAlertManager qosAlertManager;
53 private final QosNeutronUtils qosNeutronUtils;
54 private final JobCoordinator jobCoordinator;
57 public QosPolicyChangeListener(final DataBroker dataBroker, final QosAlertManager qosAlertManager,
58 final QosNeutronUtils qosNeutronUtils, final JobCoordinator jobCoordinator,
59 final ServiceRecoveryRegistry serviceRecoveryRegistry,
60 final QosServiceRecoveryHandler qosServiceRecoveryHandler) {
61 super(QosPolicy.class, QosPolicyChangeListener.class);
62 this.dataBroker = dataBroker;
63 this.qosAlertManager = qosAlertManager;
64 this.qosNeutronUtils = qosNeutronUtils;
65 this.jobCoordinator = jobCoordinator;
66 serviceRecoveryRegistry.addRecoverableListener(qosServiceRecoveryHandler.buildServiceRegistryKey(),
68 LOG.debug("{} created", getClass().getSimpleName());
74 supportedQoSRuleTypes();
75 LOG.debug("{} init and registerListener done", getClass().getSimpleName());
79 public void registerListener() {
80 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
84 protected InstanceIdentifier<QosPolicy> getWildCardPath() {
85 return InstanceIdentifier.create(Neutron.class).child(QosPolicies.class).child(QosPolicy.class);
89 public void onDataTreeChanged(Collection<DataTreeModification<QosPolicy>> changes) {
90 handleQosPolicyChanges(changes);
91 handleBandwidthLimitRulesChanges(changes);
92 handleDscpMarkingRulesChanges(changes);
96 protected QosPolicyChangeListener getDataTreeChangeListener() {
97 return QosPolicyChangeListener.this;
100 private void handleQosPolicyChanges(Collection<DataTreeModification<QosPolicy>> changes) {
101 Map<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyOriginalMap =
102 ChangeUtils.extractOriginal(changes, QosPolicy.class);
104 for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
105 ChangeUtils.extractCreated(changes, QosPolicy.class).entrySet()) {
106 add(qosPolicyMapEntry.getKey(), qosPolicyMapEntry.getValue());
108 for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
109 ChangeUtils.extractUpdated(changes, QosPolicy.class).entrySet()) {
110 update(qosPolicyMapEntry.getKey(), qosPolicyOriginalMap.get(qosPolicyMapEntry.getKey()),
111 qosPolicyMapEntry.getValue());
113 for (InstanceIdentifier<QosPolicy> qosPolicyIid : ChangeUtils.extractRemoved(changes, QosPolicy.class)) {
114 remove(qosPolicyIid, qosPolicyOriginalMap.get(qosPolicyIid));
118 private void handleBandwidthLimitRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
119 Map<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitOriginalMap =
120 ChangeUtils.extractOriginal(changes, BandwidthLimitRules.class);
122 for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
123 ChangeUtils.extractCreated(changes, BandwidthLimitRules.class).entrySet()) {
124 add(bwLimitMapEntry.getKey(), bwLimitMapEntry.getValue());
126 for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
127 ChangeUtils.extractUpdated(changes, BandwidthLimitRules.class).entrySet()) {
128 update(bwLimitMapEntry.getKey(), bwLimitOriginalMap.get(bwLimitMapEntry.getKey()),
129 bwLimitMapEntry.getValue());
131 for (InstanceIdentifier<BandwidthLimitRules> bwLimitIid :
132 ChangeUtils.extractRemoved(changes, BandwidthLimitRules.class)) {
133 remove(bwLimitIid, bwLimitOriginalMap.get(bwLimitIid));
137 private void handleDscpMarkingRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
138 Map<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkOriginalMap =
139 ChangeUtils.extractOriginal(changes, DscpmarkingRules.class);
141 for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
142 ChangeUtils.extractCreated(changes, DscpmarkingRules.class).entrySet()) {
143 add(dscpMarkMapEntry.getKey(), dscpMarkMapEntry.getValue());
145 for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
146 ChangeUtils.extractUpdated(changes, DscpmarkingRules.class).entrySet()) {
147 update(dscpMarkMapEntry.getKey(), dscpMarkOriginalMap.get(dscpMarkMapEntry.getKey()),
148 dscpMarkMapEntry.getValue());
150 for (InstanceIdentifier<DscpmarkingRules> dscpMarkIid :
151 ChangeUtils.extractRemoved(changes, DscpmarkingRules.class)) {
152 remove(dscpMarkIid, dscpMarkOriginalMap.get(dscpMarkIid));
157 protected void add(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
158 LOG.trace("Adding QosPolicy : key: {}, value={}", identifier, input);
159 qosNeutronUtils.addToQosPolicyCache(input);
162 protected void add(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
163 LOG.trace("Adding BandwidthlimitRules : key: {}, value={}", identifier, input);
165 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
166 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
167 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
168 qosAlertManager.addToQosAlertCache(network);
171 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
172 qosAlertManager.addToQosAlertCache(port);
173 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
174 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
175 List<ListenableFuture<Void>> futures = new ArrayList<>();
176 qosNeutronUtils.setPortBandwidthLimits(port, input, wrtConfigTxn);
177 futures.add(wrtConfigTxn.submit());
183 private void add(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules input) {
184 LOG.trace("Adding DscpMarkingRules : key: {}, value={}", identifier, input);
186 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
188 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
189 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
192 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
193 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
194 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
195 List<ListenableFuture<Void>> futures = new ArrayList<>();
196 qosNeutronUtils.setPortDscpMarking(port, input);
197 futures.add(wrtConfigTxn.submit());
204 protected void remove(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
205 LOG.trace("Removing QosPolicy : key: {}, value={}", identifier, input);
206 qosNeutronUtils.removeFromQosPolicyCache(input);
209 private void remove(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
210 LOG.trace("Removing BandwidthLimitRules : key: {}, value={}", identifier, input);
212 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
213 BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
214 BandwidthLimitRules zeroBwLimitRule =
215 bwLimitBuilder.setMaxBurstKbps(BigInteger.ZERO).setMaxKbps(BigInteger.ZERO).build();
217 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
218 qosAlertManager.removeFromQosAlertCache(network);
219 qosNeutronUtils.handleNeutronNetworkQosBwRuleRemove(network, zeroBwLimitRule);
222 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
223 qosAlertManager.removeFromQosAlertCache(port);
224 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
225 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
226 List<ListenableFuture<Void>> futures = new ArrayList<>();
227 qosNeutronUtils.setPortBandwidthLimits(port, zeroBwLimitRule, wrtConfigTxn);
228 futures.add(wrtConfigTxn.submit());
234 private void remove(InstanceIdentifier<DscpmarkingRules> identifier,DscpmarkingRules input) {
235 LOG.trace("Removing DscpMarkingRules : key: {}, value={}", identifier, input);
237 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
239 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
240 qosNeutronUtils.handleNeutronNetworkQosDscpRuleRemove(network);
243 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
244 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
245 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
246 List<ListenableFuture<Void>> futures = new ArrayList<>();
247 qosNeutronUtils.unsetPortDscpMark(port);
248 futures.add(wrtConfigTxn.submit());
254 public void reapplyPolicy(String entityid) {
255 Uuid policyUuid = Uuid.getDefaultInstance(entityid);
257 if (!qosNeutronUtils.getQosPolicyMap().get(policyUuid).getBandwidthLimitRules().isEmpty()) {
258 BandwidthLimitRules bandwidthLimitRules =
259 qosNeutronUtils.getQosPolicyMap().get(policyUuid).getBandwidthLimitRules().get(0);
260 update(policyUuid, bandwidthLimitRules);
263 if (!qosNeutronUtils.getQosPolicyMap().get(policyUuid).getDscpmarkingRules().isEmpty()) {
264 DscpmarkingRules dscpmarkingRules =
265 qosNeutronUtils.getQosPolicyMap().get(policyUuid).getDscpmarkingRules().get(0);
266 update(policyUuid, dscpmarkingRules);
271 protected void update(InstanceIdentifier<QosPolicy> identifier, QosPolicy original, QosPolicy update) {
272 LOG.trace("Updating QosPolicy : key: {}, original value={}, update value={}", identifier, original, update);
273 qosNeutronUtils.addToQosPolicyCache(update);
276 private void update(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules original,
277 BandwidthLimitRules update) {
278 LOG.trace("Updating BandwidthLimitRules : key: {}, original value={}, update value={}", identifier, original,
280 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
281 update(qosUuid, update);
284 private void update(Uuid qosUuid, BandwidthLimitRules update) {
285 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
286 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
289 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
290 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
291 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
292 List<ListenableFuture<Void>> futures = new ArrayList<>();
293 qosNeutronUtils.setPortBandwidthLimits(port, update, wrtConfigTxn);
294 futures.add(wrtConfigTxn.submit());
300 private void update(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules original,
301 DscpmarkingRules update) {
302 LOG.trace("Updating DscpMarkingRules : key: {}, original value={}, update value={}", identifier, original,
304 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
305 update(qosUuid, update);
308 private void update(Uuid qosUuid, DscpmarkingRules update) {
309 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
310 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
313 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
314 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
315 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
316 List<ListenableFuture<Void>> futures = new ArrayList<>();
317 qosNeutronUtils.setPortDscpMarking(port, update);
318 futures.add(wrtConfigTxn.submit());
324 private void supportedQoSRuleTypes() {
325 QosRuleTypesBuilder qrtBuilder = new QosRuleTypesBuilder();
326 List<RuleTypes> value = new ArrayList<>();
328 value.add(getRuleTypes("bandwidth_limit_rules"));
329 value.add(getRuleTypes("dscp_marking_rules"));
331 qrtBuilder.setRuleTypes(value);
332 final WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
334 InstanceIdentifier instanceIdentifier = InstanceIdentifier.create(Neutron.class).child(QosRuleTypes.class);
336 writeTx.merge(LogicalDatastoreType.OPERATIONAL, instanceIdentifier, qrtBuilder.build());
342 private RuleTypes getRuleTypes(String ruleType) {
343 RuleTypesBuilder rtBuilder = new RuleTypesBuilder();
344 rtBuilder.setRuleType(ruleType);
345 return rtBuilder.build();