blob: aae847623c4c71e2a4e3c53249e2e86b70c97eca [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
alshabib6b5cfec2014-09-18 17:42:18 -070019package org.onlab.onos.provider.of.flow.impl;
20
21import static org.slf4j.LoggerFactory.getLogger;
22
23import java.util.List;
24
25import org.onlab.onos.net.DeviceId;
26import org.onlab.onos.net.PortNumber;
alshabib1c319ff2014-10-04 20:29:09 -070027import org.onlab.onos.net.flow.DefaultFlowEntry;
alshabib6b5cfec2014-09-18 17:42:18 -070028import org.onlab.onos.net.flow.DefaultFlowRule;
29import org.onlab.onos.net.flow.DefaultTrafficSelector;
30import org.onlab.onos.net.flow.DefaultTrafficTreatment;
alshabib1c319ff2014-10-04 20:29:09 -070031import org.onlab.onos.net.flow.FlowEntry;
32import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
alshabib6b5cfec2014-09-18 17:42:18 -070033import org.onlab.onos.net.flow.FlowRule;
34import org.onlab.onos.net.flow.TrafficSelector;
35import org.onlab.onos.net.flow.TrafficTreatment;
alshabib6b5cfec2014-09-18 17:42:18 -070036import org.onlab.onos.openflow.controller.Dpid;
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -070037import org.onlab.packet.IpPrefix;
alshabib6b5cfec2014-09-18 17:42:18 -070038import org.onlab.packet.MacAddress;
39import org.onlab.packet.VlanId;
40import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
41import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
alshabib19fdc122014-10-03 11:38:19 -070042import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib6b5cfec2014-09-18 17:42:18 -070043import org.projectfloodlight.openflow.protocol.action.OFAction;
Marc De Leenheer49087752014-10-23 13:54:09 -070044import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
45import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
alshabib6b5cfec2014-09-18 17:42:18 -070046import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
47import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
48import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
49import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
50import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
51import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
52import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
alshabib19fdc122014-10-03 11:38:19 -070053import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Jonathan Hart86e59352014-10-22 10:42:16 -070054import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions;
alshabib6b5cfec2014-09-18 17:42:18 -070055import org.projectfloodlight.openflow.protocol.match.Match;
56import org.projectfloodlight.openflow.protocol.match.MatchField;
Marc De Leenheer49087752014-10-23 13:54:09 -070057import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
alshabib6b5cfec2014-09-18 17:42:18 -070058import org.projectfloodlight.openflow.types.IPv4Address;
Jonathan Hart0e12fad2014-10-17 14:54:58 -070059import org.projectfloodlight.openflow.types.Masked;
alshabib6b5cfec2014-09-18 17:42:18 -070060import org.slf4j.Logger;
61
alshabib19fdc122014-10-03 11:38:19 -070062import com.google.common.collect.Lists;
63
alshabib1c319ff2014-10-04 20:29:09 -070064public class FlowEntryBuilder {
alshabib6b5cfec2014-09-18 17:42:18 -070065 private final Logger log = getLogger(getClass());
66
67 private final OFFlowStatsEntry stat;
68 private final OFFlowRemoved removed;
69
70 private final Match match;
71 private final List<OFAction> actions;
72
73 private final Dpid dpid;
74
alshabib19fdc122014-10-03 11:38:19 -070075 private final boolean addedRule;
alshabib6b5cfec2014-09-18 17:42:18 -070076
77
alshabib1c319ff2014-10-04 20:29:09 -070078 public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
alshabib6b5cfec2014-09-18 17:42:18 -070079 this.stat = entry;
80 this.match = entry.getMatch();
alshabib19fdc122014-10-03 11:38:19 -070081 this.actions = getActions(entry);
alshabib6b5cfec2014-09-18 17:42:18 -070082 this.dpid = dpid;
alshabib219ebaa2014-09-22 15:41:24 -070083 this.removed = null;
alshabib19fdc122014-10-03 11:38:19 -070084 this.addedRule = true;
alshabib6b5cfec2014-09-18 17:42:18 -070085 }
86
alshabib1c319ff2014-10-04 20:29:09 -070087 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
alshabib6b5cfec2014-09-18 17:42:18 -070088 this.match = removed.getMatch();
89 this.removed = removed;
90
91 this.dpid = dpid;
92 this.actions = null;
93 this.stat = null;
alshabib19fdc122014-10-03 11:38:19 -070094 this.addedRule = false;
alshabib6b5cfec2014-09-18 17:42:18 -070095
96 }
97
alshabib1c319ff2014-10-04 20:29:09 -070098 public FlowEntry build() {
alshabib19fdc122014-10-03 11:38:19 -070099 if (addedRule) {
alshabib1c319ff2014-10-04 20:29:09 -0700100 FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
alshabib6b5cfec2014-09-18 17:42:18 -0700101 buildSelector(), buildTreatment(), stat.getPriority(),
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700102 stat.getCookie().getValue(), stat.getIdleTimeout(), false);
alshabib1c319ff2014-10-04 20:29:09 -0700103 return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
104 stat.getDurationSec(), stat.getPacketCount().getValue(),
105 stat.getByteCount().getValue());
106
alshabib6b5cfec2014-09-18 17:42:18 -0700107 } else {
alshabib1c319ff2014-10-04 20:29:09 -0700108 FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
alshabib6b5cfec2014-09-18 17:42:18 -0700109 buildSelector(), null, removed.getPriority(),
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700110 removed.getCookie().getValue(), removed.getIdleTimeout(), false);
alshabib1c319ff2014-10-04 20:29:09 -0700111 return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
112 removed.getPacketCount().getValue(), removed.getByteCount().getValue());
alshabib6b5cfec2014-09-18 17:42:18 -0700113 }
114 }
115
alshabib19fdc122014-10-03 11:38:19 -0700116 private List<OFAction> getActions(OFFlowStatsEntry entry) {
117 switch (entry.getVersion()) {
118 case OF_10:
119 return entry.getActions();
120 case OF_11:
121 case OF_12:
122 case OF_13:
123 List<OFInstruction> ins = entry.getInstructions();
124 for (OFInstruction in : ins) {
Jonathan Hart86e59352014-10-22 10:42:16 -0700125 if (in.getType().equals(OFInstructionType.WRITE_ACTIONS)) {
126 OFInstructionWriteActions apply = (OFInstructionWriteActions) in;
alshabib19fdc122014-10-03 11:38:19 -0700127 return apply.getActions();
128 }
129 }
130 return Lists.newLinkedList();
131 default:
132 log.warn("Unknown OF version {}", entry.getVersion());
133 }
134 return Lists.newLinkedList();
135 }
alshabib6b5cfec2014-09-18 17:42:18 -0700136
137 private TrafficTreatment buildTreatment() {
tom9a693fd2014-10-03 11:32:19 -0700138 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700139 // If this is a drop rule
140 if (actions.size() == 0) {
alshabib010c31d2014-09-26 10:01:12 -0700141 builder.drop();
alshabib6b5cfec2014-09-18 17:42:18 -0700142 return builder.build();
143 }
144 for (OFAction act : actions) {
145 switch (act.getType()) {
146 case OUTPUT:
147 OFActionOutput out = (OFActionOutput) act;
alshabib010c31d2014-09-26 10:01:12 -0700148 builder.setOutput(
149 PortNumber.portNumber(out.getPort().getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700150 break;
151 case SET_VLAN_VID:
alshabib010c31d2014-09-26 10:01:12 -0700152 OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
153 builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
154 break;
155 case SET_VLAN_PCP:
alshabib6b5cfec2014-09-18 17:42:18 -0700156 OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
alshabib010c31d2014-09-26 10:01:12 -0700157 builder.setVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue()));
alshabib6b5cfec2014-09-18 17:42:18 -0700158 break;
159 case SET_DL_DST:
160 OFActionSetDlDst dldst = (OFActionSetDlDst) act;
alshabib010c31d2014-09-26 10:01:12 -0700161 builder.setEthDst(
162 MacAddress.valueOf(dldst.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700163 break;
164 case SET_DL_SRC:
165 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
alshabib010c31d2014-09-26 10:01:12 -0700166 builder.setEthSrc(
167 MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700168
169 break;
170 case SET_NW_DST:
171 OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
172 IPv4Address di = nwdst.getNwAddr();
173 if (di.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700174 builder.setIpDst(IpPrefix.valueOf(di.getInt(),
175 di.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700176 } else {
alshabib010c31d2014-09-26 10:01:12 -0700177 builder.setIpDst(IpPrefix.valueOf(di.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700178 }
179 break;
180 case SET_NW_SRC:
181 OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
182 IPv4Address si = nwsrc.getNwAddr();
183 if (si.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700184 builder.setIpSrc(IpPrefix.valueOf(si.getInt(),
185 si.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700186 } else {
alshabib010c31d2014-09-26 10:01:12 -0700187 builder.setIpSrc(IpPrefix.valueOf(si.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700188 }
189 break;
Marc De Leenheer49087752014-10-23 13:54:09 -0700190 case EXPERIMENTER:
191 OFActionExperimenter exp = (OFActionExperimenter) act;
192 if (exp.getExperimenter() == 0x80005A06) {
193 OFActionCircuit ct = (OFActionCircuit) exp;
194 builder.setLambda(((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber());
195 } else {
196 log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
197 }
198 break;
alshabib6b5cfec2014-09-18 17:42:18 -0700199 case SET_TP_DST:
200 case SET_TP_SRC:
201 case POP_MPLS:
202 case POP_PBB:
203 case POP_VLAN:
204 case PUSH_MPLS:
205 case PUSH_PBB:
206 case PUSH_VLAN:
207 case SET_FIELD:
208 case SET_MPLS_LABEL:
209 case SET_MPLS_TC:
210 case SET_MPLS_TTL:
211 case SET_NW_ECN:
212 case SET_NW_TOS:
213 case SET_NW_TTL:
214 case SET_QUEUE:
215 case STRIP_VLAN:
216 case COPY_TTL_IN:
217 case COPY_TTL_OUT:
218 case DEC_MPLS_TTL:
219 case DEC_NW_TTL:
220 case ENQUEUE:
Marc De Leenheer49087752014-10-23 13:54:09 -0700221
alshabib6b5cfec2014-09-18 17:42:18 -0700222 case GROUP:
223 default:
224 log.warn("Action type {} not yet implemented.", act.getType());
225 }
226 }
227
228 return builder.build();
229 }
230
231 private TrafficSelector buildSelector() {
tom9a693fd2014-10-03 11:32:19 -0700232 TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700233 for (MatchField<?> field : match.getMatchFields()) {
234 switch (field.id) {
235 case IN_PORT:
alshabib010c31d2014-09-26 10:01:12 -0700236 builder.matchInport(PortNumber
237 .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700238 break;
239 case ETH_SRC:
240 MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700241 builder.matchEthSrc(sMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700242 break;
243 case ETH_DST:
244 MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700245 builder.matchEthDst(dMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700246 break;
247 case ETH_TYPE:
248 int ethType = match.get(MatchField.ETH_TYPE).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700249 builder.matchEthType((short) ethType);
alshabib6b5cfec2014-09-18 17:42:18 -0700250 break;
251 case IPV4_DST:
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700252 IpPrefix dip;
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700253 if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
254 Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
255
256 dip = IpPrefix.valueOf(
257 maskedIp.getValue().getInt(),
258 maskedIp.getMask().asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700259 } else {
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700260 dip = IpPrefix.valueOf(
261 match.get(MatchField.IPV4_DST).getInt(),
262 IpPrefix.MAX_INET_MASK);
alshabib6b5cfec2014-09-18 17:42:18 -0700263 }
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700264
alshabib010c31d2014-09-26 10:01:12 -0700265 builder.matchIPDst(dip);
alshabib6b5cfec2014-09-18 17:42:18 -0700266 break;
267 case IPV4_SRC:
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700268 IpPrefix sip;
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700269 if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
270 Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
271
272 sip = IpPrefix.valueOf(
273 maskedIp.getValue().getInt(),
274 maskedIp.getMask().asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700275 } else {
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700276 sip = IpPrefix.valueOf(
277 match.get(MatchField.IPV4_SRC).getInt(),
278 IpPrefix.MAX_INET_MASK);
alshabib6b5cfec2014-09-18 17:42:18 -0700279 }
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700280
alshabib010c31d2014-09-26 10:01:12 -0700281 builder.matchIPSrc(sip);
alshabib6b5cfec2014-09-18 17:42:18 -0700282 break;
283 case IP_PROTO:
284 short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
alshabib010c31d2014-09-26 10:01:12 -0700285 builder.matchIPProtocol((byte) proto);
alshabib6b5cfec2014-09-18 17:42:18 -0700286 break;
287 case VLAN_PCP:
288 byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700289 builder.matchVlanPcp(vlanPcp);
alshabib6b5cfec2014-09-18 17:42:18 -0700290 break;
291 case VLAN_VID:
292 VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
alshabib010c31d2014-09-26 10:01:12 -0700293 builder.matchVlanId(vlanId);
alshabib6b5cfec2014-09-18 17:42:18 -0700294 break;
Jonathan Hart34bc6142014-10-17 11:00:43 -0700295 case TCP_DST:
296 builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort());
297 break;
298 case TCP_SRC:
299 builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort());
300 break;
Marc De Leenheer49087752014-10-23 13:54:09 -0700301 case OCH_SIGID:
302 builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
303 break;
304 case OCH_SIGTYPE_BASIC:
alshabib6b5cfec2014-09-18 17:42:18 -0700305 case ARP_OP:
306 case ARP_SHA:
307 case ARP_SPA:
308 case ARP_THA:
309 case ARP_TPA:
310 case ICMPV4_CODE:
311 case ICMPV4_TYPE:
312 case ICMPV6_CODE:
313 case ICMPV6_TYPE:
314 case IN_PHY_PORT:
315 case IPV6_DST:
316 case IPV6_FLABEL:
317 case IPV6_ND_SLL:
318 case IPV6_ND_TARGET:
319 case IPV6_ND_TLL:
320 case IPV6_SRC:
321 case IP_DSCP:
322 case IP_ECN:
323 case METADATA:
324 case MPLS_LABEL:
325 case MPLS_TC:
326 case SCTP_DST:
327 case SCTP_SRC:
alshabib6b5cfec2014-09-18 17:42:18 -0700328 case TUNNEL_ID:
329 case UDP_DST:
330 case UDP_SRC:
331 default:
332 log.warn("Match type {} not yet implemented.", field.id);
333
334
335 }
336 }
337 return builder.build();
338 }
339
340}