Migrate to serviceutils/tools and serviceutils/srm
[netvirt.git] / qosservice / impl / src / main / java / org / opendaylight / netvirt / qosservice / QosNeutronPortChangeListener.java
1 /*
2  * Copyright (c) 2017 Intel Corporation and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.qosservice;
9
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;
32
33 @Singleton
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;
41
42     @Inject
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(),
54                 this);
55         LOG.trace("{} created",  getClass().getSimpleName());
56     }
57
58     @PostConstruct
59     public void init() {
60         registerListener();
61         LOG.trace("{} init and registerListener done", getClass().getSimpleName());
62     }
63
64     @Override
65     protected InstanceIdentifier<Port> getWildCardPath() {
66         return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
67     }
68
69     @Override
70     public void registerListener() {
71         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
72     }
73
74     @Override
75     protected QosNeutronPortChangeListener getDataTreeChangeListener() {
76         return QosNeutronPortChangeListener.this;
77     }
78
79     @Override
80     protected void add(InstanceIdentifier<Port> instanceIdentifier, Port port) {
81         qosNeutronUtils.addToPortCache(port);
82     }
83
84     @Override
85     protected void remove(InstanceIdentifier<Port> instanceIdentifier, Port port) {
86         qosNeutronUtils.removeFromPortCache(port);
87     }
88
89     @Override
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);
95
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())) {
102
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);
112         }
113
114         if (qosEosHandler.isQosClusterOwner()) {
115             checkForPortIpAddressUpdate(original, update);
116         }
117     }
118
119
120
121     private void checkForPortIpAddressUpdate(Port original, Port update) {
122         QosPolicy qosPolicy = qosNeutronUtils.getQosPolicy(update);
123         if (qosPolicy == null || !qosNeutronUtils.hasDscpMarkingRule(qosPolicy)) {
124             return;
125         }
126         int origAddrMask = qosNeutronUtils.getIpVersions(original);
127         int updateAddrMask = qosNeutronUtils.getIpVersions(update);
128
129         if (origAddrMask == updateAddrMask) {
130             return;
131         }
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();
139             }
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);
147             }
148
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);
155             }
156             return Collections.emptyList();
157         });
158     }
159 }