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