blob: 61b8b0e73a6707a9c96c9805b7f5c6915b6f2a3c [file] [log] [blame]
Brian O'Connor7cbbbb72016-04-09 02:13:23 -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 */
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -050016package org.onosproject.driver.pipeline;
17
18import org.onlab.packet.Ethernet;
19import org.onlab.packet.MacAddress;
20import org.onlab.packet.VlanId;
21import org.onosproject.core.ApplicationId;
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.FlowRuleOperations;
27import org.onosproject.net.flow.FlowRuleOperationsContext;
28import org.onosproject.net.flow.TrafficSelector;
29import org.onosproject.net.flow.TrafficTreatment;
30import org.onosproject.net.flow.criteria.Criteria;
31import org.onosproject.net.flow.criteria.Criterion;
32import org.onosproject.net.flow.criteria.EthCriterion;
33import org.onosproject.net.flow.criteria.IPCriterion;
34import org.onosproject.net.flow.criteria.PortCriterion;
35import org.onosproject.net.flow.criteria.VlanIdCriterion;
36import org.onosproject.net.flow.instructions.Instructions;
37import org.onosproject.net.flow.instructions.L2ModificationInstruction;
38import org.onosproject.net.flowobjective.FilteringObjective;
39import org.onosproject.net.flowobjective.ForwardingObjective;
40import org.onosproject.net.flowobjective.ObjectiveError;
41import org.onosproject.net.meter.Band;
42import org.onosproject.net.meter.DefaultBand;
43import org.onosproject.net.meter.DefaultMeterRequest;
44import org.onosproject.net.meter.Meter;
45import org.onosproject.net.meter.MeterId;
46import org.onosproject.net.meter.MeterRequest;
47import org.slf4j.Logger;
48
49import java.util.Collection;
50import java.util.Collections;
51
52import static org.slf4j.LoggerFactory.getLogger;
53
54public class CorsaPipelineV3 extends OVSCorsaPipeline {
55
56 private final Logger log = getLogger(getClass());
57
58 protected static final int PORT_BASED_PROTO_TABLE = 0;
59 protected static final int VLAN_CHECK_TABLE = 1;
60 protected static final int VLAN_MAC_XLATE_TABLE = 2;
61 protected static final int VLAN_CIRCUIT_TABLE = 3;
62 protected static final int PRIORITY_MAP_TABLE = 4;
63 protected static final int L3_IF_MAC_DA_TABLE = 5;
64 protected static final int ETHER_TABLE = 6;
65 protected static final int FIB_TABLE = 7;
66 protected static final int LOCAL_TABLE = 9;
67
68 protected static final byte MAX_VLAN_PCP = 7;
69
70 private MeterId defaultMeterId = null;
71
72 @Override
73 protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) {
74 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
75
76 treatment.immediate().stream()
77 .filter(i -> i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
78 i instanceof L2ModificationInstruction.ModEtherInstruction ||
79 i instanceof Instructions.OutputInstruction)
80 .forEach(i -> tb.add(i));
81 return tb.build();
82 }
83
84 @Override
85 protected TrafficTreatment.Builder processSpecificRoutingTreatment() {
86 return DefaultTrafficTreatment.builder().deferred();
87 }
88
89 @Override
90 protected FlowRule.Builder processSpecificRoutingRule(FlowRule.Builder rb) {
91 return rb.forTable(FIB_TABLE);
92 }
93
94 @Override
95 protected Collection<FlowRule> processSpecificSwitch(ForwardingObjective fwd) {
96 TrafficSelector filteredSelector =
97 DefaultTrafficSelector.builder()
98 .matchInPort(
99 ((PortCriterion) fwd.selector().getCriterion(Criterion.Type.IN_PORT)).port())
100 .matchVlanId(
101 ((VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID)).vlanId())
102 .build();
103
104 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
105 .fromApp(fwd.appId())
106 .withPriority(fwd.priority())
107 .forDevice(deviceId)
108 .withSelector(filteredSelector)
109 .withTreatment(fwd.treatment())
110 .forTable(VLAN_CIRCUIT_TABLE);
111
112 if (fwd.permanent()) {
113 ruleBuilder.makePermanent();
114 } else {
115 ruleBuilder.makeTemporary(fwd.timeout());
116 }
117
118 return Collections.singletonList(ruleBuilder.build());
119 }
120
121 @Override
122 protected void processFilter(FilteringObjective filt, boolean install,
123 ApplicationId applicationId) {
124 // This driver only processes filtering criteria defined with switch
125 // ports as the key
126 PortCriterion p;
127 if (!filt.key().equals(Criteria.dummy()) &&
128 filt.key().type() == Criterion.Type.IN_PORT) {
129 p = (PortCriterion) filt.key();
130 } else {
131 log.warn("No key defined in filtering objective from app: {}. Not"
132 + "processing filtering objective", applicationId);
133 fail(filt, ObjectiveError.UNKNOWN);
134 return;
135 }
136 // convert filtering conditions for switch-intfs into flowrules
137 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
138 for (Criterion c : filt.conditions()) {
139 if (c.type() == Criterion.Type.ETH_DST) {
140 EthCriterion e = (EthCriterion) c;
141 log.debug("adding rule for MAC: {}", e.mac());
142 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
143 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
144 selector.matchEthDst(e.mac());
145 selector.matchInPort(p.port());
146 treatment.transition(ETHER_TABLE);
147 FlowRule rule = DefaultFlowRule.builder()
148 .forDevice(deviceId)
149 .withSelector(selector.build())
150 .withTreatment(treatment.build())
151 .withPriority(CONTROLLER_PRIORITY)
152 .fromApp(applicationId)
153 .makePermanent()
154 .forTable(L3_IF_MAC_DA_TABLE).build();
155 ops = install ? ops.add(rule) : ops.remove(rule);
156 } else if (c.type() == Criterion.Type.VLAN_VID) {
157 VlanIdCriterion v = (VlanIdCriterion) c;
158 log.debug("adding rule for VLAN: {}", v.vlanId());
159 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
160 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
161 selector.matchVlanId(v.vlanId());
162 selector.matchInPort(p.port());
163 /* Static treatment for VLAN_CIRCUIT_TABLE */
164 treatment.setVlanPcp(MAX_VLAN_PCP);
165 treatment.setQueue(0);
166 treatment.meter(MeterId.meterId(defaultMeterId.id())); /* use default meter (Green) */
167 treatment.transition(L3_IF_MAC_DA_TABLE);
168 FlowRule rule = DefaultFlowRule.builder()
169 .forDevice(deviceId)
170 .withSelector(selector.build())
171 .withTreatment(treatment.build())
172 .withPriority(CONTROLLER_PRIORITY)
173 .fromApp(applicationId)
174 .makePermanent()
175 .forTable(VLAN_CIRCUIT_TABLE).build();
176 ops = install ? ops.add(rule) : ops.remove(rule);
177 } else if (c.type() == Criterion.Type.IPV4_DST) {
178 IPCriterion ip = (IPCriterion) c;
179 log.debug("adding rule for IP: {}", ip.ip());
180 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
181 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
182 selector.matchEthType(Ethernet.TYPE_IPV4);
183 selector.matchIPDst(ip.ip());
184 treatment.transition(LOCAL_TABLE);
185 FlowRule rule = DefaultFlowRule.builder()
186 .forDevice(deviceId)
187 .withSelector(selector.build())
188 .withTreatment(treatment.build())
189 .withPriority(HIGHEST_PRIORITY)
190 .fromApp(applicationId)
191 .makePermanent()
192 .forTable(FIB_TABLE).build();
193
194 ops = install ? ops.add(rule) : ops.remove(rule);
195 } else {
196 log.warn("Driver does not currently process filtering condition"
197 + " of type: {}", c.type());
198 fail(filt, ObjectiveError.UNSUPPORTED);
199 }
200 }
201 // apply filtering flow rules
202 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
203 @Override
204 public void onSuccess(FlowRuleOperations ops) {
205 pass(filt);
206 log.info("Applied filtering rules");
207 }
208
209 @Override
210 public void onError(FlowRuleOperations ops) {
211 fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
212 log.info("Failed to apply filtering rules");
213 }
214 }));
215 }
216
217 public void initializePipeline() {
218 processMeterTable(true);
219 processPortBasedProtoTable(true); /* Table 0 */
220 processVlanCheckTable(true); /* Table 1 */
221 processVlanMacXlateTable(true); /* Table 2 */
222 processVlanCircuitTable(true); /* Table 3 */
223 processPriorityMapTable(true); /* Table 4 */
224 processL3IFMacDATable(true); /* Table 5 */
225 processEtherTable(true); /* Table 6 */
226 processFibTable(true); /* Table 7 */
227 processLocalTable(true); /* Table 9 */
228 }
229
230 private void processMeterTable(boolean install) {
231 /* Green meter : Pass all traffic */
232 Band dropBand = DefaultBand.builder()
233 .ofType(Band.Type.DROP)
234 .withRate(0xFFFFFFFF) /* Max Rate */
235 .build();
236 MeterRequest.Builder ops = DefaultMeterRequest.builder()
237 .forDevice(deviceId)
238 .withBands(Collections.singletonList(dropBand))
239 .fromApp(appId);
240
241 Meter meter = meterService.submit(install ? ops.add() : ops.remove());
242 defaultMeterId = meter.id();
243 }
244
245 private void processPortBasedProtoTable(boolean install) {
246 /* Default action */
247 processTableMissGoTo(install, PORT_BASED_PROTO_TABLE, VLAN_CHECK_TABLE);
248 }
249
250 private void processVlanCheckTable(boolean install) {
251 int table = VLAN_CHECK_TABLE;
252
253 /* Default action */
254 processTableMissDrop(install, table);
255
256 /* Tagged packets to VLAN_MAC_XLATE */
257 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
258 selector.matchVlanId(VlanId.ANY);
259
260 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
261 treatment.transition(VLAN_MAC_XLATE_TABLE);
262
263 FlowRule rule = DefaultFlowRule.builder()
264 .forDevice(deviceId)
265 .withSelector(selector.build())
266 .withTreatment(treatment.build())
267 .withPriority(CONTROLLER_PRIORITY)
268 .fromApp(appId)
269 .makePermanent()
270 .forTable(table).build();
271 processFlowRule(install, rule);
272 }
273
274 private void processVlanMacXlateTable(boolean install) {
275 /* Default action */
276 processTableMissGoTo(install, VLAN_MAC_XLATE_TABLE, VLAN_CIRCUIT_TABLE);
277 }
278
279 private void processVlanCircuitTable(boolean install) {
280 /* Default action */
281 processTableMissDrop(install, VLAN_CIRCUIT_TABLE);
282 }
283
284 private void processPriorityMapTable(boolean install) {
285 /* Not required currently */
286 }
287
288 private void processL3IFMacDATable(boolean install) {
289 int table = L3_IF_MAC_DA_TABLE;
290
291 /* Default action */
292 processTableMissDrop(install, table);
293
294 /* Allow MAC broadcast frames on all ports */
295 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
296 selector.matchEthDst(MacAddress.BROADCAST);
297
298 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
299 treatment.transition(ETHER_TABLE);
300
301 FlowRule rule = DefaultFlowRule.builder()
302 .forDevice(deviceId)
303 .withSelector(selector.build())
304 .withTreatment(treatment.build())
305 .withPriority(CONTROLLER_PRIORITY)
306 .fromApp(appId)
307 .makePermanent()
308 .forTable(table).build();
309 processFlowRule(install, rule);
310 }
311
312
313 private void processEtherTable(boolean install) {
314 int table = ETHER_TABLE;
315
316 /* Default action */
317 processTableMissDrop(install, table);
318
319 /* Arp to controller */
320 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
321 selector.matchEthType(Ethernet.TYPE_ARP);
322
323 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
324 treatment.punt();
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(table).build();
334 processFlowRule(install, rule);
335
336 /* IP to FIB_TABLE */
337 selector = DefaultTrafficSelector.builder();
338 selector.matchEthType(Ethernet.TYPE_IPV4);
339
340 treatment = DefaultTrafficTreatment.builder();
341 treatment.transition(FIB_TABLE);
342
343 rule = DefaultFlowRule.builder()
344 .forDevice(deviceId)
345 .withSelector(selector.build())
346 .withTreatment(treatment.build())
347 .withPriority(CONTROLLER_PRIORITY)
348 .fromApp(appId)
349 .makePermanent()
350 .forTable(table).build();
351 processFlowRule(install, rule);
352 }
353
354 private void processFibTable(boolean install) {
355 /* Default action */
356 processTableMissDrop(install, FIB_TABLE);
357 }
358
359 private void processLocalTable(boolean install) {
360 int table = LOCAL_TABLE;
361 /* Default action */
362 processTableMissDrop(install, table);
363
364 /* Send all protocols to controller */
365 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
366
367 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
368 treatment.punt();
369
370 FlowRule rule = DefaultFlowRule.builder()
371 .forDevice(deviceId)
372 .withSelector(selector.build())
373 .withTreatment(treatment.build())
374 .withPriority(CONTROLLER_PRIORITY)
375 .fromApp(appId)
376 .makePermanent()
377 .forTable(table).build();
378 processFlowRule(install, rule);
379 }
380
381 /* Init helper: Apply flow rule */
382 private void processFlowRule(boolean install, FlowRule rule) {
383 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
384 ops = install ? ops.add(rule) : ops.remove(rule);
385
386 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
387 @Override
388 public void onSuccess(FlowRuleOperations ops) {
389 log.info("Flow provision success: " + ops.toString() + ", " + rule.toString());
390 }
391
392 @Override
393 public void onError(FlowRuleOperations ops) {
394 log.info("Flow provision error: " + ops.toString() + ", " + rule.toString());
395 }
396 }));
397 }
398
399 /* Init helper: Table Miss = Drop */
400 private void processTableMissDrop(boolean install, int table) {
401 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
402
403 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
404 treatment.drop();
405
406 FlowRule rule = DefaultFlowRule.builder()
407 .forDevice(deviceId)
408 .withSelector(selector.build())
409 .withTreatment(treatment.build())
410 .withPriority(DROP_PRIORITY)
411 .fromApp(appId)
412 .makePermanent()
413 .forTable(table).build();
414
415 processFlowRule(install, rule);
416 }
417
418 /* Init helper: Table Miss = GoTo */
419 private void processTableMissGoTo(boolean install, int table, int goTo) {
420 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
421
422 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
423 treatment.transition(goTo);
424
425 FlowRule rule = DefaultFlowRule.builder()
426 .forDevice(deviceId)
427 .withSelector(selector.build())
428 .withTreatment(treatment.build())
429 .withPriority(DROP_PRIORITY)
430 .fromApp(appId)
431 .makePermanent()
432 .forTable(table).build();
433
434 processFlowRule(install, rule);
435 }
436}