[VOL-3836] Extract the OLT pipeliners from ONOS
Change-Id: I1a11000b1e92148b5d5230c311202ba4abbb2ca8
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/NokiaOltPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/NokiaOltPipeline.java
deleted file mode 100644
index 667d8cf..0000000
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/NokiaOltPipeline.java
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.driver.pipeline;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalCause;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.NextGroup;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.FlowRuleOperationsContext;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.IPProtocolCriterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveStore;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.group.DefaultGroupBucket;
-import org.onosproject.net.group.DefaultGroupDescription;
-import org.onosproject.net.group.DefaultGroupKey;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupBuckets;
-import org.onosproject.net.group.GroupDescription;
-import org.onosproject.net.group.GroupEvent;
-import org.onosproject.net.group.GroupKey;
-import org.onosproject.net.group.GroupListener;
-import org.onosproject.net.group.GroupService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.StorageService;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.Iterator;
-
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pipeliner for OLT device.
- */
-
-public class NokiaOltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- private static final Integer QQ_TABLE = 1;
- private static final short MCAST_VLAN = 4000;
- private static final String OLTCOOKIES = "olt-cookies-must-be-unique";
- private static final int EAPOL_FLOW_PRIORITY = 1200;
- private final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private GroupService groupService;
- private CoreService coreService;
- private StorageService storageService;
-
- private DeviceId deviceId;
- private ApplicationId appId;
-
-
- protected FlowObjectiveStore flowObjectiveStore;
-
- private Cache<GroupKey, NextObjective> pendingGroups;
-
- protected static KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(GroupKey.class)
- .register(DefaultGroupKey.class)
- .register(OLTPipelineGroup.class)
- .build("OltPipeline");
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- log.debug("Initiate OLT pipeline");
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- coreService = serviceDirectory.get(CoreService.class);
- groupService = serviceDirectory.get(GroupService.class);
- flowObjectiveStore = context.store();
- storageService = serviceDirectory.get(StorageService.class);
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.OLTPipeline");
-
-
- pendingGroups = CacheBuilder.newBuilder()
- .expireAfterWrite(20, TimeUnit.SECONDS)
- .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
- if (notification.getCause() == RemovalCause.EXPIRED) {
- fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
- }
- }).build();
-
- groupService.addListener(new InnerGroupListener());
-
- }
-
- @Override
- public void filter(FilteringObjective filter) {
- Instructions.OutputInstruction output;
-
- if (filter.meta() != null && !filter.meta().immediate().isEmpty()) {
- output = (Instructions.OutputInstruction) filter.meta().immediate().stream()
- .filter(t -> t.type().equals(Instruction.Type.OUTPUT))
- .limit(1)
- .findFirst().get();
-
- if (output == null || !output.port().equals(PortNumber.CONTROLLER)) {
- log.error("OLT can only filter packet to controller");
- fail(filter, ObjectiveError.UNSUPPORTED);
- return;
- }
- } else {
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
-
- if (filter.key().type() != Criterion.Type.IN_PORT) {
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
-
- EthTypeCriterion ethType = (EthTypeCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.ETH_TYPE);
-
- if (ethType == null) {
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
-
- if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) {
- provisionEapol(filter, ethType, output);
- } else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) {
- IPProtocolCriterion ipProto = (IPProtocolCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
- if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) {
- provisionIgmp(filter, ethType, ipProto, output);
- } else {
- log.error("OLT can only filter igmp");
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
- } else {
- log.error("OLT can only filter eapol and igmp");
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
-
- }
-
- private void installObjective(FlowRule.Builder ruleBuilder, Objective objective) {
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
- switch (objective.op()) {
-
- case ADD:
- flowBuilder.add(ruleBuilder.build());
- break;
- case REMOVE:
- flowBuilder.remove(ruleBuilder.build());
- break;
- default:
- log.warn("Unknown operation {}", objective.op());
- }
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- objective.context().ifPresent(context -> context.onSuccess(objective));
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- objective.context()
- .ifPresent(context -> context.onError(objective, ObjectiveError.FLOWINSTALLATIONFAILED));
- }
- }));
- }
-
- @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);
- }
- }
-
- }
-
-
- @Override
- public void next(NextObjective nextObjective) {
- if (nextObjective.type() != NextObjective.Type.BROADCAST) {
- log.error("OLT only supports broadcast groups.");
- fail(nextObjective, ObjectiveError.BADPARAMS);
- }
-
- if (nextObjective.next().size() != 1) {
- log.error("OLT only supports singleton broadcast groups.");
- fail(nextObjective, ObjectiveError.BADPARAMS);
- }
-
- TrafficTreatment treatment = nextObjective.next().stream().findFirst().get();
-
-
- GroupBucket bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
- GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
-
-
- pendingGroups.put(key, nextObjective);
-
- switch (nextObjective.op()) {
- case ADD:
- GroupDescription groupDesc =
- new DefaultGroupDescription(deviceId,
- GroupDescription.Type.ALL,
- new GroupBuckets(Collections.singletonList(bucket)),
- key,
- null,
- nextObjective.appId());
- groupService.addGroup(groupDesc);
- break;
- case REMOVE:
- groupService.removeGroup(deviceId, key, nextObjective.appId());
- break;
- case ADD_TO_EXISTING:
- groupService.addBucketsToGroup(deviceId, key,
- new GroupBuckets(Collections.singletonList(bucket)),
- key, nextObjective.appId());
- break;
- case REMOVE_FROM_EXISTING:
- groupService.removeBucketsFromGroup(deviceId, key,
- new GroupBuckets(Collections.singletonList(bucket)),
- key, nextObjective.appId());
- break;
- default:
- log.warn("Unknown next objective operation: {}", nextObjective.op());
- }
-
-
- }
-
- private void processMulticastRule(ForwardingObjective fwd) {
- if (fwd.nextId() == null) {
- log.error("Multicast objective does not have a next id");
- fail(fwd, ObjectiveError.BADPARAMS);
- }
-
- GroupKey key = getGroupForNextObjective(fwd.nextId());
-
- if (key == null) {
- log.error("Group for forwarding objective missing: {}", fwd);
- fail(fwd, ObjectiveError.GROUPMISSING);
- }
-
- Group group = groupService.getGroup(deviceId, key);
- TrafficTreatment treatment =
- buildTreatment(Instructions.createGroup(group.id()));
-
- FlowRule rule = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(0)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(fwd.selector())
- .withTreatment(treatment)
- .build();
-
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- switch (fwd.op()) {
-
- case ADD:
- builder.add(rule);
- break;
- case REMOVE:
- builder.remove(rule);
- break;
- case ADD_TO_EXISTING:
- case REMOVE_FROM_EXISTING:
- break;
- default:
- log.warn("Unknown forwarding operation: {}", fwd.op());
- }
-
- applyFlowRules(builder, fwd);
-
- }
-
- private boolean checkForMulticast(ForwardingObjective fwd) {
-
- IPCriterion ip = (IPCriterion) filterForCriterion(fwd.selector().criteria(),
- Criterion.Type.IPV4_DST);
-
- if (ip == null) {
- return false;
- }
-
- return ip.ip().isMulticast();
-
- }
-
- private boolean checkForEAPOL(ForwardingObjective fwd) {
- EthTypeCriterion ethType = (EthTypeCriterion)
- filterForCriterion(fwd.selector().criteria(), Criterion.Type.ETH_TYPE);
-
- return ethType != null && ethType.ethType().equals(EthType.EtherType.EAPOL.ethType());
- }
- private GroupKey getGroupForNextObjective(Integer nextId) {
- NextGroup next = flowObjectiveStore.getNextGroup(nextId);
- return appKryo.deserialize(next.data());
-
- }
-
- private void installDownstreamRules(ForwardingObjective fwd) {
- List<Pair<Instruction, Instruction>> vlanOps =
- vlanOps(fwd,
- L2ModificationInstruction.L2SubType.VLAN_POP);
-
- if (vlanOps == null) {
- return;
- }
-
- Instructions.OutputInstruction output = (Instructions.OutputInstruction) fetchOutput(fwd, "downstream");
-
- if (output == null) {
- return;
- }
-
- Pair<Instruction, Instruction> popAndRewrite = vlanOps.remove(0);
-
- TrafficSelector selector = fwd.selector();
-
- Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
- Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
- Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
- Criterion bullshit = Criteria.matchMetadata(output.port().toLong());
-
- if (outerVlan == null || innerVlan == null || inport == null) {
- log.error("Forwarding objective is underspecified: {}", fwd);
- fail(fwd, ObjectiveError.BADPARAMS);
- return;
- }
-
- Criterion innerVid = Criteria.matchVlanId(((VlanIdCriterion) innerVlan).vlanId());
-
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(buildSelector(inport, outerVlan, bullshit))
- .withTreatment(buildTreatment(popAndRewrite.getLeft(),
- Instructions.transition(QQ_TABLE)));
-
- FlowRule.Builder inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(QQ_TABLE)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(buildSelector(inport, innerVid))
- .withTreatment(buildTreatment(popAndRewrite.getLeft(),
- output));
-
- applyRules(fwd, inner, outer);
-
- }
-
- private boolean hasUntaggedVlanTag(TrafficSelector selector) {
- Iterator<Criterion> iter = selector.criteria().iterator();
-
- while (iter.hasNext()) {
- Criterion criterion = iter.next();
- if (criterion.type() == Criterion.Type.VLAN_VID &&
- ((VlanIdCriterion) criterion).vlanId().toShort() == VlanId.UNTAGGED) {
- return true;
- }
- }
-
- return false;
- }
-
- private void installUpstreamRules(ForwardingObjective fwd) {
- List<Pair<Instruction, Instruction>> vlanOps =
- vlanOps(fwd,
- L2ModificationInstruction.L2SubType.VLAN_PUSH);
- FlowRule.Builder inner;
-
- if (vlanOps == null) {
- return;
- }
-
- Instruction output = fetchOutput(fwd, "upstream");
-
- if (output == null) {
- return;
- }
-
- Pair<Instruction, Instruction> innerPair = vlanOps.remove(0);
-
- Pair<Instruction, Instruction> outerPair = vlanOps.remove(0);
-
-
- if (hasUntaggedVlanTag(fwd.selector())) {
- inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(fwd.selector())
- .withTreatment(buildTreatment(innerPair.getLeft(),
- innerPair.getRight(),
- Instructions.transition(QQ_TABLE)));
- } else {
- inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(fwd.selector())
- .withTreatment(buildTreatment(
- innerPair.getRight(),
- Instructions.transition(QQ_TABLE)));
- }
-
-
- PortCriterion inPort = (PortCriterion)
- fwd.selector().getCriterion(Criterion.Type.IN_PORT);
-
- VlanId cVlanId = ((L2ModificationInstruction.ModVlanIdInstruction)
- innerPair.getRight()).vlanId();
-
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(QQ_TABLE)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(buildSelector(inPort,
- Criteria.matchVlanId(cVlanId)))
- .withTreatment(buildTreatment(outerPair.getLeft(),
- outerPair.getRight(),
- output));
-
- applyRules(fwd, inner, outer);
-
- }
-
- private Instruction fetchOutput(ForwardingObjective fwd, String direction) {
- Instruction output = fwd.treatment().allInstructions().stream()
- .filter(i -> i.type() == Instruction.Type.OUTPUT)
- .findFirst().orElse(null);
-
- if (output == null) {
- log.error("OLT {} rule has no output", direction);
- fail(fwd, ObjectiveError.BADPARAMS);
- return null;
- }
- return output;
- }
-
- private List<Pair<Instruction, Instruction>> vlanOps(ForwardingObjective fwd,
- L2ModificationInstruction.L2SubType type) {
-
- List<Pair<Instruction, Instruction>> vlanOps = findVlanOps(
- fwd.treatment().allInstructions(), type);
-
- if (vlanOps == null) {
- String direction = type == L2ModificationInstruction.L2SubType.VLAN_POP
- ? "downstream" : "upstream";
- log.error("Missing vlan operations in {} forwarding: {}", direction, fwd);
- fail(fwd, ObjectiveError.BADPARAMS);
- return null;
- }
- return vlanOps;
- }
-
-
- private List<Pair<Instruction, Instruction>> findVlanOps(List<Instruction> instructions,
- L2ModificationInstruction.L2SubType type) {
-
- List<Instruction> vlanPushs = findL2Instructions(
- type,
- instructions);
- List<Instruction> vlanSets = findL2Instructions(
- L2ModificationInstruction.L2SubType.VLAN_ID,
- instructions);
-
- if (vlanPushs.size() != vlanSets.size()) {
- return null;
- }
-
- List<Pair<Instruction, Instruction>> pairs = Lists.newArrayList();
-
- for (int i = 0; i < vlanPushs.size(); i++) {
- pairs.add(new ImmutablePair<>(vlanPushs.get(i), vlanSets.get(i)));
- }
- return pairs;
- }
-
- private List<Instruction> findL2Instructions(L2ModificationInstruction.L2SubType subType,
- List<Instruction> actions) {
- return actions.stream()
- .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
- .filter(i -> ((L2ModificationInstruction) i).subtype() == subType)
- .collect(Collectors.toList());
- }
-
- private void provisionEapol(FilteringObjective filter,
- EthTypeCriterion ethType,
- Instructions.OutputInstruction output) {
-
- TrafficSelector selector = buildSelector(filter.key(), ethType);
- TrafficTreatment treatment = buildTreatment(output);
- buildAndApplyRule(filter, selector, treatment, EAPOL_FLOW_PRIORITY);
-
- }
-
- private void provisionIgmp(FilteringObjective filter, EthTypeCriterion ethType,
- IPProtocolCriterion ipProto,
- Instructions.OutputInstruction output) {
- TrafficSelector selector = buildSelector(filter.key(), ethType, ipProto);
- TrafficTreatment treatment = buildTreatment(output);
- buildAndApplyRule(filter, selector, treatment);
- }
-
- private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector,
- TrafficTreatment treatment) {
- buildAndApplyRule(filter, selector, treatment, filter.priority());
- }
-
- private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector,
- TrafficTreatment treatment, int priority) {
- FlowRule rule = DefaultFlowRule.builder()
- .fromApp(filter.appId())
- .forDevice(deviceId)
- .forTable(0)
- .makePermanent()
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(priority)
- .build();
-
- FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
-
- switch (filter.type()) {
- case PERMIT:
- opsBuilder.add(rule);
- break;
- case DENY:
- opsBuilder.remove(rule);
- break;
- default:
- log.warn("Unknown filter type : {}", filter.type());
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
-
- applyFlowRules(opsBuilder, filter);
- }
-
- private void applyRules(ForwardingObjective fwd,
- FlowRule.Builder inner, FlowRule.Builder outer) {
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- switch (fwd.op()) {
- case ADD:
- builder.add(inner.build()).add(outer.build());
- break;
- case REMOVE:
- builder.remove(inner.build()).remove(outer.build());
- break;
- case ADD_TO_EXISTING:
- break;
- case REMOVE_FROM_EXISTING:
- break;
- default:
- log.warn("Unknown forwarding operation: {}", fwd.op());
- }
-
- applyFlowRules(builder, fwd);
- }
-
- private void applyFlowRules(FlowRuleOperations.Builder builder,
- Objective objective) {
- flowRuleService.apply(builder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(objective);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(objective, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
- }
-
- private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) {
- return criteria.stream()
- .filter(c -> c.type().equals(type))
- .limit(1)
- .findFirst().orElse(null);
- }
-
- private TrafficSelector buildSelector(Criterion... criteria) {
-
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
- for (Criterion c : criteria) {
- sBuilder.add(c);
- }
-
- return sBuilder.build();
- }
-
- private TrafficTreatment buildTreatment(Instruction... instructions) {
-
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- for (Instruction i : instructions) {
- tBuilder.add(i);
- }
-
- return tBuilder.build();
- }
-
-
- private void fail(Objective obj, ObjectiveError error) {
- obj.context().ifPresent(context -> context.onError(obj, error));
- }
-
- private void pass(Objective obj) {
- obj.context().ifPresent(context -> context.onSuccess(obj));
- }
-
-
- private class InnerGroupListener implements GroupListener {
- @Override
- public void event(GroupEvent event) {
- if (event.type() == GroupEvent.Type.GROUP_ADDED || event.type() == GroupEvent.Type.GROUP_UPDATED) {
- GroupKey key = event.subject().appCookie();
-
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj != null) {
- flowObjectiveStore.putNextGroup(obj.id(), new OLTPipelineGroup(key));
- pass(obj);
- pendingGroups.invalidate(key);
- }
- }
- }
- }
-
- private static class OLTPipelineGroup implements NextGroup {
-
- private final GroupKey key;
-
- public OLTPipelineGroup(GroupKey key) {
- this.key = key;
- }
-
- public GroupKey key() {
- return key;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(key);
- }
-
- }
-
- @Override
- public List<String> getNextMappings(NextGroup nextGroup) {
- // TODO Implementation deferred to vendor
- return null;
- }
-}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java
deleted file mode 100644
index 6790e58..0000000
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java
+++ /dev/null
@@ -1,1287 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.driver.pipeline;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalCause;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onlab.util.AbstractAccumulator;
-import org.onlab.util.Accumulator;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.NextGroup;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.driver.Driver;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.FlowRuleOperationsContext;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.IPProtocolCriterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.criteria.UdpPortCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveStore;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.group.DefaultGroupBucket;
-import org.onosproject.net.group.DefaultGroupDescription;
-import org.onosproject.net.group.DefaultGroupKey;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupBuckets;
-import org.onosproject.net.group.GroupDescription;
-import org.onosproject.net.group.GroupEvent;
-import org.onosproject.net.group.GroupKey;
-import org.onosproject.net.group.GroupListener;
-import org.onosproject.net.group.GroupService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.StorageService;
-import org.slf4j.Logger;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.Timer;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.onosproject.core.CoreService.CORE_APP_NAME;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pipeliner for OLT device.
- */
-
-public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- private static final Integer QQ_TABLE = 1;
- private static final int NO_ACTION_PRIORITY = 500;
- private static final String DOWNSTREAM = "downstream";
- private static final String UPSTREAM = "upstream";
- private final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private GroupService groupService;
- private CoreService coreService;
- private StorageService storageService;
-
- private DeviceId deviceId;
- private ApplicationId appId;
-
-
- protected FlowObjectiveStore flowObjectiveStore;
-
- private Cache<GroupKey, NextObjective> pendingGroups;
-
- protected static KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(GroupKey.class)
- .register(DefaultGroupKey.class)
- .register(OLTPipelineGroup.class)
- .build("OltPipeline");
-
- private static final Timer TIMER = new Timer("filterobj-batching");
- private Accumulator<Pair<FilteringObjective, FlowRule>> accumulator;
-
- // accumulator executor service
- private ScheduledExecutorService accumulatorExecutorService
- = newSingleThreadScheduledExecutor(groupedThreads("OltPipeliner", "acc-%d", log));
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- log.debug("Initiate OLT pipeline");
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- coreService = serviceDirectory.get(CoreService.class);
- groupService = serviceDirectory.get(GroupService.class);
- flowObjectiveStore = context.store();
- storageService = serviceDirectory.get(StorageService.class);
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.OLTPipeline");
-
- // Init the accumulator, if enabled
- if (isAccumulatorEnabled()) {
- log.debug("Building accumulator with maxObjs {}, batchMs {}, idleMs {}",
- context.accumulatorMaxObjectives(), context.accumulatorMaxBatchMillis(),
- context.accumulatorMaxIdleMillis());
- accumulator = new ObjectiveAccumulator(context.accumulatorMaxObjectives(),
- context.accumulatorMaxBatchMillis(),
- context.accumulatorMaxIdleMillis());
- }
-
-
- pendingGroups = CacheBuilder.newBuilder()
- .expireAfterWrite(20, TimeUnit.SECONDS)
- .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
- if (notification.getCause() == RemovalCause.EXPIRED) {
- fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
- }
- }).build();
-
- groupService.addListener(new InnerGroupListener());
-
- }
-
- public boolean isAccumulatorEnabled() {
- Driver driver = super.data().driver();
- // we cannot determine the property
- if (driver == null) {
- return false;
- }
- return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED));
- }
-
- @Override
- public void filter(FilteringObjective filter) {
- Instructions.OutputInstruction output;
-
- if (filter.meta() != null && !filter.meta().immediate().isEmpty()) {
- output = (Instructions.OutputInstruction) filter.meta().immediate().stream()
- .filter(t -> t.type().equals(Instruction.Type.OUTPUT))
- .limit(1)
- .findFirst().get();
-
- if (output == null || !output.port().equals(PortNumber.CONTROLLER)) {
- log.warn("OLT can only filter packet to controller");
- fail(filter, ObjectiveError.UNSUPPORTED);
- return;
- }
- } else {
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
-
- if (filter.key().type() != Criterion.Type.IN_PORT) {
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
-
- EthTypeCriterion ethType = (EthTypeCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.ETH_TYPE);
-
- if (ethType == null) {
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
- Optional<Instruction> vlanId = filter.meta().immediate().stream()
- .filter(t -> t.type().equals(Instruction.Type.L2MODIFICATION)
- && ((L2ModificationInstruction) t).subtype()
- .equals(L2ModificationInstruction.L2SubType.VLAN_ID))
- .limit(1)
- .findFirst();
-
- Optional<Instruction> vlanPcp = filter.meta().immediate().stream()
- .filter(t -> t.type().equals(Instruction.Type.L2MODIFICATION)
- && ((L2ModificationInstruction) t).subtype()
- .equals(L2ModificationInstruction.L2SubType.VLAN_PCP))
- .limit(1)
- .findFirst();
-
- Optional<Instruction> vlanPush = filter.meta().immediate().stream()
- .filter(t -> t.type().equals(Instruction.Type.L2MODIFICATION)
- && ((L2ModificationInstruction) t).subtype()
- .equals(L2ModificationInstruction.L2SubType.VLAN_PUSH))
- .limit(1)
- .findFirst();
-
- if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) {
-
- if (vlanId.isEmpty() || vlanPush.isEmpty()) {
- log.warn("Missing EAPOL vlan or vlanPush");
- fail(filter, ObjectiveError.BADPARAMS);
- return;
- }
- provisionEthTypeBasedFilter(filter, ethType, output,
- (L2ModificationInstruction) vlanId.get(),
- (L2ModificationInstruction) vlanPush.get());
- } else if (ethType.ethType().equals(EthType.EtherType.PPPoED.ethType())) {
- provisionPPPoED(filter, ethType, vlanId.orElse(null), vlanPcp.orElse(null), output);
- } else if (ethType.ethType().equals(EthType.EtherType.LLDP.ethType())) {
- provisionEthTypeBasedFilter(filter, ethType, output, null, null);
- } else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) {
- IPProtocolCriterion ipProto = (IPProtocolCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
- if (ipProto == null) {
- log.warn("OLT can only filter IGMP and DHCP");
- fail(filter, ObjectiveError.UNSUPPORTED);
- return;
- }
- if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) {
- provisionIgmp(filter, ethType, ipProto, output,
- vlanId.orElse(null),
- vlanPcp.orElse(null));
- } else if (ipProto.protocol() == IPv4.PROTOCOL_UDP) {
- UdpPortCriterion udpSrcPort = (UdpPortCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.UDP_SRC);
-
- UdpPortCriterion udpDstPort = (UdpPortCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.UDP_DST);
-
- if ((udpSrcPort.udpPort().toInt() == 67 && udpDstPort.udpPort().toInt() == 68) ||
- (udpSrcPort.udpPort().toInt() == 68 && udpDstPort.udpPort().toInt() == 67)) {
- provisionDhcp(filter, ethType, ipProto, udpSrcPort, udpDstPort, vlanId.orElse(null),
- vlanPcp.orElse(null), output);
- } else {
- log.warn("Filtering rule with unsupported UDP src {} or dst {} port", udpSrcPort, udpDstPort);
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
- } else {
- log.warn("Currently supporting only IGMP and DHCP filters for IPv4 packets");
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
- } else if (ethType.ethType().equals(EthType.EtherType.IPV6.ethType())) {
- IPProtocolCriterion ipProto = (IPProtocolCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO);
- if (ipProto == null) {
- log.warn("OLT can only filter DHCP");
- fail(filter, ObjectiveError.UNSUPPORTED);
- return;
- }
- if (ipProto.protocol() == IPv6.PROTOCOL_UDP) {
- UdpPortCriterion udpSrcPort = (UdpPortCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.UDP_SRC);
-
- UdpPortCriterion udpDstPort = (UdpPortCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.UDP_DST);
-
- if ((udpSrcPort.udpPort().toInt() == 546 && udpDstPort.udpPort().toInt() == 547) ||
- (udpSrcPort.udpPort().toInt() == 547 && udpDstPort.udpPort().toInt() == 546)) {
- provisionDhcp(filter, ethType, ipProto, udpSrcPort, udpDstPort, vlanId.orElse(null),
- vlanPcp.orElse(null), output);
- } else {
- log.warn("Filtering rule with unsupported UDP src {} or dst {} port", udpSrcPort, udpDstPort);
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
- } else {
- log.warn("Currently supporting only DHCP filters for IPv6 packets");
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
- } else {
- log.warn("\nOnly the following are Supported in OLT for filter ->\n"
- + "ETH TYPE : EAPOL, LLDP and IPV4\n"
- + "IPV4 TYPE: IGMP and UDP (for DHCP)"
- + "IPV6 TYPE: UDP (for DHCP)");
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
-
- }
-
-
- @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);
-
- }
-
-
- @Override
- public void next(NextObjective nextObjective) {
- if (nextObjective.type() != NextObjective.Type.BROADCAST) {
- log.error("OLT only supports broadcast groups.");
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
- }
-
- if (nextObjective.next().size() != 1 && !nextObjective.op().equals(Objective.Operation.REMOVE)) {
- log.error("OLT only supports singleton broadcast groups.");
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
- }
-
- Optional<TrafficTreatment> treatmentOpt = nextObjective.next().stream().findFirst();
- if (treatmentOpt.isEmpty() && !nextObjective.op().equals(Objective.Operation.REMOVE)) {
- log.error("Next objective {} does not have a treatment", nextObjective);
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
- }
-
- GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
-
- pendingGroups.put(key, nextObjective);
- log.trace("NextObjective Operation {}", nextObjective.op());
- switch (nextObjective.op()) {
- case ADD:
- GroupDescription groupDesc =
- new DefaultGroupDescription(deviceId,
- GroupDescription.Type.ALL,
- new GroupBuckets(
- Collections.singletonList(
- buildBucket(treatmentOpt.get()))),
- key,
- null,
- nextObjective.appId());
- groupService.addGroup(groupDesc);
- break;
- case REMOVE:
- groupService.removeGroup(deviceId, key, nextObjective.appId());
- break;
- case ADD_TO_EXISTING:
- groupService.addBucketsToGroup(deviceId, key,
- new GroupBuckets(
- Collections.singletonList(
- buildBucket(treatmentOpt.get()))),
- key, nextObjective.appId());
- break;
- case REMOVE_FROM_EXISTING:
- groupService.removeBucketsFromGroup(deviceId, key,
- new GroupBuckets(
- Collections.singletonList(
- buildBucket(treatmentOpt.get()))),
- key, nextObjective.appId());
- break;
- default:
- log.warn("Unknown next objective operation: {}", nextObjective.op());
- }
-
-
- }
-
- private GroupBucket buildBucket(TrafficTreatment treatment) {
- return DefaultGroupBucket.createAllGroupBucket(treatment);
- }
-
- private void processMulticastRule(ForwardingObjective fwd) {
- if (fwd.nextId() == null) {
- log.error("Multicast objective does not have a next id");
- fail(fwd, ObjectiveError.BADPARAMS);
- }
-
- GroupKey key = getGroupForNextObjective(fwd.nextId());
-
- if (key == null) {
- log.error("Group for forwarding objective missing: {}", fwd);
- fail(fwd, ObjectiveError.GROUPMISSING);
- }
-
- Group group = groupService.getGroup(deviceId, key);
- TrafficTreatment treatment =
- buildTreatment(Instructions.createGroup(group.id()));
-
- TrafficSelector.Builder selectorBuilder = buildIpv4SelectorForMulticast(fwd);
-
- FlowRule rule = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(0)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(selectorBuilder.build())
- .withTreatment(treatment)
- .build();
-
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- switch (fwd.op()) {
-
- case ADD:
- builder.add(rule);
- break;
- case REMOVE:
- builder.remove(rule);
- break;
- case ADD_TO_EXISTING:
- case REMOVE_FROM_EXISTING:
- break;
- default:
- log.warn("Unknown forwarding operation: {}", fwd.op());
- }
-
- applyFlowRules(ImmutableList.of(fwd), builder);
-
-
- }
-
- private TrafficSelector.Builder buildIpv4SelectorForMulticast(ForwardingObjective fwd) {
- TrafficSelector.Builder builderToUpdate = DefaultTrafficSelector.builder();
-
- Optional<Criterion> vlanIdCriterion = readFromSelector(fwd.meta(), Criterion.Type.VLAN_VID);
- if (vlanIdCriterion.isPresent()) {
- VlanId assignedVlan = ((VlanIdCriterion) vlanIdCriterion.get()).vlanId();
- builderToUpdate.matchVlanId(assignedVlan);
- }
-
- Optional<Criterion> innerVlanIdCriterion = readFromSelector(fwd.meta(), Criterion.Type.INNER_VLAN_VID);
- if (innerVlanIdCriterion.isPresent()) {
- VlanId assignedInnerVlan = ((VlanIdCriterion) innerVlanIdCriterion.get()).vlanId();
- builderToUpdate.matchMetadata(assignedInnerVlan.toShort());
- }
-
- Optional<Criterion> ethTypeCriterion = readFromSelector(fwd.selector(), Criterion.Type.ETH_TYPE);
- if (ethTypeCriterion.isPresent()) {
- EthType ethType = ((EthTypeCriterion) ethTypeCriterion.get()).ethType();
- builderToUpdate.matchEthType(ethType.toShort());
- }
-
- Optional<Criterion> ipv4DstCriterion = readFromSelector(fwd.selector(), Criterion.Type.IPV4_DST);
- if (ipv4DstCriterion.isPresent()) {
- IpPrefix ipv4Dst = ((IPCriterion) ipv4DstCriterion.get()).ip();
- builderToUpdate.matchIPDst(ipv4Dst);
- }
-
- return builderToUpdate;
- }
-
- static Optional<Criterion> readFromSelector(TrafficSelector selector, Criterion.Type type) {
- if (selector == null) {
- return Optional.empty();
- }
- Criterion criterion = selector.getCriterion(type);
- return (criterion == null)
- ? Optional.empty() : Optional.of(criterion);
- }
-
- private boolean checkForMulticast(ForwardingObjective fwd) {
-
- IPCriterion ip = (IPCriterion) filterForCriterion(fwd.selector().criteria(),
- Criterion.Type.IPV4_DST);
-
- if (ip == null) {
- return false;
- }
-
- return ip.ip().isMulticast();
-
- }
-
- private GroupKey getGroupForNextObjective(Integer nextId) {
- NextGroup next = flowObjectiveStore.getNextGroup(nextId);
- return appKryo.deserialize(next.data());
-
- }
-
- private void installNoModificationRules(ForwardingObjective fwd) {
- Instructions.OutputInstruction output = (Instructions.OutputInstruction) fetchOutput(fwd, DOWNSTREAM);
- Instructions.MetadataInstruction writeMetadata = fetchWriteMetadata(fwd);
- Instructions.MeterInstruction meter = (Instructions.MeterInstruction) fetchMeter(fwd);
-
- TrafficSelector selector = fwd.selector();
-
- Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
- Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
- Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
-
- if (inport == null || output == null || innerVlan == null || outerVlan == null) {
- // Avoid logging a non-error from lldp, bbdp and eapol core flows.
- if (!fwd.appId().name().equals(CORE_APP_NAME)) {
- log.error("Forwarding objective is underspecified: {}", fwd);
- } else {
- log.debug("Not installing unsupported core generated flow {}", fwd);
- }
- fail(fwd, ObjectiveError.BADPARAMS);
- return;
- }
-
-
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(buildSelector(inport, outerVlan))
- .withTreatment(buildTreatment(output, writeMetadata, meter));
-
- applyRules(fwd, outer);
- }
-
- private void installDownstreamRules(ForwardingObjective fwd) {
- Instructions.OutputInstruction output = (Instructions.OutputInstruction) fetchOutput(fwd, DOWNSTREAM);
-
- if (output == null) {
- return;
- }
-
- TrafficSelector selector = fwd.selector();
-
- Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
- Criterion outerPbit = selector.getCriterion(Criterion.Type.VLAN_PCP);
- Criterion innerVlanCriterion = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
- Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
- Criterion dstMac = selector.getCriterion(Criterion.Type.ETH_DST);
-
- if (outerVlan == null || innerVlanCriterion == null || inport == null) {
- // Avoid logging a non-error from lldp, bbdp and eapol core flows.
- if (!fwd.appId().name().equals(CORE_APP_NAME)) {
- log.error("Forwarding objective is underspecified: {}", fwd);
- } else {
- log.debug("Not installing unsupported core generated flow {}", fwd);
- }
- fail(fwd, ObjectiveError.BADPARAMS);
- return;
- }
-
- VlanId innerVlan = ((VlanIdCriterion) innerVlanCriterion).vlanId();
- Criterion innerVid = Criteria.matchVlanId(innerVlan);
-
- // In the case where the C-tag is the same for all the subscribers,
- // we add a metadata with the outport in the selector to make the flow unique
- Criterion innerSelectorMeta = Criteria.matchMetadata(output.port().toLong());
-
- if (innerVlan.toShort() == VlanId.ANY_VALUE) {
- TrafficSelector outerSelector = buildSelector(inport, outerVlan, outerPbit, dstMac);
- installDownstreamRulesForAnyVlan(fwd, output, outerSelector, buildSelector(inport,
- Criteria.matchVlanId(VlanId.ANY), innerSelectorMeta));
- } else {
- // Required to differentiate the same match flows
- // Please note that S tag and S p bit values will be same for the same service - so conflict flows!
- // Metadata match criteria solves the conflict issue - but not used by the voltha
- // Maybe - find a better way to solve the above problem
- Criterion metadata = Criteria.matchMetadata(innerVlan.toShort());
- TrafficSelector outerSelector = buildSelector(inport, metadata, outerVlan, outerPbit, dstMac);
- installDownstreamRulesForVlans(fwd, output, outerSelector, buildSelector(inport, innerVid,
- innerSelectorMeta));
- }
- }
-
- private void installDownstreamRulesForVlans(ForwardingObjective fwd, Instruction output,
- TrafficSelector outerSelector, TrafficSelector innerSelector) {
-
- List<Pair<Instruction, Instruction>> vlanOps =
- vlanOps(fwd,
- L2ModificationInstruction.L2SubType.VLAN_POP);
-
- if (vlanOps == null || vlanOps.isEmpty()) {
- return;
- }
-
- Pair<Instruction, Instruction> popAndRewrite = vlanOps.remove(0);
-
- TrafficTreatment innerTreatment;
- VlanId setVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) popAndRewrite.getRight()).vlanId();
- if (VlanId.NONE.equals(setVlanId)) {
- innerTreatment = (buildTreatment(popAndRewrite.getLeft(), fetchMeter(fwd),
- writeMetadataIncludingOnlyTp(fwd), output));
- } else {
- innerTreatment = (buildTreatment(popAndRewrite.getRight(),
- fetchMeter(fwd), writeMetadataIncludingOnlyTp(fwd), output));
- }
-
- List<Instruction> setVlanPcps = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_PCP,
- fwd.treatment().allInstructions());
-
- Instruction innerPbitSet = null;
-
- if (setVlanPcps != null && !setVlanPcps.isEmpty()) {
- innerPbitSet = setVlanPcps.get(0);
- }
-
- VlanId remarkInnerVlan = null;
- Optional<Criterion> vlanIdCriterion = readFromSelector(innerSelector, Criterion.Type.VLAN_VID);
- if (vlanIdCriterion.isPresent()) {
- remarkInnerVlan = ((VlanIdCriterion) vlanIdCriterion.get()).vlanId();
- }
-
- Instruction modVlanId = null;
- if (innerPbitSet != null) {
- modVlanId = Instructions.modVlanId(remarkInnerVlan);
- }
-
- //match: in port (nni), s-tag
- //action: pop vlan (s-tag), write metadata, go to table 1, meter
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(outerSelector)
- .withTreatment(buildTreatment(popAndRewrite.getLeft(), modVlanId,
- innerPbitSet, fetchMeter(fwd), fetchWriteMetadata(fwd), Instructions.transition(QQ_TABLE)));
-
- //match: in port (nni), c-tag
- //action: immediate: write metadata and pop, meter, output
- FlowRule.Builder inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(QQ_TABLE)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(innerSelector)
- .withTreatment(innerTreatment);
- applyRules(fwd, inner, outer);
- }
-
- private void installDownstreamRulesForAnyVlan(ForwardingObjective fwd, Instruction output,
- TrafficSelector outerSelector, TrafficSelector innerSelector) {
-
- //match: in port (nni), s-tag
- //action: immediate: write metadata, pop vlan, meter and go to table 1
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(outerSelector)
- .withTreatment(buildTreatment(Instructions.popVlan(), fetchMeter(fwd),
- fetchWriteMetadata(fwd), Instructions.transition(QQ_TABLE)));
-
- //match: in port (nni) and s-tag
- //action: immediate : write metadata, meter and output
- FlowRule.Builder inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(QQ_TABLE)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(innerSelector)
- .withTreatment(buildTreatment(fetchMeter(fwd),
- writeMetadataIncludingOnlyTp(fwd), output));
-
- applyRules(fwd, inner, outer);
- }
-
- private void installUpstreamRules(ForwardingObjective fwd) {
- List<Pair<Instruction, Instruction>> vlanOps =
- vlanOps(fwd,
- L2ModificationInstruction.L2SubType.VLAN_PUSH);
-
- if (vlanOps == null || vlanOps.isEmpty()) {
- return;
- }
-
- Instruction output = fetchOutput(fwd, UPSTREAM);
-
- if (output == null) {
- return;
- }
-
- Pair<Instruction, Instruction> outerPair = vlanOps.remove(0);
-
- boolean noneValueVlanStatus = checkNoneVlanCriteria(fwd);
- boolean anyValueVlanStatus = checkAnyVlanMatchCriteria(fwd);
-
- if (anyValueVlanStatus) {
- installUpstreamRulesForAnyVlan(fwd, output, outerPair);
- } else {
- Pair<Instruction, Instruction> innerPair = outerPair;
- outerPair = vlanOps.remove(0);
- installUpstreamRulesForVlans(fwd, output, innerPair, outerPair, noneValueVlanStatus);
- }
- }
-
- private void installUpstreamRulesForVlans(ForwardingObjective fwd, Instruction output,
- Pair<Instruction, Instruction> innerPair,
- Pair<Instruction, Instruction> outerPair, Boolean noneValueVlanStatus) {
-
- List<Instruction> setVlanPcps = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_PCP,
- fwd.treatment().allInstructions());
-
- Instruction innerPbitSet = null;
- Instruction outerPbitSet = null;
-
- if (setVlanPcps != null && !setVlanPcps.isEmpty()) {
- innerPbitSet = setVlanPcps.get(0);
- outerPbitSet = setVlanPcps.get(1);
- }
-
- TrafficTreatment innerTreatment;
- if (noneValueVlanStatus) {
- innerTreatment = buildTreatment(innerPair.getLeft(), innerPair.getRight(), fetchMeter(fwd),
- fetchWriteMetadata(fwd), innerPbitSet,
- Instructions.transition(QQ_TABLE));
- } else {
- innerTreatment = buildTreatment(innerPair.getRight(), fetchMeter(fwd), fetchWriteMetadata(fwd),
- innerPbitSet, Instructions.transition(QQ_TABLE));
- }
-
- //match: in port, vlanId (0 or None)
- //action:
- //if vlanId None, push & set c-tag go to table 1
- //if vlanId 0 or any specific vlan, set c-tag, write metadata, meter and go to table 1
- FlowRule.Builder inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(fwd.selector())
- .withTreatment(innerTreatment);
-
- PortCriterion inPort = (PortCriterion)
- fwd.selector().getCriterion(Criterion.Type.IN_PORT);
-
- VlanId cVlanId = ((L2ModificationInstruction.ModVlanIdInstruction)
- innerPair.getRight()).vlanId();
-
- //match: in port, c-tag
- //action: immediate: push s-tag, write metadata, meter and output
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(QQ_TABLE)
- .makePermanent()
- .withPriority(fwd.priority())
- .withTreatment(buildTreatment(outerPair.getLeft(), outerPair.getRight(),
- fetchMeter(fwd), writeMetadataIncludingOnlyTp(fwd),
- outerPbitSet, output));
-
- if (innerPbitSet != null) {
- byte innerPbit = ((L2ModificationInstruction.ModVlanPcpInstruction)
- innerPbitSet).vlanPcp();
- outer.withSelector(buildSelector(inPort, Criteria.matchVlanId(cVlanId), Criteria.matchVlanPcp(innerPbit)));
- } else {
- outer.withSelector(buildSelector(inPort, Criteria.matchVlanId(cVlanId)));
- }
-
- applyRules(fwd, inner, outer);
- }
-
- private void installUpstreamRulesForAnyVlan(ForwardingObjective fwd, Instruction output,
- Pair<Instruction, Instruction> outerPair) {
-
- log.debug("Installing upstream rules for any value vlan");
-
- //match: in port and any-vlan (coming from OLT app.)
- //action: write metadata, go to table 1 and meter
- FlowRule.Builder inner = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(fwd.selector())
- .withTreatment(buildTreatment(Instructions.transition(QQ_TABLE), fetchMeter(fwd),
- fetchWriteMetadata(fwd)));
-
- //match: in port and any-vlan (coming from OLT app.)
- //action: immediate: push:QinQ, vlanId (s-tag), write metadata, meter and output
- FlowRule.Builder outer = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .forDevice(deviceId)
- .forTable(QQ_TABLE)
- .makePermanent()
- .withPriority(fwd.priority())
- .withSelector(fwd.selector())
- .withTreatment(buildTreatment(outerPair.getLeft(), outerPair.getRight(),
- fetchMeter(fwd), writeMetadataIncludingOnlyTp(fwd), output));
-
- applyRules(fwd, inner, outer);
- }
-
- private boolean checkNoneVlanCriteria(ForwardingObjective fwd) {
- // Add the VLAN_PUSH treatment if we're matching on VlanId.NONE
- Criterion vlanMatchCriterion = filterForCriterion(fwd.selector().criteria(), Criterion.Type.VLAN_VID);
- boolean noneValueVlanStatus = false;
- if (vlanMatchCriterion != null) {
- noneValueVlanStatus = ((VlanIdCriterion) vlanMatchCriterion).vlanId().equals(VlanId.NONE);
- }
- return noneValueVlanStatus;
- }
-
- private boolean checkAnyVlanMatchCriteria(ForwardingObjective fwd) {
- Criterion anyValueVlanCriterion = fwd.selector().criteria().stream()
- .filter(c -> c.type().equals(Criterion.Type.VLAN_VID))
- .filter(vc -> ((VlanIdCriterion) vc).vlanId().toShort() == VlanId.ANY_VALUE)
- .findAny().orElse(null);
-
- if (anyValueVlanCriterion == null) {
- log.debug("Any value vlan match criteria is not found, criteria {}",
- fwd.selector().criteria());
- return false;
- }
-
- return true;
- }
-
- private Instruction fetchOutput(ForwardingObjective fwd, String direction) {
- Instruction output = fwd.treatment().allInstructions().stream()
- .filter(i -> i.type() == Instruction.Type.OUTPUT)
- .findFirst().orElse(null);
-
- if (output == null) {
- log.error("OLT {} rule has no output", direction);
- fail(fwd, ObjectiveError.BADPARAMS);
- return null;
- }
- return output;
- }
-
- private Instruction fetchMeter(ForwardingObjective fwd) {
- Instruction meter = fwd.treatment().metered();
-
- if (meter == null) {
- log.debug("Meter instruction is not found for the forwarding objective {}", fwd);
- return null;
- }
-
- log.debug("Meter instruction is found.");
- return meter;
- }
-
- private Instructions.MetadataInstruction fetchWriteMetadata(ForwardingObjective fwd) {
- Instructions.MetadataInstruction writeMetadata = fwd.treatment().writeMetadata();
-
- if (writeMetadata == null) {
- log.warn("Write metadata is not found for the forwarding obj");
- fail(fwd, ObjectiveError.BADPARAMS);
- return null;
- }
-
- log.debug("Write metadata is found {}", writeMetadata);
- return writeMetadata;
- }
-
- private List<Pair<Instruction, Instruction>> vlanOps(ForwardingObjective fwd,
- L2ModificationInstruction.L2SubType type) {
-
- List<Pair<Instruction, Instruction>> vlanOps = findVlanOps(
- fwd.treatment().allInstructions(), type);
-
- if (vlanOps == null || vlanOps.isEmpty()) {
- String direction = type == L2ModificationInstruction.L2SubType.VLAN_POP
- ? DOWNSTREAM : UPSTREAM;
- log.error("Missing vlan operations in {} forwarding: {}", direction, fwd);
- fail(fwd, ObjectiveError.BADPARAMS);
- return ImmutableList.of();
- }
- return vlanOps;
- }
-
-
- private List<Pair<Instruction, Instruction>> findVlanOps(List<Instruction> instructions,
- L2ModificationInstruction.L2SubType type) {
-
- List<Instruction> vlanOperations = findL2Instructions(
- type,
- instructions);
- List<Instruction> vlanSets = findL2Instructions(
- L2ModificationInstruction.L2SubType.VLAN_ID,
- instructions);
-
- if (vlanOperations.size() != vlanSets.size()) {
- return ImmutableList.of();
- }
-
- List<Pair<Instruction, Instruction>> pairs = Lists.newArrayList();
-
- for (int i = 0; i < vlanOperations.size(); i++) {
- pairs.add(new ImmutablePair<>(vlanOperations.get(i), vlanSets.get(i)));
- }
- return pairs;
- }
-
- private List<Instruction> findL2Instructions(L2ModificationInstruction.L2SubType subType,
- List<Instruction> actions) {
- return actions.stream()
- .filter(i -> i.type() == Instruction.Type.L2MODIFICATION)
- .filter(i -> ((L2ModificationInstruction) i).subtype() == subType)
- .collect(Collectors.toList());
- }
-
- private void provisionEthTypeBasedFilter(FilteringObjective filter,
- EthTypeCriterion ethType,
- Instructions.OutputInstruction output,
- L2ModificationInstruction vlanId,
- L2ModificationInstruction vlanPush) {
-
- Instruction meter = filter.meta().metered();
- Instruction writeMetadata = filter.meta().writeMetadata();
-
- TrafficSelector selector = buildSelector(filter.key(), ethType);
- TrafficTreatment treatment;
-
- if (vlanPush == null || vlanId == null) {
- treatment = buildTreatment(output, meter, writeMetadata);
- } else {
- // we need to push the vlan because it came untagged (ATT)
- treatment = buildTreatment(output, meter, vlanPush, vlanId, writeMetadata);
- }
-
- buildAndApplyRule(filter, selector, treatment);
-
- }
-
- private void provisionIgmp(FilteringObjective filter, EthTypeCriterion ethType,
- IPProtocolCriterion ipProto,
- Instructions.OutputInstruction output,
- Instruction vlan, Instruction pcp) {
-
- Instruction meter = filter.meta().metered();
- Instruction writeMetadata = filter.meta().writeMetadata();
-
- // uniTagMatch
- VlanIdCriterion vlanId = (VlanIdCriterion) filterForCriterion(filter.conditions(),
- Criterion.Type.VLAN_VID);
-
- TrafficSelector selector = buildSelector(filter.key(), ethType, ipProto, vlanId);
- TrafficTreatment treatment = buildTreatment(output, vlan, pcp, meter, writeMetadata);
- buildAndApplyRule(filter, selector, treatment);
- }
-
- private void provisionDhcp(FilteringObjective filter, EthTypeCriterion ethType,
- IPProtocolCriterion ipProto,
- UdpPortCriterion udpSrcPort,
- UdpPortCriterion udpDstPort,
- Instruction vlanIdInstruction,
- Instruction vlanPcpInstruction,
- Instructions.OutputInstruction output) {
-
- Instruction meter = filter.meta().metered();
- Instruction writeMetadata = filter.meta().writeMetadata();
-
- VlanIdCriterion matchVlanId = (VlanIdCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.VLAN_VID);
-
- TrafficSelector selector;
- TrafficTreatment treatment;
-
- if (matchVlanId != null) {
- log.debug("Building selector with match VLAN, {}", matchVlanId);
- // in case of TT upstream the packet comes tagged and the vlan is swapped.
- selector = buildSelector(filter.key(), ethType, ipProto, udpSrcPort,
- udpDstPort, matchVlanId);
- treatment = buildTreatment(output, meter, writeMetadata,
- vlanIdInstruction, vlanPcpInstruction);
- } else {
- log.debug("Building selector with no VLAN");
- // in case of ATT upstream the packet comes in untagged and we need to push the vlan
- selector = buildSelector(filter.key(), ethType, ipProto, udpSrcPort, udpDstPort);
- treatment = buildTreatment(output, meter, vlanIdInstruction, writeMetadata);
- }
- //In case of downstream there will be no match on the VLAN, which is null,
- // so it will just be output, meter, writeMetadata
-
- buildAndApplyRule(filter, selector, treatment);
- }
-
- private void provisionPPPoED(FilteringObjective filter, EthTypeCriterion ethType,
- Instruction vlanIdInstruction,
- Instruction vlanPcpInstruction,
- Instructions.OutputInstruction output) {
- Instruction meter = filter.meta().metered();
- Instruction writeMetadata = filter.meta().writeMetadata();
-
- VlanIdCriterion matchVlanId = (VlanIdCriterion)
- filterForCriterion(filter.conditions(), Criterion.Type.VLAN_VID);
-
- TrafficSelector selector;
- TrafficTreatment treatment;
-
- if (matchVlanId != null) {
- log.debug("Building pppoed selector with match VLAN {}.", matchVlanId);
- } else {
- log.debug("Building pppoed selector without match VLAN.");
- }
-
- selector = buildSelector(filter.key(), ethType, matchVlanId);
- treatment = buildTreatment(output, meter, writeMetadata, vlanIdInstruction, vlanPcpInstruction);
- buildAndApplyRule(filter, selector, treatment);
- }
-
- private void buildAndApplyRule(FilteringObjective filter, TrafficSelector selector,
- TrafficTreatment treatment) {
- FlowRule rule = DefaultFlowRule.builder()
- .fromApp(filter.appId())
- .forDevice(deviceId)
- .forTable(0)
- .makePermanent()
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(filter.priority())
- .build();
-
- if (accumulator != null) {
- if (log.isDebugEnabled()) {
- log.debug("Adding pair to batch: {}", Pair.of(filter, rule));
- }
- accumulator.add(Pair.of(filter, rule));
- } else {
- FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
- switch (filter.type()) {
- case PERMIT:
- opsBuilder.add(rule);
- break;
- case DENY:
- opsBuilder.remove(rule);
- break;
- default:
- log.warn("Unknown filter type : {}", filter.type());
- fail(filter, ObjectiveError.UNSUPPORTED);
- }
- applyFlowRules(ImmutableList.of(filter), opsBuilder);
- }
- }
-
- private void applyRules(ForwardingObjective fwd, FlowRule.Builder... fwdBuilders) {
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- switch (fwd.op()) {
- case ADD:
- for (FlowRule.Builder fwdBuilder : fwdBuilders) {
- builder.add(fwdBuilder.build());
- }
- break;
- case REMOVE:
- for (FlowRule.Builder fwdBuilder : fwdBuilders) {
- builder.remove(fwdBuilder.build());
- }
- break;
- case ADD_TO_EXISTING:
- break;
- case REMOVE_FROM_EXISTING:
- break;
- default:
- log.warn("Unknown forwarding operation: {}", fwd.op());
- }
-
- applyFlowRules(ImmutableList.of(fwd), builder);
-
-
- }
-
- private void applyFlowRules(List<Objective> objectives, FlowRuleOperations.Builder builder) {
- flowRuleService.apply(builder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- objectives.forEach(obj -> {
- pass(obj);
- });
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- objectives.forEach(obj -> {
- fail(obj, ObjectiveError.FLOWINSTALLATIONFAILED);
- });
-
- }
- }));
- }
-
- // Builds the batch using the accumulated flow rules
- private void sendFilters(List<Pair<FilteringObjective, FlowRule>> pairs) {
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
- log.debug("Sending batch of {} filter-objs", pairs.size());
- List<Objective> filterObjs = Lists.newArrayList();
- // Iterates over all accumulated flow rules and then build an unique batch
- pairs.forEach(pair -> {
- FilteringObjective filter = pair.getLeft();
- FlowRule rule = pair.getRight();
- switch (filter.type()) {
- case PERMIT:
- flowOpsBuilder.add(rule);
- log.debug("Applying add filter-obj {} to device: {}", filter.id(), deviceId);
- filterObjs.add(filter);
- break;
- case DENY:
- flowOpsBuilder.remove(rule);
- log.debug("Deleting flow rule {} to device: {}", rule, deviceId);
- filterObjs.add(filter);
- break;
- default:
- fail(filter, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", filter.type());
- }
- });
- if (log.isDebugEnabled()) {
- log.debug("Applying batch {}", flowOpsBuilder.build());
- }
- // Finally applies the operations
- applyFlowRules(filterObjs, flowOpsBuilder);
- }
-
- private Criterion filterForCriterion(Collection<Criterion> criteria, Criterion.Type type) {
- return criteria.stream()
- .filter(c -> c.type().equals(type))
- .limit(1)
- .findFirst().orElse(null);
- }
-
- private TrafficSelector buildSelector(Criterion... criteria) {
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
- Arrays.stream(criteria).filter(Objects::nonNull).forEach(sBuilder::add);
-
- return sBuilder.build();
- }
-
- private TrafficTreatment buildTreatment(Instruction... instructions) {
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- Arrays.stream(instructions).filter(Objects::nonNull).forEach(tBuilder::add);
-
- return tBuilder.build();
- }
-
- private Instruction writeMetadataIncludingOnlyTp(ForwardingObjective fwd) {
-
- return Instructions.writeMetadata(
- fetchWriteMetadata(fwd).metadata() & 0xFFFF00000000L, 0L);
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- obj.context().ifPresent(context -> context.onError(obj, error));
- }
-
- private void pass(Objective obj) {
- obj.context().ifPresent(context -> context.onSuccess(obj));
- }
-
-
- private class InnerGroupListener implements GroupListener {
- @Override
- public void event(GroupEvent event) {
- GroupKey key = event.subject().appCookie();
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj == null) {
- log.debug("No pending group for {}, moving on", key);
- return;
- }
- log.trace("Event {} for group {}, handling pending" +
- "NextGroup {}", event.type(), key, obj.id());
- if (event.type() == GroupEvent.Type.GROUP_ADDED ||
- event.type() == GroupEvent.Type.GROUP_UPDATED) {
- flowObjectiveStore.putNextGroup(obj.id(), new OLTPipelineGroup(key));
- pass(obj);
- pendingGroups.invalidate(key);
- } else if (event.type() == GroupEvent.Type.GROUP_REMOVED) {
- flowObjectiveStore.removeNextGroup(obj.id());
- pass(obj);
- pendingGroups.invalidate(key);
- }
- }
- }
-
- private static class OLTPipelineGroup implements NextGroup {
-
- private final GroupKey key;
-
- public OLTPipelineGroup(GroupKey key) {
- this.key = key;
- }
-
- public GroupKey key() {
- return key;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(key);
- }
-
- }
-
- @Override
- public List<String> getNextMappings(NextGroup nextGroup) {
- // TODO Implementation deferred to vendor
- return null;
- }
-
- // Flow rules accumulator for reducing the number of transactions required to the devices.
- private final class ObjectiveAccumulator
- extends AbstractAccumulator<Pair<FilteringObjective, FlowRule>> {
-
- ObjectiveAccumulator(int maxFilter, int maxBatchMS, int maxIdleMS) {
- super(TIMER, maxFilter, maxBatchMS, maxIdleMS);
- }
-
- @Override
- public void processItems(List<Pair<FilteringObjective, FlowRule>> pairs) {
- // Triggers creation of a batch using the list of flowrules generated from objs.
- accumulatorExecutorService.execute(new FlowRulesBuilderTask(pairs));
- }
- }
-
- // Task for building batch of flow rules in a separate thread.
- private final class FlowRulesBuilderTask implements Runnable {
- private final List<Pair<FilteringObjective, FlowRule>> pairs;
-
- FlowRulesBuilderTask(List<Pair<FilteringObjective, FlowRule>> pairs) {
- this.pairs = pairs;
- }
-
- @Override
- public void run() {
- try {
- sendFilters(pairs);
- } catch (Exception e) {
- log.warn("Unable to send objectives", e);
- }
- }
- }
-}
diff --git a/drivers/default/src/main/resources/onos-drivers.xml b/drivers/default/src/main/resources/onos-drivers.xml
index d63638b..48cb791 100644
--- a/drivers/default/src/main/resources/onos-drivers.xml
+++ b/drivers/default/src/main/resources/onos-drivers.xml
@@ -173,49 +173,6 @@
impl="org.onosproject.driver.traceable.OfdpaPipelineTraceable" />
</driver>
- <driver name="celestica" extends="default"
- manufacturer="PMC GPON Networks" hwVersion="PAS5211 v2" swVersion="vOLT version 1.5.3.*">
- <behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OltPipeline"/>
- <behaviour api="org.onosproject.net.behaviour.MeterQuery"
- impl="org.onosproject.driver.query.FullMetersAvailable"/>
- </driver>
- <driver name="pmc-olt" extends="default"
- manufacturer="PMC GPON Networks" hwVersion="PASffffffff v-1" swVersion="vOLT.*">
- <behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OltPipeline"/>
- <behaviour api="org.onosproject.net.behaviour.MeterQuery"
- impl="org.onosproject.driver.query.FullMetersAvailable"/>
- </driver>
- <driver name="voltha" extends="default"
- manufacturer="VOLTHA Project" hwVersion=".*" swVersion=".*">
- <behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OltPipeline"/>
- <behaviour api="org.onosproject.net.behaviour.MeterQuery"
- impl="org.onosproject.driver.query.FullMetersAvailable"/>
- <property name="accumulatorEnabled">true</property>
- </driver>
- <driver name="fj-olt" extends="default"
- manufacturer="Fujitsu" hwVersion="svkOLT" swVersion="v1.0">
- <behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OltPipeline"/>
- <behaviour api="org.onosproject.net.behaviour.MeterQuery"
- impl="org.onosproject.driver.query.FullMetersAvailable"/>
- </driver>
- <driver name="nokia-olt" extends="default"
- manufacturer="Nokia" hwVersion="SDOLT" swVersion="5.2.1">
- <behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.NokiaOltPipeline"/>
- <behaviour api="org.onosproject.net.behaviour.MeterQuery"
- impl="org.onosproject.driver.query.FullMetersAvailable"/>
- </driver>
- <driver name="g.fast" extends="default"
- manufacturer="TEST1" hwVersion="TEST2" swVersion="TEST3">
- <behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OltPipeline"/>
- <behaviour api="org.onosproject.net.behaviour.MeterQuery"
- impl="org.onosproject.driver.query.FullMetersAvailable"/>
- </driver>
<!-- The SoftRouter driver is meant to be used by any software/NPU based
~ switch that wishes to implement a simple 2-table router. To use this
~ driver, configure ONOS with the dpid of the device, or extend the