blob: 93aa70f20940676ec952cdab33a7f88bfe423cb2 [file] [log] [blame]
Jian Lie0e01c22016-02-09 14:02:49 -08001/*
2 * Copyright 2016 Open Networking Laboratory
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 */
16package org.onosproject.provider.of.message.impl;
17
Jian Li1d13c262016-02-09 14:58:28 -080018import com.google.common.collect.Maps;
Jian Lie0e01c22016-02-09 14:02:49 -080019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
Jian Li1d13c262016-02-09 14:58:28 -080024import org.onlab.metrics.MetricsService;
Jian Lie0e01c22016-02-09 14:02:49 -080025import org.onosproject.cpman.message.ControlMessageProvider;
26import org.onosproject.cpman.message.ControlMessageProviderRegistry;
27import org.onosproject.cpman.message.ControlMessageProviderService;
Jian Li1d13c262016-02-09 14:58:28 -080028import org.onosproject.net.DeviceId;
Jian Lie0e01c22016-02-09 14:02:49 -080029import org.onosproject.net.provider.AbstractProvider;
30import org.onosproject.net.provider.ProviderId;
Jian Li1d13c262016-02-09 14:58:28 -080031import org.onosproject.openflow.controller.Dpid;
32import org.onosproject.openflow.controller.OpenFlowController;
33import org.onosproject.openflow.controller.OpenFlowEventListener;
34import org.onosproject.openflow.controller.OpenFlowSwitch;
35import org.onosproject.openflow.controller.OpenFlowSwitchListener;
36import org.onosproject.openflow.controller.RoleState;
37import org.projectfloodlight.openflow.protocol.OFMessage;
38import org.projectfloodlight.openflow.protocol.OFPortStatus;
Jian Lie0e01c22016-02-09 14:02:49 -080039import org.slf4j.Logger;
40
Jian Li1d13c262016-02-09 14:58:28 -080041import java.util.HashMap;
42import java.util.concurrent.Executors;
43import java.util.concurrent.ScheduledExecutorService;
44import java.util.concurrent.ScheduledFuture;
45import java.util.concurrent.TimeUnit;
46
47import static org.onosproject.net.DeviceId.deviceId;
48import static org.onosproject.openflow.controller.Dpid.uri;
Jian Lie0e01c22016-02-09 14:02:49 -080049import static org.slf4j.LoggerFactory.getLogger;
Jian Li1d13c262016-02-09 14:58:28 -080050import static org.onlab.util.Tools.groupedThreads;
Jian Lie0e01c22016-02-09 14:02:49 -080051
52/**
53 * Provider which uses an OpenFlow controller to collect control message.
54 */
55@Component(immediate = true)
56public class OpenFlowControlMessageProvider extends AbstractProvider
57 implements ControlMessageProvider {
58
Jian Li1d13c262016-02-09 14:58:28 -080059 private final Logger log = getLogger(getClass());
Jian Lie0e01c22016-02-09 14:02:49 -080060
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected ControlMessageProviderRegistry providerRegistry;
63
Jian Li1d13c262016-02-09 14:58:28 -080064 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected OpenFlowController controller;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected MetricsService metricsService;
69
Jian Lie0e01c22016-02-09 14:02:49 -080070 private ControlMessageProviderService providerService;
71
Jian Li1d13c262016-02-09 14:58:28 -080072 private final InternalDeviceProvider listener = new InternalDeviceProvider();
73
74 private final InternalIncomingMessageProvider inMsgListener =
75 new InternalIncomingMessageProvider();
76
77 private final InternalOutgoingMessageProvider outMsgListener =
78 new InternalOutgoingMessageProvider();
79
80 private HashMap<Dpid, OpenFlowControlMessageAggregator> aggregators = Maps.newHashMap();
81 private ScheduledExecutorService executor;
82 private static final int AGGR_INIT_DELAY = 1;
83 private static final int AGGR_PERIOD = 1;
84 private static final TimeUnit AGGR_TIME_UNIT = TimeUnit.MINUTES;
85 private HashMap<Dpid, ScheduledFuture<?>> executorResults = Maps.newHashMap();
86
Jian Lie0e01c22016-02-09 14:02:49 -080087 /**
88 * Creates a provider with the supplier identifier.
89 */
90 public OpenFlowControlMessageProvider() {
91 super(new ProviderId("of", "org.onosproject.provider.openflow"));
92 }
93
94 @Activate
95 protected void activate() {
96 providerService = providerRegistry.register(this);
Jian Li1d13c262016-02-09 14:58:28 -080097
98 // listens all OpenFlow device related events
99 controller.addListener(listener);
100
101 // listens all OpenFlow incoming message events
102 controller.addEventListener(inMsgListener);
103 controller.monitorAllEvents(true);
104
105 // listens all OpenFlow outgoing message events
106 controller.getSwitches().forEach(sw -> sw.addEventListener(outMsgListener));
107
108 executor = Executors.newSingleThreadScheduledExecutor(
Jian Li7d9d4392016-02-11 11:41:26 -0800109 groupedThreads("onos/provider", "aggregator"));
Jian Li1d13c262016-02-09 14:58:28 -0800110
111 connectInitialDevices();
112 log.info("Started");
Jian Lie0e01c22016-02-09 14:02:49 -0800113 }
114
115 @Deactivate
116 protected void deactivate() {
Jian Li1d13c262016-02-09 14:58:28 -0800117 controller.removeListener(listener);
Jian Lie0e01c22016-02-09 14:02:49 -0800118 providerRegistry.unregister(this);
119 providerService = null;
Jian Li1d13c262016-02-09 14:58:28 -0800120
121 // stops listening all OpenFlow incoming message events
122 controller.monitorAllEvents(false);
123 controller.removeEventListener(inMsgListener);
124
125 // stops listening all OpenFlow outgoing message events
126 controller.getSwitches().forEach(sw -> sw.removeEventListener(outMsgListener));
127
128 log.info("Stopped");
129 }
130
131 private void connectInitialDevices() {
132 for (OpenFlowSwitch sw: controller.getSwitches()) {
133 try {
134 listener.switchAdded(new Dpid(sw.getId()));
135 } catch (Exception e) {
136 log.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
137 log.debug("Error details:", e);
138 }
139 }
140 }
141
142 /**
143 * A listener for OpenFlow switch event.
144 */
145 private class InternalDeviceProvider implements OpenFlowSwitchListener {
146
147 @Override
148 public void switchAdded(Dpid dpid) {
149 if (providerService == null) {
150 return;
151 }
152
153 OpenFlowSwitch sw = controller.getSwitch(dpid);
154 if (sw != null) {
155 // start to monitor the outgoing control messages
156 sw.addEventListener(outMsgListener);
157 }
158
159 DeviceId deviceId = deviceId(uri(dpid));
160 OpenFlowControlMessageAggregator ofcma =
161 new OpenFlowControlMessageAggregator(metricsService,
162 providerService, deviceId);
163 ScheduledFuture result = executor.scheduleAtFixedRate(ofcma,
164 AGGR_INIT_DELAY, AGGR_PERIOD, AGGR_TIME_UNIT);
165 aggregators.put(dpid, ofcma);
166 executorResults.put(dpid, result);
167 }
168
169 @Override
170 public void switchRemoved(Dpid dpid) {
171 if (providerService == null) {
172 return;
173 }
174
175 OpenFlowSwitch sw = controller.getSwitch(dpid);
176 if (sw != null) {
177 // stop monitoring the outgoing control messages
178 sw.removeEventListener(outMsgListener);
179 }
180
181 // removes the aggregator when switch is removed
182 // this also stops the aggregator from running
183 OpenFlowControlMessageAggregator aggregator = aggregators.remove(dpid);
184 if (aggregator != null) {
185 executorResults.get(dpid).cancel(true);
186 executorResults.remove(dpid);
187 }
188 }
189
190 @Override
191 public void switchChanged(Dpid dpid) {
192 }
193
194 @Override
195 public void portChanged(Dpid dpid, OFPortStatus status) {
196 }
197
198 @Override
199 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
200 }
201 }
202
203 /**
204 * A listener for incoming OpenFlow messages.
205 */
206 private class InternalIncomingMessageProvider implements OpenFlowEventListener {
207
208 @Override
209 public void handleMessage(Dpid dpid, OFMessage msg) {
210 aggregators.get(dpid).increment(msg);
211 }
212 }
213
214 /**
215 * A listener for outgoing OpenFlow messages.
216 */
217 private class InternalOutgoingMessageProvider implements OpenFlowEventListener {
218
219 @Override
220 public void handleMessage(Dpid dpid, OFMessage msg) {
221 aggregators.get(dpid).increment(msg);
222 }
Jian Lie0e01c22016-02-09 14:02:49 -0800223 }
224}