Search in sources :

Example 11 with Instruction

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

the class OvsOfdpaPipeline method versatileTreatmentBuilder.

@Override
protected TrafficTreatment.Builder versatileTreatmentBuilder(ForwardingObjective fwd) {
    // XXX driver does not currently do type checking as per Tables 65-67 in
    // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller.
    TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
    if (fwd.treatment() != null) {
        for (Instruction ins : fwd.treatment().allInstructions()) {
            if (ins instanceof OutputInstruction) {
                OutputInstruction o = (OutputInstruction) ins;
                if (PortNumber.CONTROLLER.equals(o.port())) {
                    ttBuilder.transition(PUNT_TABLE);
                } else {
                    log.warn("Only allowed treatments in versatile forwarding " + "objectives are punts to the controller");
                }
            } else if (ins instanceof NoActionInstruction) {
            // No action is allowed and nothing needs to be done
            } else {
                log.warn("Cannot process instruction in versatile fwd {}", ins);
            }
        }
        if (fwd.treatment().clearedDeferred()) {
            ttBuilder.wipeDeferred();
        }
    }
    if (fwd.nextId() != null) {
        // Override case
        NextGroup next = getGroupForNextObjective(fwd.nextId());
        if (next == null) {
            fail(fwd, ObjectiveError.BADPARAMS);
            return 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 null;
        }
        ttBuilder.deferred().group(group.id());
    }
    return ttBuilder;
}
Also used : OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) NextGroup(org.onosproject.net.behaviour.NextGroup) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) Deque(java.util.Deque)

Example 12 with Instruction

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

the class OvsOfdpaPipeline method processEthTypeSpecific.

/*
     * Open vSwitch emulation allows MPLS ECMP.
     *
     * (non-Javadoc)
     * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific
     */
@Override
protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
    if (isDoubleTagged(fwd)) {
        return processDoubleTaggedFwd(fwd);
    }
    TrafficSelector selector = fwd.selector();
    EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
    if ((ethType == null) || (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST) && (ethType.ethType().toShort() != Ethernet.TYPE_IPV6)) {
        log.warn("processSpecific: Unsupported forwarding objective criteria" + "ethType:{} in dev:{}", ethType, deviceId);
        fail(fwd, ObjectiveError.UNSUPPORTED);
        return Collections.emptySet();
    }
    boolean defaultRule = false;
    int forTableId;
    TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
    TrafficSelector.Builder complementarySelector = DefaultTrafficSelector.builder();
    if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
        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 ImmutableSet.of();
            }
            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 ImmutableSet.of();
            }
            filteredSelector.matchVlanId(assignedVlan);
            filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
            forTableId = MULTICAST_ROUTING_TABLE;
            log.debug("processing IPv4 multicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
        } else {
            if (ipv4Dst.prefixLength() == 0) {
                // The entire IPV4_DST field is wildcarded intentionally
                filteredSelector.matchEthType(Ethernet.TYPE_IPV4);
            } else {
                filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
            }
            forTableId = UNICAST_ROUTING_TABLE;
            log.debug("processing IPv4 unicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
        }
    } else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV6) {
        IpPrefix ipv6Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
        if (ipv6Dst.isMulticast()) {
            if (ipv6Dst.prefixLength() != IpAddress.INET6_BIT_LENGTH) {
                log.debug("Multicast specific IPv6 forwarding objective can only be /128");
                fail(fwd, ObjectiveError.BADPARAMS);
                return ImmutableSet.of();
            }
            VlanId assignedVlan = readVlanFromSelector(fwd.meta());
            if (assignedVlan == null) {
                log.debug("VLAN ID required by multicast specific fwd obj is missing. Abort.");
                fail(fwd, ObjectiveError.BADPARAMS);
                return ImmutableSet.of();
            }
            filteredSelector.matchVlanId(assignedVlan);
            filteredSelector.matchEthType(Ethernet.TYPE_IPV6).matchIPv6Dst(ipv6Dst);
            forTableId = MULTICAST_ROUTING_TABLE;
            log.debug("processing IPv6 multicast specific forwarding objective {} -> next:{}" + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
        } else {
            if (buildIpv6Selector(filteredSelector, fwd) < 0) {
                return Collections.emptyList();
            }
            forTableId = UNICAST_ROUTING_TABLE;
        }
    } else {
        filteredSelector.matchEthType(Ethernet.MPLS_UNICAST).matchMplsLabel(((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
        MplsBosCriterion bos = (MplsBosCriterion) selector.getCriterion(Criterion.Type.MPLS_BOS);
        if (bos != null) {
            filteredSelector.matchMplsBos(bos.mplsBos());
        }
        forTableId = MPLS_TABLE_1;
        log.debug("processing MPLS specific forwarding objective {} -> next:{}" + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
    }
    TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
    if (fwd.treatment() != null) {
        for (Instruction i : fwd.treatment().allInstructions()) {
            if (i instanceof L3ModificationInstruction) {
                L3ModificationInstruction l3instr = (L3ModificationInstruction) i;
                if (l3instr.subtype().equals(L3ModificationInstruction.L3SubType.TTL_IN) || l3instr.subtype().equals(L3ModificationInstruction.L3SubType.TTL_OUT)) {
                    continue;
                }
            }
            /*
                 * NOTE: OF-DPA does not support immediate instruction in
                 * L3 unicast and MPLS table.
                 */
            tb.deferred().add(i);
        }
    }
    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();
            }
            tb.deferred().group(group.id());
        }
    }
    tb.transition(ACL_TABLE);
    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 (defaultRule) {
        flowRuleCollection.add(defaultRoute(fwd, complementarySelector, forTableId, tb));
        log.debug("Default rule 0.0.0.0/0 is being installed two rules");
    }
    return flowRuleCollection;
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) ArrayList(java.util.ArrayList) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) Deque(java.util.Deque) ConnectPoint(org.onosproject.net.ConnectPoint) IpPrefix(org.onlab.packet.IpPrefix) MplsBosCriterion(org.onosproject.net.flow.criteria.MplsBosCriterion) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) MplsCriterion(org.onosproject.net.flow.criteria.MplsCriterion) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) VlanId(org.onlab.packet.VlanId)

Example 13 with Instruction

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

the class OvsOfdpaPipeline method processEgress.

/**
 * In the OF-DPA 2.0 pipeline, egress forwarding objectives go to the
 * egress tables.
 * @param fwd  the forwarding objective of type 'egress'
 * @return     a collection of flow rules to be sent to the switch. An empty
 *             collection may be returned if there is a problem in processing
 *             the flow rule
 */
@Override
protected Collection<FlowRule> processEgress(ForwardingObjective fwd) {
    log.debug("Processing egress forwarding objective:{} in dev:{}", fwd, deviceId);
    List<FlowRule> rules = new ArrayList<>();
    // Build selector
    TrafficSelector.Builder sb = DefaultTrafficSelector.builder();
    VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID);
    if (vlanIdCriterion == null) {
        log.error("Egress forwarding objective:{} must include vlanId", fwd.id());
        fail(fwd, ObjectiveError.BADPARAMS);
        return rules;
    }
    Optional<Instruction> outInstr = fwd.treatment().allInstructions().stream().filter(instruction -> instruction instanceof Instructions.OutputInstruction).findFirst();
    if (!outInstr.isPresent()) {
        log.error("Egress forwarding objective:{} must include output port", fwd.id());
        fail(fwd, ObjectiveError.BADPARAMS);
        return rules;
    }
    PortNumber portNumber = ((Instructions.OutputInstruction) outInstr.get()).port();
    sb.matchVlanId(vlanIdCriterion.vlanId());
    OfdpaMatchActsetOutput actsetOutput = new OfdpaMatchActsetOutput(portNumber);
    sb.extension(actsetOutput, deviceId);
    // Build a flow rule for Egress VLAN Flow table
    TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
    tb.transition(UNICAST_ROUTING_TABLE_1);
    if (fwd.treatment() != null) {
        for (Instruction instr : fwd.treatment().allInstructions()) {
            if (instr instanceof L2ModificationInstruction && ((L2ModificationInstruction) instr).subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
                tb.immediate().add(instr);
            }
            if (instr instanceof L2ModificationInstruction && ((L2ModificationInstruction) instr).subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
                EthType ethType = ((L2ModificationInstruction.ModVlanHeaderInstruction) instr).ethernetType();
                tb.immediate().pushVlan(ethType);
            }
        }
    }
    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(sb.build()).withTreatment(tb.build()).makePermanent().forTable(EGRESS_VLAN_FLOW_TABLE_IN_INGRESS);
    rules.add(ruleBuilder.build());
    return rules;
}
Also used : MplsBosCriterion(org.onosproject.net.flow.criteria.MplsBosCriterion) OfdpaPipelineUtility(org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) PortNumber(org.onosproject.net.PortNumber) Tools.groupedThreads(org.onlab.util.Tools.groupedThreads) PortCriterion(org.onosproject.net.flow.criteria.PortCriterion) ForwardingObjective(org.onosproject.net.flowobjective.ForwardingObjective) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) ConnectPoint(org.onosproject.net.ConnectPoint) OfdpaMatchActsetOutput(org.onosproject.driver.extensions.OfdpaMatchActsetOutput) ObjectiveError(org.onosproject.net.flowobjective.ObjectiveError) Ethernet(org.onlab.packet.Ethernet) Port(org.onosproject.net.Port) ApplicationId(org.onosproject.core.ApplicationId) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) NONE(org.onlab.packet.MacAddress.NONE) PipelinerContext(org.onosproject.net.behaviour.PipelinerContext) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) ImmutableSet(com.google.common.collect.ImmutableSet) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) FilteringObjective(org.onosproject.net.flowobjective.FilteringObjective) VLAN_VID(org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID) Collection(java.util.Collection) Executors(java.util.concurrent.Executors) Objects(java.util.Objects) EthType(org.onlab.packet.EthType) List(java.util.List) FlowRule(org.onosproject.net.flow.FlowRule) GroupBuckets(org.onosproject.net.group.GroupBuckets) Optional(java.util.Optional) Queue(java.util.Queue) DeviceId(org.onosproject.net.DeviceId) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) GroupDescription(org.onosproject.net.group.GroupDescription) IpPrefix(org.onlab.packet.IpPrefix) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) MplsCriterion(org.onosproject.net.flow.criteria.MplsCriterion) FlowRuleOperationsContext(org.onosproject.net.flow.FlowRuleOperationsContext) BROADCAST(org.onlab.packet.MacAddress.BROADCAST) Host(org.onosproject.net.Host) GroupBucket(org.onosproject.net.group.GroupBucket) NextGroup(org.onosproject.net.behaviour.NextGroup) GroupKey(org.onosproject.net.group.GroupKey) Deque(java.util.Deque) HostService(org.onosproject.net.host.HostService) EthCriterion(org.onosproject.net.flow.criteria.EthCriterion) Group(org.onosproject.net.group.Group) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) TrafficSelector(org.onosproject.net.flow.TrafficSelector) ImmutableList(com.google.common.collect.ImmutableList) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) OfdpaGroupHandlerUtility(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility) Criteria(org.onosproject.net.flow.criteria.Criteria) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) Criterion(org.onosproject.net.flow.criteria.Criterion) IpAddress(org.onlab.packet.IpAddress) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) FlowRuleOperations(org.onosproject.net.flow.FlowRuleOperations) Instructions(org.onosproject.net.flow.instructions.Instructions) Logger(org.slf4j.Logger) ReentrantLock(java.util.concurrent.locks.ReentrantLock) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) Instruction(org.onosproject.net.flow.instructions.Instruction) VlanId(org.onlab.packet.VlanId) DefaultGroupBucket(org.onosproject.net.group.DefaultGroupBucket) TimeUnit(java.util.concurrent.TimeUnit) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) GroupId(org.onosproject.core.GroupId) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion) LoggerFactory.getLogger(org.slf4j.LoggerFactory.getLogger) MacAddress(org.onlab.packet.MacAddress) PacketPriority(org.onosproject.net.packet.PacketPriority) Collections(java.util.Collections) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) OfdpaMatchActsetOutput(org.onosproject.driver.extensions.OfdpaMatchActsetOutput) ArrayList(java.util.ArrayList) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) NoActionInstruction(org.onosproject.net.flow.instructions.Instructions.NoActionInstruction) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) EthType(org.onlab.packet.EthType) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) PortNumber(org.onosproject.net.PortNumber) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion)

Example 14 with Instruction

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

the class OfdpaPipelineTraceable method apply.

@Override
public PipelineTraceableOutput apply(PipelineTraceableInput input) {
    PipelineTraceableOutput.Builder outputBuilder = PipelineTraceableOutput.builder();
    log.debug("Current packet {} - applying flow tables", input.ingressPacket());
    List<FlowEntry> outputFlows = new ArrayList<>();
    List<Instruction> deferredInstructions = new ArrayList<>();
    PipelineTraceableHitChain currentHitChain = PipelineTraceableHitChain.emptyHitChain();
    TrafficSelector currentPacket = DefaultTrafficSelector.builder(input.ingressPacket().packet()).build();
    // Init step - find out the first table
    int initialTableId = -1;
    FlowEntry nextTableIdEntry = findNextTableIdEntry(initialTableId, input.flows());
    if (nextTableIdEntry == null) {
        currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
        currentHitChain.dropped();
        return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting").noFlows().addHitChain(currentHitChain).build();
    }
    // Iterates over the flow tables until the end of the pipeline
    TableId tableId = nextTableIdEntry.table();
    FlowEntry flowEntry;
    boolean lastTable = false;
    while (!lastTable) {
        log.debug("Searching a Flow Entry on table {} for packet {}", tableId, currentPacket);
        // Gets the rule that matches the incoming packet
        flowEntry = matchHighestPriority(currentPacket, tableId, input.flows());
        log.debug("Found Flow Entry {}", flowEntry);
        // If the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
        if (flowEntry == null && isHardwareSwitch()) {
            log.debug("Ofdpa Hw setup, no flow rule means table miss");
            if (((IndexTableId) tableId).id() == MPLS_L3_TYPE_TABLE) {
                // Apparently a miss but Table 27 on OFDPA is a fixed table
                currentPacket = handleOfdpa27FixedTable(input.ingressPacket().packet(), currentPacket);
                // The nextTable should be ACL
                tableId = IndexTableId.of(ACL_TABLE - 1);
            }
            // Finding next table to go In case of miss
            nextTableIdEntry = findNextTableIdEntry(((IndexTableId) tableId).id(), input.flows());
            log.debug("Next table id entry {}", nextTableIdEntry);
            // (another possibility is max tableId)
            if (nextTableIdEntry == null && currentHitChain.hitChain().size() == 0) {
                currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
                currentHitChain.dropped();
                return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting").noFlows().addHitChain(currentHitChain).build();
            } else if (nextTableIdEntry == null) {
                // Means that no more flow rules are present
                lastTable = true;
            } else if (((IndexTableId) tableId).id() == TMAC_TABLE) {
                // If the table is 20 OFDPA skips to table 50
                log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
                tableId = IndexTableId.of(BRIDGING_TABLE);
            } else if (((IndexTableId) tableId).id() == MULTICAST_ROUTING_TABLE) {
                // If the table is 40 OFDPA skips to table 60
                log.debug("A miss on Table 40 on OFDPA means that we skip directly to table 60");
                tableId = IndexTableId.of(ACL_TABLE);
            } else {
                tableId = nextTableIdEntry.table();
            }
        } else if (flowEntry == null) {
            currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
            currentHitChain.dropped();
            return outputBuilder.appendToLog("Packet has no match on table " + tableId + " in device " + deviceId + ". Dropping").noFlows().addHitChain(currentHitChain).build();
        } else {
            // If the table has a transition
            if (flowEntry.treatment().tableTransition() != null) {
                // Updates the next table we transitions to
                tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
                log.debug("Flow Entry has transition to table Id {}", tableId);
                currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
            } else {
                // Table has no transition so it means that it's an output rule if on the last table
                log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
                currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
                outputFlows.add(flowEntry);
                lastTable = true;
            }
            // Updates the packet according to the immediate actions of this flow rule.
            currentPacket = updatePacket(currentPacket, flowEntry.treatment().immediate()).build();
            // Saves the deferred rules for later maintaining the order
            deferredInstructions.addAll(flowEntry.treatment().deferred());
            // If the flow requires to clear deferred actions we do so for all the ones we encountered.
            if (flowEntry.treatment().clearedDeferred()) {
                deferredInstructions.clear();
            }
            // On table 10 OFDPA needs two rules to apply the vlan if none and then to transition to the next table.
            if (shouldMatchSecondVlanFlow(flowEntry)) {
                // Let's get the packet vlanId instruction
                VlanIdCriterion packetVlanIdCriterion = (VlanIdCriterion) currentPacket.getCriterion(Criterion.Type.VLAN_VID);
                // Let's get the flow entry vlan mod instructions
                ModVlanIdInstruction entryModVlanIdInstruction = (ModVlanIdInstruction) flowEntry.treatment().immediate().stream().filter(instruction -> instruction instanceof ModVlanIdInstruction).findFirst().orElse(null);
                // is a flow rule that matches on same criteria and with updated vlanId
                if (entryModVlanIdInstruction != null) {
                    FlowEntry secondVlanFlow = getSecondFlowEntryOnTable10(currentPacket, packetVlanIdCriterion, entryModVlanIdInstruction, input.flows());
                    // We found the flow that we expected
                    if (secondVlanFlow != null) {
                        currentHitChain.addDataPlaneEntity(new DataPlaneEntity(secondVlanFlow));
                    } else {
                        currentHitChain.setEgressPacket(new PipelineTraceablePacket(currentPacket));
                        currentHitChain.dropped();
                        return outputBuilder.appendToLog("Missing forwarding rule for tagged" + " packet on " + deviceId).noFlows().addHitChain(currentHitChain).build();
                    }
                }
            }
        }
    }
    // Creating a modifiable builder for the egress packet
    TrafficSelector.Builder egressPacket = DefaultTrafficSelector.builder(currentPacket);
    log.debug("Current packet {} - applying output flows", currentPacket);
    // Handling output flows which basically means handling output to controller.
    // OVS and OFDPA have both immediate -> OUTPUT:CONTROLLER. Theoretically there is no
    // need to reflect the updates performed on the packets and on the chain.
    List<PortNumber> outputPorts = new ArrayList<>();
    handleOutputFlows(currentPacket, outputFlows, egressPacket, outputPorts, currentHitChain, outputBuilder, input.ingressPacket().packet());
    // Immediate instructions
    log.debug("Current packet {} - applying immediate instructions", currentPacket);
    // Handling immediate instructions which basically means handling output to controller.
    // OVS has immediate -> group -> OUTPUT:CONTROLLER.
    List<DataPlaneEntity> entries = ImmutableList.copyOf(currentHitChain.hitChain());
    // Go to the next step - using a copy of the egress packet and of the hit chain
    PipelineTraceableHitChain newHitChain = PipelineTraceableHitChain.emptyHitChain();
    currentHitChain.hitChain().forEach(newHitChain::addDataPlaneEntity);
    TrafficSelector.Builder newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
    for (DataPlaneEntity entry : entries) {
        flowEntry = entry.getFlowEntry();
        if (flowEntry != null) {
            getGroupsFromInstructions(input.groups(), flowEntry.treatment().immediate(), newEgressPacket, outputPorts, newHitChain, outputBuilder, input, false);
        }
    }
    // Deferred instructions
    log.debug("Current packet {} - applying deferred instructions", egressPacket.build());
    // egress packet and of the hit chain. This is the last step.
    if (deferredInstructions.size() > 0) {
        handleDeferredActions(egressPacket.build(), input.groups(), deferredInstructions, outputPorts, currentHitChain, outputBuilder, input);
    }
    // Let's store the partial hit chain and set a message
    if (outputPorts.isEmpty()) {
        currentHitChain.setEgressPacket(new PipelineTraceablePacket(egressPacket.build()));
        currentHitChain.dropped();
        outputBuilder.appendToLog("Packet has no output in device " + deviceId + ". Dropping").dropped().addHitChain(currentHitChain);
    }
    // Done!
    return outputBuilder.build();
}
Also used : IndexTableId(org.onosproject.net.flow.IndexTableId) TableId(org.onosproject.net.flow.TableId) IndexTableId(org.onosproject.net.flow.IndexTableId) ArrayList(java.util.ArrayList) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) ModVlanIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction) ConnectPoint(org.onosproject.net.ConnectPoint) DataPlaneEntity(org.onosproject.net.DataPlaneEntity) ModVlanIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) PipelineTraceableOutput(org.onosproject.net.PipelineTraceableOutput) PipelineTraceableHitChain(org.onosproject.net.PipelineTraceableHitChain) PortNumber(org.onosproject.net.PortNumber) FlowEntry(org.onosproject.net.flow.FlowEntry) PipelineTraceablePacket(org.onosproject.net.PipelineTraceablePacket) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion)

Example 15 with Instruction

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

the class LinkCollectionCompiler method generateEgressActions.

/**
 * Helper method to generate the egress actions.
 *
 * @param treatmentBuilder the treatment builder to update
 * @param egressPoints the egress points
 * @param initialState the initial state of the transition
 */
private void generateEgressActions(TrafficTreatment.Builder treatmentBuilder, List<FilteredConnectPoint> egressPoints, TrafficSelector initialState, LinkCollectionIntent intent) {
    TrafficSelector prevState = initialState;
    for (FilteredConnectPoint egressPoint : egressPoints) {
        /*
             * If we are at the egress, we have to transit to the final
             * state. First we add the Intent treatment.
             */
        intent.treatment().allInstructions().stream().filter(inst -> inst.type() != Instruction.Type.NOACTION).forEach(treatmentBuilder::add);
        /*
             * We generate the transition FIP->FEP.
             */
        TrafficTreatment forwardingTreatment = forwardingTreatment(prevState, egressPoint.trafficSelector(), getEthType(intent.selector()));
        /*
             * We add the instruction necessary to the transition.
             * Potentially we override the intent treatment.
             */
        forwardingTreatment.allInstructions().stream().filter(inst -> inst.type() != Instruction.Type.NOACTION).forEach(treatmentBuilder::add);
        /*
             * Finally we set the output action.
             */
        treatmentBuilder.setOutput(egressPoint.connectPoint().port());
        if (optimizeTreatments()) {
            /*
                 * We update the previous state. In this way instead of
                 * transiting from FIP->FEP we do FEP->FEP and so on.
                 */
            prevState = egressPoint.trafficSelector();
        }
    }
}
Also used : PortNumber(org.onosproject.net.PortNumber) LoggerFactory(org.slf4j.LoggerFactory) ModIPv6FlowLabelInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction) Link(org.onosproject.net.Link) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) ConnectPoint(org.onosproject.net.ConnectPoint) Ethernet(org.onlab.packet.Ethernet) Map(java.util.Map) L2ModificationInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction) Ip4Address(org.onlab.packet.Ip4Address) L3ModificationInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction) Set(java.util.Set) ModVlanIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) EthType(org.onlab.packet.EthType) ModTransportPortInstruction(org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction) List(java.util.List) EncapsulationType(org.onosproject.net.EncapsulationType) ModEtherInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction) ModTunnelIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction) Optional(java.util.Optional) DeviceId(org.onosproject.net.DeviceId) TunnelIdCriterion(org.onosproject.net.flow.criteria.TunnelIdCriterion) IpPrefix(org.onlab.packet.IpPrefix) MplsCriterion(org.onosproject.net.flow.criteria.MplsCriterion) Identifier(org.onlab.util.Identifier) L4ModificationInstruction(org.onosproject.net.flow.instructions.L4ModificationInstruction) LabelAllocator(org.onosproject.net.resource.impl.LabelAllocator) ModMplsLabelInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction) DomainConstraint(org.onosproject.net.intent.constraint.DomainConstraint) IntentCompilationException(org.onosproject.net.intent.IntentCompilationException) ModIPInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction) ModArpIPInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction) EncapsulationConstraint(org.onosproject.net.intent.constraint.EncapsulationConstraint) ModVlanPcpInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction) Type(org.onosproject.net.flow.criteria.Criterion.Type) Lists(com.google.common.collect.Lists) TrafficSelector(org.onosproject.net.flow.TrafficSelector) ImmutableList(com.google.common.collect.ImmutableList) DomainService(org.onosproject.net.domain.DomainService) L0ModificationInstruction(org.onosproject.net.flow.instructions.L0ModificationInstruction) DomainPointToPointIntent(org.onosproject.net.domain.DomainPointToPointIntent) Intent(org.onosproject.net.intent.Intent) LOCAL(org.onosproject.net.domain.DomainId.LOCAL) Criteria(org.onosproject.net.flow.criteria.Criteria) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) Criterion(org.onosproject.net.flow.criteria.Criterion) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) ModMplsBosInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction) Logger(org.slf4j.Logger) MplsLabel(org.onlab.packet.MplsLabel) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) Instruction(org.onosproject.net.flow.instructions.Instruction) VlanId(org.onlab.packet.VlanId) ModArpEthInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction) LinkCollectionIntent(org.onosproject.net.intent.LinkCollectionIntent) Maps(com.google.common.collect.Maps) SetMultimap(com.google.common.collect.SetMultimap) DomainId(org.onosproject.net.domain.DomainId) L1ModificationInstruction(org.onosproject.net.flow.instructions.L1ModificationInstruction) VlanIdCriterion(org.onosproject.net.flow.criteria.VlanIdCriterion) ModArpOpInstruction(org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction) FilteredConnectPoint(org.onosproject.net.FilteredConnectPoint) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) FilteredConnectPoint(org.onosproject.net.FilteredConnectPoint)

Aggregations

Instruction (org.onosproject.net.flow.instructions.Instruction)104 L2ModificationInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction)59 TrafficTreatment (org.onosproject.net.flow.TrafficTreatment)48 DefaultTrafficTreatment (org.onosproject.net.flow.DefaultTrafficTreatment)44 Criterion (org.onosproject.net.flow.criteria.Criterion)42 TrafficSelector (org.onosproject.net.flow.TrafficSelector)34 VlanIdCriterion (org.onosproject.net.flow.criteria.VlanIdCriterion)33 Instructions (org.onosproject.net.flow.instructions.Instructions)33 OutputInstruction (org.onosproject.net.flow.instructions.Instructions.OutputInstruction)32 L3ModificationInstruction (org.onosproject.net.flow.instructions.L3ModificationInstruction)32 PortNumber (org.onosproject.net.PortNumber)30 DefaultTrafficSelector (org.onosproject.net.flow.DefaultTrafficSelector)28 EthTypeCriterion (org.onosproject.net.flow.criteria.EthTypeCriterion)27 IPCriterion (org.onosproject.net.flow.criteria.IPCriterion)26 VlanId (org.onlab.packet.VlanId)25 DeviceId (org.onosproject.net.DeviceId)25 EthCriterion (org.onosproject.net.flow.criteria.EthCriterion)25 PortCriterion (org.onosproject.net.flow.criteria.PortCriterion)25 FlowRule (org.onosproject.net.flow.FlowRule)24 Group (org.onosproject.net.group.Group)23