Search in sources :

Example 1 with GroupInstruction

use of org.onosproject.net.flow.instructions.Instructions.GroupInstruction in project onos by opennetworkinglab.

the class Ofdpa2GroupHandler method verifyGroup.

/**
 *  Checks existing buckets in {@link NextGroup}  to verify if they match
 *  the buckets in the given {@link NextObjective}. Adds or removes buckets
 *  to ensure that the buckets match up.
 *
 * @param nextObjective the next objective to verify
 * @param next the representation of the existing group which has to be
 *             modified to match the given next objective
 */
protected void verifyGroup(NextObjective nextObjective, NextGroup next) {
    if (nextObjective.type() == NextObjective.Type.SIMPLE) {
        log.warn("verification not supported for indirect group");
        fail(nextObjective, ObjectiveError.UNSUPPORTED);
        return;
    }
    log.trace("Call to verify device:{} nextId:{}", deviceId, nextObjective.id());
    List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
    List<TrafficTreatment> bucketsToCreate = Lists.newArrayList();
    List<Integer> indicesToRemove = Lists.newArrayList();
    // to detect missing buckets and/or duplicate buckets (to be removed)
    for (TrafficTreatment bkt : nextObjective.next()) {
        PortNumber portNumber = readOutPortFromTreatment(bkt);
        int label = readLabelFromTreatment(bkt);
        if (portNumber == null) {
            log.warn("treatment {} of next objective {} has no outport.. " + "cannot remove bucket from group in dev: {}", bkt, nextObjective.id(), deviceId);
            fail(nextObjective, ObjectiveError.BADPARAMS);
            return;
        }
        List<Integer> existing = existingPortAndLabel(allActiveKeys, groupService, deviceId, portNumber, label);
        if (existing.isEmpty()) {
            // if it doesn't exist, mark this bucket for creation
            bucketsToCreate.add(bkt);
        }
        if (existing.size() > 1) {
            // if it exists but there are duplicates, mark the others for removal
            existing.remove(0);
            indicesToRemove.addAll(existing);
        }
    }
    // (not duplicates) respect to the next objective
    if (allActiveKeys.size() > nextObjective.next().size() && // ignore specific case of empty group
    !(nextObjective.next().size() == 0 && allActiveKeys.size() == 1 && allActiveKeys.get(0).size() == 1)) {
        log.warn("Mismatch detected between next and flowobjstore for device {}: " + "nextId:{}, nextObjective-size:{} next-size:{} .. correcting", deviceId, nextObjective.id(), nextObjective.next().size(), allActiveKeys.size());
        List<Integer> otherIndices = indicesToRemoveFromNextGroup(allActiveKeys, nextObjective, groupService, deviceId);
        // Filter out the indices not present
        otherIndices = otherIndices.stream().filter(index -> !indicesToRemove.contains(index)).collect(Collectors.toList());
        // Add all to the final list
        indicesToRemove.addAll(otherIndices);
    }
    log.trace("Buckets to create {}", bucketsToCreate);
    log.trace("Indices to remove {}", indicesToRemove);
    if (!bucketsToCreate.isEmpty()) {
        log.info("creating {} buckets as part of nextId: {} verification", bucketsToCreate.size(), nextObjective.id());
        // create a nextObjective only with these buckets
        NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(nextObjective.id()).withType(nextObjective.type()).withMeta(nextObjective.meta()).fromApp(nextObjective.appId());
        bucketsToCreate.forEach(nextObjBuilder::addTreatment);
        // According to the next type we call the proper add function
        if (nextObjective.type() == NextObjective.Type.HASHED) {
            if (isL2Hash(nextObjective)) {
                addBucketToL2HashGroup(nextObjBuilder.addToExisting(), allActiveKeys);
            } else {
                addBucketToEcmpHashGroup(nextObjBuilder.addToExisting(), allActiveKeys);
            }
        } else {
            addBucketToBroadcastGroup(nextObjBuilder.addToExisting(), allActiveKeys);
        }
    }
    if (!indicesToRemove.isEmpty()) {
        log.info("removing {} buckets as part of nextId: {} verification", indicesToRemove.size(), nextObjective.id());
        List<Deque<GroupKey>> chainsToRemove = Lists.newArrayList();
        indicesToRemove.forEach(index -> chainsToRemove.add(allActiveKeys.get(index)));
        removeBucket(chainsToRemove, nextObjective);
    }
    log.trace("Checking mismatch with GroupStore device:{} nextId:{}", deviceId, nextObjective.id());
    if (bucketsToCreate.isEmpty() && indicesToRemove.isEmpty()) {
        // flowObjective store record is in-sync with nextObjective passed-in
        // Nevertheless groupStore may not be in sync due to bug in the store
        // - see CORD-1844. XXX When this bug is fixed, the rest of this verify
        // method will not be required.
        GroupKey topGroupKey = allActiveKeys.get(0).peekFirst();
        Group topGroup = groupService.getGroup(deviceId, topGroupKey);
        // topGroup should not be null - adding guard
        if (topGroup == null) {
            log.warn("topGroup {} not found in GroupStore device:{}, nextId:{}", topGroupKey, deviceId, nextObjective.id());
            fail(nextObjective, ObjectiveError.GROUPMISSING);
            return;
        }
        int actualGroupSize = topGroup.buckets().buckets().size();
        int objGroupSize = nextObjective.next().size();
        if (actualGroupSize != objGroupSize) {
            log.warn("Mismatch detected in device:{}, nextId:{}, nextObjective-size" + ":{} group-size:{} .. correcting", deviceId, nextObjective.id(), objGroupSize, actualGroupSize);
        }
        if (actualGroupSize > objGroupSize) {
            // Group in the device has more chains
            List<GroupBucket> bucketsToRemove = Lists.newArrayList();
            // check every bucket in the actual group
            for (GroupBucket bucket : topGroup.buckets().buckets()) {
                GroupInstruction g = (GroupInstruction) bucket.treatment().allInstructions().iterator().next();
                // the group pointed to
                GroupId gidToCheck = g.groupId();
                boolean matches = false;
                for (Deque<GroupKey> validChain : allActiveKeys) {
                    if (validChain.size() < 2) {
                        continue;
                    }
                    GroupKey pointedGroupKey = validChain.stream().collect(Collectors.toList()).get(1);
                    Group pointedGroup = groupService.getGroup(deviceId, pointedGroupKey);
                    if (pointedGroup != null && gidToCheck.equals(pointedGroup.id())) {
                        matches = true;
                        break;
                    }
                }
                if (!matches) {
                    log.warn("Removing bucket pointing to groupId:{}", gidToCheck);
                    bucketsToRemove.add(bucket);
                }
            }
            // remove buckets for which there was no record in the obj store
            if (bucketsToRemove.isEmpty()) {
                log.warn("Mismatch detected but could not determine which" + "buckets to remove");
            } else {
                GroupBuckets removeBuckets = new GroupBuckets(bucketsToRemove);
                groupService.removeBucketsFromGroup(deviceId, topGroupKey, removeBuckets, topGroupKey, nextObjective.appId());
            }
        } else if (actualGroupSize < objGroupSize) {
            // Group in the device has less chains
            // should also add buckets not in group-store but in obj-store
            List<GroupBucket> bucketsToAdd = Lists.newArrayList();
            // check every bucket in the obj
            for (Deque<GroupKey> validChain : allActiveKeys) {
                if (validChain.size() < 2) {
                    continue;
                }
                GroupKey pointedGroupKey = validChain.stream().collect(Collectors.toList()).get(1);
                Group pointedGroup = groupService.getGroup(deviceId, pointedGroupKey);
                if (pointedGroup == null) {
                    // group should exist, otherwise cannot be added as bucket
                    continue;
                }
                boolean matches = false;
                for (GroupBucket bucket : topGroup.buckets().buckets()) {
                    GroupInstruction g = (GroupInstruction) bucket.treatment().allInstructions().iterator().next();
                    // the group pointed to
                    GroupId gidToCheck = g.groupId();
                    if (pointedGroup.id().equals(gidToCheck)) {
                        matches = true;
                        break;
                    }
                }
                if (!matches) {
                    log.warn("Adding bucket pointing to groupId:{}", pointedGroup);
                    TrafficTreatment t = DefaultTrafficTreatment.builder().group(pointedGroup.id()).build();
                    // Create the proper bucket according to the next type
                    if (nextObjective.type() == NextObjective.Type.HASHED) {
                        bucketsToAdd.add(DefaultGroupBucket.createSelectGroupBucket(t));
                    } else {
                        bucketsToAdd.add(DefaultGroupBucket.createAllGroupBucket(t));
                    }
                }
            }
            if (bucketsToAdd.isEmpty()) {
                log.warn("Mismatch detected but could not determine which " + "buckets to add");
            } else {
                GroupBuckets addBuckets = new GroupBuckets(bucketsToAdd);
                groupService.addBucketsToGroup(deviceId, topGroupKey, addBuckets, topGroupKey, nextObjective.appId());
            }
        }
    }
    log.trace("Verify done for device:{} nextId:{}", deviceId, nextObjective.id());
    pass(nextObjective);
}
Also used : DefaultNextObjective(org.onosproject.net.flowobjective.DefaultNextObjective) NextObjective(org.onosproject.net.flowobjective.NextObjective) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) GroupKey(org.onosproject.net.group.GroupKey) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) OfdpaGroupHandlerUtility.l2MulticastGroupKey(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) GroupBuckets(org.onosproject.net.group.GroupBuckets) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque) GroupId(org.onosproject.core.GroupId) GroupBucket(org.onosproject.net.group.GroupBucket) DefaultGroupBucket(org.onosproject.net.group.DefaultGroupBucket) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) PortNumber(org.onosproject.net.PortNumber) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction)

Example 2 with GroupInstruction

use of org.onosproject.net.flow.instructions.Instructions.GroupInstruction in project onos by opennetworkinglab.

the class InstructionJsonMatcher method matchesSafely.

@Override
public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
    // check type
    final JsonNode jsonTypeNode = jsonInstruction.get("type");
    final String jsonType = jsonTypeNode.textValue();
    final String type = instruction.type().name();
    if (!jsonType.equals(type)) {
        description.appendText("type was " + type);
        return false;
    }
    if (instruction instanceof ModMplsHeaderInstruction) {
        return matchModMplsHeaderInstruction(jsonInstruction, description);
    } else if (instruction instanceof OutputInstruction) {
        return matchOutputInstruction(jsonInstruction, description);
    } else if (instruction instanceof GroupInstruction) {
        return matchGroupInstruction(jsonInstruction, description);
    } else if (instruction instanceof MeterInstruction) {
        return matchMeterInstruction(jsonInstruction, description);
    } else if (instruction instanceof SetQueueInstruction) {
        return matchSetQueueInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModOchSignalInstruction) {
        return matchModOchSingalInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModEtherInstruction) {
        return matchModEtherInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModVlanIdInstruction) {
        return matchModVlanIdInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModVlanPcpInstruction) {
        return matchModVlanPcpInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModIPInstruction) {
        return matchModIpInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
        return matchModIPv6FlowLabelInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModMplsLabelInstruction) {
        return matchModMplsLabelInstruction(jsonInstruction, description);
    } else if (instruction instanceof ModOduSignalIdInstruction) {
        return matchModOduSingalIdInstruction(jsonInstruction, description);
    } else if (instruction instanceof PiInstruction) {
        return matchPiInstruction(jsonInstruction, description);
    } else if (instruction instanceof NoActionInstruction) {
        return true;
    }
    return false;
}
Also used : OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) ModOchSignalInstruction(org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction) PiInstruction(org.onosproject.net.flow.instructions.PiInstruction) JsonNode(com.fasterxml.jackson.databind.JsonNode) HexString(org.onlab.util.HexString) ModEtherInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction) ModMplsHeaderInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction) ModIPInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction) ModOduSignalIdInstruction(org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction) SetQueueInstruction(org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction) ModMplsLabelInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction) ModVlanIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) MeterInstruction(org.onosproject.net.flow.instructions.Instructions.MeterInstruction) ModIPv6FlowLabelInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction) ModVlanPcpInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction)

Example 3 with GroupInstruction

use of org.onosproject.net.flow.instructions.Instructions.GroupInstruction in project onos by opennetworkinglab.

the class InstructionJsonMatcher method matchGroupInstruction.

/**
 * Matches the contents of a group instruction.
 *
 * @param instructionJson JSON instruction to match
 * @param description Description object used for recording errors
 * @return true if contents match, false otherwise
 */
private boolean matchGroupInstruction(JsonNode instructionJson, Description description) {
    final String jsonType = instructionJson.get("type").textValue();
    GroupInstruction instructionToMatch = (GroupInstruction) instruction;
    if (!instructionToMatch.type().name().equals(jsonType)) {
        description.appendText("type was " + jsonType);
        return false;
    }
    final int jsonGroupId = instructionJson.get("groupId").intValue();
    if (instructionToMatch.groupId().id() != jsonGroupId) {
        description.appendText("groupId was " + jsonGroupId);
        return false;
    }
    return true;
}
Also used : HexString(org.onlab.util.HexString) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction)

Example 4 with GroupInstruction

use of org.onosproject.net.flow.instructions.Instructions.GroupInstruction in project onos by opennetworkinglab.

the class FlowModBuilderVer13 method buildActions.

private List<OFAction> buildActions(List<Instruction> treatments) {
    if (treatment == null) {
        return Collections.emptyList();
    }
    boolean tableFound = false;
    List<OFAction> actions = new LinkedList<>();
    for (Instruction i : treatments) {
        switch(i.type()) {
            case NOACTION:
                return Collections.emptyList();
            case L0MODIFICATION:
                actions.add(buildL0Modification(i));
                break;
            case L1MODIFICATION:
                actions.add(buildL1Modification(i));
                break;
            case L2MODIFICATION:
                actions.add(buildL2Modification(i));
                break;
            case L3MODIFICATION:
                actions.add(buildL3Modification(i));
                break;
            case L4MODIFICATION:
                actions.add(buildL4Modification(i));
                break;
            case OUTPUT:
                OutputInstruction out = (OutputInstruction) i;
                OFActionOutput.Builder action = factory().actions().buildOutput().setPort(OFPort.of((int) out.port().toLong()));
                if (out.port().equals(PortNumber.CONTROLLER)) {
                    action.setMaxLen(OFPCML_NO_BUFFER);
                }
                actions.add(action.build());
                break;
            case GROUP:
                GroupInstruction group = (GroupInstruction) i;
                OFActionGroup.Builder groupBuilder = factory().actions().buildGroup().setGroup(OFGroup.of(group.groupId().id()));
                actions.add(groupBuilder.build());
                break;
            case QUEUE:
                SetQueueInstruction queue = (SetQueueInstruction) i;
                OFActionSetQueue.Builder queueBuilder = factory().actions().buildSetQueue().setQueueId(queue.queueId());
                actions.add(queueBuilder.build());
                break;
            case TABLE:
                // FIXME: should not occur here.
                tableFound = true;
                break;
            case EXTENSION:
                actions.add(buildExtensionAction(((Instructions.ExtensionInstructionWrapper) i).extensionInstruction()));
                break;
            default:
                log.warn("Instruction type {} not yet implemented.", i.type());
        }
    }
    if (tableFound && actions.isEmpty()) {
        // a goto instruction for the next table
        return Collections.emptyList();
    }
    return actions;
}
Also used : OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) OFActionOutput(org.projectfloodlight.openflow.protocol.action.OFActionOutput) OFActionSetQueue(org.projectfloodlight.openflow.protocol.action.OFActionSetQueue) OFAction(org.projectfloodlight.openflow.protocol.action.OFAction) ModIPv6FlowLabelInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction) ModOchSignalInstruction(org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) OFInstruction(org.projectfloodlight.openflow.protocol.instruction.OFInstruction) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) ModVlanIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction) ModOduSignalIdInstruction(org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction) ModTransportPortInstruction(org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction) ModEtherInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction) ModTunnelIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction) L4ModificationInstruction(org.onosproject.net.flow.instructions.L4ModificationInstruction) ModMplsLabelInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction) ModIPInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction) ModArpIPInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction) ModVlanPcpInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction) L0ModificationInstruction(org.onosproject.net.flow.instructions.L0ModificationInstruction) ModVlanHeaderInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanHeaderInstruction) ModMplsBosInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) ModArpEthInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction) ModMplsHeaderInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction) L1ModificationInstruction(org.onosproject.net.flow.instructions.L1ModificationInstruction) ModArpOpInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction) SetQueueInstruction(org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction) OFActionGroup(org.projectfloodlight.openflow.protocol.action.OFActionGroup) LinkedList(java.util.LinkedList) SetQueueInstruction(org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction)

Aggregations

GroupInstruction (org.onosproject.net.flow.instructions.Instructions.GroupInstruction)4 HexString (org.onlab.util.HexString)2 OutputInstruction (org.onosproject.net.flow.instructions.Instructions.OutputInstruction)2 SetQueueInstruction (org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction)2 ModOchSignalInstruction (org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction)2 ModOduSignalIdInstruction (org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction)2 ModEtherInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction)2 ModMplsHeaderInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction)2 ModMplsLabelInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction)2 ModVlanIdInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction)2 ModVlanPcpInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction)2 ModIPInstruction (org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction)2 ModIPv6FlowLabelInstruction (org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 ImmutableList (com.google.common.collect.ImmutableList)1 ArrayDeque (java.util.ArrayDeque)1 ArrayList (java.util.ArrayList)1 Deque (java.util.Deque)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1