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