use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method getGroupsFromInstructions.
// Gets group information from instructions.
private void getGroupsFromInstructions(Map<GroupId, Group> groups, List<Instruction> instructions, TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts, PipelineTraceableHitChain currentHitChain, PipelineTraceableOutput.Builder outputBuilder, PipelineTraceableInput input, boolean dropped) {
List<Instruction> groupInstructionlist = new ArrayList<>();
// sort instructions according to priority (larger Instruction.Type ENUM constant first)
// which enables to treat other actions before the OUTPUT action
// TODO improve the priority scheme according to the OpenFlow ActionSet spec
List<Instruction> instructionsSorted = new ArrayList<>();
instructionsSorted.addAll(instructions);
instructionsSorted.sort((instr1, instr2) -> Integer.compare(instr2.type().ordinal(), instr1.type().ordinal()));
// Handles first all non-group instructions
for (Instruction instruction : instructionsSorted) {
log.debug("Considering Instruction {}", instruction);
// to the possible outputs for this packet
if (!instruction.type().equals(Instruction.Type.GROUP)) {
// or add the output to the possible outputs for this packet
if (instruction.type().equals(Instruction.Type.OUTPUT)) {
buildOutputFromDevice(egressPacket, outputPorts, (OutputInstruction) instruction, currentHitChain, outputBuilder, input.ingressPacket().packet(), dropped);
} else {
egressPacket = translateInstruction(egressPacket, instruction);
}
} else {
// Store for later if the instruction is pointing to a group
groupInstructionlist.add(instruction);
}
}
// handle all the internal instructions pointing to a group.
for (Instruction instr : groupInstructionlist) {
Instructions.GroupInstruction groupInstruction = (Instructions.GroupInstruction) instr;
Group group = groups.get(groupInstruction.groupId());
// group does not exist in the dataplane
if (group == null) {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(egressPacket.build()));
currentHitChain.dropped();
outputBuilder.appendToLog("Null group for Instruction " + instr).noGroups().addHitChain(currentHitChain);
break;
}
log.debug("Analyzing group {}", group.id());
// group is there but there are no members/buckets
if (group.buckets().buckets().size() == 0) {
// add the group to the traversed groups
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
currentHitChain.setEgressPacket(new PipelineTraceablePacket(egressPacket.build()));
currentHitChain.dropped();
outputBuilder.appendToLog("Group " + group.id() + " has no buckets").noMembers().addHitChain(currentHitChain);
break;
}
PipelineTraceableHitChain newHitChain;
TrafficSelector.Builder newEgressPacket;
// Cycle in each of the group's buckets and add them to the groups for this Device.
for (GroupBucket bucket : group.buckets().buckets()) {
// add the group to the traversed groups
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
// Go to the next step - using a copy of the egress packet and of the hit chain
newHitChain = PipelineTraceableHitChain.emptyHitChain();
currentHitChain.hitChain().forEach(newHitChain::addDataPlaneEntity);
newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
getGroupsFromInstructions(groups, bucket.treatment().allInstructions(), newEgressPacket, outputPorts, newHitChain, outputBuilder, input, dropped | isDropped(group.id(), bucket, input.ingressPort()));
}
}
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class SimpleVirtualGroupStore method addOrUpdateGroupEntry.
@Override
public void addOrUpdateGroupEntry(NetworkId networkId, Group group) {
// check if this new entry is an update to an existing entry
StoredGroupEntry existing = null;
if (groupEntriesById.get(networkId) != null && groupEntriesById.get(networkId).get(group.deviceId()) != null) {
existing = groupEntriesById.get(networkId).get(group.deviceId()).get(group.id());
}
GroupEvent event = null;
if (existing != null) {
synchronized (existing) {
for (GroupBucket bucket : group.buckets().buckets()) {
Optional<GroupBucket> matchingBucket = existing.buckets().buckets().stream().filter((existingBucket) -> (existingBucket.equals(bucket))).findFirst();
if (matchingBucket.isPresent()) {
((StoredGroupBucketEntry) matchingBucket.get()).setPackets(bucket.packets());
((StoredGroupBucketEntry) matchingBucket.get()).setBytes(bucket.bytes());
} else {
log.warn("addOrUpdateGroupEntry: No matching " + "buckets to update stats");
}
}
existing.setLife(group.life());
existing.setPackets(group.packets());
existing.setBytes(group.bytes());
if (existing.state() == Group.GroupState.PENDING_ADD) {
existing.setState(Group.GroupState.ADDED);
event = new GroupEvent(GroupEvent.Type.GROUP_ADDED, existing);
} else {
if (existing.state() == Group.GroupState.PENDING_UPDATE) {
existing.setState(Group.GroupState.ADDED);
}
event = new GroupEvent(GroupEvent.Type.GROUP_UPDATED, existing);
}
}
}
if (event != null) {
notifyDelegate(networkId, event);
}
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class SimpleVirtualGroupStore method getUpdatedBucketList.
private List<GroupBucket> getUpdatedBucketList(Group oldGroup, UpdateType type, GroupBuckets buckets) {
if (type == UpdateType.SET) {
return buckets.buckets();
}
List<GroupBucket> oldBuckets = oldGroup.buckets().buckets();
List<GroupBucket> updatedBucketList = new ArrayList<>();
boolean groupDescUpdated = false;
if (type == UpdateType.ADD) {
List<GroupBucket> newBuckets = buckets.buckets();
// Add old buckets that will not be updated and check if any will be updated.
for (GroupBucket oldBucket : oldBuckets) {
int newBucketIndex = newBuckets.indexOf(oldBucket);
if (newBucketIndex != -1) {
GroupBucket newBucket = newBuckets.get(newBucketIndex);
if (!newBucket.hasSameParameters(oldBucket)) {
// Bucket will be updated
groupDescUpdated = true;
}
} else {
// Old bucket will remain the same - add it.
updatedBucketList.add(oldBucket);
}
}
// Add all new buckets
updatedBucketList.addAll(newBuckets);
if (!oldBuckets.containsAll(newBuckets)) {
groupDescUpdated = true;
}
} else if (type == UpdateType.REMOVE) {
List<GroupBucket> bucketsToRemove = buckets.buckets();
// Check which old buckets should remain
for (GroupBucket oldBucket : oldBuckets) {
if (!bucketsToRemove.contains(oldBucket)) {
updatedBucketList.add(oldBucket);
} else {
groupDescUpdated = true;
}
}
}
if (groupDescUpdated) {
return updatedBucketList;
} else {
return null;
}
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class SimpleVirtualGroupStore method updateGroupDescription.
@Override
public void updateGroupDescription(NetworkId networkId, DeviceId deviceId, GroupKey oldAppCookie, UpdateType type, GroupBuckets newBuckets, GroupKey newAppCookie) {
// Check if a group is existing with the provided key
Group oldGroup = getGroup(networkId, deviceId, oldAppCookie);
if (oldGroup == null) {
return;
}
List<GroupBucket> newBucketList = getUpdatedBucketList(oldGroup, type, newBuckets);
if (newBucketList != null) {
// Create a new group object from the old group
GroupBuckets updatedBuckets = new GroupBuckets(newBucketList);
GroupKey newCookie = (newAppCookie != null) ? newAppCookie : oldAppCookie;
GroupDescription updatedGroupDesc = new DefaultGroupDescription(oldGroup.deviceId(), oldGroup.type(), updatedBuckets, newCookie, oldGroup.givenGroupId(), oldGroup.appId());
StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(), updatedGroupDesc);
newGroup.setState(Group.GroupState.PENDING_UPDATE);
newGroup.setLife(oldGroup.life());
newGroup.setPackets(oldGroup.packets());
newGroup.setBytes(oldGroup.bytes());
// Remove the old entry from maps and add new entry using new key
ConcurrentMap<GroupKey, StoredGroupEntry> keyTable = getGroupKeyTable(networkId, oldGroup.deviceId());
ConcurrentMap<GroupId, StoredGroupEntry> idTable = getGroupIdTable(networkId, oldGroup.deviceId());
keyTable.remove(oldGroup.appCookie());
idTable.remove(oldGroup.id());
keyTable.put(newGroup.appCookie(), newGroup);
idTable.put(newGroup.id(), newGroup);
notifyDelegate(networkId, new GroupEvent(GroupEvent.Type.GROUP_UPDATE_REQUESTED, newGroup));
}
}
use of org.onosproject.net.group.GroupBucket in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method createL2L3ChainInternal.
/**
* Internal implementation of createL2L3Chain.
* <p>
* The is_present bit in set_vlan_vid action is required to be 0 in OFDPA i12.
* Since it is non-OF spec, we need an extension treatment for that.
* The useSetVlanExtension must be set to false for OFDPA i12.
* </p>
*
* @param treatment that needs to be broken up to create the group chain
* @param nextId of the next objective that needs this group chain
* @param appId of the application that sent this next objective
* @param mpls determines if L3Unicast or MPLSInterface group is created
* @param meta metadata passed in by the application as part of the nextObjective
* @param useSetVlanExtension use the setVlanVid extension that has is_present bit set to 0.
* @return GroupInfo containing the GroupDescription of the
* L2Interface group(inner) and the GroupDescription of the (outer)
* L3Unicast/MPLSInterface group. May return null if there is an
* error in processing the chain
*/
protected GroupInfo createL2L3ChainInternal(TrafficTreatment treatment, int nextId, ApplicationId appId, boolean mpls, TrafficSelector meta, boolean useSetVlanExtension) {
// 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();
TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
VlanId vlanid = null;
long portNum = 0;
boolean setVlan = false, popVlan = false;
MacAddress srcMac;
MacAddress dstMac;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
switch(l2ins.subtype()) {
case ETH_DST:
dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
outerTtb.setEthDst(dstMac);
break;
case ETH_SRC:
srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
outerTtb.setEthSrc(srcMac);
break;
case VLAN_ID:
vlanid = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
if (useSetVlanExtension) {
OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(vlanid);
outerTtb.extension(ofdpaSetVlanVid, deviceId);
} else {
outerTtb.setVlanId(vlanid);
}
setVlan = true;
break;
case VLAN_POP:
innerTtb.popVlan();
popVlan = true;
break;
case DEC_MPLS_TTL:
case MPLS_LABEL:
case MPLS_POP:
case MPLS_PUSH:
case VLAN_PCP:
case VLAN_PUSH:
default:
break;
}
} else if (ins.type() == Instruction.Type.OUTPUT) {
portNum = ((Instructions.OutputInstruction) ins).port().toLong();
innerTtb.add(ins);
} else {
log.debug("Driver does not handle this type of TrafficTreatment" + " instruction in l2l3chain: {} - {}", ins.type(), ins);
}
}
if (vlanid == null && meta != null) {
// use metadata if available
Criterion vidCriterion = meta.getCriterion(VLAN_VID);
if (vidCriterion != null) {
vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
}
// if vlan is not set, use the vlan in metadata for outerTtb
if (vlanid != null && !setVlan) {
if (useSetVlanExtension) {
OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(vlanid);
outerTtb.extension(ofdpaSetVlanVid, deviceId);
} else {
outerTtb.setVlanId(vlanid);
}
}
}
if (vlanid == null) {
log.error("Driver cannot process an L2/L3 group chain without " + "egress vlan information for dev: {} port:{}", deviceId, portNum);
return null;
}
if (!setVlan && !popVlan) {
// untagged outgoing port
TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
temp.popVlan();
innerTtb.build().allInstructions().forEach(temp::add);
innerTtb = temp;
}
// assemble information for ofdpa l2interface group
int l2groupId = l2GroupId(vlanid, portNum);
// a globally unique groupkey that is different for ports in the same device,
// but different for the same portnumber on different devices. Also different
// for the various group-types created out of the same next objective.
int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum);
final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
// assemble information for outer group
GroupDescription outerGrpDesc;
if (mpls) {
// outer group is MPLS Interface
int mplsInterfaceIndex = getNextAvailableIndex();
int mplsGroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
final GroupKey mplsGroupKey = new DefaultGroupKey(appKryo.serialize(mplsInterfaceIndex));
outerTtb.group(new GroupId(l2groupId));
// create the mpls-interface group description to wait for the
// l2 interface group to be processed
GroupBucket mplsinterfaceGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
outerGrpDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(mplsinterfaceGroupBucket)), mplsGroupKey, mplsGroupId, appId);
log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(mplsGroupId), mplsGroupKey, nextId);
} else {
// outer group is L3Unicast
int l3unicastIndex = getNextAvailableIndex();
int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3unicastIndex));
outerTtb.group(new GroupId(l2groupId));
// create the l3unicast group description to wait for the
// l2 interface group to be processed
GroupBucket l3unicastGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
outerGrpDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l3unicastGroupBucket)), l3groupkey, l3groupId, appId);
log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l3groupId), l3groupkey, nextId);
}
// store l2groupkey with the groupChainElem for the outer-group that depends on it
GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1, false, deviceId);
updatePendingGroups(l2groupkey, gce);
// create group description for the inner l2 interface group
GroupBucket l2InterfaceGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
GroupDescription l2groupDescription = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l2InterfaceGroupBucket)), l2groupkey, l2groupId, appId);
log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(l2groupId), l2groupkey, nextId);
return new GroupInfo(l2groupDescription, outerGrpDesc);
}
Aggregations