NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / qosservice / impl / src / main / java / org / opendaylight / netvirt / qosservice / QosNeutronUtils.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 static java.util.Collections.emptyList;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ConcurrentMap;
21 import java.util.concurrent.CopyOnWriteArraySet;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.Future;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
29 import org.opendaylight.genius.infra.Datastore;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
31 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
32 import org.opendaylight.genius.infra.TypedWriteTransaction;
33 import org.opendaylight.genius.mdsalutil.ActionInfo;
34 import org.opendaylight.genius.mdsalutil.FlowEntity;
35 import org.opendaylight.genius.mdsalutil.InstructionInfo;
36 import org.opendaylight.genius.mdsalutil.MDSALUtil;
37 import org.opendaylight.genius.mdsalutil.MatchInfo;
38 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
39 import org.opendaylight.genius.mdsalutil.NwConstants;
40 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
41 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldDscp;
42 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
43 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
45 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
46 import org.opendaylight.genius.utils.ServiceIndex;
47 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
48 import org.opendaylight.mdsal.binding.api.DataBroker;
49 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
50 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
51 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeInterfaceInfo;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntryKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosNetworkExtension;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosPortExtension;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.QosPolicy;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRules;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRulesBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.DscpmarkingRules;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
103 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
104 import org.opendaylight.yangtools.yang.common.RpcResult;
105 import org.opendaylight.yangtools.yang.common.Uint64;
106 import org.slf4j.Logger;
107 import org.slf4j.LoggerFactory;
108
109 @Singleton
110 public class QosNeutronUtils {
111     private static final Logger LOG = LoggerFactory.getLogger(QosNeutronUtils.class);
112
113     private final ConcurrentMap<Uuid, QosPolicy> qosPolicyMap = new ConcurrentHashMap<>();
114     private final ConcurrentMap<Uuid, ConcurrentMap<Uuid, Port>> qosPortsMap = new ConcurrentHashMap<>();
115     private final ConcurrentMap<Uuid, ConcurrentMap<Uuid, Network>> qosNetworksMap = new ConcurrentHashMap<>();
116     private final CopyOnWriteArraySet<Uuid> qosServiceConfiguredPorts = new CopyOnWriteArraySet<>();
117     private final ConcurrentHashMap<Uuid, Port> neutronPortMap = new ConcurrentHashMap<>();
118     private final ConcurrentHashMap<Uuid, Network> neutronNetworkMap = new ConcurrentHashMap<>();
119
120     private final QosEosHandler qosEosHandler;
121     private final INeutronVpnManager neutronVpnManager;
122     private final OdlInterfaceRpcService odlInterfaceRpcService;
123     private final DataBroker dataBroker;
124     private final ManagedNewTransactionRunner txRunner;
125     private final IMdsalApiManager mdsalUtils;
126     private final JobCoordinator jobCoordinator;
127
128     @Inject
129     public QosNeutronUtils(final QosEosHandler qosEosHandler, final INeutronVpnManager neutronVpnManager,
130             final OdlInterfaceRpcService odlInterfaceRpcService, final DataBroker dataBroker,
131             final IMdsalApiManager mdsalUtils, final JobCoordinator jobCoordinator) {
132         this.qosEosHandler = qosEosHandler;
133         this.neutronVpnManager = neutronVpnManager;
134         this.odlInterfaceRpcService = odlInterfaceRpcService;
135         this.dataBroker = dataBroker;
136         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
137         this.mdsalUtils = mdsalUtils;
138         this.jobCoordinator = jobCoordinator;
139     }
140
141     public void addToQosPolicyCache(QosPolicy qosPolicy) {
142         qosPolicyMap.put(qosPolicy.getUuid(),qosPolicy);
143     }
144
145     public void removeFromQosPolicyCache(QosPolicy qosPolicy) {
146         qosPolicyMap.remove(qosPolicy.getUuid());
147     }
148
149     public Map<Uuid, QosPolicy> getQosPolicyMap() {
150         return qosPolicyMap;
151     }
152
153     public Collection<Port> getQosPorts(Uuid qosUuid) {
154         final ConcurrentMap<Uuid, Port> portMap = qosPortsMap.get(qosUuid);
155         return portMap != null ? portMap.values() : emptyList();
156     }
157
158     public void addToQosPortsCache(Uuid qosUuid, Port port) {
159         qosPortsMap.computeIfAbsent(qosUuid, key -> new ConcurrentHashMap<>()).putIfAbsent(port.getUuid(), port);
160     }
161
162     public void removeFromQosPortsCache(Uuid qosUuid, Port port) {
163         if (qosPortsMap.containsKey(qosUuid) && qosPortsMap.get(qosUuid).containsKey(port.getUuid())) {
164             qosPortsMap.get(qosUuid).remove(port.getUuid(), port);
165         }
166     }
167
168     public void addToQosNetworksCache(Uuid qosUuid, Network network) {
169         qosNetworksMap.computeIfAbsent(qosUuid, key -> new ConcurrentHashMap<>()).putIfAbsent(network.getUuid(),
170                 network);
171     }
172
173     public void removeFromQosNetworksCache(Uuid qosUuid, Network network) {
174         if (qosNetworksMap.containsKey(qosUuid) && qosNetworksMap.get(qosUuid).containsKey(network.getUuid())) {
175             qosNetworksMap.get(qosUuid).remove(network.getUuid(), network);
176         }
177     }
178
179     @NonNull
180     public Collection<Network> getQosNetworks(Uuid qosUuid) {
181         final ConcurrentMap<Uuid, Network> networkMap = qosNetworksMap.get(qosUuid);
182         return networkMap != null ? networkMap.values() : emptyList();
183     }
184
185     @NonNull
186     public List<Uuid> getSubnetIdsFromNetworkId(Uuid networkId) {
187         InstanceIdentifier<NetworkMap> networkMapId = InstanceIdentifier.builder(NetworkMaps.class)
188                 .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
189         Optional<NetworkMap> optionalNetworkMap = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION,
190                 networkMapId, dataBroker);
191         return (optionalNetworkMap.isPresent() && optionalNetworkMap.get().getSubnetIdList() != null)
192             ? optionalNetworkMap.get().getSubnetIdList() : emptyList();
193     }
194
195     @NonNull
196     protected List<Uuid> getPortIdsFromSubnetId(Uuid subnetId) {
197         InstanceIdentifier<Subnetmap> subnetMapId = InstanceIdentifier
198                 .builder(Subnetmaps.class)
199                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
200         Optional<Subnetmap> optionalSubnetmap = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION,
201                 subnetMapId,dataBroker);
202         return (optionalSubnetmap.isPresent() && optionalSubnetmap.get().getPortList() != null)
203             ? optionalSubnetmap.get().getPortList() : emptyList();
204     }
205
206     public void handleNeutronPortQosAdd(Port port, Uuid qosUuid) {
207         LOG.debug("Handling Port add and QoS associated: port: {} qos: {}", port.getUuid().getValue(),
208                 qosUuid.getValue());
209
210         QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
211
212         jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(),
213             () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
214                 // handle Bandwidth Limit Rules update
215                 if (qosPolicy != null && qosPolicy.getBandwidthLimitRules() != null
216                         && !qosPolicy.getBandwidthLimitRules().isEmpty()) {
217                     setPortBandwidthLimits(port, qosPolicy.getBandwidthLimitRules().get(0), tx);
218                 }
219                 // handle DSCP Mark Rules update
220                 if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
221                         && !qosPolicy.getDscpmarkingRules().isEmpty()) {
222                     setPortDscpMarking(port, qosPolicy.getDscpmarkingRules().get(0));
223                 }
224             })));
225     }
226
227     public void handleQosInterfaceAdd(Port port, Uuid qosUuid) {
228         LOG.debug("Handling Port add and QoS associated: port: {} qos: {}", port.getUuid().getValue(),
229                 qosUuid.getValue());
230
231         QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
232
233         jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
234             // handle DSCP Mark Rules update
235             if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
236                     && !qosPolicy.getDscpmarkingRules().isEmpty()) {
237                 setPortDscpMarking(port, qosPolicy.getDscpmarkingRules().get(0));
238             }
239             return emptyList();
240         });
241     }
242
243     public void handleNeutronPortQosUpdate(Port port, Uuid qosUuidNew, Uuid qosUuidOld) {
244         LOG.debug("Handling Port QoS update: port: {} qosservice: {}", port.getUuid().getValue(),
245                 qosUuidNew.getValue());
246
247         QosPolicy qosPolicyNew = qosPolicyMap.get(qosUuidNew);
248         QosPolicy qosPolicyOld = qosPolicyMap.get(qosUuidOld);
249
250         jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(),
251             () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
252                 // handle Bandwidth Limit Rules update
253                 if (qosPolicyNew != null && qosPolicyNew.getBandwidthLimitRules() != null
254                         && !qosPolicyNew.getBandwidthLimitRules().isEmpty()) {
255                     setPortBandwidthLimits(port, qosPolicyNew.getBandwidthLimitRules().get(0), tx);
256                 } else {
257                     if (qosPolicyOld != null && qosPolicyOld.getBandwidthLimitRules() != null
258                             && !qosPolicyOld.getBandwidthLimitRules().isEmpty()) {
259                         BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
260                         setPortBandwidthLimits(port, bwLimitBuilder
261                                 .setMaxBurstKbps(Uint64.ZERO)
262                                 .setMaxKbps(Uint64.ZERO).build(), tx);
263                     }
264                 }
265                 //handle DSCP Mark Rules update
266                 if (qosPolicyNew != null && qosPolicyNew.getDscpmarkingRules() != null
267                         && !qosPolicyNew.getDscpmarkingRules().isEmpty()) {
268                     setPortDscpMarking(port, qosPolicyNew.getDscpmarkingRules().get(0));
269                 } else {
270                     if (qosPolicyOld != null && qosPolicyOld.getDscpmarkingRules() != null
271                             && !qosPolicyOld.getDscpmarkingRules().isEmpty()) {
272                         unsetPortDscpMark(port);
273                     }
274                 }
275             })));
276     }
277
278     public void handleNeutronPortQosRemove(Port port, Uuid qosUuid) {
279         LOG.debug("Handling Port QoS removal: port: {} qosservice: {}", port.getUuid().getValue(), qosUuid.getValue());
280
281         // check for network qosservice to apply
282         Network network =  neutronVpnManager.getNeutronNetwork(port.getNetworkId());
283         if (network != null && network.augmentation(QosNetworkExtension.class) != null) {
284             Uuid networkQosUuid = network.augmentation(QosNetworkExtension.class).getQosPolicyId();
285             if (networkQosUuid != null) {
286                 handleNeutronPortQosUpdate(port, networkQosUuid, qosUuid);
287             }
288         } else {
289             QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
290
291             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(),
292                 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
293                     // handle Bandwidth Limit Rules removal
294                     if (qosPolicy != null && qosPolicy.getBandwidthLimitRules() != null
295                             && !qosPolicy.getBandwidthLimitRules().isEmpty()) {
296                         BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
297                         setPortBandwidthLimits(port, bwLimitBuilder
298                                 .setMaxBurstKbps(Uint64.ZERO)
299                                 .setMaxKbps(Uint64.ZERO).build(), tx);
300                     }
301                     // handle DSCP MArk Rules removal
302                     if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
303                             && !qosPolicy.getDscpmarkingRules().isEmpty()) {
304                         unsetPortDscpMark(port);
305                     }
306                 })));
307         }
308     }
309
310     public void handleNeutronPortRemove(Port port, Uuid qosUuid) {
311         LOG.debug("Handling Port removal and Qos associated: port: {} qos: {}", port.getUuid().getValue(),
312                 qosUuid.getValue());
313         QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
314
315         jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
316             //check if any DSCP rule in the policy
317             if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
318                     && !qosPolicy.getDscpmarkingRules().isEmpty()) {
319                 unsetPortDscpMark(port);
320             }
321             return emptyList();
322         });
323     }
324
325     public void handleNeutronPortRemove(Port port, Uuid qosUuid, Interface intrf) {
326         LOG.debug("Handling Port removal and Qos associated: port: {} qos: {}", port.getUuid().getValue(),
327                 qosUuid.getValue());
328         QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
329
330         jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
331             if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
332                     && !qosPolicy.getDscpmarkingRules().isEmpty()) {
333                 unsetPortDscpMark(port, intrf);
334             }
335             return emptyList();
336         });
337     }
338
339
340     public void handleNeutronNetworkQosUpdate(Network network, Uuid qosUuid) {
341         LOG.debug("Handling Network QoS update: net: {} qosservice: {}", network.getUuid().getValue(), qosUuid);
342         QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
343         if (qosPolicy == null || (qosPolicy.getBandwidthLimitRules() == null
344                 || qosPolicy.getBandwidthLimitRules().isEmpty())
345                 && (qosPolicy.getDscpmarkingRules() == null
346                 || qosPolicy.getDscpmarkingRules().isEmpty())) {
347             return;
348         }
349         List<Uuid> subnetIds = getSubnetIdsFromNetworkId(network.getUuid());
350         for (Uuid subnetId : subnetIds) {
351             List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
352             for (Uuid portId : portIds) {
353                 Port port = getNeutronPort(portId);
354                 if (port != null && (port.augmentation(QosPortExtension.class) == null
355                         || port.augmentation(QosPortExtension.class).getQosPolicyId() == null)) {
356                     jobCoordinator.enqueueJob("QosPort-" + portId.getValue(),
357                         () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
358                             CONFIGURATION, tx -> {
359                                 if (qosPolicy.getBandwidthLimitRules() != null
360                                         && !qosPolicy.getBandwidthLimitRules().isEmpty()) {
361                                     setPortBandwidthLimits(port, qosPolicy.getBandwidthLimitRules().get(0), tx);
362                                 }
363                                 if (qosPolicy.getDscpmarkingRules() != null
364                                         && !qosPolicy.getDscpmarkingRules().isEmpty()) {
365                                     setPortDscpMarking(port, qosPolicy.getDscpmarkingRules().get(0));
366                                 }
367                             })));
368                 }
369             }
370         }
371     }
372
373     public void handleNeutronNetworkQosRemove(Network network, Uuid qosUuid) {
374         LOG.debug("Handling Network QoS removal: net: {} qosservice: {}", network.getUuid().getValue(),
375                 qosUuid.getValue());
376         QosPolicy qosPolicy = qosPolicyMap.get(qosUuid);
377
378         List<Uuid> subnetIds = getSubnetIdsFromNetworkId(network.getUuid());
379         for (Uuid subnetId : subnetIds) {
380             List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
381             for (Uuid portId : portIds) {
382                 Port port = getNeutronPort(portId);
383                 if (port != null && (port.augmentation(QosPortExtension.class) == null
384                         || port.augmentation(QosPortExtension.class).getQosPolicyId() == null)) {
385                     jobCoordinator.enqueueJob("QosPort-" + portId.getValue(),
386                         () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
387                             CONFIGURATION, tx -> {
388                                 if (qosPolicy != null && qosPolicy.getBandwidthLimitRules() != null
389                                         && !qosPolicy.getBandwidthLimitRules().isEmpty()) {
390                                     BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
391                                     setPortBandwidthLimits(port, bwLimitBuilder
392                                             .setMaxBurstKbps(Uint64.ZERO)
393                                             .setMaxKbps(Uint64.ZERO).build(), tx);
394                                 }
395                                 if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
396                                         && !qosPolicy.getDscpmarkingRules().isEmpty()) {
397                                     unsetPortDscpMark(port);
398                                 }
399                             })));
400                 }
401             }
402         }
403     }
404
405     public void handleNeutronNetworkQosBwRuleRemove(Network network, BandwidthLimitRules zeroBwLimitRule) {
406         LOG.debug("Handling Qos Bandwidth Rule Remove, net: {}", network.getUuid().getValue());
407
408         List<Uuid> subnetIds = getSubnetIdsFromNetworkId(network.getUuid());
409
410         for (Uuid subnetId: subnetIds) {
411             List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
412             for (Uuid portId : portIds) {
413                 Port port = getNeutronPort(portId);
414                 if (port != null && (port.augmentation(QosPortExtension.class) == null
415                         || port.augmentation(QosPortExtension.class).getQosPolicyId() == null)) {
416                     jobCoordinator.enqueueJob("QosPort-" + portId.getValue(), () -> Collections.singletonList(
417                             txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
418                                 tx -> setPortBandwidthLimits(port, zeroBwLimitRule, tx))));
419                 }
420             }
421         }
422     }
423
424     public void handleNeutronNetworkQosDscpRuleRemove(Network network) {
425         LOG.debug("Handling Qos Dscp Rule Remove, net: {}", network.getUuid().getValue());
426
427         List<Uuid> subnetIds = getSubnetIdsFromNetworkId(network.getUuid());
428
429         for (Uuid subnetId: subnetIds) {
430             List<Uuid> portIds = getPortIdsFromSubnetId(subnetId);
431             for (Uuid portId : portIds) {
432                 Port port = getNeutronPort(portId);
433                 if (port != null && (port.augmentation(QosPortExtension.class) == null
434                         || port.augmentation(QosPortExtension.class).getQosPolicyId() == null)) {
435                     jobCoordinator.enqueueJob("QosPort-" + portId.getValue(), () -> {
436                         unsetPortDscpMark(port);
437                         return emptyList();
438                     });
439                 }
440             }
441         }
442     }
443
444     // TODO Clean up the exception handling
445     @SuppressWarnings("checkstyle:IllegalCatch")
446     public void setPortBandwidthLimits(Port port, BandwidthLimitRules bwLimit,
447                                        TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
448         if (!qosEosHandler.isQosClusterOwner()) {
449             LOG.debug("Not Qos Cluster Owner. Ignoring setting bandwidth limits");
450             return;
451         }
452         Uint64 dpId = getDpnForInterface(port.getUuid().getValue());
453         if (dpId.equals(Uint64.ZERO)) {
454             LOG.info("DPN ID for interface {} not found", port.getUuid().getValue());
455             return;
456         }
457
458         LOG.trace("Setting bandwidth limits {} on Port {}", port.getUuid().getValue(), bwLimit);
459         OvsdbBridgeRef bridgeRefEntry = getBridgeRefEntryFromOperDS(dpId);
460         Optional<Node> bridgeNode = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL,
461                 bridgeRefEntry.getValue().firstIdentifierOf(Node.class), dataBroker);
462         if (!bridgeNode.isPresent()) {
463             LOG.error("bridge not found for dpn {} port {} in operational datastore", dpId, port.getUuid().getValue());
464             return;
465         }
466         LOG.debug("bridgeNode {}", bridgeNode.get().getNodeId().getValue());
467
468         TerminationPoint tp = SouthboundUtils.getTerminationPointByExternalId(bridgeNode.get(),
469                 port.getUuid().getValue());
470         if (tp == null) {
471             LOG.debug("Skipping setting of bandwidth limit rules for subport {}",
472                     port.getUuid().getValue());
473             return;
474         }
475         LOG.debug("tp: {}", tp.getTpId().getValue());
476         OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
477
478         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
479         tpAugmentationBuilder.setName(ovsdbTp.getName());
480         tpAugmentationBuilder.setIngressPolicingRate(bwLimit.getMaxKbps().longValue());
481         tpAugmentationBuilder.setIngressPolicingBurst(bwLimit.getMaxBurstKbps().longValue());
482
483         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
484         tpBuilder.withKey(tp.key());
485         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
486         try {
487             if (writeConfigTxn != null) {
488                 writeConfigTxn.merge(InstanceIdentifier
489                         .create(NetworkTopology.class)
490                         .child(Topology.class, new TopologyKey(SouthboundUtils.OVSDB_TOPOLOGY_ID))
491                         .child(Node.class, bridgeNode.get().key())
492                         .child(TerminationPoint.class, new TerminationPointKey(tp.key())), tpBuilder.build(), true);
493             } else {
494                 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
495                         .create(NetworkTopology.class)
496                         .child(Topology.class, new TopologyKey(SouthboundUtils.OVSDB_TOPOLOGY_ID))
497                         .child(Node.class, bridgeNode.get().key())
498                         .child(TerminationPoint.class, new TerminationPointKey(tp.key())), tpBuilder.build());
499             }
500         } catch (Exception e) {
501             if (LOG.isDebugEnabled()) {
502                 LOG.debug("Failure while setting BwLimitRule {} to port {} exception ", bwLimit,
503                         port.getUuid().getValue(), e);
504             } else {
505                 LOG.error("Failure while setting BwLimitRule {} to port {}", bwLimit, port.getUuid().getValue());
506             }
507         }
508
509     }
510
511     public void setPortDscpMarking(Port port, DscpmarkingRules dscpMark) {
512
513         Uint64 dpnId = getDpnForInterface(port.getUuid().getValue());
514         String ifName = port.getUuid().getValue();
515
516         if (dpnId.equals(Uint64.ZERO)) {
517             LOG.info("DPN ID for interface {} not found. Cannot set dscp value {} on port {}",
518                     port.getUuid().getValue(), dscpMark, port.getUuid().getValue());
519             return;
520         }
521
522         if (!qosEosHandler.isQosClusterOwner()) {
523             qosServiceConfiguredPorts.add(port.getUuid());
524             LOG.trace("Not Qos Cluster Owner. Ignoring setting DSCP marking");
525             return;
526         } else {
527             Interface ifState = getInterfaceStateFromOperDS(ifName);
528             Short dscpValue = dscpMark.getDscpMark().toJava();
529             int ipVersions = getIpVersions(port);
530             //1. OF rules
531             if (hasIpv4Addr(ipVersions)) {
532                 LOG.trace("setting ipv4 flow for port: {}, dscp: {}", ifName, dscpValue);
533                 addFlow(dpnId, dscpValue, ifName, NwConstants.ETHTYPE_IPV4, ifState);
534             }
535             if (hasIpv6Addr(ipVersions)) {
536                 LOG.trace("setting ipv6 flow for port: {}, dscp: {}", ifName, dscpValue);
537                 addFlow(dpnId, dscpValue, ifName, NwConstants.ETHTYPE_IPV6, ifState);
538             }
539
540             if (qosServiceConfiguredPorts.add(port.getUuid())) {
541                 // bind qos service to interface
542                 bindservice(ifName);
543             }
544
545         }
546     }
547
548     public void unsetPortDscpMark(Port port) {
549
550         Uint64 dpnId = getDpnForInterface(port.getUuid().getValue());
551         String ifName = port.getUuid().getValue();
552
553         if (dpnId.equals(Uint64.ZERO)) {
554             LOG.debug("DPN ID for port {} not found. Cannot unset dscp value", port.getUuid().getValue());
555             return;
556         }
557
558         if (!qosEosHandler.isQosClusterOwner()) {
559             qosServiceConfiguredPorts.remove(port.getUuid());
560             LOG.debug("Not Qos Cluster Owner. Ignoring unsetting DSCP marking");
561             return;
562         } else {
563             LOG.trace("Removing dscp marking rule from Port {}", port.getUuid().getValue());
564             Interface intf = getInterfaceStateFromOperDS(ifName);
565             //unbind service from interface
566             unbindservice(ifName);
567             // 1. OF
568             int ipVersions = getIpVersions(port);
569             if (hasIpv4Addr(ipVersions)) {
570                 removeFlow(dpnId, ifName, NwConstants.ETHTYPE_IPV4, intf);
571             }
572             if (hasIpv6Addr(ipVersions)) {
573                 removeFlow(dpnId, ifName, NwConstants.ETHTYPE_IPV6, intf);
574             }
575             qosServiceConfiguredPorts.remove(port.getUuid());
576         }
577     }
578
579     public void unsetPortDscpMark(Port port, Interface intrf) {
580
581         Uint64 dpnId = getDpIdFromInterface(intrf);
582         String ifName = port.getUuid().getValue();
583
584         if (dpnId.equals(Uint64.ZERO)) {
585             LOG.error("Unable to retrieve DPN Id for interface {}. Cannot unset dscp value on port", ifName);
586             return;
587         }
588         if (!qosEosHandler.isQosClusterOwner()) {
589             qosServiceConfiguredPorts.remove(port.getUuid());
590             return;
591         } else {
592             LOG.trace("Removing dscp marking rule from Port {}", port.getUuid().getValue());
593             unbindservice(ifName);
594             int ipVersions = getIpVersions(port);
595             if (hasIpv4Addr(ipVersions)) {
596                 removeFlow(dpnId, ifName, NwConstants.ETHTYPE_IPV4, intrf);
597             }
598             if (hasIpv6Addr(ipVersions)) {
599                 removeFlow(dpnId, ifName, NwConstants.ETHTYPE_IPV6, intrf);
600             }
601             qosServiceConfiguredPorts.remove(port.getUuid());
602         }
603     }
604
605     private static Uint64 getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
606                                                            .interfaces.rev140508.interfaces.state.Interface ifState) {
607         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
608         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
609         Long dpIdLong = MDSALUtil.getDpnIdFromPortName(nodeConnectorId);
610         Uint64 dpnId = dpIdLong < 0 ? Uint64.ZERO : Uint64.valueOf(dpIdLong);
611         return dpnId;
612     }
613
614     public Uint64 getDpnForInterface(String ifName) {
615         Uint64 nodeId = Uint64.ZERO;
616         try {
617             GetDpidFromInterfaceInput
618                     dpIdInput = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
619             Future<RpcResult<GetDpidFromInterfaceOutput>>
620                     dpIdOutput = odlInterfaceRpcService.getDpidFromInterface(dpIdInput);
621             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
622             if (dpIdResult.isSuccessful()) {
623                 nodeId = dpIdResult.getResult().getDpid();
624             } else {
625                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
626             }
627         } catch (NullPointerException | InterruptedException | ExecutionException e) {
628             if (LOG.isDebugEnabled()) {
629                 LOG.debug("Exception when getting DPN for interface {} exception ", ifName, e);
630             } else {
631                 LOG.error("Could not retrieve DPN for interface {}", ifName);
632             }
633         }
634         return nodeId;
635     }
636
637     @Nullable
638     private BridgeEntry getBridgeEntryFromConfigDS(Uint64 dpnId) {
639         BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpnId);
640         InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier = getBridgeEntryIdentifier(bridgeEntryKey);
641         LOG.debug("Trying to retrieve bridge entry from config for Id: {}", bridgeEntryInstanceIdentifier);
642         return getBridgeEntryFromConfigDS(bridgeEntryInstanceIdentifier);
643     }
644
645     @Nullable
646     private BridgeEntry getBridgeEntryFromConfigDS(InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier) {
647         return MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, bridgeEntryInstanceIdentifier, dataBroker)
648                 .orElse(null);
649     }
650
651     @Nullable
652     private BridgeRefEntry getBridgeRefEntryFromOperDS(InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid) {
653         return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid, dataBroker).orElse(null);
654     }
655
656     @Nullable
657     private OvsdbBridgeRef getBridgeRefEntryFromOperDS(Uint64 dpId) {
658         BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpId);
659         InstanceIdentifier<BridgeRefEntry> bridgeRefEntryIid = getBridgeRefEntryIdentifier(bridgeRefEntryKey);
660         BridgeRefEntry bridgeRefEntry = getBridgeRefEntryFromOperDS(bridgeRefEntryIid);
661         if (bridgeRefEntry == null) {
662             // bridge ref entry will be null if the bridge is disconnected from controller.
663             // In that case, fetch bridge reference from bridge interface entry config DS
664             BridgeEntry bridgeEntry = getBridgeEntryFromConfigDS(dpId);
665             if (bridgeEntry == null) {
666                 return null;
667             }
668             return  bridgeEntry.getBridgeReference();
669         }
670         return bridgeRefEntry.getBridgeReference();
671     }
672
673     @NonNull
674     private static InstanceIdentifier<BridgeRefEntry> getBridgeRefEntryIdentifier(BridgeRefEntryKey bridgeRefEntryKey) {
675         return InstanceIdentifier.builder(BridgeRefInfo.class).child(BridgeRefEntry.class, bridgeRefEntryKey).build();
676     }
677
678     @NonNull
679     private static InstanceIdentifier<BridgeEntry> getBridgeEntryIdentifier(BridgeEntryKey bridgeEntryKey) {
680         return InstanceIdentifier.builder(BridgeInterfaceInfo.class).child(BridgeEntry.class, bridgeEntryKey).build();
681     }
682
683     public void removeStaleFlowEntry(Interface intrf, int ethType) {
684         List<MatchInfo> matches = new ArrayList<>();
685
686         Uint64 dpnId = getDpIdFromInterface(intrf);
687
688         Integer ifIndex = intrf.getIfIndex();
689         matches.add(new MatchMetadata(MetaDataUtil.getLportTagMetaData(ifIndex), MetaDataUtil.METADATA_MASK_LPORT_TAG));
690         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.QOS_DSCP_TABLE,
691                 getQosFlowId(NwConstants.QOS_DSCP_TABLE, dpnId, ifIndex, ethType),
692                 QosConstants.QOS_DEFAULT_FLOW_PRIORITY, "QoSRemoveFlow", 0, 0, NwConstants.COOKIE_QOS_TABLE,
693                 matches, null);
694         mdsalUtils.removeFlow(flowEntity);
695     }
696
697     public void addFlow(Uint64 dpnId, Short dscpValue, String ifName, int ethType, Interface ifState) {
698         if (ifState == null) {
699             LOG.debug("Could not find the ifState for interface {}", ifName);
700             return;
701         }
702         Integer ifIndex = ifState.getIfIndex();
703
704         List<MatchInfo> matches = new ArrayList<>();
705         matches.add(new MatchEthernetType(ethType));
706         matches.add(new MatchMetadata(MetaDataUtil.getLportTagMetaData(ifIndex), MetaDataUtil.METADATA_MASK_LPORT_TAG));
707
708         List<ActionInfo> actionsInfos = new ArrayList<>();
709         actionsInfos.add(new ActionSetFieldDscp(dscpValue));
710         actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
711
712         List<InstructionInfo> instructions = Collections.singletonList(new InstructionApplyActions(actionsInfos));
713         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.QOS_DSCP_TABLE,
714                 getQosFlowId(NwConstants.QOS_DSCP_TABLE, dpnId, ifIndex, ethType),
715                 QosConstants.QOS_DEFAULT_FLOW_PRIORITY, "QoSConfigFlow", 0, 0, NwConstants.COOKIE_QOS_TABLE,
716                 matches, instructions);
717         mdsalUtils.installFlow(flowEntity);
718     }
719
720     public void removeFlow(Uint64 dpnId, String ifName, int ethType, Interface ifState) {
721         if (ifState == null) {
722             LOG.debug("Could not find the ifState for interface {}", ifName);
723             return;
724         }
725         Integer ifIndex = ifState.getIfIndex();
726
727         mdsalUtils.removeFlow(dpnId, NwConstants.QOS_DSCP_TABLE,
728                 new FlowId(getQosFlowId(NwConstants.QOS_DSCP_TABLE, dpnId, ifIndex, ethType)));
729     }
730
731     public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
732             .@Nullable Interface getInterfaceStateFromOperDS(String interfaceName) {
733         try {
734             return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
735                     createInterfaceStateInstanceIdentifier(interfaceName)).orElse(null);
736         } catch (ExecutionException | InterruptedException e) {
737             LOG.error("getInterfaceStateFromOperDS: Exception while reading interface DS for the interface {}",
738                     interfaceName, e);
739         }
740         return null;
741     }
742
743     @NonNull
744     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
745             .ietf.interfaces.rev140508.interfaces.state.Interface> createInterfaceStateInstanceIdentifier(
746             String interfaceName) {
747         return InstanceIdentifier
748                 .builder(InterfacesState.class)
749                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
750                                 .ietf.interfaces.rev140508.interfaces.state.Interface.class,
751                         new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
752                                 .ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
753                                 interfaceName))
754                 .build();
755     }
756
757     public void bindservice(String ifName) {
758         int priority = QosConstants.QOS_DEFAULT_FLOW_PRIORITY;
759         int instructionKey = 0;
760         List<Instruction> instructions = new ArrayList<>();
761         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.QOS_DSCP_TABLE, ++instructionKey));
762         short qosServiceIndex = ServiceIndex.getIndex(NwConstants.QOS_SERVICE_NAME, NwConstants.QOS_SERVICE_INDEX);
763
764         BoundServices serviceInfo = getBoundServices(
765                 String.format("%s.%s", "qos", ifName), qosServiceIndex,
766                 priority, NwConstants.COOKIE_QOS_TABLE, instructions);
767         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
768                 buildServiceId(ifName, qosServiceIndex),
769                 serviceInfo);
770     }
771
772     public void unbindservice(String ifName) {
773         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, buildServiceId(ifName,
774                 ServiceIndex.getIndex(NwConstants.QOS_SERVICE_NAME, NwConstants.QOS_SERVICE_INDEX)));
775     }
776
777     private static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short qosServiceIndex) {
778         return InstanceIdentifier.builder(ServiceBindings.class)
779                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
780                 .child(BoundServices.class, new BoundServicesKey(qosServiceIndex)).build();
781     }
782
783     private static BoundServices getBoundServices(String serviceName, short qosServiceIndex, int priority,
784                                                   Uint64 cookieQosTable, List<Instruction> instructions) {
785         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookieQosTable)
786                 .setFlowPriority(priority).setInstruction(instructions);
787         return new BoundServicesBuilder().withKey(new BoundServicesKey(qosServiceIndex)).setServiceName(serviceName)
788                 .setServicePriority(qosServiceIndex).setServiceType(ServiceTypeFlowBased.class)
789                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
790     }
791
792     @NonNull
793     public static String getQosFlowId(short tableId, Uint64 dpId, int lportTag, int ethType) {
794         return new StringBuilder().append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(dpId)
795                 .append(NwConstants.FLOWID_SEPARATOR).append(lportTag)
796                 .append(NwConstants.FLOWID_SEPARATOR).append(ethType).toString();
797     }
798
799     public boolean portHasQosPolicy(Port port) {
800         LOG.trace("checking qos policy for port: {}", port.getUuid().getValue());
801
802         boolean isQosPolicy = port.augmentation(QosPortExtension.class) != null
803                 && port.augmentation(QosPortExtension.class).getQosPolicyId() != null;
804
805         LOG.trace("portHasQosPolicy for  port: {} return value {}", port.getUuid().getValue(), isQosPolicy);
806         return isQosPolicy;
807     }
808
809     @Nullable
810     public QosPolicy getQosPolicy(Port port) {
811         Uuid qosUuid = null;
812         QosPolicy qosPolicy = null;
813
814         if (port.augmentation(QosPortExtension.class) != null) {
815             qosUuid = port.augmentation(QosPortExtension.class).getQosPolicyId();
816         } else {
817             Network network = neutronVpnManager.getNeutronNetwork(port.getNetworkId());
818
819             if (network != null && network.augmentation(QosNetworkExtension.class) != null) {
820                 qosUuid = network.augmentation(QosNetworkExtension.class).getQosPolicyId();
821             }
822         }
823
824         if (qosUuid != null) {
825             qosPolicy = qosPolicyMap.get(qosUuid);
826         }
827
828         return qosPolicy;
829     }
830
831     public boolean hasDscpMarkingRule(QosPolicy qosPolicy) {
832         if (qosPolicy != null) {
833             return qosPolicy.getDscpmarkingRules() != null && !qosPolicy.getDscpmarkingRules().isEmpty();
834         }
835         return false;
836     }
837
838     public void addToPortCache(Port port) {
839         neutronPortMap.put(port.getUuid(), port);
840     }
841
842     public void removeFromPortCache(Port port) {
843         neutronPortMap.remove(port.getUuid());
844     }
845
846     public Port getNeutronPort(Uuid portUuid) {
847         return neutronPortMap.get(portUuid);
848     }
849
850     public Port getNeutronPort(String portName) {
851         return getNeutronPort(new Uuid(portName));
852     }
853
854     public void addToNetworkCache(Network network) {
855         neutronNetworkMap.put(network.getUuid(), network);
856     }
857
858     public void removeFromNetworkCache(Network network) {
859         neutronNetworkMap.remove(network.getUuid());
860     }
861
862     public Network getNeutronNetwork(Uuid networkUuid) {
863         return neutronNetworkMap.get(networkUuid);
864     }
865
866     @Nullable
867     public static Uint64 getDpnIdFromLowerLayerIf(String lowerLayerIf) {
868         try {
869             return Uint64.valueOf(lowerLayerIf.substring(lowerLayerIf.indexOf(":") + 1, lowerLayerIf.lastIndexOf(":")));
870         } catch (NullPointerException e) {
871             return null;
872         }
873     }
874
875     @Nullable
876     public static String getPortNumberFromLowerLayerIf(String lowerLayerIf) {
877         try {
878             return (lowerLayerIf.substring(lowerLayerIf.lastIndexOf(":") + 1));
879         } catch (NullPointerException e) {
880             return null;
881         }
882     }
883
884     public int getIpVersions(Port port) {
885         int versions = 0;
886         for (FixedIps fixedIp: port.getFixedIps()) {
887             if (fixedIp.getIpAddress().getIpv4Address() != null) {
888                 versions |= (1 << QosConstants.IPV4_ADDR_MASK_BIT);
889             } else if (fixedIp.getIpAddress().getIpv6Address() != null) {
890                 versions |= (1 << QosConstants.IPV6_ADDR_MASK_BIT);
891             }
892         }
893         return versions;
894     }
895
896     public boolean hasIpv4Addr(int versions) {
897         return (versions & (1 << QosConstants.IPV4_ADDR_MASK_BIT)) != 0;
898     }
899
900     public boolean hasIpv6Addr(int versions) {
901         return (versions & (1 << QosConstants.IPV6_ADDR_MASK_BIT)) != 0;
902     }
903
904     public boolean isBindServiceDone(Optional<Uuid> uuid) {
905         if (uuid != null) {
906             return qosServiceConfiguredPorts.contains(uuid.get());
907         }
908         return false;
909     }
910
911     public void removeInterfaceInQosConfiguredPorts(Optional<Uuid> uuid) {
912         if (uuid != null) {
913             qosServiceConfiguredPorts.remove(uuid.get());
914         }
915     }
916 }