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