MRI version bumpup for Aluminium
[netvirt.git] / statistics / impl / src / main / java / org / opendaylight / netvirt / statistics / StatisticsImpl.java
1 /*
2  * Copyright (c) 2017 HPE, Inc. 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.statistics;
9
10 import com.google.common.util.concurrent.CheckedFuture;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import com.google.common.util.concurrent.SettableFuture;
16 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Map.Entry;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.UUID;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.Future;
29 import org.eclipse.jdt.annotation.NonNull;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
31 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
32 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
33 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
34 import org.opendaylight.genius.mdsalutil.MDSALUtil;
35 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
36 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
37 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
38 import org.opendaylight.mdsal.binding.api.DataBroker;
39 import org.opendaylight.mdsal.binding.api.ReadTransaction;
40 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
41 import org.opendaylight.mdsal.binding.api.WriteTransaction;
42 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
43 import org.opendaylight.mdsal.common.api.ReadFailedException;
44 import org.opendaylight.netvirt.statistics.api.ICountersInterfaceChangeHandler;
45 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.AcquireElementCountersRequestHandlerInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.AcquireElementCountersRequestHandlerOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.AcquireElementCountersRequestHandlerOutputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.CleanAllElementCounterRequestsInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.CleanAllElementCounterRequestsOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.EgressElementCountersRequestConfig;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.EgressElementCountersRequestConfigBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetElementCountersByHandlerInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetElementCountersByHandlerOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetElementCountersByHandlerOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeAggregatedCountersInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeAggregatedCountersOutput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeAggregatedCountersOutputBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeConnectorCountersInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeConnectorCountersOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeConnectorCountersOutputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeCountersInput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeCountersOutput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.GetNodeCountersOutputBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.IngressElementCountersRequestConfig;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.IngressElementCountersRequestConfigBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.ReleaseElementCountersRequestHandlerInput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.ReleaseElementCountersRequestHandlerOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.StatisticsService;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.counterrequestsconfig.CounterRequests;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.counterrequestsconfig.CounterRequestsBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.counterrequestsconfig.CounterRequestsKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.elementrequestdata.Filters;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.elementrequestdata.filters.TcpFilter;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.elementrequestdata.filters.UdpFilter;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.CounterResult;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.CounterResultBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.Groups;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.GroupsBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.groups.Counters;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.statistics.rev170120.result.counterresult.groups.CountersBuilder;
102 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
103 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
104 import org.opendaylight.yangtools.yang.common.RpcResult;
105 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
106 import org.slf4j.Logger;
107 import org.slf4j.LoggerFactory;
108
109 public class StatisticsImpl implements StatisticsService, ICountersInterfaceChangeHandler {
110     private static final Logger LOG = LoggerFactory.getLogger(StatisticsImpl.class);
111     private final DataBroker db;
112     private final ManagedNewTransactionRunner txRunner;
113     private final CounterRetriever counterRetriever;
114     private final IInterfaceManager interfaceManager;
115     private final IMdsalApiManager mdsalApiManager;
116     private final IdManagerService idManagerService;
117     private final StatisticsCounters statisticsCounters;
118
119     public StatisticsImpl(DataBroker db, CounterRetriever counterRetriever, IInterfaceManager interfaceManager,
120             IMdsalApiManager mdsalApiManager, IdManagerService idManagerService,
121             StatisticsCounters statisticsCounters) {
122         this.db = db;
123         this.txRunner = new ManagedNewTransactionRunnerImpl(db);
124         this.counterRetriever = counterRetriever;
125         this.interfaceManager = interfaceManager;
126         this.mdsalApiManager = mdsalApiManager;
127         this.idManagerService = idManagerService;
128         this.statisticsCounters = statisticsCounters;
129         initializeCountrsConfigDataSrore();
130     }
131
132     @Override
133     @SuppressWarnings("checkstyle:illegalCatch")
134     public ListenableFuture<RpcResult<GetNodeCountersOutput>> getNodeCounters(GetNodeCountersInput input) {
135         BigInteger dpId = input.getNodeId();
136         LOG.trace("getting node counters for node {}", dpId);
137         GetNodeCountersOutputBuilder gncob = new GetNodeCountersOutputBuilder();
138
139         List<CounterResult> counterResults = new ArrayList<>();
140         try {
141             if (!getNodeResult(counterResults, dpId)) {
142                 statisticsCounters.failedGettingNodeCounters();
143                 return RpcResultBuilder.<GetNodeCountersOutput>failed()
144                         .withError(ErrorType.APPLICATION, "failed to get node counters for node: " + dpId)
145                         .buildFuture();
146             }
147         } catch (RuntimeException e) {
148             LOG.warn("failed to get counter result for node {}", dpId, e);
149             return RpcResultBuilder.<GetNodeCountersOutput>failed()
150                     .withError(ErrorType.APPLICATION, "failed to get node counters for node: " + dpId).buildFuture();
151         }
152
153         gncob.setCounterResult(counterResults);
154         return RpcResultBuilder.success(gncob.build()).buildFuture();
155     }
156
157     @Override
158     @SuppressWarnings("checkstyle:illegalCatch")
159     public ListenableFuture<RpcResult<GetNodeAggregatedCountersOutput>> getNodeAggregatedCounters(
160             GetNodeAggregatedCountersInput input) {
161         BigInteger dpId = input.getNodeId();
162         LOG.trace("getting aggregated node counters for node {}", dpId);
163         GetNodeAggregatedCountersOutputBuilder gnacob = new GetNodeAggregatedCountersOutputBuilder();
164
165         List<CounterResult> aggregatedCounterResults = new ArrayList<>();
166         try {
167             if (!getNodeAggregatedResult(aggregatedCounterResults, dpId)) {
168                 statisticsCounters.failedGettingAggregatedNodeCounters();
169                 return RpcResultBuilder.<GetNodeAggregatedCountersOutput>failed()
170                         .withError(ErrorType.APPLICATION, "failed to get node aggregated counters for node " + dpId)
171                         .buildFuture();
172             }
173         } catch (Exception e) {
174             LOG.warn("failed to get counter result for node {}", dpId, e);
175             return RpcResultBuilder.<GetNodeAggregatedCountersOutput>failed()
176                     .withError(ErrorType.APPLICATION, "failed to get node aggregated counters for node " + dpId)
177                     .buildFuture();
178         }
179
180         gnacob.setCounterResult(aggregatedCounterResults);
181         return RpcResultBuilder.success(gnacob.build()).buildFuture();
182     }
183
184     @Override
185     @SuppressWarnings("checkstyle:illegalCatch")
186     public ListenableFuture<RpcResult<GetNodeConnectorCountersOutput>> getNodeConnectorCounters(
187             GetNodeConnectorCountersInput input) {
188         String portId = input.getPortId();
189         LOG.trace("getting port counters of port {}", portId);
190
191         Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(db, portId);
192         if (interfaceState == null) {
193             LOG.warn("trying to get counters for non exist port {}", portId);
194             return RpcResultBuilder.<GetNodeConnectorCountersOutput>failed().buildFuture();
195         }
196
197         BigInteger dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
198         if (interfaceState.getLowerLayerIf() == null || interfaceState.getLowerLayerIf().isEmpty()) {
199             LOG.warn("Lower layer if wasn't found for port {}", portId);
200             return RpcResultBuilder.<GetNodeConnectorCountersOutput>failed().buildFuture();
201         }
202
203         String portNumber = interfaceState.getLowerLayerIf().get(0);
204         portNumber = portNumber.split(":")[2];
205         List<CounterResult> counterResults = new ArrayList<>();
206
207         try {
208             if (!getNodeConnectorResult(counterResults, dpId, portNumber)) {
209                 statisticsCounters.failedGettingNodeConnectorCounters();
210                 return RpcResultBuilder.<GetNodeConnectorCountersOutput>failed()
211                         .withError(ErrorType.APPLICATION, "failed to get port counters").buildFuture();
212             }
213         } catch (RuntimeException e) {
214             LOG.warn("failed to get counter result for port {}", portId, e);
215         }
216
217         GetNodeConnectorCountersOutputBuilder gpcob = new GetNodeConnectorCountersOutputBuilder();
218         gpcob.setCounterResult(counterResults);
219         return RpcResultBuilder.success(gpcob.build()).buildFuture();
220     }
221
222     @Override
223     public ListenableFuture<RpcResult<AcquireElementCountersRequestHandlerOutput>> acquireElementCountersRequestHandler(
224             AcquireElementCountersRequestHandlerInput input) {
225         AcquireElementCountersRequestHandlerOutputBuilder aecrhob =
226                 new AcquireElementCountersRequestHandlerOutputBuilder();
227         UUID randomNumber = UUID.randomUUID();
228         Integer intRequestKey = allocateId(randomNumber.toString());
229         if (intRequestKey == null) {
230             LOG.warn("failed generating unique request identifier");
231             statisticsCounters.failedGeneratingUniqueRequestId();
232             return RpcResultBuilder.<AcquireElementCountersRequestHandlerOutput>failed()
233                     .withError(ErrorType.APPLICATION, "failed generating unique request identifier").buildFuture();
234         }
235         String requestKey = String.valueOf(intRequestKey);
236         SettableFuture<RpcResult<AcquireElementCountersRequestHandlerOutput>> result = SettableFuture.create();
237
238         ListenableFutures.addErrorLogging(
239             txRunner.callWithNewReadWriteTransactionAndSubmit(transaction -> {
240                 if (input.getIncomingTraffic() != null) {
241                     Optional<EgressElementCountersRequestConfig> eecrcOpt =
242                             transaction.read(LogicalDatastoreType.CONFIGURATION,
243                                     CountersServiceUtils.EECRC_IDENTIFIER).get();
244                     if (!eecrcOpt.isPresent()) {
245                         LOG.warn("failed creating incoming traffic counter request data container in DB");
246                         statisticsCounters.failedCreatingEgressCounterDataConfig();
247                         result.setFuture(RpcResultBuilder.<AcquireElementCountersRequestHandlerOutput>failed()
248                                 .withError(ErrorType.APPLICATION,
249                                         "failed creating egress counter request data container in DB")
250                                 .buildFuture());
251                         return;
252                     }
253                     if (!isIdenticalCounterRequestExist(input.getPortId(),
254                             ElementCountersDirection.EGRESS.toString(),
255                             input.getIncomingTraffic().getFilters(), eecrcOpt.get().getCounterRequests())) {
256                         installCounterSpecificRules(input.getPortId(), getLportTag(input.getPortId()),
257                                 getDpn(input.getPortId()), ElementCountersDirection.EGRESS,
258                                 input.getIncomingTraffic().getFilters());
259                     }
260                     putEgressElementCounterRequestInConfig(input, ElementCountersDirection.EGRESS, transaction,
261                             requestKey, CountersServiceUtils.EECRC_IDENTIFIER, eecrcOpt, randomNumber.toString());
262
263                     aecrhob.setIncomingTrafficHandler(requestKey);
264
265                     bindCountersServiceIfUnbound(input.getPortId(), ElementCountersDirection.EGRESS);
266                 }
267
268                 if (input.getOutgoingTraffic() != null) {
269                     Optional<IngressElementCountersRequestConfig> iecrcOpt =
270                             transaction.read(LogicalDatastoreType.CONFIGURATION,
271                                     CountersServiceUtils.IECRC_IDENTIFIER).get();
272                     if (!iecrcOpt.isPresent()) {
273                         LOG.warn("failed creating outgoing traffc counter request data container in DB");
274                         statisticsCounters.failedCreatingIngressCounterDataConfig();
275                         result.setFuture(RpcResultBuilder.<AcquireElementCountersRequestHandlerOutput>failed()
276                                 .withError(ErrorType.APPLICATION,
277                                         "failed creating ingress counter request data container in DB")
278                                 .buildFuture());
279                         return;
280                     }
281                     if (!isIdenticalCounterRequestExist(input.getPortId(),
282                             ElementCountersDirection.INGRESS.toString(),
283                             input.getOutgoingTraffic().getFilters(), iecrcOpt.get().getCounterRequests())) {
284                         installCounterSpecificRules(input.getPortId(), getLportTag(input.getPortId()),
285                                 getDpn(input.getPortId()), ElementCountersDirection.INGRESS,
286                                 input.getOutgoingTraffic().getFilters());
287                     }
288                     putIngressElementCounterRequestInConfig(input, ElementCountersDirection.INGRESS, transaction,
289                             requestKey, CountersServiceUtils.IECRC_IDENTIFIER, iecrcOpt, randomNumber.toString());
290
291                     aecrhob.setIncomingTrafficHandler(requestKey);
292
293                     bindCountersServiceIfUnbound(input.getPortId(), ElementCountersDirection.INGRESS);
294
295                     result.setFuture(RpcResultBuilder.success(aecrhob.build()).buildFuture());
296                 }
297             }), LOG, "Error acquiring element counters");
298
299         return result;
300     }
301
302     @Override
303     public ListenableFuture<RpcResult<ReleaseElementCountersRequestHandlerOutput>> releaseElementCountersRequestHandler(
304             ReleaseElementCountersRequestHandlerInput input) {
305         InstanceIdentifier<CounterRequests> ingressPath =
306                 InstanceIdentifier.builder(IngressElementCountersRequestConfig.class)
307                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
308         InstanceIdentifier<CounterRequests> egressPath =
309                 InstanceIdentifier.builder(EgressElementCountersRequestConfig.class)
310                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
311
312         SettableFuture<RpcResult<ReleaseElementCountersRequestHandlerOutput>> result = SettableFuture.create();
313         ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
314             Optional<IngressElementCountersRequestConfig> iecrcOpt =
315                     tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.IECRC_IDENTIFIER).get();
316             Optional<EgressElementCountersRequestConfig> eecrcOpt =
317                     tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.EECRC_IDENTIFIER).get();
318             if (!iecrcOpt.isPresent() || !eecrcOpt.isPresent()) {
319                 LOG.warn("Couldn't read element counters config data from DB");
320                 statisticsCounters.failedReadingCounterDataFromConfig();
321                 result.setFuture(RpcResultBuilder.<ReleaseElementCountersRequestHandlerOutput>failed()
322                         .withError(ErrorType.APPLICATION, "Couldn't read element counters config data from DB")
323                         .buildFuture());
324                 return;
325             }
326             Optional<CounterRequests> ingressRequestOpt =
327                     tx.read(LogicalDatastoreType.CONFIGURATION, ingressPath).get();
328             Optional<CounterRequests> egressRequestOpt =
329                     tx.read(LogicalDatastoreType.CONFIGURATION, egressPath).get();
330             if (!ingressRequestOpt.isPresent() && !egressRequestOpt.isPresent()) {
331                 LOG.warn("Handler does not exists");
332                 statisticsCounters.unknownRequestHandler();
333                 result.setFuture(RpcResultBuilder.<ReleaseElementCountersRequestHandlerOutput>failed()
334                         .withError(ErrorType.APPLICATION, "Handler does not exists").buildFuture());
335                 return;
336             }
337             String generatedKey = null;
338             if (ingressRequestOpt.isPresent()) {
339                 handleReleaseTransaction(tx, input, ingressPath, ingressRequestOpt,
340                         iecrcOpt.get().getCounterRequests());
341                 generatedKey = ingressRequestOpt.get().getGeneratedUniqueId();
342             }
343             if (egressRequestOpt.isPresent()) {
344                 handleReleaseTransaction(tx, input, egressPath, egressRequestOpt, eecrcOpt.get().getCounterRequests());
345                 generatedKey = egressRequestOpt.get().getGeneratedUniqueId();
346             }
347             releaseId(generatedKey);
348             result.setFuture(RpcResultBuilder.<ReleaseElementCountersRequestHandlerOutput>success().buildFuture());
349         }), LOG, "Error releasing element counters");
350
351         return result;
352     }
353
354     @Override
355     public ListenableFuture<RpcResult<GetElementCountersByHandlerOutput>> getElementCountersByHandler(
356             GetElementCountersByHandlerInput input) {
357         InstanceIdentifier<CounterRequests> ingressPath =
358                 InstanceIdentifier.builder(IngressElementCountersRequestConfig.class)
359                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
360         InstanceIdentifier<CounterRequests> egressPath =
361                 InstanceIdentifier.builder(EgressElementCountersRequestConfig.class)
362                         .child(CounterRequests.class, new CounterRequestsKey(input.getHandler())).build();
363
364         ReadTransaction tx = db.newReadOnlyTransaction();
365         CheckedFuture<Optional<CounterRequests>, ReadFailedException> ingressRequestData =
366                 tx.read(LogicalDatastoreType.CONFIGURATION, ingressPath);
367         CheckedFuture<Optional<CounterRequests>, ReadFailedException> egressRequestData =
368                 tx.read(LogicalDatastoreType.CONFIGURATION, egressPath);
369         List<CounterResult> counters = new ArrayList<>();
370
371         try {
372             if (!ingressRequestData.get().isPresent() && !egressRequestData.get().isPresent()) {
373                 LOG.warn("Handler does not exists");
374                 return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
375                         .withError(ErrorType.APPLICATION, "Handler does not exists").buildFuture();
376             }
377             if (ingressRequestData.get().isPresent()) {
378                 CounterRequests ingressCounterRequest = ingressRequestData.get().get();
379                 CounterResultDataStructure ingressCounterResultDS = createElementCountersResult(ingressCounterRequest);
380                 if (ingressCounterResultDS == null) {
381                     LOG.warn("Unable to get counter results");
382                     statisticsCounters.failedGettingCounterResults();
383                     return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
384                             .withError(ErrorType.APPLICATION, "Unable to get counter results").buildFuture();
385                 }
386                 createCounterResults(counters, ingressCounterResultDS, CountersServiceUtils.INGRESS_COUNTER_RESULT_ID);
387             }
388             if (egressRequestData.get().isPresent()) {
389                 CounterRequests egressCounterRequest = egressRequestData.get().get();
390                 CounterResultDataStructure egressCounterResultDS = createElementCountersResult(egressCounterRequest);
391                 if (egressCounterResultDS == null) {
392                     LOG.warn("Unable to get counter results");
393                     statisticsCounters.failedGettingCounterResults();
394                     return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
395                             .withError(ErrorType.APPLICATION, "Unable to get counter results").buildFuture();
396                 }
397                 createCounterResults(counters, egressCounterResultDS, CountersServiceUtils.EGRESS_COUNTER_RESULT_ID);
398             }
399         } catch (InterruptedException | ExecutionException e) {
400             LOG.warn("failed to get counter request data from DB");
401             return RpcResultBuilder.<GetElementCountersByHandlerOutput>failed()
402                     .withError(ErrorType.APPLICATION, "failed to get counter request data from DB").buildFuture();
403         } finally {
404             tx.close();
405         }
406
407         GetElementCountersByHandlerOutputBuilder gecbhob = new GetElementCountersByHandlerOutputBuilder();
408         gecbhob.setCounterResult(counters);
409         return RpcResultBuilder.success(gecbhob.build()).buildFuture();
410     }
411
412     @Override
413     public void handleInterfaceRemoval(String interfaceId) {
414         CheckedFuture<Optional<IngressElementCountersRequestConfig>, ReadFailedException> iecrc;
415         CheckedFuture<Optional<EgressElementCountersRequestConfig>, ReadFailedException> eecrc;
416         try (ReadTransaction tx = db.newReadOnlyTransaction()) {
417             iecrc = tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.IECRC_IDENTIFIER);
418             eecrc = tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.EECRC_IDENTIFIER);
419         }
420
421         try {
422             Optional<IngressElementCountersRequestConfig> iecrcOpt = iecrc.get();
423             Optional<EgressElementCountersRequestConfig> eecrcOpt = eecrc.get();
424             if (!iecrcOpt.isPresent() || !eecrcOpt.isPresent()) {
425                 LOG.warn("Couldn't read element counters config data from DB");
426                 statisticsCounters.failedReadingCounterDataFromConfig();
427                 return;
428             }
429             removeAllElementCounterRequestsOnPort(interfaceId, iecrcOpt.get().getCounterRequests());
430             removeAllElementCounterRequestsOnPort(interfaceId, eecrcOpt.get().getCounterRequests());
431         } catch (InterruptedException | ExecutionException e) {
432             LOG.warn("failed to get counter request data from DB");
433             statisticsCounters.failedGettingCounterResultsPortRemoval();
434             return;
435         }
436     }
437
438     @Override
439     public ListenableFuture<RpcResult<CleanAllElementCounterRequestsOutput>> cleanAllElementCounterRequests(
440             CleanAllElementCounterRequestsInput input) {
441         ReadTransaction tx = db.newReadOnlyTransaction();
442         CheckedFuture<Optional<IngressElementCountersRequestConfig>, ReadFailedException> iecrc =
443                 tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.IECRC_IDENTIFIER);
444         CheckedFuture<Optional<EgressElementCountersRequestConfig>, ReadFailedException> eecrc =
445                 tx.read(LogicalDatastoreType.CONFIGURATION, CountersServiceUtils.EECRC_IDENTIFIER);
446         try {
447             Optional<IngressElementCountersRequestConfig> iecrcOpt = iecrc.get();
448             Optional<EgressElementCountersRequestConfig> eecrcOpt = eecrc.get();
449             if (!iecrcOpt.isPresent() || !eecrcOpt.isPresent()) {
450                 LOG.warn("Couldn't read element counters config data from DB");
451                 statisticsCounters.failedReadingCounterDataFromConfig();
452                 return RpcResultBuilder.<CleanAllElementCounterRequestsOutput>failed()
453                         .withError(ErrorType.APPLICATION, "Couldn't read element counters config data from DB")
454                         .buildFuture();
455             }
456             Set<String> idsToRelease = new HashSet<>();
457             if (input.getPortId() != null && !input.getPortId().isEmpty()) {
458                 idsToRelease
459                         .addAll(getAllPortRequestsUniqueIds(input.getPortId(), iecrcOpt.get().getCounterRequests()));
460                 idsToRelease
461                         .addAll(getAllPortRequestsUniqueIds(input.getPortId(), eecrcOpt.get().getCounterRequests()));
462                 removeAllElementCounterRequestsOnPort(input.getPortId(), iecrcOpt.get().getCounterRequests());
463                 removeAllElementCounterRequestsOnPort(input.getPortId(), eecrcOpt.get().getCounterRequests());
464             } else {
465                 idsToRelease.addAll(getAllRquestsUniqueIds(iecrcOpt.get().getCounterRequests()));
466                 idsToRelease.addAll(getAllRquestsUniqueIds(eecrcOpt.get().getCounterRequests()));
467                 removeAllElementCounterRequests(iecrcOpt.get().getCounterRequests());
468                 removeAllElementCounterRequests(eecrcOpt.get().getCounterRequests());
469             }
470             releaseIds(idsToRelease);
471         } catch (InterruptedException | ExecutionException e) {
472             LOG.warn("failed to get counter request data from DB");
473             return RpcResultBuilder.<CleanAllElementCounterRequestsOutput>failed()
474                     .withError(ErrorType.APPLICATION, "failed to get counter request data from DB").buildFuture();
475         } finally {
476             tx.close();
477         }
478         return RpcResultBuilder.<CleanAllElementCounterRequestsOutput>success().buildFuture();
479     }
480
481     private Set<String> getAllPortRequestsUniqueIds(String interfaceId, List<CounterRequests> counterRequests) {
482         Set<String> result = new HashSet<>();
483         for (CounterRequests counterRequest : counterRequests) {
484             if (counterRequest.getPortId().equals(interfaceId)) {
485                 result.add(counterRequest.getGeneratedUniqueId());
486             }
487         }
488         return result;
489     }
490
491     private Set<String> getAllRquestsUniqueIds(List<CounterRequests> counterRequests) {
492         Set<String> result = new HashSet<>();
493         for (CounterRequests counterRequest : counterRequests) {
494             result.add(counterRequest.getGeneratedUniqueId());
495         }
496         return result;
497     }
498
499     private void releaseIds(Set<String> ids) {
500         for (String id : ids) {
501             releaseId(id);
502         }
503     }
504
505     private void removeAllElementCounterRequestsOnPort(String interfaceId, List<CounterRequests> counterRequests) {
506         unbindCountersServiceIfBound(interfaceId, ElementCountersDirection.INGRESS);
507         unbindCountersServiceIfBound(interfaceId, ElementCountersDirection.EGRESS);
508         if (counterRequests != null) {
509             for (CounterRequests counterRequest : counterRequests) {
510                 if (interfaceId.equals(counterRequest.getPortId())) {
511                     countersRequestCleanup(counterRequest);
512                 }
513             }
514         }
515     }
516
517     private void removeAllElementCounterRequests(List<CounterRequests> counterRequests) {
518         for (CounterRequests counterRequest : counterRequests) {
519             unbindCountersServiceIfBound(counterRequest.getPortId(), ElementCountersDirection.INGRESS);
520             unbindCountersServiceIfBound(counterRequest.getPortId(), ElementCountersDirection.EGRESS);
521             countersRequestCleanup(counterRequest);
522         }
523     }
524
525     private void countersRequestCleanup(CounterRequests counterRequest) {
526         ElementCountersDirection direction = ElementCountersDirection.valueOf(counterRequest.getTrafficDirection());
527         deleteCounterSpecificRules(counterRequest.getPortId(), counterRequest.getLportTag(), counterRequest.getDpn(),
528                 direction, counterRequest.getFilters());
529         deleteCounterRequest(counterRequest, direction);
530     }
531
532     private void deleteCounterSpecificRules(String portId, int lportTag, BigInteger dpn,
533             ElementCountersDirection direction, Filters filters) {
534         List<ElementCountersRequest> ecrList = createElementCounterRequest(portId, lportTag, dpn, direction, filters);
535         for (ElementCountersRequest ecr : ecrList) {
536             if (ElementCountersDirection.INGRESS.equals(ecr.getDirection())) {
537                 IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
538                 icsi.deleteCounterRules(ecr);
539             } else if (ElementCountersDirection.EGRESS.equals(ecr.getDirection())) {
540                 EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
541                 ecsi.deleteCounterRules(ecr);
542             }
543         }
544     }
545
546     private void deleteCounterRequest(CounterRequests counterRequest, ElementCountersDirection direction) {
547         ListenableFutures.addErrorLogging(
548             txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
549                 if (ElementCountersDirection.INGRESS.equals(direction)) {
550                     tx.delete(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
551                             .builder(IngressElementCountersRequestConfig.class)
552                             .child(CounterRequests.class,
553                                     new CounterRequestsKey(counterRequest.key().getRequestId()))
554                             .build());
555                 } else if (ElementCountersDirection.EGRESS.equals(direction)) {
556                     tx.delete(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
557                             .builder(EgressElementCountersRequestConfig.class)
558                             .child(CounterRequests.class,
559                                     new CounterRequestsKey(counterRequest.key().getRequestId()))
560                             .build());
561                 }
562             }), LOG, "Error deleting counter");
563     }
564
565     private CounterResultDataStructure createElementCountersResult(CounterRequests counterRequest) {
566         ElementCountersRequest ecr =
567                 createElementCounterRequest(counterRequest.getPortId(), counterRequest.getLportTag(),
568                         counterRequest.getDpn(), ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()),
569                         counterRequest.getFilters()).iterator().next();
570         BigInteger dpId = getDpn(ecr.getPortId());
571         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ecr.getPortId());
572         if (interfaceInfo == null) {
573             return null;
574         }
575         int lportTag = interfaceInfo.getInterfaceTag();
576         List<MatchInfoBase> matches = CountersServiceUtils.getCounterFlowMatch(ecr, lportTag,
577                 ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()));
578         Match match = MDSALUtil.buildMatches(matches);
579         return counterRetriever.getSwitchFlowCountersDirect(dpId, match);
580     }
581
582     private void initializeCountrsConfigDataSrore() {
583         ListenableFutures.addErrorLogging(
584             txRunner.callWithNewReadWriteTransactionAndSubmit(transaction -> {
585                 Optional<IngressElementCountersRequestConfig> iecrcOpt =
586                         transaction.read(LogicalDatastoreType.CONFIGURATION,
587                                 CountersServiceUtils.IECRC_IDENTIFIER).get();
588                 Optional<EgressElementCountersRequestConfig> eecrcOpt =
589                         transaction.read(LogicalDatastoreType.CONFIGURATION,
590                                 CountersServiceUtils.EECRC_IDENTIFIER).get();
591                 if (!iecrcOpt.isPresent()) {
592                     creatIngressEelementCountersContainerInConfig(transaction,
593                             CountersServiceUtils.IECRC_IDENTIFIER);
594                 }
595                 if (!eecrcOpt.isPresent()) {
596                     creatEgressEelementCountersContainerInConfig(transaction,
597                             CountersServiceUtils.EECRC_IDENTIFIER);
598                 }
599             }), LOG, "Failed to create counters in config datastore");
600     }
601
602     private void handleReleaseTransaction(WriteTransaction transaction, ReleaseElementCountersRequestHandlerInput input,
603             InstanceIdentifier<CounterRequests> path, Optional<CounterRequests> requestData,
604             List<CounterRequests> counterRequests) {
605         transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
606         CounterRequests counterRequest = requestData.get();
607         if (shouldUnbindCountersService(counterRequest.getPortId(), counterRequest.key().getRequestId(),
608                 counterRequests)) {
609             unbindCountersServiceIfBound(counterRequest.getPortId(),
610                     ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()));
611         }
612         if (!isIdenticalCounterRequestExist(input.getHandler(), counterRequest.getPortId(),
613                 counterRequest.getTrafficDirection(), counterRequest.getFilters(), counterRequests)) {
614             deleteCounterSpecificRules(counterRequest.getPortId(), counterRequest.getLportTag(),
615                     counterRequest.getDpn(), ElementCountersDirection.valueOf(counterRequest.getTrafficDirection()),
616                     counterRequest.getFilters());
617         }
618     }
619
620     private boolean getNodeConnectorResult(List<CounterResult> counters, BigInteger dpId, String portNumber) {
621         CounterResultDataStructure counterResultDS =
622                 counterRetriever.getNodeConnectorCountersDirect(new NodeId(CountersUtils.getNodeId(dpId)),
623                         new NodeConnectorId(CountersUtils.getNodeConnectorId(dpId, portNumber)));
624         if (counterResultDS == null) {
625             return false;
626         }
627
628         CounterResultBuilder crb = new CounterResultBuilder();
629         String resultId = CountersUtils.getNodeConnectorId(dpId, portNumber);
630         crb.setId(resultId);
631
632         createGroups(counters, counterResultDS, crb, resultId);
633
634         return !counters.isEmpty();
635     }
636
637     private boolean getNodeResult(List<CounterResult> counters, BigInteger dpId) {
638         InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
639                 .child(Node.class, new NodeKey(new NodeId(CountersUtils.getNodeId(dpId)))).build();
640         Optional<Node> nodeOptional = MDSALUtil.read(db, LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier);
641         if (!nodeOptional.isPresent()) {
642             return false;
643         }
644
645         Node node = nodeOptional.get();
646         CounterResultDataStructure counterResultDS = counterRetriever.getNodeCountersDirect(node);
647         if (counterResultDS == null) {
648             return false;
649         }
650
651         createCounterResults(counters, counterResultDS);
652
653         return !counters.isEmpty();
654     }
655
656     private boolean getNodeAggregatedResult(List<CounterResult> aggregatedCounters, BigInteger dpId) {
657         InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class)
658                 .child(Node.class, new NodeKey(new NodeId(CountersUtils.getNodeId(dpId)))).build();
659         Optional<Node> nodeOptional = MDSALUtil.read(db, LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier);
660         if (!nodeOptional.isPresent()) {
661             return false;
662         }
663
664         Node node = nodeOptional.get();
665         CounterResultDataStructure counters = counterRetriever.getNodeCountersDirect(node);
666         if (counters == null || counters.isEmpty()) {
667             return false;
668         }
669
670         CounterResultDataStructure aggregatedResultsDS =
671                 CountersUtils.aggregateCounters(counters, CountersUtils.getNodeId(dpId));
672         createCounterResults(aggregatedCounters, aggregatedResultsDS);
673         return !aggregatedCounters.isEmpty();
674
675     }
676
677     private void createCounterResults(List<CounterResult> counters, CounterResultDataStructure counterResultDS) {
678         for (String counterResultId : counterResultDS.getResults().keySet()) {
679             CounterResultBuilder crb = new CounterResultBuilder();
680             crb.setId(counterResultId);
681             createGroups(counters, counterResultDS, crb, counterResultId);
682         }
683     }
684
685     private void createCounterResults(List<CounterResult> counters, CounterResultDataStructure counterResultDS,
686             String resultId) {
687         for (String counterResultId : counterResultDS.getResults().keySet()) {
688             CounterResultBuilder crb = new CounterResultBuilder();
689             crb.setId(resultId);
690             createGroups(counters, counterResultDS, crb, counterResultId);
691         }
692     }
693
694     private void createGroups(List<CounterResult> counters, CounterResultDataStructure counterResultDS,
695             CounterResultBuilder crb, String resultId) {
696         List<Groups> groups = new ArrayList<>();
697         Map<String, Map<String, BigInteger>> counterGroups = counterResultDS.getGroups(resultId);
698         if (counterGroups != null && !counterGroups.isEmpty()) {
699             for (Entry<String, Map<String, BigInteger>> entry : counterGroups.entrySet()) {
700                 String groupName = entry.getKey();
701                 groups.add(createGroupsResult(groupName, entry.getValue()));
702             }
703             crb.setGroups(groups);
704             counters.add(crb.build());
705         }
706     }
707
708     private Groups createGroupsResult(String groupName, Map<String, BigInteger> countersMap) {
709         GroupsBuilder gb = new GroupsBuilder();
710         gb.setName(groupName);
711
712         Map<String, Counters> counters = new HashMap<>();
713         List<Counters> countersList = new ArrayList<>();
714         for (String counterName : countersMap.keySet()) {
715             addCountersToMap(countersMap, counters, counterName);
716         }
717         for (Counters counter : counters.values()) {
718             countersList.add(counter);
719         }
720
721         gb.setCounters(countersList);
722         return gb.build();
723     }
724
725     private Counters buildCounter(String counterName, BigInteger value, Counters prevCounter) {
726         BigInteger prevValue = BigInteger.ZERO;
727         if (prevCounter != null) {
728             prevValue = prevCounter.getValue();
729         }
730         CountersBuilder cb = new CountersBuilder();
731         cb.setName(counterName);
732         cb.setValue(value.add(prevValue));
733         return cb.build();
734     }
735
736     private void addCountersToMap(Map<String, BigInteger> result, Map<String, Counters> counters, String counterName) {
737         counters.put(counterName, buildCounter(counterName, result.get(counterName), counters.get(counterName)));
738     }
739
740     private void addElementCounterRequest(List<ElementCountersRequest> ecrList, String portId, int lportTag,
741             BigInteger dpn, ElementCountersDirection direction, Filters filters) {
742         ElementCountersRequest ecr = new ElementCountersRequest(portId);
743         ecr.setLportTag(lportTag);
744         ecr.setDpn(dpn);
745         ecr.setElementCountersDirection(direction);
746         if (filters.getIpFilter() != null) {
747             String ip = filters.getIpFilter().getIp();
748             if (ip != null) {
749                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_IP_FILTER_GROUP_NAME,
750                         CountersUtils.IP_FILTER_NAME, ip);
751             }
752         }
753
754         boolean isTcpPortExist = false;
755         if (filters.getTcpFilter() != null && filters.getTcpFilter().isOn()) {
756             TcpFilter tcpFilter = filters.getTcpFilter();
757             int srcPort = tcpFilter.getSrcPort();
758             int dstPort = tcpFilter.getDstPort();
759             if (srcPort != -1) {
760                 isTcpPortExist = true;
761                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
762                         CountersUtils.TCP_SRC_PORT_FILTER_NAME, String.valueOf(srcPort));
763             }
764             if (dstPort != -1) {
765                 isTcpPortExist = true;
766                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
767                         CountersUtils.TCP_DST_PORT_FILTER_NAME, String.valueOf(dstPort));
768             }
769             if (!isTcpPortExist) {
770                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_TCP_FILTER_GROUP_NAME,
771                         CountersUtils.TCP_FILTER_NAME, "");
772             }
773
774         } else if (filters.getUdpFilter() != null && filters.getUdpFilter().isOn()) {
775             UdpFilter udpFilter = filters.getUdpFilter();
776             int srcPort = udpFilter.getSrcPort();
777             int dstPort = udpFilter.getDstPort();
778             if (srcPort != -1) {
779                 isTcpPortExist = true;
780                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
781                         CountersUtils.UDP_SRC_PORT_FILTER_NAME, String.valueOf(srcPort));
782             }
783             if (dstPort != -1) {
784                 isTcpPortExist = true;
785                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
786                         CountersUtils.UDP_DST_PORT_FILTER_NAME, String.valueOf(dstPort));
787             }
788             if (!isTcpPortExist) {
789                 ecr.addFilterToFilterGroup(CountersUtils.ELEMENT_COUNTERS_UDP_FILTER_GROUP_NAME,
790                         CountersUtils.UDP_FILTER_NAME, "");
791             }
792         }
793
794         if (!ecr.getFilters().isEmpty()) {
795             ecrList.add(ecr);
796         }
797     }
798
799     @SuppressFBWarnings("SLF4J_FORMAT_SHOULD_BE_CONST")
800     private void logElementCounterRequests(List<ElementCountersRequest> ecrList) {
801         for (ElementCountersRequest counterRequest : ecrList) {
802             LOG.debug(counterRequest.toString());
803         }
804     }
805
806     private void bindCountersServiceIfUnbound(String interfaceId, ElementCountersDirection direction) {
807         if (ElementCountersDirection.INGRESS.equals(direction) && !interfaceManager.isServiceBoundOnInterfaceForIngress(
808                 CountersServiceUtils.INGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
809             IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
810             icsi.bindService(interfaceId);
811             statisticsCounters.ingressCountersServiceBind();
812         } else if (ElementCountersDirection.EGRESS.equals(direction) && !interfaceManager
813                 .isServiceBoundOnInterfaceForEgress(CountersServiceUtils.EGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
814             EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
815             ecsi.bindService(interfaceId);
816             statisticsCounters.egressCountersServiceBind();
817         }
818     }
819
820     private void unbindCountersServiceIfBound(String interfaceId, ElementCountersDirection direction) {
821         if (ElementCountersDirection.INGRESS.equals(direction) && interfaceManager.isServiceBoundOnInterfaceForIngress(
822                 CountersServiceUtils.INGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
823             IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
824             icsi.unBindService(interfaceId);
825             statisticsCounters.ingressCountersServiceUnbind();
826         } else if (ElementCountersDirection.EGRESS.equals(direction) && interfaceManager
827                 .isServiceBoundOnInterfaceForEgress(CountersServiceUtils.EGRESS_COUNTERS_SERVICE_INDEX, interfaceId)) {
828             EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
829             ecsi.unBindService(interfaceId);
830             statisticsCounters.egressCountersServiceUnbind();
831         }
832     }
833
834     private boolean shouldUnbindCountersService(String portId, String requesId, List<CounterRequests> counterRequests) {
835         for (CounterRequests counterRequest : counterRequests) {
836             if (portId.equals(counterRequest.getPortId()) && !requesId.equals(counterRequest.key().getRequestId())) {
837                 return false;
838             }
839         }
840         return true;
841     }
842
843     private void installCounterSpecificRules(String portId, int lportTag, BigInteger dpn,
844             ElementCountersDirection direction, Filters filters) {
845         List<ElementCountersRequest> ecrList = createElementCounterRequest(portId, lportTag, dpn, direction, filters);
846         for (ElementCountersRequest ecr : ecrList) {
847             if (ElementCountersDirection.INGRESS.equals(ecr.getDirection())) {
848                 IngressCountersServiceImpl icsi = new IngressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
849                 icsi.installCounterRules(ecr);
850             } else if (ElementCountersDirection.EGRESS.equals(ecr.getDirection())) {
851                 EgressCountersServiceImpl ecsi = new EgressCountersServiceImpl(db, interfaceManager, mdsalApiManager);
852                 ecsi.installCounterRules(ecr);
853             }
854         }
855     }
856
857     private boolean areFiltersEqual(Filters filterGroup1, Filters filterGroup2) {
858         if (filterGroup1 == null && filterGroup2 == null) {
859             return true;
860         }
861         if (filterGroup1 == null || filterGroup2 == null) {
862             return false;
863         }
864
865         return filterGroup1.toString().equals(filterGroup2.toString());
866     }
867
868     private void putIngressElementCounterRequestInConfig(AcquireElementCountersRequestHandlerInput input,
869             ElementCountersDirection direcion, ReadWriteTransaction transaction, String requestKey,
870             InstanceIdentifier<IngressElementCountersRequestConfig> ecrcIdentifier,
871             Optional<IngressElementCountersRequestConfig> iecrcOpt, String generatedUniqueId) {
872         IngressElementCountersRequestConfig requestConfig = iecrcOpt.get();
873         CounterRequestsBuilder crb = new CounterRequestsBuilder();
874         crb.setRequestId(requestKey);
875         crb.withKey(new CounterRequestsKey(requestKey));
876         crb.setFilters(input.getOutgoingTraffic().getFilters());
877         crb.setPortId(input.getPortId());
878         crb.setLportTag(getLportTag(input.getPortId()));
879         crb.setDpn(getDpn(input.getPortId()));
880         crb.setTrafficDirection(direcion.toString());
881         crb.setGeneratedUniqueId(generatedUniqueId);
882         List<CounterRequests> counterRequests = requestConfig.getCounterRequests();
883         counterRequests.add(crb.build());
884
885         IngressElementCountersRequestConfigBuilder ecrcb = new IngressElementCountersRequestConfigBuilder();
886         ecrcb.setCounterRequests(counterRequests);
887         requestConfig = ecrcb.build();
888         transaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, requestConfig);
889     }
890
891     private void putEgressElementCounterRequestInConfig(AcquireElementCountersRequestHandlerInput input,
892             ElementCountersDirection direcion, ReadWriteTransaction transaction, String requestKey,
893             InstanceIdentifier<EgressElementCountersRequestConfig> ecrcIdentifier,
894             Optional<EgressElementCountersRequestConfig> eecrcOpt, String generatedUniqueId) {
895         EgressElementCountersRequestConfig requestConfig = eecrcOpt.get();
896         CounterRequestsBuilder crb = new CounterRequestsBuilder();
897         crb.setRequestId(requestKey);
898         crb.withKey(new CounterRequestsKey(requestKey));
899         crb.setFilters(input.getIncomingTraffic().getFilters());
900         crb.setPortId(input.getPortId());
901         crb.setLportTag(getLportTag(input.getPortId()));
902         crb.setDpn(getDpn(input.getPortId()));
903         crb.setTrafficDirection(direcion.toString());
904         crb.setGeneratedUniqueId(generatedUniqueId);
905         List<CounterRequests> counterRequests = requestConfig.getCounterRequests();
906         counterRequests.add(crb.build());
907
908         EgressElementCountersRequestConfigBuilder ecrcb = new EgressElementCountersRequestConfigBuilder();
909         ecrcb.setCounterRequests(counterRequests);
910         requestConfig = ecrcb.build();
911         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, requestConfig);
912     }
913
914     private void creatIngressEelementCountersContainerInConfig(ReadWriteTransaction transaction,
915             InstanceIdentifier<IngressElementCountersRequestConfig> ecrcIdentifier) {
916         IngressElementCountersRequestConfigBuilder iecrcb = new IngressElementCountersRequestConfigBuilder();
917         List<CounterRequests> counterRequests = new ArrayList<>();
918         iecrcb.setCounterRequests(counterRequests);
919         IngressElementCountersRequestConfig iecrc = iecrcb.build();
920         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, iecrc);
921     }
922
923     private void creatEgressEelementCountersContainerInConfig(ReadWriteTransaction transaction,
924             InstanceIdentifier<EgressElementCountersRequestConfig> ecrcIdentifier) {
925         EgressElementCountersRequestConfigBuilder eecrcb = new EgressElementCountersRequestConfigBuilder();
926         List<CounterRequests> counterRequests = new ArrayList<>();
927         eecrcb.setCounterRequests(counterRequests);
928         EgressElementCountersRequestConfig eecrc = eecrcb.build();
929         transaction.put(LogicalDatastoreType.CONFIGURATION, ecrcIdentifier, eecrc);
930     }
931
932     private Integer allocateId(String idKey) {
933         createIdPool();
934         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(CountersServiceUtils.COUNTERS_PULL_NAME)
935                 .setIdKey(idKey).build();
936         try {
937             Future<RpcResult<AllocateIdOutput>> result = idManagerService.allocateId(getIdInput);
938             RpcResult<AllocateIdOutput> rpcResult = result.get();
939             if (rpcResult.isSuccessful()) {
940                 return rpcResult.getResult().getIdValue().intValue();
941             } else {
942                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
943             }
944         } catch (InterruptedException | ExecutionException e) {
945             LOG.warn("Exception when getting Unique Id", e);
946         }
947         return null;
948     }
949
950     private void createIdPool() {
951         if (checkPoolExists()) {
952             return;
953         }
954         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
955                 .setPoolName(CountersServiceUtils.COUNTERS_PULL_NAME).setLow(CountersServiceUtils.COUNTERS_PULL_START)
956                 .setHigh(CountersServiceUtils.COUNTERS_PULL_START + CountersServiceUtils.COUNTERS_PULL_END).build();
957         ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManagerService.createIdPool(createPool);
958         Futures.addCallback(result, new FutureCallback<RpcResult<CreateIdPoolOutput>>() {
959
960             @Override
961             public void onFailure(Throwable error) {
962                 LOG.error("Failed to create idPool for Aliveness Monitor Service", error);
963             }
964
965             @Override
966             public void onSuccess(@NonNull RpcResult<CreateIdPoolOutput> rpcResult) {
967                 if (rpcResult.isSuccessful()) {
968                     LOG.debug("Created IdPool for tap");
969                 } else {
970                     LOG.error("RPC to create Idpool failed {}", rpcResult.getErrors());
971                 }
972             }
973         }, MoreExecutors.directExecutor());
974     }
975
976     private void releaseId(String idKey) {
977         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(CountersServiceUtils.COUNTERS_PULL_NAME)
978                 .setIdKey(idKey).build();
979         try {
980             RpcResult<ReleaseIdOutput> rpcResult = idManagerService.releaseId(idInput).get();
981             if (!rpcResult.isSuccessful()) {
982                 LOG.warn("RPC Call to release Id with Key {} returned with Errors {}", idKey, rpcResult.getErrors());
983             }
984         } catch (InterruptedException | ExecutionException e) {
985             LOG.warn("Exception when releasing Id for key {}", idKey, e);
986         }
987     }
988
989     private boolean checkPoolExists() {
990         ReadTransaction roTransaction = db.newReadOnlyTransaction();
991         InstanceIdentifier<IdPool> path = InstanceIdentifier.create(IdPools.class).child(IdPool.class,
992                 new IdPoolKey(CountersServiceUtils.COUNTERS_PULL_NAME));
993         CheckedFuture<Optional<IdPool>, ReadFailedException> pool =
994                 roTransaction.read(LogicalDatastoreType.CONFIGURATION, path);
995         try {
996             Optional<IdPool> poolOpt = pool.get();
997             if (poolOpt.isPresent()) {
998                 return true;
999             }
1000         } catch (InterruptedException | ExecutionException e) {
1001             return false;
1002         } finally {
1003             roTransaction.close();
1004         }
1005         return false;
1006     }
1007
1008     private boolean isIdenticalCounterRequestExist(String portId, String dirction, Filters filters,
1009             List<CounterRequests> counterRequests) {
1010         if (counterRequests.isEmpty()) {
1011             return false;
1012         }
1013
1014         for (CounterRequests counterRequest : counterRequests) {
1015             if (portId.equals(counterRequest.getPortId()) && dirction.equals(counterRequest.getTrafficDirection())) {
1016                 if (areFiltersEqual(filters, counterRequest.getFilters())) {
1017                     return true;
1018                 }
1019             }
1020         }
1021         return false;
1022     }
1023
1024     private boolean isIdenticalCounterRequestExist(String requesId, String portId, String dirction, Filters filters,
1025             List<CounterRequests> counterRequests) {
1026         if (counterRequests.isEmpty()) {
1027             return false;
1028         }
1029
1030         for (CounterRequests counterRequest : counterRequests) {
1031             if (portId.equals(counterRequest.getPortId()) && dirction.equals(counterRequest.getTrafficDirection())
1032                     && !counterRequest.key().getRequestId().equals(requesId)) {
1033                 if (areFiltersEqual(filters, counterRequest.getFilters())) {
1034                     return true;
1035                 }
1036             }
1037         }
1038         return false;
1039     }
1040
1041     private int getLportTag(String interfaceId) {
1042         return interfaceManager.getInterfaceInfo(interfaceId).getInterfaceTag();
1043     }
1044
1045     private BigInteger getDpn(String interfaceId) {
1046         return interfaceManager.getDpnForInterface(interfaceId);
1047     }
1048
1049     private List<ElementCountersRequest> createElementCounterRequest(String portId, int lportTag, BigInteger dpn,
1050             ElementCountersDirection direcrtion, Filters filters) {
1051         List<ElementCountersRequest> ecrList = new ArrayList<>();
1052         LOG.debug("getting element counters for port {}", portId);
1053         addElementCounterRequest(ecrList, portId, lportTag, dpn, direcrtion, filters);
1054
1055         logElementCounterRequests(ecrList);
1056
1057         return ecrList;
1058     }
1059 }