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