blob: 714340b431cdb173f5bf257efef30391759c9028 [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 Lie0e01c22016-02-09 14:02:49 -080041import org.slf4j.Logger;
42
Jian Li1d13c262016-02-09 14:58:28 -080043import java.util.HashMap;
Jian Li1d13c262016-02-09 14:58:28 -080044import 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;
50
51/**
52 * Provider which uses an OpenFlow controller to collect control message.
53 */
54@Component(immediate = true)
55public class OpenFlowControlMessageProvider extends AbstractProvider
56 implements ControlMessageProvider {
57
Jian Li1d13c262016-02-09 14:58:28 -080058 private final Logger log = getLogger(getClass());
Jian Lie0e01c22016-02-09 14:02:49 -080059
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected ControlMessageProviderRegistry providerRegistry;
62
Jian Li1d13c262016-02-09 14:58:28 -080063 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected OpenFlowController controller;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected MetricsService metricsService;
68
Jian Lie0e01c22016-02-09 14:02:49 -080069 private ControlMessageProviderService providerService;
70
Jian Li1d13c262016-02-09 14:58:28 -080071 private final InternalDeviceProvider listener = new InternalDeviceProvider();
72
73 private final InternalIncomingMessageProvider inMsgListener =
74 new InternalIncomingMessageProvider();
75
76 private final InternalOutgoingMessageProvider outMsgListener =
77 new InternalOutgoingMessageProvider();
78
79 private HashMap<Dpid, OpenFlowControlMessageAggregator> aggregators = Maps.newHashMap();
Jian Lia1d7f272016-03-28 17:21:47 -070080 private SharedScheduledExecutorService executor;
Jian Li1d13c262016-02-09 14:58:28 -080081 private static final int AGGR_INIT_DELAY = 1;
82 private static final int AGGR_PERIOD = 1;
83 private static final TimeUnit AGGR_TIME_UNIT = TimeUnit.MINUTES;
84 private HashMap<Dpid, ScheduledFuture<?>> executorResults = Maps.newHashMap();
85
Jian Lie0e01c22016-02-09 14:02:49 -080086 /**
87 * Creates a provider with the supplier identifier.
88 */
89 public OpenFlowControlMessageProvider() {
90 super(new ProviderId("of", "org.onosproject.provider.openflow"));
91 }
92
93 @Activate
94 protected void activate() {
95 providerService = providerRegistry.register(this);
Jian Li1d13c262016-02-09 14:58:28 -080096
97 // listens all OpenFlow device related events
98 controller.addListener(listener);
99
100 // listens all OpenFlow incoming message events
101 controller.addEventListener(inMsgListener);
102 controller.monitorAllEvents(true);
103
104 // listens all OpenFlow outgoing message events
105 controller.getSwitches().forEach(sw -> sw.addEventListener(outMsgListener));
106
Jian Li66f15262016-03-03 11:18:40 -0800107 executor = SharedScheduledExecutors.getSingleThreadExecutor();
Jian Li1d13c262016-02-09 14:58:28 -0800108
109 connectInitialDevices();
110 log.info("Started");
Jian Lie0e01c22016-02-09 14:02:49 -0800111 }
112
113 @Deactivate
114 protected void deactivate() {
Jian Li1d13c262016-02-09 14:58:28 -0800115 controller.removeListener(listener);
Jian Lie0e01c22016-02-09 14:02:49 -0800116 providerRegistry.unregister(this);
117 providerService = null;
Jian Li1d13c262016-02-09 14:58:28 -0800118
119 // stops listening all OpenFlow incoming message events
120 controller.monitorAllEvents(false);
121 controller.removeEventListener(inMsgListener);
122
123 // stops listening all OpenFlow outgoing message events
124 controller.getSwitches().forEach(sw -> sw.removeEventListener(outMsgListener));
125
126 log.info("Stopped");
127 }
128
129 private void connectInitialDevices() {
130 for (OpenFlowSwitch sw: controller.getSwitches()) {
131 try {
132 listener.switchAdded(new Dpid(sw.getId()));
133 } catch (Exception e) {
134 log.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
135 log.debug("Error details:", e);
136 }
137 }
138 }
139
140 /**
141 * A listener for OpenFlow switch event.
142 */
143 private class InternalDeviceProvider implements OpenFlowSwitchListener {
144
145 @Override
146 public void switchAdded(Dpid dpid) {
147 if (providerService == null) {
148 return;
149 }
150
151 OpenFlowSwitch sw = controller.getSwitch(dpid);
152 if (sw != null) {
153 // start to monitor the outgoing control messages
154 sw.addEventListener(outMsgListener);
155 }
156
157 DeviceId deviceId = deviceId(uri(dpid));
158 OpenFlowControlMessageAggregator ofcma =
159 new OpenFlowControlMessageAggregator(metricsService,
160 providerService, deviceId);
161 ScheduledFuture result = executor.scheduleAtFixedRate(ofcma,
Jian Lia1d7f272016-03-28 17:21:47 -0700162 AGGR_INIT_DELAY, AGGR_PERIOD, AGGR_TIME_UNIT, true);
Jian Li1d13c262016-02-09 14:58:28 -0800163 aggregators.put(dpid, ofcma);
164 executorResults.put(dpid, result);
165 }
166
167 @Override
168 public void switchRemoved(Dpid dpid) {
169 if (providerService == null) {
170 return;
171 }
172
173 OpenFlowSwitch sw = controller.getSwitch(dpid);
174 if (sw != null) {
175 // stop monitoring the outgoing control messages
176 sw.removeEventListener(outMsgListener);
177 }
178
179 // removes the aggregator when switch is removed
180 // this also stops the aggregator from running
181 OpenFlowControlMessageAggregator aggregator = aggregators.remove(dpid);
182 if (aggregator != null) {
183 executorResults.get(dpid).cancel(true);
184 executorResults.remove(dpid);
185 }
186 }
187
188 @Override
189 public void switchChanged(Dpid dpid) {
190 }
191
192 @Override
193 public void portChanged(Dpid dpid, OFPortStatus status) {
194 }
195
196 @Override
197 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
198 }
199 }
200
201 /**
202 * A listener for incoming OpenFlow messages.
203 */
204 private class InternalIncomingMessageProvider implements OpenFlowEventListener {
205
206 @Override
207 public void handleMessage(Dpid dpid, OFMessage msg) {
208 aggregators.get(dpid).increment(msg);
209 }
210 }
211
212 /**
213 * A listener for outgoing OpenFlow messages.
214 */
215 private class InternalOutgoingMessageProvider implements OpenFlowEventListener {
216
217 @Override
218 public void handleMessage(Dpid dpid, OFMessage msg) {
219 aggregators.get(dpid).increment(msg);
220 }
Jian Lie0e01c22016-02-09 14:02:49 -0800221 }
222}