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.Collections;
12 import javax.annotation.PostConstruct;
13 import javax.inject.Inject;
14 import javax.inject.Singleton;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
20 import org.opendaylight.netvirt.qosservice.recovery.QosServiceRecoveryHandler;
21 import org.opendaylight.serviceutils.srm.RecoverableListener;
22 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosPortExtension;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.QosPolicy;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 public class QosNeutronPortChangeListener extends AsyncClusteredDataTreeChangeListenerBase<Port,
35 QosNeutronPortChangeListener> implements RecoverableListener {
36 private static final Logger LOG = LoggerFactory.getLogger(QosNeutronPortChangeListener.class);
37 private final DataBroker dataBroker;
38 private final QosNeutronUtils qosNeutronUtils;
39 private final QosEosHandler qosEosHandler;
40 private final JobCoordinator jobCoordinator;
43 public QosNeutronPortChangeListener(final DataBroker dataBroker,
44 final QosNeutronUtils qosNeutronUtils, final QosServiceRecoveryHandler qosServiceRecoveryHandler,
45 final ServiceRecoveryRegistry serviceRecoveryRegistry,
46 final QosEosHandler qosEosHandler,
47 final JobCoordinator jobCoordinator) {
48 super(Port.class, QosNeutronPortChangeListener.class);
49 this.dataBroker = dataBroker;
50 this.qosNeutronUtils = qosNeutronUtils;
51 this.qosEosHandler = qosEosHandler;
52 this.jobCoordinator = jobCoordinator;
53 serviceRecoveryRegistry.addRecoverableListener(qosServiceRecoveryHandler.buildServiceRegistryKey(),
55 LOG.trace("{} created", getClass().getSimpleName());
61 LOG.trace("{} init and registerListener done", getClass().getSimpleName());
65 protected InstanceIdentifier<Port> getWildCardPath() {
66 return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
70 public void registerListener() {
71 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
75 protected QosNeutronPortChangeListener getDataTreeChangeListener() {
76 return QosNeutronPortChangeListener.this;
80 protected void add(InstanceIdentifier<Port> instanceIdentifier, Port port) {
81 qosNeutronUtils.addToPortCache(port);
85 protected void remove(InstanceIdentifier<Port> instanceIdentifier, Port port) {
86 qosNeutronUtils.removeFromPortCache(port);
90 protected void update(InstanceIdentifier<Port> instanceIdentifier, Port original, Port update) {
91 qosNeutronUtils.addToPortCache(update);
92 // check for QoS updates
93 QosPortExtension updateQos = update.augmentation(QosPortExtension.class);
94 QosPortExtension originalQos = original.augmentation(QosPortExtension.class);
96 if (originalQos == null && updateQos != null) {
97 // qosservice policy add
98 qosNeutronUtils.addToQosPortsCache(updateQos.getQosPolicyId(), update);
99 qosNeutronUtils.handleNeutronPortQosAdd(update, updateQos.getQosPolicyId());
100 } else if (originalQos != null && updateQos != null
101 && !originalQos.getQosPolicyId().equals(updateQos.getQosPolicyId())) {
103 // qosservice policy update
104 qosNeutronUtils.removeFromQosPortsCache(originalQos.getQosPolicyId(), original);
105 qosNeutronUtils.addToQosPortsCache(updateQos.getQosPolicyId(), update);
106 qosNeutronUtils.handleNeutronPortQosUpdate(update, updateQos.getQosPolicyId(),
107 originalQos.getQosPolicyId());
108 } else if (originalQos != null && updateQos == null) {
109 // qosservice policy delete
110 qosNeutronUtils.handleNeutronPortQosRemove(original, originalQos.getQosPolicyId());
111 qosNeutronUtils.removeFromQosPortsCache(originalQos.getQosPolicyId(), original);
114 if (qosEosHandler.isQosClusterOwner()) {
115 checkForPortIpAddressUpdate(original, update);
121 private void checkForPortIpAddressUpdate(Port original, Port update) {
122 QosPolicy qosPolicy = qosNeutronUtils.getQosPolicy(update);
123 if (qosPolicy == null || !qosNeutronUtils.hasDscpMarkingRule(qosPolicy)) {
126 int origAddrMask = qosNeutronUtils.getIpVersions(original);
127 int updateAddrMask = qosNeutronUtils.getIpVersions(update);
129 if (origAddrMask == updateAddrMask) {
132 jobCoordinator.enqueueJob("QosPort-" + update.getUuid().getValue(), () -> {
133 short dscpVal = qosPolicy.getDscpmarkingRules().get(0).getDscpMark();
134 String ifName = update.getUuid().getValue();
135 BigInteger dpnId = qosNeutronUtils.getDpnForInterface(ifName);
136 if (dpnId.equals(BigInteger.ZERO)) {
137 LOG.warn("dpnId not found for intf {}", ifName);
138 return Collections.emptyList();
140 Interface intf = qosNeutronUtils.getInterfaceStateFromOperDS(ifName);
141 if (qosNeutronUtils.hasIpv4Addr(origAddrMask) && !qosNeutronUtils.hasIpv4Addr(updateAddrMask)) {
142 LOG.debug("removing ipv4 flow for port: {}", update.getUuid().getValue());
143 qosNeutronUtils.removeFlow(dpnId, ifName, NwConstants.ETHTYPE_IPV4, intf);
144 } else if (!qosNeutronUtils.hasIpv4Addr(origAddrMask) && qosNeutronUtils.hasIpv4Addr(updateAddrMask)) {
145 LOG.debug("adding ipv4 flow for port: {}, dscp: {}", update.getUuid().getValue(), dscpVal);
146 qosNeutronUtils.addFlow(dpnId, dscpVal, ifName, NwConstants.ETHTYPE_IPV4, intf);
149 if (qosNeutronUtils.hasIpv6Addr(origAddrMask) && !qosNeutronUtils.hasIpv6Addr(updateAddrMask)) {
150 LOG.debug("removing ipv6 flow for port: {}", update.getUuid().getValue());
151 qosNeutronUtils.removeFlow(dpnId, ifName, NwConstants.ETHTYPE_IPV6, intf);
152 } else if (!qosNeutronUtils.hasIpv6Addr(origAddrMask) && qosNeutronUtils.hasIpv6Addr(updateAddrMask)) {
153 LOG.debug("adding ipv6 flow for port: {}, dscp: {}", update.getUuid().getValue(), dscpVal);
154 qosNeutronUtils.addFlow(dpnId, dscpVal, ifName, NwConstants.ETHTYPE_IPV6, intf);
156 return Collections.emptyList();