blob: 937c9ac88eabe67775df7c33235f564bb3ee4e3a [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
2 * Copyright 2015 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 */
Saurav Das558afec2015-05-31 17:12:48 -070016package org.onosproject.driver.pipeline;
17
18import static org.slf4j.LoggerFactory.getLogger;
19
Saurav Das2857f382015-11-03 14:39:27 -080020import java.util.ArrayList;
Saurav Das8a0732e2015-11-20 15:27:53 -080021import java.util.Collection;
Saurav Das4f980082015-11-05 13:39:15 -080022import java.util.Collections;
Saurav Das8a0732e2015-11-20 15:27:53 -080023import java.util.Deque;
Saurav Das2857f382015-11-03 14:39:27 -080024import java.util.List;
Saurav Das4f980082015-11-05 13:39:15 -080025import java.util.Set;
26import java.util.concurrent.ConcurrentHashMap;
Saurav Das2857f382015-11-03 14:39:27 -080027
Saurav Das8a0732e2015-11-20 15:27:53 -080028import org.onlab.packet.Ethernet;
Saurav Das2857f382015-11-03 14:39:27 -080029import org.onlab.packet.VlanId;
30import org.onosproject.core.ApplicationId;
31import org.onosproject.net.Port;
32import org.onosproject.net.PortNumber;
Saurav Das8a0732e2015-11-20 15:27:53 -080033import org.onosproject.net.behaviour.NextGroup;
Saurav Das558afec2015-05-31 17:12:48 -070034import org.onosproject.net.flow.DefaultFlowRule;
35import org.onosproject.net.flow.DefaultTrafficSelector;
36import org.onosproject.net.flow.DefaultTrafficTreatment;
37import org.onosproject.net.flow.FlowRule;
38import org.onosproject.net.flow.FlowRuleOperations;
39import org.onosproject.net.flow.FlowRuleOperationsContext;
40import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.flow.TrafficTreatment;
Saurav Das8a0732e2015-11-20 15:27:53 -080042import org.onosproject.net.flow.criteria.Criterion;
43import org.onosproject.net.flow.criteria.EthTypeCriterion;
44import org.onosproject.net.flow.criteria.IPCriterion;
45import org.onosproject.net.flow.criteria.MplsBosCriterion;
46import org.onosproject.net.flow.criteria.MplsCriterion;
Saurav Das2857f382015-11-03 14:39:27 -080047import org.onosproject.net.flow.criteria.PortCriterion;
48import org.onosproject.net.flow.criteria.VlanIdCriterion;
Saurav Das8a0732e2015-11-20 15:27:53 -080049import org.onosproject.net.flow.instructions.Instruction;
50import org.onosproject.net.flowobjective.ForwardingObjective;
51import org.onosproject.net.flowobjective.ObjectiveError;
52import org.onosproject.net.group.Group;
53import org.onosproject.net.group.GroupKey;
Saurav Das558afec2015-05-31 17:12:48 -070054import org.slf4j.Logger;
55
56
57/**
Saurav Das822c4e22015-10-23 10:51:11 -070058 * Driver for software switch emulation of the OFDPA 2.0 pipeline.
Saurav Das558afec2015-05-31 17:12:48 -070059 * The software switch is the CPqD OF 1.3 switch.
60 */
Saurav Das822c4e22015-10-23 10:51:11 -070061public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
Saurav Das558afec2015-05-31 17:12:48 -070062
63 private final Logger log = getLogger(getClass());
64
65 @Override
Saurav Das2857f382015-11-03 14:39:27 -080066 protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
67 VlanIdCriterion vidCriterion,
68 VlanId assignedVlan,
69 ApplicationId applicationId) {
70 List<FlowRule> rules = new ArrayList<FlowRule>();
71 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
72 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
73 selector.matchVlanId(vidCriterion.vlanId());
Saurav Das4f980082015-11-05 13:39:15 -080074 treatment.transition(TMAC_TABLE);
75
76 VlanId storeVlan = null;
Saurav Das2857f382015-11-03 14:39:27 -080077 if (vidCriterion.vlanId() == VlanId.NONE) {
78 // untagged packets are assigned vlans
79 treatment.pushVlan().setVlanId(assignedVlan);
Saurav Das4f980082015-11-05 13:39:15 -080080 storeVlan = assignedVlan;
81 } else {
82 storeVlan = vidCriterion.vlanId();
Saurav Das2857f382015-11-03 14:39:27 -080083 }
Saurav Das2857f382015-11-03 14:39:27 -080084
85 // ofdpa cannot match on ALL portnumber, so we need to use separate
86 // rules for each port.
87 List<PortNumber> portnums = new ArrayList<PortNumber>();
88 if (portCriterion.port() == PortNumber.ALL) {
89 for (Port port : deviceService.getPorts(deviceId)) {
90 if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
91 portnums.add(port.number());
92 }
93 }
94 } else {
95 portnums.add(portCriterion.port());
96 }
Saurav Das4f980082015-11-05 13:39:15 -080097
Saurav Das2857f382015-11-03 14:39:27 -080098 for (PortNumber pnum : portnums) {
Saurav Das4f980082015-11-05 13:39:15 -080099 // update storage
100 port2Vlan.put(pnum, storeVlan);
101 Set<PortNumber> vlanPorts = vlan2Port.get(storeVlan);
102 if (vlanPorts == null) {
103 vlanPorts = Collections.newSetFromMap(
104 new ConcurrentHashMap<PortNumber, Boolean>());
105 vlanPorts.add(pnum);
106 vlan2Port.put(storeVlan, vlanPorts);
107 } else {
108 vlanPorts.add(pnum);
109 }
110 // create rest of flowrule
Saurav Das2857f382015-11-03 14:39:27 -0800111 selector.matchInPort(pnum);
112 FlowRule rule = DefaultFlowRule.builder()
113 .forDevice(deviceId)
114 .withSelector(selector.build())
115 .withTreatment(treatment.build())
116 .withPriority(DEFAULT_PRIORITY)
117 .fromApp(applicationId)
118 .makePermanent()
119 .forTable(VLAN_TABLE).build();
120 rules.add(rule);
121 }
122 return rules;
123 }
124
Saurav Das8a0732e2015-11-20 15:27:53 -0800125 @Override
126 protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
127 TrafficSelector selector = fwd.selector();
128 EthTypeCriterion ethType =
129 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
130 if ((ethType == null) ||
131 (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
132 (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
133 log.warn("processSpecific: Unsupported "
134 + "forwarding objective criteraia");
135 fail(fwd, ObjectiveError.UNSUPPORTED);
136 return Collections.emptySet();
137 }
138
139 int forTableId = -1;
140 TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
141 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
142 filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
143 .matchIPDst(((IPCriterion)
144 selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
145 forTableId = UNICAST_ROUTING_TABLE;
146 log.debug("processing IPv4 specific forwarding objective {} hash{} in dev:{}",
147 fwd.id(), fwd.hashCode(), deviceId);
148 } else {
149 filteredSelector
150 .matchEthType(Ethernet.MPLS_UNICAST)
151 .matchMplsLabel(((MplsCriterion)
152 selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
153 MplsBosCriterion bos = (MplsBosCriterion) selector
154 .getCriterion(Criterion.Type.MPLS_BOS);
155 if (bos != null) {
156 filteredSelector.matchMplsBos(bos.mplsBos());
157 }
158 forTableId = MPLS_TABLE_1;
159 log.debug("processing MPLS specific forwarding objective {} hash:{} in dev {}",
160 fwd.id(), fwd.hashCode(), deviceId);
161 }
162
163 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
164 if (fwd.treatment() != null) {
165 for (Instruction i : fwd.treatment().allInstructions()) {
166 tb.add(i);
167 }
168 }
169
170 if (fwd.nextId() != null) {
171 NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
172 List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
173 // we only need the top level group's key to point the flow to it
174 Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
175 if (group == null) {
176 log.warn("The group left!");
177 fail(fwd, ObjectiveError.GROUPMISSING);
178 return Collections.emptySet();
179 }
180 tb.deferred().group(group.id());
181 }
182 tb.transition(ACL_TABLE);
183 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
184 .fromApp(fwd.appId())
185 .withPriority(fwd.priority())
186 .forDevice(deviceId)
187 .withSelector(filteredSelector.build())
188 .withTreatment(tb.build())
189 .forTable(forTableId);
190
191 if (fwd.permanent()) {
192 ruleBuilder.makePermanent();
193 } else {
194 ruleBuilder.makeTemporary(fwd.timeout());
195 }
196
197 return Collections.singletonList(ruleBuilder.build());
198 }
199
Saurav Das2857f382015-11-03 14:39:27 -0800200
201 @Override
Saurav Das558afec2015-05-31 17:12:48 -0700202 protected void initializePipeline() {
203 processPortTable();
Saurav Das2857f382015-11-03 14:39:27 -0800204 // vlan table processing not required, as default is to drop packets
205 // which can be accomplished without a table-miss-entry.
Saurav Das558afec2015-05-31 17:12:48 -0700206 processTmacTable();
207 processIpTable();
Saurav Das2857f382015-11-03 14:39:27 -0800208 processMplsTable();
Saurav Das558afec2015-05-31 17:12:48 -0700209 processBridgingTable();
Saurav Das337c7a42015-06-02 15:12:06 -0700210 processAclTable();
Saurav Das558afec2015-05-31 17:12:48 -0700211 }
212
213 @Override
214 protected void processPortTable() {
215 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
216 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
217 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
218 treatment.transition(VLAN_TABLE);
219 FlowRule tmisse = DefaultFlowRule.builder()
220 .forDevice(deviceId)
221 .withSelector(selector.build())
222 .withTreatment(treatment.build())
223 .withPriority(LOWEST_PRIORITY)
224 .fromApp(driverId)
225 .makePermanent()
226 .forTable(PORT_TABLE).build();
227 ops = ops.add(tmisse);
228
229 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
230 @Override
231 public void onSuccess(FlowRuleOperations ops) {
232 log.info("Initialized port table");
233 }
234
235 @Override
236 public void onError(FlowRuleOperations ops) {
237 log.info("Failed to initialize port table");
238 }
239 }));
240 }
241
242 @Override
243 protected void processTmacTable() {
244 //table miss entry
245 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
246 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
247 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
248 selector = DefaultTrafficSelector.builder();
249 treatment = DefaultTrafficTreatment.builder();
250 treatment.transition(BRIDGING_TABLE);
251 FlowRule rule = DefaultFlowRule.builder()
252 .forDevice(deviceId)
253 .withSelector(selector.build())
254 .withTreatment(treatment.build())
255 .withPriority(LOWEST_PRIORITY)
256 .fromApp(driverId)
257 .makePermanent()
258 .forTable(TMAC_TABLE).build();
259 ops = ops.add(rule);
260 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
261 @Override
262 public void onSuccess(FlowRuleOperations ops) {
263 log.info("Initialized tmac table");
264 }
265
266 @Override
267 public void onError(FlowRuleOperations ops) {
268 log.info("Failed to initialize tmac table");
269 }
270 }));
271 }
272
273 @Override
274 protected void processIpTable() {
275 //table miss entry
276 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
277 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
278 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
279 selector = DefaultTrafficSelector.builder();
280 treatment = DefaultTrafficTreatment.builder();
281 treatment.transition(ACL_TABLE);
282 FlowRule rule = DefaultFlowRule.builder()
283 .forDevice(deviceId)
284 .withSelector(selector.build())
285 .withTreatment(treatment.build())
286 .withPriority(LOWEST_PRIORITY)
287 .fromApp(driverId)
288 .makePermanent()
289 .forTable(UNICAST_ROUTING_TABLE).build();
290 ops = ops.add(rule);
291 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
292 @Override
293 public void onSuccess(FlowRuleOperations ops) {
294 log.info("Initialized IP table");
295 }
296
297 @Override
298 public void onError(FlowRuleOperations ops) {
299 log.info("Failed to initialize unicast IP table");
300 }
301 }));
302 }
303
Saurav Das2857f382015-11-03 14:39:27 -0800304 @Override
305 protected void processMplsTable() {
306 //table miss entry
307 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
308 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
309 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
310 selector = DefaultTrafficSelector.builder();
311 treatment = DefaultTrafficTreatment.builder();
312 treatment.transition(MPLS_TABLE_1);
313 FlowRule rule = DefaultFlowRule.builder()
314 .forDevice(deviceId)
315 .withSelector(selector.build())
316 .withTreatment(treatment.build())
317 .withPriority(LOWEST_PRIORITY)
318 .fromApp(driverId)
319 .makePermanent()
320 .forTable(MPLS_TABLE_0).build();
321 ops = ops.add(rule);
322
323 treatment.transition(ACL_TABLE);
324 rule = DefaultFlowRule.builder()
325 .forDevice(deviceId)
326 .withSelector(selector.build())
327 .withTreatment(treatment.build())
328 .withPriority(LOWEST_PRIORITY)
329 .fromApp(driverId)
330 .makePermanent()
331 .forTable(MPLS_TABLE_1).build();
332 ops = ops.add(rule);
333
334 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
335 @Override
336 public void onSuccess(FlowRuleOperations ops) {
337 log.info("Initialized MPLS tables");
338 }
339
340 @Override
341 public void onError(FlowRuleOperations ops) {
342 log.info("Failed to initialize MPLS tables");
343 }
344 }));
345 }
346
Saurav Das558afec2015-05-31 17:12:48 -0700347 private void processBridgingTable() {
348 //table miss entry
349 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
350 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
351 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
352 selector = DefaultTrafficSelector.builder();
353 treatment = DefaultTrafficTreatment.builder();
354 treatment.transition(ACL_TABLE);
355 FlowRule rule = DefaultFlowRule.builder()
356 .forDevice(deviceId)
357 .withSelector(selector.build())
358 .withTreatment(treatment.build())
359 .withPriority(LOWEST_PRIORITY)
360 .fromApp(driverId)
361 .makePermanent()
362 .forTable(BRIDGING_TABLE).build();
363 ops = ops.add(rule);
364 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
365 @Override
366 public void onSuccess(FlowRuleOperations ops) {
367 log.info("Initialized Bridging table");
368 }
369
370 @Override
371 public void onError(FlowRuleOperations ops) {
372 log.info("Failed to initialize Bridging table");
373 }
374 }));
Saurav Das337c7a42015-06-02 15:12:06 -0700375 }
Saurav Das558afec2015-05-31 17:12:48 -0700376
Saurav Das822c4e22015-10-23 10:51:11 -0700377 @Override
Saurav Dasa07f2032015-10-19 14:37:36 -0700378 protected void processAclTable() {
Saurav Das337c7a42015-06-02 15:12:06 -0700379 //table miss entry - catch all to executed action-set
380 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
381 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
382 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
383 selector = DefaultTrafficSelector.builder();
384 treatment = DefaultTrafficTreatment.builder();
385 FlowRule rule = DefaultFlowRule.builder()
386 .forDevice(deviceId)
387 .withSelector(selector.build())
388 .withTreatment(treatment.build())
389 .withPriority(LOWEST_PRIORITY)
390 .fromApp(driverId)
391 .makePermanent()
392 .forTable(ACL_TABLE).build();
393 ops = ops.add(rule);
394 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
395 @Override
396 public void onSuccess(FlowRuleOperations ops) {
397 log.info("Initialized Acl table");
398 }
399
400 @Override
401 public void onError(FlowRuleOperations ops) {
402 log.info("Failed to initialize Acl table");
403 }
404 }));
Saurav Das558afec2015-05-31 17:12:48 -0700405 }
406
407}