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 static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
23 import org.opendaylight.infrautils.utils.concurrent.Executors;
24 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.netvirt.qosservice.recovery.QosServiceRecoveryHandler;
28 import org.opendaylight.serviceutils.srm.RecoverableListener;
29 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
30 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosPolicies;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.QosPolicy;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRules;
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 AbstractClusteredAsyncDataTreeChangeListener<QosPolicy>
49 implements RecoverableListener {
50 private static final Logger LOG = LoggerFactory.getLogger(QosPolicyChangeListener.class);
51 private final DataBroker dataBroker;
52 private final ManagedNewTransactionRunner txRunner;
53 private final QosNeutronUtils qosNeutronUtils;
54 private final JobCoordinator jobCoordinator;
57 public QosPolicyChangeListener(final DataBroker dataBroker,
58 final QosNeutronUtils qosNeutronUtils, final JobCoordinator jobCoordinator,
59 final ServiceRecoveryRegistry serviceRecoveryRegistry,
60 final QosServiceRecoveryHandler qosServiceRecoveryHandler) {
61 super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Neutron.class)
62 .child(QosPolicies.class).child(QosPolicy.class),
63 Executors.newListeningSingleThreadExecutor("QosPolicyChangeListener", LOG));
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());
75 supportedQoSRuleTypes();
76 LOG.trace("{} init and registerListener done", getClass().getSimpleName());
83 Executors.shutdownAndAwaitTermination(getExecutorService());
87 public void registerListener() {
92 public void deregisterListener() {
97 public void onDataTreeChanged(Collection<DataTreeModification<QosPolicy>> changes) {
98 handleQosPolicyChanges(changes);
99 handleBandwidthLimitRulesChanges(changes);
100 handleDscpMarkingRulesChanges(changes);
103 private void handleQosPolicyChanges(Collection<DataTreeModification<QosPolicy>> changes) {
104 Map<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyOriginalMap =
105 ChangeUtils.extractOriginal(changes, QosPolicy.class);
107 for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
108 ChangeUtils.extractCreated(changes, QosPolicy.class).entrySet()) {
109 add(qosPolicyMapEntry.getKey(), qosPolicyMapEntry.getValue());
111 for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
112 ChangeUtils.extractUpdated(changes, QosPolicy.class).entrySet()) {
113 update(qosPolicyMapEntry.getKey(), qosPolicyOriginalMap.get(qosPolicyMapEntry.getKey()),
114 qosPolicyMapEntry.getValue());
116 for (InstanceIdentifier<QosPolicy> qosPolicyIid : ChangeUtils.extractRemoved(changes, QosPolicy.class)) {
117 remove(qosPolicyIid, qosPolicyOriginalMap.get(qosPolicyIid));
121 private void handleBandwidthLimitRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
122 Map<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitOriginalMap =
123 ChangeUtils.extractOriginal(changes, BandwidthLimitRules.class);
125 for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
126 ChangeUtils.extractCreated(changes, BandwidthLimitRules.class).entrySet()) {
127 add(bwLimitMapEntry.getKey(), bwLimitMapEntry.getValue());
129 for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
130 ChangeUtils.extractUpdated(changes, BandwidthLimitRules.class).entrySet()) {
131 update(bwLimitMapEntry.getKey(), bwLimitOriginalMap.get(bwLimitMapEntry.getKey()),
132 bwLimitMapEntry.getValue());
134 for (InstanceIdentifier<BandwidthLimitRules> bwLimitIid :
135 ChangeUtils.extractRemoved(changes, BandwidthLimitRules.class)) {
136 remove(bwLimitIid, bwLimitOriginalMap.get(bwLimitIid));
140 private void handleDscpMarkingRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
141 Map<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkOriginalMap =
142 ChangeUtils.extractOriginal(changes, DscpmarkingRules.class);
144 for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
145 ChangeUtils.extractCreated(changes, DscpmarkingRules.class).entrySet()) {
146 add(dscpMarkMapEntry.getKey(), dscpMarkMapEntry.getValue());
148 for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
149 ChangeUtils.extractUpdated(changes, DscpmarkingRules.class).entrySet()) {
150 update(dscpMarkMapEntry.getKey(), dscpMarkOriginalMap.get(dscpMarkMapEntry.getKey()),
151 dscpMarkMapEntry.getValue());
153 for (InstanceIdentifier<DscpmarkingRules> dscpMarkIid :
154 ChangeUtils.extractRemoved(changes, DscpmarkingRules.class)) {
155 remove(dscpMarkIid, dscpMarkOriginalMap.get(dscpMarkIid));
160 public void add(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
161 LOG.debug("Adding QosPolicy : key: {}, value={}",
162 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(),input);
163 qosNeutronUtils.addToQosPolicyCache(input);
166 protected void add(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
167 LOG.debug("Adding BandwidthlimitRules : key: {}, value={}",
168 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
170 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
171 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
172 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
175 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
176 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
177 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
178 tx -> qosNeutronUtils.setPortBandwidthLimits(port, input, tx))));
182 /* private void add(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules input) {
183 LOG.debug("Adding DscpMarkingRules : key: {}, value={}",
184 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), 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 qosNeutronUtils.setPortDscpMarking(port, input);
195 return Collections.emptyList();
201 public void remove(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
202 LOG.debug("Removing QosPolicy : key: {}, value={}",
203 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
204 qosNeutronUtils.removeFromQosPolicyCache(input);
207 /* private void remove(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
208 LOG.debug("Removing BandwidthLimitRules : key: {}, value={}",
209 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
211 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
212 BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
213 BandwidthLimitRules zeroBwLimitRule =
214 bwLimitBuilder.setMaxBurstKbps(Uint64.ZERO).setMaxKbps(Uint64.ZERO).build();
216 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
217 qosNeutronUtils.handleNeutronNetworkQosBwRuleRemove(network, zeroBwLimitRule);
220 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
221 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
222 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
223 tx -> qosNeutronUtils.setPortBandwidthLimits(port, zeroBwLimitRule, tx))));
227 /* private void remove(InstanceIdentifier<DscpmarkingRules> identifier,DscpmarkingRules input) {
228 LOG.debug("Removing DscpMarkingRules : key: {}, value={}",
229 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
231 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
233 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
234 qosNeutronUtils.handleNeutronNetworkQosDscpRuleRemove(network);
237 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
238 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
239 qosNeutronUtils.unsetPortDscpMark(port);
240 return Collections.emptyList();
245 public void reapplyPolicy(String entityid) {
246 Uuid policyUuid = Uuid.getDefaultInstance(entityid);
247 if (qosNeutronUtils.getQosPolicyMap().get(policyUuid) == null) {
248 LOG.debug("Policy with Uuid: {} does not exist", entityid);
252 @NonNull List<BandwidthLimitRules> nonnullBandwidthLimitRules =
253 new ArrayList<BandwidthLimitRules>(qosNeutronUtils.getQosPolicyMap().get(policyUuid)
254 .nonnullBandwidthLimitRules().values());
255 if (!nonnullBandwidthLimitRules.isEmpty()) {
256 BandwidthLimitRules bandwidthLimitRules = nonnullBandwidthLimitRules.get(0);
257 update(policyUuid, bandwidthLimitRules);
260 @NonNull List<DscpmarkingRules> nonnullDscpmarkingRules =
261 new ArrayList<DscpmarkingRules>(qosNeutronUtils.getQosPolicyMap().get(policyUuid)
262 .nonnullDscpmarkingRules().values());
263 if (!nonnullDscpmarkingRules.isEmpty()) {
264 DscpmarkingRules dscpmarkingRules = nonnullDscpmarkingRules.get(0);
265 update(policyUuid, dscpmarkingRules);
270 public void update(InstanceIdentifier<QosPolicy> identifier, QosPolicy original, QosPolicy update) {
271 LOG.debug("Updating QosPolicy : key: {}, original value={}, update value={}",
272 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original, update);
273 qosNeutronUtils.addToQosPolicyCache(update);
276 /* private void update(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules original,
277 BandwidthLimitRules update) {
278 LOG.debug("Updating BandwidthLimitRules : key: {}, original value={}, update value={}",
279 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original,
281 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
282 update(qosUuid, update);
285 private void update(Uuid qosUuid, BandwidthLimitRules update) {
286 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
287 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
290 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
291 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
292 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
293 tx -> qosNeutronUtils.setPortBandwidthLimits(port, update, tx))));
297 /* private void update(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules original,
298 DscpmarkingRules update) {
299 LOG.debug("Updating DscpMarkingRules : key: {}, original value={}, update value={}",
300 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original, update);
301 Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
302 update(qosUuid, update);
305 private void update(Uuid qosUuid, DscpmarkingRules update) {
306 for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
307 qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
310 for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
311 jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
312 qosNeutronUtils.setPortDscpMarking(port, update);
313 return Collections.emptyList();
318 private void supportedQoSRuleTypes() {
319 QosRuleTypesBuilder qrtBuilder = new QosRuleTypesBuilder();
320 List<RuleTypes> value = new ArrayList<>();
322 value.add(getRuleTypes("bandwidth_limit_rules"));
323 value.add(getRuleTypes("dscp_marking_rules"));
325 qrtBuilder.setRuleTypes(value);
327 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
328 InstanceIdentifier instanceIdentifier = InstanceIdentifier.create(Neutron.class).child(QosRuleTypes.class);
329 tx.merge(instanceIdentifier, qrtBuilder.build());
330 }), LOG, "Error setting up supported QoS rule types");
333 private RuleTypes getRuleTypes(String ruleType) {
334 RuleTypesBuilder rtBuilder = new RuleTypesBuilder();
335 rtBuilder.setRuleType(ruleType);
336 return rtBuilder.build();