blob: 1b670993c40e1916b4c4712255f2d81534a9008b [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
alshabib35edb1a2014-09-16 17:44:44 -07005import java.util.Collections;
6import java.util.LinkedList;
7import java.util.List;
8
alshabib1cc04f72014-09-16 16:09:58 -07009import org.apache.felix.scr.annotations.Activate;
10import org.apache.felix.scr.annotations.Component;
11import org.apache.felix.scr.annotations.Deactivate;
12import org.apache.felix.scr.annotations.Reference;
13import org.apache.felix.scr.annotations.ReferenceCardinality;
14import org.onlab.onos.net.DeviceId;
15import org.onlab.onos.net.flow.FlowEntry;
16import org.onlab.onos.net.flow.FlowRule;
17import org.onlab.onos.net.flow.FlowRuleProvider;
18import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
19import org.onlab.onos.net.flow.FlowRuleProviderService;
alshabib35edb1a2014-09-16 17:44:44 -070020import org.onlab.onos.net.flow.criteria.Criteria.EthCriterion;
21import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion;
22import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion;
23import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion;
24import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion;
25import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion;
26import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion;
27import org.onlab.onos.net.flow.criteria.Criterion;
28import org.onlab.onos.net.flow.instructions.Instruction;
29import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
30import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
31import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
32import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
33import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
34import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
alshabib1cc04f72014-09-16 16:09:58 -070035import org.onlab.onos.net.provider.AbstractProvider;
36import org.onlab.onos.net.provider.ProviderId;
37import org.onlab.onos.net.topology.TopologyService;
alshabib35edb1a2014-09-16 17:44:44 -070038import org.onlab.onos.of.controller.Dpid;
alshabib1cc04f72014-09-16 16:09:58 -070039import org.onlab.onos.of.controller.OpenFlowController;
alshabib35edb1a2014-09-16 17:44:44 -070040import org.onlab.onos.of.controller.OpenFlowSwitch;
41import org.projectfloodlight.openflow.protocol.OFFactory;
42import org.projectfloodlight.openflow.protocol.OFFlowMod;
43import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
44import org.projectfloodlight.openflow.protocol.action.OFAction;
45import org.projectfloodlight.openflow.protocol.match.Match;
46import org.projectfloodlight.openflow.protocol.match.MatchField;
47import org.projectfloodlight.openflow.types.EthType;
48import org.projectfloodlight.openflow.types.IPv4Address;
49import org.projectfloodlight.openflow.types.IpProtocol;
50import org.projectfloodlight.openflow.types.MacAddress;
51import org.projectfloodlight.openflow.types.OFPort;
52import org.projectfloodlight.openflow.types.OFVlanVidMatch;
53import org.projectfloodlight.openflow.types.VlanPcp;
54import org.projectfloodlight.openflow.types.VlanVid;
alshabib1cc04f72014-09-16 16:09:58 -070055import org.slf4j.Logger;
56
57/**
58 * Provider which uses an OpenFlow controller to detect network
59 * end-station hosts.
60 */
61@Component(immediate = true)
62public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
63
64 private final Logger log = getLogger(getClass());
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected FlowRuleProviderRegistry providerRegistry;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected OpenFlowController controller;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected TopologyService topologyService;
74
75 private FlowRuleProviderService providerService;
76
77 /**
78 * Creates an OpenFlow host provider.
79 */
80 public OpenFlowRuleProvider() {
81 super(new ProviderId("org.onlab.onos.provider.openflow"));
82 }
83
84 @Activate
85 public void activate() {
86 providerService = providerRegistry.register(this);
87 log.info("Started");
88 }
89
90 @Deactivate
91 public void deactivate() {
92 providerRegistry.unregister(this);
93 providerService = null;
94
95 log.info("Stopped");
96 }
97 @Override
98 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -070099 for (int i = 0; i < flowRules.length; i++) {
100 applyRule(flowRules[i]);
101 }
alshabib1cc04f72014-09-16 16:09:58 -0700102
103 }
104
alshabib35edb1a2014-09-16 17:44:44 -0700105 private void applyRule(FlowRule flowRule) {
106 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
107 Match match = buildMatch(flowRule.selector().criteria(), sw.factory());
108 List<OFAction> actions =
109 buildActions(flowRule.treatment().instructions(), sw.factory());
110
111 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
112 OFFlowMod fm = sw.factory().buildFlowModify()
113 .setActions(actions)
114 .setMatch(match)
115 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
116 .setIdleTimeout(10)
117 .setHardTimeout(10)
118 .setPriority(flowRule.priority())
119 .build();
120
121 sw.sendMsg(fm);
122
123 }
124
125 private List<OFAction> buildActions(List<Instruction> instructions, OFFactory factory) {
126 List<OFAction> acts = new LinkedList<>();
127 for (Instruction i : instructions) {
128 switch (i.type()) {
129 case DROP:
130 log.warn("Saw drop action; assigning drop action");
131 return acts;
132 case L2MODIFICATION:
133 acts.add(buildL2Modification(i, factory));
134 case L3MODIFICATION:
135 acts.add(buildL3Modification(i, factory));
136 case OUTPUT:
137 break;
138 case GROUP:
139 default:
140 log.warn("Instruction type {} not yet implemented.", i.type());
141 }
142 }
143
144 return acts;
145 }
146
147 private OFAction buildL3Modification(Instruction i, OFFactory factory) {
148 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
149 ModIPInstruction ip;
150 switch (l3m.subtype()) {
151 case L3_DST:
152 ip = (ModIPInstruction) i;
153 return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
154 case L3_SRC:
155 ip = (ModIPInstruction) i;
156 return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
157 default:
158 log.warn("Unimplemented action type {}.", l3m.subtype());
159 break;
160 }
161 return null;
162 }
163
164 private OFAction buildL2Modification(Instruction i, OFFactory factory) {
165 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
166 ModEtherInstruction eth;
167 switch (l2m.subtype()) {
168 case L2_DST:
169 eth = (ModEtherInstruction) l2m;
170 return factory.actions().setDlDst(MacAddress.of(eth.mac().toLong()));
171 case L2_SRC:
172 eth = (ModEtherInstruction) l2m;
173 return factory.actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
174 case VLAN_ID:
175 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
176 return factory.actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId.toShort()));
177 case VLAN_PCP:
178 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
179 return factory.actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
180 default:
181 log.warn("Unimplemented action type {}.", l2m.subtype());
182 break;
183 }
184 return null;
185 }
186
187 private Match buildMatch(List<Criterion> criteria, OFFactory factory) {
188 Match.Builder mBuilder = factory.buildMatch();
189 EthCriterion eth;
190 IPCriterion ip;
191 for (Criterion c : criteria) {
192 switch (c.type()) {
193 case IN_PORT:
194 PortCriterion inport = (PortCriterion) c;
195 mBuilder.setExact(MatchField.IN_PORT, OFPort.of((int) inport.port().toLong()));
196 break;
197 case ETH_SRC:
198 eth = (EthCriterion) c;
199 mBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(eth.mac().toLong()));
200 break;
201 case ETH_DST:
202 eth = (EthCriterion) c;
203 mBuilder.setExact(MatchField.ETH_DST, MacAddress.of(eth.mac().toLong()));
204 break;
205 case ETH_TYPE:
206 EthTypeCriterion ethType = (EthTypeCriterion) c;
207 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType()));
208 case IPV4_DST:
209 ip = (IPCriterion) c;
210 mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toString()));
211 break;
212 case IPV4_SRC:
213 ip = (IPCriterion) c;
214 mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toString()));
215 break;
216 case IP_PROTO:
217 IPProtocolCriterion p = (IPProtocolCriterion) c;
218 mBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(p.protocol()));
219 break;
220 case VLAN_PCP:
221 VlanPcpCriterion vpcp = (VlanPcpCriterion) c;
222 mBuilder.setExact(MatchField.VLAN_PCP, VlanPcp.of(vpcp.priority()));
223 break;
224 case VLAN_VID:
225 VlanIdCriterion vid = (VlanIdCriterion) c;
226 mBuilder.setExact(MatchField.VLAN_VID,
227 OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
228 break;
229 case ARP_OP:
230 case ARP_SHA:
231 case ARP_SPA:
232 case ARP_THA:
233 case ARP_TPA:
234 case ICMPV4_CODE:
235 case ICMPV4_TYPE:
236 case ICMPV6_CODE:
237 case ICMPV6_TYPE:
238 case IN_PHY_PORT:
239 case IPV6_DST:
240 case IPV6_EXTHDR:
241 case IPV6_FLABEL:
242 case IPV6_ND_SLL:
243 case IPV6_ND_TARGET:
244 case IPV6_ND_TLL:
245 case IPV6_SRC:
246 case IP_DSCP:
247 case IP_ECN:
248 case METADATA:
249 case MPLS_BOS:
250 case MPLS_LABEL:
251 case MPLS_TC:
252 case PBB_ISID:
253 case SCTP_DST:
254 case SCTP_SRC:
255 case TCP_DST:
256 case TCP_SRC:
257 case TUNNEL_ID:
258 case UDP_DST:
259 case UDP_SRC:
260 default:
261 log.warn("Action type {} not yet implemented.", c.type());
262 }
263 }
264 return mBuilder.build();
265 }
266
alshabib1cc04f72014-09-16 16:09:58 -0700267 @Override
268 public void removeFlowRule(FlowRule... flowRules) {
269 // TODO Auto-generated method stub
270
271 }
272
273 @Override
274 public Iterable<FlowEntry> getFlowMetrics(DeviceId deviceId) {
275 // TODO Auto-generated method stub
276 return null;
277 }
278
279
280 //TODO: InternalFlowRuleProvider listening to stats and error and flowremoved.
281 // possibly barriers as well. May not be internal at all...
282
283
284}