blob: 9638f20d6f559f7167f8ca6d4974ca8ffe871505 [file] [log] [blame]
Charles Chanf9e98652016-09-07 16:54:23 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Charles Chanf9e98652016-09-07 16:54:23 -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 */
16
Yi Tsengef19de12017-04-24 11:33:05 -070017package org.onosproject.driver.pipeline.ofdpa;
Charles Chanf9e98652016-09-07 16:54:23 -070018
Pier Ventre42287df2016-11-09 14:17:26 -080019import com.google.common.collect.ImmutableList;
Jonghwan Hyuna76bf032018-04-09 09:40:50 -070020import org.onlab.packet.MacAddress;
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -070021import org.onlab.packet.VlanId;
Charles Chanf9e98652016-09-07 16:54:23 -070022import org.onosproject.core.ApplicationId;
Pier Ventre42287df2016-11-09 14:17:26 -080023import org.onosproject.driver.extensions.Ofdpa3MatchMplsL2Port;
24import org.onosproject.driver.extensions.Ofdpa3MatchOvid;
Pier Ventre70d53ba2016-11-17 22:26:29 -080025import org.onosproject.driver.extensions.Ofdpa3PopCw;
26import org.onosproject.driver.extensions.Ofdpa3PopL2Header;
Pier Ventre42287df2016-11-09 14:17:26 -080027import org.onosproject.driver.extensions.Ofdpa3SetMplsL2Port;
28import org.onosproject.driver.extensions.Ofdpa3SetMplsType;
29import org.onosproject.driver.extensions.Ofdpa3SetOvid;
30import org.onosproject.driver.extensions.Ofdpa3SetQosIndex;
Jonghwan Hyuna76bf032018-04-09 09:40:50 -070031import org.onosproject.driver.extensions.OfdpaMatchVlanVid;
32import org.onosproject.net.PortNumber;
Pier Ventre42287df2016-11-09 14:17:26 -080033import org.onosproject.net.behaviour.NextGroup;
Charles Chanf9e98652016-09-07 16:54:23 -070034import org.onosproject.net.behaviour.PipelinerContext;
Pier Ventre42287df2016-11-09 14:17:26 -080035import org.onosproject.net.flow.DefaultFlowRule;
36import org.onosproject.net.flow.DefaultTrafficSelector;
37import org.onosproject.net.flow.DefaultTrafficTreatment;
Charles Chanf9e98652016-09-07 16:54:23 -070038import org.onosproject.net.flow.FlowRule;
Pier Ventre42287df2016-11-09 14:17:26 -080039import org.onosproject.net.flow.FlowRuleOperations;
40import org.onosproject.net.flow.FlowRuleOperationsContext;
Andreas Pantelopoulos0eaa5162018-06-28 17:06:14 -070041import org.onosproject.net.flow.IndexTableId;
Pier Ventre42287df2016-11-09 14:17:26 -080042import org.onosproject.net.flow.TrafficSelector;
43import org.onosproject.net.flow.TrafficTreatment;
Jonghwan Hyuna76bf032018-04-09 09:40:50 -070044import org.onosproject.net.flow.criteria.Criteria;
Pier Ventre42287df2016-11-09 14:17:26 -080045import org.onosproject.net.flow.criteria.Criterion;
Jonghwan Hyuna76bf032018-04-09 09:40:50 -070046import org.onosproject.net.flow.criteria.EthCriterion;
Charles Chanf9e98652016-09-07 16:54:23 -070047import org.onosproject.net.flow.criteria.PortCriterion;
Pier Ventre42287df2016-11-09 14:17:26 -080048import org.onosproject.net.flow.criteria.TunnelIdCriterion;
Charles Chanf9e98652016-09-07 16:54:23 -070049import org.onosproject.net.flow.criteria.VlanIdCriterion;
Pier Ventre70d53ba2016-11-17 22:26:29 -080050import org.onosproject.net.flow.instructions.Instruction;
Andreas Pantelopoulos0eaa5162018-06-28 17:06:14 -070051import org.onosproject.net.flow.instructions.Instructions;
Pier Ventre70d53ba2016-11-17 22:26:29 -080052import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
Pier Ventre42287df2016-11-09 14:17:26 -080053import org.onosproject.net.flow.instructions.L2ModificationInstruction;
54import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
Pier Ventre70d53ba2016-11-17 22:26:29 -080055import org.onosproject.net.flow.instructions.L3ModificationInstruction;
Pier Ventre42287df2016-11-09 14:17:26 -080056import org.onosproject.net.flowobjective.FilteringObjective;
Charles Chanf9e98652016-09-07 16:54:23 -070057import org.onosproject.net.flowobjective.ForwardingObjective;
Pier Ventre42287df2016-11-09 14:17:26 -080058import org.onosproject.net.flowobjective.ObjectiveError;
59import org.onosproject.net.group.Group;
60import org.onosproject.net.group.GroupKey;
61import org.slf4j.Logger;
Charles Chanf9e98652016-09-07 16:54:23 -070062
63import java.util.Collection;
Pier Ventre42287df2016-11-09 14:17:26 -080064import java.util.Collections;
65import java.util.Deque;
Charles Chanf9e98652016-09-07 16:54:23 -070066import java.util.List;
67
Jonghwan Hyuna76bf032018-04-09 09:40:50 -070068import static org.onlab.packet.MacAddress.NONE;
Pier Ventre42287df2016-11-09 14:17:26 -080069import static org.onosproject.driver.extensions.Ofdpa3MplsType.VPWS;
Andrea Campanella2ade0c92018-04-30 11:48:55 +020070import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID;
71import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT;
72import static org.onosproject.net.flow.criteria.Criterion.Type.TUNNEL_ID;
73import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
Pier Ventre42287df2016-11-09 14:17:26 -080074import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
75import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
76import static org.slf4j.LoggerFactory.getLogger;
77
Charles Chanf9e98652016-09-07 16:54:23 -070078/**
79 * Pipeliner for Broadcom OF-DPA 3.0 TTP.
80 */
81public class Ofdpa3Pipeline extends Ofdpa2Pipeline {
Pier Ventre42287df2016-11-09 14:17:26 -080082
83 private final Logger log = getLogger(getClass());
84
Charles Chanf9e98652016-09-07 16:54:23 -070085 @Override
Charles Chan40132b32017-01-22 00:19:37 -080086 protected void initDriverId() {
Charles Chanf9e98652016-09-07 16:54:23 -070087 driverId = coreService.registerApplication(
88 "org.onosproject.driver.Ofdpa3Pipeline");
Charles Chan40132b32017-01-22 00:19:37 -080089 }
Charles Chanf9e98652016-09-07 16:54:23 -070090
Charles Chan40132b32017-01-22 00:19:37 -080091 @Override
92 protected void initGroupHander(PipelinerContext context) {
93 groupHandler = new Ofdpa3GroupHandler();
94 groupHandler.init(deviceId, context);
Charles Chanf9e98652016-09-07 16:54:23 -070095 }
96
97 @Override
Charles Chand1172632017-03-15 17:33:09 -070098 protected boolean requireVlanExtensions() {
99 return false;
100 }
101
102 @Override
Saurav Dasc568c342018-01-25 09:49:01 -0800103 protected boolean shouldRetry() {
104 return false;
105 }
106
107 @Override
Andrea Campanella2ade0c92018-04-30 11:48:55 +0200108 protected boolean supportsUnicastBlackHole() {
109 return true;
110 }
111
112 @Override
Pier Ventre42287df2016-11-09 14:17:26 -0800113 protected void processFilter(FilteringObjective filteringObjective,
114 boolean install,
115 ApplicationId applicationId) {
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700116
117 // Check if filter is intended for pseudowire
118 boolean isPw = isPseudowire(filteringObjective);
119
120 if (isPw) {
Pier Ventre42287df2016-11-09 14:17:26 -0800121 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
122 PortCriterion portCriterion;
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700123
124 VlanIdCriterion innerVlanIdCriterion = null;
125 for (Criterion criterion : filteringObjective.conditions()) {
126 if (criterion.type() == INNER_VLAN_VID) {
127 innerVlanIdCriterion = (VlanIdCriterion) criterion;
128 break;
129 }
130 }
131
Pier Ventre42287df2016-11-09 14:17:26 -0800132 VlanIdCriterion outerVlanIdCriterion = null;
133 // We extract the expected port criterion in the key.
134 portCriterion = (PortCriterion) filteringObjective.key();
135 // We extract the outer vlan id criterion.
136 for (Criterion criterion : filteringObjective.conditions()) {
137 if (criterion.type() == VLAN_VID) {
138 outerVlanIdCriterion = (VlanIdCriterion) criterion;
139 break;
140 }
141 }
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700142
Pier Ventre42287df2016-11-09 14:17:26 -0800143 // We extract the tunnel id.
144 long tunnelId;
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700145 VlanId egressVlan;
146
Pier Ventre42287df2016-11-09 14:17:26 -0800147 if (filteringObjective.meta() != null &&
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700148 filteringObjective.meta().allInstructions().size() != 2) {
Pier Ventre42287df2016-11-09 14:17:26 -0800149 log.warn("Bad filtering objective from app: {}. Not"
150 + "processing filtering objective", applicationId);
151 fail(filteringObjective, ObjectiveError.BADPARAMS);
152 return;
153 } else if (filteringObjective.meta() != null &&
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700154 filteringObjective.meta().allInstructions().size() == 2 &&
155 filteringObjective.meta().allInstructions().get(0).type() == L2MODIFICATION &&
156 filteringObjective.meta().allInstructions().get(1).type() == L2MODIFICATION) {
157
Pier Ventre42287df2016-11-09 14:17:26 -0800158 L2ModificationInstruction l2instruction = (L2ModificationInstruction)
159 filteringObjective.meta().allInstructions().get(0);
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700160
Pier Ventre42287df2016-11-09 14:17:26 -0800161 if (l2instruction.subtype() != L2SubType.TUNNEL_ID) {
162 log.warn("Bad filtering objective from app: {}. Not"
163 + "processing filtering objective", applicationId);
164 fail(filteringObjective, ObjectiveError.BADPARAMS);
165 return;
166 } else {
167 tunnelId = ((ModTunnelIdInstruction) l2instruction).tunnelId();
168 }
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700169
170 L2ModificationInstruction vlanInstruction = (L2ModificationInstruction)
171 filteringObjective.meta().allInstructions().get(1);
172
173 if (vlanInstruction.subtype() != L2SubType.VLAN_ID) {
174 log.warn("Bad filtering objective from app: {}. Not"
175 + "processing filtering objective", applicationId);
176 fail(filteringObjective, ObjectiveError.BADPARAMS);
177 return;
178 } else {
179 egressVlan = ((L2ModificationInstruction.ModVlanIdInstruction) vlanInstruction).vlanId();
180 }
Pier Ventre42287df2016-11-09 14:17:26 -0800181 } else {
182 log.warn("Bad filtering objective from app: {}. Not"
183 + "processing filtering objective", applicationId);
184 fail(filteringObjective, ObjectiveError.BADPARAMS);
185 return;
186 }
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700187
Pier Ventre42287df2016-11-09 14:17:26 -0800188 // Mpls tunnel ids according to the OFDPA manual have to be
189 // in the range [2^17-1, 2^16].
190 tunnelId = MPLS_TUNNEL_ID_BASE | tunnelId;
191 // Sanity check for the filtering objective.
192 if (portCriterion == null ||
193 outerVlanIdCriterion == null ||
194 tunnelId > MPLS_TUNNEL_ID_MAX) {
195 log.warn("Bad filtering objective from app: {}. Not"
196 + "processing filtering objective", applicationId);
197 fail(filteringObjective, ObjectiveError.BADPARAMS);
198 return;
199 }
200 // 0x0000XXXX is UNI interface.
Pier Ventre70d53ba2016-11-17 22:26:29 -0800201 if (portCriterion.port().toLong() > MPLS_UNI_PORT_MAX) {
Sivachidambaram Subramaniana0efdcc2017-06-22 05:26:46 +0530202 log.error("Filtering Objective invalid logical port {}",
Pier Ventre42287df2016-11-09 14:17:26 -0800203 portCriterion.port().toLong());
204 fail(filteringObjective, ObjectiveError.BADPARAMS);
205 return;
206 }
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700207
Pier Ventre42287df2016-11-09 14:17:26 -0800208 // We create the flows.
209 List<FlowRule> pwRules = processPwFilter(portCriterion,
210 innerVlanIdCriterion,
211 outerVlanIdCriterion,
212 tunnelId,
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700213 applicationId,
214 egressVlan
Pier Ventre42287df2016-11-09 14:17:26 -0800215 );
216 // We tag the flow for adding or for removing.
217 for (FlowRule pwRule : pwRules) {
218 log.debug("adding filtering rule in VLAN tables: {} for dev: {}",
219 pwRule, deviceId);
220 ops = install ? ops.add(pwRule) : ops.remove(pwRule);
221 }
222 // We push the filtering rules for the pw.
223 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
224 @Override
225 public void onSuccess(FlowRuleOperations ops) {
226 log.info("Applied {} filtering rules in device {}",
227 ops.stages().get(0).size(), deviceId);
228 pass(filteringObjective);
229 }
230
231 @Override
232 public void onError(FlowRuleOperations ops) {
233 log.info("Failed to apply all filtering rules in dev {}", deviceId);
234 fail(filteringObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
235 }
236 }));
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700237 } else if (isDoubleTagged(filteringObjective)) {
238 processDoubleTaggedFilter(filteringObjective, install, applicationId);
239 } else {
240 // If it is not a pseudo wire flow or double-tagged filter, we fall back
241 // to the OFDPA 2.0 pipeline.
242 super.processFilter(filteringObjective, install, applicationId);
243 }
244 }
Pier Ventre42287df2016-11-09 14:17:26 -0800245
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700246 /**
Andreas Pantelopoulos0eaa5162018-06-28 17:06:14 -0700247 *
248 * @param meta The metadata instruction of this treatment
249 * @return True if we should remove both VLAN and Mac Termination flow entries.
250 * This is only used for double tagged hosts.
251 */
252 public boolean shouldRemoveDoubleTagged(Instruction meta) {
253
254 Instructions.MetadataInstruction metadataInstruction = (Instructions.MetadataInstruction) meta;
255 return ((metadataInstruction.metadata() & metadataInstruction.metadataMask()) == 1);
256 }
257
258 /**
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700259 * Configure filtering rules of outer and inner VLAN IDs, and a MAC address.
260 * Filtering happens in three tables (VLAN_TABLE, VLAN_1_TABLE, TMAC_TABLE).
261 *
262 * @param filteringObjective the filtering objective
263 * @param install true to add, false to remove
264 * @param applicationId for application programming this filter
265 */
266 private void processDoubleTaggedFilter(FilteringObjective filteringObjective,
267 boolean install,
268 ApplicationId applicationId) {
269 PortCriterion portCriterion = null;
270 EthCriterion ethCriterion = null;
271 VlanIdCriterion innervidCriterion = null;
272 VlanIdCriterion outerVidCriterion = null;
273 boolean popVlan = false;
Andreas Pantelopoulos0eaa5162018-06-28 17:06:14 -0700274 boolean removeDoubleTagged = true;
275 if (filteringObjective.meta().writeMetadata() != null) {
276 removeDoubleTagged = shouldRemoveDoubleTagged(filteringObjective.meta().writeMetadata());
277 }
278 log.info("HERE , removeDoubleTagged {}", removeDoubleTagged);
279
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700280 TrafficTreatment meta = filteringObjective.meta();
281 if (!filteringObjective.key().equals(Criteria.dummy()) &&
282 filteringObjective.key().type() == Criterion.Type.IN_PORT) {
283 portCriterion = (PortCriterion) filteringObjective.key();
284 }
285 if (portCriterion == null) {
286 log.warn("No IN_PORT defined in filtering objective from app: {}" +
287 "Failed to program VLAN tables.", applicationId);
288 return;
289 } else {
290 log.debug("Received filtering objective for dev/port: {}/{}", deviceId,
291 portCriterion.port());
292 }
293
294 // meta should have only one instruction, popVlan.
295 if (meta != null && meta.allInstructions().size() == 1) {
296 L2ModificationInstruction l2Inst = (L2ModificationInstruction) meta.allInstructions().get(0);
297 if (l2Inst.subtype().equals(L2SubType.VLAN_POP)) {
298 popVlan = true;
299 } else {
300 log.warn("Filtering objective can have only VLAN_POP instruction.");
301 return;
302 }
303 } else {
304 log.warn("Filtering objective should have one instruction.");
Pier Ventre42287df2016-11-09 14:17:26 -0800305 return;
306 }
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700307
308 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
309 for (Criterion criterion : filteringObjective.conditions()) {
310 switch (criterion.type()) {
311 case ETH_DST:
312 case ETH_DST_MASKED:
313 ethCriterion = (EthCriterion) criterion;
314 break;
315 case VLAN_VID:
316 if (innervidCriterion == null) {
317 innervidCriterion = (VlanIdCriterion) criterion;
318 } else {
319 outerVidCriterion = innervidCriterion;
320 innervidCriterion = (VlanIdCriterion) criterion;
321 }
322 break;
323 default:
324 log.warn("Unsupported filter {}", criterion);
325 fail(filteringObjective, ObjectiveError.UNSUPPORTED);
326 return;
327 }
328 }
329
330 if (innervidCriterion == null || outerVidCriterion == null) {
331 log.warn("filtering objective should have two vidCriterion.");
332 return;
333 }
334
335 if (ethCriterion == null || ethCriterion.mac().equals(NONE)) {
336 // NOTE: it is possible that a filtering objective only has vidCriterion
337 log.warn("filtering objective missing dstMac, cannot program TMAC table");
338 return;
339 } else {
340 MacAddress unicastMac = readEthDstFromTreatment(filteringObjective.meta());
341 List<List<FlowRule>> allStages = processEthDstFilter(portCriterion, ethCriterion, innervidCriterion,
342 innervidCriterion.vlanId(), unicastMac,
343 applicationId);
344 for (List<FlowRule> flowRules : allStages) {
345 log.trace("Starting a new flow rule stage for TMAC table flow");
346 ops.newStage();
347
348 for (FlowRule flowRule : flowRules) {
349 log.trace("{} flow rules in TMAC table: {} for dev: {}",
350 (install) ? "adding" : "removing", flowRules, deviceId);
351 if (install) {
352 ops = ops.add(flowRule);
353 } else {
354 // NOTE: Only remove TMAC flow when there is no more enabled port within the
355 // same VLAN on this device if TMAC doesn't support matching on in_port.
356 if (matchInPortTmacTable()
357 || (filteringObjective.meta() != null
358 && filteringObjective.meta().clearedDeferred())) {
Andreas Pantelopoulos0eaa5162018-06-28 17:06:14 -0700359
360 // if metadata instruction not null and not removeDoubleTagged move on.
361 if ((filteringObjective.meta().writeMetadata() != null) && (!removeDoubleTagged)) {
362 log.info("Skipping removal of tmac rule for device {}", deviceId);
363 continue;
364 } else {
365 ops = ops.remove(flowRule);
366 }
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700367 } else {
368 log.debug("Abort TMAC flow removal on {}. Some other ports still share this TMAC flow");
369 }
370 }
371 }
372 }
373 }
374
375 List<FlowRule> rules;
376 rules = processDoubleVlanIdFilter(portCriterion, innervidCriterion,
377 outerVidCriterion, popVlan, applicationId);
378 for (FlowRule flowRule : rules) {
379 log.trace("{} flow rule in VLAN table: {} for dev: {}",
380 (install) ? "adding" : "removing", flowRule, deviceId);
Andreas Pantelopoulos0eaa5162018-06-28 17:06:14 -0700381 // if context is remove, table is vlan_1 and removeDoubleTagged is false, continue.
382 if (flowRule.table().equals(IndexTableId.of(VLAN_TABLE)) &&
383 !removeDoubleTagged && !install) {
384 log.info("Skipping removal of vlan table rule for now!");
385 continue;
386 }
Jonghwan Hyuna76bf032018-04-09 09:40:50 -0700387 ops = install ? ops.add(flowRule) : ops.remove(flowRule);
388 }
389
390 // apply filtering flow rules
391 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
392 @Override
393 public void onSuccess(FlowRuleOperations ops) {
394 log.debug("Applied {} filtering rules in device {}",
395 ops.stages().get(0).size(), deviceId);
396 pass(filteringObjective);
397 }
398
399 @Override
400 public void onError(FlowRuleOperations ops) {
401 log.info("Failed to apply all filtering rules in dev {}", deviceId);
402 fail(filteringObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
403 }
404 }));
405
406 }
407 /**
408 * Internal implementation of processDoubleVlanIdFilter.
409 *
410 * @param portCriterion port on device for which this filter is programmed
411 * @param innerVidCriterion inner vlan
412 * @param outerVidCriterion outer vlan
413 * @param popVlan true if outer vlan header needs to be removed
414 * @param applicationId for application programming this filter
415 * @return flow rules for port-vlan filters
416 */
417 private List<FlowRule> processDoubleVlanIdFilter(PortCriterion portCriterion,
418 VlanIdCriterion innerVidCriterion,
419 VlanIdCriterion outerVidCriterion,
420 boolean popVlan,
421 ApplicationId applicationId) {
422 TrafficSelector.Builder outerSelector = DefaultTrafficSelector.builder();
423 TrafficTreatment.Builder outerTreatment = DefaultTrafficTreatment.builder();
424 TrafficSelector.Builder innerSelector = DefaultTrafficSelector.builder();
425 TrafficTreatment.Builder innerTreatment = DefaultTrafficTreatment.builder();
426
427 VlanId outerVlanId = outerVidCriterion.vlanId();
428 VlanId innerVlanId = innerVidCriterion.vlanId();
429 PortNumber portNumber = portCriterion.port();
430 // Check arguments
431 if (PortNumber.ALL.equals(portNumber)
432 || outerVlanId.equals(VlanId.NONE)
433 || innerVlanId.equals(VlanId.NONE)) {
434 log.warn("Incomplete Filtering Objective. " +
435 "VLAN Table cannot be programmed for {}", deviceId);
436 return ImmutableList.of();
437 } else {
438 outerSelector.matchInPort(portNumber);
439 innerSelector.matchInPort(portNumber);
440 outerTreatment.transition(VLAN_1_TABLE);
441 innerTreatment.transition(TMAC_TABLE);
442
443 if (requireVlanExtensions()) {
444 OfdpaMatchVlanVid ofdpaOuterMatchVlanVid = new OfdpaMatchVlanVid(outerVlanId);
445 outerSelector.extension(ofdpaOuterMatchVlanVid, deviceId);
446 OfdpaMatchVlanVid ofdpaInnerMatchVlanVid = new OfdpaMatchVlanVid(innerVlanId);
447 innerSelector.extension(ofdpaInnerMatchVlanVid, deviceId);
448 } else {
449 outerSelector.matchVlanId(outerVlanId);
450 innerSelector.matchVlanId(innerVlanId);
451 }
452
453 innerSelector.extension(new Ofdpa3MatchOvid(outerVlanId), deviceId);
454 outerTreatment.extension(new Ofdpa3SetOvid(outerVlanId), deviceId);
455 if (popVlan) {
456 outerTreatment.popVlan();
457 }
458 }
459 FlowRule outerRule = DefaultFlowRule.builder()
460 .forDevice(deviceId)
461 .withSelector(outerSelector.build())
462 .withTreatment(outerTreatment.build())
463 .withPriority(DEFAULT_PRIORITY)
464 .fromApp(applicationId)
465 .makePermanent()
466 .forTable(VLAN_TABLE)
467 .build();
468 FlowRule innerRule = DefaultFlowRule.builder()
469 .forDevice(deviceId)
470 .withSelector(innerSelector.build())
471 .withTreatment(innerTreatment.build())
472 .withPriority(DEFAULT_PRIORITY)
473 .fromApp(applicationId)
474 .makePermanent()
475 .forTable(VLAN_1_TABLE)
476 .build();
477
478 return ImmutableList.of(outerRule, innerRule);
479 }
480
481 /**
482 * Determines if the filtering objective will be used for double-tagged packets.
483 *
484 * @param fob Filtering objective
485 * @return True if the objective was created for double-tagged packets, false otherwise.
486 */
487 private boolean isDoubleTagged(FilteringObjective fob) {
488 return fob.meta() != null &&
489 fob.meta().allInstructions().stream().anyMatch(inst -> inst.type() == L2MODIFICATION
490 && ((L2ModificationInstruction) inst).subtype() == L2SubType.VLAN_POP) &&
491 fob.conditions().stream().filter(criterion -> criterion.type() == VLAN_VID).count() == 2;
Pier Ventre42287df2016-11-09 14:17:26 -0800492 }
493
494 /**
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700495 * Determines if the filtering objective will be used for a pseudowire.
496 *
497 * @param filteringObjective
498 * @return True if objective was created for a pseudowire, false otherwise.
499 */
500 private boolean isPseudowire(FilteringObjective filteringObjective) {
501
502
503 if (filteringObjective.meta() != null) {
504
505 TrafficTreatment treatment = filteringObjective.meta();
506 for (Instruction instr : treatment.immediate()) {
507 if (instr.type().equals(Instruction.Type.L2MODIFICATION)) {
508
509 L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr;
510 if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) {
511 return true;
512 }
513 }
514 }
515 }
516
517 return false;
518 }
519
520 /**
Pier Ventre42287df2016-11-09 14:17:26 -0800521 * Method to process the pw related filtering objectives.
522 *
523 * @param portCriterion the in port match
524 * @param innerVlanIdCriterion the inner vlan match
525 * @param outerVlanIdCriterion the outer vlan match
526 * @param tunnelId the tunnel id
527 * @param applicationId the application id
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700528 * @param egressVlan the vlan to modify, was passed in metadata
Pier Ventre42287df2016-11-09 14:17:26 -0800529 * @return a list of flow rules to install
530 */
531 private List<FlowRule> processPwFilter(PortCriterion portCriterion,
Yi Tsengef19de12017-04-24 11:33:05 -0700532 VlanIdCriterion innerVlanIdCriterion,
533 VlanIdCriterion outerVlanIdCriterion,
534 long tunnelId,
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700535 ApplicationId applicationId,
536 VlanId egressVlan) {
537
Pier Ventre42287df2016-11-09 14:17:26 -0800538 FlowRule vlan1FlowRule;
539 int mplsLogicalPort = ((int) portCriterion.port().toLong());
540 // We have to match on the inner vlan and outer vlan at the same time.
541 // Ofdpa supports this through the OVID meta-data type.
Pier Ventre42287df2016-11-09 14:17:26 -0800542
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700543 ImmutableList<FlowRule> toReturn;
544
545 // pseudowire configured with double tagged vlans
546 if (!(innerVlanIdCriterion.vlanId().equals(VlanId.NONE))
547 && !(outerVlanIdCriterion.vlanId().equals(VlanId.NONE))) {
548
549 log.info("Installing filter objective for double tagged CE for tunnel {}", tunnelId);
550
551 TrafficSelector.Builder vlan1Selector = DefaultTrafficSelector.builder()
552 .matchInPort(portCriterion.port())
553 .matchVlanId(innerVlanIdCriterion.vlanId())
554 .extension(new Ofdpa3MatchOvid(outerVlanIdCriterion.vlanId()), deviceId);
555 // TODO understand for the future how to manage the vlan rewrite.
556 TrafficTreatment.Builder vlan1Treatment = DefaultTrafficTreatment.builder()
557 .pushVlan()
558 .setVlanId(egressVlan)
559 .extension(new Ofdpa3SetMplsType(VPWS), deviceId)
560 .extension(new Ofdpa3SetMplsL2Port(mplsLogicalPort), deviceId)
561 .setTunnelId(tunnelId)
562 .transition(MPLS_L2_PORT_FLOW_TABLE);
563 vlan1FlowRule = DefaultFlowRule.builder()
564 .forDevice(deviceId)
565 .withSelector(vlan1Selector.build())
566 .withTreatment(vlan1Treatment.build())
567 .withPriority(DEFAULT_PRIORITY)
568 .fromApp(applicationId)
569 .makePermanent()
570 .forTable(VLAN_1_TABLE)
571 .build();
572 // Finally we create the flow rule for the vlan table.
573 FlowRule vlanFlowRule;
574 // We have to match on the outer vlan.
575 TrafficSelector.Builder vlanSelector = DefaultTrafficSelector.builder()
576 .matchInPort(portCriterion.port())
577 .matchVlanId(outerVlanIdCriterion.vlanId());
578 // TODO understand for the future how to manage the vlan rewrite.
579 TrafficTreatment.Builder vlanTreatment = DefaultTrafficTreatment.builder()
580 .popVlan()
581 .extension(new Ofdpa3SetOvid(outerVlanIdCriterion.vlanId()), deviceId)
582 .transition(VLAN_1_TABLE);
583 vlanFlowRule = DefaultFlowRule.builder()
584 .forDevice(deviceId)
585 .withSelector(vlanSelector.build())
586 .withTreatment(vlanTreatment.build())
587 .withPriority(DEFAULT_PRIORITY)
588 .fromApp(applicationId)
589 .makePermanent()
590 .forTable(VLAN_TABLE)
591 .build();
592
593 return ImmutableList.of(vlan1FlowRule, vlanFlowRule);
594 } else if (!(innerVlanIdCriterion.vlanId().equals(VlanId.NONE))
595 && (outerVlanIdCriterion.vlanId().equals(VlanId.NONE))) {
596
597 log.info("Installing filter objective for single tagged CE for tunnel {}", tunnelId);
598
599 TrafficSelector.Builder singleVlanSelector = DefaultTrafficSelector.builder()
600 .matchInPort(portCriterion.port())
601 .matchVlanId(innerVlanIdCriterion.vlanId());
602
603 TrafficTreatment.Builder singleVlanTreatment = DefaultTrafficTreatment.builder()
Charles Chan636906e2018-07-13 18:08:33 -0700604 // FIXME PW VLAN translation is not supported on Dune
605 // Need to explore doing that in egress table later if there is a requirement
606 // .setVlanId(egressVlan)
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700607 .extension(new Ofdpa3SetMplsType(VPWS), deviceId)
608 .extension(new Ofdpa3SetMplsL2Port(mplsLogicalPort), deviceId)
609 .setTunnelId(tunnelId)
610 .transition(MPLS_L2_PORT_FLOW_TABLE);
611
612 vlan1FlowRule = DefaultFlowRule.builder()
613 .forDevice(deviceId)
614 .withSelector(singleVlanSelector.build())
615 .withTreatment(singleVlanTreatment.build())
616 .withPriority(DEFAULT_PRIORITY)
617 .fromApp(applicationId)
618 .makePermanent()
619 .forTable(VLAN_TABLE)
620 .build();
621
622 return ImmutableList.of(vlan1FlowRule);
623 } else if ((innerVlanIdCriterion.vlanId().equals(VlanId.NONE))
624 && (outerVlanIdCriterion.vlanId().equals(VlanId.NONE))) {
625
626 TrafficSelector.Builder singleVlanSelector = DefaultTrafficSelector.builder()
627 .matchInPort(portCriterion.port())
628 .matchVlanId(innerVlanIdCriterion.vlanId());
629
630 TrafficTreatment.Builder singleVlanTreatment = DefaultTrafficTreatment.builder()
631 .extension(new Ofdpa3SetMplsType(VPWS), deviceId)
632 .extension(new Ofdpa3SetMplsL2Port(mplsLogicalPort), deviceId)
633 .setTunnelId(tunnelId)
634 .transition(MPLS_L2_PORT_FLOW_TABLE);
635
636 vlan1FlowRule = DefaultFlowRule.builder()
637 .forDevice(deviceId)
638 .withSelector(singleVlanSelector.build())
639 .withTreatment(singleVlanTreatment.build())
640 .withPriority(DEFAULT_PRIORITY)
641 .fromApp(applicationId)
642 .makePermanent()
643 .forTable(VLAN_TABLE)
644 .build();
645
646 return ImmutableList.of(vlan1FlowRule);
647 } else {
648 // failure...
649 return Collections.emptyList();
650 }
Pier Ventre42287df2016-11-09 14:17:26 -0800651 }
652
653 @Override
Charles Chanf9e98652016-09-07 16:54:23 -0700654 protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
Saurav Dasa4020382018-02-14 14:14:54 -0800655 // if its not-bos, we go to MPLS_TYPE_TABLE regardless of whether we pop or swap
656 // if it is bos, we go to MPLS_TYPE_TABLE only if we swap
657 if (isNotMplsBos(fwd.selector())
658 || (isMplsBos(fwd.selector()) && !isMplsPop(fwd))) {
Pier Ventre140a8942016-11-02 07:26:38 -0700659 return processEthTypeSpecificInternal(fwd, true, MPLS_TYPE_TABLE);
660 }
Saurav Dasa4020382018-02-14 14:14:54 -0800661 // if it is bos, and we pop, we go to MPLS_L3_TYPE_TABLE
Pier Ventre140a8942016-11-02 07:26:38 -0700662 return processEthTypeSpecificInternal(fwd, true, MPLS_L3_TYPE_TABLE);
Charles Chanf9e98652016-09-07 16:54:23 -0700663 }
Pier Ventre42287df2016-11-09 14:17:26 -0800664
665 @Override
666 protected Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
667 // We use the tunnel id to identify pw related flows.
Pier Ventre70d53ba2016-11-17 22:26:29 -0800668 // Looking for the fwd objective of the initiation.
Pier Ventre42287df2016-11-09 14:17:26 -0800669 TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) fwd.selector()
670 .getCriterion(TUNNEL_ID);
671 if (tunnelIdCriterion != null) {
Pier Ventre70d53ba2016-11-17 22:26:29 -0800672 return processInitPwVersatile(fwd);
673 }
674 // Looking for the fwd objective of the termination.
675 ModTunnelIdInstruction modTunnelIdInstruction = getModTunnelIdInstruction(fwd.treatment());
676 OutputInstruction outputInstruction = getOutputInstruction(fwd.treatment());
677 if (modTunnelIdInstruction != null && outputInstruction != null) {
678 return processTermPwVersatile(fwd, modTunnelIdInstruction, outputInstruction);
Pier Ventre42287df2016-11-09 14:17:26 -0800679 }
680 // If it is not a pseudo wire flow we fall back
681 // to the OFDPA 2.0 pipeline.
682 return super.processVersatile(fwd);
683 }
684
Pier Ventre70d53ba2016-11-17 22:26:29 -0800685 private Collection<FlowRule> processTermPwVersatile(ForwardingObjective forwardingObjective,
686 ModTunnelIdInstruction modTunnelIdInstruction,
687 OutputInstruction outputInstruction) {
688 TrafficTreatment.Builder flowTreatment;
689 TrafficSelector.Builder flowSelector;
690 // We divide the mpls actions from the tunnel actions. We need
691 // this to order the actions in the final treatment.
692 TrafficTreatment.Builder mplsTreatment = DefaultTrafficTreatment.builder();
693 createMplsTreatment(forwardingObjective.treatment(), mplsTreatment);
694 // The match of the forwarding objective is ready to go.
695 flowSelector = DefaultTrafficSelector.builder(forwardingObjective.selector());
696 // We verify the tunnel id and mpls port are correct.
697 long tunnelId = MPLS_TUNNEL_ID_BASE | modTunnelIdInstruction.tunnelId();
698 if (tunnelId > MPLS_TUNNEL_ID_MAX) {
699 log.error("Pw Versatile Forwarding Objective must include tunnel id < {}",
700 MPLS_TUNNEL_ID_MAX);
701 fail(forwardingObjective, ObjectiveError.BADPARAMS);
702 return Collections.emptySet();
703 }
704 // 0x0002XXXX is NNI interface.
705 int mplsLogicalPort = ((int) outputInstruction.port().toLong()) | MPLS_NNI_PORT_BASE;
706 if (mplsLogicalPort > MPLS_NNI_PORT_MAX) {
707 log.error("Pw Versatile Forwarding Objective invalid logical port {}",
708 mplsLogicalPort);
709 fail(forwardingObjective, ObjectiveError.BADPARAMS);
710 return Collections.emptySet();
711 }
712 // Next id cannot be null.
713 if (forwardingObjective.nextId() == null) {
714 log.error("Pw Versatile Forwarding Objective must contain nextId ",
715 forwardingObjective.nextId());
716 fail(forwardingObjective, ObjectiveError.BADPARAMS);
717 return Collections.emptySet();
718 }
719 // We retrieve the l2 interface group and point the mpls
720 // flow to this.
721 NextGroup next = getGroupForNextObjective(forwardingObjective.nextId());
722 if (next == null) {
723 log.warn("next-id:{} not found in dev:{}", forwardingObjective.nextId(), deviceId);
724 fail(forwardingObjective, ObjectiveError.GROUPMISSING);
725 return Collections.emptySet();
726 }
727 List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
728 Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
729 if (group == null) {
730 log.warn("Group with key:{} for next-id:{} not found in dev:{}",
731 gkeys.get(0).peekFirst(), forwardingObjective.nextId(), deviceId);
732 fail(forwardingObjective, ObjectiveError.GROUPMISSING);
733 return Collections.emptySet();
734 }
735 // We prepare the treatment for the mpls flow table.
736 // The order of the actions has to be strictly this
737 // according to the OFDPA 2.0 specification.
738 flowTreatment = DefaultTrafficTreatment.builder(mplsTreatment.build());
739 flowTreatment.extension(new Ofdpa3PopCw(), deviceId);
Pier Luigi3bfe32c2017-01-30 09:47:36 -0800740 // Even though the specification and the xml/json files
741 // specify is allowed, the switch rejects the flow. In the
742 // OFDPA 3.0 EA0 version was necessary
743 //flowTreatment.popVlan();
Pier Ventre70d53ba2016-11-17 22:26:29 -0800744 flowTreatment.extension(new Ofdpa3PopL2Header(), deviceId);
745 flowTreatment.setTunnelId(tunnelId);
746 flowTreatment.extension(new Ofdpa3SetMplsL2Port(mplsLogicalPort), deviceId);
747 flowTreatment.extension(new Ofdpa3SetMplsType(VPWS), deviceId);
748 flowTreatment.transition(MPLS_TYPE_TABLE);
749 flowTreatment.deferred().group(group.id());
750 // We prepare the flow rule for the mpls table.
751 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
752 .fromApp(forwardingObjective.appId())
753 .withPriority(forwardingObjective.priority())
754 .forDevice(deviceId)
755 .withSelector(flowSelector.build())
756 .withTreatment(flowTreatment.build())
757 .makePermanent()
758 .forTable(MPLS_TABLE_1);
759 return Collections.singletonList(ruleBuilder.build());
760 }
761
Pier Ventre42287df2016-11-09 14:17:26 -0800762 /**
763 * Helper method to process the pw forwarding objectives.
764 *
765 * @param forwardingObjective the fw objective to process
766 * @return a singleton list of flow rule
767 */
Pier Ventre70d53ba2016-11-17 22:26:29 -0800768 private Collection<FlowRule> processInitPwVersatile(ForwardingObjective forwardingObjective) {
Pier Ventre42287df2016-11-09 14:17:26 -0800769 // We retrieve the matching criteria for mpls l2 port.
770 TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) forwardingObjective.selector()
771 .getCriterion(TUNNEL_ID);
772 PortCriterion portCriterion = (PortCriterion) forwardingObjective.selector()
773 .getCriterion(IN_PORT);
774 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
775 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
776 int mplsLogicalPort;
777 long tunnelId;
778 // Mpls tunnel ids according to the OFDPA manual have to be
779 // in the range [2^17-1, 2^16].
780 tunnelId = MPLS_TUNNEL_ID_BASE | tunnelIdCriterion.tunnelId();
781 if (tunnelId > MPLS_TUNNEL_ID_MAX) {
782 log.error("Pw Versatile Forwarding Objective must include tunnel id < {}",
783 MPLS_TUNNEL_ID_MAX);
784 fail(forwardingObjective, ObjectiveError.BADPARAMS);
785 return Collections.emptySet();
786 }
787 // Port has not been null.
788 if (portCriterion == null) {
789 log.error("Pw Versatile Forwarding Objective must include port");
790 fail(forwardingObjective, ObjectiveError.BADPARAMS);
791 return Collections.emptySet();
792 }
793 // 0x0000XXXX is UNI interface.
Pier Ventre70d53ba2016-11-17 22:26:29 -0800794 if (portCriterion.port().toLong() > MPLS_UNI_PORT_MAX) {
Pier Ventre42287df2016-11-09 14:17:26 -0800795 log.error("Pw Versatile Forwarding Objective invalid logical port {}",
796 portCriterion.port().toLong());
797 fail(forwardingObjective, ObjectiveError.BADPARAMS);
798 return Collections.emptySet();
799 }
800 mplsLogicalPort = ((int) portCriterion.port().toLong());
801 if (forwardingObjective.nextId() == null) {
802 log.error("Pw Versatile Forwarding Objective must contain nextId ",
803 forwardingObjective.nextId());
804 fail(forwardingObjective, ObjectiveError.BADPARAMS);
805 return Collections.emptySet();
806 }
807 // We don't expect a treatment.
808 if (forwardingObjective.treatment() != null &&
809 !forwardingObjective.treatment().equals(DefaultTrafficTreatment.emptyTreatment())) {
810 log.error("Pw Versatile Forwarding Objective cannot contain a treatment ",
811 forwardingObjective.nextId());
812 fail(forwardingObjective, ObjectiveError.BADPARAMS);
813 return Collections.emptySet();
814 }
815 // We retrieve the l2 vpn group and point the mpls
816 // l2 port to this.
817 NextGroup next = getGroupForNextObjective(forwardingObjective.nextId());
818 if (next == null) {
819 log.warn("next-id:{} not found in dev:{}", forwardingObjective.nextId(), deviceId);
820 fail(forwardingObjective, ObjectiveError.GROUPMISSING);
821 return Collections.emptySet();
822 }
823 List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
824 Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
825 if (group == null) {
826 log.warn("Group with key:{} for next-id:{} not found in dev:{}",
827 gkeys.get(0).peekFirst(), forwardingObjective.nextId(), deviceId);
828 fail(forwardingObjective, ObjectiveError.GROUPMISSING);
829 return Collections.emptySet();
830 }
831 // We prepare the flow rule for the mpls l2 port table.
832 selector.matchTunnelId(tunnelId);
833 selector.extension(new Ofdpa3MatchMplsL2Port(mplsLogicalPort), deviceId);
834 // This should not be necessary but without we receive an error
835 treatment.extension(new Ofdpa3SetQosIndex(0), deviceId);
836 treatment.transition(MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE);
837 treatment.deferred().group(group.id());
838 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
839 .fromApp(forwardingObjective.appId())
840 .withPriority(MPLS_L2_PORT_PRIORITY)
841 .forDevice(deviceId)
842 .withSelector(selector.build())
843 .withTreatment(treatment.build())
844 .makePermanent()
845 .forTable(MPLS_L2_PORT_FLOW_TABLE);
846 return Collections.singletonList(ruleBuilder.build());
847 }
Pier Ventre70d53ba2016-11-17 22:26:29 -0800848
849 /**
850 * Utility function to get the mod tunnel id instruction
851 * if present.
852 *
853 * @param treatment the treatment to analyze
854 * @return the mod tunnel id instruction if present,
855 * otherwise null
856 */
857 private ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) {
Charles Chan3bb11702017-02-16 14:58:58 -0800858 if (treatment == null) {
859 return null;
860 }
861
Pier Ventre70d53ba2016-11-17 22:26:29 -0800862 L2ModificationInstruction l2ModificationInstruction;
863 for (Instruction instruction : treatment.allInstructions()) {
864 if (instruction.type() == L2MODIFICATION) {
865 l2ModificationInstruction = (L2ModificationInstruction) instruction;
866 if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) {
867 return (ModTunnelIdInstruction) l2ModificationInstruction;
868 }
869 }
870 }
871 return null;
872 }
873
874 /**
875 * Utility function to get the output instruction
876 * if present.
877 *
878 * @param treatment the treatment to analyze
879 * @return the output instruction if present,
880 * otherwise null
881 */
882 private OutputInstruction getOutputInstruction(TrafficTreatment treatment) {
Saurav Das018605f2017-02-18 14:05:44 -0800883 if (treatment == null) {
884 return null;
885 }
886
Pier Ventre70d53ba2016-11-17 22:26:29 -0800887 for (Instruction instruction : treatment.allInstructions()) {
888 if (instruction.type() == Instruction.Type.OUTPUT) {
889 return (OutputInstruction) instruction;
890 }
891 }
892 return null;
893 }
894
895 /**
896 * Helper method for dividing the tunnel instructions from the mpls
897 * instructions.
898 *
899 * @param treatment the treatment to analyze
900 * @param mplsTreatment the mpls treatment builder
901 */
902 private void createMplsTreatment(TrafficTreatment treatment,
903 TrafficTreatment.Builder mplsTreatment) {
904
905 for (Instruction ins : treatment.allInstructions()) {
906
907 if (ins.type() == Instruction.Type.L2MODIFICATION) {
908 L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
909 switch (l2ins.subtype()) {
910 // These instructions have to go in the mpls
911 // treatment.
912 case TUNNEL_ID:
913 break;
914 case DEC_MPLS_TTL:
915 case MPLS_POP:
916 mplsTreatment.add(ins);
917 break;
918 default:
919 log.warn("Driver does not handle this type of TrafficTreatment"
920 + " instruction in nextObjectives: {} - {}",
921 ins.type(), ins);
922 break;
923 }
924 } else if (ins.type() == Instruction.Type.OUTPUT) {
925 break;
926 } else if (ins.type() == Instruction.Type.L3MODIFICATION) {
927 // We support partially the l3 instructions.
928 L3ModificationInstruction l3ins = (L3ModificationInstruction) ins;
929 switch (l3ins.subtype()) {
930 case TTL_IN:
931 mplsTreatment.add(ins);
932 break;
933 default:
934 log.warn("Driver does not handle this type of TrafficTreatment"
935 + " instruction in nextObjectives: {} - {}",
936 ins.type(), ins);
937 }
938
939 } else {
940 log.warn("Driver does not handle this type of TrafficTreatment"
941 + " instruction in nextObjectives: {} - {}",
942 ins.type(), ins);
943 }
944 }
945 }
Charles Chanf9e98652016-09-07 16:54:23 -0700946}