blob: d427a6cb3ef7be51d9105aa7c2182c66e9db8634 [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.Lists;
Jonghwan Hyun800d9d02018-04-09 09:40:50 -070020import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
Charles Chanf9e98652016-09-07 16:54:23 -070022import org.onosproject.core.ApplicationId;
Yi Tsengfa394de2017-02-01 11:26:40 -080023import org.onosproject.core.GroupId;
Jonghwan Hyun800d9d02018-04-09 09:40:50 -070024import org.onosproject.driver.extensions.Ofdpa3AllowVlanTranslationType;
Pier Ventre42287df2016-11-09 14:17:26 -080025import org.onosproject.driver.extensions.Ofdpa3PushCw;
26import org.onosproject.driver.extensions.Ofdpa3PushL2Header;
Jonghwan Hyun800d9d02018-04-09 09:40:50 -070027import org.onosproject.driver.extensions.OfdpaSetAllowVlanTranslation;
28import org.onosproject.driver.extensions.OfdpaSetVlanVid;
Pier Ventre42287df2016-11-09 14:17:26 -080029import org.onosproject.net.flow.DefaultTrafficTreatment;
Charles Chanf9e98652016-09-07 16:54:23 -070030import org.onosproject.net.flow.TrafficSelector;
31import org.onosproject.net.flow.TrafficTreatment;
Pier Ventre42287df2016-11-09 14:17:26 -080032import org.onosproject.net.flow.instructions.Instruction;
Jonghwan Hyun800d9d02018-04-09 09:40:50 -070033import org.onosproject.net.flow.instructions.Instructions;
Pier Ventre42287df2016-11-09 14:17:26 -080034import org.onosproject.net.flow.instructions.L2ModificationInstruction;
35import org.onosproject.net.flow.instructions.L3ModificationInstruction;
36import org.onosproject.net.flowobjective.NextObjective;
37import org.onosproject.net.flowobjective.ObjectiveError;
38import org.onosproject.net.group.DefaultGroupBucket;
39import org.onosproject.net.group.DefaultGroupDescription;
40import org.onosproject.net.group.DefaultGroupKey;
41import org.onosproject.net.group.GroupBucket;
42import org.onosproject.net.group.GroupBuckets;
43import org.onosproject.net.group.GroupDescription;
44import org.onosproject.net.group.GroupKey;
45import org.slf4j.Logger;
46
47import java.util.ArrayDeque;
48import java.util.Collections;
49import java.util.Deque;
50import java.util.List;
51
Yi Tsengef19de12017-04-24 11:33:05 -070052import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
Pier Ventre42287df2016-11-09 14:17:26 -080053import static org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType.TTL_OUT;
54import static org.onosproject.net.group.GroupDescription.Type.INDIRECT;
55import static org.slf4j.LoggerFactory.getLogger;
Charles Chanf9e98652016-09-07 16:54:23 -070056
57/**
58 * Group handler for OFDPA2 pipeline.
59 */
60public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
Pier Ventre42287df2016-11-09 14:17:26 -080061
62 private static final int PW_INTERNAL_VLAN = 4094;
63 private static final int MAX_DEPTH_UNPROTECTED_PW = 3;
64
65 private final Logger log = getLogger(getClass());
66
Charles Chanf9e98652016-09-07 16:54:23 -070067 @Override
68 protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
69 ApplicationId appId, boolean mpls,
70 TrafficSelector meta) {
Jonghwan Hyun800d9d02018-04-09 09:40:50 -070071 return isUnfiltered(treatment, meta) ?
72 createUnfilteredL2L3Chain(treatment, nextId, appId, false) :
73 createL2L3ChainInternal(treatment, nextId, appId, mpls, meta, false);
Charles Chanf9e98652016-09-07 16:54:23 -070074 }
Pier Ventre42287df2016-11-09 14:17:26 -080075
76 @Override
77 protected void processPwNextObjective(NextObjective nextObjective) {
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -080078
79 log.info("Started deploying nextObjective id={} for pseudowire", nextObjective.id());
80
Pier Ventre42287df2016-11-09 14:17:26 -080081 TrafficTreatment treatment = nextObjective.next().iterator().next();
82 Deque<GroupKey> gkeyChain = new ArrayDeque<>();
83 GroupChainElem groupChainElem;
84 GroupKey groupKey;
85 GroupDescription groupDescription;
86 // Now we separate the mpls actions from the l2/l3 actions
87 TrafficTreatment.Builder l2L3Treatment = DefaultTrafficTreatment.builder();
88 TrafficTreatment.Builder mplsTreatment = DefaultTrafficTreatment.builder();
89 createL2L3AndMplsTreatments(treatment, l2L3Treatment, mplsTreatment);
90 // We create the chain from mpls intf group to
91 // l2 intf group.
92 GroupInfo groupInfo = createL2L3ChainInternal(
93 l2L3Treatment.build(),
94 nextObjective.id(),
95 nextObjective.appId(),
96 true,
97 nextObjective.meta(),
98 false
99 );
100 if (groupInfo == null) {
101 log.error("Could not process nextObj={} in dev:{}", nextObjective.id(), deviceId);
pier9469f3e2019-04-17 17:05:08 +0200102 OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED);
Pier Ventre42287df2016-11-09 14:17:26 -0800103 return;
104 }
105 // We update the chain with the last two groups;
Yi Tsengef19de12017-04-24 11:33:05 -0700106 gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
107 gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
Pier Ventre42287df2016-11-09 14:17:26 -0800108 // We retrieve also all mpls instructions.
109 List<List<Instruction>> mplsInstructionSets = Lists.newArrayList();
110 List<Instruction> mplsInstructionSet = Lists.newArrayList();
111 L3ModificationInstruction l3Ins;
112 for (Instruction ins : treatment.allInstructions()) {
113 // Each mpls instruction set is delimited by a
114 // copy ttl outward action.
115 mplsInstructionSet.add(ins);
116 if (ins.type() == Instruction.Type.L3MODIFICATION) {
117 l3Ins = (L3ModificationInstruction) ins;
118 if (l3Ins.subtype() == TTL_OUT) {
119 mplsInstructionSets.add(mplsInstructionSet);
120 mplsInstructionSet = Lists.newArrayList();
121 }
Pier Ventre42287df2016-11-09 14:17:26 -0800122 }
123 }
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800124
Pier Ventre42287df2016-11-09 14:17:26 -0800125 if (mplsInstructionSets.size() > MAX_DEPTH_UNPROTECTED_PW) {
126 log.error("Next Objective for pseudo wire should have at "
127 + "most {} mpls instruction sets. Next Objective Id:{}",
128 MAX_DEPTH_UNPROTECTED_PW, nextObjective.id());
pier9469f3e2019-04-17 17:05:08 +0200129 OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.BADPARAMS);
Pier Ventre42287df2016-11-09 14:17:26 -0800130 return;
131 }
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800132
133 log.debug("Size of mpls instructions is {}.", mplsInstructionSets.size());
134 log.debug("mpls instructions sets are {}.", mplsInstructionSets);
135
Yi Tsengef19de12017-04-24 11:33:05 -0700136 int nextGid = groupInfo.nextGroupDesc().givenGroupId();
Pier Ventre42287df2016-11-09 14:17:26 -0800137 int index;
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800138
Pier Ventre42287df2016-11-09 14:17:26 -0800139 // We create the mpls tunnel label groups.
140 // In this case we need to use also the
141 // tunnel label group 2;
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800142 // this is for inter-co pws
Pier Ventre42287df2016-11-09 14:17:26 -0800143 if (mplsInstructionSets.size() == MAX_DEPTH_UNPROTECTED_PW) {
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800144
145 log.debug("Creating inter-co pw mpls chains with nextid {}", nextObjective.id());
146
Pier Ventre42287df2016-11-09 14:17:26 -0800147 // We deal with the label 2 group.
148 index = getNextAvailableIndex();
149 groupDescription = createMplsTunnelLabelGroup(
150 nextGid,
Yi Tsengef19de12017-04-24 11:33:05 -0700151 OfdpaMplsGroupSubType.MPLS_TUNNEL_LABEL_2,
Pier Ventre42287df2016-11-09 14:17:26 -0800152 index,
153 mplsInstructionSets.get(2),
154 nextObjective.appId()
155 );
156 groupKey = new DefaultGroupKey(
157 Ofdpa2Pipeline.appKryo.serialize(index)
158 );
159 // We update the chain.
Yi Tsengef19de12017-04-24 11:33:05 -0700160 groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
Pier Ventre42287df2016-11-09 14:17:26 -0800161 updatePendingGroups(
Yi Tsengef19de12017-04-24 11:33:05 -0700162 groupInfo.nextGroupDesc().appCookie(),
Pier Ventre42287df2016-11-09 14:17:26 -0800163 groupChainElem
164 );
165 gkeyChain.addFirst(groupKey);
166 // We have to create tunnel label group and
167 // l2 vpn group before to send the inner most
168 // group. We update the nextGid.
169 nextGid = groupDescription.givenGroupId();
Yi Tsengef19de12017-04-24 11:33:05 -0700170 groupInfo = new GroupInfo(groupInfo.innerMostGroupDesc(), groupDescription);
Pier Ventre42287df2016-11-09 14:17:26 -0800171
172 log.debug("Trying Label 2 Group: device:{} gid:{} gkey:{} nextId:{}",
173 deviceId, Integer.toHexString(nextGid),
174 groupKey, nextObjective.id());
175 }
Pier Ventre42287df2016-11-09 14:17:26 -0800176
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800177 // if treatment has 2 mpls labels, then this is a pseudowire from leaf to another leaf
178 // inside a single co
179 if (mplsInstructionSets.size() == 2) {
Pier Ventre42287df2016-11-09 14:17:26 -0800180
Andreas Pantelopoulos20474e02017-12-20 18:04:27 -0800181 log.debug("Creating leaf-leaf pw mpls chains with nextid {}", nextObjective.id());
182 // We deal with the label 1 group.
183 index = getNextAvailableIndex();
184 groupDescription = createMplsTunnelLabelGroup(nextGid,
185 OfdpaMplsGroupSubType.MPLS_TUNNEL_LABEL_1,
186 index,
187 mplsInstructionSets.get(1),
188 nextObjective.appId());
189 groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
190 groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
191 updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
192 gkeyChain.addFirst(groupKey);
193 // We have to create the l2 vpn group before
194 // to send the inner most group.
195 nextGid = groupDescription.givenGroupId();
196 groupInfo = new GroupInfo(groupInfo.innerMostGroupDesc(), groupDescription);
197
198 log.debug("Trying Label 1 Group: device:{} gid:{} gkey:{} nextId:{}",
199 deviceId, Integer.toHexString(nextGid),
200 groupKey, nextObjective.id());
201 // Finally we create the l2 vpn group.
202 index = getNextAvailableIndex();
203 groupDescription = createMplsL2VpnGroup(nextGid, index,
204 mplsInstructionSets.get(0), nextObjective.appId());
205 groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
206 groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
207 updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
208 gkeyChain.addFirst(groupKey);
209 OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(Collections.singletonList(gkeyChain), nextObjective);
210 updatePendingNextObjective(groupKey, ofdpaGrp);
211
212 log.debug("Trying L2 Vpn Group: device:{} gid:{} gkey:{} nextId:{}", deviceId,
213 Integer.toHexString(nextGid), groupKey, nextObjective.id());
214 // Finally we send the innermost group.
215 log.debug("Sending innermost group {} in group chain on device {} ",
216 Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
217 groupService.addGroup(groupInfo.innerMostGroupDesc());
218 }
219
220 // this is a pseudowire from leaf to spine,
221 // only one label is used
222 if (mplsInstructionSets.size() == 1) {
223
224 log.debug("Creating leaf-spine pw mpls chains with nextid {}", nextObjective.id());
225
226 // Finally we create the l2 vpn group.
227 index = getNextAvailableIndex();
228 groupDescription = createMplsL2VpnGroup(nextGid, index, mplsInstructionSets.get(0),
229 nextObjective.appId());
230 groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
231 groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
232 updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
233 gkeyChain.addFirst(groupKey);
234 OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(Collections.singletonList(gkeyChain), nextObjective);
235 updatePendingNextObjective(groupKey, ofdpaGrp);
236
237 log.debug("Trying L2 Vpn Group: device:{} gid:{} gkey:{} nextId:{}",
238 deviceId, Integer.toHexString(nextGid), groupKey, nextObjective.id());
239 // Finally we send the innermost group.
240 log.debug("Sending innermost group {} in group chain on device {} ",
241 Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
242 groupService.addGroup(groupInfo.innerMostGroupDesc());
243 }
Pier Ventre42287df2016-11-09 14:17:26 -0800244 }
245
246 /**
247 * Helper method to create a mpls tunnel label group.
248 *
249 * @param nextGroupId the next group in the chain
250 * @param subtype the mpls tunnel label group subtype
251 * @param index the index of the group
252 * @param instructions the instructions to push
253 * @param applicationId the application id
254 * @return the group description
255 */
256 private GroupDescription createMplsTunnelLabelGroup(int nextGroupId,
Yi Tsengef19de12017-04-24 11:33:05 -0700257 OfdpaMplsGroupSubType subtype,
258 int index,
259 List<Instruction> instructions,
260 ApplicationId applicationId) {
Pier Ventre42287df2016-11-09 14:17:26 -0800261 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
262 // We add all the instructions.
263 instructions.forEach(treatment::add);
264 // We point the group to the next group.
Yi Tsengfa394de2017-02-01 11:26:40 -0800265 treatment.group(new GroupId(nextGroupId));
Pier Ventre42287df2016-11-09 14:17:26 -0800266 GroupBucket groupBucket = DefaultGroupBucket
267 .createIndirectGroupBucket(treatment.build());
268 // Finally we build the group description.
269 int groupId = makeMplsLabelGroupId(subtype, index);
270 GroupKey groupKey = new DefaultGroupKey(
271 Ofdpa2Pipeline.appKryo.serialize(index)
272 );
273 return new DefaultGroupDescription(
274 deviceId,
275 INDIRECT,
276 new GroupBuckets(Collections.singletonList(groupBucket)),
277 groupKey,
278 groupId,
279 applicationId
280 );
281 }
282
283 /**
284 * Helper method to create a mpls l2 vpn group.
285 *
286 * @param nextGroupId the next group in the chain
287 * @param index the index of the group
288 * @param instructions the instructions to push
289 * @param applicationId the application id
290 * @return the group description
291 */
292 private GroupDescription createMplsL2VpnGroup(int nextGroupId,
Yi Tsengef19de12017-04-24 11:33:05 -0700293 int index,
294 List<Instruction> instructions,
295 ApplicationId applicationId) {
Pier Ventre42287df2016-11-09 14:17:26 -0800296 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
297 // We add the extensions and the instructions.
298 treatment.extension(new Ofdpa3PushL2Header(), deviceId);
299 treatment.pushVlan();
300 instructions.forEach(treatment::add);
301 treatment.extension(new Ofdpa3PushCw(), deviceId);
302 // We point the group to the next group.
Yi Tsengfa394de2017-02-01 11:26:40 -0800303 treatment.group(new GroupId(nextGroupId));
Pier Ventre42287df2016-11-09 14:17:26 -0800304 GroupBucket groupBucket = DefaultGroupBucket
305 .createIndirectGroupBucket(treatment.build());
306 // Finally we build the group description.
Yi Tsengef19de12017-04-24 11:33:05 -0700307 int groupId = makeMplsLabelGroupId(OfdpaMplsGroupSubType.L2_VPN, index);
Pier Ventre42287df2016-11-09 14:17:26 -0800308 GroupKey groupKey = new DefaultGroupKey(
309 Ofdpa2Pipeline.appKryo.serialize(index)
310 );
311 return new DefaultGroupDescription(
312 deviceId,
313 INDIRECT,
314 new GroupBuckets(Collections.singletonList(groupBucket)),
315 groupKey,
316 groupId,
317 applicationId
318 );
319 }
320
321 /**
322 * Helper method for dividing the l2/l3 instructions from the mpls
323 * instructions.
324 *
325 * @param treatment the treatment to analyze
326 * @param l2L3Treatment the l2/l3 treatment builder
327 * @param mplsTreatment the mpls treatment builder
328 */
329 private void createL2L3AndMplsTreatments(TrafficTreatment treatment,
Yi Tsengef19de12017-04-24 11:33:05 -0700330 TrafficTreatment.Builder l2L3Treatment,
331 TrafficTreatment.Builder mplsTreatment) {
Pier Ventre42287df2016-11-09 14:17:26 -0800332
333 for (Instruction ins : treatment.allInstructions()) {
334
335 if (ins.type() == Instruction.Type.L2MODIFICATION) {
336 L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
337 switch (l2ins.subtype()) {
338 // These instructions have to go in the l2/l3 treatment.
339 case ETH_DST:
340 case ETH_SRC:
341 case VLAN_ID:
342 case VLAN_POP:
343 l2L3Treatment.add(ins);
344 break;
345 // These instructions have to go in the mpls treatment.
346 case MPLS_BOS:
347 case DEC_MPLS_TTL:
348 case MPLS_LABEL:
349 case MPLS_PUSH:
350 mplsTreatment.add(ins);
351 break;
352 default:
Saurav Dasa4020382018-02-14 14:14:54 -0800353 log.warn("Driver does not handle TrafficTreatment"
354 + " L2Mod {} for pw next-obj", l2ins.subtype());
Pier Ventre42287df2016-11-09 14:17:26 -0800355 break;
356 }
357 } else if (ins.type() == Instruction.Type.OUTPUT) {
358 // The output goes in the l2/l3 treatment.
359 l2L3Treatment.add(ins);
360 } else if (ins.type() == Instruction.Type.L3MODIFICATION) {
361 // We support partially the l3 instructions.
362 L3ModificationInstruction l3ins = (L3ModificationInstruction) ins;
363 switch (l3ins.subtype()) {
364 case TTL_OUT:
365 mplsTreatment.add(ins);
366 break;
367 default:
Saurav Dasa4020382018-02-14 14:14:54 -0800368 log.warn("Driver does not handle TrafficTreatment"
369 + " L3Mod for pw next-obj", l3ins.subtype());
Pier Ventre42287df2016-11-09 14:17:26 -0800370 }
371
372 } else {
373 log.warn("Driver does not handle this type of TrafficTreatment"
Saurav Dasa4020382018-02-14 14:14:54 -0800374 + " instruction for pw next-obj: {} - {}",
Pier Ventre42287df2016-11-09 14:17:26 -0800375 ins.type(), ins);
376 }
377 }
Pier Ventre42287df2016-11-09 14:17:26 -0800378 }
379 // TODO Introduce in the future an inner class to return two treatments
Jonghwan Hyun800d9d02018-04-09 09:40:50 -0700380
381 /**
382 * Internal implementation of createL2L3Chain for L2 unfiltered interface group.
383 *
384 * @param treatment that needs to be broken up to create the group chain
385 * @param nextId of the next objective that needs this group chain
386 * @param appId of the application that sent this next objective
387 * @param useSetVlanExtension use the setVlanVid extension that has is_present bit set to 0.
388 * @return GroupInfo containing the GroupDescription of the
389 * L2 Unfiltered Interface group(inner) and the GroupDescription of the (outer)
390 * L3Unicast group. May return null if there is an error in processing the chain.
391 */
392 private GroupInfo createUnfilteredL2L3Chain(TrafficTreatment treatment, int nextId,
393 ApplicationId appId, boolean useSetVlanExtension) {
394 // for the l2 unfiltered interface group, get port info
395 // for the l3 unicast group, get the src/dst mac, and vlan info
396 TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
397 TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
398 VlanId vlanId;
399 long portNum = 0;
400 MacAddress srcMac;
401 MacAddress dstMac;
402 for (Instruction ins : treatment.allInstructions()) {
403 if (ins.type() == Instruction.Type.L2MODIFICATION) {
404 L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
405 switch (l2ins.subtype()) {
406 case ETH_DST:
407 dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
408 outerTtb.setEthDst(dstMac);
409 break;
410 case ETH_SRC:
411 srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
412 outerTtb.setEthSrc(srcMac);
413 break;
414 case VLAN_ID:
415 vlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
416 if (useSetVlanExtension) {
417 OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(vlanId);
418 outerTtb.extension(ofdpaSetVlanVid, deviceId);
419 } else {
420 outerTtb.setVlanId(vlanId);
421 }
422 break;
423 default:
424 break;
425 }
426 } else if (ins.type() == Instruction.Type.OUTPUT) {
427 portNum = ((Instructions.OutputInstruction) ins).port().toLong();
428 innerTtb.add(ins);
429 } else {
430 log.debug("Driver does not handle this type of TrafficTreatment"
431 + " instruction in l2l3chain: {} - {}", ins.type(),
432 ins);
433 }
434 }
435
436 innerTtb.extension(new OfdpaSetAllowVlanTranslation(
437 Ofdpa3AllowVlanTranslationType.ALLOW), deviceId);
438
439 // assemble information for ofdpa l2 unfiltered interface group
440 int l2groupId = l2UnfilteredGroupId(portNum);
441 // a globally unique groupkey that is different for ports in the same device,
442 // but different for the same portnumber on different devices. Also different
443 // for the various group-types created out of the same next objective.
444 int l2gk = l2UnfilteredGroupKey(deviceId, portNum);
445 final GroupKey l2groupkey = new DefaultGroupKey(Ofdpa3Pipeline.appKryo.serialize(l2gk));
446
447 // assemble information for outer group (L3Unicast)
448 GroupDescription outerGrpDesc;
449 int l3unicastIndex = getNextAvailableIndex();
450 int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
451 final GroupKey l3groupkey = new DefaultGroupKey(
452 Ofdpa3Pipeline.appKryo.serialize(l3unicastIndex));
453 outerTtb.group(new GroupId(l2groupId));
454 // create the l3unicast group description to wait for the
455 // l2 unfiltered interface group to be processed
456 GroupBucket l3unicastGroupBucket =
457 DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
458 outerGrpDesc = new DefaultGroupDescription(
459 deviceId,
460 GroupDescription.Type.INDIRECT,
461 new GroupBuckets(Collections.singletonList(l3unicastGroupBucket)),
462 l3groupkey,
463 l3groupId,
464 appId);
465 log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}",
466 deviceId, Integer.toHexString(l3groupId),
467 l3groupkey, nextId);
468
469 // store l2groupkey with the groupChainElem for the outer-group that depends on it
470 GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1, false, deviceId);
471 updatePendingGroups(l2groupkey, gce);
472
473 // create group description for the inner l2 unfiltered interface group
474 GroupBucket l2InterfaceGroupBucket =
475 DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
476 GroupDescription l2groupDescription =
477 new DefaultGroupDescription(deviceId,
478 GroupDescription.Type.INDIRECT,
479 new GroupBuckets(Collections.singletonList(l2InterfaceGroupBucket)),
480 l2groupkey,
481 l2groupId,
482 appId);
483 log.debug("Trying L2Unfiltered: device:{} gid:{} gkey:{} nextId:{}",
484 deviceId, Integer.toHexString(l2groupId), l2groupkey, nextId);
485 return new GroupInfo(l2groupDescription, outerGrpDesc);
486 }
487
Charles Chanf9e98652016-09-07 16:54:23 -0700488}