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