Search in sources :

Example 16 with NextGroup

use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.

the class PicaPipeline method processSpecific.

private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
    log.debug("Processing specific forwarding objective");
    TrafficSelector selector = fwd.selector();
    EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
    if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) {
        fail(fwd, ObjectiveError.UNSUPPORTED);
        return Collections.emptySet();
    }
    List<FlowRule> ipflows = new ArrayList<FlowRule>();
    for (Filter f : filters) {
        TrafficSelector filteredSelector = DefaultTrafficSelector.builder().matchEthType(Ethernet.TYPE_IPV4).matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()).matchEthDst(f.mac()).matchVlanId(f.vlanId()).build();
        TrafficTreatment tt = null;
        if (fwd.nextId() != null) {
            NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
            if (next == null) {
                log.error("next-id {} does not exist in store", fwd.nextId());
                return Collections.emptySet();
            }
            tt = appKryo.deserialize(next.data());
            if (tt == null) {
                log.error("Error in deserializing next-id {}", fwd.nextId());
                return Collections.emptySet();
            }
        }
        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector).withTreatment(tt);
        if (fwd.permanent()) {
            ruleBuilder.makePermanent();
        } else {
            ruleBuilder.makeTemporary(fwd.timeout());
        }
        ruleBuilder.forTable(IP_UNICAST_TABLE);
        ipflows.add(ruleBuilder.build());
    }
    return ipflows;
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) IPCriterion(org.onosproject.net.flow.criteria.IPCriterion) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) ArrayList(java.util.ArrayList) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment)

Example 17 with NextGroup

use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.

the class SpringOpenTTP method processVersatile.

private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
    log.debug("Processing versatile forwarding objective in dev:{}", deviceId);
    TrafficSelector selector = fwd.selector();
    EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
    if (ethType == null) {
        log.error("Versatile forwarding objective must include ethType");
        fail(fwd, ObjectiveError.UNKNOWN);
        return Collections.emptySet();
    }
    if (fwd.treatment() == null && fwd.nextId() == null) {
        log.error("VERSATILE forwarding objective needs next objective ID " + "or treatment.");
        return Collections.emptySet();
    }
    // emulation of ACL table (for versatile fwd objective) requires
    // overriding any previous instructions
    TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
    treatmentBuilder.wipeDeferred();
    if (fwd.nextId() != null) {
        NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
        if (next != null) {
            SpringOpenGroup soGroup = appKryo.deserialize(next.data());
            if (soGroup.dummy) {
                // need to convert to flow-actions
                for (Instruction ins : soGroup.treatment.allInstructions()) {
                    treatmentBuilder.add(ins);
                }
            } else {
                GroupKey key = soGroup.key;
                Group group = groupService.getGroup(deviceId, key);
                if (group == null) {
                    log.warn("The group left!");
                    fail(fwd, ObjectiveError.GROUPMISSING);
                    return Collections.emptySet();
                }
                treatmentBuilder.deferred().group(group.id());
                log.debug("Adding OUTGROUP action");
            }
        }
    }
    if (fwd.treatment() != null) {
        if (fwd.treatment().allInstructions().size() == 1 && fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) {
            OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0);
            if (o.port() == PortNumber.CONTROLLER) {
                treatmentBuilder.popVlan();
                treatmentBuilder.punt();
            } else {
                treatmentBuilder.add(o);
            }
        } else {
            for (Instruction ins : fwd.treatment().allInstructions()) {
                treatmentBuilder.add(ins);
            }
        }
    }
    FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(fwd.selector()).withTreatment(treatmentBuilder.build());
    if (fwd.permanent()) {
        ruleBuilder.makePermanent();
    } else {
        ruleBuilder.makeTemporary(fwd.timeout());
    }
    ruleBuilder.forTable(aclTableId);
    return Collections.singletonList(ruleBuilder.build());
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) OutputInstruction(org.onosproject.net.flow.instructions.Instructions.OutputInstruction) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) EthTypeCriterion(org.onosproject.net.flow.criteria.EthTypeCriterion) GroupKey(org.onosproject.net.group.GroupKey) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) TrafficSelector(org.onosproject.net.flow.TrafficSelector) DefaultTrafficSelector(org.onosproject.net.flow.DefaultTrafficSelector) DefaultFlowRule(org.onosproject.net.flow.DefaultFlowRule) FlowRule(org.onosproject.net.flow.FlowRule) 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) ModVlanIdInstruction(org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction) Instruction(org.onosproject.net.flow.instructions.Instruction)

Example 18 with NextGroup

use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.

the class Ofdpa2GroupHandler method addBucketToL2FloodGroup.

private void addBucketToL2FloodGroup(NextObjective nextObj, List<Deque<GroupKey>> allActiveKeys, List<GroupInfo> groupInfos, VlanId assignedVlan) {
    Group l2FloodGroup = retrieveTopLevelGroup(allActiveKeys, deviceId, groupService, nextObj.id());
    if (l2FloodGroup == null) {
        log.warn("Can't find L2 flood group while adding bucket to it. NextObj = {}", nextObj);
        fail(nextObj, ObjectiveError.GROUPMISSING);
        return;
    }
    GroupKey l2floodGroupKey = l2FloodGroup.appCookie();
    int l2floodGroupId = l2FloodGroup.id().id();
    List<GroupBucket> newBuckets = generateNextGroupBuckets(groupInfos, ALL);
    GroupDescription l2FloodGroupDescription = new DefaultGroupDescription(deviceId, ALL, new GroupBuckets(newBuckets), l2floodGroupKey, l2floodGroupId, nextObj.appId());
    GroupChainElem l2FloodGroupChainElement = new GroupChainElem(l2FloodGroupDescription, groupInfos.size(), true, deviceId);
    // ensure assignedVlan applies to the chosen group
    VlanId floodGroupVlan = extractVlanIdFromGroupId(l2floodGroupId);
    if (!floodGroupVlan.equals(assignedVlan)) {
        log.warn("VLAN ID {} does not match Flood group {} to which bucket is " + "being added, for next:{} in dev:{}. Abort.", assignedVlan, Integer.toHexString(l2floodGroupId), nextObj.id(), deviceId);
        fail(nextObj, ObjectiveError.BADPARAMS);
        return;
    }
    List<Deque<GroupKey>> addedKeys = new ArrayList<>();
    groupInfos.forEach(groupInfo -> {
        // update original NextGroup with new bucket-chain
        Deque<GroupKey> newBucketChain = new ArrayDeque<>();
        newBucketChain.addFirst(groupInfo.nextGroupDesc().appCookie());
        newBucketChain.addFirst(l2floodGroupKey);
        addedKeys.add(newBucketChain);
        log.debug("Adding to L2FLOOD: device:{} gid:{} group key:{} nextId:{}", deviceId, Integer.toHexString(l2floodGroupId), l2floodGroupKey, nextObj.id());
        // send the innermost group
        log.debug("Sending innermost group {} in group chain on device {} ", Integer.toHexString(groupInfo.innerMostGroupDesc().givenGroupId()), deviceId);
        updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), l2FloodGroupChainElement);
        DeviceId innerMostGroupDevice = groupInfo.innerMostGroupDesc().deviceId();
        GroupKey innerMostGroupKey = groupInfo.innerMostGroupDesc().appCookie();
        Group existsL2IGroup = groupService.getGroup(innerMostGroupDevice, innerMostGroupKey);
        if (existsL2IGroup != null) {
            // group already exist
            processPendingAddGroupsOrNextObjs(innerMostGroupKey, true);
        } else {
            groupService.addGroup(groupInfo.innerMostGroupDesc());
        }
    });
    updatePendingNextObjective(l2floodGroupKey, new OfdpaNextGroup(addedKeys, nextObj));
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) DeviceId(org.onosproject.net.DeviceId) GroupKey(org.onosproject.net.group.GroupKey) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) OfdpaGroupHandlerUtility.l2MulticastGroupKey(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) GroupBuckets(org.onosproject.net.group.GroupBuckets) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque) ArrayDeque(java.util.ArrayDeque) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) GroupDescription(org.onosproject.net.group.GroupDescription) GroupBucket(org.onosproject.net.group.GroupBucket) DefaultGroupBucket(org.onosproject.net.group.DefaultGroupBucket) DefaultGroupDescription(org.onosproject.net.group.DefaultGroupDescription) VlanId(org.onlab.packet.VlanId)

Example 19 with NextGroup

use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.

the class Ofdpa2GroupHandler method updateFlowObjectiveStore.

private void updateFlowObjectiveStore(Integer nextId, OfdpaNextGroup nextGrp) {
    synchronized (flowObjectiveStore) {
        // get fresh copy of what the store holds
        NextGroup next = flowObjectiveStore.getNextGroup(nextId);
        if (next == null || nextGrp.nextObjective().op() == Operation.ADD) {
            flowObjectiveStore.putNextGroup(nextId, nextGrp);
            return;
        }
        if (nextGrp.nextObjective().op() == Operation.ADD_TO_EXISTING) {
            List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
            allActiveKeys = Lists.newArrayList(allActiveKeys);
            // then it represents an empty group. Update by replacing empty chain.
            if (allActiveKeys.size() == 1 && allActiveKeys.get(0).size() == 1) {
                allActiveKeys.clear();
            }
            allActiveKeys.addAll(nextGrp.allKeys());
            flowObjectiveStore.putNextGroup(nextId, new OfdpaNextGroup(allActiveKeys, nextGrp.nextObjective()));
        }
    }
}
Also used : NextGroup(org.onosproject.net.behaviour.NextGroup) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque)

Example 20 with NextGroup

use of org.onosproject.net.behaviour.NextGroup in project onos by opennetworkinglab.

the class Ofdpa2GroupHandler method verifyGroup.

/**
 *  Checks existing buckets in {@link NextGroup}  to verify if they match
 *  the buckets in the given {@link NextObjective}. Adds or removes buckets
 *  to ensure that the buckets match up.
 *
 * @param nextObjective the next objective to verify
 * @param next the representation of the existing group which has to be
 *             modified to match the given next objective
 */
protected void verifyGroup(NextObjective nextObjective, NextGroup next) {
    if (nextObjective.type() == NextObjective.Type.SIMPLE) {
        log.warn("verification not supported for indirect group");
        fail(nextObjective, ObjectiveError.UNSUPPORTED);
        return;
    }
    log.trace("Call to verify device:{} nextId:{}", deviceId, nextObjective.id());
    List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
    List<TrafficTreatment> bucketsToCreate = Lists.newArrayList();
    List<Integer> indicesToRemove = Lists.newArrayList();
    // to detect missing buckets and/or duplicate buckets (to be removed)
    for (TrafficTreatment bkt : nextObjective.next()) {
        PortNumber portNumber = readOutPortFromTreatment(bkt);
        int label = readLabelFromTreatment(bkt);
        if (portNumber == null) {
            log.warn("treatment {} of next objective {} has no outport.. " + "cannot remove bucket from group in dev: {}", bkt, nextObjective.id(), deviceId);
            fail(nextObjective, ObjectiveError.BADPARAMS);
            return;
        }
        List<Integer> existing = existingPortAndLabel(allActiveKeys, groupService, deviceId, portNumber, label);
        if (existing.isEmpty()) {
            // if it doesn't exist, mark this bucket for creation
            bucketsToCreate.add(bkt);
        }
        if (existing.size() > 1) {
            // if it exists but there are duplicates, mark the others for removal
            existing.remove(0);
            indicesToRemove.addAll(existing);
        }
    }
    // (not duplicates) respect to the next objective
    if (allActiveKeys.size() > nextObjective.next().size() && // ignore specific case of empty group
    !(nextObjective.next().size() == 0 && allActiveKeys.size() == 1 && allActiveKeys.get(0).size() == 1)) {
        log.warn("Mismatch detected between next and flowobjstore for device {}: " + "nextId:{}, nextObjective-size:{} next-size:{} .. correcting", deviceId, nextObjective.id(), nextObjective.next().size(), allActiveKeys.size());
        List<Integer> otherIndices = indicesToRemoveFromNextGroup(allActiveKeys, nextObjective, groupService, deviceId);
        // Filter out the indices not present
        otherIndices = otherIndices.stream().filter(index -> !indicesToRemove.contains(index)).collect(Collectors.toList());
        // Add all to the final list
        indicesToRemove.addAll(otherIndices);
    }
    log.trace("Buckets to create {}", bucketsToCreate);
    log.trace("Indices to remove {}", indicesToRemove);
    if (!bucketsToCreate.isEmpty()) {
        log.info("creating {} buckets as part of nextId: {} verification", bucketsToCreate.size(), nextObjective.id());
        // create a nextObjective only with these buckets
        NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(nextObjective.id()).withType(nextObjective.type()).withMeta(nextObjective.meta()).fromApp(nextObjective.appId());
        bucketsToCreate.forEach(nextObjBuilder::addTreatment);
        // According to the next type we call the proper add function
        if (nextObjective.type() == NextObjective.Type.HASHED) {
            if (isL2Hash(nextObjective)) {
                addBucketToL2HashGroup(nextObjBuilder.addToExisting(), allActiveKeys);
            } else {
                addBucketToEcmpHashGroup(nextObjBuilder.addToExisting(), allActiveKeys);
            }
        } else {
            addBucketToBroadcastGroup(nextObjBuilder.addToExisting(), allActiveKeys);
        }
    }
    if (!indicesToRemove.isEmpty()) {
        log.info("removing {} buckets as part of nextId: {} verification", indicesToRemove.size(), nextObjective.id());
        List<Deque<GroupKey>> chainsToRemove = Lists.newArrayList();
        indicesToRemove.forEach(index -> chainsToRemove.add(allActiveKeys.get(index)));
        removeBucket(chainsToRemove, nextObjective);
    }
    log.trace("Checking mismatch with GroupStore device:{} nextId:{}", deviceId, nextObjective.id());
    if (bucketsToCreate.isEmpty() && indicesToRemove.isEmpty()) {
        // flowObjective store record is in-sync with nextObjective passed-in
        // Nevertheless groupStore may not be in sync due to bug in the store
        // - see CORD-1844. XXX When this bug is fixed, the rest of this verify
        // method will not be required.
        GroupKey topGroupKey = allActiveKeys.get(0).peekFirst();
        Group topGroup = groupService.getGroup(deviceId, topGroupKey);
        // topGroup should not be null - adding guard
        if (topGroup == null) {
            log.warn("topGroup {} not found in GroupStore device:{}, nextId:{}", topGroupKey, deviceId, nextObjective.id());
            fail(nextObjective, ObjectiveError.GROUPMISSING);
            return;
        }
        int actualGroupSize = topGroup.buckets().buckets().size();
        int objGroupSize = nextObjective.next().size();
        if (actualGroupSize != objGroupSize) {
            log.warn("Mismatch detected in device:{}, nextId:{}, nextObjective-size" + ":{} group-size:{} .. correcting", deviceId, nextObjective.id(), objGroupSize, actualGroupSize);
        }
        if (actualGroupSize > objGroupSize) {
            // Group in the device has more chains
            List<GroupBucket> bucketsToRemove = Lists.newArrayList();
            // check every bucket in the actual group
            for (GroupBucket bucket : topGroup.buckets().buckets()) {
                GroupInstruction g = (GroupInstruction) bucket.treatment().allInstructions().iterator().next();
                // the group pointed to
                GroupId gidToCheck = g.groupId();
                boolean matches = false;
                for (Deque<GroupKey> validChain : allActiveKeys) {
                    if (validChain.size() < 2) {
                        continue;
                    }
                    GroupKey pointedGroupKey = validChain.stream().collect(Collectors.toList()).get(1);
                    Group pointedGroup = groupService.getGroup(deviceId, pointedGroupKey);
                    if (pointedGroup != null && gidToCheck.equals(pointedGroup.id())) {
                        matches = true;
                        break;
                    }
                }
                if (!matches) {
                    log.warn("Removing bucket pointing to groupId:{}", gidToCheck);
                    bucketsToRemove.add(bucket);
                }
            }
            // remove buckets for which there was no record in the obj store
            if (bucketsToRemove.isEmpty()) {
                log.warn("Mismatch detected but could not determine which" + "buckets to remove");
            } else {
                GroupBuckets removeBuckets = new GroupBuckets(bucketsToRemove);
                groupService.removeBucketsFromGroup(deviceId, topGroupKey, removeBuckets, topGroupKey, nextObjective.appId());
            }
        } else if (actualGroupSize < objGroupSize) {
            // Group in the device has less chains
            // should also add buckets not in group-store but in obj-store
            List<GroupBucket> bucketsToAdd = Lists.newArrayList();
            // check every bucket in the obj
            for (Deque<GroupKey> validChain : allActiveKeys) {
                if (validChain.size() < 2) {
                    continue;
                }
                GroupKey pointedGroupKey = validChain.stream().collect(Collectors.toList()).get(1);
                Group pointedGroup = groupService.getGroup(deviceId, pointedGroupKey);
                if (pointedGroup == null) {
                    // group should exist, otherwise cannot be added as bucket
                    continue;
                }
                boolean matches = false;
                for (GroupBucket bucket : topGroup.buckets().buckets()) {
                    GroupInstruction g = (GroupInstruction) bucket.treatment().allInstructions().iterator().next();
                    // the group pointed to
                    GroupId gidToCheck = g.groupId();
                    if (pointedGroup.id().equals(gidToCheck)) {
                        matches = true;
                        break;
                    }
                }
                if (!matches) {
                    log.warn("Adding bucket pointing to groupId:{}", pointedGroup);
                    TrafficTreatment t = DefaultTrafficTreatment.builder().group(pointedGroup.id()).build();
                    // Create the proper bucket according to the next type
                    if (nextObjective.type() == NextObjective.Type.HASHED) {
                        bucketsToAdd.add(DefaultGroupBucket.createSelectGroupBucket(t));
                    } else {
                        bucketsToAdd.add(DefaultGroupBucket.createAllGroupBucket(t));
                    }
                }
            }
            if (bucketsToAdd.isEmpty()) {
                log.warn("Mismatch detected but could not determine which " + "buckets to add");
            } else {
                GroupBuckets addBuckets = new GroupBuckets(bucketsToAdd);
                groupService.addBucketsToGroup(deviceId, topGroupKey, addBuckets, topGroupKey, nextObjective.appId());
            }
        }
    }
    log.trace("Verify done for device:{} nextId:{}", deviceId, nextObjective.id());
    pass(nextObjective);
}
Also used : DefaultNextObjective(org.onosproject.net.flowobjective.DefaultNextObjective) NextObjective(org.onosproject.net.flowobjective.NextObjective) NextGroup(org.onosproject.net.behaviour.NextGroup) Group(org.onosproject.net.group.Group) GroupKey(org.onosproject.net.group.GroupKey) DefaultGroupKey(org.onosproject.net.group.DefaultGroupKey) OfdpaGroupHandlerUtility.l2MulticastGroupKey(org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) GroupBuckets(org.onosproject.net.group.GroupBuckets) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque) GroupId(org.onosproject.core.GroupId) GroupBucket(org.onosproject.net.group.GroupBucket) DefaultGroupBucket(org.onosproject.net.group.DefaultGroupBucket) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) PortNumber(org.onosproject.net.PortNumber) GroupInstruction(org.onosproject.net.flow.instructions.Instructions.GroupInstruction)

Aggregations

NextGroup (org.onosproject.net.behaviour.NextGroup)38 DefaultTrafficTreatment (org.onosproject.net.flow.DefaultTrafficTreatment)25 TrafficTreatment (org.onosproject.net.flow.TrafficTreatment)25 Group (org.onosproject.net.group.Group)23 TrafficSelector (org.onosproject.net.flow.TrafficSelector)18 Deque (java.util.Deque)17 DefaultFlowRule (org.onosproject.net.flow.DefaultFlowRule)17 FlowRule (org.onosproject.net.flow.FlowRule)17 ArrayList (java.util.ArrayList)16 DefaultTrafficSelector (org.onosproject.net.flow.DefaultTrafficSelector)16 Instruction (org.onosproject.net.flow.instructions.Instruction)12 DefaultGroupKey (org.onosproject.net.group.DefaultGroupKey)12 GroupKey (org.onosproject.net.group.GroupKey)12 ArrayDeque (java.util.ArrayDeque)10 L2ModificationInstruction (org.onosproject.net.flow.instructions.L2ModificationInstruction)10 EthTypeCriterion (org.onosproject.net.flow.criteria.EthTypeCriterion)9 OutputInstruction (org.onosproject.net.flow.instructions.Instructions.OutputInstruction)9 IPCriterion (org.onosproject.net.flow.criteria.IPCriterion)8 IpPrefix (org.onlab.packet.IpPrefix)6 DeviceId (org.onosproject.net.DeviceId)6