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