Search in sources :

Example 21 with TrafficTreatment

use of org.onosproject.net.flow.TrafficTreatment in project onos by opennetworkinglab.

the class Ofdpa2GroupHandler method processSimpleNextObjective.

/**
 * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
 * a chain of groups. The simple Next Objective passed in by the application
 * is broken up into a group chain. The following chains can be created
 * depending on the parameters in the Next Objective.
 * 1. L2 Interface group (no chaining)
 * 2. L3 Unicast group -> L2 Interface group
 * 3. MPLS Interface group -> L2 Interface group
 * 4. MPLS Swap group -> MPLS Interface group -> L2 Interface group
 * 5. PW initiation group chain
 *
 * @param nextObj  the nextObjective of type SIMPLE
 */
private void processSimpleNextObjective(NextObjective nextObj) {
    TrafficTreatment treatment = nextObj.next().iterator().next();
    // determine if plain L2 or L3->L2 or MPLS Swap -> MPLS Interface -> L2
    boolean plainL2 = true;
    boolean mplsSwap = false;
    MplsLabel mplsLabel = null;
    for (Instruction ins : treatment.allInstructions()) {
        if (ins.type() == Instruction.Type.L2MODIFICATION) {
            L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
            if (l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_DST || l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_SRC) {
                plainL2 = false;
            }
            // a MPLS Swap group before the MPLS Interface Group
            if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_LABEL) {
                mplsSwap = true;
                mplsLabel = ((L2ModificationInstruction.ModMplsLabelInstruction) l2ins).label();
            }
        }
    }
    if (plainL2) {
        createL2InterfaceGroup(nextObj);
        return;
    }
    // In order to understand if it is a pseudowire related
    // next objective we look for the tunnel id in the meta.
    boolean isPw = false;
    if (nextObj.meta() != null) {
        TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) nextObj.meta().getCriterion(TUNNEL_ID);
        if (tunnelIdCriterion != null) {
            isPw = true;
        }
    }
    if (mplsSwap && !isPw) {
        log.debug("Creating a MPLS Swap -> MPLS Interface -> L2 Interface group chain.");
        // break up simple next objective to GroupChain objects
        GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(), nextObj.appId(), true, nextObj.meta());
        if (groupInfo == null) {
            log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
            fail(nextObj, ObjectiveError.BADPARAMS);
            return;
        }
        Deque<GroupKey> gkeyChain = new ArrayDeque<>();
        // l2 interface
        gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
        // mpls interface
        gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
        // creating the mpls swap group and adding it to the chain
        int nextGid = groupInfo.nextGroupDesc().givenGroupId();
        int index = getNextAvailableIndex();
        GroupDescription swapGroupDescription = createMplsSwap(nextGid, OfdpaMplsGroupSubType.MPLS_SWAP_LABEL, index, mplsLabel, nextObj.appId());
        // ensure swap group is added after L2L3 chain
        GroupKey swapGroupKey = swapGroupDescription.appCookie();
        GroupChainElem swapChainElem = new GroupChainElem(swapGroupDescription, 1, false, deviceId);
        updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), swapChainElem);
        gkeyChain.addFirst(swapGroupKey);
        // ensure nextObjective waits on the outermost groupKey
        List<Deque<GroupKey>> allGroupKeys = Lists.newArrayList();
        allGroupKeys.add(gkeyChain);
        OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
        updatePendingNextObjective(swapGroupKey, ofdpaGrp);
        // now we are ready to send the l2 groupDescription (inner), as all the stores
        // that will get async replies have been updated. By waiting to update
        // the stores, we prevent nasty race conditions.
        groupService.addGroup(groupInfo.innerMostGroupDesc());
    } else if (!isPw) {
        boolean isMpls = false;
        if (nextObj.meta() != null) {
            isMpls = isNotMplsBos(nextObj.meta());
        }
        log.debug("Creating a {} -> L2 Interface group chain.", (isMpls) ? "MPLS Interface" : "L3 Unicast");
        // break up simple next objective to GroupChain objects
        GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(), nextObj.appId(), isMpls, nextObj.meta());
        if (groupInfo == null) {
            log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
            fail(nextObj, ObjectiveError.BADPARAMS);
            return;
        }
        // create object for local and distributed storage
        Deque<GroupKey> gkeyChain = new ArrayDeque<>();
        gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
        gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
        List<Deque<GroupKey>> allGroupKeys = Lists.newArrayList();
        allGroupKeys.add(gkeyChain);
        OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
        // store l3groupkey with the ofdpaNextGroup for the nextObjective that depends on it
        updatePendingNextObjective(groupInfo.nextGroupDesc().appCookie(), ofdpaGrp);
        // now we are ready to send the l2 groupDescription (inner), as all the stores
        // that will get async replies have been updated. By waiting to update
        // the stores, we prevent nasty race conditions.
        groupService.addGroup(groupInfo.innerMostGroupDesc());
    } else {
        // We handle the pseudo wire with a different a procedure.
        // This procedure is meant to handle both initiation and
        // termination of the pseudo wire.
        processPwNextObjective(nextObj);
    }
}
Also used : TunnelIdCriterion(org.onosproject.net.flow.criteria.TunnelIdCriterion) GroupKey(org.onosproject.net.group.GroupKey) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) OfdpaGroupHandlerUtility.l2MulticastGroupKey(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque) ArrayDeque(java.util.ArrayDeque) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) GroupDescription(org.onosproject.net.group.GroupDescription) MplsLabel(org.onlab.packet.MplsLabel) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList)

Example 22 with TrafficTreatment

use of org.onosproject.net.flow.TrafficTreatment in project onos by opennetworkinglab.

the class Ofdpa2GroupHandler method removeBucket.

/**
 * Removes top-level buckets from a group that represents the given next objective.
 *
 * @param chainsToRemove a list of group bucket chains to remove
 * @param nextObjective the next objective that contains information for the
 *                  buckets to be removed from the group
 */
protected void removeBucket(List<Deque<GroupKey>> chainsToRemove, NextObjective nextObjective) {
    List<GroupBucket> bucketsToRemove = Lists.newArrayList();
    // first group key is the one we want to modify
    GroupKey modGroupKey = chainsToRemove.get(0).peekFirst();
    Group modGroup = groupService.getGroup(deviceId, modGroupKey);
    if (modGroup == null) {
        log.warn("removeBucket(): Attempt to modify non-existent group {} for device {}", modGroupKey, deviceId);
        return;
    }
    for (Deque<GroupKey> foundChain : chainsToRemove) {
        // second group key is the one we wish to remove the reference to
        if (foundChain.size() < 2) {
            // additional check to make sure second group key exists in
            // the chain.
            log.warn("Can't find second group key from chain {}", foundChain);
            continue;
        }
        GroupKey pointedGroupKey = foundChain.stream().collect(Collectors.toList()).get(1);
        Group pointedGroup = groupService.getGroup(deviceId, pointedGroupKey);
        if (pointedGroup == null) {
            continue;
        }
        GroupBucket bucket;
        if (nextObjective.type() == NextObjective.Type.HASHED) {
            bucket = DefaultGroupBucket.createSelectGroupBucket(DefaultTrafficTreatment.builder().group(pointedGroup.id()).build());
        } else {
            bucket = DefaultGroupBucket.createAllGroupBucket(DefaultTrafficTreatment.builder().group(pointedGroup.id()).build());
        }
        bucketsToRemove.add(bucket);
    }
    GroupBuckets removeBuckets = new GroupBuckets(bucketsToRemove);
    // for debug log
    List<String> pointedGroupIds;
    pointedGroupIds = bucketsToRemove.stream().map(GroupBucket::treatment).map(TrafficTreatment::allInstructions).flatMap(List::stream).filter(inst -> inst instanceof Instructions.GroupInstruction).map(inst -> (Instructions.GroupInstruction) inst).map(Instructions.GroupInstruction::groupId).map(GroupId::id).map(Integer::toHexString).map(id -> HEX_PREFIX + id).collect(Collectors.toList());
    log.debug("Removing buckets from group id 0x{} pointing to group id(s) {} " + "for next id {} in device {}", Integer.toHexString(modGroup.id().id()), pointedGroupIds, nextObjective.id(), deviceId);
    addPendingUpdateNextObjective(modGroupKey, nextObjective);
    groupService.removeBucketsFromGroup(deviceId, modGroupKey, removeBuckets, modGroupKey, nextObjective.appId());
    // potentially stale copy of allActiveKeys
    synchronized (flowObjectiveStore) {
        // get a fresh copy of what the store holds
        NextGroup next = flowObjectiveStore.getNextGroup(nextObjective.id());
        List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
        allActiveKeys = Lists.newArrayList(allActiveKeys);
        // Note that since we got a new object, and ArrayDeque does not implement
        // Object.equals(), we have to check the deque elems one by one
        allActiveKeys.removeIf(active -> chainsToRemove.stream().anyMatch(remove -> Arrays.equals(remove.toArray(new GroupKey[0]), active.toArray(new GroupKey[0]))));
        // top level group which still exists.
        if (allActiveKeys.isEmpty()) {
            ArrayDeque<GroupKey> top = new ArrayDeque<>();
            top.add(modGroupKey);
            allActiveKeys.add(top);
        }
        flowObjectiveStore.putNextGroup(nextObjective.id(), new OfdpaNextGroup(allActiveKeys, nextObjective));
    }
}
Also used : Arrays(java.util.Arrays) TUNNEL_ID(org.onosproject.net.flow.criteria.Criterion.Type.TUNNEL_ID) AtomicCounter(org.onosproject.store.service.AtomicCounter) OfdpaPipelineUtility(org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility) PortNumber(org.onosproject.net.PortNumber) Tools.groupedThreads(org.onlab.util.Tools.groupedThreads) Operation(org.onosproject.net.flowobjective.Objective.Operation) DefaultNextObjective(org.onosproject.net.flowobjective.DefaultNextObjective) PortCriterion(org.onosproject.net.flow.criteria.PortCriterion) ServiceDirectory(org.onlab.osgi.ServiceDirectory) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) ObjectiveError(org.onosproject.net.flowobjective.ObjectiveError) INDIRECT(org.onosproject.net.group.GroupDescription.Type.INDIRECT) StorageService(org.onosproject.store.service.StorageService) GroupListener(org.onosproject.net.group.GroupListener) ApplicationId(org.onosproject.core.ApplicationId) NextObjective(org.onosproject.net.flowobjective.NextObjective) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) IN_PORT(org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT) SELECT(org.onosproject.net.group.GroupDescription.Type.SELECT) ALL(org.onosproject.net.group.GroupDescription.Type.ALL) PipelinerContext(org.onosproject.net.behaviour.PipelinerContext) VLAN_VID(org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) FlowObjectiveStore(org.onosproject.net.flowobjective.FlowObjectiveStore) GroupEvent(org.onosproject.net.group.GroupEvent) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Executors(java.util.concurrent.Executors) Objects(java.util.Objects) L2_MULTICAST_TYPE(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_MULTICAST_TYPE) List(java.util.List) ObjectiveContext(org.onosproject.net.flowobjective.ObjectiveContext) GroupBuckets(org.onosproject.net.group.GroupBuckets) Optional(java.util.Optional) CacheBuilder(com.google.common.cache.CacheBuilder) DeviceId(org.onosproject.net.DeviceId) Ofdpa2Pipeline(org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline) TunnelIdCriterion(org.onosproject.net.flow.criteria.TunnelIdCriterion) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) GroupDescription(org.onosproject.net.group.GroupDescription) IpPrefix(org.onlab.packet.IpPrefix) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) OfdpaSetAllowVlanTranslation(org.onosproject.driver.extensions.OfdpaSetAllowVlanTranslation) NextTreatment(org.onosproject.net.flowobjective.NextTreatment) OfdpaSetVlanVid(org.onosproject.driver.extensions.OfdpaSetVlanVid) DefaultNextTreatment(org.onosproject.net.flowobjective.DefaultNextTreatment) GroupBucket(org.onosproject.net.group.GroupBucket) NextGroup(org.onosproject.net.behaviour.NextGroup) GroupKey(org.onosproject.net.group.GroupKey) Deque(java.util.Deque) Group(org.onosproject.net.group.Group) ArrayList(java.util.ArrayList) Lists(com.google.common.collect.Lists) TrafficSelector(org.onosproject.net.flow.TrafficSelector) ImmutableList(com.google.common.collect.ImmutableList) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) OfdpaGroupHandlerUtility.l2MulticastGroupKey(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) OfdpaGroupHandlerUtility(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility) Criterion(org.onosproject.net.flow.criteria.Criterion) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) RemovalNotification(com.google.common.cache.RemovalNotification) Ofdpa3AllowVlanTranslationType(org.onosproject.driver.extensions.Ofdpa3AllowVlanTranslationType) Instructions(org.onosproject.net.flow.instructions.Instructions) Logger(org.slf4j.Logger) MplsLabel(org.onlab.packet.MplsLabel) Instruction(org.onosproject.net.flow.instructions.Instruction) VlanId(org.onlab.packet.VlanId) GroupService(org.onosproject.net.group.GroupService) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction) DefaultGroupBucket(org.onosproject.net.group.DefaultGroupBucket) IdNextTreatment(org.onosproject.net.flowobjective.IdNextTreatment) TimeUnit(java.util.concurrent.TimeUnit) RemovalCause(com.google.common.cache.RemovalCause) GroupId(org.onosproject.core.GroupId) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion) LoggerFactory.getLogger(org.slf4j.LoggerFactory.getLogger) MacAddress(org.onlab.packet.MacAddress) Cache(com.google.common.cache.Cache) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) NextGroup(org.onosproject.net.behaviour.NextGroup) 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) Instructions(org.onosproject.net.flow.instructions.Instructions) GroupBuckets(org.onosproject.net.group.GroupBuckets) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque) 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) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction)

Example 23 with TrafficTreatment

use of org.onosproject.net.flow.TrafficTreatment in project onos by opennetworkinglab.

the class Ofdpa2Pipeline method processEthDstSpecific.

/**
 * Handles forwarding rules to the L2 bridging table. Flow actions are not
 * allowed in the bridging table - instead we use L2 Interface group or
 * L2 flood group
 *
 * @param fwd the forwarding objective
 * @return A collection of flow rules, or an empty set
 */
protected Collection<FlowRule> processEthDstSpecific(ForwardingObjective fwd) {
    List<FlowRule> rules = new ArrayList<>();
    // Build filtered selector
    TrafficSelector selector = fwd.selector();
    EthCriterion ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST);
    VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID);
    if (vlanIdCriterion == null) {
        log.warn("Forwarding objective for bridging requires vlan. Not " + "installing fwd:{} in dev:{}", fwd.id(), deviceId);
        fail(fwd, ObjectiveError.BADPARAMS);
        return Collections.emptySet();
    }
    TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder();
    if (!ethCriterion.mac().equals(NONE) && !ethCriterion.mac().equals(BROADCAST)) {
        filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
        log.debug("processing L2 forwarding objective:{} -> next:{} in dev:{}", fwd.id(), fwd.nextId(), deviceId);
    } else {
        // Use wildcard DST_MAC if the MacAddress is None or Broadcast
        log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} " + "in dev:{} for vlan:{}", fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId());
    }
    if (requireVlanExtensions()) {
        OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vlanIdCriterion.vlanId());
        filteredSelectorBuilder.extension(ofdpaMatchVlanVid, deviceId);
    } else {
        filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
    }
    TrafficSelector filteredSelector = filteredSelectorBuilder.build();
    if (fwd.treatment() != null) {
        log.warn("Ignoring traffic treatment in fwd rule {} meant for L2 table" + "for dev:{}. Expecting only nextId", fwd.id(), deviceId);
    }
    TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
    if (fwd.nextId() != null) {
        NextGroup next = getGroupForNextObjective(fwd.nextId());
        if (next != null) {
            List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
            // we only need the top level group's key to point the flow to it
            Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
            if (group != null) {
                treatmentBuilder.deferred().group(group.id());
            } else {
                log.warn("Group with key:{} for next-id:{} not found in dev:{}", gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
                fail(fwd, ObjectiveError.GROUPMISSING);
                return Collections.emptySet();
            }
        }
    }
    treatmentBuilder.immediate().transition(ACL_TABLE);
    TrafficTreatment filteredTreatment = treatmentBuilder.build();
    // Build bridging table entries
    FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
    flowRuleBuilder.fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector).withTreatment(filteredTreatment).forTable(BRIDGING_TABLE);
    if (fwd.permanent()) {
        flowRuleBuilder.makePermanent();
    } else {
        flowRuleBuilder.makeTemporary(fwd.timeout());
    }
    rules.add(flowRuleBuilder.build());
    return rules;
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) EthCriterion(org.onosproject.net.flow.criteria.EthCriterion) ArrayList(java.util.ArrayList) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) ArrayDeque(java.util.ArrayDeque) Deque(java.util.Deque) OfdpaMatchVlanVid(org.onosproject.driver.extensions.OfdpaMatchVlanVid) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion)

Example 24 with TrafficTreatment

use of org.onosproject.net.flow.TrafficTreatment in project onos by opennetworkinglab.

the class Ofdpa3GroupHandler method processPwNextObjective.

@Override
protected void processPwNextObjective(NextObjective nextObjective) {
    log.info("Started deploying nextObjective id={} for pseudowire", nextObjective.id());
    TrafficTreatment treatment = nextObjective.next().iterator().next();
    Deque<GroupKey> gkeyChain = new ArrayDeque<>();
    GroupChainElem groupChainElem;
    GroupKey groupKey;
    GroupDescription groupDescription;
    // Now we separate the mpls actions from the l2/l3 actions
    TrafficTreatment.Builder l2L3Treatment = DefaultTrafficTreatment.builder();
    TrafficTreatment.Builder mplsTreatment = DefaultTrafficTreatment.builder();
    createL2L3AndMplsTreatments(treatment, l2L3Treatment, mplsTreatment);
    // We create the chain from mpls intf group to
    // l2 intf group.
    GroupInfo groupInfo = createL2L3ChainInternal(l2L3Treatment.build(), nextObjective.id(), nextObjective.appId(), true, nextObjective.meta(), false);
    if (groupInfo == null) {
        log.error("Could not process nextObj={} in dev:{}", nextObjective.id(), deviceId);
        OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED);
        return;
    }
    // We update the chain with the last two groups;
    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();
    L3ModificationInstruction l3Ins;
    for (Instruction ins : treatment.allInstructions()) {
        // Each mpls instruction set is delimited by a
        // copy ttl outward action.
        mplsInstructionSet.add(ins);
        if (ins.type() == Instruction.Type.L3MODIFICATION) {
            l3Ins = (L3ModificationInstruction) ins;
            if (l3Ins.subtype() == TTL_OUT) {
                mplsInstructionSets.add(mplsInstructionSet);
                mplsInstructionSet = Lists.newArrayList();
            }
        }
    }
    if (mplsInstructionSets.size() > MAX_DEPTH_UNPROTECTED_PW) {
        log.error("Next Objective for pseudo wire should have at " + "most {} mpls instruction sets. Next Objective Id:{}", MAX_DEPTH_UNPROTECTED_PW, nextObjective.id());
        OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.BADPARAMS);
        return;
    }
    log.debug("Size of mpls instructions is {}.", mplsInstructionSets.size());
    log.debug("mpls instructions sets are {}.", mplsInstructionSets);
    int nextGid = groupInfo.nextGroupDesc().givenGroupId();
    int index;
    // this is for inter-co pws
    if (mplsInstructionSets.size() == MAX_DEPTH_UNPROTECTED_PW) {
        log.debug("Creating inter-co pw mpls chains with nextid {}", nextObjective.id());
        // We deal with the label 2 group.
        index = getNextAvailableIndex();
        groupDescription = createMplsTunnelLabelGroup(nextGid, OfdpaMplsGroupSubType.MPLS_TUNNEL_LABEL_2, index, mplsInstructionSets.get(2), nextObjective.appId());
        groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
        // We update the chain.
        groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
        updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
        gkeyChain.addFirst(groupKey);
        // We have to create tunnel label group and
        // l2 vpn group before to send the inner most
        // group. We update the nextGid.
        nextGid = groupDescription.givenGroupId();
        groupInfo = new GroupInfo(groupInfo.innerMostGroupDesc(), groupDescription);
        log.debug("Trying Label 2 Group: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(nextGid), groupKey, nextObjective.id());
    }
    // inside a single co
    if (mplsInstructionSets.size() == 2) {
        log.debug("Creating leaf-leaf pw mpls chains with nextid {}", nextObjective.id());
        // We deal with the label 1 group.
        index = getNextAvailableIndex();
        groupDescription = createMplsTunnelLabelGroup(nextGid, OfdpaMplsGroupSubType.MPLS_TUNNEL_LABEL_1, index, mplsInstructionSets.get(1), nextObjective.appId());
        groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
        groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
        updatePendingGroups(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.innerMostGroupDesc(), groupDescription);
        log.debug("Trying Label 1 Group: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(nextGid), groupKey, nextObjective.id());
        // Finally we create the l2 vpn group.
        index = getNextAvailableIndex();
        groupDescription = createMplsL2VpnGroup(nextGid, index, mplsInstructionSets.get(0), nextObjective.appId());
        groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
        groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
        updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
        gkeyChain.addFirst(groupKey);
        OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(Collections.singletonList(gkeyChain), nextObjective);
        updatePendingNextObjective(groupKey, ofdpaGrp);
        log.debug("Trying L2 Vpn Group: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(nextGid), groupKey, nextObjective.id());
        // Finally we send the innermost group.
        log.debug("Sending innermost group {} in group chain on device {} ", Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
        groupService.addGroup(groupInfo.innerMostGroupDesc());
    }
    // only one label is used
    if (mplsInstructionSets.size() == 1) {
        log.debug("Creating leaf-spine pw mpls chains with nextid {}", nextObjective.id());
        // Finally we create the l2 vpn group.
        index = getNextAvailableIndex();
        groupDescription = createMplsL2VpnGroup(nextGid, index, mplsInstructionSets.get(0), nextObjective.appId());
        groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
        groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
        updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
        gkeyChain.addFirst(groupKey);
        OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(Collections.singletonList(gkeyChain), nextObjective);
        updatePendingNextObjective(groupKey, ofdpaGrp);
        log.debug("Trying L2 Vpn Group: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(nextGid), groupKey, nextObjective.id());
        // Finally we send the innermost group.
        log.debug("Sending innermost group {} in group chain on device {} ", Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
        groupService.addGroup(groupInfo.innerMostGroupDesc());
    }
}
Also used : L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) GroupKey(org.onosproject.net.group.GroupKey) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) ArrayDeque(java.util.ArrayDeque) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) GroupDescription(org.onosproject.net.group.GroupDescription) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) List(java.util.List)

Example 25 with TrafficTreatment

use of org.onosproject.net.flow.TrafficTreatment in project onos by opennetworkinglab.

the class OvsOfdpaPipeline method processDoubleTaggedFilter.

/**
 * Configure filtering rules of outer and inner VLAN IDs, and a MAC address.
 * Filtering happens in three tables (VLAN_TABLE, VLAN_1_TABLE, TMAC_TABLE).
 *
 * @param filteringObjective the filtering objective
 * @param install            true to add, false to remove
 * @param applicationId      for application programming this filter
 */
private void processDoubleTaggedFilter(FilteringObjective filteringObjective, boolean install, ApplicationId applicationId) {
    PortCriterion portCriterion = null;
    EthCriterion ethCriterion = null;
    VlanIdCriterion innervidCriterion = null;
    VlanIdCriterion outerVidCriterion = null;
    boolean popVlan = false;
    TrafficTreatment meta = filteringObjective.meta();
    if (!filteringObjective.key().equals(Criteria.dummy()) && filteringObjective.key().type() == Criterion.Type.IN_PORT) {
        portCriterion = (PortCriterion) filteringObjective.key();
    }
    if (portCriterion == null) {
        log.warn("No IN_PORT defined in filtering objective from app: {}" + "Failed to program VLAN tables.", applicationId);
        return;
    } else {
        log.debug("Received filtering objective for dev/port: {}/{}", deviceId, portCriterion.port());
    }
    // meta should have only one instruction, popVlan.
    if (meta != null && meta.allInstructions().size() == 1) {
        L2ModificationInstruction l2Inst = (L2ModificationInstruction) meta.allInstructions().get(0);
        if (l2Inst.subtype().equals(L2ModificationInstruction.L2SubType.VLAN_POP)) {
            popVlan = true;
        } else {
            log.warn("Filtering objective can have only VLAN_POP instruction.");
            return;
        }
    } else {
        log.warn("Filtering objective should have one instruction.");
        return;
    }
    FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
    for (Criterion criterion : filteringObjective.conditions()) {
        switch(criterion.type()) {
            case ETH_DST:
            case ETH_DST_MASKED:
                ethCriterion = (EthCriterion) criterion;
                break;
            case VLAN_VID:
                outerVidCriterion = (VlanIdCriterion) criterion;
                break;
            case INNER_VLAN_VID:
                innervidCriterion = (VlanIdCriterion) criterion;
                break;
            default:
                log.warn("Unsupported filter {}", criterion);
                fail(filteringObjective, ObjectiveError.UNSUPPORTED);
                return;
        }
    }
    if (innervidCriterion == null || outerVidCriterion == null) {
        log.warn("filtering objective should have two vidCriterion.");
        return;
    }
    if (ethCriterion == null || ethCriterion.mac().equals(NONE)) {
        // NOTE: it is possible that a filtering objective only has vidCriterion
        log.warn("filtering objective missing dstMac, cannot program TMAC table");
        return;
    } else {
        MacAddress unicastMac = readEthDstFromTreatment(filteringObjective.meta());
        List<List<FlowRule>> allStages = processEthDstFilter(portCriterion, ethCriterion, innervidCriterion, innervidCriterion.vlanId(), unicastMac, applicationId);
        for (List<FlowRule> flowRules : allStages) {
            log.trace("Starting a new flow rule stage for TMAC table flow");
            ops.newStage();
            for (FlowRule flowRule : flowRules) {
                log.trace("{} flow rules in TMAC table: {} for dev: {}", (install) ? "adding" : "removing", flowRules, deviceId);
                if (install) {
                    ops = ops.add(flowRule);
                } else {
                    // same VLAN on this device if TMAC doesn't support matching on in_port.
                    if (matchInPortTmacTable() || (filteringObjective.meta() != null && filteringObjective.meta().clearedDeferred())) {
                        ops = ops.remove(flowRule);
                    } else {
                        log.debug("Abort TMAC flow removal on {}. Some other ports still share this TMAC flow");
                    }
                }
            }
        }
    }
    List<FlowRule> rules;
    rules = processDoubleVlanIdFilter(portCriterion, innervidCriterion, outerVidCriterion, popVlan, applicationId);
    for (FlowRule flowRule : rules) {
        log.trace("{} flow rule in VLAN table: {} for dev: {}", (install) ? "adding" : "removing", flowRule, deviceId);
        ops = install ? ops.add(flowRule) : ops.remove(flowRule);
    }
    // apply filtering flow rules
    flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {

        @Override
        public void onSuccess(FlowRuleOperations ops) {
            log.debug("Applied {} filtering rules in device {}", ops.stages().get(0).size(), deviceId);
            pass(filteringObjective);
        }

        @Override
        public void onError(FlowRuleOperations ops) {
            log.info("Failed to apply all filtering rules in dev {}", deviceId);
            fail(filteringObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
        }
    }));
}
Also used : FlowRuleOperations(org.onosproject.net.flow.FlowRuleOperations) EthCriterion(org.onosproject.net.flow.criteria.EthCriterion) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) PortCriterion(org.onosproject.net.flow.criteria.PortCriterion) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) MacAddress(org.onlab.packet.MacAddress) MplsBosCriterion(org.onosproject.net.flow.criteria.MplsBosCriterion) PortCriterion(org.onosproject.net.flow.criteria.PortCriterion) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) MplsCriterion(org.onosproject.net.flow.criteria.MplsCriterion) EthCriterion(org.onosproject.net.flow.criteria.EthCriterion) Criterion(org.onosproject.net.flow.criteria.Criterion) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) FlowRuleOperationsContext(org.onosproject.net.flow.FlowRuleOperationsContext) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion)

Aggregations

TrafficTreatment (org.onosproject.net.flow.TrafficTreatment)395 DefaultTrafficTreatment (org.onosproject.net.flow.DefaultTrafficTreatment)369 TrafficSelector (org.onosproject.net.flow.TrafficSelector)257 DefaultTrafficSelector (org.onosproject.net.flow.DefaultTrafficSelector)236 FlowRule (org.onosproject.net.flow.FlowRule)93 DefaultFlowRule (org.onosproject.net.flow.DefaultFlowRule)86 PiAction (org.onosproject.net.pi.runtime.PiAction)79 Test (org.junit.Test)78 PortNumber (org.onosproject.net.PortNumber)70 PiActionParam (org.onosproject.net.pi.runtime.PiActionParam)56 Instruction (org.onosproject.net.flow.instructions.Instruction)52 DeviceId (org.onosproject.net.DeviceId)46 NextObjective (org.onosproject.net.flowobjective.NextObjective)45 ConnectPoint (org.onosproject.net.ConnectPoint)44 List (java.util.List)43 ForwardingObjective (org.onosproject.net.flowobjective.ForwardingObjective)43 Ethernet (org.onlab.packet.Ethernet)40 Criterion (org.onosproject.net.flow.criteria.Criterion)39 GroupBucket (org.onosproject.net.group.GroupBucket)39 DefaultGroupDescription (org.onosproject.net.group.DefaultGroupDescription)37