blob: e56118bad480e5034f3559ca319dcfd35c8098f8 [file] [log] [blame]
Arjun E Kabf9e6e2020-03-02 10:15:21 +00001/*
2 * Copyright 2018-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 */
Daniele Moro8ea9e102020-03-24 18:56:52 +010016package org.opencord.cordmcast.impl;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000017
18
Ilayda Ozdemir2fccbce2021-02-23 15:36:47 +000019import com.google.common.collect.Lists;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000020import org.onlab.packet.VlanId;
21import org.onlab.util.SafeRecurringTask;
22import org.onosproject.cfg.ComponentConfigService;
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +000023import org.onosproject.cluster.ClusterService;
24import org.onosproject.cluster.LeadershipService;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000025import org.onosproject.event.AbstractListenerManager;
26import org.onosproject.mcast.api.McastRoute;
27import org.onosproject.mcast.api.MulticastRouteService;
Daniele Moro8ea9e102020-03-24 18:56:52 +010028import org.opencord.cordmcast.CordMcastStatistics;
29import org.opencord.cordmcast.CordMcastStatisticsEvent;
30import org.opencord.cordmcast.CordMcastStatisticsEventListener;
31import org.opencord.cordmcast.CordMcastStatisticsService;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000032import org.osgi.service.component.ComponentContext;
33import org.osgi.service.component.annotations.Modified;
34import org.osgi.service.component.annotations.Activate;
35import org.osgi.service.component.annotations.Deactivate;
36import org.osgi.service.component.annotations.Component;
37import org.osgi.service.component.annotations.Reference;
38import org.osgi.service.component.annotations.ReferenceCardinality;
Ilayda Ozdemir2fccbce2021-02-23 15:36:47 +000039import org.osgi.service.component.annotations.ReferencePolicy;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000040import org.slf4j.Logger;
41
42import java.util.Dictionary;
43import java.util.Set;
44import java.util.List;
45import java.util.ArrayList;
46import java.util.Properties;
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +000047import java.util.Objects;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000048
49import java.util.concurrent.Executors;
50import java.util.concurrent.ScheduledExecutorService;
51import java.util.concurrent.ScheduledFuture;
52import java.util.concurrent.TimeUnit;
53
54import static com.google.common.base.Strings.isNullOrEmpty;
55import static org.onlab.util.Tools.get;
Daniele Moro8ea9e102020-03-24 18:56:52 +010056import static org.opencord.cordmcast.impl.OsgiPropertyConstants.EVENT_GENERATION_PERIOD;
57import static org.opencord.cordmcast.impl.OsgiPropertyConstants.EVENT_GENERATION_PERIOD_DEFAULT;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000058
59import static org.slf4j.LoggerFactory.getLogger;
60
61/**
62 * For managing CordMcastStatisticsEvent.
63 */
64@Component(immediate = true, property = { EVENT_GENERATION_PERIOD + ":Integer=" + EVENT_GENERATION_PERIOD_DEFAULT, })
65public class CordMcastStatisticsManager
66 extends AbstractListenerManager<CordMcastStatisticsEvent, CordMcastStatisticsEventListener>
67 implements CordMcastStatisticsService {
Ilayda Ozdemir2fccbce2021-02-23 15:36:47 +000068 private static final String MCAST_NOT_RUNNING = "Multicast is not running.";
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +000069 private static final String CORD_MCAST_STATISTICS_LEADERSHIP = "cord-mcast-statistics-leadership";
70
Ilayda Ozdemir2fccbce2021-02-23 15:36:47 +000071 @Reference(cardinality = ReferenceCardinality.OPTIONAL,
72 bind = "bindMcastRouteService",
73 unbind = "unbindMcastRouteService",
74 policy = ReferencePolicy.DYNAMIC)
75 protected volatile MulticastRouteService mcastService;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000076
77 @Reference(cardinality = ReferenceCardinality.MANDATORY)
78 protected ComponentConfigService componentConfigService;
79
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +000080 @Reference(cardinality = ReferenceCardinality.MANDATORY)
81 protected ClusterService clusterService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY)
84 protected LeadershipService leadershipService;
85
Arjun E Kabf9e6e2020-03-02 10:15:21 +000086
87 /**
88 * Multicast Statistics generation time interval.
89 **/
90 private int eventGenerationPeriodInSeconds = EVENT_GENERATION_PERIOD_DEFAULT;
91 private final Logger log = getLogger(getClass());
92 private ScheduledFuture<?> scheduledFuture = null;
93 private ScheduledExecutorService executor;
94
95 private VlanId vlanId;
Esin Karamane4890012020-04-19 11:58:54 +000096 private VlanId innerVlanId;
Arjun E Kabf9e6e2020-03-02 10:15:21 +000097
98 @Activate
99 public void activate(ComponentContext context) {
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +0000100 leadershipService.runForLeadership(CORD_MCAST_STATISTICS_LEADERSHIP);
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000101 eventDispatcher.addSink(CordMcastStatisticsEvent.class, listenerRegistry);
102 executor = Executors.newScheduledThreadPool(1);
103 componentConfigService.registerProperties(getClass());
104 modified(context);
105 log.info("CordMcastStatisticsManager activated.");
106 }
107
108 @Modified
109 public void modified(ComponentContext context) {
110 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
111 try {
112 String s = get(properties, EVENT_GENERATION_PERIOD);
113 eventGenerationPeriodInSeconds =
114 isNullOrEmpty(s) ? EVENT_GENERATION_PERIOD_DEFAULT : Integer.parseInt(s.trim());
115 } catch (NumberFormatException ne) {
116 log.error("Unable to parse configuration parameter for eventGenerationPeriodInSeconds", ne);
117 eventGenerationPeriodInSeconds = EVENT_GENERATION_PERIOD_DEFAULT;
118 }
119 if (scheduledFuture != null) {
120 scheduledFuture.cancel(true);
121 }
122 scheduledFuture = executor.scheduleAtFixedRate(SafeRecurringTask.wrap(this::publishEvent),
123 0, eventGenerationPeriodInSeconds, TimeUnit.SECONDS);
124 }
125
126 @Deactivate
127 public void deactivate() {
128 eventDispatcher.removeSink(CordMcastStatisticsEvent.class);
129 scheduledFuture.cancel(true);
130 executor.shutdown();
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +0000131 leadershipService.withdraw(CORD_MCAST_STATISTICS_LEADERSHIP);
132 log.info("CordMcastStatisticsManager deactivated.");
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000133 }
134
Ilayda Ozdemir2fccbce2021-02-23 15:36:47 +0000135 protected void bindMcastRouteService(MulticastRouteService service) {
136 mcastService = service;
137 log.info("Multicast route service binds to onos.");
138 }
139
140 protected void unbindMcastRouteService(MulticastRouteService service) {
141 mcastService = null;
142 log.info("Multicast route service unbinds from onos.");
143 }
144
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000145 public List<CordMcastStatistics> getMcastDetails() {
Ilayda Ozdemir2fccbce2021-02-23 15:36:47 +0000146 if (mcastService == null) {
147 log.warn(MCAST_NOT_RUNNING);
148 return Lists.newArrayList();
149 }
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000150 List<CordMcastStatistics> mcastData = new ArrayList<CordMcastStatistics>();
151 Set<McastRoute> routes = mcastService.getRoutes();
152 routes.forEach(route -> {
153 mcastData.add(new CordMcastStatistics(route.group(),
154 route.source().isEmpty() ? "*" : route.source().get().toString(),
Esin Karamane4890012020-04-19 11:58:54 +0000155 vlanId, innerVlanId));
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000156 });
157 return mcastData;
158 }
159
160 @Override
161 public void setVlanValue(VlanId vlanValue) {
162 vlanId = vlanValue;
163 }
164
Esin Karamane4890012020-04-19 11:58:54 +0000165 @Override
166 public void setInnerVlanValue(VlanId innerVlanValue) {
167 innerVlanId = innerVlanValue;
168 }
169
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000170 /**
171 * pushing mcast stat data as event.
172 */
173 protected void publishEvent() {
Ilayda Ozdemir0414dde2020-06-27 23:18:07 +0000174 // Only publish events if we are the cluster leader for Igmp-stats
175 if (!Objects.equals(leadershipService.getLeader(CORD_MCAST_STATISTICS_LEADERSHIP),
176 clusterService.getLocalNode().id())) {
177 log.debug("This is not leader of : {}", CORD_MCAST_STATISTICS_LEADERSHIP);
178 return;
179 }
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000180 log.debug("pushing cord mcast event to kafka");
181 List<CordMcastStatistics> routeList = getMcastDetails();
182 routeList.forEach(mcastStats -> {
183 log.debug("Group: " +
184 (mcastStats.getGroupAddress() != null ? mcastStats.getGroupAddress().toString() : "null") +
185 " | Source: " +
186 (mcastStats.getSourceAddress() != null ? mcastStats.getSourceAddress().toString() : "null") +
187 " | Vlan: " +
Esin Karamane4890012020-04-19 11:58:54 +0000188 (mcastStats.getVlanId() != null ? mcastStats.getVlanId().toString() : "null") +
189 " | InnerVlan: " +
190 (mcastStats.getInnerVlanId() != null ? mcastStats.getInnerVlanId().toString() : "null"));
Arjun E Kabf9e6e2020-03-02 10:15:21 +0000191 });
192 post(new CordMcastStatisticsEvent(CordMcastStatisticsEvent.Type.STATUS_UPDATE, routeList));
193 }
194}