blob: 7ddc65d2f65374bfd3978a8febf1f53d8f0d8bcd [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;
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;
32import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib1cc04f72014-09-16 16:09:58 -070033import org.slf4j.Logger;
34
alshabib5c370ff2014-09-18 10:12:14 -070035import com.google.common.collect.Lists;
36import com.google.common.collect.Maps;
alshabibeec3a062014-09-17 18:01:26 -070037
alshabib1cc04f72014-09-16 16:09:58 -070038/**
39 * Provider which uses an OpenFlow controller to detect network
40 * end-station hosts.
41 */
42@Component(immediate = true)
43public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
44
45 private final Logger log = getLogger(getClass());
46
47 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
48 protected FlowRuleProviderRegistry providerRegistry;
49
50 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected OpenFlowController controller;
52
53 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 protected TopologyService topologyService;
55
56 private FlowRuleProviderService providerService;
57
alshabibeec3a062014-09-17 18:01:26 -070058 private final InternalFlowProvider listener = new InternalFlowProvider();
59
alshabib1cc04f72014-09-16 16:09:58 -070060 /**
61 * Creates an OpenFlow host provider.
62 */
63 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -070064 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -070065 }
66
67 @Activate
68 public void activate() {
69 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -070070 controller.addListener(listener);
71 controller.addEventListener(listener);
alshabib1cc04f72014-09-16 16:09:58 -070072 log.info("Started");
73 }
74
75 @Deactivate
76 public void deactivate() {
77 providerRegistry.unregister(this);
78 providerService = null;
79
80 log.info("Stopped");
81 }
82 @Override
83 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -070084 for (int i = 0; i < flowRules.length; i++) {
85 applyRule(flowRules[i]);
86 }
alshabib1cc04f72014-09-16 16:09:58 -070087 }
88
alshabib35edb1a2014-09-16 17:44:44 -070089 private void applyRule(FlowRule flowRule) {
90 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib8f1cf4a2014-09-17 14:44:48 -070091 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod());
alshabib35edb1a2014-09-16 17:44:44 -070092 }
93
alshabib35edb1a2014-09-16 17:44:44 -070094
alshabib35edb1a2014-09-16 17:44:44 -070095
alshabib1cc04f72014-09-16 16:09:58 -070096 @Override
97 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -070098 for (int i = 0; i < flowRules.length; i++) {
99 removeRule(flowRules[i]);
100 }
alshabib1cc04f72014-09-16 16:09:58 -0700101
102 }
103
alshabib1cc04f72014-09-16 16:09:58 -0700104
alshabib219ebaa2014-09-22 15:41:24 -0700105 private void removeRule(FlowRule flowRule) {
106 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
107 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
108 }
109
110
alshabib1cc04f72014-09-16 16:09:58 -0700111 //TODO: InternalFlowRuleProvider listening to stats and error and flowremoved.
112 // possibly barriers as well. May not be internal at all...
alshabib8f1cf4a2014-09-17 14:44:48 -0700113 private class InternalFlowProvider
114 implements OpenFlowSwitchListener, OpenFlowEventListener {
115
alshabibeec3a062014-09-17 18:01:26 -0700116 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
alshabib8f1cf4a2014-09-17 14:44:48 -0700117
118 @Override
119 public void switchAdded(Dpid dpid) {
alshabib219ebaa2014-09-22 15:41:24 -0700120 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), 5);
alshabibeec3a062014-09-17 18:01:26 -0700121 fsc.start();
122 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700123 }
124
125 @Override
126 public void switchRemoved(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700127 collectors.remove(dpid).stop();
alshabib8f1cf4a2014-09-17 14:44:48 -0700128 }
129
130 @Override
131 public void portChanged(Dpid dpid, OFPortStatus status) {
132 //TODO: Decide whether to evict flows internal store.
133 }
134
135 @Override
136 public void handleMessage(Dpid dpid, OFMessage msg) {
137 switch (msg.getType()) {
138 case FLOW_REMOVED:
alshabibeec3a062014-09-17 18:01:26 -0700139 //TODO: make this better
alshabib8f1cf4a2014-09-17 14:44:48 -0700140 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700141
142 FlowRule fr = new FlowRuleBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700143 providerService.flowRemoved(fr);
144 break;
145 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700146 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700147 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700148 case BARRIER_REPLY:
149 case ERROR:
150 default:
151 log.warn("Unhandled message type: {}", msg.getType());
152 }
153
154 }
155
alshabib97044902014-09-18 14:52:16 -0700156 private void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700157 if (stats.getStatsType() != OFStatsType.FLOW) {
158 return;
159 }
160 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabibb45d1962014-09-18 14:25:45 -0700161 final List<FlowRule> entries = Lists.newLinkedList();
alshabib5c370ff2014-09-18 10:12:14 -0700162 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib97044902014-09-18 14:52:16 -0700163 entries.add(new FlowRuleBuilder(dpid, reply).build());
alshabib5c370ff2014-09-18 10:12:14 -0700164 }
alshabib6b5cfec2014-09-18 17:42:18 -0700165 log.debug("sending flowstats to core {}", entries);
alshabiba7f7ca82014-09-22 11:41:23 -0700166 providerService.pushFlowMetrics(DeviceId.deviceId(Dpid.uri(dpid)), entries);
alshabib5c370ff2014-09-18 10:12:14 -0700167 }
168
alshabib8f1cf4a2014-09-17 14:44:48 -0700169 }
alshabib1cc04f72014-09-16 16:09:58 -0700170
171
172}