blob: f9d415e86e324141db21e222ce9f918925234563 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
jcc3d4e14a2015-04-21 11:32:05 +08002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.flow.impl;
alshabib1cc04f72014-09-16 16:09:58 -070017
Thomas Vachuska75aaa672015-04-29 12:24:43 -070018import com.google.common.cache.Cache;
19import com.google.common.cache.CacheBuilder;
20import com.google.common.cache.RemovalCause;
21import com.google.common.cache.RemovalNotification;
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
alshabib1cc04f72014-09-16 16:09:58 -070024import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuska75aaa672015-04-29 12:24:43 -070027import org.apache.felix.scr.annotations.Modified;
28import org.apache.felix.scr.annotations.Property;
alshabib1cc04f72014-09-16 16:09:58 -070029import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuska75aaa672015-04-29 12:24:43 -070031import org.onosproject.cfg.ComponentConfigService;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.core.ApplicationId;
33import org.onosproject.net.DeviceId;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.flow.CompletedBatchOperation;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.flow.FlowEntry;
36import org.onosproject.net.flow.FlowRule;
37import org.onosproject.net.flow.FlowRuleBatchEntry;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080038import org.onosproject.net.flow.FlowRuleBatchOperation;
Thomas Vachuskaa6c0d042015-04-23 10:17:37 -070039import org.onosproject.net.flow.FlowRuleExtPayLoad;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.flow.FlowRuleProvider;
41import org.onosproject.net.flow.FlowRuleProviderRegistry;
42import org.onosproject.net.flow.FlowRuleProviderService;
43import org.onosproject.net.provider.AbstractProvider;
44import org.onosproject.net.provider.ProviderId;
Thomas Vachuska75aaa672015-04-29 12:24:43 -070045import org.onosproject.net.statistic.DefaultLoad;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.openflow.controller.Dpid;
47import org.onosproject.openflow.controller.OpenFlowController;
48import org.onosproject.openflow.controller.OpenFlowEventListener;
49import org.onosproject.openflow.controller.OpenFlowSwitch;
50import org.onosproject.openflow.controller.OpenFlowSwitchListener;
51import org.onosproject.openflow.controller.RoleState;
jcc3d4e14a2015-04-21 11:32:05 +080052import org.onosproject.openflow.controller.ThirdPartyMessage;
Thomas Vachuska75aaa672015-04-29 12:24:43 -070053import org.osgi.service.component.ComponentContext;
Thomas Vachuska3358af22015-05-19 18:40:34 -070054import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
alshabib902d41b2014-10-07 16:52:05 -070055import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
56import org.projectfloodlight.openflow.protocol.OFErrorMsg;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080057import org.projectfloodlight.openflow.protocol.OFErrorType;
alshabib193525b2014-10-08 18:58:03 -070058import org.projectfloodlight.openflow.protocol.OFFlowMod;
alshabib8f1cf4a2014-09-17 14:44:48 -070059import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070060import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib8f1cf4a2014-09-17 14:44:48 -070061import org.projectfloodlight.openflow.protocol.OFMessage;
62import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070063import org.projectfloodlight.openflow.protocol.OFStatsReply;
sangho89bf6fb2015-02-09 09:33:13 -080064import org.projectfloodlight.openflow.protocol.OFStatsType;
Thomas Vachuska3358af22015-05-19 18:40:34 -070065import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
alshabib193525b2014-10-08 18:58:03 -070066import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
alshabib1cc04f72014-09-16 16:09:58 -070067import org.slf4j.Logger;
68
Thomas Vachuska75aaa672015-04-29 12:24:43 -070069import java.util.Collections;
70import java.util.Dictionary;
71import java.util.List;
72import java.util.Map;
73import java.util.Optional;
74import java.util.Set;
75import java.util.Timer;
76import java.util.concurrent.TimeUnit;
77import java.util.stream.Collectors;
78
79import static com.google.common.base.Strings.isNullOrEmpty;
80import static org.onlab.util.Tools.get;
81import static org.slf4j.LoggerFactory.getLogger;
alshabibeec3a062014-09-17 18:01:26 -070082
alshabib1cc04f72014-09-16 16:09:58 -070083/**
jcc3d4e14a2015-04-21 11:32:05 +080084 * Provider which uses an OpenFlow controller to detect network end-station
85 * hosts.
alshabib1cc04f72014-09-16 16:09:58 -070086 */
87@Component(immediate = true)
jcc3d4e14a2015-04-21 11:32:05 +080088public class OpenFlowRuleProvider extends AbstractProvider
89 implements FlowRuleProvider {
alshabib1cc04f72014-09-16 16:09:58 -070090
91 private final Logger log = getLogger(getClass());
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected FlowRuleProviderRegistry providerRegistry;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected OpenFlowController controller;
98
Thomas Vachuska75aaa672015-04-29 12:24:43 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected ComponentConfigService cfgService;
101
102 private static final int DEFAULT_POLL_FREQUENCY = 10;
103 @Property(name = "flowPollFrequency", intValue = DEFAULT_POLL_FREQUENCY,
104 label = "Frequency (in seconds) for polling flow statistics")
105 private int flowPollFrequency = DEFAULT_POLL_FREQUENCY;
106
alshabib1cc04f72014-09-16 16:09:58 -0700107 private FlowRuleProviderService providerService;
108
alshabibeec3a062014-09-17 18:01:26 -0700109 private final InternalFlowProvider listener = new InternalFlowProvider();
110
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800111 private Cache<Long, InternalCacheEntry> pendingBatches;
alshabib193525b2014-10-08 18:58:03 -0700112
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700113 private final Timer timer = new Timer("onos-openflow-collector");
alshabib3d643ec2014-10-22 18:33:00 -0700114 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
115
alshabib1cc04f72014-09-16 16:09:58 -0700116 /**
117 * Creates an OpenFlow host provider.
118 */
119 public OpenFlowRuleProvider() {
Brian O'Connorabafb502014-12-02 22:26:20 -0800120 super(new ProviderId("of", "org.onosproject.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -0700121 }
122
123 @Activate
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700124 public void activate(ComponentContext context) {
125 cfgService.registerProperties(getClass());
alshabib1cc04f72014-09-16 16:09:58 -0700126 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -0700127 controller.addListener(listener);
128 controller.addEventListener(listener);
alshabib3d643ec2014-10-22 18:33:00 -0700129
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700130 pendingBatches = createBatchCache();
131 createCollectors();
alshabib3d643ec2014-10-22 18:33:00 -0700132
alshabib1cc04f72014-09-16 16:09:58 -0700133 log.info("Started");
134 }
135
136 @Deactivate
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700137 public void deactivate(ComponentContext context) {
138 cfgService.unregisterProperties(getClass(), false);
139 stopCollectors();
alshabib1cc04f72014-09-16 16:09:58 -0700140 providerRegistry.unregister(this);
141 providerService = null;
142
143 log.info("Stopped");
144 }
Thomas Vachuska9b2da212014-11-10 19:30:25 -0800145
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700146 @Modified
147 public void modified(ComponentContext context) {
148 Dictionary<?, ?> properties = context.getProperties();
149 int newFlowPollFrequency;
150 try {
151 String s = get(properties, "flowPollFrequency");
152 newFlowPollFrequency = isNullOrEmpty(s) ? flowPollFrequency : Integer.parseInt(s.trim());
153
154 } catch (NumberFormatException | ClassCastException e) {
155 newFlowPollFrequency = flowPollFrequency;
156 }
157
158 if (newFlowPollFrequency != flowPollFrequency) {
159 flowPollFrequency = newFlowPollFrequency;
160 adjustRate();
161 }
162
163 log.info("Settings: flowPollFrequency={}", flowPollFrequency);
164 }
165
166 private Cache<Long, InternalCacheEntry> createBatchCache() {
167 return CacheBuilder.newBuilder()
168 .expireAfterWrite(10, TimeUnit.SECONDS)
169 .removalListener((RemovalNotification<Long, InternalCacheEntry> notification) -> {
170 if (notification.getCause() == RemovalCause.EXPIRED) {
171 providerService.batchOperationCompleted(notification.getKey(),
172 notification.getValue().failedCompletion());
173 }
174 }).build();
175 }
176
177 private void createCollectors() {
178 controller.getSwitches().forEach(this::createCollector);
179 }
180
181 private void createCollector(OpenFlowSwitch sw) {
182 FlowStatsCollector fsc = new FlowStatsCollector(timer, sw, flowPollFrequency);
183 fsc.start();
184 collectors.put(new Dpid(sw.getId()), fsc);
185 }
186
187 private void stopCollectors() {
188 collectors.values().forEach(FlowStatsCollector::stop);
189 collectors.clear();
190 }
191
192 private void adjustRate() {
193 DefaultLoad.setPollInterval(flowPollFrequency);
194 collectors.values().forEach(fsc -> fsc.adjustPollInterval(flowPollFrequency));
195 }
196
alshabib1cc04f72014-09-16 16:09:58 -0700197 @Override
198 public void applyFlowRule(FlowRule... flowRules) {
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800199 for (FlowRule flowRule : flowRules) {
200 applyRule(flowRule);
alshabib35edb1a2014-09-16 17:44:44 -0700201 }
alshabib1cc04f72014-09-16 16:09:58 -0700202 }
203
alshabib35edb1a2014-09-16 17:44:44 -0700204 private void applyRule(FlowRule flowRule) {
jcc3d4e14a2015-04-21 11:32:05 +0800205 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId()
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700206 .uri()));
Thomas Vachuskaa6c0d042015-04-23 10:17:37 -0700207 FlowRuleExtPayLoad flowRuleExtPayLoad = flowRule.payLoad();
208 if (hasPayload(flowRuleExtPayLoad)) {
209 OFMessage msg = new ThirdPartyMessage(flowRuleExtPayLoad.payLoad());
jcc3d4e14a2015-04-21 11:32:05 +0800210 sw.sendMsg(msg);
211 return;
212 }
alshabibbdcbb102015-04-22 14:16:38 -0700213 sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
jcc3d4e14a2015-04-21 11:32:05 +0800214 Optional.empty()).buildFlowAdd());
alshabib35edb1a2014-09-16 17:44:44 -0700215 }
216
alshabib1cc04f72014-09-16 16:09:58 -0700217 @Override
218 public void removeFlowRule(FlowRule... flowRules) {
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800219 for (FlowRule flowRule : flowRules) {
220 removeRule(flowRule);
alshabib219ebaa2014-09-22 15:41:24 -0700221 }
alshabib1cc04f72014-09-16 16:09:58 -0700222 }
223
alshabib219ebaa2014-09-22 15:41:24 -0700224 private void removeRule(FlowRule flowRule) {
jcc3d4e14a2015-04-21 11:32:05 +0800225 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId()
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700226 .uri()));
Thomas Vachuskaa6c0d042015-04-23 10:17:37 -0700227 FlowRuleExtPayLoad flowRuleExtPayLoad = flowRule.payLoad();
228 if (hasPayload(flowRuleExtPayLoad)) {
229 OFMessage msg = new ThirdPartyMessage(flowRuleExtPayLoad.payLoad());
jcc3d4e14a2015-04-21 11:32:05 +0800230 sw.sendMsg(msg);
231 return;
232 }
alshabibbdcbb102015-04-22 14:16:38 -0700233 sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
jcc3d4e14a2015-04-21 11:32:05 +0800234 Optional.empty()).buildFlowDel());
alshabib219ebaa2014-09-22 15:41:24 -0700235 }
236
alshabiba68eb962014-09-24 20:34:13 -0700237 @Override
238 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
239 // TODO: optimize using the ApplicationId
240 removeFlowRule(flowRules);
241 }
242
alshabib193525b2014-10-08 18:58:03 -0700243 @Override
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800244 public void executeBatch(FlowRuleBatchOperation batch) {
245
246 pendingBatches.put(batch.id(), new InternalCacheEntry(batch));
247
jcc3d4e14a2015-04-21 11:32:05 +0800248 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(batch.deviceId()
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700249 .uri()));
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800250 OFFlowMod mod;
alshabib193525b2014-10-08 18:58:03 -0700251 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
jcc3d4e14a2015-04-21 11:32:05 +0800252 // flow is the third party privacy flow
Thomas Vachuskaa6c0d042015-04-23 10:17:37 -0700253
254 FlowRuleExtPayLoad flowRuleExtPayLoad = fbe.target().payLoad();
255 if (hasPayload(flowRuleExtPayLoad)) {
256 OFMessage msg = new ThirdPartyMessage(flowRuleExtPayLoad.payLoad());
jcc3d4e14a2015-04-21 11:32:05 +0800257 sw.sendMsg(msg);
258 continue;
259 }
260 FlowModBuilder builder = FlowModBuilder.builder(fbe.target(), sw
261 .factory(), Optional.of(batch.id()));
Sho SHIMIZUaba9d002015-01-29 14:51:04 -0800262 switch (fbe.operator()) {
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700263 case ADD:
264 mod = builder.buildFlowAdd();
265 break;
266 case REMOVE:
267 mod = builder.buildFlowDel();
268 break;
269 case MODIFY:
270 mod = builder.buildFlowMod();
271 break;
272 default:
273 log.error("Unsupported batch operation {}; skipping flowmod {}",
274 fbe.operator(), fbe);
275 continue;
jcc3d4e14a2015-04-21 11:32:05 +0800276 }
Saurav Das3ea46622015-04-22 14:01:34 -0700277 sw.sendMsg(mod);
alshabib193525b2014-10-08 18:58:03 -0700278 }
jcc3d4e14a2015-04-21 11:32:05 +0800279 OFBarrierRequest.Builder builder = sw.factory().buildBarrierRequest()
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800280 .setXid(batch.id());
281 sw.sendMsg(builder.build());
alshabib193525b2014-10-08 18:58:03 -0700282 }
283
Thomas Vachuskaa6c0d042015-04-23 10:17:37 -0700284 private boolean hasPayload(FlowRuleExtPayLoad flowRuleExtPayLoad) {
285 return flowRuleExtPayLoad != null &&
286 flowRuleExtPayLoad.payLoad() != null &&
287 flowRuleExtPayLoad.payLoad().length > 0;
288 }
289
alshabib8f1cf4a2014-09-17 14:44:48 -0700290 private class InternalFlowProvider
Thomas Vachuska9b2da212014-11-10 19:30:25 -0800291 implements OpenFlowSwitchListener, OpenFlowEventListener {
alshabib8f1cf4a2014-09-17 14:44:48 -0700292
alshabib8f1cf4a2014-09-17 14:44:48 -0700293 @Override
294 public void switchAdded(Dpid dpid) {
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700295 createCollector(controller.getSwitch(dpid));
alshabib8f1cf4a2014-09-17 14:44:48 -0700296 }
297
298 @Override
299 public void switchRemoved(Dpid dpid) {
alshabibdfc7afb2014-10-21 20:13:27 -0700300 FlowStatsCollector collector = collectors.remove(dpid);
301 if (collector != null) {
302 collector.stop();
303 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700304 }
305
306 @Override
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700307 public void switchChanged(Dpid dpid) {
308 }
309
310 @Override
alshabib8f1cf4a2014-09-17 14:44:48 -0700311 public void portChanged(Dpid dpid, OFPortStatus status) {
jcc3d4e14a2015-04-21 11:32:05 +0800312 // TODO: Decide whether to evict flows internal store.
alshabib8f1cf4a2014-09-17 14:44:48 -0700313 }
314
315 @Override
316 public void handleMessage(Dpid dpid, OFMessage msg) {
alshabibda1644e2015-03-13 14:01:35 -0700317 OpenFlowSwitch sw = controller.getSwitch(dpid);
alshabib8f1cf4a2014-09-17 14:44:48 -0700318 switch (msg.getType()) {
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700319 case FLOW_REMOVED:
320 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700321
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700322 FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
323 providerService.flowRemoved(fr);
324 break;
325 case STATS_REPLY:
326 if (((OFStatsReply) msg).getStatsType() == OFStatsType.FLOW) {
327 pushFlowMetrics(dpid, (OFFlowStatsReply) msg);
sangho89bf6fb2015-02-09 09:33:13 -0800328 }
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700329 break;
330 case BARRIER_REPLY:
331 try {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700332 InternalCacheEntry entry = pendingBatches.getIfPresent(msg.getXid());
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800333 if (entry != null) {
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700334 providerService
335 .batchOperationCompleted(msg.getXid(),
336 entry.completed());
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800337 } else {
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700338 log.warn("Received unknown Barrier Reply: {}",
339 msg.getXid());
340 }
341 } finally {
342 pendingBatches.invalidate(msg.getXid());
343 }
344 break;
345 case ERROR:
Thomas Vachuska3358af22015-05-19 18:40:34 -0700346 // TODO: This needs to get suppressed in a better way.
347 if (msg instanceof OFBadRequestErrorMsg &&
348 ((OFBadRequestErrorMsg) msg).getCode() == OFBadRequestCode.BAD_TYPE) {
349 log.debug("Received error message {} from {}", msg, dpid);
350 } else {
351 log.warn("Received error message {} from {}", msg, dpid);
352 }
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700353
354 OFErrorMsg error = (OFErrorMsg) msg;
355 if (error.getErrType() == OFErrorType.FLOW_MOD_FAILED) {
356 OFFlowModFailedErrorMsg fmFailed = (OFFlowModFailedErrorMsg) error;
357 if (fmFailed.getData().getParsedMessage().isPresent()) {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700358 OFMessage m = fmFailed.getData().getParsedMessage().get();
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700359 OFFlowMod fm = (OFFlowMod) m;
Thomas Vachuska3358af22015-05-19 18:40:34 -0700360 InternalCacheEntry entry =
361 pendingBatches.getIfPresent(msg.getXid());
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700362 if (entry != null) {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700363 entry.appendFailure(new FlowEntryBuilder(dpid, fm).build());
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700364 } else {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700365 log.error("No matching batch for this error: {}", error);
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700366 }
367 } else {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700368 // FIXME: Potentially add flowtracking to avoid this message.
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700369 log.error("Flow installation failed but switch didn't"
370 + " tell us which one.");
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800371 }
Thomas Vachuska9b2da212014-11-10 19:30:25 -0800372 }
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800373
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700374 default:
375 log.debug("Unhandled message type: {}", msg.getType());
alshabib8f1cf4a2014-09-17 14:44:48 -0700376 }
377
378 }
379
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700380 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700381 public void receivedRoleReply(Dpid dpid, RoleState requested,
Thomas Vachuska9b2da212014-11-10 19:30:25 -0800382 RoleState response) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700383 // Do nothing here for now.
384 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700385
sangho89bf6fb2015-02-09 09:33:13 -0800386 private void pushFlowMetrics(Dpid dpid, OFFlowStatsReply replies) {
alshabib64def642014-12-02 23:27:37 -0800387
alshabib54ce5892014-09-23 17:50:51 -0700388 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
Saurav Dasfa2fa932015-03-03 11:29:48 -0800389 OpenFlowSwitch sw = controller.getSwitch(dpid);
alshabib54ce5892014-09-23 17:50:51 -0700390
alshabib64def642014-12-02 23:27:37 -0800391 List<FlowEntry> flowEntries = replies.getEntries().stream()
alshabibbdcbb102015-04-22 14:16:38 -0700392 .map(entry -> new FlowEntryBuilder(dpid, entry).build())
alshabib64def642014-12-02 23:27:37 -0800393 .collect(Collectors.toList());
alshabib54ce5892014-09-23 17:50:51 -0700394
alshabib64def642014-12-02 23:27:37 -0800395 providerService.pushFlowMetrics(did, flowEntries);
alshabib5c370ff2014-09-18 10:12:14 -0700396 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700397 }
alshabib1cc04f72014-09-16 16:09:58 -0700398
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800399 /**
jcc3d4e14a2015-04-21 11:32:05 +0800400 * The internal cache entry holding the original request as well as
401 * accumulating the any failures along the way.
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700402 * <p/>
jcc3d4e14a2015-04-21 11:32:05 +0800403 * If this entry is evicted from the cache then the entire operation is
404 * considered failed. Otherwise, only the failures reported by the device
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800405 * will be propagated up.
406 */
407 private class InternalCacheEntry {
alshabib902d41b2014-10-07 16:52:05 -0700408
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800409 private final FlowRuleBatchOperation operation;
410 private final Set<FlowRule> failures = Sets.newConcurrentHashSet();
alshabib193525b2014-10-08 18:58:03 -0700411
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800412 public InternalCacheEntry(FlowRuleBatchOperation operation) {
413 this.operation = operation;
alshabib902d41b2014-10-07 16:52:05 -0700414 }
415
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800416 /**
417 * Appends a failed rule to the set of failed items.
jcc3d4e14a2015-04-21 11:32:05 +0800418 *
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800419 * @param rule the failed rule
420 */
421 public void appendFailure(FlowRule rule) {
422 failures.add(rule);
Thomas Vachuska9b2da212014-11-10 19:30:25 -0800423 }
424
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800425 /**
426 * Fails the entire batch and returns the failed operation.
jcc3d4e14a2015-04-21 11:32:05 +0800427 *
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800428 * @return the failed operation
429 */
430 public CompletedBatchOperation failedCompletion() {
431 Set<FlowRule> fails = operation.getOperations().stream()
432 .map(op -> op.target()).collect(Collectors.toSet());
jcc3d4e14a2015-04-21 11:32:05 +0800433 return new CompletedBatchOperation(false,
434 Collections
435 .unmodifiableSet(fails),
436 operation.deviceId());
alshabib902d41b2014-10-07 16:52:05 -0700437 }
438
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800439 /**
440 * Returns the completed operation and whether the batch suceeded.
jcc3d4e14a2015-04-21 11:32:05 +0800441 *
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800442 * @return the completed operation
443 */
444 public CompletedBatchOperation completed() {
jcc3d4e14a2015-04-21 11:32:05 +0800445 return new CompletedBatchOperation(
Thomas Vachuska75aaa672015-04-29 12:24:43 -0700446 failures.isEmpty(),
447 Collections
448 .unmodifiableSet(failures),
449 operation.deviceId());
alshabib902d41b2014-10-07 16:52:05 -0700450 }
alshabib902d41b2014-10-07 16:52:05 -0700451 }
alshabiba68eb962014-09-24 20:34:13 -0700452
alshabib1cc04f72014-09-16 16:09:58 -0700453}