blob: 3ba155fda2561b3656d4a1ec12d3ed2f87af5e69 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.flow.impl;
Jonathan Hart86e59352014-10-22 10:42:16 -070017
alshabib346b5b32015-03-06 00:42:16 -080018import com.google.common.collect.Lists;
Jonathan Hart29afca32015-01-20 18:17:39 -080019import org.onlab.packet.Ip4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080020import org.onlab.packet.Ip6Address;
Charles M.C. Chanfe421812015-01-12 18:20:51 +080021import org.onosproject.net.PortNumber;
Brian O'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.net.flow.FlowRule;
23import org.onosproject.net.flow.TrafficTreatment;
24import org.onosproject.net.flow.instructions.Instruction;
alshabib9af70072015-02-09 14:34:16 -080025import org.onosproject.net.flow.instructions.Instructions;
sangho8995ac52015-02-04 11:29:03 -080026import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
alshabib9af70072015-02-09 14:34:16 -080027import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.flow.instructions.L0ModificationInstruction;
29import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction;
31import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
Jonathan Hart29afca32015-01-20 18:17:39 -080032import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
34import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
36import org.onosproject.net.flow.instructions.L3ModificationInstruction;
37import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080038import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
Jonathan Hart86e59352014-10-22 10:42:16 -070039import org.projectfloodlight.openflow.protocol.OFFactory;
40import org.projectfloodlight.openflow.protocol.OFFlowAdd;
41import org.projectfloodlight.openflow.protocol.OFFlowDelete;
42import org.projectfloodlight.openflow.protocol.OFFlowMod;
43import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
44import org.projectfloodlight.openflow.protocol.action.OFAction;
sangho8995ac52015-02-04 11:29:03 -080045import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
Charles M.C. Chanfe421812015-01-12 18:20:51 +080046import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib9af70072015-02-09 14:34:16 -080047import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Jonathan Hart86e59352014-10-22 10:42:16 -070048import org.projectfloodlight.openflow.protocol.match.Match;
49import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
50import org.projectfloodlight.openflow.types.CircuitSignalID;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080051import org.projectfloodlight.openflow.types.EthType;
Jonathan Hart86e59352014-10-22 10:42:16 -070052import org.projectfloodlight.openflow.types.IPv4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080053import org.projectfloodlight.openflow.types.IPv6Address;
54import org.projectfloodlight.openflow.types.IPv6FlowLabel;
Jonathan Hart86e59352014-10-22 10:42:16 -070055import org.projectfloodlight.openflow.types.MacAddress;
56import org.projectfloodlight.openflow.types.OFBufferId;
sangho8995ac52015-02-04 11:29:03 -080057import org.projectfloodlight.openflow.types.OFGroup;
Jonathan Hart86e59352014-10-22 10:42:16 -070058import org.projectfloodlight.openflow.types.OFPort;
59import org.projectfloodlight.openflow.types.OFVlanVidMatch;
alshabib9af70072015-02-09 14:34:16 -080060import org.projectfloodlight.openflow.types.TableId;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080061import org.projectfloodlight.openflow.types.U32;
Jonathan Hart86e59352014-10-22 10:42:16 -070062import org.projectfloodlight.openflow.types.U64;
63import org.projectfloodlight.openflow.types.VlanPcp;
64import org.slf4j.Logger;
65import org.slf4j.LoggerFactory;
66
Jonathan Hart29afca32015-01-20 18:17:39 -080067import java.util.Collections;
68import java.util.LinkedList;
69import java.util.List;
70import java.util.Optional;
71
Jonathan Hart86e59352014-10-22 10:42:16 -070072/**
73 * Flow mod builder for OpenFlow 1.3+.
74 */
75public class FlowModBuilderVer13 extends FlowModBuilder {
76
alshabib10580802015-02-18 18:30:33 -080077 private final Logger log = LoggerFactory.getLogger(getClass());
Charles M.C. Chanfe421812015-01-12 18:20:51 +080078 private static final int OFPCML_NO_BUFFER = 0xffff;
Jonathan Hart86e59352014-10-22 10:42:16 -070079
80 private final TrafficTreatment treatment;
81
82 /**
83 * Constructor for a flow mod builder for OpenFlow 1.3.
84 *
85 * @param flowRule the flow rule to transform into a flow mod
86 * @param factory the OpenFlow factory to use to build the flow mod
Pavlin Radoslavov119fd5c2014-11-25 19:08:19 -080087 * @param xid the transaction ID
Jonathan Hart86e59352014-10-22 10:42:16 -070088 */
Brian O'Connor427a1762014-11-19 18:40:32 -080089 protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
90 super(flowRule, factory, xid);
Jonathan Hart86e59352014-10-22 10:42:16 -070091
92 this.treatment = flowRule.treatment();
93 }
94
95 @Override
96 public OFFlowAdd buildFlowAdd() {
97 Match match = buildMatch();
alshabib346b5b32015-03-06 00:42:16 -080098 List<OFAction> deferredActions = buildActions(treatment.deferred());
99 List<OFAction> immediateActions = buildActions(treatment.immediate());
100 List<OFInstruction> instructions = Lists.newLinkedList();
Saurav Dascbe6de32015-03-01 18:30:46 -0800101
Jonathan Hartd4a8bba2014-10-28 12:44:20 -0700102
alshabib346b5b32015-03-06 00:42:16 -0800103 if (immediateActions.size() > 0) {
104 instructions.add(factory().instructions().applyActions(immediateActions));
105 }
106 if (treatment.clearedDeferred()) {
107 instructions.add(factory().instructions().clearActions());
108 }
109 if (deferredActions.size() > 0) {
110 instructions.add(factory().instructions().writeActions(deferredActions));
111 }
112 if (treatment.tableTransition() != null) {
113 instructions.add(buildTableGoto(treatment.tableTransition()));
Saurav Dascbe6de32015-03-01 18:30:46 -0800114 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700115
116 long cookie = flowRule().id().value();
117
Jonathan Hart86e59352014-10-22 10:42:16 -0700118 OFFlowAdd fm = factory().buildFlowAdd()
Brian O'Connor427a1762014-11-19 18:40:32 -0800119 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700120 .setCookie(U64.of(cookie))
121 .setBufferId(OFBufferId.NO_BUFFER)
alshabib9af70072015-02-09 14:34:16 -0800122 .setInstructions(instructions)
Jonathan Hart86e59352014-10-22 10:42:16 -0700123 .setMatch(match)
124 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
125 .setPriority(flowRule().priority())
alshabib08d98982015-04-21 16:25:50 -0700126 .setTableId(TableId.of(flowRule().tableId()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700127 .build();
128
129 return fm;
130 }
131
132 @Override
133 public OFFlowMod buildFlowMod() {
134 Match match = buildMatch();
alshabib346b5b32015-03-06 00:42:16 -0800135 List<OFAction> deferredActions = buildActions(treatment.deferred());
136 List<OFAction> immediateActions = buildActions(treatment.immediate());
137 List<OFInstruction> instructions = Lists.newLinkedList();
Jonathan Harteda33872015-02-18 10:22:32 -0800138
alshabib346b5b32015-03-06 00:42:16 -0800139
140 if (immediateActions.size() > 0) {
141 instructions.add(factory().instructions().applyActions(immediateActions));
142 }
143 if (treatment.clearedDeferred()) {
144 instructions.add(factory().instructions().clearActions());
145 }
146 if (deferredActions.size() > 0) {
147 instructions.add(factory().instructions().writeActions(deferredActions));
148 }
149 if (treatment.tableTransition() != null) {
150 instructions.add(buildTableGoto(treatment.tableTransition()));
Saurav Dascbe6de32015-03-01 18:30:46 -0800151 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700152
153 long cookie = flowRule().id().value();
154
Jonathan Hart86e59352014-10-22 10:42:16 -0700155 OFFlowMod fm = factory().buildFlowModify()
Brian O'Connor427a1762014-11-19 18:40:32 -0800156 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700157 .setCookie(U64.of(cookie))
158 .setBufferId(OFBufferId.NO_BUFFER)
alshabib9af70072015-02-09 14:34:16 -0800159 .setInstructions(instructions)
Jonathan Hart86e59352014-10-22 10:42:16 -0700160 .setMatch(match)
161 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
162 .setPriority(flowRule().priority())
alshabib08d98982015-04-21 16:25:50 -0700163 .setTableId(TableId.of(flowRule().tableId()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700164 .build();
165
166 return fm;
167 }
168
169 @Override
170 public OFFlowDelete buildFlowDel() {
171 Match match = buildMatch();
Jonathan Hart86e59352014-10-22 10:42:16 -0700172
173 long cookie = flowRule().id().value();
174
175 OFFlowDelete fm = factory().buildFlowDelete()
Brian O'Connor427a1762014-11-19 18:40:32 -0800176 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700177 .setCookie(U64.of(cookie))
178 .setBufferId(OFBufferId.NO_BUFFER)
Jonathan Hart86e59352014-10-22 10:42:16 -0700179 .setMatch(match)
180 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
181 .setPriority(flowRule().priority())
alshabib08d98982015-04-21 16:25:50 -0700182 .setTableId(TableId.of(flowRule().tableId()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700183 .build();
184
185 return fm;
186 }
187
alshabib346b5b32015-03-06 00:42:16 -0800188 private List<OFAction> buildActions(List<Instruction> treatments) {
Jonathan Hart86e59352014-10-22 10:42:16 -0700189 List<OFAction> actions = new LinkedList<>();
Saurav Dascbe6de32015-03-01 18:30:46 -0800190 boolean tableFound = false;
Jonathan Hart86e59352014-10-22 10:42:16 -0700191 if (treatment == null) {
192 return actions;
193 }
alshabib346b5b32015-03-06 00:42:16 -0800194 for (Instruction i : treatments) {
Jonathan Hart86e59352014-10-22 10:42:16 -0700195 switch (i.type()) {
alshabib9af70072015-02-09 14:34:16 -0800196 case DROP:
alshabib9af70072015-02-09 14:34:16 -0800197 return new LinkedList<>();
198 case L0MODIFICATION:
199 actions.add(buildL0Modification(i));
200 break;
201 case L2MODIFICATION:
202 actions.add(buildL2Modification(i));
203 break;
204 case L3MODIFICATION:
205 actions.add(buildL3Modification(i));
206 break;
207 case OUTPUT:
208 OutputInstruction out = (OutputInstruction) i;
209 OFActionOutput.Builder action = factory().actions().buildOutput()
210 .setPort(OFPort.of((int) out.port().toLong()));
211 if (out.port().equals(PortNumber.CONTROLLER)) {
212 action.setMaxLen(OFPCML_NO_BUFFER);
213 }
214 actions.add(action.build());
215 break;
216 case GROUP:
217 GroupInstruction group = (GroupInstruction) i;
218 OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
219 .setGroup(OFGroup.of(group.groupId().id()));
220 actions.add(groupBuilder.build());
221 break;
alshabib10580802015-02-18 18:30:33 -0800222 case TABLE:
223 //FIXME: should not occur here.
Saurav Dascbe6de32015-03-01 18:30:46 -0800224 tableFound = true;
alshabib10580802015-02-18 18:30:33 -0800225 break;
alshabib9af70072015-02-09 14:34:16 -0800226 default:
227 log.warn("Instruction type {} not yet implemented.", i.type());
Jonathan Hart86e59352014-10-22 10:42:16 -0700228 }
229 }
Saurav Dascbe6de32015-03-01 18:30:46 -0800230 if (tableFound && actions.isEmpty()) {
231 // handles the case where there are no actions, but there is
232 // a goto instruction for the next table
233 return null;
234 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700235 return actions;
236 }
237
alshabib9af70072015-02-09 14:34:16 -0800238 private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
239 OFInstruction instruction = factory().instructions().gotoTable(
alshabibd17abc22015-04-21 18:26:35 -0700240 TableId.of(i.tableId()));
alshabib9af70072015-02-09 14:34:16 -0800241 return instruction;
242 }
243
Jonathan Hart86e59352014-10-22 10:42:16 -0700244 private OFAction buildL0Modification(Instruction i) {
245 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
246 switch (l0m.subtype()) {
247 case LAMBDA:
248 ModLambdaInstruction ml = (ModLambdaInstruction) i;
249 return factory().actions().circuit(factory().oxms().ochSigidBasic(
250 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
251 default:
252 log.warn("Unimplemented action type {}.", l0m.subtype());
253 break;
254 }
255 return null;
256 }
257
258 private OFAction buildL2Modification(Instruction i) {
259 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
260 ModEtherInstruction eth;
261 OFOxm<?> oxm = null;
262 switch (l2m.subtype()) {
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800263 case ETH_DST:
264 eth = (ModEtherInstruction) l2m;
265 oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
266 break;
267 case ETH_SRC:
268 eth = (ModEtherInstruction) l2m;
269 oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
270 break;
271 case VLAN_ID:
272 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
273 oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
274 break;
275 case VLAN_PCP:
276 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
277 oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
278 break;
279 case MPLS_PUSH:
280 PushHeaderInstructions pushHeaderInstructions =
281 (PushHeaderInstructions) l2m;
282 return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800283 .ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800284 case MPLS_POP:
Jonathan Hart67fc0972015-03-19 15:21:20 -0700285 PushHeaderInstructions popHeaderInstructions =
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800286 (PushHeaderInstructions) l2m;
287 return factory().actions().popMpls(EthType.of(popHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800288 .ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800289 case MPLS_LABEL:
290 ModMplsLabelInstruction mplsLabel =
291 (ModMplsLabelInstruction) l2m;
292 oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label()
293 .longValue()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800294 break;
sangho3f97a17d2015-01-29 22:56:29 -0800295 case DEC_MPLS_TTL:
296 return factory().actions().decMplsTtl();
Saurav Dasfbe25c52015-03-04 11:12:00 -0800297 case VLAN_POP:
298 return factory().actions().popVlan();
Jonathan Hart54b406b2015-03-06 16:24:14 -0800299 case VLAN_PUSH:
300 PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
301 return factory().actions().pushVlan(
302 EthType.of(pushVlanInstruction.ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800303 default:
304 log.warn("Unimplemented action type {}.", l2m.subtype());
305 break;
Jonathan Hart86e59352014-10-22 10:42:16 -0700306 }
307
308 if (oxm != null) {
309 return factory().actions().buildSetField().setField(oxm).build();
310 }
311 return null;
312 }
313
314 private OFAction buildL3Modification(Instruction i) {
315 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
316 ModIPInstruction ip;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800317 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800318 Ip6Address ip6;
Jonathan Hart86e59352014-10-22 10:42:16 -0700319 OFOxm<?> oxm = null;
320 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800321 case IPV4_SRC:
322 ip = (ModIPInstruction) i;
323 ip4 = ip.ip().getIp4Address();
324 oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
325 break;
326 case IPV4_DST:
Jonathan Hart86e59352014-10-22 10:42:16 -0700327 ip = (ModIPInstruction) i;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800328 ip4 = ip.ip().getIp4Address();
329 oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
Ray Milkey241b96a2014-11-17 13:08:20 -0800330 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800331 case IPV6_SRC:
Jonathan Hart86e59352014-10-22 10:42:16 -0700332 ip = (ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800333 ip6 = ip.ip().getIp6Address();
334 oxm = factory().oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
335 break;
336 case IPV6_DST:
337 ip = (ModIPInstruction) i;
338 ip6 = ip.ip().getIp6Address();
339 oxm = factory().oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
340 break;
341 case IPV6_FLABEL:
342 ModIPv6FlowLabelInstruction flowLabelInstruction =
343 (ModIPv6FlowLabelInstruction) i;
344 int flowLabel = flowLabelInstruction.flowLabel();
345 oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
Ray Milkey241b96a2014-11-17 13:08:20 -0800346 break;
sangho3f97a17d2015-01-29 22:56:29 -0800347 case DEC_TTL:
348 return factory().actions().decNwTtl();
349 case TTL_IN:
350 return factory().actions().copyTtlIn();
351 case TTL_OUT:
352 return factory().actions().copyTtlOut();
Jonathan Hart86e59352014-10-22 10:42:16 -0700353 default:
354 log.warn("Unimplemented action type {}.", l3m.subtype());
355 break;
356 }
357
358 if (oxm != null) {
359 return factory().actions().buildSetField().setField(oxm).build();
360 }
361 return null;
362 }
363
364}