blob: 9272fe5d4737b7a3bf9784e5b28bbe1356d87ce0 [file] [log] [blame]
Michele Santuari9a8d16d2016-03-24 10:37:58 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Michele Santuari9a8d16d2016-03-24 10:37:58 -07003 *
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.drivers.corsa;
17
Michele Santuarid2c8b152016-03-30 17:57:56 -070018import com.google.common.collect.ImmutableSet;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070019import org.onlab.packet.Ethernet;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
22import org.onosproject.net.flow.DefaultFlowRule;
23import org.onosproject.net.flow.DefaultTrafficSelector;
24import org.onosproject.net.flow.DefaultTrafficTreatment;
25import org.onosproject.net.flow.FlowRule;
26import org.onosproject.net.flow.TrafficSelector;
27import org.onosproject.net.flow.TrafficTreatment;
28import org.onosproject.net.flow.criteria.Criterion;
29import org.onosproject.net.flow.criteria.EthCriterion;
30import org.onosproject.net.flow.criteria.IPCriterion;
31import org.onosproject.net.flow.criteria.PortCriterion;
32import org.onosproject.net.flow.criteria.VlanIdCriterion;
Pier Ventredb673552016-07-20 15:37:19 +020033import org.onosproject.net.flow.instructions.Instruction;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070034import org.onosproject.net.flow.instructions.L2ModificationInstruction;
35import org.onosproject.net.flowobjective.FilteringObjective;
36import org.onosproject.net.flowobjective.ForwardingObjective;
Pier Ventredb673552016-07-20 15:37:19 +020037import org.onosproject.net.flowobjective.NextObjective;
38import org.onosproject.net.flowobjective.ObjectiveError;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070039import org.onosproject.net.meter.Band;
40import org.onosproject.net.meter.DefaultBand;
41import org.onosproject.net.meter.DefaultMeterRequest;
42import org.onosproject.net.meter.Meter;
43import org.onosproject.net.meter.MeterId;
44import org.onosproject.net.meter.MeterRequest;
45import org.slf4j.Logger;
46
47import java.util.Collection;
48import java.util.Collections;
49
50import static org.onosproject.net.flow.FlowRule.Builder;
51import static org.slf4j.LoggerFactory.getLogger;
52
53/**
54 * Implementation of the Corsa pipeline handler for pipeline version 3.
55 */
56public class CorsaPipelineV3 extends AbstractCorsaPipeline {
57
58 private final Logger log = getLogger(getClass());
59
60 protected static final int PORT_BASED_PROTO_TABLE = 0;
61 protected static final int VLAN_CHECK_TABLE = 1;
62 protected static final int VLAN_MAC_XLATE_TABLE = 2;
63 protected static final int VLAN_CIRCUIT_TABLE = 3;
64 protected static final int PRIORITY_MAP_TABLE = 4;
65 protected static final int L3_IF_MAC_DA_TABLE = 5;
66 protected static final int ETHER_TABLE = 6;
67 protected static final int FIB_TABLE = 7;
68 protected static final int LOCAL_TABLE = 9;
69
70 protected static final byte MAX_VLAN_PCP = 7;
71
72 protected MeterId defaultMeterId = null;
73
74 @Override
Pier Ventredb673552016-07-20 15:37:19 +020075 protected CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) {
Michele Santuari9a8d16d2016-03-24 10:37:58 -070076 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
77
Pier Ventredb673552016-07-20 15:37:19 +020078
79
Michele Santuari9a8d16d2016-03-24 10:37:58 -070080 treatment.immediate().stream()
81 .filter(i -> {
82 switch (i.type()) {
83 case L2MODIFICATION:
84 L2ModificationInstruction l2i = (L2ModificationInstruction) i;
85 if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
86 l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
87 return true;
88 }
89 case OUTPUT:
90 return true;
91 default:
92 return false;
93 }
94 }).forEach(i -> tb.add(i));
Pier Ventredb673552016-07-20 15:37:19 +020095
96 TrafficTreatment t = tb.build();
97
98
99 boolean isPresentModVlanId = false;
100 boolean isPresentModEthSrc = false;
101 boolean isPresentModEthDst = false;
102 boolean isPresentOutpuPort = false;
103
104 for (Instruction instruction : t.immediate()) {
105 switch (instruction.type()) {
106 case L2MODIFICATION:
107 L2ModificationInstruction l2i = (L2ModificationInstruction) instruction;
108 if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) {
109 isPresentModVlanId = true;
110 }
111
112 if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
113 L2ModificationInstruction.L2SubType subType = l2i.subtype();
114 if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) {
115 isPresentModEthSrc = true;
116 } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) {
117 isPresentModEthDst = true;
118 }
119 }
Pier Luigi325c7572018-01-18 19:30:33 +0100120 break;
Pier Ventredb673552016-07-20 15:37:19 +0200121 case OUTPUT:
122 isPresentOutpuPort = true;
123 default:
124 }
125 }
126 CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS;
127 /**
128 * This represents the allowed group for CorsaPipelinev3
129 */
130 if (isPresentModVlanId &&
131 isPresentModEthSrc &&
132 isPresentModEthDst &&
133 isPresentOutpuPort) {
134 type = CorsaTrafficTreatmentType.GROUP;
135 }
136 CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t);
137 return corsaTreatment;
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700138 }
139
140 @Override
141 protected TrafficTreatment.Builder processSpecificRoutingTreatment() {
142 return DefaultTrafficTreatment.builder().deferred();
143 }
144
145 @Override
146 protected Builder processSpecificRoutingRule(Builder rb) {
147 return rb.forTable(FIB_TABLE);
148 }
149
150 @Override
151 protected Collection<FlowRule> processSpecificSwitch(ForwardingObjective fwd) {
152 TrafficSelector filteredSelector =
153 DefaultTrafficSelector.builder()
154 .matchInPort(
155 ((PortCriterion) fwd.selector().getCriterion(Criterion.Type.IN_PORT)).port())
156 .matchVlanId(
157 ((VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID)).vlanId())
158 .build();
159
160 Builder ruleBuilder = DefaultFlowRule.builder()
161 .fromApp(fwd.appId())
162 .withPriority(fwd.priority())
163 .forDevice(deviceId)
164 .withSelector(filteredSelector)
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700165 .forTable(VLAN_CIRCUIT_TABLE);
166
Pier Ventredb673552016-07-20 15:37:19 +0200167 if (fwd.treatment() != null) {
168 ruleBuilder.withTreatment(fwd.treatment());
169 } else {
170 if (fwd.nextId() != null) {
171 NextObjective nextObjective = pendingNext.getIfPresent(fwd.nextId());
172 if (nextObjective != null) {
173 pendingNext.invalidate(fwd.nextId());
174 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
175 .setVlanPcp((byte) 0)
176 .setQueue(0)
177 .meter(defaultMeterId);
178 nextObjective.next().forEach(trafficTreatment -> {
179 trafficTreatment.allInstructions().forEach(instruction -> {
180 treatment.add(instruction);
181 });
182 });
183 ruleBuilder.withTreatment(treatment.build());
184 } else {
185 log.warn("The group left!");
186 fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
187 return ImmutableSet.of();
188 }
189 } else {
190 log.warn("Missing NextObjective ID for ForwardingObjective {}", fwd.id());
191 fail(fwd, ObjectiveError.BADPARAMS);
192 return ImmutableSet.of();
193 }
194 }
195
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700196 if (fwd.permanent()) {
197 ruleBuilder.makePermanent();
198 } else {
199 ruleBuilder.makeTemporary(fwd.timeout());
200 }
201
202 return Collections.singletonList(ruleBuilder.build());
203 }
204
205 @Override
206 protected Collection<FlowRule> processArpTraffic(ForwardingObjective fwd, Builder rule) {
207 //TODO
Michele Santuarid2c8b152016-03-30 17:57:56 -0700208 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700209 }
210
211 @Override
212 protected Collection<FlowRule> processLinkDiscovery(ForwardingObjective fwd, Builder rule) {
213 //TODO
Michele Santuarid2c8b152016-03-30 17:57:56 -0700214 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700215 }
216
217 @Override
218 protected Collection<FlowRule> processIpTraffic(ForwardingObjective fwd, Builder rule) {
219 //TODO
Michele Santuarid2c8b152016-03-30 17:57:56 -0700220 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700221 }
222
223 @Override
224 protected Builder processEthFiler(FilteringObjective filt, EthCriterion eth, PortCriterion port) {
Michele Santuarid2c8b152016-03-30 17:57:56 -0700225 log.debug("adding rule for MAC: {}", eth.mac());
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700226 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
227 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
228 selector.matchEthDst(eth.mac());
229 selector.matchInPort(port.port());
230 treatment.transition(ETHER_TABLE);
231 return DefaultFlowRule.builder()
232 .withSelector(selector.build())
233 .withTreatment(treatment.build())
234 .withPriority(CONTROLLER_PRIORITY)
235 .makePermanent()
236 .forTable(L3_IF_MAC_DA_TABLE);
237 }
238
239 @Override
240 protected Builder processVlanFiler(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) {
241 log.debug("adding rule for VLAN: {}", vlan.vlanId());
242 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
243 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
244 selector.matchVlanId(vlan.vlanId());
245 selector.matchInPort(port.port());
246 /* Static treatment for VLAN_CIRCUIT_TABLE */
247 treatment.setVlanPcp(MAX_VLAN_PCP);
248 treatment.setQueue(0);
249 treatment.meter(MeterId.meterId(defaultMeterId.id())); /* use default meter (Green) */
250 treatment.transition(L3_IF_MAC_DA_TABLE);
251 return DefaultFlowRule.builder()
252 .withSelector(selector.build())
253 .withTreatment(treatment.build())
254 .withPriority(CONTROLLER_PRIORITY)
255 .makePermanent()
256 .forTable(VLAN_CIRCUIT_TABLE);
257 }
258
259 @Override
260 protected Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) {
261 log.debug("adding rule for IP: {}", ip.ip());
262 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
263 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
264 selector.matchEthType(Ethernet.TYPE_IPV4);
265 selector.matchIPDst(ip.ip());
266 treatment.transition(LOCAL_TABLE);
267 return DefaultFlowRule.builder()
268 .withSelector(selector.build())
269 .withTreatment(treatment.build())
270 .withPriority(HIGHEST_PRIORITY)
271 .makePermanent()
272 .forTable(FIB_TABLE);
273 }
274
275 @Override
276 public void initializePipeline() {
277 processMeterTable(true);
278 processPortBasedProtoTable(true); /* Table 0 */
279 processVlanCheckTable(true); /* Table 1 */
280 processVlanMacXlateTable(true); /* Table 2 */
281 processVlanCircuitTable(true); /* Table 3 */
282 processPriorityMapTable(true); /* Table 4 */
283 processL3IFMacDATable(true); /* Table 5 */
284 processEtherTable(true); /* Table 6 */
285 processFibTable(true); /* Table 7 */
286 processLocalTable(true); /* Table 9 */
287 }
288
289 protected void processMeterTable(boolean install) {
290 //Green meter : Pass all traffic
291 Band dropBand = DefaultBand.builder()
292 .ofType(Band.Type.DROP)
293 .withRate(0xFFFFFFFF) /* Max Rate */
294 .build();
295 MeterRequest.Builder ops = DefaultMeterRequest.builder()
296 .forDevice(deviceId)
297 .withBands(Collections.singletonList(dropBand))
298 .fromApp(appId);
299
300 Meter meter = meterService.submit(install ? ops.add() : ops.remove());
301 defaultMeterId = meter.id();
302 }
303
304 protected void processPortBasedProtoTable(boolean install) {
305 /* Default action */
306 processTableMissGoTo(install, PORT_BASED_PROTO_TABLE, VLAN_CHECK_TABLE, "Provisioned port-based table");
307 }
308
309 protected void processVlanCheckTable(boolean install) {
310
311 /* Default action */
312 processTableMissDrop(install, VLAN_CHECK_TABLE, "Provisioned vlantable drop");
313
314 processTaggedPackets(install);
315
316 }
317
318 /* Tagged packets to VLAN_MAC_XLATE */
319 protected void processTaggedPackets(boolean install) {
320 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
321 selector.matchVlanId(VlanId.ANY);
322
323 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
324 treatment.transition(VLAN_MAC_XLATE_TABLE);
325
326 FlowRule rule = DefaultFlowRule.builder()
327 .forDevice(deviceId)
328 .withSelector(selector.build())
329 .withTreatment(treatment.build())
330 .withPriority(CONTROLLER_PRIORITY)
331 .fromApp(appId)
332 .makePermanent()
333 .forTable(VLAN_CHECK_TABLE).build();
334 processFlowRule(install, rule, "Provisioned vlan table tagged packets");
335 }
336
337 protected void processVlanMacXlateTable(boolean install) {
338 /* Default action */
339 processTableMissGoTo(install, VLAN_MAC_XLATE_TABLE, VLAN_CIRCUIT_TABLE, "Provisioned vlan mac table");
340 }
341
342 protected void processVlanCircuitTable(boolean install) {
343 /* Default action */
344 processTableMissDrop(install, VLAN_CIRCUIT_TABLE, "Provisioned vlan circuit");
345 }
346
347 private void processPriorityMapTable(boolean install) {
348 /* Not required currently */
349 }
350
351 protected void processL3IFMacDATable(boolean install) {
352 int table = L3_IF_MAC_DA_TABLE;
353
354 /* Default action */
355 processTableMissDrop(install, table, "Provisioned l3 table drop");
356
357 /* Allow MAC broadcast frames on all ports */
358 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
359 selector.matchEthDst(MacAddress.BROADCAST);
360
361 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
362 treatment.transition(ETHER_TABLE);
363
364 FlowRule rule = DefaultFlowRule.builder()
365 .forDevice(deviceId)
366 .withSelector(selector.build())
367 .withTreatment(treatment.build())
368 .withPriority(CONTROLLER_PRIORITY)
369 .fromApp(appId)
370 .makePermanent()
371 .forTable(table).build();
372 processFlowRule(install, rule, "Provisioned l3 table");
373 }
374
375
376 protected void processEtherTable(boolean install) {
377 int table = ETHER_TABLE;
378
379 /* Default action */
380 processTableMissDrop(install, table, "Provisioned ether type table drop");
381
382 /* Arp to controller */
383 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
384 selector.matchEthType(Ethernet.TYPE_ARP);
385
386 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
387 treatment.punt();
388
389 FlowRule rule = DefaultFlowRule.builder()
390 .forDevice(deviceId)
391 .withSelector(selector.build())
392 .withTreatment(treatment.build())
393 .withPriority(CONTROLLER_PRIORITY)
394 .fromApp(appId)
395 .makePermanent()
396 .forTable(table).build();
397 processFlowRule(install, rule, "Provisioned ether type table arp");
398
399 /* IP to FIB_TABLE */
400 selector = DefaultTrafficSelector.builder();
401 selector.matchEthType(Ethernet.TYPE_IPV4);
402
403 treatment = DefaultTrafficTreatment.builder();
404 treatment.transition(FIB_TABLE);
405
406 rule = DefaultFlowRule.builder()
407 .forDevice(deviceId)
408 .withSelector(selector.build())
409 .withTreatment(treatment.build())
410 .withPriority(CONTROLLER_PRIORITY)
411 .fromApp(appId)
412 .makePermanent()
413 .forTable(table).build();
414 processFlowRule(install, rule, "Provisioned ether type table ip");
415 }
416
Michele Santuarid2c8b152016-03-30 17:57:56 -0700417 protected void processFibTable(boolean install) {
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700418 /* Default action */
419 processTableMissDrop(install, FIB_TABLE, "Provisioned fib drop");
420 }
421
422 private void processLocalTable(boolean install) {
423 int table = LOCAL_TABLE;
424 /* Default action */
425 processTableMissDrop(install, table, "Provisioned local table drop");
426
427 /* Send all protocols to controller */
428 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
429
430 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
431 treatment.punt();
432
433 FlowRule rule = DefaultFlowRule.builder()
434 .forDevice(deviceId)
435 .withSelector(selector.build())
436 .withTreatment(treatment.build())
437 .withPriority(CONTROLLER_PRIORITY)
438 .fromApp(appId)
439 .makePermanent()
440 .forTable(table).build();
441 processFlowRule(install, rule, "Provisioned ether type table to controller");
442 }
443
444
445}