blob: 9924a7198b42e0e3f9f5ff8390df70380193fe23 [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;
26import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
27import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
28import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
29import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
30import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
31import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
32import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
alshabib19fdc122014-10-03 11:38:19 -070033import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
34import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
alshabib6b5cfec2014-09-18 17:42:18 -070035import org.projectfloodlight.openflow.protocol.match.Match;
36import org.projectfloodlight.openflow.protocol.match.MatchField;
37import org.projectfloodlight.openflow.types.IPv4Address;
Jonathan Hart0e12fad2014-10-17 14:54:58 -070038import org.projectfloodlight.openflow.types.Masked;
alshabib6b5cfec2014-09-18 17:42:18 -070039import org.slf4j.Logger;
40
alshabib19fdc122014-10-03 11:38:19 -070041import com.google.common.collect.Lists;
42
alshabib1c319ff2014-10-04 20:29:09 -070043public class FlowEntryBuilder {
alshabib6b5cfec2014-09-18 17:42:18 -070044 private final Logger log = getLogger(getClass());
45
46 private final OFFlowStatsEntry stat;
47 private final OFFlowRemoved removed;
48
49 private final Match match;
50 private final List<OFAction> actions;
51
52 private final Dpid dpid;
53
alshabib19fdc122014-10-03 11:38:19 -070054 private final boolean addedRule;
alshabib6b5cfec2014-09-18 17:42:18 -070055
56
alshabib1c319ff2014-10-04 20:29:09 -070057 public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
alshabib6b5cfec2014-09-18 17:42:18 -070058 this.stat = entry;
59 this.match = entry.getMatch();
alshabib19fdc122014-10-03 11:38:19 -070060 this.actions = getActions(entry);
alshabib6b5cfec2014-09-18 17:42:18 -070061 this.dpid = dpid;
alshabib219ebaa2014-09-22 15:41:24 -070062 this.removed = null;
alshabib19fdc122014-10-03 11:38:19 -070063 this.addedRule = true;
alshabib6b5cfec2014-09-18 17:42:18 -070064 }
65
alshabib1c319ff2014-10-04 20:29:09 -070066 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
alshabib6b5cfec2014-09-18 17:42:18 -070067 this.match = removed.getMatch();
68 this.removed = removed;
69
70 this.dpid = dpid;
71 this.actions = null;
72 this.stat = null;
alshabib19fdc122014-10-03 11:38:19 -070073 this.addedRule = false;
alshabib6b5cfec2014-09-18 17:42:18 -070074
75 }
76
alshabib1c319ff2014-10-04 20:29:09 -070077 public FlowEntry build() {
alshabib19fdc122014-10-03 11:38:19 -070078 if (addedRule) {
alshabib1c319ff2014-10-04 20:29:09 -070079 FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
alshabib6b5cfec2014-09-18 17:42:18 -070080 buildSelector(), buildTreatment(), stat.getPriority(),
alshabiba0e04982014-10-03 13:03:19 -070081 stat.getCookie().getValue(), stat.getIdleTimeout());
alshabib1c319ff2014-10-04 20:29:09 -070082 return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
83 stat.getDurationSec(), stat.getPacketCount().getValue(),
84 stat.getByteCount().getValue());
85
alshabib6b5cfec2014-09-18 17:42:18 -070086 } else {
alshabib1c319ff2014-10-04 20:29:09 -070087 FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
alshabib6b5cfec2014-09-18 17:42:18 -070088 buildSelector(), null, removed.getPriority(),
alshabib1c319ff2014-10-04 20:29:09 -070089 removed.getCookie().getValue(), removed.getIdleTimeout());
90 return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
91 removed.getPacketCount().getValue(), removed.getByteCount().getValue());
alshabib6b5cfec2014-09-18 17:42:18 -070092 }
93 }
94
alshabib19fdc122014-10-03 11:38:19 -070095 private List<OFAction> getActions(OFFlowStatsEntry entry) {
96 switch (entry.getVersion()) {
97 case OF_10:
98 return entry.getActions();
99 case OF_11:
100 case OF_12:
101 case OF_13:
102 List<OFInstruction> ins = entry.getInstructions();
103 for (OFInstruction in : ins) {
104 if (in.getType().equals(OFInstructionType.APPLY_ACTIONS)) {
105 OFInstructionApplyActions apply = (OFInstructionApplyActions) in;
106 return apply.getActions();
107 }
108 }
109 return Lists.newLinkedList();
110 default:
111 log.warn("Unknown OF version {}", entry.getVersion());
112 }
113 return Lists.newLinkedList();
114 }
alshabib6b5cfec2014-09-18 17:42:18 -0700115
116 private TrafficTreatment buildTreatment() {
tom9a693fd2014-10-03 11:32:19 -0700117 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700118 // If this is a drop rule
119 if (actions.size() == 0) {
alshabib010c31d2014-09-26 10:01:12 -0700120 builder.drop();
alshabib6b5cfec2014-09-18 17:42:18 -0700121 return builder.build();
122 }
123 for (OFAction act : actions) {
124 switch (act.getType()) {
125 case OUTPUT:
126 OFActionOutput out = (OFActionOutput) act;
alshabib010c31d2014-09-26 10:01:12 -0700127 builder.setOutput(
128 PortNumber.portNumber(out.getPort().getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700129 break;
130 case SET_VLAN_VID:
alshabib010c31d2014-09-26 10:01:12 -0700131 OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
132 builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
133 break;
134 case SET_VLAN_PCP:
alshabib6b5cfec2014-09-18 17:42:18 -0700135 OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
alshabib010c31d2014-09-26 10:01:12 -0700136 builder.setVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue()));
alshabib6b5cfec2014-09-18 17:42:18 -0700137 break;
138 case SET_DL_DST:
139 OFActionSetDlDst dldst = (OFActionSetDlDst) act;
alshabib010c31d2014-09-26 10:01:12 -0700140 builder.setEthDst(
141 MacAddress.valueOf(dldst.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700142 break;
143 case SET_DL_SRC:
144 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
alshabib010c31d2014-09-26 10:01:12 -0700145 builder.setEthSrc(
146 MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700147
148 break;
149 case SET_NW_DST:
150 OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
151 IPv4Address di = nwdst.getNwAddr();
152 if (di.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700153 builder.setIpDst(IpPrefix.valueOf(di.getInt(),
154 di.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700155 } else {
alshabib010c31d2014-09-26 10:01:12 -0700156 builder.setIpDst(IpPrefix.valueOf(di.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700157 }
158 break;
159 case SET_NW_SRC:
160 OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
161 IPv4Address si = nwsrc.getNwAddr();
162 if (si.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700163 builder.setIpSrc(IpPrefix.valueOf(si.getInt(),
164 si.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700165 } else {
alshabib010c31d2014-09-26 10:01:12 -0700166 builder.setIpSrc(IpPrefix.valueOf(si.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700167 }
168 break;
169 case SET_TP_DST:
170 case SET_TP_SRC:
171 case POP_MPLS:
172 case POP_PBB:
173 case POP_VLAN:
174 case PUSH_MPLS:
175 case PUSH_PBB:
176 case PUSH_VLAN:
177 case SET_FIELD:
178 case SET_MPLS_LABEL:
179 case SET_MPLS_TC:
180 case SET_MPLS_TTL:
181 case SET_NW_ECN:
182 case SET_NW_TOS:
183 case SET_NW_TTL:
184 case SET_QUEUE:
185 case STRIP_VLAN:
186 case COPY_TTL_IN:
187 case COPY_TTL_OUT:
188 case DEC_MPLS_TTL:
189 case DEC_NW_TTL:
190 case ENQUEUE:
191 case EXPERIMENTER:
192 case GROUP:
193 default:
194 log.warn("Action type {} not yet implemented.", act.getType());
195 }
196 }
197
198 return builder.build();
199 }
200
201 private TrafficSelector buildSelector() {
tom9a693fd2014-10-03 11:32:19 -0700202 TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700203 for (MatchField<?> field : match.getMatchFields()) {
204 switch (field.id) {
205 case IN_PORT:
alshabib010c31d2014-09-26 10:01:12 -0700206 builder.matchInport(PortNumber
207 .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700208 break;
209 case ETH_SRC:
210 MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700211 builder.matchEthSrc(sMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700212 break;
213 case ETH_DST:
214 MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700215 builder.matchEthDst(dMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700216 break;
217 case ETH_TYPE:
218 int ethType = match.get(MatchField.ETH_TYPE).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700219 builder.matchEthType((short) ethType);
alshabib6b5cfec2014-09-18 17:42:18 -0700220 break;
221 case IPV4_DST:
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700222 IpPrefix dip;
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700223 if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
224 Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
225
226 dip = IpPrefix.valueOf(
227 maskedIp.getValue().getInt(),
228 maskedIp.getMask().asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700229 } else {
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700230 dip = IpPrefix.valueOf(
231 match.get(MatchField.IPV4_DST).getInt(),
232 IpPrefix.MAX_INET_MASK);
alshabib6b5cfec2014-09-18 17:42:18 -0700233 }
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700234
alshabib010c31d2014-09-26 10:01:12 -0700235 builder.matchIPDst(dip);
alshabib6b5cfec2014-09-18 17:42:18 -0700236 break;
237 case IPV4_SRC:
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700238 IpPrefix sip;
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700239 if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
240 Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
241
242 sip = IpPrefix.valueOf(
243 maskedIp.getValue().getInt(),
244 maskedIp.getMask().asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700245 } else {
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700246 sip = IpPrefix.valueOf(
247 match.get(MatchField.IPV4_SRC).getInt(),
248 IpPrefix.MAX_INET_MASK);
alshabib6b5cfec2014-09-18 17:42:18 -0700249 }
Jonathan Hart0e12fad2014-10-17 14:54:58 -0700250
alshabib010c31d2014-09-26 10:01:12 -0700251 builder.matchIPSrc(sip);
alshabib6b5cfec2014-09-18 17:42:18 -0700252 break;
253 case IP_PROTO:
254 short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
alshabib010c31d2014-09-26 10:01:12 -0700255 builder.matchIPProtocol((byte) proto);
alshabib6b5cfec2014-09-18 17:42:18 -0700256 break;
257 case VLAN_PCP:
258 byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700259 builder.matchVlanPcp(vlanPcp);
alshabib6b5cfec2014-09-18 17:42:18 -0700260 break;
261 case VLAN_VID:
262 VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
alshabib010c31d2014-09-26 10:01:12 -0700263 builder.matchVlanId(vlanId);
alshabib6b5cfec2014-09-18 17:42:18 -0700264 break;
Jonathan Hart34bc6142014-10-17 11:00:43 -0700265 case TCP_DST:
266 builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort());
267 break;
268 case TCP_SRC:
269 builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort());
270 break;
alshabib6b5cfec2014-09-18 17:42:18 -0700271 case ARP_OP:
272 case ARP_SHA:
273 case ARP_SPA:
274 case ARP_THA:
275 case ARP_TPA:
276 case ICMPV4_CODE:
277 case ICMPV4_TYPE:
278 case ICMPV6_CODE:
279 case ICMPV6_TYPE:
280 case IN_PHY_PORT:
281 case IPV6_DST:
282 case IPV6_FLABEL:
283 case IPV6_ND_SLL:
284 case IPV6_ND_TARGET:
285 case IPV6_ND_TLL:
286 case IPV6_SRC:
287 case IP_DSCP:
288 case IP_ECN:
289 case METADATA:
290 case MPLS_LABEL:
291 case MPLS_TC:
292 case SCTP_DST:
293 case SCTP_SRC:
alshabib6b5cfec2014-09-18 17:42:18 -0700294 case TUNNEL_ID:
295 case UDP_DST:
296 case UDP_SRC:
297 default:
298 log.warn("Match type {} not yet implemented.", field.id);
299
300
301 }
302 }
303 return builder.build();
304 }
305
306}