blob: c9d006320e8e07eab953bbcda1159e13c80bd66c [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 Lia1d7f272016-03-28 17:21:47 -070025import org.onlab.util.SharedScheduledExecutorService;
Jian Li66f15262016-03-03 11:18:40 -080026import org.onlab.util.SharedScheduledExecutors;
Jian Lie0e01c22016-02-09 14:02:49 -080027import org.onosproject.cpman.message.ControlMessageProvider;
28import org.onosproject.cpman.message.ControlMessageProviderRegistry;
29import org.onosproject.cpman.message.ControlMessageProviderService;
Jian Li1d13c262016-02-09 14:58:28 -080030import org.onosproject.net.DeviceId;
Jian Lie0e01c22016-02-09 14:02:49 -080031import org.onosproject.net.provider.AbstractProvider;
32import org.onosproject.net.provider.ProviderId;
Jian Li1d13c262016-02-09 14:58:28 -080033import org.onosproject.openflow.controller.Dpid;
34import org.onosproject.openflow.controller.OpenFlowController;
35import org.onosproject.openflow.controller.OpenFlowEventListener;
36import org.onosproject.openflow.controller.OpenFlowSwitch;
37import org.onosproject.openflow.controller.OpenFlowSwitchListener;
38import org.onosproject.openflow.controller.RoleState;
39import org.projectfloodlight.openflow.protocol.OFMessage;
40import org.projectfloodlight.openflow.protocol.OFPortStatus;
Jian Li7ceb7b02016-04-04 12:42:40 -070041import org.projectfloodlight.openflow.protocol.OFType;
Jian Lie0e01c22016-02-09 14:02:49 -080042import org.slf4j.Logger;
43
Jian Li1d13c262016-02-09 14:58:28 -080044import java.util.HashMap;
Jian Li1d13c262016-02-09 14:58:28 -080045import java.util.concurrent.ScheduledFuture;
46import java.util.concurrent.TimeUnit;
47
48import static org.onosproject.net.DeviceId.deviceId;
49import static org.onosproject.openflow.controller.Dpid.uri;
Jian Lie0e01c22016-02-09 14:02:49 -080050import static org.slf4j.LoggerFactory.getLogger;
51
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();
Jian Lia1d7f272016-03-28 17:21:47 -070081 private SharedScheduledExecutorService executor;
Jian Li1d13c262016-02-09 14:58:28 -080082 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
Jian Li66f15262016-03-03 11:18:40 -0800108 executor = SharedScheduledExecutors.getSingleThreadExecutor();
Jian Li1d13c262016-02-09 14:58:28 -0800109
110 connectInitialDevices();
111 log.info("Started");
Jian Lie0e01c22016-02-09 14:02:49 -0800112 }
113
114 @Deactivate
115 protected void deactivate() {
Jian Li1d13c262016-02-09 14:58:28 -0800116 controller.removeListener(listener);
Jian Lie0e01c22016-02-09 14:02:49 -0800117 providerRegistry.unregister(this);
118 providerService = null;
Jian Li1d13c262016-02-09 14:58:28 -0800119
120 // stops listening all OpenFlow incoming message events
121 controller.monitorAllEvents(false);
122 controller.removeEventListener(inMsgListener);
123
124 // stops listening all OpenFlow outgoing message events
125 controller.getSwitches().forEach(sw -> sw.removeEventListener(outMsgListener));
126
127 log.info("Stopped");
128 }
129
130 private void connectInitialDevices() {
131 for (OpenFlowSwitch sw: controller.getSwitches()) {
132 try {
133 listener.switchAdded(new Dpid(sw.getId()));
134 } catch (Exception e) {
135 log.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
136 log.debug("Error details:", e);
137 }
138 }
139 }
140
141 /**
142 * A listener for OpenFlow switch event.
143 */
144 private class InternalDeviceProvider implements OpenFlowSwitchListener {
145
146 @Override
147 public void switchAdded(Dpid dpid) {
148 if (providerService == null) {
149 return;
150 }
151
152 OpenFlowSwitch sw = controller.getSwitch(dpid);
153 if (sw != null) {
154 // start to monitor the outgoing control messages
155 sw.addEventListener(outMsgListener);
156 }
157
158 DeviceId deviceId = deviceId(uri(dpid));
159 OpenFlowControlMessageAggregator ofcma =
160 new OpenFlowControlMessageAggregator(metricsService,
161 providerService, deviceId);
162 ScheduledFuture result = executor.scheduleAtFixedRate(ofcma,
Jian Lia1d7f272016-03-28 17:21:47 -0700163 AGGR_INIT_DELAY, AGGR_PERIOD, AGGR_TIME_UNIT, true);
Jian Li1d13c262016-02-09 14:58:28 -0800164 aggregators.put(dpid, ofcma);
165 executorResults.put(dpid, result);
166 }
167
168 @Override
169 public void switchRemoved(Dpid dpid) {
170 if (providerService == null) {
171 return;
172 }
173
174 OpenFlowSwitch sw = controller.getSwitch(dpid);
175 if (sw != null) {
176 // stop monitoring the outgoing control messages
177 sw.removeEventListener(outMsgListener);
178 }
179
180 // removes the aggregator when switch is removed
181 // this also stops the aggregator from running
182 OpenFlowControlMessageAggregator aggregator = aggregators.remove(dpid);
183 if (aggregator != null) {
184 executorResults.get(dpid).cancel(true);
185 executorResults.remove(dpid);
186 }
187 }
188
189 @Override
190 public void switchChanged(Dpid dpid) {
191 }
192
193 @Override
194 public void portChanged(Dpid dpid, OFPortStatus status) {
195 }
196
197 @Override
198 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
199 }
200 }
201
202 /**
203 * A listener for incoming OpenFlow messages.
204 */
205 private class InternalIncomingMessageProvider implements OpenFlowEventListener {
206
207 @Override
208 public void handleMessage(Dpid dpid, OFMessage msg) {
Jian Li7ceb7b02016-04-04 12:42:40 -0700209 if (msg.getType() == OFType.PACKET_IN ||
210 msg.getType() == OFType.FLOW_MOD ||
211 msg.getType() == OFType.STATS_REPLY) {
212 aggregators.get(dpid).increment(msg);
213 }
Jian Li1d13c262016-02-09 14:58:28 -0800214 }
215 }
216
217 /**
218 * A listener for outgoing OpenFlow messages.
219 */
220 private class InternalOutgoingMessageProvider implements OpenFlowEventListener {
221
222 @Override
223 public void handleMessage(Dpid dpid, OFMessage msg) {
224 aggregators.get(dpid).increment(msg);
225 }
Jian Lie0e01c22016-02-09 14:02:49 -0800226 }
227}