blob: b11eb0c6984ccd0f0f98b8340c62da37998c376e [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
alshabibb45d1962014-09-18 14:25:45 -07005import java.util.List;
alshabibeec3a062014-09-17 18:01:26 -07006import java.util.Map;
7
alshabib1cc04f72014-09-16 16:09:58 -07008import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
11import org.apache.felix.scr.annotations.Reference;
12import org.apache.felix.scr.annotations.ReferenceCardinality;
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;
31import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib1cc04f72014-09-16 16:09:58 -070032import org.slf4j.Logger;
33
alshabib5c370ff2014-09-18 10:12:14 -070034import com.google.common.collect.Lists;
35import com.google.common.collect.Maps;
alshabibeec3a062014-09-17 18:01:26 -070036
alshabib1cc04f72014-09-16 16:09:58 -070037/**
38 * Provider which uses an OpenFlow controller to detect network
39 * end-station hosts.
40 */
41@Component(immediate = true)
42public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
43
44 private final Logger log = getLogger(getClass());
45
46 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
47 protected FlowRuleProviderRegistry providerRegistry;
48
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected OpenFlowController controller;
51
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected TopologyService topologyService;
54
55 private FlowRuleProviderService providerService;
56
alshabibeec3a062014-09-17 18:01:26 -070057 private final InternalFlowProvider listener = new InternalFlowProvider();
58
alshabib1cc04f72014-09-16 16:09:58 -070059 /**
60 * Creates an OpenFlow host provider.
61 */
62 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -070063 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -070064 }
65
66 @Activate
67 public void activate() {
68 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -070069 controller.addListener(listener);
70 controller.addEventListener(listener);
alshabib1cc04f72014-09-16 16:09:58 -070071 log.info("Started");
72 }
73
74 @Deactivate
75 public void deactivate() {
76 providerRegistry.unregister(this);
77 providerService = null;
78
79 log.info("Stopped");
80 }
81 @Override
82 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -070083 for (int i = 0; i < flowRules.length; i++) {
84 applyRule(flowRules[i]);
85 }
alshabib1cc04f72014-09-16 16:09:58 -070086 }
87
alshabib35edb1a2014-09-16 17:44:44 -070088 private void applyRule(FlowRule flowRule) {
89 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib8f1cf4a2014-09-17 14:44:48 -070090 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod());
alshabib35edb1a2014-09-16 17:44:44 -070091 }
92
alshabib35edb1a2014-09-16 17:44:44 -070093
alshabib35edb1a2014-09-16 17:44:44 -070094
alshabib1cc04f72014-09-16 16:09:58 -070095 @Override
96 public void removeFlowRule(FlowRule... flowRules) {
97 // TODO Auto-generated method stub
98
99 }
100
alshabib1cc04f72014-09-16 16:09:58 -0700101
102 //TODO: InternalFlowRuleProvider listening to stats and error and flowremoved.
103 // possibly barriers as well. May not be internal at all...
alshabib8f1cf4a2014-09-17 14:44:48 -0700104 private class InternalFlowProvider
105 implements OpenFlowSwitchListener, OpenFlowEventListener {
106
alshabibeec3a062014-09-17 18:01:26 -0700107 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
alshabib8f1cf4a2014-09-17 14:44:48 -0700108
109 @Override
110 public void switchAdded(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700111 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), 1);
112 fsc.start();
113 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700114 }
115
116 @Override
117 public void switchRemoved(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700118 collectors.remove(dpid).stop();
alshabib8f1cf4a2014-09-17 14:44:48 -0700119 }
120
121 @Override
122 public void portChanged(Dpid dpid, OFPortStatus status) {
123 //TODO: Decide whether to evict flows internal store.
124 }
125
126 @Override
127 public void handleMessage(Dpid dpid, OFMessage msg) {
128 switch (msg.getType()) {
129 case FLOW_REMOVED:
alshabibeec3a062014-09-17 18:01:26 -0700130 //TODO: make this better
alshabib8f1cf4a2014-09-17 14:44:48 -0700131 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700132
133 FlowRule fr = new FlowRuleBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700134 providerService.flowRemoved(fr);
135 break;
136 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700137 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700138 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700139 case BARRIER_REPLY:
140 case ERROR:
141 default:
142 log.warn("Unhandled message type: {}", msg.getType());
143 }
144
145 }
146
alshabib97044902014-09-18 14:52:16 -0700147 private void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700148 if (stats.getStatsType() != OFStatsType.FLOW) {
149 return;
150 }
151 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabibb45d1962014-09-18 14:25:45 -0700152 final List<FlowRule> entries = Lists.newLinkedList();
alshabib5c370ff2014-09-18 10:12:14 -0700153 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib97044902014-09-18 14:52:16 -0700154 entries.add(new FlowRuleBuilder(dpid, reply).build());
alshabib5c370ff2014-09-18 10:12:14 -0700155 }
alshabib6b5cfec2014-09-18 17:42:18 -0700156 log.debug("sending flowstats to core {}", entries);
alshabibb45d1962014-09-18 14:25:45 -0700157 providerService.pushFlowMetrics(entries);
alshabib5c370ff2014-09-18 10:12:14 -0700158 }
159
alshabib8f1cf4a2014-09-17 14:44:48 -0700160 }
alshabib1cc04f72014-09-16 16:09:58 -0700161
162
163}