blob: 9568f1f8bade1e70fc73896f21ba317df2825e3d [file] [log] [blame]
alshabibeec3a062014-09-17 18:01:26 -07001package org.onlab.onos.provider.of.flow.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.Collections;
6import java.util.LinkedList;
7import java.util.List;
8
alshabib6b5cfec2014-09-18 17:42:18 -07009import org.onlab.onos.net.flow.FlowId;
alshabibeec3a062014-09-17 18:01:26 -070010import org.onlab.onos.net.flow.FlowRule;
11import org.onlab.onos.net.flow.TrafficSelector;
12import org.onlab.onos.net.flow.TrafficTreatment;
13import org.onlab.onos.net.flow.criteria.Criteria.EthCriterion;
14import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion;
15import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion;
16import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion;
17import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion;
18import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion;
19import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion;
20import org.onlab.onos.net.flow.criteria.Criterion;
21import org.onlab.onos.net.flow.instructions.Instruction;
22import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
23import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
24import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
25import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
26import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
27import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
28import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
29import org.projectfloodlight.openflow.protocol.OFFactory;
alshabib193525b2014-10-08 18:58:03 -070030import org.projectfloodlight.openflow.protocol.OFFlowAdd;
31import org.projectfloodlight.openflow.protocol.OFFlowDelete;
alshabibeec3a062014-09-17 18:01:26 -070032import org.projectfloodlight.openflow.protocol.OFFlowMod;
33import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
34import org.projectfloodlight.openflow.protocol.action.OFAction;
35import org.projectfloodlight.openflow.protocol.match.Match;
36import org.projectfloodlight.openflow.protocol.match.MatchField;
37import org.projectfloodlight.openflow.types.EthType;
38import org.projectfloodlight.openflow.types.IPv4Address;
39import org.projectfloodlight.openflow.types.IpProtocol;
40import org.projectfloodlight.openflow.types.MacAddress;
41import org.projectfloodlight.openflow.types.Masked;
42import org.projectfloodlight.openflow.types.OFBufferId;
43import org.projectfloodlight.openflow.types.OFPort;
44import org.projectfloodlight.openflow.types.OFVlanVidMatch;
alshabib6b5cfec2014-09-18 17:42:18 -070045import org.projectfloodlight.openflow.types.U64;
alshabibeec3a062014-09-17 18:01:26 -070046import org.projectfloodlight.openflow.types.VlanPcp;
47import org.projectfloodlight.openflow.types.VlanVid;
48import org.slf4j.Logger;
49
50
51public class FlowModBuilder {
52
53 private final Logger log = getLogger(getClass());
54
55 private final OFFactory factory;
56 private final TrafficTreatment treatment;
57 private final TrafficSelector selector;
58
59 private final int priority;
60
alshabib6b5cfec2014-09-18 17:42:18 -070061 private final FlowId cookie;
62
alshabibeec3a062014-09-17 18:01:26 -070063
64
65 public FlowModBuilder(FlowRule flowRule, OFFactory factory) {
66 this.factory = factory;
67 this.treatment = flowRule.treatment();
68 this.selector = flowRule.selector();
69 this.priority = flowRule.priority();
alshabib6b5cfec2014-09-18 17:42:18 -070070 this.cookie = flowRule.id();
alshabibeec3a062014-09-17 18:01:26 -070071 }
72
alshabib193525b2014-10-08 18:58:03 -070073 public OFFlowAdd buildFlowAdd() {
alshabibeec3a062014-09-17 18:01:26 -070074 Match match = buildMatch();
75 List<OFAction> actions = buildActions();
76
77 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
alshabib193525b2014-10-08 18:58:03 -070078 OFFlowAdd fm = factory.buildFlowAdd()
79 .setXid(cookie.value())
alshabib6b5cfec2014-09-18 17:42:18 -070080 .setCookie(U64.of(cookie.value()))
alshabibeec3a062014-09-17 18:01:26 -070081 .setBufferId(OFBufferId.NO_BUFFER)
82 .setActions(actions)
83 .setMatch(match)
84 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
alshabibeec3a062014-09-17 18:01:26 -070085 .setPriority(priority)
86 .build();
87
88 return fm;
89
90 }
91
alshabib902d41b2014-10-07 16:52:05 -070092 public OFFlowMod buildFlowMod() {
93 Match match = buildMatch();
94 List<OFAction> actions = buildActions();
95
96 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
97 OFFlowMod fm = factory.buildFlowModify()
alshabib193525b2014-10-08 18:58:03 -070098 .setXid(cookie.value())
alshabib902d41b2014-10-07 16:52:05 -070099 .setCookie(U64.of(cookie.value()))
100 .setBufferId(OFBufferId.NO_BUFFER)
101 .setActions(actions)
102 .setMatch(match)
103 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
104 .setPriority(priority)
105 .build();
106
107 return fm;
108
109 }
110
alshabib193525b2014-10-08 18:58:03 -0700111 public OFFlowDelete buildFlowDel() {
alshabib219ebaa2014-09-22 15:41:24 -0700112 Match match = buildMatch();
113 List<OFAction> actions = buildActions();
114
alshabib193525b2014-10-08 18:58:03 -0700115 OFFlowDelete fm = factory.buildFlowDelete()
116 .setXid(cookie.value())
alshabib219ebaa2014-09-22 15:41:24 -0700117 .setCookie(U64.of(cookie.value()))
118 .setBufferId(OFBufferId.NO_BUFFER)
alshabib7814e9f2014-09-30 11:52:12 -0700119 .setActions(actions)
alshabib219ebaa2014-09-22 15:41:24 -0700120 .setMatch(match)
121 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
alshabib219ebaa2014-09-22 15:41:24 -0700122 .setPriority(priority)
123 .build();
124
125 return fm;
126 }
127
alshabibeec3a062014-09-17 18:01:26 -0700128 private List<OFAction> buildActions() {
129 List<OFAction> acts = new LinkedList<>();
alshabib4906fab2014-09-29 23:58:12 -0700130 if (treatment == null) {
131 return acts;
132 }
alshabibeec3a062014-09-17 18:01:26 -0700133 for (Instruction i : treatment.instructions()) {
134 switch (i.type()) {
135 case DROP:
136 log.warn("Saw drop action; assigning drop action");
137 return new LinkedList<>();
138 case L2MODIFICATION:
139 acts.add(buildL2Modification(i));
alshabibf410eee2014-09-22 18:17:45 -0700140 break;
alshabibeec3a062014-09-17 18:01:26 -0700141 case L3MODIFICATION:
142 acts.add(buildL3Modification(i));
alshabibf410eee2014-09-22 18:17:45 -0700143 break;
alshabibeec3a062014-09-17 18:01:26 -0700144 case OUTPUT:
145 OutputInstruction out = (OutputInstruction) i;
146 acts.add(factory.actions().buildOutput().setPort(
147 OFPort.of((int) out.port().toLong())).build());
148 break;
149 case GROUP:
150 default:
151 log.warn("Instruction type {} not yet implemented.", i.type());
152 }
153 }
154
155 return acts;
156 }
157
158 private OFAction buildL3Modification(Instruction i) {
159 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
160 ModIPInstruction ip;
161 switch (l3m.subtype()) {
alshabib99b8fdc2014-09-25 14:30:22 -0700162 case IP_DST:
alshabibeec3a062014-09-17 18:01:26 -0700163 ip = (ModIPInstruction) i;
Jonathan Hartbcae7bd2014-10-16 10:24:41 -0700164 return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
alshabib99b8fdc2014-09-25 14:30:22 -0700165 case IP_SRC:
alshabibeec3a062014-09-17 18:01:26 -0700166 ip = (ModIPInstruction) i;
Jonathan Hartbcae7bd2014-10-16 10:24:41 -0700167 return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700168 default:
169 log.warn("Unimplemented action type {}.", l3m.subtype());
170 break;
171 }
172 return null;
173 }
174
175 private OFAction buildL2Modification(Instruction i) {
176 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
177 ModEtherInstruction eth;
178 switch (l2m.subtype()) {
alshabib99b8fdc2014-09-25 14:30:22 -0700179 case ETH_DST:
alshabibeec3a062014-09-17 18:01:26 -0700180 eth = (ModEtherInstruction) l2m;
181 return factory.actions().setDlDst(MacAddress.of(eth.mac().toLong()));
alshabib99b8fdc2014-09-25 14:30:22 -0700182 case ETH_SRC:
alshabibeec3a062014-09-17 18:01:26 -0700183 eth = (ModEtherInstruction) l2m;
184 return factory.actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
185 case VLAN_ID:
186 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
187 return factory.actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId.toShort()));
188 case VLAN_PCP:
189 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
190 return factory.actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
191 default:
192 log.warn("Unimplemented action type {}.", l2m.subtype());
193 break;
194 }
195 return null;
196 }
197
198 private Match buildMatch() {
199 Match.Builder mBuilder = factory.buildMatch();
200 EthCriterion eth;
201 IPCriterion ip;
202 for (Criterion c : selector.criteria()) {
203 switch (c.type()) {
204 case IN_PORT:
205 PortCriterion inport = (PortCriterion) c;
206 mBuilder.setExact(MatchField.IN_PORT, OFPort.of((int) inport.port().toLong()));
207 break;
208 case ETH_SRC:
209 eth = (EthCriterion) c;
210 mBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(eth.mac().toLong()));
211 break;
212 case ETH_DST:
213 eth = (EthCriterion) c;
214 mBuilder.setExact(MatchField.ETH_DST, MacAddress.of(eth.mac().toLong()));
215 break;
216 case ETH_TYPE:
217 EthTypeCriterion ethType = (EthTypeCriterion) c;
218 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType()));
219 break;
220 case IPV4_DST:
221 ip = (IPCriterion) c;
222 if (ip.ip().isMasked()) {
Jonathan Hartbcae7bd2014-10-16 10:24:41 -0700223 Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
224 IPv4Address.of(ip.ip().netmask().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700225 mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
226 } else {
Jonathan Hartbcae7bd2014-10-16 10:24:41 -0700227 mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700228 }
229 break;
230 case IPV4_SRC:
231 ip = (IPCriterion) c;
232 if (ip.ip().isMasked()) {
Jonathan Hartbcae7bd2014-10-16 10:24:41 -0700233 Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
234 IPv4Address.of(ip.ip().netmask().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700235 mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
236 } else {
Jonathan Hartbcae7bd2014-10-16 10:24:41 -0700237 mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700238 }
239 break;
240 case IP_PROTO:
241 IPProtocolCriterion p = (IPProtocolCriterion) c;
242 mBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(p.protocol()));
243 break;
244 case VLAN_PCP:
245 VlanPcpCriterion vpcp = (VlanPcpCriterion) c;
246 mBuilder.setExact(MatchField.VLAN_PCP, VlanPcp.of(vpcp.priority()));
247 break;
248 case VLAN_VID:
249 VlanIdCriterion vid = (VlanIdCriterion) c;
250 mBuilder.setExact(MatchField.VLAN_VID,
251 OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
252 break;
253 case ARP_OP:
254 case ARP_SHA:
255 case ARP_SPA:
256 case ARP_THA:
257 case ARP_TPA:
258 case ICMPV4_CODE:
259 case ICMPV4_TYPE:
260 case ICMPV6_CODE:
261 case ICMPV6_TYPE:
262 case IN_PHY_PORT:
263 case IPV6_DST:
264 case IPV6_EXTHDR:
265 case IPV6_FLABEL:
266 case IPV6_ND_SLL:
267 case IPV6_ND_TARGET:
268 case IPV6_ND_TLL:
269 case IPV6_SRC:
270 case IP_DSCP:
271 case IP_ECN:
272 case METADATA:
273 case MPLS_BOS:
274 case MPLS_LABEL:
275 case MPLS_TC:
276 case PBB_ISID:
277 case SCTP_DST:
278 case SCTP_SRC:
279 case TCP_DST:
280 case TCP_SRC:
281 case TUNNEL_ID:
282 case UDP_DST:
283 case UDP_SRC:
284 default:
285 log.warn("Match type {} not yet implemented.", c.type());
286 }
287 }
288 return mBuilder.build();
289 }
290
alshabib219ebaa2014-09-22 15:41:24 -0700291
292
alshabibeec3a062014-09-17 18:01:26 -0700293}