blob: 827b5522be9e8bb7276341a7aedc4fd34e58b31e [file] [log] [blame]
Daniele Moro94660a02019-12-02 12:02:07 -08001/*
2 * Copyright 2019-present Open Networking Foundation
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package org.opencord.bng;
18
19import com.google.common.collect.Maps;
20import org.onlab.util.SharedScheduledExecutors;
21import org.onlab.util.Tools;
22import org.onosproject.cfg.ComponentConfigService;
23import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
25import org.onosproject.event.AbstractListenerManager;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.behaviour.BngProgrammable;
28import org.onosproject.net.device.DeviceService;
29import org.onosproject.net.pi.runtime.PiCounterCellData;
30import org.osgi.service.component.ComponentContext;
31import org.osgi.service.component.annotations.Activate;
32import org.osgi.service.component.annotations.Component;
33import org.osgi.service.component.annotations.Deactivate;
34import org.osgi.service.component.annotations.Modified;
35import org.osgi.service.component.annotations.Reference;
36import org.osgi.service.component.annotations.ReferenceCardinality;
37import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.util.Dictionary;
41import java.util.Map;
42import java.util.Properties;
43import java.util.concurrent.ScheduledFuture;
44import java.util.concurrent.TimeUnit;
45
46import static org.opencord.bng.OsgiPropertyConstants.BNG_STATISTICS_PROBE_RATE;
47import static org.opencord.bng.OsgiPropertyConstants.BNG_STATISTICS_PROBE_RATE_DEFAULT;
48
49@Component(immediate = true,
50 service = BngStatsService.class,
51 property = {
52 BNG_STATISTICS_PROBE_RATE + ":Long=" + BNG_STATISTICS_PROBE_RATE_DEFAULT,
53 }
54)
55public class BngStatsManager
56 extends AbstractListenerManager<BngStatsEvent, BngStatsEventListener> implements BngStatsService {
57
58 private final Logger log = LoggerFactory.getLogger(getClass());
59 private final BngStatisticsMonitor bngStatsMonitor = new BngStatisticsMonitor();
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY)
62 protected ComponentConfigService componentConfigService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY)
65 protected BngService bngService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY)
68 protected DeviceService deviceService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY)
71 protected CoreService coreService;
72
73 private ApplicationId appId;
74 /**
75 * The BNG statistics probe rate.
76 */
77 private long bngStatisticsProbeRate = BNG_STATISTICS_PROBE_RATE_DEFAULT;
78 private ScheduledFuture<?> timeout;
79
80 @Activate
81 protected void activate() {
82 eventDispatcher.addSink(BngStatsEvent.class, listenerRegistry);
83 componentConfigService.registerProperties(getClass());
84 appId = coreService.getAppId(BngManager.BNG_APP);
85 start();
86 log.info("BNG Statistics manager activated");
87 }
88
89 @Modified
90 protected void modified(ComponentContext context) {
91 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
92 Long probeRate = Tools.getLongProperty(properties, BNG_STATISTICS_PROBE_RATE);
93 if (probeRate != null) {
94 bngStatisticsProbeRate = probeRate;
95 }
96 }
97
98 @Deactivate
99 protected void deactivate() {
100 shutdown();
101 componentConfigService.unregisterProperties(getClass(), false);
102 eventDispatcher.removeSink(BngStatsEvent.class);
103 log.info("BNG Statistics manager deactivated");
104
105 }
106
107 /**
108 * Starts the BNG statistics monitor. Does nothing if the monitor is already
109 * running.
110 */
111 private void start() {
112 synchronized (bngStatsMonitor) {
113 if (timeout == null) {
114 timeout = SharedScheduledExecutors.newTimeout(bngStatsMonitor, 0, TimeUnit.MILLISECONDS);
115 }
116 }
117 }
118
119 /**
120 * Stops the BNG statistics monitor.
121 */
122 private void shutdown() {
123 synchronized (bngStatsMonitor) {
124 if (timeout != null) {
125 timeout.cancel(true);
126 timeout = null;
127 }
128 }
129 }
130
131 private Map<String, Map<BngProgrammable.BngCounterType, PiCounterCellData>> getStats(
132 Map<String, BngAttachment> attachments) {
133 Map<String, Map<BngProgrammable.BngCounterType, PiCounterCellData>>
134 stats = Maps.newHashMap();
135 attachments.forEach((key, value) -> stats.put(key, getStats(key)));
136 return stats;
137 }
138
139 @Override
140 public Map<BngProgrammable.BngCounterType, PiCounterCellData> getStats(
141 String bngAttachmentKey) {
142 BngProgrammable bngProgrammable = getBngProgrammable(bngService.getBngDeviceId());
143 BngAttachment attachment = bngService.getAttachment(bngAttachmentKey);
144 if (bngProgrammable != null && attachment != null) {
145 try {
146 return bngProgrammable.readCounters(attachment);
147 } catch (BngProgrammable.BngProgrammableException e) {
148 log.error("Error getting statistics of {}", bngAttachmentKey);
149 }
150 }
151 return Maps.newHashMap();
152 }
153
154 @Override
155 public PiCounterCellData getControlStats() {
156 BngProgrammable bngProgrammable = getBngProgrammable(bngService.getBngDeviceId());
157 if (bngProgrammable != null) {
158 try {
159 return bngProgrammable.readControlTrafficCounter();
160 } catch (BngProgrammable.BngProgrammableException e) {
161 log.error("Error control plane packets statistics");
162 }
163 }
164 return null;
165 }
166
167 private BngProgrammable getBngProgrammable(DeviceId deviceId) {
168 if (deviceId != null && deviceService.isAvailable(deviceId)) {
169 return deviceService.getDevice(deviceId).as(BngProgrammable.class);
170 }
171 return null;
172 }
173
174 private class BngStatisticsMonitor implements Runnable {
175 @Override
176 public void run() {
177 BngProgrammable bngProgrammable = getBngProgrammable(bngService.getBngDeviceId());
178 if (bngProgrammable != null) {
179 var attachments = bngService.getAttachments();
180 Map<String, Map<BngProgrammable.BngCounterType, PiCounterCellData>>
181 attachmentsStats = getStats(attachments);
182 // Create an event for each attachment statistics
183 attachmentsStats.forEach((attachmentKey, stats) -> {
184 BngStatsEventSubject evInfo =
185 new BngStatsEventSubject(attachmentKey,
186 attachments.get(attachmentKey),
187 stats);
188 post(new BngStatsEvent(BngStatsEvent.EventType.STATS_UPDATED, evInfo));
189 });
190 } else {
191 log.debug("BngProgrammable not available");
192 }
193 synchronized (this) {
194 if (timeout != null) {
195 timeout = SharedScheduledExecutors.newTimeout(this, bngStatisticsProbeRate, TimeUnit.MILLISECONDS);
196 }
197 }
198 }
199 }
200}
201
202