2 * Copyright (c) 2019 PANTHEON.tech.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package io.fd.hc2vpp.v3po.notification;
19 import com.google.common.collect.Lists;
20 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
21 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
22 import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceCacheStatisticsDumpManager;
23 import io.fd.honeycomb.notification.ManagedNotificationProducer;
24 import io.fd.honeycomb.notification.NotificationCollector;
25 import io.fd.vpp.jvpp.VppBaseCallException;
26 import io.fd.vpp.jvpp.VppCallbackException;
27 import io.fd.vpp.jvpp.core.callback.VnetPerInterfaceCombinedCountersCallback;
28 import io.fd.vpp.jvpp.core.dto.VnetPerInterfaceCombinedCounters;
29 import io.fd.vpp.jvpp.core.dto.WantPerInterfaceCombinedStats;
30 import io.fd.vpp.jvpp.core.dto.WantPerInterfaceCombinedStatsReply;
31 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
32 import java.math.BigInteger;
33 import java.time.LocalDateTime;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Optional;
37 import java.util.concurrent.CompletionStage;
38 import java.util.concurrent.TimeoutException;
39 import javax.annotation.Nonnull;
40 import javax.annotation.Nullable;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181128.InterfaceStatisticsChange;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev181128.InterfaceStatisticsChangeBuilder;
44 import org.opendaylight.yangtools.yang.binding.Notification;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class StatisticsChangeNotificationProducer implements ManagedNotificationProducer, JvppReplyConsumer,
51 private static final Logger LOG = LoggerFactory.getLogger(StatisticsChangeNotificationProducer.class);
53 private final FutureJVppCore jvpp;
54 private InterfaceCacheStatisticsDumpManager ifcStatDumpManager;
57 private AutoCloseable notificationListenerReg;
59 public StatisticsChangeNotificationProducer(final FutureJVppCore jvpp,
60 final InterfaceCacheStatisticsDumpManager ifcStatDumpManager) {
63 this.ifcStatDumpManager = ifcStatDumpManager;
67 public void start(@Nonnull final NotificationCollector collector) {
68 LOG.trace("Starting statistics notifications");
70 notificationListenerReg = jvpp.getEventRegistry().registerVnetPerInterfaceCombinedCountersCallback(
71 new VnetPerInterfaceCombinedCountersCallback() {
73 public void onVnetPerInterfaceCombinedCounters(
74 final VnetPerInterfaceCombinedCounters vnetPerInterfaceCombinedCounters) {
75 LOG.trace("Statistics notification received: {}", vnetPerInterfaceCombinedCounters);
77 ifcStatDumpManager.setStatisticsData(vnetPerInterfaceCombinedCounters, LocalDateTime.now(),
78 vnetPerInterfaceCombinedCounters.data[0].swIfIndex);
79 collector.onNotification(transformNotification(vnetPerInterfaceCombinedCounters));
81 } catch (Exception e) {
82 // There is no need to propagate exception to jvpp rx thread in case of unexpected failures.
83 // We can't do much about it, so lets log the exception.
84 LOG.warn("Failed to process statistics notification {}", vnetPerInterfaceCombinedCounters,
90 public void onError(final VppCallbackException e) {
91 LOG.warn("Statistics notification error received.", e);
97 private Notification transformNotification(final VnetPerInterfaceCombinedCounters reading) {
99 InterfaceStatisticsChangeBuilder builder = new InterfaceStatisticsChangeBuilder();
100 if (reading.data.length > 0) {
101 builder.setInBroadcastPkts(new Counter64(BigInteger.valueOf(reading.data[0].rxBroadcastPackets)))
102 .setOutBroadcastPkts(new Counter64(BigInteger.valueOf(reading.data[0].txBroadcastPackets)))
103 .setInMulticastPkts(new Counter64(BigInteger.valueOf(reading.data[0].rxMulticastPackets)))
104 .setOutMulticastPkts(new Counter64(BigInteger.valueOf(reading.data[0].txMulticastPackets)))
105 .setInOctets(new Counter64(BigInteger.valueOf(reading.data[0].rxBytes)))
106 .setOutOctets(new Counter64(BigInteger.valueOf(reading.data[0].txBytes)));
108 return builder.build();
113 LOG.trace("Stopping statistics notifications");
114 disableIfcNotifications(ifcStatDumpManager.getEnabledInterfaces());
115 ifcStatDumpManager.disableAll();
116 LOG.debug("Statistics notifications stopped successfully");
118 if (notificationListenerReg != null) {
119 notificationListenerReg.close();
121 } catch (Exception e) {
122 LOG.warn("Unable to properly close notification registration: {}", notificationListenerReg, e);
128 public Collection<Class<? extends Notification>> getNotificationTypes() {
129 final ArrayList<Class<? extends Notification>> classes = Lists.newArrayList();
130 classes.add(InterfaceStatisticsChange.class);
135 public void close() throws Exception {
136 LOG.trace("Closing statistics notifications producer");
140 private void disableIfcNotifications(final int[] swIfIndexes) {
141 if (swIfIndexes.length == 0) {
144 WantPerInterfaceCombinedStats request = new WantPerInterfaceCombinedStats();
145 request.num = swIfIndexes.length;
146 request.enableDisable = BYTE_FALSE;
148 request.swIfs = Optional.of(swIfIndexes).orElse(new int[]{});
149 final CompletionStage<WantPerInterfaceCombinedStatsReply> result =
150 this.jvpp.wantPerInterfaceCombinedStats(request);
152 getReply(result.toCompletableFuture());
153 } catch (VppBaseCallException | TimeoutException e) {
154 LOG.warn("Unable to disable statistics notifications", e);
155 throw new IllegalStateException("Unable to disable statistics notifications", e);