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