blob: 3eb6261719d5fba3e53fe2df2a68252ba8cfa16c [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;
Pier Luigi7f7f7ac2018-01-25 17:53:38 +010085 return l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
86 l2i instanceof L2ModificationInstruction.ModEtherInstruction;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070087 case OUTPUT:
88 return true;
89 default:
90 return false;
91 }
92 }).forEach(i -> tb.add(i));
Pier Ventredb673552016-07-20 15:37:19 +020093
94 TrafficTreatment t = tb.build();
95
96
97 boolean isPresentModVlanId = false;
98 boolean isPresentModEthSrc = false;
99 boolean isPresentModEthDst = false;
100 boolean isPresentOutpuPort = false;
101
102 for (Instruction instruction : t.immediate()) {
103 switch (instruction.type()) {
104 case L2MODIFICATION:
105 L2ModificationInstruction l2i = (L2ModificationInstruction) instruction;
106 if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) {
107 isPresentModVlanId = true;
108 }
109
110 if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
111 L2ModificationInstruction.L2SubType subType = l2i.subtype();
112 if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) {
113 isPresentModEthSrc = true;
114 } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) {
115 isPresentModEthDst = true;
116 }
117 }
Pier Luigi325c7572018-01-18 19:30:33 +0100118 break;
Pier Ventredb673552016-07-20 15:37:19 +0200119 case OUTPUT:
120 isPresentOutpuPort = true;
121 default:
122 }
123 }
124 CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS;
125 /**
126 * This represents the allowed group for CorsaPipelinev3
127 */
128 if (isPresentModVlanId &&
129 isPresentModEthSrc &&
130 isPresentModEthDst &&
131 isPresentOutpuPort) {
132 type = CorsaTrafficTreatmentType.GROUP;
133 }
134 CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t);
135 return corsaTreatment;
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700136 }
137
138 @Override
139 protected TrafficTreatment.Builder processSpecificRoutingTreatment() {
140 return DefaultTrafficTreatment.builder().deferred();
141 }
142
143 @Override
144 protected Builder processSpecificRoutingRule(Builder rb) {
145 return rb.forTable(FIB_TABLE);
146 }
147
148 @Override
149 protected Collection<FlowRule> processSpecificSwitch(ForwardingObjective fwd) {
150 TrafficSelector filteredSelector =
151 DefaultTrafficSelector.builder()
152 .matchInPort(
153 ((PortCriterion) fwd.selector().getCriterion(Criterion.Type.IN_PORT)).port())
154 .matchVlanId(
155 ((VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID)).vlanId())
156 .build();
157
158 Builder ruleBuilder = DefaultFlowRule.builder()
159 .fromApp(fwd.appId())
160 .withPriority(fwd.priority())
161 .forDevice(deviceId)
162 .withSelector(filteredSelector)
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700163 .forTable(VLAN_CIRCUIT_TABLE);
164
Pier Ventredb673552016-07-20 15:37:19 +0200165 if (fwd.treatment() != null) {
166 ruleBuilder.withTreatment(fwd.treatment());
167 } else {
168 if (fwd.nextId() != null) {
169 NextObjective nextObjective = pendingNext.getIfPresent(fwd.nextId());
170 if (nextObjective != null) {
171 pendingNext.invalidate(fwd.nextId());
172 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
173 .setVlanPcp((byte) 0)
174 .setQueue(0)
175 .meter(defaultMeterId);
176 nextObjective.next().forEach(trafficTreatment -> {
177 trafficTreatment.allInstructions().forEach(instruction -> {
178 treatment.add(instruction);
179 });
180 });
181 ruleBuilder.withTreatment(treatment.build());
182 } else {
183 log.warn("The group left!");
184 fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
185 return ImmutableSet.of();
186 }
187 } else {
188 log.warn("Missing NextObjective ID for ForwardingObjective {}", fwd.id());
189 fail(fwd, ObjectiveError.BADPARAMS);
190 return ImmutableSet.of();
191 }
192 }
193
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700194 if (fwd.permanent()) {
195 ruleBuilder.makePermanent();
196 } else {
197 ruleBuilder.makeTemporary(fwd.timeout());
198 }
199
200 return Collections.singletonList(ruleBuilder.build());
201 }
202
203 @Override
204 protected Collection<FlowRule> processArpTraffic(ForwardingObjective fwd, Builder rule) {
205 //TODO
Michele Santuarid2c8b152016-03-30 17:57:56 -0700206 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700207 }
208
209 @Override
210 protected Collection<FlowRule> processLinkDiscovery(ForwardingObjective fwd, Builder rule) {
211 //TODO
Michele Santuarid2c8b152016-03-30 17:57:56 -0700212 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700213 }
214
215 @Override
216 protected Collection<FlowRule> processIpTraffic(ForwardingObjective fwd, Builder rule) {
217 //TODO
Michele Santuarid2c8b152016-03-30 17:57:56 -0700218 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700219 }
220
221 @Override
222 protected Builder processEthFiler(FilteringObjective filt, EthCriterion eth, PortCriterion port) {
Michele Santuarid2c8b152016-03-30 17:57:56 -0700223 log.debug("adding rule for MAC: {}", eth.mac());
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700224 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
225 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
226 selector.matchEthDst(eth.mac());
227 selector.matchInPort(port.port());
228 treatment.transition(ETHER_TABLE);
229 return DefaultFlowRule.builder()
230 .withSelector(selector.build())
231 .withTreatment(treatment.build())
232 .withPriority(CONTROLLER_PRIORITY)
233 .makePermanent()
234 .forTable(L3_IF_MAC_DA_TABLE);
235 }
236
237 @Override
238 protected Builder processVlanFiler(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) {
239 log.debug("adding rule for VLAN: {}", vlan.vlanId());
240 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
241 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
242 selector.matchVlanId(vlan.vlanId());
243 selector.matchInPort(port.port());
244 /* Static treatment for VLAN_CIRCUIT_TABLE */
245 treatment.setVlanPcp(MAX_VLAN_PCP);
246 treatment.setQueue(0);
247 treatment.meter(MeterId.meterId(defaultMeterId.id())); /* use default meter (Green) */
248 treatment.transition(L3_IF_MAC_DA_TABLE);
249 return DefaultFlowRule.builder()
250 .withSelector(selector.build())
251 .withTreatment(treatment.build())
252 .withPriority(CONTROLLER_PRIORITY)
253 .makePermanent()
254 .forTable(VLAN_CIRCUIT_TABLE);
255 }
256
257 @Override
258 protected Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) {
259 log.debug("adding rule for IP: {}", ip.ip());
260 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
261 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
262 selector.matchEthType(Ethernet.TYPE_IPV4);
263 selector.matchIPDst(ip.ip());
264 treatment.transition(LOCAL_TABLE);
265 return DefaultFlowRule.builder()
266 .withSelector(selector.build())
267 .withTreatment(treatment.build())
268 .withPriority(HIGHEST_PRIORITY)
269 .makePermanent()
270 .forTable(FIB_TABLE);
271 }
272
273 @Override
274 public void initializePipeline() {
275 processMeterTable(true);
276 processPortBasedProtoTable(true); /* Table 0 */
277 processVlanCheckTable(true); /* Table 1 */
278 processVlanMacXlateTable(true); /* Table 2 */
279 processVlanCircuitTable(true); /* Table 3 */
280 processPriorityMapTable(true); /* Table 4 */
281 processL3IFMacDATable(true); /* Table 5 */
282 processEtherTable(true); /* Table 6 */
283 processFibTable(true); /* Table 7 */
284 processLocalTable(true); /* Table 9 */
285 }
286
287 protected void processMeterTable(boolean install) {
288 //Green meter : Pass all traffic
289 Band dropBand = DefaultBand.builder()
290 .ofType(Band.Type.DROP)
291 .withRate(0xFFFFFFFF) /* Max Rate */
292 .build();
293 MeterRequest.Builder ops = DefaultMeterRequest.builder()
294 .forDevice(deviceId)
295 .withBands(Collections.singletonList(dropBand))
296 .fromApp(appId);
297
298 Meter meter = meterService.submit(install ? ops.add() : ops.remove());
299 defaultMeterId = meter.id();
300 }
301
302 protected void processPortBasedProtoTable(boolean install) {
303 /* Default action */
304 processTableMissGoTo(install, PORT_BASED_PROTO_TABLE, VLAN_CHECK_TABLE, "Provisioned port-based table");
305 }
306
307 protected void processVlanCheckTable(boolean install) {
308
309 /* Default action */
310 processTableMissDrop(install, VLAN_CHECK_TABLE, "Provisioned vlantable drop");
311
312 processTaggedPackets(install);
313
314 }
315
316 /* Tagged packets to VLAN_MAC_XLATE */
317 protected void processTaggedPackets(boolean install) {
318 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
319 selector.matchVlanId(VlanId.ANY);
320
321 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
322 treatment.transition(VLAN_MAC_XLATE_TABLE);
323
324 FlowRule rule = DefaultFlowRule.builder()
325 .forDevice(deviceId)
326 .withSelector(selector.build())
327 .withTreatment(treatment.build())
328 .withPriority(CONTROLLER_PRIORITY)
329 .fromApp(appId)
330 .makePermanent()
331 .forTable(VLAN_CHECK_TABLE).build();
332 processFlowRule(install, rule, "Provisioned vlan table tagged packets");
333 }
334
335 protected void processVlanMacXlateTable(boolean install) {
336 /* Default action */
337 processTableMissGoTo(install, VLAN_MAC_XLATE_TABLE, VLAN_CIRCUIT_TABLE, "Provisioned vlan mac table");
338 }
339
340 protected void processVlanCircuitTable(boolean install) {
341 /* Default action */
342 processTableMissDrop(install, VLAN_CIRCUIT_TABLE, "Provisioned vlan circuit");
343 }
344
345 private void processPriorityMapTable(boolean install) {
346 /* Not required currently */
347 }
348
349 protected void processL3IFMacDATable(boolean install) {
350 int table = L3_IF_MAC_DA_TABLE;
351
352 /* Default action */
353 processTableMissDrop(install, table, "Provisioned l3 table drop");
354
355 /* Allow MAC broadcast frames on all ports */
356 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
357 selector.matchEthDst(MacAddress.BROADCAST);
358
359 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
360 treatment.transition(ETHER_TABLE);
361
362 FlowRule rule = DefaultFlowRule.builder()
363 .forDevice(deviceId)
364 .withSelector(selector.build())
365 .withTreatment(treatment.build())
366 .withPriority(CONTROLLER_PRIORITY)
367 .fromApp(appId)
368 .makePermanent()
369 .forTable(table).build();
370 processFlowRule(install, rule, "Provisioned l3 table");
371 }
372
373
374 protected void processEtherTable(boolean install) {
375 int table = ETHER_TABLE;
376
377 /* Default action */
378 processTableMissDrop(install, table, "Provisioned ether type table drop");
379
380 /* Arp to controller */
381 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
382 selector.matchEthType(Ethernet.TYPE_ARP);
383
384 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
385 treatment.punt();
386
387 FlowRule rule = DefaultFlowRule.builder()
388 .forDevice(deviceId)
389 .withSelector(selector.build())
390 .withTreatment(treatment.build())
391 .withPriority(CONTROLLER_PRIORITY)
392 .fromApp(appId)
393 .makePermanent()
394 .forTable(table).build();
395 processFlowRule(install, rule, "Provisioned ether type table arp");
396
397 /* IP to FIB_TABLE */
398 selector = DefaultTrafficSelector.builder();
399 selector.matchEthType(Ethernet.TYPE_IPV4);
400
401 treatment = DefaultTrafficTreatment.builder();
402 treatment.transition(FIB_TABLE);
403
404 rule = DefaultFlowRule.builder()
405 .forDevice(deviceId)
406 .withSelector(selector.build())
407 .withTreatment(treatment.build())
408 .withPriority(CONTROLLER_PRIORITY)
409 .fromApp(appId)
410 .makePermanent()
411 .forTable(table).build();
412 processFlowRule(install, rule, "Provisioned ether type table ip");
413 }
414
Michele Santuarid2c8b152016-03-30 17:57:56 -0700415 protected void processFibTable(boolean install) {
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700416 /* Default action */
417 processTableMissDrop(install, FIB_TABLE, "Provisioned fib drop");
418 }
419
420 private void processLocalTable(boolean install) {
421 int table = LOCAL_TABLE;
422 /* Default action */
423 processTableMissDrop(install, table, "Provisioned local table drop");
424
425 /* Send all protocols to controller */
426 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
427
428 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
429 treatment.punt();
430
431 FlowRule rule = DefaultFlowRule.builder()
432 .forDevice(deviceId)
433 .withSelector(selector.build())
434 .withTreatment(treatment.build())
435 .withPriority(CONTROLLER_PRIORITY)
436 .fromApp(appId)
437 .makePermanent()
438 .forTable(table).build();
439 processFlowRule(install, rule, "Provisioned ether type table to controller");
440 }
441
442
443}