[CORD-1108] Refactoring OFDPA Group Handler

Create package "ofdpa" under pipeline package
Move helper functions and classes to OfdpaGroupHandlerUtility

Change-Id: I47e42f2c8afc9088ed684cd6a087233a82c452f6
This commit is contained in:
Yi Tseng 2017-04-24 11:33:05 -07:00 committed by Andrea Campanella
parent 02f8d2efd6
commit ef19de1e84
13 changed files with 943 additions and 796 deletions

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
@ -43,8 +43,7 @@ import java.util.Collections;
import java.util.Deque;
import java.util.List;
import static org.onosproject.driver.pipeline.Ofdpa2GroupHandler.OfdpaMplsGroupSubType.MPLS_ECMP;
import static org.onosproject.driver.pipeline.Ofdpa2Pipeline.isNotMplsBos;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
@ -55,8 +54,8 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
@Override
protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
ApplicationId appId, boolean mpls,
TrafficSelector meta) {
ApplicationId appId, boolean mpls,
TrafficSelector meta) {
// for the l2interface group, get vlan and port info
// for the outer group, get the src/dst mac, and vlan info
TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
@ -189,7 +188,10 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
}
// store l2groupkey with the groupChainElem for the outer-group that depends on it
GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1, false);
GroupChainElem gce = new GroupChainElem(outerGrpDesc,
1,
false,
deviceId);
updatePendingGroups(l2groupkey, gce);
// create group description for the inner l2interfacegroup
@ -210,11 +212,6 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
return new GroupInfo(l2groupDescription, outerGrpDesc);
}
@Override
public boolean verifyHashedNextObjective(NextObjective nextObjective) {
return true;
}
/**
* In OFDPA2 we do not support the MPLS-ECMP, while we do in
* CPQD implementation.
@ -227,7 +224,7 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
// the transport of a VPWS. The necessary info are contained in the
// meta selector. In particular we are looking for the case of BoS==False;
TrafficSelector metaSelector = nextObjective.meta();
if (metaSelector != null && isNotMplsBos(metaSelector)) {
if (metaSelector != null && Ofdpa2Pipeline.isNotMplsBos(metaSelector)) {
// storage for all group keys in the chain of groups created
List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
List<GroupInfo> unsentGroups = new ArrayList<>();
@ -237,13 +234,13 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
for (GroupInfo gi : unsentGroups) {
// create ECMP bucket to point to the outer group
TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
ttb.group(new GroupId(gi.getNextGroupDesc().givenGroupId()));
ttb.group(new GroupId(gi.nextGroupDesc().givenGroupId()));
GroupBucket sbucket = DefaultGroupBucket
.createSelectGroupBucket(ttb.build());
mplsEcmpGroupBuckets.add(sbucket);
}
int mplsEcmpIndex = getNextAvailableIndex();
int mplsEcmpGroupId = makeMplsForwardingGroupId(MPLS_ECMP, mplsEcmpIndex);
int mplsEcmpGroupId = makeMplsForwardingGroupId(OfdpaMplsGroupSubType.MPLS_ECMP, mplsEcmpIndex);
GroupKey mplsEmpGroupKey = new DefaultGroupKey(
Ofdpa2Pipeline.appKryo.serialize(mplsEcmpIndex)
);
@ -257,7 +254,8 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
);
GroupChainElem mplsEcmpGce = new GroupChainElem(mplsEcmpGroupDesc,
mplsEcmpGroupBuckets.size(),
false);
false,
deviceId);
// create objects for local and distributed storage
allGroupKeys.forEach(gkeyChain -> gkeyChain.addFirst(mplsEmpGroupKey));
@ -274,9 +272,9 @@ public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
// finally we are ready to send the innermost groups
for (GroupInfo gi : unsentGroups) {
log.debug("Sending innermost group {} in group chain on device {} ",
Integer.toHexString(gi.getInnerMostGroupDesc().givenGroupId()), deviceId);
updatePendingGroups(gi.getNextGroupDesc().appCookie(), mplsEcmpGce);
groupService.addGroup(gi.getInnerMostGroupDesc());
Integer.toHexString(gi.innerMostGroupDesc().givenGroupId()), deviceId);
updatePendingGroups(gi.nextGroupDesc().appCookie(), mplsEcmpGce);
groupService.addGroup(gi.innerMostGroupDesc());
}
return;
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@ -71,7 +71,7 @@ import java.util.Objects;
import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
import static org.onlab.packet.MacAddress.BROADCAST;
import static org.onlab.packet.MacAddress.NONE;
import static org.onosproject.driver.pipeline.Ofdpa2GroupHandler.FOUR_BIT_MASK;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
import static org.slf4j.LoggerFactory.getLogger;
@ -193,8 +193,7 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
// NOTE: Emulating OFDPA behavior by popping off internal assigned
// VLAN before sending to controller
if (supportPuntGroup() && vidCriterion.vlanId() == VlanId.NONE) {
GroupKey groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(
POP_VLAN_PUNT_GROUP_ID | (Objects.hash(deviceId) & FOUR_BIT_MASK)));
GroupKey groupKey = popVlanPuntGroupKey();
Group group = groupService.getGroup(deviceId, groupKey);
if (group != null) {
rules.add(buildPuntTableRule(pnum, assignedVlan));
@ -416,7 +415,7 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
@Override
protected List<FlowRule> processEthDstOnlyFilter(EthCriterion ethCriterion,
ApplicationId applicationId) {
ApplicationId applicationId) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
@ -812,8 +811,7 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
* the copy of packet on the data plane is not affected by the pop vlan action.
*/
private void initPopVlanPuntGroup() {
GroupKey groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(
POP_VLAN_PUNT_GROUP_ID | (Objects.hash(deviceId) & FOUR_BIT_MASK)));
GroupKey groupKey = popVlanPuntGroupKey();
TrafficTreatment bucketTreatment = DefaultTrafficTreatment.builder()
.popVlan().punt().build();
GroupBucket bucket =
@ -830,4 +828,15 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
log.info("Initialized pop vlan punt group on {}", deviceId);
}
/**
* Generates group key for a static indirect group that pop vlan and punt to
* controller.
*
* @return the group key of the indirect table
*/
private GroupKey popVlanPuntGroupKey() {
int hash = POP_VLAN_PUNT_GROUP_ID | (Objects.hash(deviceId) & FOUR_BIT_MASK);
return new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(hash));
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import static org.slf4j.LoggerFactory.getLogger;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
@ -91,13 +91,13 @@ import static java.util.concurrent.Executors.newScheduledThreadPool;
import static org.onlab.packet.MacAddress.BROADCAST;
import static org.onlab.packet.MacAddress.NONE;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_BOS;
import static org.onosproject.net.flowobjective.NextObjective.Type.HASHED;
/**
* Driver for Broadcom's OF-DPA v2.0 TTP.
*
*/
public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeliner {
@ -142,12 +142,12 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
protected ApplicationId driverId;
protected DeviceService deviceService;
protected static KryoNamespace appKryo = new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(GroupKey.class)
.register(DefaultGroupKey.class)
.register(Ofdpa2GroupHandler.OfdpaNextGroup.class)
.register(ArrayDeque.class)
.build("Ofdpa2Pipeline");
.register(KryoNamespaces.API)
.register(GroupKey.class)
.register(DefaultGroupKey.class)
.register(OfdpaNextGroup.class)
.register(ArrayDeque.class)
.build("Ofdpa2Pipeline");
protected Ofdpa2GroupHandler groupHandler;
@ -493,9 +493,9 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
* @return list of FlowRule for port-vlan filters
*/
protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
VlanIdCriterion vidCriterion,
VlanId assignedVlan,
ApplicationId applicationId) {
VlanIdCriterion vidCriterion,
VlanId assignedVlan,
ApplicationId applicationId) {
List<FlowRule> rules = new ArrayList<>();
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
@ -706,7 +706,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
protected List<FlowRule> processEthDstOnlyFilter(EthCriterion ethCriterion,
ApplicationId applicationId) {
ApplicationId applicationId) {
ImmutableList.Builder<FlowRule> builder = ImmutableList.builder();
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
@ -741,7 +741,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
protected List<FlowRule> processMcastEthDstFilter(EthCriterion ethCriterion,
ApplicationId applicationId) {
ApplicationId applicationId) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import com.google.common.collect.Lists;
import org.onlab.packet.VlanId;
@ -44,7 +44,7 @@ import java.util.Collections;
import java.util.Deque;
import java.util.List;
import static org.onosproject.driver.pipeline.Ofdpa2GroupHandler.OfdpaMplsGroupSubType.*;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
import static org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType.TTL_OUT;
import static org.onosproject.net.group.GroupDescription.Type.INDIRECT;
import static org.slf4j.LoggerFactory.getLogger;
@ -93,8 +93,8 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
return;
}
// We update the chain with the last two groups;
gkeyChain.addFirst(groupInfo.getInnerMostGroupDesc().appCookie());
gkeyChain.addFirst(groupInfo.getNextGroupDesc().appCookie());
gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
// We retrieve also all mpls instructions.
List<List<Instruction>> mplsInstructionSets = Lists.newArrayList();
List<Instruction> mplsInstructionSet = Lists.newArrayList();
@ -119,7 +119,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.BADPARAMS);
return;
}
int nextGid = groupInfo.getNextGroupDesc().givenGroupId();
int nextGid = groupInfo.nextGroupDesc().givenGroupId();
int index;
// We create the mpls tunnel label groups.
// In this case we need to use also the
@ -129,7 +129,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
index = getNextAvailableIndex();
groupDescription = createMplsTunnelLabelGroup(
nextGid,
MPLS_TUNNEL_LABEL_2,
OfdpaMplsGroupSubType.MPLS_TUNNEL_LABEL_2,
index,
mplsInstructionSets.get(2),
nextObjective.appId()
@ -138,9 +138,9 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
Ofdpa2Pipeline.appKryo.serialize(index)
);
// We update the chain.
groupChainElem = new GroupChainElem(groupDescription, 1, false);
groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
updatePendingGroups(
groupInfo.getNextGroupDesc().appCookie(),
groupInfo.nextGroupDesc().appCookie(),
groupChainElem
);
gkeyChain.addFirst(groupKey);
@ -148,7 +148,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
// l2 vpn group before to send the inner most
// group. We update the nextGid.
nextGid = groupDescription.givenGroupId();
groupInfo = new GroupInfo(groupInfo.getInnerMostGroupDesc(), groupDescription);
groupInfo = new GroupInfo(groupInfo.innerMostGroupDesc(), groupDescription);
log.debug("Trying Label 2 Group: device:{} gid:{} gkey:{} nextId:{}",
deviceId, Integer.toHexString(nextGid),
@ -158,7 +158,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
index = getNextAvailableIndex();
groupDescription = createMplsTunnelLabelGroup(
nextGid,
MPLS_TUNNEL_LABEL_1,
OfdpaMplsGroupSubType.MPLS_TUNNEL_LABEL_1,
index,
mplsInstructionSets.get(1),
nextObjective.appId()
@ -166,16 +166,16 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
groupKey = new DefaultGroupKey(
Ofdpa2Pipeline.appKryo.serialize(index)
);
groupChainElem = new GroupChainElem(groupDescription, 1, false);
groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
updatePendingGroups(
groupInfo.getNextGroupDesc().appCookie(),
groupInfo.nextGroupDesc().appCookie(),
groupChainElem
);
gkeyChain.addFirst(groupKey);
// We have to create the l2 vpn group before
// to send the inner most group.
nextGid = groupDescription.givenGroupId();
groupInfo = new GroupInfo(groupInfo.getInnerMostGroupDesc(), groupDescription);
groupInfo = new GroupInfo(groupInfo.innerMostGroupDesc(), groupDescription);
log.debug("Trying Label 1 Group: device:{} gid:{} gkey:{} nextId:{}",
deviceId, Integer.toHexString(nextGid),
@ -191,9 +191,9 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
groupKey = new DefaultGroupKey(
Ofdpa2Pipeline.appKryo.serialize(index)
);
groupChainElem = new GroupChainElem(groupDescription, 1, false);
groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
updatePendingGroups(
groupInfo.getNextGroupDesc().appCookie(),
groupInfo.nextGroupDesc().appCookie(),
groupChainElem
);
gkeyChain.addFirst(groupKey);
@ -208,8 +208,8 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
groupKey, nextObjective.id());
// Finally we send the innermost group.
log.debug("Sending innermost group {} in group chain on device {} ",
Integer.toHexString(groupInfo.getInnerMostGroupDesc().givenGroupId()), deviceId);
groupService.addGroup(groupInfo.getInnerMostGroupDesc());
Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
groupService.addGroup(groupInfo.innerMostGroupDesc());
}
/**
@ -223,10 +223,10 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
* @return the group description
*/
private GroupDescription createMplsTunnelLabelGroup(int nextGroupId,
OfdpaMplsGroupSubType subtype,
int index,
List<Instruction> instructions,
ApplicationId applicationId) {
OfdpaMplsGroupSubType subtype,
int index,
List<Instruction> instructions,
ApplicationId applicationId) {
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
// We add all the instructions.
instructions.forEach(treatment::add);
@ -259,9 +259,9 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
* @return the group description
*/
private GroupDescription createMplsL2VpnGroup(int nextGroupId,
int index,
List<Instruction> instructions,
ApplicationId applicationId) {
int index,
List<Instruction> instructions,
ApplicationId applicationId) {
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
// We add the extensions and the instructions.
treatment.extension(new Ofdpa3PushL2Header(), deviceId);
@ -273,7 +273,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
GroupBucket groupBucket = DefaultGroupBucket
.createIndirectGroupBucket(treatment.build());
// Finally we build the group description.
int groupId = makeMplsLabelGroupId(L2_VPN, index);
int groupId = makeMplsLabelGroupId(OfdpaMplsGroupSubType.L2_VPN, index);
GroupKey groupKey = new DefaultGroupKey(
Ofdpa2Pipeline.appKryo.serialize(index)
);
@ -296,8 +296,8 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler {
* @param mplsTreatment the mpls treatment builder
*/
private void createL2L3AndMplsTreatments(TrafficTreatment treatment,
TrafficTreatment.Builder l2L3Treatment,
TrafficTreatment.Builder mplsTreatment) {
TrafficTreatment.Builder l2L3Treatment,
TrafficTreatment.Builder mplsTreatment) {
for (Instruction ins : treatment.allInstructions()) {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import com.google.common.collect.ImmutableList;
import org.onosproject.core.ApplicationId;
@ -207,10 +207,10 @@ public class Ofdpa3Pipeline extends Ofdpa2Pipeline {
* @return a list of flow rules to install
*/
private List<FlowRule> processPwFilter(PortCriterion portCriterion,
VlanIdCriterion innerVlanIdCriterion,
VlanIdCriterion outerVlanIdCriterion,
long tunnelId,
ApplicationId applicationId) {
VlanIdCriterion innerVlanIdCriterion,
VlanIdCriterion outerVlanIdCriterion,
long tunnelId,
ApplicationId applicationId) {
// As first we create the flow rule for the vlan 1 table.
FlowRule vlan1FlowRule;
int mplsLogicalPort = ((int) portCriterion.port().toLong());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016-present Open Networking Laboratory
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import static org.slf4j.LoggerFactory.getLogger;

View File

@ -0,0 +1,479 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.pipeline.ofdpa;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupService;
import org.slf4j.Logger;
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import static org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.isNotMplsBos;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_GROUP_TYPE_SHIFT;
import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_MPLS_SUBTYPE_SHIFT;
import static org.onosproject.net.flowobjective.NextObjective.Type.HASHED;
import static org.slf4j.LoggerFactory.getLogger;
public final class OfdpaGroupHandlerUtility {
/*
* OFDPA requires group-id's to have a certain form.
* L2 Interface Groups have <4bits-0><12bits-vlanId><16bits-portId>
* L3 Unicast Groups have <4bits-2><28bits-index>
* MPLS Interface Groups have <4bits-9><4bits:0><24bits-index>
* L3 ECMP Groups have <4bits-7><28bits-index>
* L2 Flood Groups have <4bits-4><12bits-vlanId><16bits-index>
* L3 VPN Groups have <4bits-9><4bits-2><24bits-index>
*/
protected static final int L2_INTERFACE_TYPE = 0x00000000;
protected static final int L3_INTERFACE_TYPE = 0x50000000;
protected static final int L3_UNICAST_TYPE = 0x20000000;
protected static final int L3_MULTICAST_TYPE = 0x60000000;
protected static final int MPLS_INTERFACE_TYPE = 0x90000000;
protected static final int MPLS_L3VPN_SUBTYPE = 0x92000000;
protected static final int L3_ECMP_TYPE = 0x70000000;
protected static final int L2_FLOOD_TYPE = 0x40000000;
protected static final int TYPE_MASK = 0x0fffffff;
protected static final int SUBTYPE_MASK = 0x00ffffff;
protected static final int TYPE_VLAN_MASK = 0x0000ffff;
protected static final int THREE_BIT_MASK = 0x0fff;
protected static final int FOUR_BIT_MASK = 0xffff;
protected static final int PORT_LEN = 16;
protected static final int PORT_LOWER_BITS_MASK = 0x3f;
protected static final long PORT_HIGHER_BITS_MASK = ~PORT_LOWER_BITS_MASK;
protected static final String HEX_PREFIX = "0x";
protected static final Logger log = getLogger(OfdpaGroupHandlerUtility.class);
private OfdpaGroupHandlerUtility() {
// Utility classes should not have a public or default constructor.
}
/**
* Returns the outport in a traffic treatment.
*
* @param tt the treatment
* @return the PortNumber for the outport or null
*/
protected static PortNumber readOutPortFromTreatment(TrafficTreatment tt) {
for (Instruction ins : tt.allInstructions()) {
if (ins.type() == Instruction.Type.OUTPUT) {
return ((Instructions.OutputInstruction) ins).port();
}
}
return null;
}
/**
* Helper enum to handle the different MPLS group
* types.
*/
public enum OfdpaMplsGroupSubType {
MPLS_INTF((short) 0),
L2_VPN((short) 1),
L3_VPN((short) 2),
MPLS_TUNNEL_LABEL_1((short) 3),
MPLS_TUNNEL_LABEL_2((short) 4),
MPLS_SWAP_LABEL((short) 5),
MPLS_ECMP((short) 8);
private short value;
public static final int OFDPA_GROUP_TYPE_SHIFT = 28;
public static final int OFDPA_MPLS_SUBTYPE_SHIFT = 24;
OfdpaMplsGroupSubType(short value) {
this.value = value;
}
/**
* Gets the value as an short.
*
* @return the value as an short
*/
public short getValue() {
return this.value;
}
}
/**
* Creates MPLS Label group id given a sub type and
* the index.
*
* @param subType the MPLS Label group sub type
* @param index the index of the group
* @return the OFDPA group id
*/
public static Integer makeMplsLabelGroupId(OfdpaMplsGroupSubType subType, int index) {
index = index & 0x00FFFFFF;
return index | (9 << OFDPA_GROUP_TYPE_SHIFT) | (subType.value << OFDPA_MPLS_SUBTYPE_SHIFT);
}
/**
* Creates MPLS Forwarding group id given a sub type and
* the index.
*
* @param subType the MPLS forwarding group sub type
* @param index the index of the group
* @return the OFDPA group id
*/
public static Integer makeMplsForwardingGroupId(OfdpaMplsGroupSubType subType, int index) {
index = index & 0x00FFFFFF;
return index | (10 << OFDPA_GROUP_TYPE_SHIFT) | (subType.value << OFDPA_MPLS_SUBTYPE_SHIFT);
}
/**
* Gets duplicated output ports between group key chains and existing groups
* in the device.
*
* @param allActiveKeys list of group key chain
* @param groupService the group service to get group information
* @param deviceId the device id to get group
* @return a set of output port from the list of group key chain
*/
public static Set<PortNumber> getExistingOutputPorts(List<Deque<GroupKey>> allActiveKeys,
GroupService groupService,
DeviceId deviceId) {
Set<PortNumber> existingPorts = Sets.newHashSet();
allActiveKeys.forEach(keyChain -> {
GroupKey ifaceGroupKey = keyChain.peekLast();
Group ifaceGroup = groupService.getGroup(deviceId, ifaceGroupKey);
if (ifaceGroup != null && !ifaceGroup.buckets().buckets().isEmpty()) {
ifaceGroup.buckets().buckets().forEach(bucket -> {
PortNumber portNumber = readOutPortFromTreatment(bucket.treatment());
if (portNumber != null) {
existingPorts.add(portNumber);
}
});
}
});
return existingPorts;
}
/**
* The purpose of this function is to verify if the hashed next
* objective is supported by the current pipeline.
*
* @param nextObjective the hashed objective to verify
* @return true if the hashed objective is supported. Otherwise false.
*/
public static boolean verifyHashedNextObjective(NextObjective nextObjective) {
// if it is not hashed, there is something wrong;
if (nextObjective.type() != HASHED) {
return false;
}
// The case non supported is the MPLS-ECMP. For now, we try
// to create a MPLS-ECMP for the transport of a VPWS. The
// necessary info are contained in the meta selector. In particular
// we are looking for the case of BoS==False;
TrafficSelector metaSelector = nextObjective.meta();
if (metaSelector != null && isNotMplsBos(metaSelector)) {
return false;
}
return true;
}
/**
* Generates a list of group buckets from given list of group information
* and group bucket type.
*
* @param groupInfos a list of group information
* @param bucketType group bucket type
* @return list of group bucket generate from group information
*/
protected static List<GroupBucket> generateNextGroupBuckets(List<GroupInfo> groupInfos,
GroupDescription.Type bucketType) {
List<GroupBucket> newBuckets = Lists.newArrayList();
groupInfos.forEach(groupInfo -> {
GroupDescription groupDesc = groupInfo.nextGroupDesc();
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
treatmentBuilder.group(new GroupId(groupDesc.givenGroupId()));
GroupBucket newBucket = null;
switch (bucketType) {
case ALL:
newBucket =
DefaultGroupBucket.createAllGroupBucket(treatmentBuilder.build());
break;
case INDIRECT:
newBucket =
DefaultGroupBucket.createIndirectGroupBucket(treatmentBuilder.build());
break;
case SELECT:
newBucket =
DefaultGroupBucket.createSelectGroupBucket(treatmentBuilder.build());
break;
case FAILOVER:
// TODO: support failover bucket type
default:
log.warn("Unknown bucket type: {}", bucketType);
break;
}
if (newBucket != null) {
newBuckets.add(newBucket);
}
});
return ImmutableList.copyOf(newBuckets);
}
/**
* Extracts VlanId from given group ID.
*
* @param groupId the group ID
* @return vlan id of the group
*/
public static VlanId extractVlanIdFromGroupId(int groupId) {
// Extract the 9th to 20th bit from group id as vlan id.
short vlanId = (short) ((groupId & 0x0fff0000) >> 16);
return VlanId.vlanId(vlanId);
}
public static GroupKey l2FloodGroupKey(VlanId vlanId, DeviceId deviceId) {
int hash = Objects.hash(deviceId, vlanId);
hash = L2_FLOOD_TYPE | TYPE_MASK & hash;
return new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(hash));
}
public static int l2GroupId(VlanId vlanId, long portNum) {
return L2_INTERFACE_TYPE | (vlanId.toShort() << 16) | (int) portNum;
}
/**
* Returns a hash as the L2 Interface Group Key.
*
* Keep the lower 6-bit for port since port number usually smaller than 64.
* Hash other information into remaining 28 bits.
*
* @param deviceId Device ID
* @param vlanId VLAN ID
* @param portNumber Port number
* @return L2 interface group key
*/
public static int l2InterfaceGroupKey(DeviceId deviceId, VlanId vlanId, long portNumber) {
int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
int hash = Objects.hash(deviceId, vlanId, portHigherBits);
return L2_INTERFACE_TYPE | (TYPE_MASK & hash << 6) | portLowerBits;
}
/**
* Utility class for moving group information around.
*
* Example: Suppose we are trying to create a group-chain A-B-C-D, where
* A is the top level group, and D is the inner-most group, typically L2 Interface.
* The innerMostGroupDesc is always D. At various stages of the creation
* process the nextGroupDesc may be C or B. The nextGroupDesc exists to
* inform the referencing group about which group it needs to point to,
* and wait for. In some cases the group chain may simply be A-B. In this case,
* both innerMostGroupDesc and nextGroupDesc will be B.
*/
public static class GroupInfo {
/**
* Description of the inner-most group of the group chain.
* It is always an L2 interface group.
*/
private GroupDescription innerMostGroupDesc;
/**
* Description of the next group in the group chain.
* It can be L2 interface, L3 interface, L3 unicast, L3 VPN group.
* It is possible that nextGroupDesc is the same as the innerMostGroup.
*/
private GroupDescription nextGroupDesc;
GroupInfo(GroupDescription innerMostGroupDesc, GroupDescription nextGroupDesc) {
this.innerMostGroupDesc = innerMostGroupDesc;
this.nextGroupDesc = nextGroupDesc;
}
/**
* Getter for innerMostGroupDesc.
*
* @return the inner most group description
*/
public GroupDescription innerMostGroupDesc() {
return innerMostGroupDesc;
}
/**
* Getter for the next group description.
*
* @return the next group description
*/
public GroupDescription nextGroupDesc() {
return nextGroupDesc;
}
/**
* Setter of nextGroupDesc.
*
* @param nextGroupDesc the given value to set
*/
public void nextGroupDesc(GroupDescription nextGroupDesc) {
this.nextGroupDesc = nextGroupDesc;
}
}
/**
* Represents an entire group-chain that implements a Next-Objective from
* the application. The objective is represented as a list of deques, where
* each deque is a separate chain of groups.
* <p>
* For example, an ECMP group with 3 buckets, where each bucket points to
* a group chain of L3 Unicast and L2 interface groups will look like this:
* <ul>
* <li>List[0] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
* <li>List[1] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
* <li>List[2] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
* </ul>
* where the first element of each deque is the same, representing the
* top level ECMP group, while every other element represents a unique groupKey.
* <p>
* Also includes information about the next objective that
* resulted in these group-chains.
*
*/
public static class OfdpaNextGroup implements NextGroup {
private final NextObjective nextObj;
private final List<Deque<GroupKey>> gkeys;
public OfdpaNextGroup(List<Deque<GroupKey>> gkeys, NextObjective nextObj) {
this.nextObj = nextObj;
this.gkeys = gkeys;
}
public NextObjective nextObjective() {
return nextObj;
}
@Override
public byte[] data() {
return Ofdpa2Pipeline.appKryo.serialize(gkeys);
}
}
/**
* Represents a group element that is part of a chain of groups.
* Stores enough information to create a Group Description to add the group
* to the switch by requesting the Group Service. Objects instantiating this
* class are meant to be temporary and live as long as it is needed to wait for
* referenced groups in the group chain to be created.
*/
public static class GroupChainElem {
private GroupDescription groupDescription;
private AtomicInteger waitOnGroups;
private boolean addBucketToGroup;
private DeviceId deviceId;
public GroupChainElem(GroupDescription groupDescription, int waitOnGroups,
boolean addBucketToGroup, DeviceId deviceId) {
this.groupDescription = groupDescription;
this.waitOnGroups = new AtomicInteger(waitOnGroups);
this.addBucketToGroup = addBucketToGroup;
this.deviceId = deviceId;
}
/**
* This method atomically decrements the counter for the number of
* groups this GroupChainElement is waiting on, for notifications from
* the Group Service. When this method returns a value of 0, this
* GroupChainElement is ready to be processed.
*
* @return integer indication of the number of notifications being waited on
*/
int decrementAndGetGroupsWaitedOn() {
return waitOnGroups.decrementAndGet();
}
public GroupDescription groupDescription() {
return groupDescription;
}
public boolean addBucketToGroup() {
return addBucketToGroup;
}
@Override
public String toString() {
return (Integer.toHexString(groupDescription.givenGroupId()) +
" groupKey: " + groupDescription.appCookie() +
" waiting-on-groups: " + waitOnGroups.get() +
" addBucketToGroup: " + addBucketToGroup +
" device: " + deviceId);
}
}
public static class GroupChecker implements Runnable {
protected final Logger log = getLogger(getClass());
private Ofdpa2GroupHandler groupHandler;
public GroupChecker(Ofdpa2GroupHandler groupHandler) {
this.groupHandler = groupHandler;
}
@Override
public void run() {
if (groupHandler.pendingGroups().size() != 0) {
log.debug("pending groups being checked: {}", groupHandler.pendingGroups().asMap().keySet());
}
if (groupHandler.pendingAddNextObjectives().size() != 0) {
log.debug("pending add-next-obj being checked: {}",
groupHandler.pendingAddNextObjectives().asMap().keySet());
}
Set<GroupKey> keys = groupHandler.pendingGroups().asMap().keySet().stream()
.filter(key -> groupHandler.groupService.getGroup(groupHandler.deviceId, key) != null)
.collect(Collectors.toSet());
Set<GroupKey> otherkeys = groupHandler.pendingAddNextObjectives().asMap().keySet().stream()
.filter(otherkey -> groupHandler.groupService.getGroup(groupHandler.deviceId, otherkey) != null)
.collect(Collectors.toSet());
keys.addAll(otherkeys);
keys.forEach(key -> groupHandler.processPendingAddGroupsOrNextObjs(key, false));
}
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
/**
* Group handler that emulates Broadcom OF-DPA TTP on OVS.

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.pipeline;
package org.onosproject.driver.pipeline.ofdpa;
import org.onosproject.net.behaviour.PipelinerContext;

View File

@ -0,0 +1,20 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Pipelines for OF-DPA.
*/
package org.onosproject.driver.pipeline.ofdpa;

View File

@ -77,7 +77,7 @@
<driver name="ofdpa" extends="default"
manufacturer="Broadcom Corp." hwVersion="OF-DPA i12_1.7" swVersion="OF-DPA i12_1.7">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.Ofdpa2Pipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline"/>
<behaviour api="org.onosproject.openflow.controller.ExtensionTreatmentInterpreter"
impl="org.onosproject.driver.extensions.OfdpaExtensionTreatmentInterpreter" />
<behaviour api="org.onosproject.net.behaviour.ExtensionTreatmentResolver"
@ -94,7 +94,7 @@
<driver name="ofdpa3" extends="default"
manufacturer="Broadcom Corp." hwVersion="OF-DPA 2.0" swVersion="OF-DPA 2.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.Ofdpa3Pipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.Ofdpa3Pipeline"/>
<behaviour api="org.onosproject.openflow.controller.ExtensionTreatmentInterpreter"
impl="org.onosproject.driver.extensions.Ofdpa3ExtensionTreatmentInterpreter" />
<behaviour api="org.onosproject.net.behaviour.ExtensionTreatmentResolver"
@ -111,13 +111,13 @@
<driver name="qmx-ofdpa3" extends="ofdpa3"
manufacturer="Broadcom Corp." hwVersion="Qmx" swVersion="Qmx">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.Ofdpa3QmxPipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.Ofdpa3QmxPipeline"/>
</driver>
<driver name="znyx-ofdpa" extends="default"
manufacturer="ZNYX Networks" hwVersion=".*" swVersion=".*OF-DPA.*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.Ofdpa3Pipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.Ofdpa3Pipeline"/>
<behaviour api="org.onosproject.openflow.controller.ExtensionTreatmentInterpreter"
impl="org.onosproject.driver.extensions.Ofdpa3ExtensionTreatmentInterpreter" />
<behaviour api="org.onosproject.net.behaviour.ExtensionTreatmentResolver"
@ -136,7 +136,7 @@
manufacturer="ONF"
hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CpqdOfdpa2Pipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.CpqdOfdpa2Pipeline"/>
</driver>
<!-- Emulation of the OFDPA pipeline using a CPqD OF 1.3 software switch.
@ -147,7 +147,7 @@
manufacturer="ONF"
hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CpqdOfdpa2VlanPipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.CpqdOfdpa2VlanPipeline"/>
</driver>
<!-- Emulation of the OFDPA pipeline using a OVS OF 1.3 software switch.
@ -158,7 +158,7 @@
manufacturer="ONF"
hwVersion="OFDPA OVS" swVersion="OFDPA OVS">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OvsOfdpa2Pipeline"/>
impl="org.onosproject.driver.pipeline.ofdpa.OvsOfdpa2Pipeline"/>
</driver>
<driver name="celestica" extends="default"