blob: 7f5a09967f2a3eaf96a93977908a7de88df36b35 [file] [log] [blame]
Cem Türker3baff672017-10-12 15:09:01 +03001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * 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
7 *
8 * 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.
15 */
16package org.onosproject.provider.of.flow.impl;
17
18import com.google.common.collect.Lists;
19import com.google.common.collect.Sets;
20import org.onosproject.net.PortNumber;
21import org.onosproject.net.driver.DriverService;
22import org.onosproject.net.flow.FlowRule;
23import org.onosproject.net.flow.StatTriggerField;
24import org.onosproject.net.flow.StatTriggerFlag;
25import org.onosproject.net.flow.instructions.Instruction;
26import org.onosproject.net.flow.instructions.Instructions;
27import org.projectfloodlight.openflow.protocol.OFFactory;
28import org.projectfloodlight.openflow.protocol.OFFlowAdd;
29import org.projectfloodlight.openflow.protocol.OFFlowMod;
30import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
31import org.projectfloodlight.openflow.protocol.OFOxsList;
32import org.projectfloodlight.openflow.protocol.OFStatTriggerFlags;
33import org.projectfloodlight.openflow.protocol.action.OFAction;
34import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
35import org.projectfloodlight.openflow.protocol.action.OFActionMeter;
36import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
37import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
38import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
39import org.projectfloodlight.openflow.protocol.match.Match;
40import org.projectfloodlight.openflow.protocol.oxs.OFOxs;
41import org.projectfloodlight.openflow.types.OFBufferId;
42import org.projectfloodlight.openflow.types.OFGroup;
43import org.projectfloodlight.openflow.types.OFPort;
44import org.projectfloodlight.openflow.types.TableId;
45import org.projectfloodlight.openflow.types.U32;
46import org.projectfloodlight.openflow.types.U64;
47
48import java.util.Collections;
49import java.util.LinkedList;
50import java.util.List;
51import java.util.Map;
52import java.util.Optional;
53import java.util.Set;
54
55import static org.projectfloodlight.openflow.protocol.OFStatTriggerFlags.ONLY_FIRST;
56import static org.projectfloodlight.openflow.protocol.OFStatTriggerFlags.PERIODIC;
57
58/**
59 * Flow mod builder for OpenFlow 1.5+.
60 */
61public class FlowModBuilderVer15 extends FlowModBuilderVer13 {
62
63 /**
64 * Constructor for a flow mod builder for OpenFlow 1.5.
65 *
66 * @param flowRule the flow rule to transform into a flow mod
67 * @param factory the OpenFlow factory to use to build the flow mod
68 * @param xid the transaction ID
69 * @param driverService the device driver service
70 */
71 protected FlowModBuilderVer15(FlowRule flowRule, OFFactory factory,
72 Optional<Long> xid,
73 Optional<DriverService> driverService) {
74 super(flowRule, factory, xid, driverService);
75 }
76
77 @Override
78 public OFFlowMod buildFlowAdd() {
79 Match match = buildMatch();
80 List<OFAction> deferredActions = buildActions(treatment.deferred(), false);
81 List<OFAction> immediateActions = buildActions(treatment.immediate(), true);
82 List<OFInstruction> instructions = Lists.newLinkedList();
83
84 if (treatment.clearedDeferred()) {
85 instructions.add(factory().instructions().clearActions());
86 }
87 if (!immediateActions.isEmpty()) {
88 instructions.add(factory().instructions().applyActions(immediateActions));
89 }
90 if (!deferredActions.isEmpty()) {
91 instructions.add(factory().instructions().writeActions(deferredActions));
92 }
93 if (treatment.tableTransition() != null) {
94 instructions.add(buildTableGoto(treatment.tableTransition()));
95 }
96 if (treatment.writeMetadata() != null) {
97 instructions.add(buildMetadata(treatment.writeMetadata()));
98 }
99 if (treatment.statTrigger() != null) {
100 instructions.add(buildStatTrigger(treatment.statTrigger()));
101 }
102
103
104
105 long cookie = flowRule().id().value();
106
107 OFFlowAdd fm = factory().buildFlowAdd()
108 .setXid(xid)
109 .setCookie(U64.of(cookie))
110 .setBufferId(OFBufferId.NO_BUFFER)
111 .setInstructions(instructions)
112 .setMatch(match)
113 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
114 .setPriority(flowRule().priority())
115 .setTableId(TableId.of(flowRule().tableId()))
116 .setHardTimeout(flowRule().hardTimeout())
117 .build();
118
119 return fm;
120 }
121
122 @Override
123 public OFFlowMod buildFlowMod() {
124 Match match = buildMatch();
125 List<OFAction> deferredActions = buildActions(treatment.deferred(), false);
126 List<OFAction> immediateActions = buildActions(treatment.immediate(), true);
127 List<OFInstruction> instructions = Lists.newLinkedList();
128
129
130 if (!immediateActions.isEmpty()) {
131 instructions.add(factory().instructions().applyActions(immediateActions));
132 }
133 if (treatment.clearedDeferred()) {
134 instructions.add(factory().instructions().clearActions());
135 }
136 if (!deferredActions.isEmpty()) {
137 instructions.add(factory().instructions().writeActions(deferredActions));
138 }
139 if (treatment.tableTransition() != null) {
140 instructions.add(buildTableGoto(treatment.tableTransition()));
141 }
142 if (treatment.writeMetadata() != null) {
143 instructions.add(buildMetadata(treatment.writeMetadata()));
144 }
145 if (treatment.statTrigger() != null) {
146 instructions.add(buildStatTrigger(treatment.statTrigger()));
147 }
148
149 long cookie = flowRule().id().value();
150
151 OFFlowMod fm = factory().buildFlowModify()
152 .setXid(xid)
153 .setCookie(U64.of(cookie))
154 .setBufferId(OFBufferId.NO_BUFFER)
155 .setInstructions(instructions)
156 .setMatch(match)
157 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
158 .setPriority(flowRule().priority())
159 .setTableId(TableId.of(flowRule().tableId()))
160 .setHardTimeout(flowRule().hardTimeout())
161 .build();
162
163 return fm;
164 }
165
166 private List<OFAction> buildActions(List<Instruction> treatments, Boolean immediateActions) {
167 if (treatment == null) {
168 return Collections.emptyList();
169 }
170
171 boolean tableFound = false;
172 List<OFAction> actions = new LinkedList<>();
173
174 //Meter action handling
cansu.toprak409289d2017-10-27 10:04:05 +0300175 if (null != treatment.meters() && immediateActions) {
176 treatment.meters().forEach(meterInstruction -> {
177 OFAction meterAction = buildMeterAction(meterInstruction);
178 actions.add(meterAction);
179 });
Cem Türker3baff672017-10-12 15:09:01 +0300180 }
181
182 for (Instruction i : treatments) {
183 switch (i.type()) {
184 case NOACTION:
185 return Collections.emptyList();
186 case L0MODIFICATION:
187 actions.add(buildL0Modification(i));
188 break;
189 case L1MODIFICATION:
190 actions.add(buildL1Modification(i));
191 break;
192 case L2MODIFICATION:
193 actions.add(buildL2Modification(i));
194 break;
195 case L3MODIFICATION:
196 actions.add(buildL3Modification(i));
197 break;
198 case L4MODIFICATION:
199 actions.add(buildL4Modification(i));
200 break;
201 case OUTPUT:
202 Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
203 OFActionOutput.Builder action = factory().actions().buildOutput()
204 .setPort(OFPort.of((int) out.port().toLong()));
205 if (out.port().equals(PortNumber.CONTROLLER)) {
206 action.setMaxLen(OFPCML_NO_BUFFER);
207 }
208 actions.add(action.build());
209 break;
210 case GROUP:
211 Instructions.GroupInstruction group = (Instructions.GroupInstruction) i;
212 OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
213 .setGroup(OFGroup.of(group.groupId().id()));
214 actions.add(groupBuilder.build());
215 break;
216 case QUEUE:
217 Instructions.SetQueueInstruction queue = (Instructions.SetQueueInstruction) i;
218 OFActionSetQueue.Builder queueBuilder = factory().actions().buildSetQueue()
219 .setQueueId(queue.queueId());
220 actions.add(queueBuilder.build());
221 break;
222 case TABLE:
223 //FIXME: should not occur here.
224 tableFound = true;
225 break;
226 case EXTENSION:
227 actions.add(buildExtensionAction(((Instructions.ExtensionInstructionWrapper) i)
228 .extensionInstruction()));
229 break;
230 default:
231 log.warn("Instruction type {} not yet implemented.", i.type());
232 }
233 }
234
235 if (tableFound && actions.isEmpty()) {
236 // handles the case where there are no actions, but there is
237 // a goto instruction for the next table
238 return Collections.emptyList();
239 }
240 return actions;
241 }
242
243 private OFOxsList getOFOxsList(Map<StatTriggerField, Long> statTriggerMap) {
244 OFFactory factory = factory();
245 List<OFOxs<?>> ofOxsList = Lists.newArrayList();
246 for (Map.Entry<StatTriggerField, Long> entry : statTriggerMap.entrySet()) {
247 switch (entry.getKey()) {
248 case DURATION:
249 ofOxsList.add(factory.oxss().buildDuration().setValue(U64.of(entry.getValue())).build());
250 break;
251 case IDLE_TIME:
252 ofOxsList.add(factory.oxss().buildIdleTime().setValue(U64.of(entry.getValue())).build());
253 break;
254 case BYTE_COUNT:
255 ofOxsList.add(factory.oxss().buildByteCount().setValue(U64.of(entry.getValue())).build());
256 break;
257 case FLOW_COUNT:
258 ofOxsList.add(factory.oxss().buildFlowCount().setValue(U32.of(entry.getValue())).build());
259 break;
260 case PACKET_COUNT:
261 ofOxsList.add(factory.oxss().buildPacketCount().setValue(U64.of(entry.getValue())).build());
262 break;
263 default:
264 log.warn("Unsupported Stat Trigger field");
265 break;
266 }
267 }
268 return OFOxsList.ofList(ofOxsList);
269 }
270
271 private Set<OFStatTriggerFlags> getStatTriggerFlag(StatTriggerFlag flag) {
272 Set<OFStatTriggerFlags> statTriggerFlagsSet = Sets.newHashSet();
273 switch (flag) {
274 case PERIODIC:
275 statTriggerFlagsSet.add(PERIODIC);
276 break;
277 case ONLY_FIRST:
278 statTriggerFlagsSet.add(ONLY_FIRST);
279 break;
280 default:
281 break;
282 }
283 return statTriggerFlagsSet;
284 }
285
286 /**
287 * Meter action builder.
288 *
289 * @param meterInstruction meter instruction
290 * @return meter action
291 */
cansu.toprak409289d2017-10-27 10:04:05 +0300292 protected OFAction buildMeterAction(Instructions.MeterInstruction meterInstruction) {
Cem Türker3baff672017-10-12 15:09:01 +0300293 OFActionMeter.Builder meterBuilder = factory().actions().buildMeter()
294 .setMeterId(meterInstruction.meterId().id());
295 return meterBuilder.build();
296 }
297
298 protected OFInstruction buildStatTrigger(Instructions.StatTriggerInstruction s) {
299 OFInstruction instruction = factory().instructions().statTrigger(getStatTriggerFlag(s.getStatTriggerFlag()),
300 getOFOxsList(s.getStatTriggerFieldMap()));
301 return instruction;
302 }
303}