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