Search in sources :

Example 21 with TrafficSelector

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

the class Ofdpa2GroupHandler method createEcmpHashBucketChains.

/**
 * Creates group chains for all buckets in a hashed group, and stores the
 * GroupInfos and GroupKeys for all the groups in the lists passed in, which
 * should be empty.
 * <p>
 * Does not create the top level ECMP group. Does not actually send the
 * groups to the groupService.
 *
 * @param nextObj  the Next Objective with buckets that need to be converted
 *                  to group chains
 * @param allGroupKeys  a list to store groupKey for each bucket-group-chain
 * @param unsentGroups  a list to store GroupInfo for each bucket-group-chain
 */
protected void createEcmpHashBucketChains(NextObjective nextObj, List<Deque<GroupKey>> allGroupKeys, List<GroupInfo> unsentGroups) {
    // break up hashed next objective to multiple groups
    Collection<TrafficTreatment> buckets = nextObj.next();
    for (TrafficTreatment bucket : buckets) {
        // figure out how many labels are pushed in each bucket
        int labelsPushed = 0;
        MplsLabel innermostLabel = null;
        for (Instruction ins : bucket.allInstructions()) {
            if (ins.type() == Instruction.Type.L2MODIFICATION) {
                L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
                if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_PUSH) {
                    labelsPushed++;
                }
                if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_LABEL) {
                    if (innermostLabel == null) {
                        innermostLabel = ((L2ModificationInstruction.ModMplsLabelInstruction) l2ins).label();
                    }
                }
            }
        }
        Deque<GroupKey> gKeyChain = new ArrayDeque<>();
        // here we only deal with 0 and 1 label push
        if (labelsPushed == 0) {
            GroupInfo noLabelGroupInfo;
            TrafficSelector metaSelector = nextObj.meta();
            if (metaSelector != null) {
                if (isNotMplsBos(metaSelector)) {
                    noLabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), true, nextObj.meta());
                } else {
                    noLabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), false, nextObj.meta());
                }
            } else {
                noLabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), false, nextObj.meta());
            }
            if (noLabelGroupInfo == null) {
                log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
                return;
            }
            gKeyChain.addFirst(noLabelGroupInfo.innerMostGroupDesc().appCookie());
            gKeyChain.addFirst(noLabelGroupInfo.nextGroupDesc().appCookie());
            // we can't send the inner group description yet, as we have to
            // create the dependent ECMP group first. So we store..
            unsentGroups.add(noLabelGroupInfo);
        } else if (labelsPushed == 1) {
            GroupInfo onelabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), nextObj.appId(), true, nextObj.meta());
            if (onelabelGroupInfo == null) {
                log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
                return;
            }
            // we need to add another group to this chain - the L3VPN group
            TrafficTreatment.Builder l3vpnTtb = DefaultTrafficTreatment.builder();
            if (requireVlanPopBeforeMplsPush()) {
                l3vpnTtb.popVlan();
            }
            l3vpnTtb.pushMpls().setMpls(innermostLabel).group(new GroupId(onelabelGroupInfo.nextGroupDesc().givenGroupId()));
            if (supportCopyTtl()) {
                l3vpnTtb.copyTtlOut();
            }
            if (supportSetMplsBos()) {
                l3vpnTtb.setMplsBos(true);
            }
            if (requireVlanPopBeforeMplsPush()) {
                l3vpnTtb.pushVlan().setVlanId(VlanId.vlanId(VlanId.RESERVED));
            }
            GroupBucket l3vpnGrpBkt = DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build());
            int l3vpnIndex = getNextAvailableIndex();
            int l3vpnGroupId = MPLS_L3VPN_SUBTYPE | (SUBTYPE_MASK & l3vpnIndex);
            GroupKey l3vpnGroupKey = new DefaultGroupKey(appKryo.serialize(l3vpnIndex));
            GroupDescription l3vpnGroupDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l3vpnGrpBkt)), l3vpnGroupKey, l3vpnGroupId, nextObj.appId());
            GroupChainElem l3vpnGce = new GroupChainElem(l3vpnGroupDesc, 1, false, deviceId);
            updatePendingGroups(onelabelGroupInfo.nextGroupDesc().appCookie(), l3vpnGce);
            gKeyChain.addFirst(onelabelGroupInfo.innerMostGroupDesc().appCookie());
            gKeyChain.addFirst(onelabelGroupInfo.nextGroupDesc().appCookie());
            gKeyChain.addFirst(l3vpnGroupKey);
            // now we can replace the outerGrpDesc with the one we just created
            onelabelGroupInfo.nextGroupDesc(l3vpnGroupDesc);
            // we can't send the innermost group yet, as we have to create
            // the dependent ECMP group first. So we store ...
            unsentGroups.add(onelabelGroupInfo);
            log.debug("Trying L3VPN: device:{} gid:{} group key:{} nextId:{}", deviceId, Integer.toHexString(l3vpnGroupId), l3vpnGroupKey, nextObj.id());
        } else {
            log.warn("Driver currently does not handle more than 1 MPLS " + "labels. Not processing nextObjective {}", nextObj.id());
            return;
        }
        // all groups in this chain
        allGroupKeys.add(gKeyChain);
    }
}
Also used : CacheBuilder(com.google.common.cache.CacheBuilder) 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) GroupBuckets(org.onosproject.net.group.GroupBuckets) ArrayDeque(java.util.ArrayDeque) GroupId(org.onosproject.core.GroupId) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) GroupDescription(org.onosproject.net.group.GroupDescription) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) MplsLabel(org.onlab.packet.MplsLabel) TrafficSelector(org.onosproject.net.flow.TrafficSelector) GroupBucket(org.onosproject.net.group.GroupBucket) DefaultGroupBucket(org.onosproject.net.group.DefaultGroupBucket) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription)

Example 22 with TrafficSelector

use of org.onosproject.net.flow.TrafficSelector 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 23 with TrafficSelector

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

the class Ofdpa2Pipeline method buildIpv6Selector.

/**
 * Helper method to build Ipv6 selector using the selector provided by
 * a forwarding objective.
 *
 * @param builderToUpdate the builder to update
 * @param fwd the selector to read
 * @return 0 if the update ends correctly. -1 if the matches
 * are not yet supported
 */
int buildIpv6Selector(TrafficSelector.Builder builderToUpdate, ForwardingObjective fwd) {
    TrafficSelector selector = fwd.selector();
    IpPrefix ipv6Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
    if (ipv6Dst.isMulticast()) {
        if (ipv6Dst.prefixLength() != IpAddress.INET6_BIT_LENGTH) {
            log.warn("Multicast specific forwarding objective can only be /128");
            fail(fwd, ObjectiveError.BADPARAMS);
            return -1;
        }
        VlanId assignedVlan = readVlanFromSelector(fwd.meta());
        if (assignedVlan == null) {
            log.warn("VLAN ID required by multicast specific fwd obj is missing. Abort.");
            fail(fwd, ObjectiveError.BADPARAMS);
            return -1;
        }
        if (requireVlanExtensions()) {
            OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(assignedVlan);
            builderToUpdate.extension(ofdpaMatchVlanVid, deviceId);
        } else {
            builderToUpdate.matchVlanId(assignedVlan);
        }
        builderToUpdate.matchEthType(Ethernet.TYPE_IPV6).matchIPv6Dst(ipv6Dst);
        log.debug("processing IPv6 multicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
    } else {
        if (ipv6Dst.prefixLength() != 0) {
            builderToUpdate.matchIPv6Dst(ipv6Dst);
        }
        builderToUpdate.matchEthType(Ethernet.TYPE_IPV6);
        log.debug("processing IPv6 unicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
    }
    return 0;
}
Also used : IpPrefix(org.onlab.packet.IpPrefix) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) VlanId(org.onlab.packet.VlanId) OfdpaMatchVlanVid(org.onosproject.driver.extensions.OfdpaMatchVlanVid)

Example 24 with TrafficSelector

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

the class Ofdpa2Pipeline method buildIpv4Selector.

private int buildIpv4Selector(TrafficSelector.Builder builderToUpdate, TrafficSelector.Builder extBuilder, ForwardingObjective fwd, boolean allowDefaultRoute) {
    TrafficSelector selector = fwd.selector();
    IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
    if (ipv4Dst.isMulticast()) {
        if (ipv4Dst.prefixLength() != 32) {
            log.warn("Multicast specific forwarding objective can only be /32");
            fail(fwd, ObjectiveError.BADPARAMS);
            return -1;
        }
        VlanId assignedVlan = readVlanFromSelector(fwd.meta());
        if (assignedVlan == null) {
            log.warn("VLAN ID required by multicast specific fwd obj is missing. Abort.");
            fail(fwd, ObjectiveError.BADPARAMS);
            return -1;
        }
        if (requireVlanExtensions()) {
            OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(assignedVlan);
            builderToUpdate.extension(ofdpaMatchVlanVid, deviceId);
        } else {
            builderToUpdate.matchVlanId(assignedVlan);
        }
        builderToUpdate.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
        log.debug("processing IPv4 multicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
    } else {
        if (ipv4Dst.prefixLength() == 0) {
            if (allowDefaultRoute) {
                // The entire IPV4_DST field is wildcarded intentionally
                builderToUpdate.matchEthType(Ethernet.TYPE_IPV4);
            } else {
                // NOTE: The switch does not support matching 0.0.0.0/0
                // Split it into 0.0.0.0/1 and 128.0.0.0/1
                builderToUpdate.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(IpPrefix.valueOf("0.0.0.0/1"));
                extBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(IpPrefix.valueOf("128.0.0.0/1"));
            }
        } else {
            builderToUpdate.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
        }
        log.debug("processing IPv4 unicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
    }
    return 0;
}
Also used : IpPrefix(org.onlab.packet.IpPrefix) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) VlanId(org.onlab.packet.VlanId) OfdpaMatchVlanVid(org.onosproject.driver.extensions.OfdpaMatchVlanVid)

Example 25 with TrafficSelector

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

the class Ofdpa2Pipeline method processEthTypeSpecificInternal.

/**
 * Internal implementation of processEthTypeSpecific.
 * <p>
 * Wildcarded IPv4_DST is not supported in OFDPA i12. Therefore, we break
 * the rule into 0.0.0.0/1 and 128.0.0.0/1.
 * The allowDefaultRoute must be set to false for OFDPA i12.
 * </p>
 *
 * @param fwd the forwarding objective
 * @param allowDefaultRoute allow wildcarded IPv4_DST or not
 * @param mplsNextTable next MPLS table
 * @return A collection of flow rules, or an empty set
 */
protected Collection<FlowRule> processEthTypeSpecificInternal(ForwardingObjective fwd, boolean allowDefaultRoute, int mplsNextTable) {
    TrafficSelector selector = fwd.selector();
    EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
    boolean emptyGroup = false;
    int forTableId;
    TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
    TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
    TrafficSelector.Builder complementarySelector = DefaultTrafficSelector.builder();
    if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
        if (buildIpv4Selector(filteredSelector, complementarySelector, fwd, allowDefaultRoute) < 0) {
            return Collections.emptyList();
        }
        // We need to set properly the next table
        IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
        if (ipv4Dst.isMulticast()) {
            forTableId = MULTICAST_ROUTING_TABLE;
        } else {
            forTableId = UNICAST_ROUTING_TABLE;
        }
    // TODO decrementing IP ttl is done automatically for routing, this
    // action is ignored or rejected in ofdpa as it is not fully implemented
    // if (fwd.treatment() != null) {
    // for (Instruction instr : fwd.treatment().allInstructions()) {
    // if (instr instanceof L3ModificationInstruction &&
    // ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
    // tb.deferred().add(instr);
    // }
    // }
    // }
    } else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV6) {
        if (buildIpv6Selector(filteredSelector, fwd) < 0) {
            return Collections.emptyList();
        }
        // We need to set the proper next table
        IpPrefix ipv6Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
        if (ipv6Dst.isMulticast()) {
            forTableId = MULTICAST_ROUTING_TABLE;
        } else {
            forTableId = UNICAST_ROUTING_TABLE;
        }
    // TODO decrementing IP ttl is done automatically for routing, this
    // action is ignored or rejected in ofdpa as it is not fully implemented
    // if (fwd.treatment() != null) {
    // for (Instruction instr : fwd.treatment().allInstructions()) {
    // if (instr instanceof L3ModificationInstruction &&
    // ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
    // tb.deferred().add(instr);
    // }
    // }
    // }
    } else {
        filteredSelector.matchEthType(Ethernet.MPLS_UNICAST).matchMplsLabel(((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
        MplsBosCriterion bos = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
        if (bos != null && requireMplsBosMatch()) {
            filteredSelector.matchMplsBos(bos.mplsBos());
        }
        forTableId = MPLS_TABLE_1;
        log.debug("processing MPLS specific forwarding objective {} -> next:{}" + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
        if (fwd.treatment() != null) {
            for (Instruction instr : fwd.treatment().allInstructions()) {
                if (instr instanceof L2ModificationInstruction && ((L2ModificationInstruction) instr).subtype() == L2SubType.MPLS_POP) {
                    // setting the MPLS_TYPE so pop can happen down the pipeline
                    if (requireMplsPop()) {
                        if (mplsNextTable == MPLS_TYPE_TABLE && isNotMplsBos(selector)) {
                            tb.immediate().popMpls();
                        }
                    } else {
                        // Skip mpls pop action for mpls_unicast label
                        if (instr instanceof ModMplsHeaderInstruction && !((ModMplsHeaderInstruction) instr).ethernetType().equals(EtherType.MPLS_UNICAST.ethType())) {
                            tb.immediate().add(instr);
                        }
                    }
                }
                if (requireMplsTtlModification()) {
                    if (instr instanceof L3ModificationInstruction && ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
                        // FIXME Should modify the app to send the correct DEC_MPLS_TTL instruction
                        tb.immediate().decMplsTtl();
                    }
                    if (instr instanceof L3ModificationInstruction && ((L3ModificationInstruction) instr).subtype() == L3SubType.TTL_IN) {
                        tb.immediate().add(instr);
                    }
                }
            }
        }
    }
    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) {
                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();
            }
            if (isNotMplsBos(selector) && group.type().equals(SELECT)) {
                log.warn("SR CONTINUE case cannot be handled as MPLS ECMP " + "is not implemented in OF-DPA yet. Aborting flow {} -> next:{} " + "in this device {}", fwd.id(), fwd.nextId(), deviceId);
                fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
                return Collections.emptySet();
            }
            tb.deferred().group(group.id());
            // retrying flows may be necessary due to bug CORD-554
            if (gkeys.size() == 1 && gkeys.get(0).size() == 1) {
                if (shouldRetry()) {
                    log.warn("Found empty group 0x{} in dev:{} .. will retry fwd:{}", Integer.toHexString(group.id().id()), deviceId, fwd.id());
                    emptyGroup = true;
                }
            }
        } else {
            log.warn("Cannot find group for nextId:{} in dev:{}. Aborting fwd:{}", fwd.nextId(), deviceId, fwd.id());
            fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
            return Collections.emptySet();
        }
    }
    if (forTableId == MPLS_TABLE_1) {
        if (mplsNextTable == MPLS_L3_TYPE_TABLE) {
            Ofdpa3SetMplsType setMplsType = new Ofdpa3SetMplsType(Ofdpa3MplsType.L3_PHP);
            // set mpls type as apply_action
            tb.immediate().extension(setMplsType, deviceId);
        }
        tb.transition(mplsNextTable);
    } else {
        tb.transition(ACL_TABLE);
    }
    if (fwd.treatment() != null && fwd.treatment().clearedDeferred()) {
        if (supportsUnicastBlackHole()) {
            tb.wipeDeferred();
        } else {
            log.warn("Clear Deferred is not supported Unicast Routing Table on device {}", deviceId);
            return Collections.emptySet();
        }
    }
    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector.build()).withTreatment(tb.build()).forTable(forTableId);
    if (fwd.permanent()) {
        ruleBuilder.makePermanent();
    } else {
        ruleBuilder.makeTemporary(fwd.timeout());
    }
    Collection<FlowRule> flowRuleCollection = new ArrayList<>();
    flowRuleCollection.add(ruleBuilder.build());
    if (!allowDefaultRoute) {
        flowRuleCollection.add(defaultRoute(fwd, complementarySelector, forTableId, tb));
        log.debug("Default rule 0.0.0.0/0 is being installed two rules");
    }
    if (emptyGroup) {
        retryExecutorService.schedule(new RetryFlows(fwd, flowRuleCollection), RETRY_MS, TimeUnit.MILLISECONDS);
    }
    return flowRuleCollection;
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) ArrayList(java.util.ArrayList) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) ModMplsHeaderInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction) ModMplsHeaderInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction) IpPrefix(org.onlab.packet.IpPrefix) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) MplsCriterion(org.onosproject.net.flow.criteria.MplsCriterion) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) ArrayDeque(java.util.ArrayDeque) Deque(java.util.Deque) MplsBosCriterion(org.onosproject.net.flow.criteria.MplsBosCriterion) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) Ofdpa3SetMplsType(org.onosproject.driver.extensions.Ofdpa3SetMplsType)

Aggregations

TrafficSelector (org.onosproject.net.flow.TrafficSelector)396 DefaultTrafficSelector (org.onosproject.net.flow.DefaultTrafficSelector)354 TrafficTreatment (org.onosproject.net.flow.TrafficTreatment)249 DefaultTrafficTreatment (org.onosproject.net.flow.DefaultTrafficTreatment)235 FlowRule (org.onosproject.net.flow.FlowRule)94 Test (org.junit.Test)85 DefaultFlowRule (org.onosproject.net.flow.DefaultFlowRule)84 PiAction (org.onosproject.net.pi.runtime.PiAction)54 ConnectPoint (org.onosproject.net.ConnectPoint)51 ForwardingObjective (org.onosproject.net.flowobjective.ForwardingObjective)48 DeviceId (org.onosproject.net.DeviceId)43 PortNumber (org.onosproject.net.PortNumber)43 List (java.util.List)42 NextObjective (org.onosproject.net.flowobjective.NextObjective)41 FilteredConnectPoint (org.onosproject.net.FilteredConnectPoint)39 PiActionParam (org.onosproject.net.pi.runtime.PiActionParam)38 Instruction (org.onosproject.net.flow.instructions.Instruction)37 Criterion (org.onosproject.net.flow.criteria.Criterion)36 PiCriterion (org.onosproject.net.flow.criteria.PiCriterion)36 DefaultForwardingObjective (org.onosproject.net.flowobjective.DefaultForwardingObjective)35