Java Code Examples for org.onosproject.net.flowobjective.ForwardingObjective#treatment()

The following examples show how to use org.onosproject.net.flowobjective.ForwardingObjective#treatment() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ForwardingObjectiveTranslator.java    From onos with Apache License 2.0 6 votes vote down vote up
private static TrafficTreatment nextIdOrTreatment(
        ForwardingObjective obj, PiTableId tableId)
        throws FabricPipelinerException {
    if (obj.nextId() == null) {
        return obj.treatment();
    } else {
        if (!NEXT_ID_ACTIONS.containsKey(tableId)) {
            throw new FabricPipelinerException(format(
                    "BUG? no next_id action set for table %s", tableId));
        }
        return DefaultTrafficTreatment.builder()
                .piTableAction(
                        setNextIdAction(obj.nextId(),
                                        NEXT_ID_ACTIONS.get(tableId)))
                .build();
    }
}
 
Example 2
Source File: CiscoN9kPipeliner.java    From onos with Apache License 2.0 6 votes vote down vote up
@Override
public void forward(ForwardingObjective forwardObjective) {
    ForwardingObjective newFwd = forwardObjective;
    Device device = deviceService.getDevice(deviceId);

    if (forwardObjective.treatment() != null && forwardObjective.treatment().clearedDeferred()) {
        log.warn("Using 'clear actions' instruction which is not supported by {} {} {} Switch"
                        + " removing the clear deferred from the forwarding objective",
                device.id(), device.manufacturer(), device.hwVersion());
        newFwd = forwardingObjectiveWithoutCleardDef(forwardObjective).orElse(forwardObjective);
    }

    EthTypeCriterion ethType =
            (EthTypeCriterion) newFwd.selector().getCriterion(Criterion.Type.ETH_TYPE);
    if (ethType != null && ethType.ethType() == EthType.EtherType.IPV6.ethType()) {
        log.error("IPv6 type not supported for {} {} {} Switch, " +
                        "The FlowRule associated with IPv6 is dropped.",
                device.id(), device.manufacturer(), device.hwVersion());
        return;
    }

    super.forward(newFwd);
}
 
Example 3
Source File: OpenVSwitchPipeline.java    From onos with Apache License 2.0 6 votes vote down vote up
private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
    log.debug("Processing versatile forwarding objective");
    TrafficSelector selector = fwd.selector();
    TrafficTreatment tb = fwd.treatment();
    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority())
            .forDevice(deviceId).withSelector(selector).withTreatment(tb).makeTemporary(TIME_OUT);
    ruleBuilder.withPriority(fwd.priority());
    if (fwd.priority() == 100) {
        ruleBuilder.forTable(ENCAP_OUTPUT_TABLE);
    } else if (fwd.priority() == 200) {
        ruleBuilder.forTable(TUN_SEND_TABLE);
    } else {
        ruleBuilder.forTable(CLASSIFIER_TABLE);
    }

    if (fwd.permanent()) {
        ruleBuilder.makePermanent();
    }
    return Collections.singletonList(ruleBuilder.build());
}
 
Example 4
Source File: BasicPipelinerImpl.java    From onos with Apache License 2.0 5 votes vote down vote up
@Override
public void forward(ForwardingObjective obj) {
    if (obj.treatment() == null) {
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Simply create an equivalent FlowRule for table 0.
    final FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
            .forTable(INGRESS_TABLE0_CONTROL_TABLE0)
            .forDevice(deviceId)
            .withSelector(obj.selector())
            .fromApp(obj.appId())
            .withPriority(obj.priority())
            .withTreatment(obj.treatment());

    if (obj.permanent()) {
        ruleBuilder.makePermanent();
    } else {
        ruleBuilder.makeTemporary(obj.timeout());
    }

    switch (obj.op()) {
        case ADD:
            flowRuleService.applyFlowRules(ruleBuilder.build());
            break;
        case REMOVE:
            flowRuleService.removeFlowRules(ruleBuilder.build());
            break;
        default:
            log.warn("Unknown operation {}", obj.op());
    }

    obj.context().ifPresent(c -> c.onSuccess(obj));
}
 
Example 5
Source File: PicaPipeline.java    From onos with Apache License 2.0 5 votes vote down vote up
private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
    log.debug("Processing versatile forwarding objective");
    TrafficSelector selector = fwd.selector();
    TrafficTreatment treatment = fwd.treatment();
    Collection<FlowRule> flowrules = new ArrayList<FlowRule>();

    // first add this rule for basic single-table operation
    // or non-ARP related multi-table operation
    FlowRule rule = DefaultFlowRule.builder()
            .forDevice(deviceId)
            .withSelector(selector)
            .withTreatment(treatment)
            .withPriority(fwd.priority())
            .fromApp(fwd.appId())
            .makePermanent()
            .forTable(ACL_TABLE).build();
    flowrules.add(rule);

    EthTypeCriterion ethType =
            (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
    if (ethType == null) {
        log.warn("No ethType in versatile forwarding obj. Not processing further.");
        return flowrules;
    }

    // now deal with possible mix of ARP with filtering objectives
    // in multi-table scenarios
    if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) {
        if (filters.isEmpty()) {
            pendingVersatiles.add(fwd);
            return flowrules;
        }
        for (Filter filter : filters) {
            flowrules.addAll(processVersatilesWithFilters(filter, fwd));
        }
    }
    return flowrules;
}
 
Example 6
Source File: OltPipeline.java    From onos with Apache License 2.0 5 votes vote down vote up
@Override
public void forward(ForwardingObjective fwd) {
    log.debug("Installing forwarding objective {}", fwd);
    if (checkForMulticast(fwd)) {
        processMulticastRule(fwd);
        return;
    }

    TrafficTreatment treatment = fwd.treatment();

    List<Instruction> instructions = treatment.allInstructions();

    Optional<Instruction> vlanInstruction = instructions.stream()
            .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
            .filter(i -> ((L2ModificationInstruction) i).subtype() ==
                    L2ModificationInstruction.L2SubType.VLAN_PUSH ||
                    ((L2ModificationInstruction) i).subtype() ==
                            L2ModificationInstruction.L2SubType.VLAN_POP)
            .findAny();


    if (!vlanInstruction.isPresent()) {
        installNoModificationRules(fwd);
    } else {
        L2ModificationInstruction vlanIns =
                (L2ModificationInstruction) vlanInstruction.get();
        if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
            installUpstreamRules(fwd);
        } else if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
            installDownstreamRules(fwd);
        } else {
            log.error("Unknown OLT operation: {}", fwd);
            fail(fwd, ObjectiveError.UNSUPPORTED);
            return;
        }
    }

    pass(fwd);

}
 
Example 7
Source File: ForwardingObjectiveCodec.java    From onos with Apache License 2.0 5 votes vote down vote up
@Override
public ObjectNode encode(ForwardingObjective forwardingObjective, CodecContext context) {

    checkNotNull(forwardingObjective, NOT_NULL_MESSAGE);

    final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class);
    final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class);

    // encode common properties
    ObjectiveCodecHelper och = new ObjectiveCodecHelper();
    ObjectNode result = och.encode(forwardingObjective, context);

    // encode id
    result.put(ID, forwardingObjective.id());

    // encode flag
    result.put(FLAG, forwardingObjective.flag().toString());

    // encode op
    result.put(OPERATION, forwardingObjective.op().toString());

    // encode selector
    ObjectNode trafficSelectorNode =
            trafficSelectorCodec.encode(forwardingObjective.selector(), context);
    result.set(SELECTOR, trafficSelectorNode);

    // encode nextId
    if (forwardingObjective.nextId() != null) {
        result.put(NEXT_ID, forwardingObjective.nextId());
    }

    // encode treatment
    if (forwardingObjective.treatment() != null) {
        ObjectNode trafficTreatmentNode =
                trafficTreatmentCodec.encode(forwardingObjective.treatment(), context);
        result.set(TREATMENT, trafficTreatmentNode);
    }

    return result;
}
 
Example 8
Source File: OfdpaPipelineUtility.java    From onos with Apache License 2.0 5 votes vote down vote up
/**
 * Returns true iff the forwarding objective includes a treatment to pop the
 * MPLS label.
 *
 * @param fwd the given forwarding objective
 * @return true iff mpls pop treatment exists
 */
static boolean isMplsPop(ForwardingObjective fwd) {
    if (fwd.treatment() != null) {
        for (Instruction instr : fwd.treatment().allInstructions()) {
            if (instr instanceof L2ModificationInstruction
                    && ((L2ModificationInstruction) instr)
                    .subtype() == L2SubType.MPLS_POP) {
                return true;
            }
        }
    }
    return false;
}
 
Example 9
Source File: AristaPipeliner.java    From onos with Apache License 2.0 5 votes vote down vote up
@Override
public void forward(ForwardingObjective forwardObjective) {
    ForwardingObjective newFwd = forwardObjective;
    Device device = deviceService.getDevice(deviceId);

    if (forwardObjective.treatment() != null && forwardObjective.treatment().clearedDeferred()) {
        log.warn("Using 'clear actions' instruction which is not supported by {} {} {} Switch"
                        + " removing the clear deferred from the forwarding objective",
                device.id(), device.manufacturer(), device.hwVersion());
        newFwd = forwardingObjectiveWithoutCleardDef(forwardObjective).orElse(forwardObjective);
    }

    super.forward(newFwd);
}
 
Example 10
Source File: Ofdpa2Pipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
/**
 * Helper function to create traffic treatment builder for versatile forwarding objectives.
 *
 * @param fwd original forwarding objective
 * @return treatment builder for the flow rule, or null if there is an error.
 */
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.add(o);
                } 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;
}
 
Example 11
Source File: OpenVSwitchPipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
    log.debug("Processing specific forwarding objective");
    TrafficSelector selector = fwd.selector();
    TrafficTreatment tb = fwd.treatment();
    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
            .fromApp(fwd.appId()).withPriority(fwd.priority())
            .forDevice(deviceId).withSelector(selector)
            .withTreatment(tb).makeTemporary(TIME_OUT);
    ruleBuilder.withPriority(fwd.priority());
    if (fwd.permanent()) {
        ruleBuilder.makePermanent();
    }
    Integer transition = null;
    Integer forTable = null;
    // MAC table flow rules
    if (selector.getCriterion(Type.TUNNEL_ID) != null
            && (selector.getCriterion(Type.ETH_DST) != null
                    || selector.getCriterion(Type.ETH_SRC) != null)) {
        forTable = MAC_TABLE;
        return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
    }
    // CLASSIFIER table flow rules
    if (selector.getCriterion(Type.IN_PORT) != null) {
        forTable = CLASSIFIER_TABLE;
        if (selector.getCriterion(Type.ETH_SRC) != null
                && selector.getCriterion(Type.ETH_DST) != null) {
            transition = L3FWD_TABLE;
        } else if (selector.getCriterion(Type.ETH_SRC) != null
                || selector.getCriterion(Type.TUNNEL_ID) != null) {
            transition = MAC_TABLE;
        } else if (selector.getCriterion(Type.IPV4_DST) != null) {
            transition = DNAT_TABLE;
        } else if (selector.getCriterion(Type.ETH_TYPE) != null
                && selector.getCriterion(Type.ETH_TYPE).equals(Criteria
                        .matchEthType(EtherType.ARP.ethType().toShort()))) {
            transition = ARP_TABLE;
        }
        return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
    }
    // ARP table flow rules
    if (selector.getCriterion(Type.ETH_TYPE) != null
            && selector.getCriterion(Type.ETH_TYPE).equals(Criteria
                    .matchEthType(EtherType.ARP.ethType().toShort()))) {
        // CLASSIFIER table arp flow rules
        if (selector.getCriterion(Type.TUNNEL_ID) == null) {
            if (selector.getCriterion(Type.ARP_OP) != null) {
                forTable = CLASSIFIER_TABLE;
                return reassemblyFlowRule(ruleBuilder, tb, null, forTable);
            }
            transition = ARP_TABLE;
            forTable = CLASSIFIER_TABLE;
            return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
        }
        forTable = ARP_TABLE;
        return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
    }
    // SNAT table flow rules
    if (selector.getCriterion(Type.TUNNEL_ID) != null
            && selector.getCriterion(Type.IPV4_SRC) != null) {
        transition = MAC_TABLE;
        forTable = SNAT_TABLE;
        return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
    }
    // L3FWD table flow rules
    if (selector.getCriterion(Type.TUNNEL_ID) != null
            && selector.getCriterion(Type.IPV4_DST) != null) {
        transition = MAC_TABLE;
        forTable = L3FWD_TABLE;
        return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
    }
    // DNAT table flow rules
    if (selector.getCriterion(Type.IPV4_DST) != null) {
        IPCriterion ipCriterion = (IPCriterion) selector.getCriterion(Type.IPV4_DST);
        IpPrefix ipPrefix = ipCriterion.ip();
        // specific CLASSIFIER table flow rules for userdata
        if (ipPrefix.address().equals(IpAddress.valueOf(USERDATA_IP))) {
            forTable = CLASSIFIER_TABLE;
            transition = MAC_TABLE;
            return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
        }
        transition = L3FWD_TABLE;
        forTable = DNAT_TABLE;
        return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
    }
    return Collections.singletonList(ruleBuilder.build());
}
 
Example 12
Source File: NokiaOltPipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
@Override
public void forward(ForwardingObjective fwd) {

    if (checkForMulticast(fwd)) {
        processMulticastRule(fwd);
        return;
    }

    if (checkForEAPOL(fwd)) {
        log.warn("Discarding EAPOL flow which is not supported on this pipeline");
        return;
    }

    TrafficTreatment treatment = fwd.treatment();

    List<Instruction> instructions = treatment.allInstructions();

    Optional<Instruction> vlanIntruction = instructions.stream()
            .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
            .filter(i -> ((L2ModificationInstruction) i).subtype() ==
                    L2ModificationInstruction.L2SubType.VLAN_PUSH ||
                    ((L2ModificationInstruction) i).subtype() ==
                            L2ModificationInstruction.L2SubType.VLAN_POP)
            .findAny();

    if (vlanIntruction.isPresent()) {
        L2ModificationInstruction vlanIns =
                (L2ModificationInstruction) vlanIntruction.get();

        if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
            installUpstreamRules(fwd);
        } else if (vlanIns.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
            installDownstreamRules(fwd);
        } else {
            log.error("Unknown OLT operation: {}", fwd);
            fail(fwd, ObjectiveError.UNSUPPORTED);
            return;
        }

        pass(fwd);
    } else {
        TrafficSelector selector = fwd.selector();

        if (fwd.treatment() != null) {
            // Deal with SPECIFIC and VERSATILE in the same manner.
            FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
                    .forDevice(deviceId)
                    .withSelector(selector)
                    .fromApp(fwd.appId())
                    .withPriority(fwd.priority())
                    .withTreatment(fwd.treatment());

            if (fwd.permanent()) {
                ruleBuilder.makePermanent();
            } else {
                ruleBuilder.makeTemporary(fwd.timeout());
            }
            installObjective(ruleBuilder, fwd);

        } else {
            log.error("No treatment error: {}", fwd);
            fail(fwd, ObjectiveError.UNSUPPORTED);
        }
    }

}
 
Example 13
Source File: Ofdpa2Pipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
/**
 * 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;
}
 
Example 14
Source File: PipelinerImpl.java    From ngsdn-tutorial with Apache License 2.0 4 votes vote down vote up
@Override
public void forward(ForwardingObjective obj) {
    if (obj.treatment() == null) {
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Whether this objective specifies an OUTPUT:CONTROLLER instruction.
    final boolean hasCloneToCpuAction = obj.treatment()
            .allInstructions().stream()
            .filter(i -> i.type().equals(OUTPUT))
            .map(i -> (Instructions.OutputInstruction) i)
            .anyMatch(i -> i.port().equals(PortNumber.CONTROLLER));

    if (!hasCloneToCpuAction) {
        // We support only objectives for clone to CPU behaviours (e.g. for
        // host and link discovery)
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Create an equivalent FlowRule with same selector and clone_to_cpu action.
    final PiAction cloneToCpuAction = PiAction.builder()
            .withId(PiActionId.of(CLONE_TO_CPU))
            .build();

    final FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
            .forTable(PiTableId.of(ACL_TABLE))
            .forDevice(deviceId)
            .withSelector(obj.selector())
            .fromApp(obj.appId())
            .withPriority(obj.priority())
            .withTreatment(DefaultTrafficTreatment.builder()
                                   .piTableAction(cloneToCpuAction).build());

    if (obj.permanent()) {
        ruleBuilder.makePermanent();
    } else {
        ruleBuilder.makeTemporary(obj.timeout());
    }

    final GroupDescription cloneGroup = Utils.buildCloneGroup(
            obj.appId(),
            deviceId,
            CPU_CLONE_SESSION_ID,
            // Ports where to clone the packet.
            // Just controller in this case.
            Collections.singleton(PortNumber.CONTROLLER));

    switch (obj.op()) {
        case ADD:
            flowRuleService.applyFlowRules(ruleBuilder.build());
            groupService.addGroup(cloneGroup);
            break;
        case REMOVE:
            flowRuleService.removeFlowRules(ruleBuilder.build());
            groupService.removeGroup(deviceId, cloneGroup.appCookie(), obj.appId());
            break;
        default:
            log.warn("Unknown operation {}", obj.op());
    }

    obj.context().ifPresent(c -> c.onSuccess(obj));
}
 
Example 15
Source File: Ofdpa2Pipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
/**
 * In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the
 * ACL table.
 * @param fwd  the forwarding objective of type 'versatile'
 * @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
 */
protected Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
    log.debug("Processing versatile forwarding objective:{} in dev:{}",
             fwd.id(), deviceId);
    List<FlowRule> flowRules = new ArrayList<>();
    final AtomicBoolean ethTypeUsed  = new AtomicBoolean(false);

    if (fwd.nextId() == null && fwd.treatment() == null) {
        log.error("Forwarding objective {} from {} must contain "
                + "nextId or Treatment", fwd.selector(), fwd.appId());
        fail(fwd, ObjectiveError.BADPARAMS);
        return Collections.emptySet();
    }

    TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
    fwd.selector().criteria().forEach(criterion -> {
        if (criterion instanceof VlanIdCriterion) {
            VlanId vlanId = ((VlanIdCriterion) criterion).vlanId();
            // ensure that match does not include vlan = NONE as OF-DPA does not
            // match untagged packets this way in the ACL table.
            if (vlanId.equals(VlanId.NONE)) {
                return;
            }
            if (requireVlanExtensions()) {
                OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vlanId);
                sbuilder.extension(ofdpaMatchVlanVid, deviceId);
            } else {
                sbuilder.matchVlanId(vlanId);
            }
        } else if (criterion instanceof Icmpv6TypeCriterion) {
            byte icmpv6Type = (byte) ((Icmpv6TypeCriterion) criterion).icmpv6Type();
            sbuilder.matchIcmpv6Type(icmpv6Type);
        } else if (criterion instanceof Icmpv6CodeCriterion) {
            byte icmpv6Code = (byte) ((Icmpv6CodeCriterion) criterion).icmpv6Code();
            sbuilder.matchIcmpv6Type(icmpv6Code);
        } else if (criterion instanceof TcpPortCriterion || criterion instanceof UdpPortCriterion) {
            // FIXME: QMX switches do not support L4 dst port matching in ACL table.
            // Currently L4 dst port matching is only used by DHCP relay feature
            // and therefore is safe to be replaced with L4 src port matching.
            // We need to revisit this if L4 dst port is used for other purpose in the future.
            if (!supportIpv6L4Dst() && isIpv6(fwd.selector())) {
                switch (criterion.type()) {
                    case UDP_DST:
                    case UDP_DST_MASKED:
                    case TCP_DST:
                    case TCP_DST_MASKED:
                        break;
                    default:
                        sbuilder.add(criterion);
                }
            } else {
                sbuilder.add(criterion);
            }
        } else if (criterion instanceof EthTypeCriterion) {
            sbuilder.add(criterion);
            ethTypeUsed.set(true);
        } else {
            sbuilder.add(criterion);
        }
    });

    TrafficTreatment.Builder ttBuilder = versatileTreatmentBuilder(fwd);
    if (ttBuilder == null) {
        return Collections.emptySet();
    }

    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
            .fromApp(fwd.appId())
            .withPriority(fwd.priority())
            .forDevice(deviceId)
            .withSelector(sbuilder.build())
            .withTreatment(ttBuilder.build())
            .makePermanent()
            .forTable(ACL_TABLE);

    flowRules.add(ruleBuilder.build());

    if (!ethTypeUsed.get() && requireEthType()) {
        log.debug("{} doesn't match on ethType but requireEthType is true, adding complementary ACL flow.",
                  sbuilder.toString());
        sbuilder.matchEthType(Ethernet.TYPE_IPV6);
        FlowRule.Builder ethTypeRuleBuilder = DefaultFlowRule.builder()
                .fromApp(fwd.appId())
                .withPriority(fwd.priority())
                .forDevice(deviceId)
                .withSelector(sbuilder.build())
                .withTreatment(ttBuilder.build())
                .makePermanent()
                .forTable(ACL_TABLE);
        flowRules.add(ethTypeRuleBuilder.build());
    }
    return flowRules;
}
 
Example 16
Source File: Ofdpa2Pipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
/**
 * 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
 */
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 OutputInstruction).findFirst();
    if (!outInstr.isPresent()) {
        log.error("Egress forwarding objective:{} must include output port", fwd.id());
        fail(fwd, ObjectiveError.BADPARAMS);
        return rules;
    }

    PortNumber portNumber = ((OutputInstruction) outInstr.get()).port();

    sb.matchVlanId(vlanIdCriterion.vlanId());
    OfdpaMatchActsetOutput actsetOutput = new OfdpaMatchActsetOutput(portNumber);
    sb.extension(actsetOutput, deviceId);

    sb.extension(new OfdpaMatchAllowVlanTranslation(ALLOW_VLAN_TRANSLATION), deviceId);

    // Build a flow rule for Egress VLAN Flow table
    TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
    tb.transition(EGRESS_DSCP_PCP_REMARK_FLOW_TABLE);
    if (fwd.treatment() != null) {
        for (Instruction instr : fwd.treatment().allInstructions()) {
            if (instr instanceof L2ModificationInstruction &&
                    ((L2ModificationInstruction) instr).subtype() == L2SubType.VLAN_ID) {
                tb.immediate().add(instr);
            }
            if (instr instanceof L2ModificationInstruction &&
                    ((L2ModificationInstruction) instr).subtype() == L2SubType.VLAN_PUSH) {
                tb.immediate().pushVlan();
                EthType ethType = ((L2ModificationInstruction.ModVlanHeaderInstruction) instr).ethernetType();
                if (ethType.equals(EtherType.QINQ.ethType())) {
                    // Build a flow rule for Egress TPID Flow table
                    TrafficSelector tpidSelector = DefaultTrafficSelector.builder()
                            .extension(actsetOutput, deviceId)
                            .matchVlanId(VlanId.ANY).build();

                    TrafficTreatment tpidTreatment = DefaultTrafficTreatment.builder()
                            .extension(new Ofdpa3CopyField(COPY_FIELD_NBITS, COPY_FIELD_OFFSET,
                                                           COPY_FIELD_OFFSET, OXM_ID_VLAN_VID,
                                                           OXM_ID_PACKET_REG_1),
                                       deviceId)
                            .popVlan()
                            .pushVlan(EtherType.QINQ.ethType())
                            .extension(new Ofdpa3CopyField(COPY_FIELD_NBITS, COPY_FIELD_OFFSET,
                                                           COPY_FIELD_OFFSET, OXM_ID_PACKET_REG_1,
                                                           OXM_ID_VLAN_VID),
                                       deviceId)
                            .build();

                    FlowRule.Builder tpidRuleBuilder = DefaultFlowRule.builder()
                            .fromApp(fwd.appId())
                            .withPriority(fwd.priority())
                            .forDevice(deviceId)
                            .withSelector(tpidSelector)
                            .withTreatment(tpidTreatment)
                            .makePermanent()
                            .forTable(EGRESS_TPID_FLOW_TABLE);
                    rules.add(tpidRuleBuilder.build());
                }
            }
        }
    }

    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);
    rules.add(ruleBuilder.build());
    return rules;
}
 
Example 17
Source File: OvsOfdpaPipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
@Override
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(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();
    // Do not match MacAddress for subnet broadcast entry
    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 {
        log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} "
                        + "in dev:{} for vlan:{}",
                fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId());
    }
    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;
}
 
Example 18
Source File: OvsOfdpaPipeline.java    From onos with Apache License 2.0 4 votes vote down vote up
/**
 * 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;
}
 
Example 19
Source File: PipelinerImpl.java    From onos-p4-tutorial with Apache License 2.0 4 votes vote down vote up
@Override
public void forward(ForwardingObjective obj) {
    if (obj.treatment() == null) {
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Whether this objective specifies an OUTPUT:CONTROLLER instruction.
    final boolean hasCloneToCpuAction = obj.treatment()
            .allInstructions().stream()
            .filter(i -> i.type().equals(OUTPUT))
            .map(i -> (Instructions.OutputInstruction) i)
            .anyMatch(i -> i.port().equals(PortNumber.CONTROLLER));

    if (!hasCloneToCpuAction) {
        // We support only objectives for clone to CPU behaviours (e.g. for
        // host and link discovery)
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Create an equivalent FlowRule with same selector and clone_to_cpu action.
    final PiAction cloneToCpuAction = PiAction.builder()
            .withId(PiActionId.of(CLONE_TO_CPU))
            .build();

    final FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
            .forTable(PiTableId.of(ACL_TABLE))
            .forDevice(deviceId)
            .withSelector(obj.selector())
            .fromApp(obj.appId())
            .withPriority(obj.priority())
            .withTreatment(DefaultTrafficTreatment.builder()
                                   .piTableAction(cloneToCpuAction).build());

    if (obj.permanent()) {
        ruleBuilder.makePermanent();
    } else {
        ruleBuilder.makeTemporary(obj.timeout());
    }

    final GroupDescription cloneGroup = Utils.buildCloneGroup(
            obj.appId(),
            deviceId,
            CPU_CLONE_SESSION_ID,
            // Ports where to clone the packet.
            // Just controller in this case.
            Collections.singleton(PortNumber.CONTROLLER));

    switch (obj.op()) {
        case ADD:
            flowRuleService.applyFlowRules(ruleBuilder.build());
            groupService.addGroup(cloneGroup);
            break;
        case REMOVE:
            flowRuleService.removeFlowRules(ruleBuilder.build());
            groupService.removeGroup(deviceId, cloneGroup.appCookie(), obj.appId());
            break;
        default:
            log.warn("Unknown operation {}", obj.op());
    }

    obj.context().ifPresent(c -> c.onSuccess(obj));
}
 
Example 20
Source File: PipelinerImpl.java    From onos-p4-tutorial with Apache License 2.0 4 votes vote down vote up
@Override
public void forward(ForwardingObjective obj) {
    if (obj.treatment() == null) {
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Whether this objective specifies an OUTPUT:CONTROLLER instruction.
    final boolean hasCloneToCpuAction = obj.treatment()
            .allInstructions().stream()
            .filter(i -> i.type().equals(OUTPUT))
            .map(i -> (Instructions.OutputInstruction) i)
            .anyMatch(i -> i.port().equals(PortNumber.CONTROLLER));

    if (!hasCloneToCpuAction) {
        // We support only objectives for clone to CPU behaviours (e.g. for
        // host and link discovery)
        obj.context().ifPresent(c -> c.onError(obj, ObjectiveError.UNSUPPORTED));
    }

    // Create an equivalent FlowRule with same selector and clone_to_cpu action.
    final PiAction cloneToCpuAction = PiAction.builder()
            .withId(PiActionId.of(CLONE_TO_CPU))
            .build();

    final FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
            .forTable(PiTableId.of(ACL_TABLE))
            .forDevice(deviceId)
            .withSelector(obj.selector())
            .fromApp(obj.appId())
            .withPriority(obj.priority())
            .withTreatment(DefaultTrafficTreatment.builder()
                                   .piTableAction(cloneToCpuAction).build());

    if (obj.permanent()) {
        ruleBuilder.makePermanent();
    } else {
        ruleBuilder.makeTemporary(obj.timeout());
    }

    final GroupDescription cloneGroup = Utils.buildCloneGroup(
            obj.appId(),
            deviceId,
            CPU_CLONE_SESSION_ID,
            // Ports where to clone the packet.
            // Just controller in this case.
            Collections.singleton(PortNumber.CONTROLLER));

    switch (obj.op()) {
        case ADD:
            flowRuleService.applyFlowRules(ruleBuilder.build());
            groupService.addGroup(cloneGroup);
            break;
        case REMOVE:
            flowRuleService.removeFlowRules(ruleBuilder.build());
            groupService.removeGroup(deviceId, cloneGroup.appCookie(), obj.appId());
            break;
        default:
            log.warn("Unknown operation {}", obj.op());
    }

    obj.context().ifPresent(c -> c.onSuccess(obj));
}