blob: 70727d3aa5fdde67a7df5e99e952daca331dadc6 [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;
9import org.onlab.onos.net.flow.DefaultFlowRule;
10import org.onlab.onos.net.flow.DefaultTrafficSelector;
11import org.onlab.onos.net.flow.DefaultTrafficTreatment;
12import org.onlab.onos.net.flow.FlowRule;
alshabiba7f7ca82014-09-22 11:41:23 -070013import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
alshabib6b5cfec2014-09-18 17:42:18 -070014import org.onlab.onos.net.flow.TrafficSelector;
15import org.onlab.onos.net.flow.TrafficTreatment;
alshabib6b5cfec2014-09-18 17:42:18 -070016import org.onlab.onos.openflow.controller.Dpid;
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -070017import org.onlab.packet.IpPrefix;
alshabib6b5cfec2014-09-18 17:42:18 -070018import org.onlab.packet.MacAddress;
19import org.onlab.packet.VlanId;
20import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
21import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
alshabib19fdc122014-10-03 11:38:19 -070022import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib6b5cfec2014-09-18 17:42:18 -070023import org.projectfloodlight.openflow.protocol.action.OFAction;
24import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
25import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
26import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
27import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
28import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
29import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
30import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
alshabib19fdc122014-10-03 11:38:19 -070031import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
32import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
alshabib6b5cfec2014-09-18 17:42:18 -070033import org.projectfloodlight.openflow.protocol.match.Match;
34import org.projectfloodlight.openflow.protocol.match.MatchField;
35import org.projectfloodlight.openflow.types.IPv4Address;
36import org.slf4j.Logger;
37
alshabib19fdc122014-10-03 11:38:19 -070038import com.google.common.collect.Lists;
39
alshabib6b5cfec2014-09-18 17:42:18 -070040public class FlowRuleBuilder {
41 private final Logger log = getLogger(getClass());
42
43 private final OFFlowStatsEntry stat;
44 private final OFFlowRemoved removed;
45
46 private final Match match;
47 private final List<OFAction> actions;
48
49 private final Dpid dpid;
50
alshabib19fdc122014-10-03 11:38:19 -070051 private final boolean addedRule;
alshabib6b5cfec2014-09-18 17:42:18 -070052
53
54 public FlowRuleBuilder(Dpid dpid, OFFlowStatsEntry entry) {
55 this.stat = entry;
56 this.match = entry.getMatch();
alshabib19fdc122014-10-03 11:38:19 -070057 this.actions = getActions(entry);
alshabib6b5cfec2014-09-18 17:42:18 -070058 this.dpid = dpid;
alshabib219ebaa2014-09-22 15:41:24 -070059 this.removed = null;
alshabib19fdc122014-10-03 11:38:19 -070060 this.addedRule = true;
alshabib6b5cfec2014-09-18 17:42:18 -070061 }
62
63 public FlowRuleBuilder(Dpid dpid, OFFlowRemoved removed) {
64 this.match = removed.getMatch();
65 this.removed = removed;
66
67 this.dpid = dpid;
68 this.actions = null;
69 this.stat = null;
alshabib19fdc122014-10-03 11:38:19 -070070 this.addedRule = false;
alshabib6b5cfec2014-09-18 17:42:18 -070071
72 }
73
74 public FlowRule build() {
alshabib19fdc122014-10-03 11:38:19 -070075 if (addedRule) {
alshabib6b5cfec2014-09-18 17:42:18 -070076 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
77 buildSelector(), buildTreatment(), stat.getPriority(),
alshabiba0e04982014-10-03 13:03:19 -070078 FlowRuleState.ADDED, stat.getDurationSec(),
alshabib6b5cfec2014-09-18 17:42:18 -070079 stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
alshabiba0e04982014-10-03 13:03:19 -070080 stat.getCookie().getValue(), stat.getIdleTimeout());
alshabib6b5cfec2014-09-18 17:42:18 -070081 } else {
82 // TODO: revisit potentially.
83 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
84 buildSelector(), null, removed.getPriority(),
alshabiba0e04982014-10-03 13:03:19 -070085 FlowRuleState.REMOVED, stat.getDurationSec(),
alshabib6b5cfec2014-09-18 17:42:18 -070086 removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
alshabib6eb438a2014-10-01 16:39:37 -070087 removed.getCookie().getValue(),
alshabibba5ac482014-10-02 17:15:20 -070088 stat.getIdleTimeout());
alshabib6b5cfec2014-09-18 17:42:18 -070089 }
90 }
91
alshabib19fdc122014-10-03 11:38:19 -070092 private List<OFAction> getActions(OFFlowStatsEntry entry) {
93 switch (entry.getVersion()) {
94 case OF_10:
95 return entry.getActions();
96 case OF_11:
97 case OF_12:
98 case OF_13:
99 List<OFInstruction> ins = entry.getInstructions();
100 for (OFInstruction in : ins) {
101 if (in.getType().equals(OFInstructionType.APPLY_ACTIONS)) {
102 OFInstructionApplyActions apply = (OFInstructionApplyActions) in;
103 return apply.getActions();
104 }
105 }
106 return Lists.newLinkedList();
107 default:
108 log.warn("Unknown OF version {}", entry.getVersion());
109 }
110 return Lists.newLinkedList();
111 }
alshabib6b5cfec2014-09-18 17:42:18 -0700112
113 private TrafficTreatment buildTreatment() {
tom9a693fd2014-10-03 11:32:19 -0700114 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700115 // If this is a drop rule
116 if (actions.size() == 0) {
alshabib010c31d2014-09-26 10:01:12 -0700117 builder.drop();
alshabib6b5cfec2014-09-18 17:42:18 -0700118 return builder.build();
119 }
120 for (OFAction act : actions) {
121 switch (act.getType()) {
122 case OUTPUT:
123 OFActionOutput out = (OFActionOutput) act;
alshabib010c31d2014-09-26 10:01:12 -0700124 builder.setOutput(
125 PortNumber.portNumber(out.getPort().getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700126 break;
127 case SET_VLAN_VID:
alshabib010c31d2014-09-26 10:01:12 -0700128 OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
129 builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
130 break;
131 case SET_VLAN_PCP:
alshabib6b5cfec2014-09-18 17:42:18 -0700132 OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
alshabib010c31d2014-09-26 10:01:12 -0700133 builder.setVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue()));
alshabib6b5cfec2014-09-18 17:42:18 -0700134 break;
135 case SET_DL_DST:
136 OFActionSetDlDst dldst = (OFActionSetDlDst) act;
alshabib010c31d2014-09-26 10:01:12 -0700137 builder.setEthDst(
138 MacAddress.valueOf(dldst.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700139 break;
140 case SET_DL_SRC:
141 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
alshabib010c31d2014-09-26 10:01:12 -0700142 builder.setEthSrc(
143 MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700144
145 break;
146 case SET_NW_DST:
147 OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
148 IPv4Address di = nwdst.getNwAddr();
149 if (di.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700150 builder.setIpDst(IpPrefix.valueOf(di.getInt(),
151 di.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700152 } else {
alshabib010c31d2014-09-26 10:01:12 -0700153 builder.setIpDst(IpPrefix.valueOf(di.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700154 }
155 break;
156 case SET_NW_SRC:
157 OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
158 IPv4Address si = nwsrc.getNwAddr();
159 if (si.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700160 builder.setIpSrc(IpPrefix.valueOf(si.getInt(),
161 si.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700162 } else {
alshabib010c31d2014-09-26 10:01:12 -0700163 builder.setIpSrc(IpPrefix.valueOf(si.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700164 }
165 break;
166 case SET_TP_DST:
167 case SET_TP_SRC:
168 case POP_MPLS:
169 case POP_PBB:
170 case POP_VLAN:
171 case PUSH_MPLS:
172 case PUSH_PBB:
173 case PUSH_VLAN:
174 case SET_FIELD:
175 case SET_MPLS_LABEL:
176 case SET_MPLS_TC:
177 case SET_MPLS_TTL:
178 case SET_NW_ECN:
179 case SET_NW_TOS:
180 case SET_NW_TTL:
181 case SET_QUEUE:
182 case STRIP_VLAN:
183 case COPY_TTL_IN:
184 case COPY_TTL_OUT:
185 case DEC_MPLS_TTL:
186 case DEC_NW_TTL:
187 case ENQUEUE:
188 case EXPERIMENTER:
189 case GROUP:
190 default:
191 log.warn("Action type {} not yet implemented.", act.getType());
192 }
193 }
194
195 return builder.build();
196 }
197
198 private TrafficSelector buildSelector() {
tom9a693fd2014-10-03 11:32:19 -0700199 TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
alshabib6b5cfec2014-09-18 17:42:18 -0700200 for (MatchField<?> field : match.getMatchFields()) {
201 switch (field.id) {
202 case IN_PORT:
alshabib010c31d2014-09-26 10:01:12 -0700203 builder.matchInport(PortNumber
204 .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700205 break;
206 case ETH_SRC:
207 MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700208 builder.matchEthSrc(sMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700209 break;
210 case ETH_DST:
211 MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700212 builder.matchEthDst(dMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700213 break;
214 case ETH_TYPE:
215 int ethType = match.get(MatchField.ETH_TYPE).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700216 builder.matchEthType((short) ethType);
alshabib6b5cfec2014-09-18 17:42:18 -0700217 break;
218 case IPV4_DST:
219 IPv4Address di = match.get(MatchField.IPV4_DST);
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700220 IpPrefix dip;
alshabib6b5cfec2014-09-18 17:42:18 -0700221 if (di.isCidrMask()) {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700222 dip = IpPrefix.valueOf(di.getInt(), di.asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700223 } else {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700224 dip = IpPrefix.valueOf(di.getInt());
alshabib6b5cfec2014-09-18 17:42:18 -0700225 }
alshabib010c31d2014-09-26 10:01:12 -0700226 builder.matchIPDst(dip);
alshabib6b5cfec2014-09-18 17:42:18 -0700227 break;
228 case IPV4_SRC:
229 IPv4Address si = match.get(MatchField.IPV4_SRC);
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700230 IpPrefix sip;
alshabib6b5cfec2014-09-18 17:42:18 -0700231 if (si.isCidrMask()) {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700232 sip = IpPrefix.valueOf(si.getInt(), si.asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700233 } else {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700234 sip = IpPrefix.valueOf(si.getInt());
alshabib6b5cfec2014-09-18 17:42:18 -0700235 }
alshabib010c31d2014-09-26 10:01:12 -0700236 builder.matchIPSrc(sip);
alshabib6b5cfec2014-09-18 17:42:18 -0700237 break;
238 case IP_PROTO:
239 short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
alshabib010c31d2014-09-26 10:01:12 -0700240 builder.matchIPProtocol((byte) proto);
alshabib6b5cfec2014-09-18 17:42:18 -0700241 break;
242 case VLAN_PCP:
243 byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700244 builder.matchVlanPcp(vlanPcp);
alshabib6b5cfec2014-09-18 17:42:18 -0700245 break;
246 case VLAN_VID:
247 VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
alshabib010c31d2014-09-26 10:01:12 -0700248 builder.matchVlanId(vlanId);
alshabib6b5cfec2014-09-18 17:42:18 -0700249 break;
250 case ARP_OP:
251 case ARP_SHA:
252 case ARP_SPA:
253 case ARP_THA:
254 case ARP_TPA:
255 case ICMPV4_CODE:
256 case ICMPV4_TYPE:
257 case ICMPV6_CODE:
258 case ICMPV6_TYPE:
259 case IN_PHY_PORT:
260 case IPV6_DST:
261 case IPV6_FLABEL:
262 case IPV6_ND_SLL:
263 case IPV6_ND_TARGET:
264 case IPV6_ND_TLL:
265 case IPV6_SRC:
266 case IP_DSCP:
267 case IP_ECN:
268 case METADATA:
269 case MPLS_LABEL:
270 case MPLS_TC:
271 case SCTP_DST:
272 case SCTP_SRC:
273 case TCP_DST:
274 case TCP_SRC:
275 case TUNNEL_ID:
276 case UDP_DST:
277 case UDP_SRC:
278 default:
279 log.warn("Match type {} not yet implemented.", field.id);
280
281
282 }
283 }
284 return builder.build();
285 }
286
287}