blob: eeffe85ad7500130857d9135b5b896738ecdcbb3 [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;
alshabiba7f7ca82014-09-22 11:41:23 -070012import org.onlab.onos.net.DeviceId;
alshabib1cc04f72014-09-16 16:09:58 -070013import org.onlab.onos.net.flow.FlowRule;
14import org.onlab.onos.net.flow.FlowRuleProvider;
15import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
16import org.onlab.onos.net.flow.FlowRuleProviderService;
17import org.onlab.onos.net.provider.AbstractProvider;
18import org.onlab.onos.net.provider.ProviderId;
19import org.onlab.onos.net.topology.TopologyService;
tom9c94c5b2014-09-17 13:14:42 -070020import org.onlab.onos.openflow.controller.Dpid;
21import org.onlab.onos.openflow.controller.OpenFlowController;
alshabibeec3a062014-09-17 18:01:26 -070022import org.onlab.onos.openflow.controller.OpenFlowEventListener;
tom9c94c5b2014-09-17 13:14:42 -070023import org.onlab.onos.openflow.controller.OpenFlowSwitch;
alshabibce4e5782014-09-17 14:56:42 -070024import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
alshabib8f1cf4a2014-09-17 14:44:48 -070025import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070026import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
27import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib8f1cf4a2014-09-17 14:44:48 -070028import org.projectfloodlight.openflow.protocol.OFMessage;
29import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070030import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib54ce5892014-09-23 17:50:51 -070031import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
alshabib5c370ff2014-09-18 10:12:14 -070032import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib1cc04f72014-09-16 16:09:58 -070033import org.slf4j.Logger;
34
alshabib54ce5892014-09-23 17:50:51 -070035import com.google.common.collect.ArrayListMultimap;
alshabib5c370ff2014-09-18 10:12:14 -070036import com.google.common.collect.Maps;
alshabib54ce5892014-09-23 17:50:51 -070037import com.google.common.collect.Multimap;
alshabibeec3a062014-09-17 18:01:26 -070038
alshabib1cc04f72014-09-16 16:09:58 -070039/**
40 * Provider which uses an OpenFlow controller to detect network
41 * end-station hosts.
42 */
43@Component(immediate = true)
44public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
45
46 private final Logger log = getLogger(getClass());
47
48 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 protected FlowRuleProviderRegistry providerRegistry;
50
51 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 protected OpenFlowController controller;
53
54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 protected TopologyService topologyService;
56
57 private FlowRuleProviderService providerService;
58
alshabibeec3a062014-09-17 18:01:26 -070059 private final InternalFlowProvider listener = new InternalFlowProvider();
60
alshabib1cc04f72014-09-16 16:09:58 -070061 /**
62 * Creates an OpenFlow host provider.
63 */
64 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -070065 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -070066 }
67
68 @Activate
69 public void activate() {
70 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -070071 controller.addListener(listener);
72 controller.addEventListener(listener);
alshabib1cc04f72014-09-16 16:09:58 -070073 log.info("Started");
74 }
75
76 @Deactivate
77 public void deactivate() {
78 providerRegistry.unregister(this);
79 providerService = null;
80
81 log.info("Stopped");
82 }
83 @Override
84 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -070085 for (int i = 0; i < flowRules.length; i++) {
86 applyRule(flowRules[i]);
87 }
alshabib1cc04f72014-09-16 16:09:58 -070088 }
89
alshabib35edb1a2014-09-16 17:44:44 -070090 private void applyRule(FlowRule flowRule) {
91 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib8f1cf4a2014-09-17 14:44:48 -070092 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod());
alshabib35edb1a2014-09-16 17:44:44 -070093 }
94
alshabib35edb1a2014-09-16 17:44:44 -070095
alshabib35edb1a2014-09-16 17:44:44 -070096
alshabib1cc04f72014-09-16 16:09:58 -070097 @Override
98 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -070099 for (int i = 0; i < flowRules.length; i++) {
100 removeRule(flowRules[i]);
101 }
alshabib1cc04f72014-09-16 16:09:58 -0700102
103 }
104
alshabib1cc04f72014-09-16 16:09:58 -0700105
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
111
alshabib1cc04f72014-09-16 16:09:58 -0700112 //TODO: InternalFlowRuleProvider listening to stats and error and flowremoved.
113 // possibly barriers as well. May not be internal at all...
alshabib8f1cf4a2014-09-17 14:44:48 -0700114 private class InternalFlowProvider
115 implements OpenFlowSwitchListener, OpenFlowEventListener {
116
alshabibeec3a062014-09-17 18:01:26 -0700117 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
alshabib54ce5892014-09-23 17:50:51 -0700118 private final Multimap<DeviceId, FlowRule> completeEntries =
119 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700120
121 @Override
122 public void switchAdded(Dpid dpid) {
alshabib219ebaa2014-09-22 15:41:24 -0700123 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), 5);
alshabibeec3a062014-09-17 18:01:26 -0700124 fsc.start();
125 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700126 }
127
128 @Override
129 public void switchRemoved(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700130 collectors.remove(dpid).stop();
alshabib8f1cf4a2014-09-17 14:44:48 -0700131 }
132
133 @Override
134 public void portChanged(Dpid dpid, OFPortStatus status) {
135 //TODO: Decide whether to evict flows internal store.
136 }
137
138 @Override
139 public void handleMessage(Dpid dpid, OFMessage msg) {
140 switch (msg.getType()) {
141 case FLOW_REMOVED:
alshabibeec3a062014-09-17 18:01:26 -0700142 //TODO: make this better
alshabib8f1cf4a2014-09-17 14:44:48 -0700143 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700144
145 FlowRule fr = new FlowRuleBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700146 providerService.flowRemoved(fr);
147 break;
148 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700149 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700150 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700151 case BARRIER_REPLY:
152 case ERROR:
153 default:
154 log.warn("Unhandled message type: {}", msg.getType());
155 }
156
157 }
158
alshabib54ce5892014-09-23 17:50:51 -0700159 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700160 if (stats.getStatsType() != OFStatsType.FLOW) {
161 return;
162 }
alshabib54ce5892014-09-23 17:50:51 -0700163 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700164 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700165 //final List<FlowRule> entries = Lists.newLinkedList();
166
alshabib5c370ff2014-09-18 10:12:14 -0700167 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib54ce5892014-09-23 17:50:51 -0700168 completeEntries.put(did, new FlowRuleBuilder(dpid, reply).build());
169 //entries.add(new FlowRuleBuilder(dpid, reply).build());
alshabib5c370ff2014-09-18 10:12:14 -0700170 }
alshabib54ce5892014-09-23 17:50:51 -0700171
172 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
173 log.debug("sending flowstats to core {}", completeEntries.get(did));
174 providerService.pushFlowMetrics(did, completeEntries.get(did));
175 completeEntries.removeAll(did);
176 }
alshabib5c370ff2014-09-18 10:12:14 -0700177 }
178
alshabib8f1cf4a2014-09-17 14:44:48 -0700179 }
alshabib1cc04f72014-09-16 16:09:58 -0700180
181
182}