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