blob: 4ab2a8b78b36eae5e199eeef5f8316864ef74e14 [file] [log] [blame]
alshabib1cc04f72014-09-16 16:09:58 -07001package org.onlab.onos.provider.of.flow.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
alshabibeec3a062014-09-17 18:01:26 -07005import java.util.Map;
6
alshabib1cc04f72014-09-16 16:09:58 -07007import org.apache.felix.scr.annotations.Activate;
8import org.apache.felix.scr.annotations.Component;
9import org.apache.felix.scr.annotations.Deactivate;
10import org.apache.felix.scr.annotations.Reference;
11import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabiba68eb962014-09-24 20:34:13 -070012import org.onlab.onos.ApplicationId;
alshabiba7f7ca82014-09-22 11:41:23 -070013import org.onlab.onos.net.DeviceId;
alshabib1cc04f72014-09-16 16:09:58 -070014import org.onlab.onos.net.flow.FlowRule;
15import org.onlab.onos.net.flow.FlowRuleProvider;
16import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
17import org.onlab.onos.net.flow.FlowRuleProviderService;
18import org.onlab.onos.net.provider.AbstractProvider;
19import org.onlab.onos.net.provider.ProviderId;
20import org.onlab.onos.net.topology.TopologyService;
tom9c94c5b2014-09-17 13:14:42 -070021import org.onlab.onos.openflow.controller.Dpid;
22import org.onlab.onos.openflow.controller.OpenFlowController;
alshabibeec3a062014-09-17 18:01:26 -070023import org.onlab.onos.openflow.controller.OpenFlowEventListener;
tom9c94c5b2014-09-17 13:14:42 -070024import org.onlab.onos.openflow.controller.OpenFlowSwitch;
alshabibce4e5782014-09-17 14:56:42 -070025import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
alshabib8f1cf4a2014-09-17 14:44:48 -070026import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070027import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
28import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib8f1cf4a2014-09-17 14:44:48 -070029import org.projectfloodlight.openflow.protocol.OFMessage;
30import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070031import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib54ce5892014-09-23 17:50:51 -070032import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
alshabib5c370ff2014-09-18 10:12:14 -070033import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib1cc04f72014-09-16 16:09:58 -070034import org.slf4j.Logger;
35
alshabib54ce5892014-09-23 17:50:51 -070036import com.google.common.collect.ArrayListMultimap;
alshabib5c370ff2014-09-18 10:12:14 -070037import com.google.common.collect.Maps;
alshabib54ce5892014-09-23 17:50:51 -070038import com.google.common.collect.Multimap;
alshabibeec3a062014-09-17 18:01:26 -070039
alshabib1cc04f72014-09-16 16:09:58 -070040/**
41 * Provider which uses an OpenFlow controller to detect network
42 * end-station hosts.
43 */
44@Component(immediate = true)
45public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
46
47 private final Logger log = getLogger(getClass());
48
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected FlowRuleProviderRegistry providerRegistry;
51
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected OpenFlowController controller;
54
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected TopologyService topologyService;
57
58 private FlowRuleProviderService providerService;
59
alshabibeec3a062014-09-17 18:01:26 -070060 private final InternalFlowProvider listener = new InternalFlowProvider();
61
alshabib1cc04f72014-09-16 16:09:58 -070062 /**
63 * Creates an OpenFlow host provider.
64 */
65 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -070066 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -070067 }
68
69 @Activate
70 public void activate() {
71 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -070072 controller.addListener(listener);
73 controller.addEventListener(listener);
alshabib1cc04f72014-09-16 16:09:58 -070074 log.info("Started");
75 }
76
77 @Deactivate
78 public void deactivate() {
79 providerRegistry.unregister(this);
80 providerService = null;
81
82 log.info("Stopped");
83 }
84 @Override
85 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -070086 for (int i = 0; i < flowRules.length; i++) {
87 applyRule(flowRules[i]);
88 }
alshabib1cc04f72014-09-16 16:09:58 -070089 }
90
alshabib35edb1a2014-09-16 17:44:44 -070091 private void applyRule(FlowRule flowRule) {
92 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib8f1cf4a2014-09-17 14:44:48 -070093 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod());
alshabib35edb1a2014-09-16 17:44:44 -070094 }
95
alshabib35edb1a2014-09-16 17:44:44 -070096
alshabib35edb1a2014-09-16 17:44:44 -070097
alshabib1cc04f72014-09-16 16:09:58 -070098 @Override
99 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -0700100 for (int i = 0; i < flowRules.length; i++) {
101 removeRule(flowRules[i]);
102 }
alshabib1cc04f72014-09-16 16:09:58 -0700103
104 }
105
alshabib219ebaa2014-09-22 15:41:24 -0700106 private void removeRule(FlowRule flowRule) {
107 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
108 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
109 }
110
alshabiba68eb962014-09-24 20:34:13 -0700111 @Override
112 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
113 // TODO: optimize using the ApplicationId
114 removeFlowRule(flowRules);
115 }
116
alshabib219ebaa2014-09-22 15:41:24 -0700117
alshabib1cc04f72014-09-16 16:09:58 -0700118 //TODO: InternalFlowRuleProvider listening to stats and error and flowremoved.
119 // possibly barriers as well. May not be internal at all...
alshabib8f1cf4a2014-09-17 14:44:48 -0700120 private class InternalFlowProvider
121 implements OpenFlowSwitchListener, OpenFlowEventListener {
122
alshabibeec3a062014-09-17 18:01:26 -0700123 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
alshabib54ce5892014-09-23 17:50:51 -0700124 private final Multimap<DeviceId, FlowRule> completeEntries =
125 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700126
127 @Override
128 public void switchAdded(Dpid dpid) {
alshabib219ebaa2014-09-22 15:41:24 -0700129 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), 5);
alshabibeec3a062014-09-17 18:01:26 -0700130 fsc.start();
131 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700132 }
133
134 @Override
135 public void switchRemoved(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700136 collectors.remove(dpid).stop();
alshabib8f1cf4a2014-09-17 14:44:48 -0700137 }
138
139 @Override
140 public void portChanged(Dpid dpid, OFPortStatus status) {
141 //TODO: Decide whether to evict flows internal store.
142 }
143
144 @Override
145 public void handleMessage(Dpid dpid, OFMessage msg) {
146 switch (msg.getType()) {
147 case FLOW_REMOVED:
alshabibeec3a062014-09-17 18:01:26 -0700148 //TODO: make this better
alshabib8f1cf4a2014-09-17 14:44:48 -0700149 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700150
151 FlowRule fr = new FlowRuleBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700152 providerService.flowRemoved(fr);
153 break;
154 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700155 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700156 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700157 case BARRIER_REPLY:
158 case ERROR:
159 default:
160 log.warn("Unhandled message type: {}", msg.getType());
161 }
162
163 }
164
alshabib54ce5892014-09-23 17:50:51 -0700165 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700166 if (stats.getStatsType() != OFStatsType.FLOW) {
167 return;
168 }
alshabib54ce5892014-09-23 17:50:51 -0700169 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700170 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700171 //final List<FlowRule> entries = Lists.newLinkedList();
172
alshabib5c370ff2014-09-18 10:12:14 -0700173 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib54ce5892014-09-23 17:50:51 -0700174 completeEntries.put(did, new FlowRuleBuilder(dpid, reply).build());
175 //entries.add(new FlowRuleBuilder(dpid, reply).build());
alshabib5c370ff2014-09-18 10:12:14 -0700176 }
alshabib54ce5892014-09-23 17:50:51 -0700177
178 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
179 log.debug("sending flowstats to core {}", completeEntries.get(did));
180 providerService.pushFlowMetrics(did, completeEntries.get(did));
181 completeEntries.removeAll(did);
182 }
alshabib5c370ff2014-09-18 10:12:14 -0700183 }
184
alshabib8f1cf4a2014-09-17 14:44:48 -0700185 }
alshabib1cc04f72014-09-16 16:09:58 -0700186
187
alshabiba68eb962014-09-24 20:34:13 -0700188
189
alshabib1cc04f72014-09-16 16:09:58 -0700190}