Search in sources :

Example 16 with OutputInstruction

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

the class BasicInterpreterImpl method mapOutboundPacket.

@Override
public Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet) throws PiInterpreterException {
    TrafficTreatment treatment = packet.treatment();
    // basic.p4 supports only OUTPUT instructions.
    List<OutputInstruction> outInstructions = treatment.allInstructions().stream().filter(i -> i.type().equals(OUTPUT)).map(i -> (OutputInstruction) i).collect(toList());
    if (treatment.allInstructions().size() != outInstructions.size()) {
        // There are other instructions that are not of type OUTPUT.
        throw new PiInterpreterException("Treatment not supported: " + treatment);
    }
    ImmutableList.Builder<PiPacketOperation> builder = ImmutableList.builder();
    for (OutputInstruction outInst : outInstructions) {
        if (outInst.port().isLogical() && !outInst.port().equals(FLOOD)) {
            throw new PiInterpreterException(format("Output on logical port '%s' not supported", outInst.port()));
        } else if (outInst.port().equals(FLOOD)) {
            // Since basic.p4 does not support flooding, we create a packet
            // operation for each switch port.
            final DeviceService deviceService = handler().get(DeviceService.class);
            for (Port port : deviceService.getPorts(packet.sendThrough())) {
                builder.add(createPiPacketOperation(packet.data(), port.number().toLong()));
            }
        } else {
            builder.add(createPiPacketOperation(packet.data(), outInst.port().toLong()));
        }
    }
    return builder.build();
}
Also used : OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) PiTableId(org.onosproject.net.pi.model.PiTableId) PortNumber(org.onosproject.net.PortNumber) DeviceService(org.onosproject.net.device.DeviceService) PiActionParam(org.onosproject.net.pi.runtime.PiActionParam) ByteBuffer(java.nio.ByteBuffer) ConnectPoint(org.onosproject.net.ConnectPoint) Ethernet(org.onlab.packet.Ethernet) ImmutableByteSequence.copyFrom(org.onlab.util.ImmutableByteSequence.copyFrom) INGRESS_WCMP_CONTROL_WCMP_TABLE(org.onosproject.pipelines.basic.BasicConstants.INGRESS_WCMP_CONTROL_WCMP_TABLE) Port(org.onosproject.net.Port) Map(java.util.Map) HDR_STANDARD_METADATA_INGRESS_PORT(org.onosproject.pipelines.basic.BasicConstants.HDR_STANDARD_METADATA_INGRESS_PORT) INGRESS_PORT(org.onosproject.pipelines.basic.BasicConstants.INGRESS_PORT) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) EGRESS_PORT(org.onosproject.pipelines.basic.BasicConstants.EGRESS_PORT) String.format(java.lang.String.format) HDR_HDR_ETHERNET_DST_ADDR(org.onosproject.pipelines.basic.BasicConstants.HDR_HDR_ETHERNET_DST_ADDR) List(java.util.List) InboundPacket(org.onosproject.net.packet.InboundPacket) PORT(org.onosproject.pipelines.basic.BasicConstants.PORT) Optional(java.util.Optional) DeviceId(org.onosproject.net.DeviceId) PiPacketMetadata(org.onosproject.net.pi.runtime.PiPacketMetadata) PACKET_OUT(org.onosproject.net.pi.model.PiPacketOperationType.PACKET_OUT) HDR_HDR_ETHERNET_ETHER_TYPE(org.onosproject.pipelines.basic.BasicConstants.HDR_HDR_ETHERNET_ETHER_TYPE) ImmutableByteSequence(org.onlab.util.ImmutableByteSequence) INGRESS_TABLE0_CONTROL_DROP(org.onosproject.pipelines.basic.BasicConstants.INGRESS_TABLE0_CONTROL_DROP) AbstractHandlerBehaviour(org.onosproject.net.driver.AbstractHandlerBehaviour) HDR_HDR_ETHERNET_SRC_ADDR(org.onosproject.pipelines.basic.BasicConstants.HDR_HDR_ETHERNET_SRC_ADDR) ImmutableList(com.google.common.collect.ImmutableList) DeserializationException(org.onlab.packet.DeserializationException) OutboundPacket(org.onosproject.net.packet.OutboundPacket) PiPacketOperation(org.onosproject.net.pi.runtime.PiPacketOperation) Criterion(org.onosproject.net.flow.criteria.Criterion) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) FLOOD(org.onosproject.net.PortNumber.FLOOD) PiPipelineInterpreter(org.onosproject.net.pi.model.PiPipelineInterpreter) DefaultInboundPacket(org.onosproject.net.packet.DefaultInboundPacket) Instruction(org.onosproject.net.flow.instructions.Instruction) NO_ACTION(org.onosproject.pipelines.basic.BasicConstants.NO_ACTION) INGRESS_TABLE0_CONTROL_SEND_TO_CPU(org.onosproject.pipelines.basic.BasicConstants.INGRESS_TABLE0_CONTROL_SEND_TO_CPU) PiMatchFieldId(org.onosproject.net.pi.model.PiMatchFieldId) INGRESS_TABLE0_CONTROL_SET_EGRESS_PORT(org.onosproject.pipelines.basic.BasicConstants.INGRESS_TABLE0_CONTROL_SET_EGRESS_PORT) CONTROLLER(org.onosproject.net.PortNumber.CONTROLLER) HDR_HDR_IPV4_DST_ADDR(org.onosproject.pipelines.basic.BasicConstants.HDR_HDR_IPV4_DST_ADDR) INGRESS_WCMP_CONTROL_SET_EGRESS_PORT(org.onosproject.pipelines.basic.BasicConstants.INGRESS_WCMP_CONTROL_SET_EGRESS_PORT) PiAction(org.onosproject.net.pi.runtime.PiAction) INGRESS_TABLE0_CONTROL_TABLE0(org.onosproject.pipelines.basic.BasicConstants.INGRESS_TABLE0_CONTROL_TABLE0) Collectors.toList(java.util.stream.Collectors.toList) HDR_HDR_IPV4_SRC_ADDR(org.onosproject.pipelines.basic.BasicConstants.HDR_HDR_IPV4_SRC_ADDR) OUTPUT(org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT) PiActionId(org.onosproject.net.pi.model.PiActionId) ImmutableList(com.google.common.collect.ImmutableList) Port(org.onosproject.net.Port) PiPacketOperation(org.onosproject.net.pi.runtime.PiPacketOperation) DeviceService(org.onosproject.net.device.DeviceService) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment)

Example 17 with OutputInstruction

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

the class FlowRuleJuniperImpl method manageRules.

private Collection<FlowRule> manageRules(Collection<FlowRule> rules, OperationType type) {
    DeviceId deviceId = this.data().deviceId();
    log.debug("{} flow entries to NETCONF device {}", type, deviceId);
    NetconfSession session = lookupNetconfSession(deviceId);
    Collection<FlowRule> managedRules = new HashSet<>();
    for (FlowRule flowRule : rules) {
        Optional<IPCriterion> ipCriterion = getIpCriterion(flowRule);
        if (!ipCriterion.isPresent()) {
            log.error("Currently not supported: IPv4 destination match must be used");
            continue;
        }
        Optional<OutputInstruction> output = getOutput(flowRule);
        if (!output.isPresent()) {
            log.error("Currently not supported: the output action is needed");
            continue;
        }
        getStaticRoute(deviceId, ipCriterion.get(), output.get(), flowRule.priority()).ifPresent(staticRoute -> {
            // If the static route is not local, the driver tries to install
            if (!staticRoute.isLocalRoute()) {
                // FlowRule as installed.
                if (editRoute(session, type, staticRoute)) {
                    managedRules.add(flowRule);
                }
            // If static route are local, they are not installed
            // because are not required. Directly connected routes
            // are automatically forwarded.
            } else {
                managedRules.add(flowRule);
            }
        });
    }
    return rules;
}
Also used : NetconfSession(org.onosproject.netconf.NetconfSession) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) DeviceId(org.onosproject.net.DeviceId) FlowRule(org.onosproject.net.flow.FlowRule) HashSet(java.util.HashSet)

Example 18 with OutputInstruction

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

the class FlowRuleJuniperImpl method getStaticRoute.

/**
 * Helper method to convert FlowRule into an abstraction of static route
 * {@link StaticRoute}.
 *
 * @param devId    the device id
 * @param criteria the IP destination criteria
 * @param output   the output instruction
 * @return optional of Static Route
 */
private Optional<StaticRoute> getStaticRoute(DeviceId devId, IPCriterion criteria, OutputInstruction output, int priority) {
    DeviceService deviceService = this.handler().get(DeviceService.class);
    Collection<Port> ports = deviceService.getPorts(devId);
    Optional<Port> port = ports.stream().filter(x -> x.number().equals(output.port())).findAny();
    if (!port.isPresent()) {
        log.error("The port {} does not exist in the device", output.port());
        return Optional.empty();
    }
    // Find if the route refers to a local interface.
    Optional<Port> local = deviceService.getPorts(devId).stream().filter(this::isIp).filter(p -> criteria.ip().getIp4Prefix().contains(Ip4Address.valueOf(p.annotations().value(JuniperUtils.AK_IP)))).findAny();
    if (local.isPresent()) {
        return Optional.of(new StaticRoute(criteria.ip().getIp4Prefix(), criteria.ip().getIp4Prefix().address(), true, priority));
    }
    Optional<Ip4Address> nextHop = findIpDst(devId, port.get());
    if (nextHop.isPresent()) {
        return Optional.of(new StaticRoute(criteria.ip().getIp4Prefix(), nextHop.get(), false, priority));
    } else {
        log.error("The destination interface has not an IP {}", port.get());
        return Optional.empty();
    }
}
Also used : NetconfException(org.onosproject.netconf.NetconfException) StringUtils(org.apache.commons.lang.StringUtils) JuniperUtils.commitBuilder(org.onosproject.drivers.juniper.JuniperUtils.commitBuilder) FlowRuleProgrammable(org.onosproject.net.flow.FlowRuleProgrammable) PortNumber(org.onosproject.net.PortNumber) DeviceService(org.onosproject.net.device.DeviceService) FlowEntry(org.onosproject.net.flow.FlowEntry) AnnotationKeys(org.onosproject.net.AnnotationKeys) JuniperUtils.routeAddBuilder(org.onosproject.drivers.juniper.JuniperUtils.routeAddBuilder) Link(org.onosproject.net.Link) NetconfSession(org.onosproject.netconf.NetconfSession) ConnectPoint(org.onosproject.net.ConnectPoint) HashSet(java.util.HashSet) XmlConfigParser.loadXmlString(org.onosproject.drivers.utilities.XmlConfigParser.loadXmlString) Strings(com.google.common.base.Strings) FlowRuleService(org.onosproject.net.flow.FlowRuleService) JuniperUtils.routeDeleteBuilder(org.onosproject.drivers.juniper.JuniperUtils.routeDeleteBuilder) Port(org.onosproject.net.Port) Map(java.util.Map) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) Criterion(org.onosproject.net.flow.criteria.Criterion) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) Ip4Address(org.onlab.packet.Ip4Address) Instruction(org.onosproject.net.flow.instructions.Instruction) Collection(java.util.Collection) PENDING_REMOVE(org.onosproject.net.flow.FlowEntry.FlowEntryState.PENDING_REMOVE) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Set(java.util.Set) Collectors(java.util.stream.Collectors) ADD(org.onosproject.drivers.juniper.JuniperUtils.OperationType.ADD) REMOVED(org.onosproject.net.flow.FlowEntry.FlowEntryState.REMOVED) Beta(com.google.common.annotations.Beta) DatastoreId(org.onosproject.netconf.DatastoreId) OperationType(org.onosproject.drivers.juniper.JuniperUtils.OperationType) FlowRule(org.onosproject.net.flow.FlowRule) LoggerFactory.getLogger(org.slf4j.LoggerFactory.getLogger) LinkService(org.onosproject.net.link.LinkService) Optional(java.util.Optional) REMOVE(org.onosproject.drivers.juniper.JuniperUtils.OperationType.REMOVE) DeviceId(org.onosproject.net.DeviceId) Collections(java.util.Collections) JuniperUtils.rollbackBuilder(org.onosproject.drivers.juniper.JuniperUtils.rollbackBuilder) Port(org.onosproject.net.Port) DeviceService(org.onosproject.net.device.DeviceService) Ip4Address(org.onlab.packet.Ip4Address)

Example 19 with OutputInstruction

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

the class FlowRuleJuniperImpl method getFlowEntries.

@Override
public Collection<FlowEntry> getFlowEntries() {
    DeviceId devId = checkNotNull(this.data().deviceId());
    NetconfSession session = lookupNetconfSession(devId);
    if (session == null) {
        return Collections.emptyList();
    }
    // Installed static routes
    String reply;
    try {
        reply = session.get(routingTableBuilder());
    } catch (NetconfException e) {
        throw new IllegalStateException(new NetconfException("Failed to retrieve configuration.", e));
    }
    Collection<StaticRoute> devicesStaticRoutes = JuniperUtils.parseRoutingTable(loadXmlString(reply));
    // Expected FlowEntries installed
    FlowRuleService flowRuleService = this.handler().get(FlowRuleService.class);
    Iterable<FlowEntry> flowEntries = flowRuleService.getFlowEntries(devId);
    Collection<FlowEntry> installedRules = new HashSet<>();
    flowEntries.forEach(flowEntry -> {
        Optional<IPCriterion> ipCriterion = getIpCriterion(flowEntry);
        if (!ipCriterion.isPresent()) {
            return;
        }
        Optional<OutputInstruction> output = getOutput(flowEntry);
        if (!output.isPresent()) {
            return;
        }
        // convert FlowRule into static route
        getStaticRoute(devId, ipCriterion.get(), output.get(), flowEntry.priority()).ifPresent(staticRoute -> {
            if (staticRoute.isLocalRoute()) {
                // if the FlowRule is in PENDING_REMOVE or REMOVED, it is not reported.
                if (flowEntry.state() == PENDING_REMOVE || flowEntry.state() == REMOVED) {
                    devicesStaticRoutes.remove(staticRoute);
                } else {
                    // FlowRule is reported installed
                    installedRules.add(flowEntry);
                    devicesStaticRoutes.remove(staticRoute);
                }
            } else {
                // if the route is found in the device, the FlowRule is reported installed.
                if (devicesStaticRoutes.contains(staticRoute)) {
                    installedRules.add(flowEntry);
                    devicesStaticRoutes.remove(staticRoute);
                }
            }
        });
    });
    if (!devicesStaticRoutes.isEmpty()) {
        log.info("Found static routes on device {} not installed by ONOS: {}", devId, devicesStaticRoutes);
    // FIXME: enable configuration to purge already installed flows.
    // It cannot be allowed by default because it may remove needed management routes
    // log.warn("Removing from device {} the FlowEntries not expected {}", deviceId, devicesStaticRoutes);
    // devicesStaticRoutes.forEach(staticRoute -> editRoute(session, REMOVE, staticRoute));
    }
    return installedRules;
}
Also used : NetconfSession(org.onosproject.netconf.NetconfSession) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) DeviceId(org.onosproject.net.DeviceId) XmlConfigParser.loadXmlString(org.onosproject.drivers.utilities.XmlConfigParser.loadXmlString) NetconfException(org.onosproject.netconf.NetconfException) FlowRuleService(org.onosproject.net.flow.FlowRuleService) FlowEntry(org.onosproject.net.flow.FlowEntry) HashSet(java.util.HashSet)

Example 20 with OutputInstruction

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

the class PiReplicationGroupTranslatorImpl method translate.

/**
 * Returns a PI PRE entry equivalent to the given group, for the given
 * pipeconf and device.
 * <p>
 * The passed group is expected to have type {@link GroupDescription.Type#ALL}
 * or {@link GroupDescription.Type#CLONE}.
 *
 * @param group    group
 * @param pipeconf pipeconf
 * @param device   device
 * @return PI PRE entry
 * @throws PiTranslationException if the group cannot be translated
 */
static PiPreEntry translate(Group group, PiPipeconf pipeconf, Device device) throws PiTranslationException {
    checkNotNull(group);
    final List<OutputInstruction> outInstructions = Lists.newArrayList();
    int truncateMaxLen = PiCloneSessionEntry.DO_NOT_TRUNCATE;
    for (GroupBucket bucket : group.buckets().buckets()) {
        int numInstructionsInBucket = bucket.treatment().allInstructions().size();
        List<OutputInstruction> outputs = getInstructions(bucket, Instruction.Type.OUTPUT, OutputInstruction.class);
        List<TruncateInstruction> truncates = getInstructions(bucket, Instruction.Type.TRUNCATE, TruncateInstruction.class);
        if (outputs.size() != 1) {
            throw new PiTranslationException("support only groups with just one OUTPUT instruction per bucket");
        }
        outInstructions.add(outputs.get(0));
        if (truncates.size() != 0) {
            if (group.type() != GroupDescription.Type.CLONE) {
                throw new PiTranslationException("only CLONE group support truncate instruction");
            }
            if (truncates.size() != 1) {
                throw new PiTranslationException("support only groups with just one TRUNCATE instruction per bucket");
            }
            int truncateInstMaxLen = truncates.get(0).maxLen();
            if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE && truncateMaxLen != truncateInstMaxLen) {
                throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
            }
            truncateMaxLen = truncateInstMaxLen;
        } else if (truncateMaxLen != PiCloneSessionEntry.DO_NOT_TRUNCATE) {
            // No truncate instruction found in this bucket, but previous bucket contains one.
            throw new PiTranslationException("all TRUNCATE instruction must be the same in a CLONE group");
        }
        if (numInstructionsInBucket != outputs.size() + truncates.size()) {
            throw new PiTranslationException("bucket contains unsupported instruction(s)");
        }
    }
    switch(group.type()) {
        case ALL:
            return PiMulticastGroupEntry.builder().withGroupId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).build();
        case CLONE:
            return PiCloneSessionEntry.builder().withSessionId(group.id().id()).addReplicas(getReplicas(outInstructions, device)).withMaxPacketLengthBytes(truncateMaxLen).build();
        default:
            throw new PiTranslationException(format("group type %s not supported", group.type()));
    }
}
Also used : OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) TruncateInstruction(org.onosproject.net.flow.instructions.Instructions.TruncateInstruction) GroupBucket(org.onosproject.net.group.GroupBucket) PiTranslationException(org.onosproject.net.pi.service.PiTranslationException)

Aggregations

OutputInstruction (org.onosproject.net.flow.instructions.Instructions.OutputInstruction)34 Instruction (org.onosproject.net.flow.instructions.Instruction)21 PortNumber (org.onosproject.net.PortNumber)17 DeviceId (org.onosproject.net.DeviceId)15 ConnectPoint (org.onosproject.net.ConnectPoint)11 Port (org.onosproject.net.Port)10 L2ModificationInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction)9 TrafficTreatment (org.onosproject.net.flow.TrafficTreatment)7 Criterion (org.onosproject.net.flow.criteria.Criterion)7 Group (org.onosproject.net.group.Group)7 Collection (java.util.Collection)6 DeviceService (org.onosproject.net.device.DeviceService)6 FlowEntry (org.onosproject.net.flow.FlowEntry)6 ImmutableList (com.google.common.collect.ImmutableList)5 HashSet (java.util.HashSet)5 Ethernet (org.onlab.packet.Ethernet)5 AbstractHandlerBehaviour (org.onosproject.net.driver.AbstractHandlerBehaviour)5 IPCriterion (org.onosproject.net.flow.criteria.IPCriterion)5 ModEtherInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction)5 ModVlanIdInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction)5