blob: a2e21dcf33bba0e9e21887fd7801566e51a8e499 [file] [log] [blame]
Jian Lie0e01c22016-02-09 14:02:49 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Jian Lie0e01c22016-02-09 14:02:49 -08003 *
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;
Jian Lia78cdb22016-04-21 13:03:58 -070035import org.onosproject.openflow.controller.OpenFlowMessageListener;
Jian Li1d13c262016-02-09 14:58:28 -080036import 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 Lia78cdb22016-04-21 13:03:58 -070045import java.util.List;
Jian Li1d13c262016-02-09 14:58:28 -080046import java.util.concurrent.ScheduledFuture;
47import java.util.concurrent.TimeUnit;
48
49import static org.onosproject.net.DeviceId.deviceId;
50import static org.onosproject.openflow.controller.Dpid.uri;
Jian Lie0e01c22016-02-09 14:02:49 -080051import static org.slf4j.LoggerFactory.getLogger;
52
53/**
54 * Provider which uses an OpenFlow controller to collect control message.
55 */
56@Component(immediate = true)
57public class OpenFlowControlMessageProvider extends AbstractProvider
58 implements ControlMessageProvider {
59
Jian Li1d13c262016-02-09 14:58:28 -080060 private final Logger log = getLogger(getClass());
Jian Lie0e01c22016-02-09 14:02:49 -080061
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected ControlMessageProviderRegistry providerRegistry;
64
Jian Li1d13c262016-02-09 14:58:28 -080065 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected OpenFlowController controller;
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected MetricsService metricsService;
70
Jian Lie0e01c22016-02-09 14:02:49 -080071 private ControlMessageProviderService providerService;
72
Jian Li1d13c262016-02-09 14:58:28 -080073 private final InternalDeviceProvider listener = new InternalDeviceProvider();
74
Jian Lia78cdb22016-04-21 13:03:58 -070075 private final InternalControlMessageListener messageListener =
76 new InternalControlMessageListener();
Jian Li1d13c262016-02-09 14:58:28 -080077
78 private HashMap<Dpid, OpenFlowControlMessageAggregator> aggregators = Maps.newHashMap();
Jian Lia1d7f272016-03-28 17:21:47 -070079 private SharedScheduledExecutorService executor;
Jian Li1d13c262016-02-09 14:58:28 -080080 private static final int AGGR_INIT_DELAY = 1;
81 private static final int AGGR_PERIOD = 1;
82 private static final TimeUnit AGGR_TIME_UNIT = TimeUnit.MINUTES;
83 private HashMap<Dpid, ScheduledFuture<?>> executorResults = Maps.newHashMap();
84
Jian Lie0e01c22016-02-09 14:02:49 -080085 /**
86 * Creates a provider with the supplier identifier.
87 */
88 public OpenFlowControlMessageProvider() {
89 super(new ProviderId("of", "org.onosproject.provider.openflow"));
90 }
91
92 @Activate
93 protected void activate() {
94 providerService = providerRegistry.register(this);
Jian Li1d13c262016-02-09 14:58:28 -080095
96 // listens all OpenFlow device related events
97 controller.addListener(listener);
98
Jian Lia78cdb22016-04-21 13:03:58 -070099 // listens all OpenFlow control message
100 controller.addMessageListener(messageListener);
Jian Li1d13c262016-02-09 14:58:28 -0800101
Jian Li66f15262016-03-03 11:18:40 -0800102 executor = SharedScheduledExecutors.getSingleThreadExecutor();
Jian Li1d13c262016-02-09 14:58:28 -0800103
104 connectInitialDevices();
105 log.info("Started");
Jian Lie0e01c22016-02-09 14:02:49 -0800106 }
107
108 @Deactivate
109 protected void deactivate() {
Jian Li1d13c262016-02-09 14:58:28 -0800110 controller.removeListener(listener);
Jian Lie0e01c22016-02-09 14:02:49 -0800111 providerRegistry.unregister(this);
112 providerService = null;
Jian Li1d13c262016-02-09 14:58:28 -0800113
Jian Lia78cdb22016-04-21 13:03:58 -0700114 // stops listening all OpenFlow control message events
115 controller.removeMessageListener(messageListener);
Jian Li1d13c262016-02-09 14:58:28 -0800116
117 log.info("Stopped");
118 }
119
120 private void connectInitialDevices() {
121 for (OpenFlowSwitch sw: controller.getSwitches()) {
122 try {
123 listener.switchAdded(new Dpid(sw.getId()));
124 } catch (Exception e) {
125 log.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
126 log.debug("Error details:", e);
127 }
128 }
129 }
130
131 /**
132 * A listener for OpenFlow switch event.
133 */
134 private class InternalDeviceProvider implements OpenFlowSwitchListener {
135
136 @Override
137 public void switchAdded(Dpid dpid) {
138 if (providerService == null) {
139 return;
140 }
141
Jian Li1d13c262016-02-09 14:58:28 -0800142 DeviceId deviceId = deviceId(uri(dpid));
143 OpenFlowControlMessageAggregator ofcma =
144 new OpenFlowControlMessageAggregator(metricsService,
145 providerService, deviceId);
146 ScheduledFuture result = executor.scheduleAtFixedRate(ofcma,
Jian Lia1d7f272016-03-28 17:21:47 -0700147 AGGR_INIT_DELAY, AGGR_PERIOD, AGGR_TIME_UNIT, true);
Jian Li1d13c262016-02-09 14:58:28 -0800148 aggregators.put(dpid, ofcma);
149 executorResults.put(dpid, result);
150 }
151
152 @Override
153 public void switchRemoved(Dpid dpid) {
154 if (providerService == null) {
155 return;
156 }
157
Jian Li1d13c262016-02-09 14:58:28 -0800158 // removes the aggregator when switch is removed
159 // this also stops the aggregator from running
160 OpenFlowControlMessageAggregator aggregator = aggregators.remove(dpid);
161 if (aggregator != null) {
162 executorResults.get(dpid).cancel(true);
163 executorResults.remove(dpid);
164 }
165 }
166
167 @Override
168 public void switchChanged(Dpid dpid) {
169 }
170
171 @Override
172 public void portChanged(Dpid dpid, OFPortStatus status) {
173 }
174
175 @Override
176 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
177 }
178 }
179
180 /**
Jian Lia78cdb22016-04-21 13:03:58 -0700181 * A listener for all OpenFlow control messages.
Jian Li1d13c262016-02-09 14:58:28 -0800182 */
Jian Lia78cdb22016-04-21 13:03:58 -0700183 private class InternalControlMessageListener implements OpenFlowMessageListener {
Jian Li1d13c262016-02-09 14:58:28 -0800184
185 @Override
Jian Lia78cdb22016-04-21 13:03:58 -0700186 public void handleIncomingMessage(Dpid dpid, OFMessage msg) {
Jian Li7ceb7b02016-04-04 12:42:40 -0700187 if (msg.getType() == OFType.PACKET_IN ||
188 msg.getType() == OFType.FLOW_MOD ||
189 msg.getType() == OFType.STATS_REPLY) {
Jian Lia371e7a2016-04-06 17:40:41 -0700190 aggregators.computeIfPresent(dpid, (k, v) -> {
191 v.increment(msg);
192 return v;
193 });
Jian Li7ceb7b02016-04-04 12:42:40 -0700194 }
Jian Li1d13c262016-02-09 14:58:28 -0800195 }
Jian Li1d13c262016-02-09 14:58:28 -0800196
197 @Override
Jian Lia78cdb22016-04-21 13:03:58 -0700198 public void handleOutgoingMessage(Dpid dpid, List<OFMessage> msgs) {
199 for (OFMessage msg : msgs) {
200 if (msg.getType() == OFType.PACKET_OUT ||
201 msg.getType() == OFType.FLOW_MOD ||
202 msg.getType() == OFType.STATS_REQUEST) {
203 aggregators.computeIfPresent(dpid, (k, v) -> {
204 v.increment(msg);
205 return v;
206 });
207 }
208 }
Jian Li1d13c262016-02-09 14:58:28 -0800209 }
Jian Lie0e01c22016-02-09 14:02:49 -0800210 }
211}