blob: 2a91b5b4e6ecf70c40628ec8d7481bee5aced714 [file] [log] [blame]
alshabib6b5cfec2014-09-18 17:42:18 -07001package org.onlab.onos.provider.of.flow.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.List;
6
7import org.onlab.onos.net.DeviceId;
8import org.onlab.onos.net.PortNumber;
alshabib1c319ff2014-10-04 20:29:09 -07009import org.onlab.onos.net.flow.DefaultFlowEntry;
alshabib6b5cfec2014-09-18 17:42:18 -070010import org.onlab.onos.net.flow.DefaultFlowRule;
11import org.onlab.onos.net.flow.DefaultTrafficSelector;
12import org.onlab.onos.net.flow.DefaultTrafficTreatment;
alshabib1c319ff2014-10-04 20:29:09 -070013import org.onlab.onos.net.flow.FlowEntry;
14import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
alshabib6b5cfec2014-09-18 17:42:18 -070015import org.onlab.onos.net.flow.FlowRule;
16import org.onlab.onos.net.flow.TrafficSelector;
17import org.onlab.onos.net.flow.TrafficTreatment;
alshabib6b5cfec2014-09-18 17:42:18 -070018import org.onlab.onos.openflow.controller.Dpid;
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -070019import org.onlab.packet.IpPrefix;
alshabib6b5cfec2014-09-18 17:42:18 -070020import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
22import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
23import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
alshabib19fdc122014-10-03 11:38:19 -070024import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib6b5cfec2014-09-18 17:42:18 -070025import org.projectfloodlight.openflow.protocol.action.OFAction;
Marc De Leenheer49087752014-10-23 13:54:09 -070026import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
27import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
alshabib6b5cfec2014-09-18 17:42:18 -070028import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
29import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
30import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
31import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
32import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
33import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
34import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
alshabib19fdc122014-10-03 11:38:19 -070035import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Jonathan Hart86e59352014-10-22 10:42:16 -070036import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions;
alshabib6b5cfec2014-09-18 17:42:18 -070037import org.projectfloodlight.openflow.protocol.match.Match;
38import org.projectfloodlight.openflow.protocol.match.MatchField;
Marc De Leenheer49087752014-10-23 13:54:09 -070039import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
alshabib6b5cfec2014-09-18 17:42:18 -070040import org.projectfloodlight.openflow.types.IPv4Address;
Jonathan Hart0e12fad2014-10-17 14:54:58 -070041import org.projectfloodlight.openflow.types.Masked;
alshabib6b5cfec2014-09-18 17:42:18 -070042import org.slf4j.Logger;
43
alshabib19fdc122014-10-03 11:38:19 -070044import com.google.common.collect.Lists;
45
alshabib1c319ff2014-10-04 20:29:09 -070046public class FlowEntryBuilder {
alshabib6b5cfec2014-09-18 17:42:18 -070047 private final Logger log = getLogger(getClass());
48
49 private final OFFlowStatsEntry stat;
50 private final OFFlowRemoved removed;
51
52 private final Match match;
53 private final List<OFAction> actions;
54
55 private final Dpid dpid;
56
alshabib19fdc122014-10-03 11:38:19 -070057 private final boolean addedRule;
alshabib6b5cfec2014-09-18 17:42:18 -070058
59
alshabib1c319ff2014-10-04 20:29:09 -070060 public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
alshabib6b5cfec2014-09-18 17:42:18 -070061 this.stat = entry;
62 this.match = entry.getMatch();
alshabib19fdc122014-10-03 11:38:19 -070063 this.actions = getActions(entry);
alshabib6b5cfec2014-09-18 17:42:18 -070064 this.dpid = dpid;
alshabib219ebaa2014-09-22 15:41:24 -070065 this.removed = null;
alshabib19fdc122014-10-03 11:38:19 -070066 this.addedRule = true;
alshabib6b5cfec2014-09-18 17:42:18 -070067 }
68
alshabib1c319ff2014-10-04 20:29:09 -070069 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
alshabib6b5cfec2014-09-18 17:42:18 -070070 this.match = removed.getMatch();
71 this.removed = removed;
72
73 this.dpid = dpid;
74 this.actions = null;
75 this.stat = null;
alshabib19fdc122014-10-03 11:38:19 -070076 this.addedRule = false;
alshabib6b5cfec2014-09-18 17:42:18 -070077
78 }
79
alshabib1c319ff2014-10-04 20:29:09 -070080 public FlowEntry build() {
alshabib19fdc122014-10-03 11:38:19 -070081 if (addedRule) {
alshabib1c319ff2014-10-04 20:29:09 -070082 FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
alshabib6b5cfec2014-09-18 17:42:18 -070083 buildSelector(), buildTreatment(), stat.getPriority(),
Jonathan Hartbc4a7932014-10-21 11:46:00 -070084 stat.getCookie().getValue(), stat.getIdleTimeout(), false);
alshabib1c319ff2014-10-04 20:29:09 -070085 return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
86 stat.getDurationSec(), stat.getPacketCount().getValue(),
87 stat.getByteCount().getValue());
88
alshabib6b5cfec2014-09-18 17:42:18 -070089 } else {
alshabib1c319ff2014-10-04 20:29:09 -070090 FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
alshabib6b5cfec2014-09-18 17:42:18 -070091 buildSelector(), null, removed.getPriority(),
Jonathan Hartbc4a7932014-10-21 11:46:00 -070092 removed.getCookie().getValue(), removed.getIdleTimeout(), false);
alshabib1c319ff2014-10-04 20:29:09 -070093 return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
94 removed.getPacketCount().getValue(), removed.getByteCount().getValue());
alshabib6b5cfec2014-09-18 17:42:18 -070095 }
96 }
97
alshabib19fdc122014-10-03 11:38:19 -070098 private List<OFAction> getActions(OFFlowStatsEntry entry) {
99 switch (entry.getVersion()) {
100 case OF_10:
101 return entry.getActions();
102 case OF_11:
103 case OF_12:
104 case OF_13:
105 List<OFInstruction> ins = entry.getInstructions();
106 for (OFInstruction in : ins) {
Jonathan Hart86e59352014-10-22 10:42:16 -0700107 if (in.getType().equals(OFInstructionType.WRITE_ACTIONS)) {
108 OFInstructionWriteActions apply = (OFInstructionWriteActions) in;
alshabib19fdc122014-10-03 11:38:19 -0700109 return apply.getActions();
110 }
111 }
112 return Lists.newLinkedList();
113 default:
114 log.warn("Unknown OF version {}", entry.getVersion());
115 }
116 return Lists.newLinkedList();
117 }
alshabib6b5cfec2014-09-18 17:42:18 -0700118
119 private TrafficTreatment buildTreatment() {
tom9a693fd2014-10-03 11:32:19 -0700120 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700121 // If this is a drop rule
122 if (actions.size() == 0) {
alshabib010c31d2014-09-26 10:01:12 -0700123 builder.drop();
alshabib6b5cfec2014-09-18 17:42:18 -0700124 return builder.build();
125 }
126 for (OFAction act : actions) {
127 switch (act.getType()) {
128 case OUTPUT:
129 OFActionOutput out = (OFActionOutput) act;
alshabib010c31d2014-09-26 10:01:12 -0700130 builder.setOutput(
131 PortNumber.portNumber(out.getPort().getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700132 break;
133 case SET_VLAN_VID:
alshabib010c31d2014-09-26 10:01:12 -0700134 OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
135 builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
136 break;
137 case SET_VLAN_PCP:
alshabib6b5cfec2014-09-18 17:42:18 -0700138 OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
alshabib010c31d2014-09-26 10:01:12 -0700139 builder.setVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue()));
alshabib6b5cfec2014-09-18 17:42:18 -0700140 break;
141 case SET_DL_DST:
142 OFActionSetDlDst dldst = (OFActionSetDlDst) act;
alshabib010c31d2014-09-26 10:01:12 -0700143 builder.setEthDst(
144 MacAddress.valueOf(dldst.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700145 break;
146 case SET_DL_SRC:
147 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
alshabib010c31d2014-09-26 10:01:12 -0700148 builder.setEthSrc(
149 MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700150
151 break;
152 case SET_NW_DST:
153 OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
154 IPv4Address di = nwdst.getNwAddr();
155 if (di.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700156 builder.setIpDst(IpPrefix.valueOf(di.getInt(),
157 di.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700158 } else {
alshabib010c31d2014-09-26 10:01:12 -0700159 builder.setIpDst(IpPrefix.valueOf(di.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700160 }
161 break;
162 case SET_NW_SRC:
163 OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
164 IPv4Address si = nwsrc.getNwAddr();
165 if (si.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700166 builder.setIpSrc(IpPrefix.valueOf(si.getInt(),
167 si.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700168 } else {
alshabib010c31d2014-09-26 10:01:12 -0700169 builder.setIpSrc(IpPrefix.valueOf(si.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700170 }
171 break;
Marc De Leenheer49087752014-10-23 13:54:09 -0700172 case EXPERIMENTER:
173 OFActionExperimenter exp = (OFActionExperimenter) act;
174 if (exp.getExperimenter() == 0x80005A06) {
175 OFActionCircuit ct = (OFActionCircuit) exp;
176 builder.setLambda(((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber());
177 } else {
178 log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
179 }
180 break;
alshabib6b5cfec2014-09-18 17:42:18 -0700181 case SET_TP_DST:
182 case SET_TP_SRC:
183 case POP_MPLS:
184 case POP_PBB:
185 case POP_VLAN:
186 case PUSH_MPLS:
187 case PUSH_PBB:
188 case PUSH_VLAN:
189 case SET_FIELD:
190 case SET_MPLS_LABEL:
191 case SET_MPLS_TC:
192 case SET_MPLS_TTL:
193 case SET_NW_ECN:
194 case SET_NW_TOS:
195 case SET_NW_TTL:
196 case SET_QUEUE:
197 case STRIP_VLAN:
198 case COPY_TTL_IN:
199 case COPY_TTL_OUT:
200 case DEC_MPLS_TTL:
201 case DEC_NW_TTL:
202 case ENQUEUE:
Marc De Leenheer49087752014-10-23 13:54:09 -0700203
alshabib6b5cfec2014-09-18 17:42:18 -0700204 case GROUP:
205 default:
206 log.warn("Action type {} not yet implemented.", act.getType());
207 }
208 }
209
210 return builder.build();
211 }
212
213 private TrafficSelector buildSelector() {
tom9a693fd2014-10-03 11:32:19 -0700214 TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700215 for (MatchField<?> field : match.getMatchFields()) {
216 switch (field.id) {
217 case IN_PORT:
alshabib010c31d2014-09-26 10:01:12 -0700218 builder.matchInport(PortNumber
219 .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700220 break;
221 case ETH_SRC:
222 MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700223 builder.matchEthSrc(sMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700224 break;
225 case ETH_DST:
226 MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700227 builder.matchEthDst(dMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700228 break;
229 case ETH_TYPE:
230 int ethType = match.get(MatchField.ETH_TYPE).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700231 builder.matchEthType((short) ethType);
alshabib6b5cfec2014-09-18 17:42:18 -0700232 break;
233 case IPV4_DST:
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700234 IpPrefix dip;
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700235 if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
236 Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
237
238 dip = IpPrefix.valueOf(
239 maskedIp.getValue().getInt(),
240 maskedIp.getMask().asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700241 } else {
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700242 dip = IpPrefix.valueOf(
243 match.get(MatchField.IPV4_DST).getInt(),
244 IpPrefix.MAX_INET_MASK);
alshabib6b5cfec2014-09-18 17:42:18 -0700245 }
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700246
alshabib010c31d2014-09-26 10:01:12 -0700247 builder.matchIPDst(dip);
alshabib6b5cfec2014-09-18 17:42:18 -0700248 break;
249 case IPV4_SRC:
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700250 IpPrefix sip;
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700251 if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
252 Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
253
254 sip = IpPrefix.valueOf(
255 maskedIp.getValue().getInt(),
256 maskedIp.getMask().asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700257 } else {
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700258 sip = IpPrefix.valueOf(
259 match.get(MatchField.IPV4_SRC).getInt(),
260 IpPrefix.MAX_INET_MASK);
alshabib6b5cfec2014-09-18 17:42:18 -0700261 }
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700262
alshabib010c31d2014-09-26 10:01:12 -0700263 builder.matchIPSrc(sip);
alshabib6b5cfec2014-09-18 17:42:18 -0700264 break;
265 case IP_PROTO:
266 short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
alshabib010c31d2014-09-26 10:01:12 -0700267 builder.matchIPProtocol((byte) proto);
alshabib6b5cfec2014-09-18 17:42:18 -0700268 break;
269 case VLAN_PCP:
270 byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700271 builder.matchVlanPcp(vlanPcp);
alshabib6b5cfec2014-09-18 17:42:18 -0700272 break;
273 case VLAN_VID:
274 VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
alshabib010c31d2014-09-26 10:01:12 -0700275 builder.matchVlanId(vlanId);
alshabib6b5cfec2014-09-18 17:42:18 -0700276 break;
Jonathan Hart34bc6142014-10-17 11:00:43 -0700277 case TCP_DST:
278 builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort());
279 break;
280 case TCP_SRC:
281 builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort());
282 break;
Marc De Leenheer49087752014-10-23 13:54:09 -0700283 case OCH_SIGID:
284 builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
285 break;
286 case OCH_SIGTYPE_BASIC:
alshabib6b5cfec2014-09-18 17:42:18 -0700287 case ARP_OP:
288 case ARP_SHA:
289 case ARP_SPA:
290 case ARP_THA:
291 case ARP_TPA:
292 case ICMPV4_CODE:
293 case ICMPV4_TYPE:
294 case ICMPV6_CODE:
295 case ICMPV6_TYPE:
296 case IN_PHY_PORT:
297 case IPV6_DST:
298 case IPV6_FLABEL:
299 case IPV6_ND_SLL:
300 case IPV6_ND_TARGET:
301 case IPV6_ND_TLL:
302 case IPV6_SRC:
303 case IP_DSCP:
304 case IP_ECN:
305 case METADATA:
306 case MPLS_LABEL:
307 case MPLS_TC:
308 case SCTP_DST:
309 case SCTP_SRC:
alshabib6b5cfec2014-09-18 17:42:18 -0700310 case TUNNEL_ID:
311 case UDP_DST:
312 case UDP_SRC:
313 default:
314 log.warn("Match type {} not yet implemented.", field.id);
315
316
317 }
318 }
319 return builder.build();
320 }
321
322}