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