summaryrefslogtreecommitdiffstats
path: root/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline')
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java640
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java76
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java497
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java129
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java1792
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java829
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java238
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java241
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java286
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java543
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java544
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java1101
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java204
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java20
14 files changed, 0 insertions, 7140 deletions
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java
deleted file mode 100644
index cd7a1b66..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.TpPort;
-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.Criterion;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-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.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Driver for Centec's V350 switches.
- */
-public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- protected static final int PORT_VLAN_TABLE = 0;
- protected static final int FILTER_TABLE = 1;
- // TMAC is configured in MAC Table to redirect packets to ROUTE_TABLE.
- protected static final int MAC_TABLE = 2;
- protected static final int ROUTE_TABLE = 3;
-
- private static final long DEFAULT_METADATA = 100;
- private static final long DEFAULT_METADATA_MASK = 0xffffffffffffffffL;
-
- // Priority used in PORT_VLAN Table, the only priority accepted is PORT_VLAN_TABLE_PRIORITY.
- // The packet passed PORT+VLAN check will goto FILTER Table.
- private static final int PORT_VLAN_TABLE_PRIORITY = 0xffff;
-
- // Priority used in Filter Table.
- private static final int FILTER_TABLE_CONTROLLER_PRIORITY = 500;
- // TMAC priority should be lower than controller.
- private static final int FILTER_TABLE_TMAC_PRIORITY = 200;
- private static final int FILTER_TABLE_HIGHEST_PRIORITY = 0xffff;
-
- // Priority used in MAC Table.
- // We do exact matching for DMAC+metadata, so priority is ignored and required to be set to 0xffff.
- private static final int MAC_TABLE_PRIORITY = 0xffff;
-
- // Priority used in Route Table.
- // We do LPM matching in Route Table, so priority is ignored and required to be set to 0xffff.
- private static final int ROUTE_TABLE_PRIORITY = 0xffff;
-
- private static final short BGP_PORT = 179;
-
- private final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private CoreService coreService;
- private GroupService groupService;
- private FlowObjectiveStore flowObjectiveStore;
- private DeviceId deviceId;
- private ApplicationId appId;
-
- private KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(GroupKey.class)
- .register(DefaultGroupKey.class)
- .register(CentecV350Group.class)
- .register(byte[].class)
- .build();
-
- private Cache<GroupKey, NextObjective> pendingGroups;
-
- private ScheduledExecutorService groupChecker =
- Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
- "centec-V350-%d"));
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- pendingGroups = CacheBuilder.newBuilder()
- .expireAfterWrite(20, TimeUnit.SECONDS)
- .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
- if (notification.getCause() == RemovalCause.EXPIRED) {
- fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
- }
- }).build();
-
- groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- groupService = serviceDirectory.get(GroupService.class);
- flowObjectiveStore = context.store();
-
- groupService.addListener(new InnerGroupListener());
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.CentecV350Pipeline");
-
- initializePipeline();
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
- processFilter(filteringObjective,
- filteringObjective.op() == Objective.Operation.ADD,
- filteringObjective.appId());
- } else {
- fail(filteringObjective, ObjectiveError.UNSUPPORTED);
- }
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowBuilder::add);
- break;
- case REMOVE:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
-
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() == 1) {
- TrafficTreatment treatment = treatments.iterator().next();
-
- // Since we do not support strip_vlan in PORT_VLAN table, we use mod_vlan
- // to modify the packet to desired vlan.
- // Note: if we use push_vlan here, the switch will add a second VLAN tag to the outgoing
- // packet, which is not what we want.
- TrafficTreatment.Builder treatmentWithoutPushVlan = DefaultTrafficTreatment.builder();
- VlanId modVlanId;
- for (Instruction ins : treatment.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- switch (l2ins.subtype()) {
- case ETH_DST:
- treatmentWithoutPushVlan.setEthDst(
- ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac());
- break;
- case ETH_SRC:
- treatmentWithoutPushVlan.setEthSrc(
- ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac());
- break;
- case VLAN_ID:
- modVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
- treatmentWithoutPushVlan.setVlanId(modVlanId);
- break;
- default:
- break;
- }
- } else if (ins.type() == Instruction.Type.OUTPUT) {
- //long portNum = ((Instructions.OutputInstruction) ins).port().toLong();
- treatmentWithoutPushVlan.add(ins);
- } else {
- // Ignore the vlan_pcp action since it's does matter much.
- log.warn("Driver does not handle this type of TrafficTreatment"
- + " instruction in nextObjectives: {}", ins.type());
- }
- }
-
- GroupBucket bucket =
- DefaultGroupBucket.createIndirectGroupBucket(treatmentWithoutPushVlan.build());
- final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
- GroupDescription groupDescription
- = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections
- .singletonList(bucket)),
- key,
- null, // let group service determine group id
- nextObjective.appId());
- groupService.addGroup(groupDescription);
- pendingGroups.put(key, nextObjective);
- }
- break;
- case HASHED:
- case BROADCAST:
- case FAILOVER:
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
- }
-
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
- log.warn("Driver does not support versatile forwarding objective");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
-
- 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();
- }
-
- // Must have metadata as key.
- TrafficSelector filteredSelector =
- DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchMetadata(DEFAULT_METADATA)
- .matchIPDst(
- ((IPCriterion)
- selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
- .build();
-
- TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
-
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- GroupKey key = appKryo.deserialize(next.data());
- Group group = groupService.getGroup(deviceId, key);
- if (group == null) {
- log.warn("The group left!");
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- tb.group(group.id());
- }
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(ROUTE_TABLE_PRIORITY)
- .forDevice(deviceId)
- .withSelector(filteredSelector)
- .withTreatment(tb.build());
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- ruleBuilder.forTable(ROUTE_TABLE);
-
- return Collections.singletonList(ruleBuilder.build());
-
- }
-
- private void processFilter(FilteringObjective filt, boolean install,
- ApplicationId applicationId) {
- PortCriterion p;
- if (!filt.key().equals(Criteria.dummy()) &&
- filt.key().type() == Criterion.Type.IN_PORT) {
- p = (PortCriterion) filt.key();
- } else {
- log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
- fail(filt, ObjectiveError.UNKNOWN);
- return;
- }
-
- // Convert filtering conditions for switch-intfs into flow rules.
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
-
- for (Criterion c : filt.conditions()) {
- // Here we do a trick to install 2 flow rules to MAC_TABLE and ROUTE_TABLE.
- if (c.type() == Criterion.Type.ETH_DST) {
- EthCriterion e = (EthCriterion) c;
-
- // Install TMAC flow rule.
- log.debug("adding rule for Termination MAC in Filter Table: {}", e.mac());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthDst(e.mac());
- // Add IPv4 matching explicitly since we will redirect it to ROUTE Table
- // through MAC table.
- selector.matchEthType(Ethernet.TYPE_IPV4);
- treatment.transition(MAC_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(FILTER_TABLE_TMAC_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- // Must install another rule to direct the IPv4 packets that hit TMAC to
- // Route table.
- log.debug("adding rule for Termination MAC in MAC Table: {}", e.mac());
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchEthDst(e.mac());
- // MAC_Table must have metadata matching configured, use the default metadata.
- selector.matchMetadata(DEFAULT_METADATA);
- treatment.transition(ROUTE_TABLE);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(MAC_TABLE_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(MAC_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
- } else if (c.type() == Criterion.Type.VLAN_VID) {
- VlanIdCriterion v = (VlanIdCriterion) c;
- log.debug("adding rule for VLAN: {}", v.vlanId());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchVlanId(v.vlanId());
- selector.matchInPort(p.port());
- // Although the accepted packets will be sent to filter table, we must
- // explicitly set goto_table instruction here.
- treatment.writeMetadata(DEFAULT_METADATA, DEFAULT_METADATA_MASK);
- // set default metadata written by PORT_VLAN Table.
- treatment.transition(FILTER_TABLE);
- // We do not support strip vlan here, treatment.deferred().popVlan();
- // PORT_VLAN table only accept 0xffff priority since it does exact match only.
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(PORT_VLAN_TABLE_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(PORT_VLAN_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
- } else if (c.type() == Criterion.Type.IPV4_DST) {
- IPCriterion ipaddr = (IPCriterion) c;
- log.debug("adding IP filtering rules in FILTER table: {}", ipaddr.ip());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ipaddr.ip()); // router IPs to the controller
- treatment.setOutput(PortNumber.CONTROLLER);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(FILTER_TABLE_CONTROLLER_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
- } else {
- log.warn("Driver does not currently process filtering condition"
- + " of type: {}", c.type());
- fail(filt, ObjectiveError.UNSUPPORTED);
- }
- }
-
- // apply filtering flow rules
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(filt);
- log.info("Applied filtering rules");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
- log.info("Failed to apply filtering rules");
- }
- }));
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
- private void initializePipeline() {
- // CENTEC_V350: PORT_VLAN_TABLE->FILTER_TABLE->MAC_TABLE(TMAC)->ROUTE_TABLE.
- processPortVlanTable(true);
- processFilterTable(true);
- }
-
- private void processPortVlanTable(boolean install) {
- // By default the packet are dropped, need install port+vlan by some ways.
-
- // XXX can we add table-miss-entry to drop? Code says drops by default
- // XXX TTP description says default goes to table1.
- // It also says that match is only on vlan -- not port-vlan -- which one is true?
- }
-
- private void processFilterTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- // Punt ARP packets to controller by default.
- selector.matchEthType(Ethernet.TYPE_ARP);
- treatment.punt();
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(FILTER_TABLE_CONTROLLER_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- // Punt BGP packets to controller directly.
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPProtocol(IPv4.PROTOCOL_TCP)
- .matchTcpSrc(TpPort.tpPort(BGP_PORT));
- treatment.punt();
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withPriority(FILTER_TABLE_HIGHEST_PRIORITY)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .fromApp(appId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPProtocol(IPv4.PROTOCOL_TCP)
- .matchTcpDst(TpPort.tpPort(BGP_PORT));
- treatment.punt();
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withPriority(FILTER_TABLE_HIGHEST_PRIORITY)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .fromApp(appId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- // Packet will be discard in PORT_VLAN table, no need to install rule in
- // filter table.
-
- // XXX does not tell me if packets are going to be dropped by default in
- // filter table or not? TTP says it will be dropped by default
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned filter table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision filter table");
- }
- }));
- }
-
- private class InnerGroupListener implements GroupListener {
- @Override
- public void event(GroupEvent event) {
- if (event.type() == GroupEvent.Type.GROUP_ADDED) {
- GroupKey key = event.subject().appCookie();
-
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj != null) {
- flowObjectiveStore.putNextGroup(obj.id(), new CentecV350Group(key));
- pass(obj);
- pendingGroups.invalidate(key);
- }
- }
- }
- }
-
-
- private class GroupChecker implements Runnable {
-
- @Override
- public void run() {
- Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
- .filter(key -> groupService.getGroup(deviceId, key) != null)
- .collect(Collectors.toSet());
-
- keys.stream().forEach(key -> {
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj == null) {
- return;
- }
- pass(obj);
- pendingGroups.invalidate(key);
- log.info("Heard back from group service for group {}. "
- + "Applying pending forwarding objectives", obj.id());
- flowObjectiveStore.putNextGroup(obj.id(), new CentecV350Group(key));
- });
- }
- }
-
- private class CentecV350Group implements NextGroup {
-
- private final GroupKey key;
-
- public CentecV350Group(GroupKey key) {
- this.key = key;
- }
-
- @SuppressWarnings("unused")
- public GroupKey key() {
- return key;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(key);
- }
-
- }
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java
deleted file mode 100644
index ccf73079..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 static org.slf4j.LoggerFactory.getLogger;
-
-import org.onlab.packet.Ethernet;
-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.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.slf4j.Logger;
-
-/**
- * Driver for Corsa TTP.
- *
- */
-public class CorsaPipeline extends OVSCorsaPipeline {
-
- private final Logger log = getLogger(getClass());
-
- @Override
- protected void processVlanMplsTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
- // corsa uses non-OF-standard way to match on presence of VLAN tags
- selector.matchEthType(Ethernet.TYPE_VLAN);
- treatment.transition(VLAN_TABLE);
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(VLAN_MPLS_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned vlan/mpls table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info(
- "Failed to provision vlan/mpls table");
- }
- }));
-
- }
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
deleted file mode 100644
index 02522cf1..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.NextGroup;
-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.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.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.MplsBosCriterion;
-import org.onosproject.net.flow.criteria.MplsCriterion;
-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.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupKey;
-import org.slf4j.Logger;
-
-
-/**
- * Driver for software switch emulation of the OFDPA 2.0 pipeline.
- * The software switch is the CPqD OF 1.3 switch.
- */
-public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
-
- private final Logger log = getLogger(getClass());
-
- /*
- * Cpqd emulation does not require the non-OF standard rules for
- * matching untagged packets.
- *
- * (non-Javadoc)
- * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processVlanIdFilter
- */
-
- @Override
- protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
- VlanIdCriterion vidCriterion,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- List<FlowRule> rules = new ArrayList<FlowRule>();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchVlanId(vidCriterion.vlanId());
- treatment.transition(TMAC_TABLE);
-
- VlanId storeVlan = null;
- if (vidCriterion.vlanId() == VlanId.NONE) {
- // untagged packets are assigned vlans
- treatment.pushVlan().setVlanId(assignedVlan);
- storeVlan = assignedVlan;
- } else {
- storeVlan = vidCriterion.vlanId();
- }
-
- // ofdpa cannot match on ALL portnumber, so we need to use separate
- // rules for each port.
- List<PortNumber> portnums = new ArrayList<PortNumber>();
- if (portCriterion.port() == PortNumber.ALL) {
- for (Port port : deviceService.getPorts(deviceId)) {
- if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
- portnums.add(port.number());
- }
- }
- } else {
- portnums.add(portCriterion.port());
- }
-
- for (PortNumber pnum : portnums) {
- // update storage
- port2Vlan.put(pnum, storeVlan);
- Set<PortNumber> vlanPorts = vlan2Port.get(storeVlan);
- if (vlanPorts == null) {
- vlanPorts = Collections.newSetFromMap(
- new ConcurrentHashMap<PortNumber, Boolean>());
- vlanPorts.add(pnum);
- vlan2Port.put(storeVlan, vlanPorts);
- } else {
- vlanPorts.add(pnum);
- }
- // create rest of flowrule
- selector.matchInPort(pnum);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(VLAN_TABLE).build();
- rules.add(rule);
- }
- return rules;
- }
-
- /*
- * Cpqd emulation does not handle vlan tags and mpls labels correctly.
- * Workaround requires popping off the VLAN tags in the TMAC table.
- *
- * (non-Javadoc)
- * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthDstFilter
- */
- @Override
- protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion,
- EthCriterion ethCriterion,
- VlanIdCriterion vidCriterion,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- //handling untagged packets via assigned VLAN
- if (vidCriterion.vlanId() == VlanId.NONE) {
- vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
- }
- // ofdpa cannot match on ALL portnumber, so we need to use separate
- // rules for each port.
- List<PortNumber> portnums = new ArrayList<PortNumber>();
- if (portCriterion.port() == PortNumber.ALL) {
- for (Port port : deviceService.getPorts(deviceId)) {
- if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
- portnums.add(port.number());
- }
- }
- } else {
- portnums.add(portCriterion.port());
- }
-
- List<FlowRule> rules = new ArrayList<FlowRule>();
- for (PortNumber pnum : portnums) {
- // for unicast IP packets
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(pnum);
- selector.matchVlanId(vidCriterion.vlanId());
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchEthDst(ethCriterion.mac());
- /*
- * Note: CpqD switches do not handle MPLS-related operation properly
- * for a packet with VLAN tag. We pop VLAN here as a workaround.
- * Side effect: HostService learns redundant hosts with same MAC but
- * different VLAN. No known side effect on the network reachability.
- */
- treatment.popVlan();
- treatment.transition(UNICAST_ROUTING_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- rules.add(rule);
- //for MPLS packets
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(pnum);
- selector.matchVlanId(vidCriterion.vlanId());
- selector.matchEthType(Ethernet.MPLS_UNICAST);
- selector.matchEthDst(ethCriterion.mac());
- // workaround here again
- treatment.popVlan();
- treatment.transition(MPLS_TABLE_0);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- rules.add(rule);
- }
- return rules;
- }
-
- /*
- * Cpqd emulation allows MPLS ecmp.
- *
- * (non-Javadoc)
- * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific
- */
- @Override
- protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType =
- (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
- if ((ethType == null) ||
- (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
- (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
- log.warn("processSpecific: Unsupported forwarding objective criteria"
- + "ethType:{} in dev:{}", ethType, deviceId);
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
-
- int forTableId = -1;
- TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
- if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
- filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(((IPCriterion)
- selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
- forTableId = UNICAST_ROUTING_TABLE;
- log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
- + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
- } else {
- filteredSelector
- .matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(((MplsCriterion)
- selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
- MplsBosCriterion bos = (MplsBosCriterion) selector
- .getCriterion(Criterion.Type.MPLS_BOS);
- if (bos != null) {
- filteredSelector.matchMplsBos(bos.mplsBos());
- }
- forTableId = MPLS_TABLE_1;
- log.debug("processing MPLS specific forwarding objective {} -> next:{}"
- + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
- }
-
- TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
- if (fwd.treatment() != null) {
- for (Instruction i : fwd.treatment().allInstructions()) {
- tb.add(i);
- }
- }
-
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
- // we only need the top level group's key to point the flow to it
- Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
- if (group == null) {
- log.warn("The group left!");
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- tb.deferred().group(group.id());
- }
- tb.transition(ACL_TABLE);
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(filteredSelector.build())
- .withTreatment(tb.build())
- .forTable(forTableId);
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- return Collections.singletonList(ruleBuilder.build());
- }
-
- @Override
- protected void initializePipeline() {
- processPortTable();
- // vlan table processing not required, as default is to drop packets
- // which can be accomplished without a table-miss-entry.
- processTmacTable();
- processIpTable();
- processMplsTable();
- processBridgingTable();
- processAclTable();
- }
-
- protected void processPortTable() {
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.transition(VLAN_TABLE);
- FlowRule tmisse = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(PORT_TABLE).build();
- ops = ops.add(tmisse);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized port table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize port table");
- }
- }));
- }
-
- protected void processTmacTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- treatment.transition(BRIDGING_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized tmac table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize tmac table");
- }
- }));
- }
-
- protected void processIpTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- treatment.deferred().setOutput(PortNumber.CONTROLLER);
- treatment.transition(ACL_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(UNICAST_ROUTING_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized IP table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize unicast IP table");
- }
- }));
- }
-
- protected void processMplsTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- treatment.transition(MPLS_TABLE_1);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(MPLS_TABLE_0).build();
- ops = ops.add(rule);
-
- treatment.transition(ACL_TABLE);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(MPLS_TABLE_1).build();
- ops = ops.add(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized MPLS tables");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize MPLS tables");
- }
- }));
- }
-
- private void processBridgingTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- treatment.transition(ACL_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(BRIDGING_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized Bridging table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize Bridging table");
- }
- }));
- }
-
- protected void processAclTable() {
- //table miss entry - catch all to executed action-set
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized Acl table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize Acl table");
- }
- }));
- }
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java
deleted file mode 100644
index d42650f5..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onosproject.net.DeviceId;
-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.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.instructions.Instructions;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.slf4j.Logger;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Simple single table pipeline abstraction.
- */
-public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- private final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private DeviceId deviceId;
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- }
-
- @Override
- public void filter(FilteringObjective filter) {}
-
- @Override
- public void forward(ForwardingObjective fwd) {
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
- throw new UnsupportedOperationException(
- "Only VERSATILE is supported.");
- }
-
- TrafficSelector selector = fwd.selector();
- TrafficTreatment treatment = fwd.treatment();
- if ((fwd.treatment().deferred().size() == 0) &&
- (fwd.treatment().immediate().size() == 0) &&
- (fwd.treatment().tableTransition() == null) &&
- (!fwd.treatment().clearedDeferred())) {
- TrafficTreatment.Builder flowTreatment = DefaultTrafficTreatment.builder();
- flowTreatment.add(Instructions.createDrop());
- treatment = flowTreatment.build();
- }
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector)
- .withTreatment(treatment)
- .fromApp(fwd.appId())
- .withPriority(fwd.priority());
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
-
- switch (fwd.op()) {
-
- case ADD:
- flowBuilder.add(ruleBuilder.build());
- break;
- case REMOVE:
- flowBuilder.remove(ruleBuilder.build());
- break;
- default:
- log.warn("Unknown operation {}", fwd.op());
- }
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- if (fwd.context().isPresent()) {
- fwd.context().get().onSuccess(fwd);
- }
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- if (fwd.context().isPresent()) {
- fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }
- }));
-
- }
-
- @Override
- public void next(NextObjective nextObjective) {}
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
deleted file mode 100644
index 5f84b43a..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
+++ /dev/null
@@ -1,1792 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.core.DefaultGroupId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-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.device.DeviceService;
-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.Criterion.Type;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.MplsBosCriterion;
-import org.onosproject.net.flow.criteria.MplsCriterion;
-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.OutputInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
-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.net.packet.PacketService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.slf4j.Logger;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalCause;
-import com.google.common.cache.RemovalNotification;
-
-/**
- * Driver for Broadcom's OF-DPA v2.0 TTP.
- *
- */
-public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- protected static final int PORT_TABLE = 0;
- protected static final int VLAN_TABLE = 10;
- protected static final int TMAC_TABLE = 20;
- protected static final int UNICAST_ROUTING_TABLE = 30;
- protected static final int MULTICAST_ROUTING_TABLE = 40;
- protected static final int MPLS_TABLE_0 = 23;
- protected static final int MPLS_TABLE_1 = 24;
- protected static final int BRIDGING_TABLE = 50;
- protected static final int ACL_TABLE = 60;
- protected static final int MAC_LEARNING_TABLE = 254;
- protected static final long OFPP_MAX = 0xffffff00L;
-
- private static final int HIGHEST_PRIORITY = 0xffff;
- protected static final int DEFAULT_PRIORITY = 0x8000;
- protected static final int LOWEST_PRIORITY = 0x0;
-
- /*
- * OFDPA requires group-id's to have a certain form.
- * L2 Interface Groups have <4bits-0><12bits-vlanid><16bits-portid>
- * L3 Unicast Groups have <4bits-2><28bits-index>
- * MPLS Interface Groups have <4bits-9><4bits:0><24bits-index>
- * L3 ECMP Groups have <4bits-7><28bits-index>
- * L2 Flood Groups have <4bits-4><12bits-vlanid><16bits-index>
- * L3 VPN Groups have <4bits-9><4bits-2><24bits-index>
- */
- private static final int L2INTERFACEMASK = 0x0;
- private static final int L3UNICASTMASK = 0x20000000;
- private static final int MPLSINTERFACEMASK = 0x90000000;
- private static final int L3ECMPMASK = 0x70000000;
- private static final int L2FLOODMASK = 0x40000000;
- private static final int L3VPNMASK = 0x92000000;
-
- private final Logger log = getLogger(getClass());
- private ServiceDirectory serviceDirectory;
- protected FlowRuleService flowRuleService;
- private CoreService coreService;
- protected GroupService groupService;
- protected FlowObjectiveStore flowObjectiveStore;
- protected DeviceId deviceId;
- protected ApplicationId driverId;
- protected PacketService packetService;
- protected DeviceService deviceService;
- protected KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(GroupKey.class)
- .register(DefaultGroupKey.class)
- .register(OfdpaNextGroup.class)
- .register(byte[].class)
- .register(ArrayDeque.class)
- .build();
-
- private Cache<GroupKey, List<OfdpaNextGroup>> pendingNextObjectives;
- private ConcurrentHashMap<GroupKey, Set<GroupChainElem>> pendingGroups;
-
- private ScheduledExecutorService groupChecker =
- Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
- "ofdpa2-%d"));
- private Set<IPCriterion> sentIpFilters = Collections.newSetFromMap(
- new ConcurrentHashMap<IPCriterion, Boolean>());
-
- // local stores for port-vlan mapping
- Map<PortNumber, VlanId> port2Vlan = new ConcurrentHashMap<PortNumber, VlanId>();
- Map<VlanId, Set<PortNumber>> vlan2Port = new ConcurrentHashMap<VlanId,
- Set<PortNumber>>();
-
- // index number for group creation
- AtomicInteger l3vpnindex = new AtomicInteger(0);
-
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- pendingNextObjectives = CacheBuilder.newBuilder()
- .expireAfterWrite(20, TimeUnit.SECONDS)
- .removalListener((
- RemovalNotification<GroupKey, List<OfdpaNextGroup>> notification) -> {
- if (notification.getCause() == RemovalCause.EXPIRED) {
- notification.getValue().forEach(ofdpaNextGrp ->
- fail(ofdpaNextGrp.nextObj,
- ObjectiveError.GROUPINSTALLATIONFAILED));
-
- }
- }).build();
-
- groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
- pendingGroups = new ConcurrentHashMap<GroupKey, Set<GroupChainElem>>();
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- groupService = serviceDirectory.get(GroupService.class);
- flowObjectiveStore = context.store();
- packetService = serviceDirectory.get(PacketService.class);
- deviceService = serviceDirectory.get(DeviceService.class);
- groupService.addListener(new InnerGroupListener());
-
- driverId = coreService.registerApplication(
- "org.onosproject.driver.OFDPA2Pipeline");
-
- // OF-DPA does not require initializing the pipeline as it puts default
- // rules automatically in the hardware. However emulation of OFDPA in
- // software switches does require table-miss-entries.
- initializePipeline();
-
- }
-
- protected void initializePipeline() {
-
- }
-
- //////////////////////////////////////
- // Flow Objectives
- //////////////////////////////////////
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
- processFilter(filteringObjective,
- filteringObjective.op() == Objective.Operation.ADD,
- filteringObjective.appId());
- } else {
- // Note that packets that don't match the PERMIT filter are
- // automatically denied. The DENY filter is used to deny packets
- // that are otherwise permitted by the PERMIT filter.
- // Use ACL table flow rules here for DENY filtering objectives
- log.debug("filter objective other than PERMIT currently not supported");
- fail(filteringObjective, ObjectiveError.UNSUPPORTED);
- }
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowOpsBuilder::add);
- break;
- case REMOVE:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowOpsBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
- flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
- switch (nextObjective.op()) {
- case ADD:
- if (nextGroup != null) {
- log.warn("Cannot add next {} that already exists in device {}",
- nextObjective.id(), deviceId);
- return;
- }
- log.debug("Processing NextObjective id{} in dev{} - add group",
- nextObjective.id(), deviceId);
- addGroup(nextObjective);
- break;
- case ADD_TO_EXISTING:
- if (nextGroup != null) {
- log.debug("Processing NextObjective id{} in dev{} - add bucket",
- nextObjective.id(), deviceId);
- addBucketToGroup(nextObjective);
- } else {
- // it is possible that group-chain has not been fully created yet
- waitToAddBucketToGroup(nextObjective);
- }
- break;
- case REMOVE:
- if (nextGroup == null) {
- log.warn("Cannot remove next {} that does not exist in device {}",
- nextObjective.id(), deviceId);
- return;
- }
- log.debug("Processing NextObjective id{} in dev{} - remove group",
- nextObjective.id(), deviceId);
- removeGroup(nextObjective);
- break;
- case REMOVE_FROM_EXISTING:
- if (nextGroup == null) {
- log.warn("Cannot remove from next {} that does not exist in device {}",
- nextObjective.id(), deviceId);
- return;
- }
- log.debug("Processing NextObjective id{} in dev{} - remove bucket",
- nextObjective.id(), deviceId);
- removeBucketFromGroup(nextObjective);
- break;
- default:
- log.warn("Unsupported operation {}", nextObjective.op());
- }
- }
-
- //////////////////////////////////////
- // Flow handling
- //////////////////////////////////////
-
- /**
- * As per OFDPA 2.0 TTP, filtering of VLAN ids, MAC addresses (for routing)
- * and IP addresses configured on switch ports happen in different tables.
- * Note that IP filtering rules need to be added to the ACL table, as there
- * is no mechanism to send to controller via IP table.
- *
- * @param filt the filtering objective
- * @param install indicates whether to add or remove the objective
- * @param applicationId the application that sent this objective
- */
- private void processFilter(FilteringObjective filt,
- boolean install, ApplicationId applicationId) {
- // This driver only processes filtering criteria defined with switch
- // ports as the key
- PortCriterion portCriterion = null;
- EthCriterion ethCriterion = null;
- VlanIdCriterion vidCriterion = null;
- Collection<IPCriterion> ips = new ArrayList<IPCriterion>();
- if (!filt.key().equals(Criteria.dummy()) &&
- filt.key().type() == Criterion.Type.IN_PORT) {
- portCriterion = (PortCriterion) filt.key();
- } else {
- log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
- fail(filt, ObjectiveError.UNKNOWN);
- return;
- }
- // convert filtering conditions for switch-intfs into flowrules
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- for (Criterion criterion : filt.conditions()) {
- if (criterion.type() == Criterion.Type.ETH_DST) {
- ethCriterion = (EthCriterion) criterion;
- } else if (criterion.type() == Criterion.Type.VLAN_VID) {
- vidCriterion = (VlanIdCriterion) criterion;
- } else if (criterion.type() == Criterion.Type.IPV4_DST) {
- ips.add((IPCriterion) criterion);
- } else {
- log.error("Unsupported filter {}", criterion);
- fail(filt, ObjectiveError.UNSUPPORTED);
- return;
- }
- }
-
- VlanId assignedVlan = null;
- if (vidCriterion != null && vidCriterion.vlanId() == VlanId.NONE) {
- // untagged packets are assigned vlans in OF-DPA
- if (filt.meta() == null) {
- log.error("Missing metadata in filtering objective required "
- + "for vlan assignment in dev {}", deviceId);
- fail(filt, ObjectiveError.BADPARAMS);
- return;
- }
- for (Instruction i : filt.meta().allInstructions()) {
- if (i instanceof ModVlanIdInstruction) {
- assignedVlan = ((ModVlanIdInstruction) i).vlanId();
- }
- }
- if (assignedVlan == null) {
- log.error("Driver requires an assigned vlan-id to tag incoming "
- + "untagged packets. Not processing vlan filters on "
- + "device {}", deviceId);
- fail(filt, ObjectiveError.BADPARAMS);
- return;
- }
- }
-
- if (ethCriterion == null) {
- log.debug("filtering objective missing dstMac, cannot program TMAC table");
- } else {
- for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion,
- vidCriterion, assignedVlan,
- applicationId)) {
- log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}",
- tmacRule, deviceId);
- ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
- }
- }
-
- if (ethCriterion == null || vidCriterion == null) {
- log.debug("filtering objective missing dstMac or vlan, cannot program"
- + "Vlan Table");
- } else {
- for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion,
- assignedVlan,
- applicationId)) {
- log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
- vlanRule, deviceId);
- ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
- }
- }
-
- for (IPCriterion ipaddr : ips) {
- // since we ignore port information for IP rules, and the same (gateway) IP
- // can be configured on multiple ports, we make sure that we send
- // only a single rule to the switch.
- if (!sentIpFilters.contains(ipaddr)) {
- sentIpFilters.add(ipaddr);
- log.debug("adding IP filtering rules in ACL table {} for dev: {}",
- ipaddr, deviceId);
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ipaddr.ip());
- treatment.setOutput(PortNumber.CONTROLLER);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
- }
- }
-
- // apply filtering flow rules
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Applied {} filtering rules in device {}",
- ops.stages().get(0).size(), deviceId);
- pass(filt);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to apply all filtering rules in dev {}", deviceId);
- fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
-
- }
-
- /**
- * Allows untagged packets into pipeline by assigning a vlan id.
- * Vlan assignment is done by the application.
- * Allows tagged packets into pipeline as per configured port-vlan info.
- *
- * @param portCriterion port on device for which this filter is programmed
- * @param vidCriterion vlan assigned to port, or NONE for untagged
- * @param assignedVlan assigned vlan-id for untagged packets
- * @param applicationId for application programming this filter
- * @return list of FlowRule for port-vlan filters
- */
- protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
- VlanIdCriterion vidCriterion,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- List<FlowRule> rules = new ArrayList<FlowRule>();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchVlanId(vidCriterion.vlanId());
- treatment.transition(TMAC_TABLE);
-
- VlanId storeVlan = null;
- if (vidCriterion.vlanId() == VlanId.NONE) {
- // untagged packets are assigned vlans
- treatment.pushVlan().setVlanId(assignedVlan);
- // XXX ofdpa will require an additional vlan match on the assigned vlan
- // and it may not require the push. This is not in compliance with OF
- // standard. Waiting on what the exact flows are going to look like.
- storeVlan = assignedVlan;
- } else {
- storeVlan = vidCriterion.vlanId();
- }
-
- // ofdpa cannot match on ALL portnumber, so we need to use separate
- // rules for each port.
- List<PortNumber> portnums = new ArrayList<PortNumber>();
- if (portCriterion.port() == PortNumber.ALL) {
- for (Port port : deviceService.getPorts(deviceId)) {
- if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
- portnums.add(port.number());
- }
- }
- } else {
- portnums.add(portCriterion.port());
- }
-
- for (PortNumber pnum : portnums) {
- // update storage
- port2Vlan.put(pnum, storeVlan);
- Set<PortNumber> vlanPorts = vlan2Port.get(storeVlan);
- if (vlanPorts == null) {
- vlanPorts = Collections.newSetFromMap(
- new ConcurrentHashMap<PortNumber, Boolean>());
- vlanPorts.add(pnum);
- vlan2Port.put(storeVlan, vlanPorts);
- } else {
- vlanPorts.add(pnum);
- }
- // create rest of flowrule
- selector.matchInPort(pnum);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(VLAN_TABLE).build();
- rules.add(rule);
- }
- return rules;
- }
-
- /**
- * Allows routed packets with correct destination MAC to be directed
- * to unicast-IP routing table or MPLS forwarding table.
- *
- * @param portCriterion port on device for which this filter is programmed
- * @param ethCriterion dstMac of device for which is filter is programmed
- * @param vidCriterion vlan assigned to port, or NONE for untagged
- * @param assignedVlan assigned vlan-id for untagged packets
- * @param applicationId for application programming this filter
- * @return list of FlowRule for port-vlan filters
-
- */
- protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion,
- EthCriterion ethCriterion,
- VlanIdCriterion vidCriterion,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- //handling untagged packets via assigned VLAN
- if (vidCriterion.vlanId() == VlanId.NONE) {
- vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
- }
- // ofdpa cannot match on ALL portnumber, so we need to use separate
- // rules for each port.
- List<PortNumber> portnums = new ArrayList<PortNumber>();
- if (portCriterion.port() == PortNumber.ALL) {
- for (Port port : deviceService.getPorts(deviceId)) {
- if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
- portnums.add(port.number());
- }
- }
- } else {
- portnums.add(portCriterion.port());
- }
-
- List<FlowRule> rules = new ArrayList<FlowRule>();
- for (PortNumber pnum : portnums) {
- // for unicast IP packets
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(pnum);
- selector.matchVlanId(vidCriterion.vlanId());
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchEthDst(ethCriterion.mac());
- treatment.transition(UNICAST_ROUTING_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- rules.add(rule);
- //for MPLS packets
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(pnum);
- selector.matchVlanId(vidCriterion.vlanId());
- selector.matchEthType(Ethernet.MPLS_UNICAST);
- selector.matchEthDst(ethCriterion.mac());
- treatment.transition(MPLS_TABLE_0);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- rules.add(rule);
- }
- return rules;
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- /**
- * In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the
- * ACL table.
- * @param fwd the forwarding objective of type 'versatile'
- * @return a collection of flow rules to be sent to the switch. An empty
- * collection may be returned if there is a problem in processing
- * the flow rule
- */
- private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
- log.info("Processing versatile forwarding objective");
- 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.BADPARAMS);
- return Collections.emptySet();
- }
- if (fwd.nextId() == null && fwd.treatment() == null) {
- log.error("Forwarding objective {} from {} must contain "
- + "nextId or Treatment", fwd.selector(), fwd.appId());
- return Collections.emptySet();
- }
- // XXX driver does not currently do type checking as per Tables 65-67 in
- // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller.
- if (fwd.treatment() != null &&
- 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) {
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(fwd.selector())
- .withTreatment(fwd.treatment())
- .makePermanent()
- .forTable(ACL_TABLE);
- return Collections.singletonList(ruleBuilder.build());
- } else {
- log.warn("Only allowed treatments in versatile forwarding "
- + "objectives are punts to the controller");
- return Collections.emptySet();
- }
- }
-
- if (fwd.nextId() != null) {
- // XXX overide case
- log.warn("versatile objective --> next Id not yet implemeted");
- }
- return Collections.emptySet();
- }
-
- /**
- * In the OF-DPA 2.0 pipeline, specific forwarding refers to the IP table
- * (unicast or multicast) or the L2 table (mac + vlan) or the MPLS table.
- *
- * @param fwd the forwarding objective of type 'specific'
- * @return a collection of flow rules. Typically there will be only one
- * for this type of forwarding objective. An empty set may be
- * returned if there is an issue in processing the objective.
- */
- protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
- log.trace("Processing specific fwd objective:{} in dev:{} with next:{}",
- fwd.id(), deviceId, fwd.nextId());
- boolean isEthTypeObj = isSupportedEthTypeObjective(fwd);
- boolean isEthDstObj = isSupportedEthDstObjective(fwd);
-
- if (isEthTypeObj) {
- return processEthTypeSpecific(fwd);
- } else if (isEthDstObj) {
- return processEthDstSpecific(fwd);
- } else {
- log.warn("processSpecific: Unsupported forwarding objective "
- + "criteria fwd:{} in dev:{}", fwd.nextId(), deviceId);
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
- }
-
- private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType = (EthTypeCriterion) selector
- .getCriterion(Criterion.Type.ETH_TYPE);
- if ((ethType == null) ||
- ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
- (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) {
- return false;
- }
- return true;
- }
-
- private boolean isSupportedEthDstObjective(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthCriterion ethDst = (EthCriterion) selector
- .getCriterion(Criterion.Type.ETH_DST);
- VlanIdCriterion vlanId = (VlanIdCriterion) selector
- .getCriterion(Criterion.Type.VLAN_VID);
- if (ethDst == null && vlanId == null) {
- return false;
- }
- return true;
- }
-
- /**
- * Handles forwarding rules to the IP and MPLS tables.
- *
- * @param fwd the forwarding objective
- * @return A collection of flow rules, or an empty set
- */
- protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType =
- (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
-
- int forTableId = -1;
- TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
- if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
- filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(((IPCriterion)
- selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
- forTableId = UNICAST_ROUTING_TABLE;
- log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
- + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
- } else {
- filteredSelector
- .matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(((MplsCriterion)
- selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
- MplsBosCriterion bos = (MplsBosCriterion) selector
- .getCriterion(Criterion.Type.MPLS_BOS);
- if (bos != null) {
- filteredSelector.matchMplsBos(bos.mplsBos());
- }
- forTableId = MPLS_TABLE_1;
- log.debug("processing MPLS specific forwarding objective {} -> next:{}"
- + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
- }
-
- TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
- boolean popMpls = false;
- if (fwd.treatment() != null) {
- for (Instruction i : fwd.treatment().allInstructions()) {
- tb.add(i);
- if (i instanceof L2ModificationInstruction &&
- ((L2ModificationInstruction) i).subtype() == L2SubType.MPLS_POP) {
- popMpls = true;
- }
- }
- }
-
- if (fwd.nextId() != null) {
- if (forTableId == MPLS_TABLE_1 && !popMpls) {
- log.warn("SR CONTINUE case cannot be handled as MPLS ECMP "
- + "is not implemented in OF-DPA yet. Aborting this flow "
- + "in this device {}", deviceId);
- // XXX We could convert to forwarding to a single-port, via a
- // MPLS interface, or a MPLS SWAP (with-same) but that would
- // have to be handled in the next-objective. Also the pop-mpls
- // logic used here won't work in non-BoS case.
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- return Collections.emptySet();
- }
-
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
- // we only need the top level group's key to point the flow to it
- Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
- if (group == null) {
- log.warn("Group with key:{} for next-id:{} not found in dev:{}",
- gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- tb.deferred().group(group.id());
- }
- tb.transition(ACL_TABLE);
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(filteredSelector.build())
- .withTreatment(tb.build())
- .forTable(forTableId);
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- return Collections.singletonList(ruleBuilder.build());
- }
-
- /**
- * Handles forwarding rules to the L2 bridging table. Flow actions are not
- * allowed in the bridging table - instead we use L2 Interface group or
- * L2 flood group
- *
- * @param fwd the forwarding objective
- * @return A collection of flow rules, or an empty set
- */
- protected Collection<FlowRule> processEthDstSpecific(ForwardingObjective fwd) {
- List<FlowRule> rules = new ArrayList<>();
-
- // Build filtered selector
- TrafficSelector selector = fwd.selector();
- EthCriterion ethCriterion = (EthCriterion) selector
- .getCriterion(Criterion.Type.ETH_DST);
- VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector
- .getCriterion(Criterion.Type.VLAN_VID);
-
- if (vlanIdCriterion == null) {
- log.warn("Forwarding objective for bridging requires vlan. Not "
- + "installing fwd:{} in dev:{}", fwd.id(), deviceId);
- fail(fwd, ObjectiveError.BADPARAMS);
- return Collections.emptySet();
- }
-
- TrafficSelector.Builder filteredSelectorBuilder =
- DefaultTrafficSelector.builder();
- // Do not match MacAddress for subnet broadcast entry
- if (!ethCriterion.mac().equals(MacAddress.NONE)) {
- filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
- log.debug("processing L2 forwarding objective:{} -> next:{} in dev:{}",
- fwd.id(), fwd.nextId(), deviceId);
- } else {
- log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} "
- + "in dev:{} for vlan:{}",
- fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId());
- }
- filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
- TrafficSelector filteredSelector = filteredSelectorBuilder.build();
-
- if (fwd.treatment() != null) {
- log.warn("Ignoring traffic treatment in fwd rule {} meant for L2 table"
- + "for dev:{}. Expecting only nextId", fwd.id(), deviceId);
- }
-
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- if (next != null) {
- List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
- // we only need the top level group's key to point the flow to it
- Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
- if (group != null) {
- treatmentBuilder.deferred().group(group.id());
- } else {
- log.warn("Group with key:{} for next-id:{} not found in dev:{}",
- gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- }
- }
- treatmentBuilder.immediate().transition(ACL_TABLE);
- TrafficTreatment filteredTreatment = treatmentBuilder.build();
-
- // Build bridging table entries
- FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
- flowRuleBuilder.fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(filteredSelector)
- .withTreatment(filteredTreatment)
- .forTable(BRIDGING_TABLE);
- if (fwd.permanent()) {
- flowRuleBuilder.makePermanent();
- } else {
- flowRuleBuilder.makeTemporary(fwd.timeout());
- }
- rules.add(flowRuleBuilder.build());
- return rules;
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- protected void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
- //////////////////////////////////////
- // Group handling
- //////////////////////////////////////
-
- private void addGroup(NextObjective nextObjective) {
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() != 1) {
- log.error("Next Objectives of type Simple should only have a "
- + "single Traffic Treatment. Next Objective Id:{}",
- nextObjective.id());
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
- }
- processSimpleNextObjective(nextObjective);
- break;
- case BROADCAST:
- processBroadcastNextObjective(nextObjective);
- break;
- case HASHED:
- processHashedNextObjective(nextObjective);
- break;
- case FAILOVER:
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
- }
- }
-
- /**
- * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
- * a chain of groups. The simple Next Objective passed
- * in by the application has to be broken up into a group chain
- * comprising of an L3 Unicast Group that points to an L2 Interface
- * Group which in-turn points to an output port. In some cases, the simple
- * next Objective can just be an L2 interface without the need for chaining.
- *
- * @param nextObj the nextObjective of type SIMPLE
- */
- private void processSimpleNextObjective(NextObjective nextObj) {
- TrafficTreatment treatment = nextObj.next().iterator().next();
- // determine if plain L2 or L3->L2
- boolean plainL2 = true;
- for (Instruction ins : treatment.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- if (l2ins.subtype() == L2SubType.ETH_DST ||
- l2ins.subtype() == L2SubType.ETH_SRC) {
- plainL2 = false;
- break;
- }
- }
- }
-
- if (plainL2) {
- createL2InterfaceGroup(nextObj);
- return;
- }
-
- // break up simple next objective to GroupChain objects
- GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(),
- nextObj.appId(), false,
- nextObj.meta());
- if (groupInfo == null) {
- log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
- return;
- }
- // create object for local and distributed storage
- Deque<GroupKey> gkeyChain = new ArrayDeque<>();
- gkeyChain.addFirst(groupInfo.innerGrpDesc.appCookie());
- gkeyChain.addFirst(groupInfo.outerGrpDesc.appCookie());
- OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(
- Collections.singletonList(gkeyChain),
- nextObj);
-
- // store l3groupkey with the ofdpaNextGroup for the nextObjective that depends on it
- updatePendingNextObjective(groupInfo.outerGrpDesc.appCookie(), ofdpaGrp);
-
- // now we are ready to send the l2 groupDescription (inner), as all the stores
- // that will get async replies have been updated. By waiting to update
- // the stores, we prevent nasty race conditions.
- groupService.addGroup(groupInfo.innerGrpDesc);
- }
-
- private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
- List<OfdpaNextGroup> nextList = new CopyOnWriteArrayList<OfdpaNextGroup>();
- nextList.add(value);
- List<OfdpaNextGroup> ret = pendingNextObjectives.asMap()
- .putIfAbsent(key, nextList);
- if (ret != null) {
- ret.add(value);
- }
- }
-
- /**
- * Creates a simple L2 Interface Group.
- *
- * @param nextObj the next Objective
- */
- private void createL2InterfaceGroup(NextObjective nextObj) {
- // only allowed actions are vlan pop and outport
- TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
- PortNumber portNum = null;
- for (Instruction ins : nextObj.next().iterator().next().allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- switch (l2ins.subtype()) {
- case VLAN_POP:
- ttb.add(l2ins);
- break;
- default:
- break;
- }
- } else if (ins.type() == Instruction.Type.OUTPUT) {
- portNum = ((OutputInstruction) ins).port();
- ttb.add(ins);
- } else {
- log.warn("Driver does not handle this type of TrafficTreatment"
- + " instruction in simple nextObjectives: {}", ins.type());
- }
- }
- //use the vlanid associated with the port
- VlanId vlanid = port2Vlan.get(portNum);
-
- if (vlanid == null && nextObj.meta() != null) {
- // use metadata vlan info if available
- Criterion vidCriterion = nextObj.meta().getCriterion(Type.VLAN_VID);
- if (vidCriterion != null) {
- vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
- }
- }
-
- if (vlanid == null) {
- log.error("Driver cannot process an L2/L3 group chain without "
- + "egress vlan information for dev: {} port:{}",
- deviceId, portNum);
- return;
- }
-
- // assemble information for ofdpa l2interface group
- Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum.toLong();
- // a globally unique groupkey that is different for ports in the same devices
- // but different for the same portnumber on different devices. Also different
- // for the various group-types created out of the same next objective.
- int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong());
- final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
-
- // create group description for the l2interfacegroup
- GroupBucket l2interfaceGroupBucket =
- DefaultGroupBucket.createIndirectGroupBucket(ttb.build());
- GroupDescription l2groupDescription =
- new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(
- l2interfaceGroupBucket)),
- l2groupkey,
- l2groupId,
- nextObj.appId());
- log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}",
- deviceId, Integer.toHexString(l2groupId),
- l2groupkey, nextObj.id());
-
- // create object for local and distributed storage
- Deque<GroupKey> singleKey = new ArrayDeque<>();
- singleKey.addFirst(l2groupkey);
- OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(
- Collections.singletonList(singleKey),
- nextObj);
-
- // store l2groupkey for the nextObjective that depends on it
- updatePendingNextObjective(l2groupkey, ofdpaGrp);
- // send the group description to the group service
- groupService.addGroup(l2groupDescription);
- }
-
- /**
- * Creates one of two possible group-chains from the treatment
- * passed in. Depending on the MPLS boolean, this method either creates
- * an L3Unicast Group --> L2Interface Group, if mpls is false;
- * or MPLSInterface Group --> L2Interface Group, if mpls is true;
- * The returned 'inner' group description is always the L2 Interface group.
- *
- * @param treatment that needs to be broken up to create the group chain
- * @param nextId of the next objective that needs this group chain
- * @param appId of the application that sent this next objective
- * @param mpls determines if L3Unicast or MPLSInterface group is created
- * @param meta metadata passed in by the application as part of the nextObjective
- * @return GroupInfo containing the GroupDescription of the
- * L2Interface group(inner) and the GroupDescription of the (outer)
- * L3Unicast/MPLSInterface group. May return null if there is an
- * error in processing the chain
- */
- private GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
- ApplicationId appId, boolean mpls,
- TrafficSelector meta) {
- // for the l2interface group, get vlan and port info
- // for the outer group, get the src/dst mac, and vlan info
- TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
- TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
- VlanId vlanid = null;
- long portNum = 0;
- boolean setVlan = false, popVlan = false;
- for (Instruction ins : treatment.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- switch (l2ins.subtype()) {
- case ETH_DST:
- outerTtb.setEthDst(((ModEtherInstruction) l2ins).mac());
- break;
- case ETH_SRC:
- outerTtb.setEthSrc(((ModEtherInstruction) l2ins).mac());
- break;
- case VLAN_ID:
- vlanid = ((ModVlanIdInstruction) l2ins).vlanId();
- outerTtb.setVlanId(vlanid);
- setVlan = true;
- break;
- case VLAN_POP:
- innerTtb.popVlan();
- popVlan = true;
- break;
- case DEC_MPLS_TTL:
- case MPLS_LABEL:
- case MPLS_POP:
- case MPLS_PUSH:
- case VLAN_PCP:
- case VLAN_PUSH:
- default:
- break;
- }
- } else if (ins.type() == Instruction.Type.OUTPUT) {
- portNum = ((OutputInstruction) ins).port().toLong();
- innerTtb.add(ins);
- } else {
- log.warn("Driver does not handle this type of TrafficTreatment"
- + " instruction in nextObjectives: {}", ins.type());
- }
- }
-
- if (vlanid == null) {
- //use the vlanid associated with the port
- vlanid = port2Vlan.get(PortNumber.portNumber(portNum));
- }
-
- if (vlanid == null && meta != null) {
- // use metadata if available
- Criterion vidCriterion = meta.getCriterion(Type.VLAN_VID);
- if (vidCriterion != null) {
- vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
- }
- }
-
- if (vlanid == null) {
- log.error("Driver cannot process an L2/L3 group chain without "
- + "egress vlan information for dev: {} port:{}",
- deviceId, portNum);
- return null;
- }
-
- if (!setVlan && !popVlan) {
- // untagged outgoing port
- TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
- temp.popVlan();
- innerTtb.build().allInstructions().forEach(i -> temp.add(i));
- innerTtb = temp;
- }
-
- // assemble information for ofdpa l2interface group
- Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum;
- // a globally unique groupkey that is different for ports in the same devices
- // but different for the same portnumber on different devices. Also different
- // for the various group-types created out of the same next objective.
- int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum);
- final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
-
- // assemble information for outer group
- GroupDescription outerGrpDesc = null;
- if (mpls) {
- // outer group is MPLSInteface
- Integer mplsgroupId = MPLSINTERFACEMASK | (int) portNum;
- // using mplsinterfacemask in groupkey to differentiate from l2interface
- int mplsgk = MPLSINTERFACEMASK | (0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum));
- final GroupKey mplsgroupkey = new DefaultGroupKey(appKryo.serialize(mplsgk));
- outerTtb.group(new DefaultGroupId(l2groupId));
- // create the mpls-interface group description to wait for the
- // l2 interface group to be processed
- GroupBucket mplsinterfaceGroupBucket =
- DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
- outerGrpDesc = new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(
- mplsinterfaceGroupBucket)),
- mplsgroupkey,
- mplsgroupId,
- appId);
- log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}",
- deviceId, Integer.toHexString(mplsgroupId),
- mplsgroupkey, nextId);
- } else {
- // outer group is L3Unicast
- Integer l3groupId = L3UNICASTMASK | (int) portNum;
- int l3gk = L3UNICASTMASK | (0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum));
- final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3gk));
- outerTtb.group(new DefaultGroupId(l2groupId));
- // create the l3unicast group description to wait for the
- // l2 interface group to be processed
- GroupBucket l3unicastGroupBucket =
- DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
- outerGrpDesc = new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(
- l3unicastGroupBucket)),
- l3groupkey,
- l3groupId,
- appId);
- log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}",
- deviceId, Integer.toHexString(l3groupId),
- l3groupkey, nextId);
- }
-
- // store l2groupkey with the groupChainElem for the outer-group that depends on it
- GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1);
- Set<GroupChainElem> gceSet = Collections.newSetFromMap(
- new ConcurrentHashMap<GroupChainElem, Boolean>());
- gceSet.add(gce);
- Set<GroupChainElem> retval = pendingGroups.putIfAbsent(l2groupkey, gceSet);
- if (retval != null) {
- retval.add(gce);
- }
-
- // create group description for the inner l2interfacegroup
- GroupBucket l2interfaceGroupBucket =
- DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
- GroupDescription l2groupDescription =
- new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(
- l2interfaceGroupBucket)),
- l2groupkey,
- l2groupId,
- appId);
- log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}",
- deviceId, Integer.toHexString(l2groupId),
- l2groupkey, nextId);
- return new GroupInfo(l2groupDescription, outerGrpDesc);
-
- }
-
- /**
- * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
- * a chain of groups. The broadcast Next Objective passed in by the application
- * has to be broken up into a group chain comprising of an
- * L2 Flood group whose buckets point to L2 Interface groups.
- *
- * @param nextObj the nextObjective of type BROADCAST
- */
- private void processBroadcastNextObjective(NextObjective nextObj) {
- // break up broadcast next objective to multiple groups
- Collection<TrafficTreatment> buckets = nextObj.next();
-
- // each treatment is converted to an L2 interface group
- VlanId vlanid = null;
- List<GroupDescription> l2interfaceGroupDescs = new ArrayList<>();
- List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
- for (TrafficTreatment treatment : buckets) {
- TrafficTreatment.Builder newTreatment = DefaultTrafficTreatment.builder();
- PortNumber portNum = null;
- // ensure that the only allowed treatments are pop-vlan and output
- for (Instruction ins : treatment.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- switch (l2ins.subtype()) {
- case VLAN_POP:
- newTreatment.add(l2ins);
- break;
- default:
- log.debug("action {} not permitted for broadcast nextObj",
- l2ins.subtype());
- break;
- }
- } else if (ins.type() == Instruction.Type.OUTPUT) {
- portNum = ((OutputInstruction) ins).port();
- newTreatment.add(ins);
- } else {
- log.debug("TrafficTreatment of type {} not permitted in "
- + " broadcast nextObjective", ins.type());
- }
- }
-
- // also ensure that all ports are in the same vlan
- // XXX maybe HA issue here?
- VlanId thisvlanid = port2Vlan.get(portNum);
- if (vlanid == null) {
- vlanid = thisvlanid;
- } else {
- if (!vlanid.equals(thisvlanid)) {
- log.error("Driver requires all ports in a broadcast nextObj "
- + "to be in the same vlan. Different vlans found "
- + "{} and {}. Aborting group creation", vlanid, thisvlanid);
- return;
- }
- }
-
- // assemble info for l2 interface group
- int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong());
- final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
- Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) |
- (int) portNum.toLong();
- GroupBucket l2interfaceGroupBucket =
- DefaultGroupBucket.createIndirectGroupBucket(newTreatment.build());
- GroupDescription l2interfaceGroupDescription =
- new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(
- l2interfaceGroupBucket)),
- l2groupkey,
- l2groupId,
- nextObj.appId());
- log.debug("Trying L2-Interface: device:{} gid:{} gkey:{} nextid:{}",
- deviceId, Integer.toHexString(l2groupId),
- l2groupkey, nextObj.id());
-
- Deque<GroupKey> gkeyChain = new ArrayDeque<>();
- gkeyChain.addFirst(l2groupkey);
-
- // store the info needed to create this group
- l2interfaceGroupDescs.add(l2interfaceGroupDescription);
- allGroupKeys.add(gkeyChain);
- }
-
- // assemble info for l2 flood group
- Integer l2floodgroupId = L2FLOODMASK | (vlanid.toShort() << 16) | nextObj.id();
- int l2floodgk = L2FLOODMASK | nextObj.id() << 12;
- final GroupKey l2floodgroupkey = new DefaultGroupKey(appKryo.serialize(l2floodgk));
- // collection of group buckets pointing to all the l2 interface groups
- List<GroupBucket> l2floodBuckets = new ArrayList<>();
- for (GroupDescription l2intGrpDesc : l2interfaceGroupDescs) {
- TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
- ttb.group(new DefaultGroupId(l2intGrpDesc.givenGroupId()));
- GroupBucket abucket = DefaultGroupBucket.createAllGroupBucket(ttb.build());
- l2floodBuckets.add(abucket);
- }
- // create the l2flood group-description to wait for all the
- // l2interface groups to be processed
- GroupDescription l2floodGroupDescription =
- new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.ALL,
- new GroupBuckets(l2floodBuckets),
- l2floodgroupkey,
- l2floodgroupId,
- nextObj.appId());
- GroupChainElem gce = new GroupChainElem(l2floodGroupDescription,
- l2interfaceGroupDescs.size());
- log.debug("Trying L2-Flood: device:{} gid:{} gkey:{} nextid:{}",
- deviceId, Integer.toHexString(l2floodgroupId),
- l2floodgroupkey, nextObj.id());
-
- // create objects for local and distributed storage
- allGroupKeys.forEach(gkeyChain -> gkeyChain.addFirst(l2floodgroupkey));
- OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
-
- // store l2floodgroupkey with the ofdpaGroupChain for the nextObjective
- // that depends on it
- updatePendingNextObjective(l2floodgroupkey, ofdpaGrp);
-
- for (GroupDescription l2intGrpDesc : l2interfaceGroupDescs) {
- // store all l2groupkeys with the groupChainElem for the l2floodgroup
- // that depends on it
- Set<GroupChainElem> gceSet = Collections.newSetFromMap(
- new ConcurrentHashMap<GroupChainElem, Boolean>());
- gceSet.add(gce);
- Set<GroupChainElem> retval = pendingGroups.putIfAbsent(
- l2intGrpDesc.appCookie(), gceSet);
- if (retval != null) {
- retval.add(gce);
- }
-
- // create and send groups for all l2 interface groups
- groupService.addGroup(l2intGrpDesc);
- }
- }
-
- /**
- * Utility class for moving group information around.
- *
- */
- private class GroupInfo {
- private GroupDescription innerGrpDesc;
- private GroupDescription outerGrpDesc;
-
- GroupInfo(GroupDescription innerGrpDesc, GroupDescription outerGrpDesc) {
- this.innerGrpDesc = innerGrpDesc;
- this.outerGrpDesc = outerGrpDesc;
- }
- }
-
- /**
- * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
- * a chain of groups. The hashed Next Objective passed in by the application
- * has to be broken up into a group chain comprising of an
- * L3 ECMP group as the top level group. Buckets of this group can point
- * to a variety of groups in a group chain, depending on the whether
- * MPLS labels are being pushed or not.
- * <p>
- * NOTE: We do not create MPLS ECMP groups as they are unimplemented in
- * OF-DPA 2.0 (even though it is in the spec). Therefore we do not
- * check the nextObjective meta.
- *
- * @param nextObj the nextObjective of type HASHED
- */
- private void processHashedNextObjective(NextObjective nextObj) {
- // break up hashed next objective to multiple groups
- Collection<TrafficTreatment> buckets = nextObj.next();
-
- // storage for all group keys in the chain of groups created
- List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
- List<GroupInfo> unsentGroups = new ArrayList<>();
- for (TrafficTreatment bucket : buckets) {
- //figure out how many labels are pushed in each bucket
- int labelsPushed = 0;
- MplsLabel innermostLabel = null;
- for (Instruction ins : bucket.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- if (l2ins.subtype() == L2SubType.MPLS_PUSH) {
- labelsPushed++;
- }
- if (l2ins.subtype() == L2SubType.MPLS_LABEL) {
- if (innermostLabel == null) {
- innermostLabel = ((ModMplsLabelInstruction) l2ins).mplsLabel();
- }
- }
- }
- }
-
- Deque<GroupKey> gkeyChain = new ArrayDeque<>();
- // XXX we only deal with 0 and 1 label push right now
- if (labelsPushed == 0) {
- GroupInfo nolabelGroupInfo = createL2L3Chain(bucket, nextObj.id(),
- nextObj.appId(), false,
- nextObj.meta());
- if (nolabelGroupInfo == null) {
- log.error("Could not process nextObj={} in dev:{}",
- nextObj.id(), deviceId);
- return;
- }
- gkeyChain.addFirst(nolabelGroupInfo.innerGrpDesc.appCookie());
- gkeyChain.addFirst(nolabelGroupInfo.outerGrpDesc.appCookie());
-
- // we can't send the inner group description yet, as we have to
- // create the dependent ECMP group first. So we store..
- unsentGroups.add(nolabelGroupInfo);
-
- } else if (labelsPushed == 1) {
- GroupInfo onelabelGroupInfo = createL2L3Chain(bucket, nextObj.id(),
- nextObj.appId(), true,
- nextObj.meta());
- if (onelabelGroupInfo == null) {
- log.error("Could not process nextObj={} in dev:{}",
- nextObj.id(), deviceId);
- return;
- }
- // we need to add another group to this chain - the L3VPN group
- TrafficTreatment.Builder l3vpnTtb = DefaultTrafficTreatment.builder();
- l3vpnTtb.pushMpls()
- .setMpls(innermostLabel)
- .setMplsBos(true)
- .copyTtlOut()
- .group(new DefaultGroupId(
- onelabelGroupInfo.outerGrpDesc.givenGroupId()));
- GroupBucket l3vpnGrpBkt =
- DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build());
- int l3vpngroupId = L3VPNMASK | l3vpnindex.incrementAndGet();
- int l3vpngk = L3VPNMASK | nextObj.id() << 12 | l3vpnindex.get();
- GroupKey l3vpngroupkey = new DefaultGroupKey(appKryo.serialize(l3vpngk));
- GroupDescription l3vpnGroupDesc =
- new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(
- l3vpnGrpBkt)),
- l3vpngroupkey,
- l3vpngroupId,
- nextObj.appId());
- GroupChainElem l3vpnGce = new GroupChainElem(l3vpnGroupDesc, 1);
- Set<GroupChainElem> gceSet = Collections.newSetFromMap(
- new ConcurrentHashMap<GroupChainElem, Boolean>());
- gceSet.add(l3vpnGce);
- Set<GroupChainElem> retval = pendingGroups
- .putIfAbsent(onelabelGroupInfo.outerGrpDesc.appCookie(), gceSet);
- if (retval != null) {
- retval.add(l3vpnGce);
- }
-
- gkeyChain.addFirst(onelabelGroupInfo.innerGrpDesc.appCookie());
- gkeyChain.addFirst(onelabelGroupInfo.outerGrpDesc.appCookie());
- gkeyChain.addFirst(l3vpngroupkey);
-
- //now we can replace the outerGrpDesc with the one we just created
- onelabelGroupInfo.outerGrpDesc = l3vpnGroupDesc;
-
- // we can't send the innermost group yet, as we have to create
- // the dependent ECMP group first. So we store ...
- unsentGroups.add(onelabelGroupInfo);
-
- log.debug("Trying L3VPN: device:{} gid:{} gkey:{} nextId:{}",
- deviceId, Integer.toHexString(l3vpngroupId),
- l3vpngroupkey, nextObj.id());
-
- } else {
- log.warn("Driver currently does not handle more than 1 MPLS "
- + "labels. Not processing nextObjective {}", nextObj);
- return;
- }
-
- // all groups in this chain
- allGroupKeys.add(gkeyChain);
- }
-
- // now we can create the outermost L3 ECMP group
- List<GroupBucket> l3ecmpGroupBuckets = new ArrayList<>();
- for (GroupInfo gi : unsentGroups) {
- // create ECMP bucket to point to the outer group
- TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
- ttb.group(new DefaultGroupId(gi.outerGrpDesc.givenGroupId()));
- GroupBucket sbucket = DefaultGroupBucket
- .createSelectGroupBucket(ttb.build());
- l3ecmpGroupBuckets.add(sbucket);
- }
- int l3ecmpGroupId = L3ECMPMASK | nextObj.id() << 12;
- GroupKey l3ecmpGroupKey = new DefaultGroupKey(appKryo.serialize(l3ecmpGroupId));
- GroupDescription l3ecmpGroupDesc =
- new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.SELECT,
- new GroupBuckets(l3ecmpGroupBuckets),
- l3ecmpGroupKey,
- l3ecmpGroupId,
- nextObj.appId());
- GroupChainElem l3ecmpGce = new GroupChainElem(l3ecmpGroupDesc,
- l3ecmpGroupBuckets.size());
-
- // create objects for local and distributed storage
- allGroupKeys.forEach(gkeyChain -> gkeyChain.addFirst(l3ecmpGroupKey));
- OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj);
-
- // store l3ecmpGroupKey with the ofdpaGroupChain for the nextObjective
- // that depends on it
- updatePendingNextObjective(l3ecmpGroupKey, ofdpaGrp);
-
- log.debug("Trying L3ECMP: device:{} gid:{} gkey:{} nextId:{}",
- deviceId, Integer.toHexString(l3ecmpGroupId),
- l3ecmpGroupKey, nextObj.id());
- // finally we are ready to send the innermost groups
- for (GroupInfo gi : unsentGroups) {
- log.debug("Sending innermost group {} in group chain on device {} ",
- Integer.toHexString(gi.innerGrpDesc.givenGroupId()), deviceId);
- Set<GroupChainElem> gceSet = Collections.newSetFromMap(
- new ConcurrentHashMap<GroupChainElem, Boolean>());
- gceSet.add(l3ecmpGce);
- Set<GroupChainElem> retval = pendingGroups
- .putIfAbsent(gi.outerGrpDesc.appCookie(), gceSet);
- if (retval != null) {
- retval.add(l3ecmpGce);
- }
-
- groupService.addGroup(gi.innerGrpDesc);
- }
-
- }
-
- private void addBucketToGroup(NextObjective nextObjective) {
- // TODO Auto-generated method stub
- }
-
- private void waitToAddBucketToGroup(NextObjective nextObjective) {
- // TODO Auto-generated method stub
- }
-
- private void removeBucketFromGroup(NextObjective nextObjective) {
- // TODO Auto-generated method stub
- }
-
- private void removeGroup(NextObjective nextObjective) {
- // TODO Auto-generated method stub
- }
-
- /**
- * Processes next element of a group chain. Assumption is that if this
- * group points to another group, the latter has already been created
- * and this driver has received notification for it. A second assumption is
- * that if there is another group waiting for this group then the appropriate
- * stores already have the information to act upon the notification for the
- * creating of this group.
- * <p>
- * The processing of the GroupChainElement depends on the number of groups
- * this element is waiting on. For all group types other than SIMPLE, a
- * GroupChainElement could be waiting on multiple groups.
- *
- * @param gce the group chain element to be processed next
- */
- private void processGroupChain(GroupChainElem gce) {
- int waitOnGroups = gce.decrementAndGetGroupsWaitedOn();
- if (waitOnGroups != 0) {
- log.debug("GCE: {} not ready to be processed", gce);
- return;
- }
- log.debug("GCE: {} ready to be processed", gce);
- groupService.addGroup(gce.groupDescription);
- }
-
- private class GroupChecker implements Runnable {
- @Override
- public void run() {
- Set<GroupKey> keys = pendingGroups.keySet().stream()
- .filter(key -> groupService.getGroup(deviceId, key) != null)
- .collect(Collectors.toSet());
- Set<GroupKey> otherkeys = pendingNextObjectives.asMap().keySet().stream()
- .filter(otherkey -> groupService.getGroup(deviceId, otherkey) != null)
- .collect(Collectors.toSet());
- keys.addAll(otherkeys);
-
- keys.stream().forEach(key -> {
- //first check for group chain
- Set<GroupChainElem> gceSet = pendingGroups.remove(key);
- if (gceSet != null) {
- for (GroupChainElem gce : gceSet) {
- log.info("Group service processed group key {} in device {}. "
- + "Processing next group in group chain with group id {}",
- key, deviceId,
- Integer.toHexString(gce.groupDescription.givenGroupId()));
- processGroupChain(gce);
- }
- } else {
- List<OfdpaNextGroup> objList = pendingNextObjectives.getIfPresent(key);
- if (objList != null) {
- pendingNextObjectives.invalidate(key);
- objList.forEach(obj -> {
- log.info("Group service processed group key {} in device:{}. "
- + "Done implementing next objective: {} <<-->> gid:{}",
- key, deviceId, obj.nextObjective().id(),
- Integer.toHexString(groupService.getGroup(deviceId, key)
- .givenGroupId()));
- pass(obj.nextObjective());
- flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj);
- });
- }
- }
- });
- }
- }
-
- private class InnerGroupListener implements GroupListener {
- @Override
- public void event(GroupEvent event) {
- log.trace("received group event of type {}", event.type());
- if (event.type() == GroupEvent.Type.GROUP_ADDED) {
- GroupKey key = event.subject().appCookie();
- // first check for group chain
- Set<GroupChainElem> gceSet = pendingGroups.remove(key);
- if (gceSet != null) {
- for (GroupChainElem gce : gceSet) {
- log.info("group ADDED with group key {} .. "
- + "Processing next group in group chain with group key {}",
- key,
- gce.groupDescription.appCookie());
- processGroupChain(gce);
- }
- } else {
- List<OfdpaNextGroup> objList = pendingNextObjectives.getIfPresent(key);
- if (objList != null) {
- pendingNextObjectives.invalidate(key);
- objList.forEach(obj -> {
- log.info("group ADDED with key {} in dev {}.. Done implementing next "
- + "objective: {} <<-->> gid:{}",
- key, deviceId, obj.nextObjective().id(),
- Integer.toHexString(groupService.getGroup(deviceId, key)
- .givenGroupId()));
- pass(obj.nextObjective());
- flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj);
- });
- }
- }
- }
- }
- }
-
- /**
- * Represents an entire group-chain that implements a Next-Objective from
- * the application. The objective is represented as a list of deques, where
- * each deque can is a separate chain of groups.
- * <p>
- * For example, an ECMP group with 3 buckets, where each bucket points to
- * a group chain of L3 Unicast and L2 interface groups will look like this:
- * <ul>
- * <li>List[0] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
- * <li>List[1] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
- * <li>List[2] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last)
- * </ul>
- * where the first element of each deque is the same, representing the
- * top level ECMP group, while every other element represents a unique groupKey.
- * <p>
- * Also includes information about the next objective that
- * resulted in this group-chain.
- *
- */
- private class OfdpaNextGroup implements NextGroup {
- private final NextObjective nextObj;
- private final List<Deque<GroupKey>> gkeys;
-
- public OfdpaNextGroup(List<Deque<GroupKey>> gkeys, NextObjective nextObj) {
- this.gkeys = gkeys;
- this.nextObj = nextObj;
- }
-
- @SuppressWarnings("unused")
- public List<Deque<GroupKey>> groupKey() {
- return gkeys;
- }
-
- public NextObjective nextObjective() {
- return nextObj;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(gkeys);
- }
-
- }
-
- /**
- * Represents a group element that is part of a chain of groups.
- * Stores enough information to create a Group Description to add the group
- * to the switch by requesting the Group Service. Objects instantiating this
- * class are meant to be temporary and live as long as it is needed to wait for
- * preceding groups in the group chain to be created.
- */
- private class GroupChainElem {
- private GroupDescription groupDescription;
- private AtomicInteger waitOnGroups;
-
- GroupChainElem(GroupDescription groupDescription, int waitOnGroups) {
- this.groupDescription = groupDescription;
- this.waitOnGroups = new AtomicInteger(waitOnGroups);
- }
-
- /**
- * This methods atomically decrements the counter for the number of
- * groups this GroupChainElement is waiting on, for notifications from
- * the Group Service. When this method returns a value of 0, this
- * GroupChainElement is ready to be processed.
- *
- * @return integer indication of the number of notifications being waited on
- */
- int decrementAndGetGroupsWaitedOn() {
- return waitOnGroups.decrementAndGet();
- }
-
- @Override
- public String toString() {
- return (Integer.toHexString(groupDescription.givenGroupId()) +
- " groupKey: " + groupDescription.appCookie() +
- " waiting-on-groups: " + waitOnGroups.get() +
- " device: " + deviceId);
- }
- }
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java
deleted file mode 100644
index 5993d96e..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.MacAddress;
-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.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.EthCriterion;
-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.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.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * OpenvSwitch emulation of the Corsa pipeline handler.
- */
-public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- protected static final int MAC_TABLE = 0;
- protected static final int VLAN_MPLS_TABLE = 1;
- protected static final int VLAN_TABLE = 2;
- //protected static final int MPLS_TABLE = 3;
- protected static final int ETHER_TABLE = 4;
- protected static final int COS_MAP_TABLE = 5;
- protected static final int FIB_TABLE = 6;
- protected static final int LOCAL_TABLE = 9;
-
-
- protected static final int CONTROLLER_PRIORITY = 255;
- private static final int DROP_PRIORITY = 0;
- private static final int HIGHEST_PRIORITY = 0xffff;
-
- private final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- protected FlowRuleService flowRuleService;
- private CoreService coreService;
- private GroupService groupService;
- private FlowObjectiveStore flowObjectiveStore;
- protected DeviceId deviceId;
- protected ApplicationId appId;
-
- private KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(GroupKey.class)
- .register(DefaultGroupKey.class)
- .register(CorsaGroup.class)
- .register(byte[].class)
- .build();
-
- private Cache<GroupKey, NextObjective> pendingGroups;
-
- private ScheduledExecutorService groupChecker =
- Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
- "ovs-corsa-%d"));
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- pendingGroups = CacheBuilder.newBuilder()
- .expireAfterWrite(20, TimeUnit.SECONDS)
- .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
- if (notification.getCause() == RemovalCause.EXPIRED) {
- fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
- }
- }).build();
-
- groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- groupService = serviceDirectory.get(GroupService.class);
- flowObjectiveStore = context.store();
-
- groupService.addListener(new InnerGroupListener());
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.OVSCorsaPipeline");
-
- initializePipeline();
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
- processFilter(filteringObjective,
- filteringObjective.op() == Objective.Operation.ADD,
- filteringObjective.appId());
- } else {
- fail(filteringObjective, ObjectiveError.UNSUPPORTED);
- }
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowBuilder::add);
- break;
- case REMOVE:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
-
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() == 1) {
- TrafficTreatment treatment = treatments.iterator().next();
- GroupBucket bucket =
- DefaultGroupBucket.createIndirectGroupBucket(treatment);
- final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
- GroupDescription groupDescription
- = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections
- .singletonList(bucket)),
- key,
- null, // let group service determine group id
- nextObjective.appId());
- groupService.addGroup(groupDescription);
- pendingGroups.put(key, nextObjective);
- }
- break;
- case HASHED:
- case BROADCAST:
- case FAILOVER:
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
- }
-
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
- log.debug("Processing versatile forwarding objective");
- 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 (ethType.ethType().toShort() == Ethernet.TYPE_ARP) {
- log.warn("Driver automatically handles ARP packets by punting to controller "
- + " from ETHER table");
- pass(fwd);
- return Collections.emptySet();
- } else if (ethType.ethType().toShort() == Ethernet.TYPE_LLDP ||
- ethType.ethType().toShort() == Ethernet.TYPE_BSN) {
- log.warn("Driver currently does not currently handle LLDP packets");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- } else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
- IPCriterion ipSrc = (IPCriterion) selector
- .getCriterion(Criterion.Type.IPV4_SRC);
- IPCriterion ipDst = (IPCriterion) selector
- .getCriterion(Criterion.Type.IPV4_DST);
- IPProtocolCriterion ipProto = (IPProtocolCriterion) selector
- .getCriterion(Criterion.Type.IP_PROTO);
- if (ipSrc != null) {
- log.warn("Driver does not currently handle matching Src IP");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
- if (ipDst != null) {
- log.error("Driver handles Dst IP matching as specific forwarding "
- + "objective, not versatile");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
- if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) {
- log.warn("Driver automatically punts all packets reaching the "
- + "LOCAL table to the controller");
- pass(fwd);
- return Collections.emptySet();
- }
- }
-
- log.warn("Driver does not support given versatile forwarding objective");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
-
- 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();
- }
-
- TrafficSelector filteredSelector =
- DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(
- ((IPCriterion)
- selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
- .build();
-
- TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
-
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- GroupKey key = appKryo.deserialize(next.data());
- Group group = groupService.getGroup(deviceId, key);
- if (group == null) {
- log.warn("The group left!");
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- tb.group(group.id());
- }
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(filteredSelector)
- .withTreatment(tb.build());
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- ruleBuilder.forTable(FIB_TABLE);
-
-
- return Collections.singletonList(ruleBuilder.build());
-
- }
-
- private void processFilter(FilteringObjective filt, boolean install,
- ApplicationId applicationId) {
- // This driver only processes filtering criteria defined with switch
- // ports as the key
- PortCriterion p;
- if (!filt.key().equals(Criteria.dummy()) &&
- filt.key().type() == Criterion.Type.IN_PORT) {
- p = (PortCriterion) filt.key();
- } else {
- log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
- fail(filt, ObjectiveError.UNKNOWN);
- return;
- }
- // convert filtering conditions for switch-intfs into flowrules
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- for (Criterion c : filt.conditions()) {
- if (c.type() == Criterion.Type.ETH_DST) {
- EthCriterion e = (EthCriterion) c;
- log.debug("adding rule for MAC: {}", e.mac());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthDst(e.mac());
- treatment.transition(VLAN_MPLS_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(MAC_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
- } else if (c.type() == Criterion.Type.VLAN_VID) {
- VlanIdCriterion v = (VlanIdCriterion) c;
- log.debug("adding rule for VLAN: {}", v.vlanId());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchVlanId(v.vlanId());
- selector.matchInPort(p.port());
- treatment.transition(ETHER_TABLE);
- treatment.deferred().popVlan();
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(VLAN_TABLE).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
- } else if (c.type() == Criterion.Type.IPV4_DST) {
- IPCriterion ip = (IPCriterion) c;
- log.debug("adding rule for IP: {}", ip.ip());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ip.ip());
- treatment.transition(LOCAL_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(FIB_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
- } else {
- log.warn("Driver does not currently process filtering condition"
- + " of type: {}", c.type());
- fail(filt, ObjectiveError.UNSUPPORTED);
- }
- }
- // apply filtering flow rules
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(filt);
- log.info("Applied filtering rules");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
- log.info("Failed to apply filtering rules");
- }
- }));
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
- private void initializePipeline() {
- processMacTable(true);
- processVlanMplsTable(true);
- processVlanTable(true);
- processEtherTable(true);
- processCosTable(true);
- processFibTable(true);
- processLocalTable(true);
- }
-
- private void processMacTable(boolean install) {
- TrafficSelector.Builder selector;
- TrafficTreatment.Builder treatment;
-
- // Bcast rule
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- selector.matchEthDst(MacAddress.BROADCAST);
- treatment.transition(VLAN_MPLS_TABLE);
-
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(MAC_TABLE).build();
-
-
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
-
- //Drop rule
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(MAC_TABLE).build();
-
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned mac table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision mac table");
- }
- }));
-
- }
-
- protected void processVlanMplsTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- selector.matchVlanId(VlanId.ANY);
- treatment.transition(VLAN_TABLE);
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(VLAN_MPLS_TABLE).build();
-
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned vlan/mpls table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info(
- "Failed to provision vlan/mpls table");
- }
- }));
-
- }
-
- private void processVlanTable(boolean install) {
- TrafficSelector.Builder selector;
- TrafficTreatment.Builder treatment;
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
-
- //Drop rule
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(VLAN_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned vlan table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision vlan table");
- }
- }));
- }
-
- private void processEtherTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- selector.matchEthType(Ethernet.TYPE_ARP);
- treatment.punt();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(ETHER_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- selector.matchEthType(Ethernet.TYPE_IPV4);
- treatment.transition(COS_MAP_TABLE);
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withPriority(CONTROLLER_PRIORITY)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .fromApp(appId)
- .makePermanent()
- .forTable(ETHER_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- //Drop rule
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(ETHER_TABLE).build();
-
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned ether table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision ether table");
- }
- }));
-
- }
-
- private void processCosTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- treatment.transition(FIB_TABLE);
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(COS_MAP_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned cos table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision cos table");
- }
- }));
-
- }
-
- private void processFibTable(boolean install) {
- TrafficSelector.Builder selector;
- TrafficTreatment.Builder treatment;
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- //Drop rule
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(FIB_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned FIB table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision FIB table");
- }
- }));
- }
-
- private void processLocalTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- treatment.punt();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(CONTROLLER_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(LOCAL_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned Local table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision Local table");
- }
- }));
- }
-
- private class InnerGroupListener implements GroupListener {
- @Override
- public void event(GroupEvent event) {
- if (event.type() == GroupEvent.Type.GROUP_ADDED) {
- GroupKey key = event.subject().appCookie();
-
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj != null) {
- flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
- pass(obj);
- pendingGroups.invalidate(key);
- }
- }
- }
- }
-
-
- private class GroupChecker implements Runnable {
-
- @Override
- public void run() {
- Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
- .filter(key -> groupService.getGroup(deviceId, key) != null)
- .collect(Collectors.toSet());
-
- keys.stream().forEach(key -> {
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj == null) {
- return;
- }
- pass(obj);
- pendingGroups.invalidate(key);
- log.info("Heard back from group service for group {}. "
- + "Applying pending forwarding objectives", obj.id());
- flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
- });
- }
- }
-
- private class CorsaGroup implements NextGroup {
-
- private final GroupKey key;
-
- public CorsaGroup(GroupKey key) {
- this.key = key;
- }
-
- @SuppressWarnings("unused")
- public GroupKey key() {
- return key;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(key);
- }
-
- }
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java
deleted file mode 100644
index 8a7b22b8..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.EthType;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.MastershipRole;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.device.DefaultDeviceDescription;
-import org.onosproject.net.device.DeviceDescription;
-import org.onosproject.net.device.DeviceProvider;
-import org.onosproject.net.device.DeviceProviderRegistry;
-import org.onosproject.net.device.DeviceService;
-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.instructions.Instructions;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.packet.PacketPriority;
-import org.onosproject.net.provider.AbstractProvider;
-import org.onosproject.net.provider.ProviderId;
-import org.slf4j.Logger;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pipeliner for OLT device.
- */
-public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- private final Logger log = getLogger(getClass());
-
- static final ProviderId PID = new ProviderId("olt", "org.onosproject.olt", true);
-
- static final String DEVICE = "isAccess";
- static final String OLT = "true";
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private DeviceId deviceId;
- private CoreService coreService;
-
- private ApplicationId appId;
-
- private DeviceProvider provider = new AnnotationProvider();
-
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
- DeviceProviderRegistry registry =
- serviceDirectory.get(DeviceProviderRegistry.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- coreService = serviceDirectory.get(CoreService.class);
-
- /*try {
- DeviceProviderService providerService = registry.register(provider);
- providerService.deviceConnected(deviceId,
- description(deviceId, DEVICE, OLT));
- } finally {
- registry.unregister(provider);
- }*/
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.OLTPipeline");
-
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.EAPOL.ethType().toShort())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .punt()
- .build();
-
- FlowRule flowRule = new DefaultFlowRule(deviceId, selector, treatment,
- PacketPriority.CONTROL.priorityValue(),
- appId, 0, true, null);
-
- //flowRuleService.applyFlowRules(flowRule);
- }
-
- @Override
- public void filter(FilteringObjective filter) {
- throw new UnsupportedOperationException("OLT does not filter.");
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
- throw new UnsupportedOperationException(
- "Only VERSATILE is supported.");
- }
-
- boolean isPunt = fwd.treatment().immediate().stream().anyMatch(i -> {
- if (i instanceof Instructions.OutputInstruction) {
- Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
- return out.port().equals(PortNumber.CONTROLLER);
- }
- return false;
- });
-
- if (isPunt) {
- return;
- }
-
- TrafficSelector selector = fwd.selector();
- TrafficTreatment treatment = fwd.treatment();
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector)
- .withTreatment(treatment)
- .fromApp(fwd.appId())
- .withPriority(fwd.priority());
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- switch (fwd.op()) {
- case ADD:
- flowBuilder.add(ruleBuilder.build());
- break;
- case REMOVE:
- flowBuilder.remove(ruleBuilder.build());
- break;
- default:
- log.warn("Unknown operation {}", fwd.op());
- }
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- if (fwd.context().isPresent()) {
- fwd.context().get().onSuccess(fwd);
- }
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- if (fwd.context().isPresent()) {
- fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }
- }));
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- throw new UnsupportedOperationException("OLT does not next hop.");
- }
-
- /**
- * Build a device description.
- *
- * @param deviceId a deviceId
- * @param key the key of the annotation
- * @param value the value for the annotation
- * @return a device description
- */
- private DeviceDescription description(DeviceId deviceId, String key, String value) {
- DeviceService deviceService = serviceDirectory.get(DeviceService.class);
- Device device = deviceService.getDevice(deviceId);
-
- checkNotNull(device, "Device not found in device service.");
-
- DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
- if (value != null) {
- builder.set(key, value);
- } else {
- builder.remove(key);
- }
- return new DefaultDeviceDescription(device.id().uri(), device.type(),
- device.manufacturer(), device.hwVersion(),
- device.swVersion(), device.serialNumber(),
- device.chassisId(), builder.build());
- }
-
- /**
- * Simple ancillary provider used to annotate device.
- */
- private static final class AnnotationProvider
- extends AbstractProvider implements DeviceProvider {
- private AnnotationProvider() {
- super(PID);
- }
-
- @Override
- public void triggerProbe(DeviceId deviceId) {
- }
-
- @Override
- public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
- }
-
- @Override
- public boolean isReachable(DeviceId deviceId) {
- return false;
- }
- }
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
deleted file mode 100644
index 5d098390..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.onlab.osgi.ServiceDirectory;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.device.DeviceService;
-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.Criterion.Type;
-import org.onosproject.net.flow.instructions.Instructions;
-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.slf4j.Logger;
-
-/**
- * Driver for standard OpenVSwitch.
- */
-public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
- implements Pipeliner {
-
- private static final String VTN_APP_ID = "org.onosproject.app.vtn";
- private final Logger log = getLogger(getClass());
- private CoreService coreService;
- private ServiceDirectory serviceDirectory;
- protected FlowObjectiveStore flowObjectiveStore;
- protected DeviceId deviceId;
- protected ApplicationId appId;
- protected FlowRuleService flowRuleService;
- protected DeviceService deviceService;
- private static final int TIME_OUT = 0;
- private static final int CLASSIFIER_TABLE = 0;
- private static final int MAC_TABLE = 50;
- private static final int TABLE_MISS_PRIORITY = 0;
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- super.init(deviceId, context);
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- flowObjectiveStore = context.store();
- appId = coreService
- .registerApplication("org.onosproject.driver.OpenVSwitchPipeline");
- initializePipeline();
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- super.filter(filteringObjective);
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- if (!VTN_APP_ID.equals(fwd.appId().name())) {
- super.forward(fwd);
- return;
- }
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations
- .builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream().filter(rule -> rule != null)
- .forEach(flowOpsBuilder::add);
- break;
- case REMOVE:
- rules.stream().filter(rule -> rule != null)
- .forEach(flowOpsBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
- flowRuleService.apply(flowOpsBuilder
- .build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- super.next(nextObjective);
- }
-
- private void initializePipeline() {
- processClassifierTable(true);
- processMacTable(true);
- }
-
- private void processClassifierTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
- treatment.transition(MAC_TABLE);
-
- FlowRule rule;
- rule = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(TABLE_MISS_PRIORITY).fromApp(appId)
- .makePermanent().forTable(CLASSIFIER_TABLE).build();
-
- applyRules(install, rule);
- }
-
- private void processMacTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- FlowRule rule;
- rule = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(TABLE_MISS_PRIORITY).fromApp(appId)
- .makePermanent().forTable(MAC_TABLE).build();
-
- applyRules(install, rule);
- }
-
- private void applyRules(boolean install, FlowRule rule) {
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("ONOSW provisioned " + rule.tableId() + " table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("ONOSW failed to provision " + rule.tableId() + " table");
- }
- }));
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
- log.debug("Processing versatile forwarding objective");
- return Collections.emptyList();
- }
-
- private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
- log.debug("Processing specific forwarding objective");
- TrafficSelector selector = fwd.selector();
- TrafficTreatment tb = fwd.treatment();
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId()).withPriority(fwd.priority())
- .forDevice(deviceId).withSelector(selector)
- .withTreatment(tb).makeTemporary(TIME_OUT);
- ruleBuilder.withPriority(fwd.priority());
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- }
- if (selector.getCriterion(Type.ETH_DST) != null
- || tb.allInstructions().contains(Instructions.createDrop())) {
- ruleBuilder.withTreatment(tb);
- ruleBuilder.forTable(MAC_TABLE);
- } else {
- TrafficTreatment.Builder newTraffic = DefaultTrafficTreatment.builder();
- tb.allInstructions().forEach(t -> newTraffic.add(t));
- newTraffic.transition(MAC_TABLE);
- ruleBuilder.withTreatment(newTraffic.build());
- ruleBuilder.forTable(CLASSIFIER_TABLE);
- }
- return Collections.singletonList(ruleBuilder.build());
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
deleted file mode 100644
index 7a92b4fa..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-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.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.UdpPortCriterion;
-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.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Driver for OpenstackSwitching.
- */
-public class OpenstackPipeline extends DefaultSingleTablePipeline
- implements Pipeliner {
-
- private final Logger log = getLogger(getClass());
- private CoreService coreService;
- private ServiceDirectory serviceDirectory;
- protected FlowObjectiveStore flowObjectiveStore;
- protected DeviceId deviceId;
- protected ApplicationId appId;
- protected FlowRuleService flowRuleService;
-
- protected static final int VNI_TABLE = 0;
- protected static final int FORWARDING_TABLE = 1;
-
- private static final int DROP_PRIORITY = 0;
- private static final int TIME_OUT = 0;
- private static final int DHCP_SERVER_PORT = 67;
- private static final int DHCP_CLIENT_PORT = 68;
-
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- super.init(deviceId, context);
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- flowObjectiveStore = context.store();
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.OpenstackPipeline");
-
- initializePipeline();
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- super.filter(filteringObjective);
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- super.next(nextObjective);
- }
-
- @Override
- public void forward(ForwardingObjective forwardingObjective) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
-
- rules = processForward(forwardingObjective);
-
- switch (forwardingObjective.op()) {
- case ADD:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowOpsBuilder::add);
- break;
- case REMOVE:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowOpsBuilder::remove);
- break;
- default:
- fail(forwardingObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}");
- }
-
- flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(forwardingObjective);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
- }
-
- private void initializePipeline() {
- processVNITable(true);
- processForwardingTable(true);
- }
-
- private void processVNITable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
- treatment.transition(FORWARDING_TABLE);
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(VNI_TABLE)
- .build();
-
- applyRules(install, flowRule);
- }
-
- private void processForwardingTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(FORWARDING_TABLE)
- .build();
-
- applyRules(install, flowRule);
- }
-
- private void applyRules(boolean install, FlowRule flowRule) {
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
-
- flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
-
- flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.debug("Provisioned vni or forwarding table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.debug("Failed to privision vni or forwarding table");
- }
- }));
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective forwardingObjective) {
- switch (forwardingObjective.flag()) {
- case SPECIFIC:
- return processSpecific(forwardingObjective);
- case VERSATILE:
- return processVersatile(forwardingObjective);
- default:
- fail(forwardingObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processVersatile(ForwardingObjective forwardingObjective) {
- log.debug("Processing versatile forwarding objective");
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(forwardingObjective.selector())
- .withTreatment(forwardingObjective.treatment())
- .withPriority(forwardingObjective.priority())
- .fromApp(forwardingObjective.appId());
-
- if (forwardingObjective.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(TIME_OUT);
- }
-
- //ARP & DHCP Rule
- EthTypeCriterion ethCriterion =
- (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE);
- UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective
- .selector().getCriterion(Criterion.Type.UDP_DST);
- if (ethCriterion != null) {
- if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP ||
- ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) {
- ruleBuilder.forTable(VNI_TABLE);
- return Collections.singletonList(ruleBuilder.build());
- } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) {
- ruleBuilder.forTable(VNI_TABLE);
- return Collections.singletonList(ruleBuilder.build());
- }
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processSpecific(ForwardingObjective forwardingObjective) {
- log.debug("Processing specific forwarding objective");
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(forwardingObjective.selector())
- .withTreatment(forwardingObjective.treatment())
- .withPriority(forwardingObjective.priority())
- .fromApp(forwardingObjective.appId());
-
- if (forwardingObjective.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(TIME_OUT);
- }
-
- //VNI Table Rule
- if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
- tBuilder.transition(FORWARDING_TABLE);
- ruleBuilder.withTreatment(tBuilder.build());
- ruleBuilder.forTable(VNI_TABLE);
- } else {
- ruleBuilder.forTable(FORWARDING_TABLE);
- }
-
- return Collections.singletonList(ruleBuilder.build());
- }
-
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-}
-
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
deleted file mode 100644
index 69d20835..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-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.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-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.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.store.serializers.KryoNamespaces;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pica pipeline handler.
- */
-public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- protected static final int IP_UNICAST_TABLE = 252;
- protected static final int ACL_TABLE = 0;
-
- //private static final int CONTROLLER_PRIORITY = 255;
- private static final int DROP_PRIORITY = 0;
- private static final int HIGHEST_PRIORITY = 0xffff;
-
- private final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private CoreService coreService;
- private FlowObjectiveStore flowObjectiveStore;
- private DeviceId deviceId;
- private ApplicationId appId;
- private Collection<Filter> filters;
- private Collection<ForwardingObjective> pendingVersatiles;
-
- private KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(PicaGroup.class)
- .register(byte[].class)
- .build();
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- flowObjectiveStore = context.store();
- filters = Collections.newSetFromMap(new ConcurrentHashMap<Filter, Boolean>());
- pendingVersatiles = Collections.newSetFromMap(
- new ConcurrentHashMap<ForwardingObjective, Boolean>());
- appId = coreService.registerApplication(
- "org.onosproject.driver.OVSPicaPipeline");
-
- initializePipeline();
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
- processFilter(filteringObjective,
- filteringObjective.op() == Objective.Operation.ADD,
- filteringObjective.appId());
- } else {
- fail(filteringObjective, ObjectiveError.UNSUPPORTED);
- }
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowBuilder::add);
- break;
- case REMOVE:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
-
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() != 1) {
- log.error("Next Objectives of type Simple should only have a "
- + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id());
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
- }
- TrafficTreatment treatment = treatments.iterator().next();
- TrafficTreatment.Builder filteredTreatment = DefaultTrafficTreatment.builder();
- VlanId modVlanId;
- for (Instruction ins : treatment.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- switch (l2ins.subtype()) {
- case ETH_DST:
- filteredTreatment.setEthDst(
- ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac());
- break;
- case ETH_SRC:
- filteredTreatment.setEthSrc(
- ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac());
- break;
- case VLAN_ID:
- modVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
- filteredTreatment.setVlanId(modVlanId);
- break;
- default:
- break;
- }
- } else if (ins.type() == Instruction.Type.OUTPUT) {
- //long portNum = ((Instructions.OutputInstruction) ins).port().toLong();
- filteredTreatment.add(ins);
- } else {
- // Ignore the vlan_pcp action since it's does matter much.
- log.warn("Driver does not handle this type of TrafficTreatment"
- + " instruction in nextObjectives: {}", ins.type());
- }
- }
- // store for future use
- flowObjectiveStore.putNextGroup(nextObjective.id(),
- new PicaGroup(filteredTreatment.build()));
- break;
- case HASHED:
- case BROADCAST:
- case FAILOVER:
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
- }
-
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
- log.debug("Processing versatile forwarding objective");
- TrafficSelector selector = fwd.selector();
- TrafficTreatment treatment = fwd.treatment();
- Collection<FlowRule> flowrules = new ArrayList<FlowRule>();
-
- // first add this rule for basic single-table operation
- // or non-ARP related multi-table operation
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector)
- .withTreatment(treatment)
- .withPriority(fwd.priority())
- .fromApp(fwd.appId())
- .makePermanent()
- .forTable(ACL_TABLE).build();
- flowrules.add(rule);
-
- EthTypeCriterion ethType =
- (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
- if (ethType == null) {
- log.warn("No ethType in versatile forwarding obj. Not processing further.");
- return flowrules;
- }
-
- // now deal with possible mix of ARP with filtering objectives
- // in multi-table scenarios
- if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) {
- if (filters.isEmpty()) {
- pendingVersatiles.add(fwd);
- return flowrules;
- }
- for (Filter filter : filters) {
- flowrules.addAll(processVersatilesWithFilters(filter, fwd));
- }
- }
- return flowrules;
- }
-
- private Collection<FlowRule> processVersatilesWithFilters(
- Filter filt, ForwardingObjective fwd) {
- Collection<FlowRule> flows = new ArrayList<FlowRule>();
-
- // rule for ARP replies
- log.debug("adding ARP rule in ACL table");
- TrafficSelector.Builder sel = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
- sel.matchInPort(filt.port());
- sel.matchVlanId(filt.vlanId());
- sel.matchEthDst(filt.mac());
- sel.matchEthType(Ethernet.TYPE_ARP);
- treat.setOutput(PortNumber.CONTROLLER);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(sel.build())
- .withTreatment(treat.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- flows.add(rule);
-
- // rule for ARP Broadcast
- sel = DefaultTrafficSelector.builder();
- treat = DefaultTrafficTreatment.builder();
- sel.matchInPort(filt.port());
- sel.matchVlanId(filt.vlanId());
- sel.matchEthDst(MacAddress.BROADCAST);
- sel.matchEthType(Ethernet.TYPE_ARP);
- treat.setOutput(PortNumber.CONTROLLER);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(sel.build())
- .withTreatment(treat.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- flows.add(rule);
-
- return flows;
- }
-
-
- 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;
- }
-
- private void processFilter(FilteringObjective filt, boolean install,
- ApplicationId applicationId) {
- // This driver only processes filtering criteria defined with switch
- // ports as the key
- PortCriterion p;
- if (!filt.key().equals(Criteria.dummy()) &&
- filt.key().type() == Criterion.Type.IN_PORT) {
- p = (PortCriterion) filt.key();
- } else {
- log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
- fail(filt, ObjectiveError.UNKNOWN);
- return;
- }
-
- EthCriterion e = null; VlanIdCriterion v = null;
- Collection<IPCriterion> ips = new ArrayList<IPCriterion>();
- // convert filtering conditions for switch-intfs into flowrules
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- for (Criterion c : filt.conditions()) {
- if (c.type() == Criterion.Type.ETH_DST) {
- e = (EthCriterion) c;
- } else if (c.type() == Criterion.Type.VLAN_VID) {
- v = (VlanIdCriterion) c;
- } else if (c.type() == Criterion.Type.IPV4_DST) {
- ips.add((IPCriterion) c);
- } else {
- log.error("Unsupported filter {}", c);
- fail(filt, ObjectiveError.UNSUPPORTED);
- return;
- }
- }
-
- // cache for later use
- Filter filter = new Filter(p, e, v, ips);
- filters.add(filter);
-
- // apply any pending versatile forwarding objectives
- for (ForwardingObjective fwd : pendingVersatiles) {
- Collection<FlowRule> ret = processVersatilesWithFilters(filter, fwd);
- for (FlowRule fr : ret) {
- ops.add(fr);
- }
- }
-
- for (IPCriterion ipaddr : ips) {
- log.debug("adding IP filtering rules in ACL table: {}", ipaddr.ip());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(p.port());
- selector.matchVlanId(v.vlanId());
- selector.matchEthDst(e.mac());
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ipaddr.ip()); // router IPs to the controller
- treatment.setOutput(PortNumber.CONTROLLER);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- ops = ops.add(rule);
- }
-
- // apply filtering flow rules
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(filt);
- log.info("Applied filtering rules");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
- log.info("Failed to apply filtering rules");
- }
- }));
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
- private void initializePipeline() {
- //processIpUnicastTable(true);
- processAclTable(true);
- }
-
- private void processAclTable(boolean install) {
- TrafficSelector.Builder selector;
- TrafficTreatment.Builder treatment;
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- FlowRule rule;
-
- //Drop rule
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
-
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
-
- ops = install ? ops.add(rule) : ops.remove(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned ACL table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision ACL table");
- }
- }));
- }
-
- private class Filter {
- private PortCriterion port;
- private VlanIdCriterion vlan;
- private EthCriterion eth;
-
- @SuppressWarnings("unused")
- private Collection<IPCriterion> ips;
-
- public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v,
- Collection<IPCriterion> ips) {
- this.eth = e;
- this.port = p;
- this.vlan = v;
- this.ips = ips;
- }
-
- public PortNumber port() {
- return port.port();
- }
-
- public VlanId vlanId() {
- return vlan.vlanId();
- }
-
- public MacAddress mac() {
- return eth.mac();
- }
- }
-
- private class PicaGroup implements NextGroup {
- TrafficTreatment nextActions;
-
- public PicaGroup(TrafficTreatment next) {
- this.nextActions = next;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(nextActions);
- }
- }
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
deleted file mode 100644
index bd49e688..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-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.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.PortCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-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.store.serializers.KryoNamespaces;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Simple 2-Table Pipeline for Software/NPU based routers. This pipeline
- * does not forward IP traffic to next-hop groups. Instead it forwards traffic
- * using OF FlowMod actions.
- */
-public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- protected static final int FILTER_TABLE = 0;
- protected static final int FIB_TABLE = 1;
-
- private static final int DROP_PRIORITY = 0;
- private static final int DEFAULT_PRIORITY = 0x8000;
- private static final int HIGHEST_PRIORITY = 0xffff;
-
- private ServiceDirectory serviceDirectory;
- protected FlowRuleService flowRuleService;
- private CoreService coreService;
- private FlowObjectiveStore flowObjectiveStore;
- protected DeviceId deviceId;
- protected ApplicationId appId;
- private ApplicationId driverId;
- private Collection<Filter> filters;
- private Collection<ForwardingObjective> pendingVersatiles;
-
- private KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(DummyGroup.class)
- .register(KryoNamespaces.API)
- .register(byte[].class)
- .build();
-
- private final Logger log = getLogger(getClass());
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- flowObjectiveStore = context.store();
- driverId = coreService.registerApplication(
- "org.onosproject.driver.SoftRouterPipeline");
- filters = Collections.newSetFromMap(new ConcurrentHashMap<Filter, Boolean>());
- pendingVersatiles = Collections.newSetFromMap(
- new ConcurrentHashMap<ForwardingObjective, Boolean>());
- initializePipeline();
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
- processFilter(filteringObjective,
- filteringObjective.op() == Objective.Operation.ADD,
- filteringObjective.appId());
- } else {
- fail(filteringObjective, ObjectiveError.UNSUPPORTED);
- }
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowOpsBuilder::add);
- break;
- case REMOVE:
- rules.stream()
- .filter(rule -> rule != null)
- .forEach(flowOpsBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
-
- flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
-
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() != 1) {
- log.error("Next Objectives of type Simple should only have a "
- + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id());
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
- }
- processSimpleNextObjective(nextObjective);
- break;
- case HASHED:
- case BROADCAST:
- case FAILOVER:
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
- }
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- private void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
-
- private void initializePipeline() {
- //Drop rules for both tables
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
-
- treatment.drop();
-
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(FILTER_TABLE)
- .build();
- ops = ops.add(rule);
-
- rule = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(FIB_TABLE)
- .build();
- ops = ops.add(rule);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Provisioned drop rules in both tables");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to provision drop rules");
- }
- }));
- }
-
- private void processFilter(FilteringObjective filt, boolean install,
- ApplicationId applicationId) {
- // This driver only processes filtering criteria defined with switch
- // ports as the key
- PortCriterion p; EthCriterion e = null; VlanIdCriterion v = null;
- Collection<IPCriterion> ips = new ArrayList<IPCriterion>();
- if (!filt.key().equals(Criteria.dummy()) &&
- filt.key().type() == Criterion.Type.IN_PORT) {
- p = (PortCriterion) filt.key();
- } else {
- log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
- fail(filt, ObjectiveError.UNKNOWN);
- return;
- }
-
- // convert filtering conditions for switch-intfs into flowrules
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- for (Criterion c : filt.conditions()) {
- if (c.type() == Criterion.Type.ETH_DST) {
- e = (EthCriterion) c;
- } else if (c.type() == Criterion.Type.VLAN_VID) {
- v = (VlanIdCriterion) c;
- } else if (c.type() == Criterion.Type.IPV4_DST) {
- ips.add((IPCriterion) c);
- } else {
- log.error("Unsupported filter {}", c);
- fail(filt, ObjectiveError.UNSUPPORTED);
- return;
- }
- }
-
- log.debug("adding Port/VLAN/MAC filtering rules in filter table: {}/{}/{}",
- p.port(), v.vlanId(), e.mac());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(p.port());
- selector.matchVlanId(v.vlanId());
- selector.matchEthDst(e.mac());
- selector.matchEthType(Ethernet.TYPE_IPV4);
- treatment.popVlan();
- treatment.transition(FIB_TABLE); // all other IPs to the FIB table
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
- ops = ops.add(rule);
-
- for (IPCriterion ipaddr : ips) {
- log.debug("adding IP filtering rules in FILTER table: {}", ipaddr.ip());
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(p.port());
- selector.matchVlanId(v.vlanId());
- selector.matchEthDst(e.mac());
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ipaddr.ip()); // router IPs to the controller
- treatment.setOutput(PortNumber.CONTROLLER);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(FILTER_TABLE).build();
- ops = ops.add(rule);
- }
-
- // cache for later use
- Filter filter = new Filter(p, e, v, ips);
- filters.add(filter);
- // apply any pending versatile forwarding objectives
- for (ForwardingObjective fwd : pendingVersatiles) {
- Collection<FlowRule> ret = processVersatilesWithFilters(filter, fwd);
- for (FlowRule fr : ret) {
- ops.add(fr);
- }
- }
-
- ops = install ? ops.add(rule) : ops.remove(rule);
- // apply filtering flow rules
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Applied filtering rules");
- pass(filt);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to apply filtering rules");
- fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- /**
- * SoftRouter has a single versatile table - the filter table. All versatile
- * flow rules must include the filtering rules.
- *
- * @param fwd The forwarding objective of type versatile
- * @return A collection of flow rules meant to be delivered to the flowrule
- * subsystem. May return empty collection in case of failures.
- */
- private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
- if (filters.isEmpty()) {
- pendingVersatiles.add(fwd);
- return Collections.emptySet();
- }
- Collection<FlowRule> flowrules = new ArrayList<FlowRule>();
- for (Filter filter : filters) {
- flowrules.addAll(processVersatilesWithFilters(filter, fwd));
- }
- return flowrules;
- }
-
- private Collection<FlowRule> processVersatilesWithFilters(
- Filter filt, ForwardingObjective fwd) {
- log.info("Processing versatile forwarding objective");
- Collection<FlowRule> flows = new ArrayList<FlowRule>();
- TrafficSelector match = fwd.selector();
- EthTypeCriterion ethType =
- (EthTypeCriterion) match.getCriterion(Criterion.Type.ETH_TYPE);
- if (ethType == null) {
- log.error("Versatile forwarding objective must include ethType");
- fail(fwd, ObjectiveError.UNKNOWN);
- return Collections.emptySet();
- }
-
- if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) {
- // need to install ARP request & reply flow rules for each interface filter
-
- // rule for ARP replies
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchInPort(filt.port());
- selector.matchVlanId(filt.vlanId());
- selector.matchEthDst(filt.mac());
- selector.matchEthType(Ethernet.TYPE_ARP);
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(fwd.treatment())
- .makePermanent()
- .forTable(FILTER_TABLE);
- flows.add(ruleBuilder.build());
-
- //rule for ARP requests
- selector = DefaultTrafficSelector.builder();
- selector.matchInPort(filt.port());
- selector.matchVlanId(filt.vlanId());
- selector.matchEthDst(MacAddress.BROADCAST);
- selector.matchEthType(Ethernet.TYPE_ARP);
- ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(fwd.treatment())
- .makePermanent()
- .forTable(FILTER_TABLE);
- flows.add(ruleBuilder.build());
-
- return flows;
- }
- // not handling other versatile flows
- return Collections.emptySet();
- }
-
- /**
- * SoftRouter has a single specific table - the FIB Table. It emulates
- * LPM matching of dstIP by using higher priority flows for longer prefixes.
- * Flows are forwarded using flow-actions
- *
- * @param fwd The forwarding objective of type simple
- * @return A collection of flow rules meant to be delivered to the flowrule
- * subsystem. Typically the returned collection has a single flowrule.
- * May return empty collection in case of failures.
- *
- */
- 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);
- // XXX currently supporting only the L3 unicast table
- if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) {
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
-
- TrafficSelector filteredSelector =
- DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(((IPCriterion)
- selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
- .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(FIB_TABLE);
- return Collections.singletonList(ruleBuilder.build());
- }
-
- /**
- * Next Objectives are stored as dummy groups for retrieval later
- * when Forwarding Objectives reference the next objective id. At that point
- * the dummy group is fetched from the distributed store and the enclosed
- * treatment is applied as a flow rule action.
- *
- * @param nextObj the next objective of type simple
- */
- private void processSimpleNextObjective(NextObjective nextObj) {
- // Simple next objective has a single treatment (not a collection)
- TrafficTreatment treatment = nextObj.next().iterator().next();
- flowObjectiveStore.putNextGroup(nextObj.id(),
- new DummyGroup(treatment));
- }
-
- private class Filter {
- private PortCriterion port;
- private VlanIdCriterion vlan;
- private EthCriterion eth;
-
- @SuppressWarnings("unused")
- private Collection<IPCriterion> ips;
-
- public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v,
- Collection<IPCriterion> ips) {
- this.eth = e;
- this.port = p;
- this.vlan = v;
- this.ips = ips;
- }
-
- public PortNumber port() {
- return port.port();
- }
-
- public VlanId vlanId() {
- return vlan.vlanId();
- }
-
- public MacAddress mac() {
- return eth.mac();
- }
- }
-
- private class DummyGroup implements NextGroup {
- TrafficTreatment nextActions;
-
- public DummyGroup(TrafficTreatment next) {
- this.nextActions = next;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(nextActions);
- }
-
- }
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
deleted file mode 100644
index dba4557a..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-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 org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-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.Criterion.Type;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.MplsCriterion;
-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.OutputInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
-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.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-/**
- * Driver for SPRING-OPEN pipeline.
- */
-public class SpringOpenTTP extends AbstractHandlerBehaviour
- implements Pipeliner {
-
- // Default table ID - compatible with CpqD switch
- private static final int TABLE_VLAN = 0;
- private static final int TABLE_TMAC = 1;
- private static final int TABLE_IPV4_UNICAST = 2;
- private static final int TABLE_MPLS = 3;
- private static final int TABLE_DMAC = 4;
- private static final int TABLE_ACL = 5;
- private static final int TABLE_SMAC = 6;
-
- /**
- * Set the default values. These variables will get overwritten based on the
- * switch vendor type
- */
- protected int vlanTableId = TABLE_VLAN;
- protected int tmacTableId = TABLE_TMAC;
- protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST;
- protected int mplsTableId = TABLE_MPLS;
- protected int dstMacTableId = TABLE_DMAC;
- protected int aclTableId = TABLE_ACL;
- protected int srcMacTableId = TABLE_SMAC;
-
- protected final Logger log = getLogger(getClass());
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private CoreService coreService;
- protected GroupService groupService;
- protected FlowObjectiveStore flowObjectiveStore;
- protected DeviceId deviceId;
- private ApplicationId appId;
-
- private Cache<GroupKey, NextObjective> pendingGroups;
-
- private ScheduledExecutorService groupChecker = Executors
- .newScheduledThreadPool(2,
- groupedThreads("onos/pipeliner",
- "spring-open-%d"));
- protected KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(GroupKey.class)
- .register(DefaultGroupKey.class)
- .register(TrafficTreatment.class)
- .register(SpringOpenGroup.class)
- .register(byte[].class)
- .build();
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
-
- pendingGroups = CacheBuilder
- .newBuilder()
- .expireAfterWrite(20, TimeUnit.SECONDS)
- .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
- if (notification.getCause() == RemovalCause.EXPIRED) {
- fail(notification.getValue(),
- ObjectiveError.GROUPINSTALLATIONFAILED);
- }
- }).build();
-
- groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500,
- TimeUnit.MILLISECONDS);
-
- coreService = serviceDirectory.get(CoreService.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- groupService = serviceDirectory.get(GroupService.class);
- flowObjectiveStore = context.store();
-
- groupService.addListener(new InnerGroupListener());
-
- appId = coreService
- .registerApplication("org.onosproject.driver.SpringOpenTTP");
-
- setTableMissEntries();
- log.info("Spring Open TTP driver initialized");
- }
-
- @Override
- public void filter(FilteringObjective filteringObjective) {
- if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
- log.debug("processing PERMIT filter objective");
- processFilter(filteringObjective,
- filteringObjective.op() == Objective.Operation.ADD,
- filteringObjective.appId());
- } else {
- log.debug("filter objective other than PERMIT not supported");
- fail(filteringObjective, ObjectiveError.UNSUPPORTED);
- }
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- rules = processForward(fwd);
- switch (fwd.op()) {
- case ADD:
- rules.stream().filter(rule -> rule != null)
- .forEach(flowBuilder::add);
- break;
- case REMOVE:
- rules.stream().filter(rule -> rule != null)
- .forEach(flowBuilder::remove);
- break;
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}", fwd.op());
- }
-
- flowRuleService.apply(flowBuilder
- .build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(fwd);
- log.debug("Provisioned tables in {} successfully with "
- + "forwarding rules", deviceId);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- log.warn("Failed to provision tables in {} with "
- + "forwarding rules", deviceId);
- }
- }));
-
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
- switch (nextObjective.op()) {
- case ADD:
- if (nextGroup != null) {
- log.warn("Cannot add next {} that already exists in device {}",
- nextObjective.id(), deviceId);
- return;
- }
- log.debug("Processing NextObjective id{} in dev{} - add group",
- nextObjective.id(), deviceId);
- addGroup(nextObjective);
- break;
- case ADD_TO_EXISTING:
- if (nextGroup != null) {
- log.debug("Processing NextObjective id{} in dev{} - add bucket",
- nextObjective.id(), deviceId);
- addBucketToGroup(nextObjective);
- } else {
- log.warn("Cannot add to group that does not exist");
- }
- break;
- case REMOVE:
- if (nextGroup == null) {
- log.warn("Cannot remove next {} that does not exist in device {}",
- nextObjective.id(), deviceId);
- return;
- }
- log.debug("Processing NextObjective id{} in dev{} - remove group",
- nextObjective.id(), deviceId);
- removeGroup(nextObjective);
- break;
- case REMOVE_FROM_EXISTING:
- if (nextGroup == null) {
- log.warn("Cannot remove from next {} that does not exist in device {}",
- nextObjective.id(), deviceId);
- return;
- }
- log.debug("Processing NextObjective id{} in dev{} - remove bucket",
- nextObjective.id(), deviceId);
- removeBucketFromGroup(nextObjective);
- break;
- default:
- log.warn("Unsupported operation {}", nextObjective.op());
- }
- }
-
- private void removeGroup(NextObjective nextObjective) {
- log.debug("removeGroup in {}: for next objective id {}",
- deviceId, nextObjective.id());
- final GroupKey key = new DefaultGroupKey(
- appKryo.serialize(nextObjective.id()));
- groupService.removeGroup(deviceId, key, appId);
- }
-
- private void addGroup(NextObjective nextObjective) {
- log.debug("addGroup with type{} for nextObjective id {}",
- nextObjective.type(), nextObjective.id());
- List<GroupBucket> buckets;
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() == 1) {
- // Spring Open TTP converts simple nextObjective to flow-actions
- // in a dummy group
- TrafficTreatment treatment = nextObjective.next().iterator().next();
- log.debug("Converting SIMPLE group for next objective id {} " +
- "to {} flow-actions in device:{}", nextObjective.id(),
- treatment.allInstructions().size(), deviceId);
- flowObjectiveStore.putNextGroup(nextObjective.id(),
- new SpringOpenGroup(null, treatment));
- }
- break;
- case HASHED:
- // we convert MPLS ECMP groups to flow-actions for a single
- // bucket(output port).
- boolean mplsEcmp = false;
- if (nextObjective.meta() != null) {
- for (Criterion c : nextObjective.meta().criteria()) {
- if (c.type() == Type.MPLS_LABEL) {
- mplsEcmp = true;
- }
- }
- }
- if (mplsEcmp) {
- // covert to flow-actions in a dummy group by choosing the first bucket
- log.debug("Converting HASHED group for next objective id {} " +
- "to flow-actions in device:{}", nextObjective.id(),
- deviceId);
- TrafficTreatment treatment = nextObjective.next().iterator().next();
- flowObjectiveStore.putNextGroup(nextObjective.id(),
- new SpringOpenGroup(null, treatment));
- } else {
- // process as ECMP group
- buckets = nextObjective
- .next()
- .stream()
- .map((treatment) -> DefaultGroupBucket
- .createSelectGroupBucket(treatment))
- .collect(Collectors.toList());
- if (!buckets.isEmpty()) {
- final GroupKey key = new DefaultGroupKey(
- appKryo.serialize(nextObjective.id()));
- GroupDescription groupDescription = new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.SELECT,
- new GroupBuckets(buckets),
- key,
- null,
- nextObjective.appId());
- log.debug("Creating HASHED group for next objective id {}"
- + " in dev:{}", nextObjective.id(), deviceId);
- pendingGroups.put(key, nextObjective);
- groupService.addGroup(groupDescription);
- }
- }
- break;
- case BROADCAST:
- buckets = nextObjective
- .next()
- .stream()
- .map((treatment) -> DefaultGroupBucket
- .createAllGroupBucket(treatment))
- .collect(Collectors.toList());
- if (!buckets.isEmpty()) {
- final GroupKey key = new DefaultGroupKey(
- appKryo.serialize(nextObjective
- .id()));
- GroupDescription groupDescription = new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.ALL,
- new GroupBuckets(buckets),
- key,
- null,
- nextObjective.appId());
- log.debug("Creating BROADCAST group for next objective id {} "
- + "in device {}", nextObjective.id(), deviceId);
- pendingGroups.put(key, nextObjective);
- groupService.addGroup(groupDescription);
- }
- break;
- case FAILOVER:
- log.debug("FAILOVER next objectives not supported");
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
- }
- }
-
- private void addBucketToGroup(NextObjective nextObjective) {
- log.debug("addBucketToGroup in {}: for next objective id {}",
- deviceId, nextObjective.id());
- Collection<TrafficTreatment> treatments = nextObjective.next();
- TrafficTreatment treatment = treatments.iterator().next();
- final GroupKey key = new DefaultGroupKey(
- appKryo.serialize(nextObjective
- .id()));
- Group group = groupService.getGroup(deviceId, key);
- if (group == null) {
- log.warn("Group is not found in {} for {}", deviceId, key);
- return;
- }
- GroupBucket bucket;
- if (group.type() == GroupDescription.Type.INDIRECT) {
- bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
- } else if (group.type() == GroupDescription.Type.SELECT) {
- bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
- } else if (group.type() == GroupDescription.Type.ALL) {
- bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
- } else {
- log.warn("Unsupported Group type {}", group.type());
- return;
- }
- GroupBuckets bucketsToAdd = new GroupBuckets(Collections.singletonList(bucket));
- log.debug("Adding buckets to group id {} of next objective id {} in device {}",
- group.id(), nextObjective.id(), deviceId);
- groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId);
- }
-
- private void removeBucketFromGroup(NextObjective nextObjective) {
- log.debug("removeBucketFromGroup in {}: for next objective id {}",
- deviceId, nextObjective.id());
- NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
- if (nextGroup != null) {
- Collection<TrafficTreatment> treatments = nextObjective.next();
- TrafficTreatment treatment = treatments.iterator().next();
- final GroupKey key = new DefaultGroupKey(
- appKryo.serialize(nextObjective
- .id()));
- Group group = groupService.getGroup(deviceId, key);
- if (group == null) {
- log.warn("Group is not found in {} for {}", deviceId, key);
- return;
- }
- GroupBucket bucket;
- if (group.type() == GroupDescription.Type.INDIRECT) {
- bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
- } else if (group.type() == GroupDescription.Type.SELECT) {
- bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
- } else if (group.type() == GroupDescription.Type.ALL) {
- bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
- } else {
- log.warn("Unsupported Group type {}", group.type());
- return;
- }
- GroupBuckets removeBuckets = new GroupBuckets(Collections.singletonList(bucket));
- log.debug("Removing buckets from group id {} of next objective id {} in device {}",
- group.id(), nextObjective.id(), deviceId);
- groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId);
- }
- }
-
- private Collection<FlowRule> processForward(ForwardingObjective fwd) {
- switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
- }
- return Collections.emptySet();
- }
-
- 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.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());
- }
-
- private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType = (EthTypeCriterion) selector
- .getCriterion(Criterion.Type.ETH_TYPE);
- if ((ethType == null) ||
- ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
- (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) {
- return false;
- }
- return true;
- }
-
- private boolean isSupportedEthDstObjective(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthCriterion ethDst = (EthCriterion) selector
- .getCriterion(Criterion.Type.ETH_DST);
- VlanIdCriterion vlanId = (VlanIdCriterion) selector
- .getCriterion(Criterion.Type.VLAN_VID);
- if (ethDst == null && vlanId == null) {
- return false;
- }
- return true;
- }
-
- protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
- log.debug("Processing specific fwd objective:{} in dev:{} with next:{}",
- fwd.id(), deviceId, fwd.nextId());
- boolean isEthTypeObj = isSupportedEthTypeObjective(fwd);
- boolean isEthDstObj = isSupportedEthDstObjective(fwd);
-
- if (isEthTypeObj) {
- return processEthTypeSpecificObjective(fwd);
- } else if (isEthDstObj) {
- return processEthDstSpecificObjective(fwd);
- } else {
- log.warn("processSpecific: Unsupported "
- + "forwarding objective criteria");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
- }
-
- protected Collection<FlowRule>
- processEthTypeSpecificObjective(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType = (EthTypeCriterion) selector
- .getCriterion(Criterion.Type.ETH_TYPE);
-
- TrafficSelector.Builder filteredSelectorBuilder =
- DefaultTrafficSelector.builder();
- int forTableId = -1;
- if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
- filteredSelectorBuilder = filteredSelectorBuilder
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(((IPCriterion) selector
- .getCriterion(Criterion.Type.IPV4_DST))
- .ip());
- forTableId = ipv4UnicastTableId;
- log.debug("processing IPv4 specific forwarding objective:{} in dev:{}",
- fwd.id(), deviceId);
- } else {
- filteredSelectorBuilder = filteredSelectorBuilder
- .matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(((MplsCriterion)
- selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
- //TODO: Add Match for BoS
- //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) {
- //}
- forTableId = mplsTableId;
- log.debug("processing MPLS specific forwarding objective:{} in dev:{}",
- fwd.id(), deviceId);
- }
-
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment
- .builder();
- if (fwd.treatment() != null) {
- for (Instruction i : fwd.treatment().allInstructions()) {
- treatmentBuilder.add(i);
- }
- }
-
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- if (next != null) {
- SpringOpenGroup soGroup = appKryo.deserialize(next.data());
- if (soGroup.dummy) {
- log.debug("Adding {} flow-actions for fwd. obj. {} -> next:{} "
- + "in dev: {}", soGroup.treatment.allInstructions().size(),
- fwd.id(), fwd.nextId(), deviceId);
- 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 to group:{} for fwd. obj. {} "
- + "for next:{} in dev: {}", group.id(), fwd.id(),
- fwd.nextId(), deviceId);
- }
- } else {
- log.warn("processSpecific: No associated next objective object");
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- }
-
- TrafficSelector filteredSelector = filteredSelectorBuilder.build();
- TrafficTreatment treatment = treatmentBuilder.transition(aclTableId)
- .build();
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId()).withPriority(fwd.priority())
- .forDevice(deviceId).withSelector(filteredSelector)
- .withTreatment(treatment);
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- ruleBuilder.forTable(forTableId);
- return Collections.singletonList(ruleBuilder.build());
-
- }
-
- protected Collection<FlowRule>
- processEthDstSpecificObjective(ForwardingObjective fwd) {
- List<FlowRule> rules = new ArrayList<>();
-
- // Build filtered selector
- TrafficSelector selector = fwd.selector();
- EthCriterion ethCriterion = (EthCriterion) selector
- .getCriterion(Criterion.Type.ETH_DST);
- VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector
- .getCriterion(Criterion.Type.VLAN_VID);
- TrafficSelector.Builder filteredSelectorBuilder =
- DefaultTrafficSelector.builder();
- // Do not match MacAddress for subnet broadcast entry
- if (!ethCriterion.mac().equals(MacAddress.NONE)) {
- filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
- log.debug("processing L2 forwarding objective:{} in dev:{}",
- fwd.id(), deviceId);
- } else {
- log.debug("processing L2 Broadcast forwarding objective:{} "
- + "in dev:{} for vlan:{}",
- fwd.id(), deviceId, vlanIdCriterion.vlanId());
- }
- filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
- TrafficSelector filteredSelector = filteredSelectorBuilder.build();
-
- // Build filtered treatment
- TrafficTreatment.Builder treatmentBuilder =
- DefaultTrafficTreatment.builder();
- if (fwd.treatment() != null) {
- treatmentBuilder.deferred();
- fwd.treatment().allInstructions().forEach(treatmentBuilder::add);
- }
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
- if (next != null) {
- SpringOpenGroup soGrp = appKryo.deserialize(next.data());
- if (soGrp.dummy) {
- log.debug("Adding {} flow-actions for fwd. obj. {} "
- + "in dev: {}", soGrp.treatment.allInstructions().size(),
- fwd.id(), deviceId);
- for (Instruction ins : soGrp.treatment.allInstructions()) {
- treatmentBuilder.deferred().add(ins);
- }
- } else {
- GroupKey key = soGrp.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 to group:{} for fwd. obj. {} "
- + "in dev: {}", group.id(), fwd.id(), deviceId);
- }
- }
- }
- treatmentBuilder.immediate().transition(aclTableId);
- TrafficTreatment filteredTreatment = treatmentBuilder.build();
-
- // Build bridging table entries
- FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
- flowRuleBuilder.fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(filteredSelector)
- .withTreatment(filteredTreatment)
- .forTable(dstMacTableId);
- if (fwd.permanent()) {
- flowRuleBuilder.makePermanent();
- } else {
- flowRuleBuilder.makeTemporary(fwd.timeout());
- }
- rules.add(flowRuleBuilder.build());
-
- /*
- // TODO Emulate source MAC table behavior
- // Do not install source MAC table entry for subnet broadcast
- if (!ethCriterion.mac().equals(MacAddress.NONE)) {
- // Build filtered selector
- selector = fwd.selector();
- ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST);
- filteredSelectorBuilder = DefaultTrafficSelector.builder();
- filteredSelectorBuilder.matchEthSrc(ethCriterion.mac());
- filteredSelector = filteredSelectorBuilder.build();
-
- // Build empty treatment. Apply existing instruction if match.
- treatmentBuilder = DefaultTrafficTreatment.builder();
- filteredTreatment = treatmentBuilder.build();
-
- // Build bridging table entries
- flowRuleBuilder = DefaultFlowRule.builder();
- flowRuleBuilder.fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(filteredSelector)
- .withTreatment(filteredTreatment)
- .forTable(srcMacTableId)
- .makePermanent();
- rules.add(flowRuleBuilder.build());
- }
- */
-
- return rules;
- }
-
- /*
- * Note: CpqD switches do not handle MPLS-related operation properly
- * for a packet with VLAN tag. We pop VLAN here as a workaround.
- * Side effect: HostService learns redundant hosts with same MAC but
- * different VLAN. No known side effect on the network reachability.
- */
- protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
- VlanIdCriterion vlanIdCriterion,
- FilteringObjective filt,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- //handling untagged packets via assigned VLAN
- if (vlanIdCriterion.vlanId() == VlanId.NONE) {
- vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
- }
-
- List<FlowRule> rules = new ArrayList<>();
- TrafficSelector.Builder selectorIp = DefaultTrafficSelector
- .builder();
- TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment
- .builder();
- selectorIp.matchEthDst(ethCriterion.mac());
- selectorIp.matchEthType(Ethernet.TYPE_IPV4);
- selectorIp.matchVlanId(vlanIdCriterion.vlanId());
- treatmentIp.popVlan();
- treatmentIp.transition(ipv4UnicastTableId);
- FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selectorIp.build())
- .withTreatment(treatmentIp.build())
- .withPriority(filt.priority()).fromApp(applicationId)
- .makePermanent().forTable(tmacTableId).build();
- log.debug("adding IP ETH rule for MAC: {}", ethCriterion.mac());
- rules.add(ruleIp);
-
- TrafficSelector.Builder selectorMpls = DefaultTrafficSelector
- .builder();
- TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment
- .builder();
- selectorMpls.matchEthDst(ethCriterion.mac());
- selectorMpls.matchEthType(Ethernet.MPLS_UNICAST);
- selectorMpls.matchVlanId(vlanIdCriterion.vlanId());
- treatmentMpls.popVlan();
- treatmentMpls.transition(mplsTableId);
- FlowRule ruleMpls = DefaultFlowRule.builder()
- .forDevice(deviceId).withSelector(selectorMpls.build())
- .withTreatment(treatmentMpls.build())
- .withPriority(filt.priority()).fromApp(applicationId)
- .makePermanent().forTable(tmacTableId).build();
- log.debug("adding MPLS ETH rule for MAC: {}", ethCriterion.mac());
- rules.add(ruleMpls);
-
- return rules;
- }
-
- protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
- FilteringObjective filt,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- List<FlowRule> rules = new ArrayList<>();
- log.debug("adding rule for VLAN: {}", vlanIdCriterion.vlanId());
- TrafficSelector.Builder selector = DefaultTrafficSelector
- .builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- PortCriterion p = (PortCriterion) filt.key();
- if (vlanIdCriterion.vlanId() != VlanId.NONE) {
- selector.matchVlanId(vlanIdCriterion.vlanId());
- selector.matchInPort(p.port());
- treatment.deferred().popVlan();
- } else {
- selector.matchInPort(p.port());
- treatment.immediate().pushVlan().setVlanId(assignedVlan);
- }
- treatment.transition(tmacTableId);
- FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(filt.priority()).fromApp(applicationId)
- .makePermanent().forTable(vlanTableId).build();
- rules.add(rule);
-
- return rules;
- }
-
- private void processFilter(FilteringObjective filt, boolean install,
- ApplicationId applicationId) {
- // This driver only processes filtering criteria defined with switch
- // ports as the key
- if (filt.key().equals(Criteria.dummy())
- || filt.key().type() != Criterion.Type.IN_PORT) {
- log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
- fail(filt, ObjectiveError.UNKNOWN);
- return;
- }
-
- EthCriterion ethCriterion = null;
- VlanIdCriterion vlanIdCriterion = null;
-
- // convert filtering conditions for switch-intfs into flowrules
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
-
- for (Criterion criterion : filt.conditions()) {
- if (criterion.type() == Criterion.Type.ETH_DST) {
- ethCriterion = (EthCriterion) criterion;
- } else if (criterion.type() == Criterion.Type.VLAN_VID) {
- vlanIdCriterion = (VlanIdCriterion) criterion;
- } else if (criterion.type() == Criterion.Type.IPV4_DST) {
- log.debug("driver does not process IP filtering rules as it " +
- "sends all misses in the IP table to the controller");
- } else {
- log.warn("Driver does not currently process filtering condition"
- + " of type: {}", criterion.type());
- fail(filt, ObjectiveError.UNSUPPORTED);
- }
- }
-
- VlanId assignedVlan = null;
- if (vlanIdCriterion != null && vlanIdCriterion.vlanId() == VlanId.NONE) {
- // Assign a VLAN ID to untagged packets
- if (filt.meta() == null) {
- log.error("Missing metadata in filtering objective required "
- + "for vlan assignment in dev {}", deviceId);
- fail(filt, ObjectiveError.BADPARAMS);
- return;
- }
- for (Instruction i : filt.meta().allInstructions()) {
- if (i instanceof ModVlanIdInstruction) {
- assignedVlan = ((ModVlanIdInstruction) i).vlanId();
- }
- }
- if (assignedVlan == null) {
- log.error("Driver requires an assigned vlan-id to tag incoming "
- + "untagged packets. Not processing vlan filters on "
- + "device {}", deviceId);
- fail(filt, ObjectiveError.BADPARAMS);
- return;
- }
- }
-
- if (ethCriterion == null) {
- log.debug("filtering objective missing dstMac, cannot program TMAC table");
- } else {
- for (FlowRule tmacRule : processEthDstFilter(ethCriterion,
- vlanIdCriterion,
- filt,
- assignedVlan,
- applicationId)) {
- log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}",
- tmacRule, deviceId);
- ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
- }
- }
-
- if (ethCriterion == null || vlanIdCriterion == null) {
- log.debug("filtering objective missing dstMac or vlan, cannot program"
- + "Vlan Table");
- } else {
- for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion,
- filt,
- assignedVlan,
- applicationId)) {
- log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
- vlanRule, deviceId);
- ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
- }
- }
-
- // apply filtering flow rules
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(filt);
- log.debug("Provisioned tables in {} with fitering "
- + "rules", deviceId);
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
- log.warn("Failed to provision tables in {} with "
- + "fitering rules", deviceId);
- }
- }));
- }
-
- protected void setTableMissEntries() {
- // set all table-miss-entries
- populateTableMissEntry(vlanTableId, true, false, false, -1);
- populateTableMissEntry(tmacTableId, false, false, true, dstMacTableId);
- populateTableMissEntry(ipv4UnicastTableId, false, true, true, aclTableId);
- populateTableMissEntry(mplsTableId, false, true, true, aclTableId);
- populateTableMissEntry(dstMacTableId, false, false, true, aclTableId);
- populateTableMissEntry(aclTableId, false, false, false, -1);
- }
-
- protected void populateTableMissEntry(int tableToAdd,
- boolean toControllerNow,
- boolean toControllerWrite,
- boolean toTable, int tableToSend) {
- TrafficSelector selector = DefaultTrafficSelector.builder().build();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- if (toControllerNow) {
- tBuilder.setOutput(PortNumber.CONTROLLER);
- }
-
- if (toControllerWrite) {
- tBuilder.deferred().setOutput(PortNumber.CONTROLLER);
- }
-
- if (toTable) {
- tBuilder.transition(tableToSend);
- }
-
- FlowRule flow = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector).withTreatment(tBuilder.build())
- .withPriority(0).fromApp(appId).makePermanent()
- .forTable(tableToAdd).build();
-
- flowRuleService.applyFlowRules(flow);
- }
-
- private void pass(Objective obj) {
- if (obj.context().isPresent()) {
- obj.context().get().onSuccess(obj);
- }
- }
-
- protected void fail(Objective obj, ObjectiveError error) {
- if (obj.context().isPresent()) {
- obj.context().get().onError(obj, error);
- }
- }
-
- private class InnerGroupListener implements GroupListener {
- @Override
- public void event(GroupEvent event) {
- if (event.type() == GroupEvent.Type.GROUP_ADDED) {
- log.trace("InnerGroupListener: Group ADDED "
- + "event received in device {}", deviceId);
- GroupKey key = event.subject().appCookie();
-
- NextObjective obj = pendingGroups.getIfPresent(key);
- if (obj != null) {
- log.debug("Group verified: dev:{} gid:{} <<->> nextId:{}",
- deviceId, event.subject().id(), obj.id());
- flowObjectiveStore
- .putNextGroup(obj.id(),
- new SpringOpenGroup(key, null));
- pass(obj);
- pendingGroups.invalidate(key);
- }
- } else if (event.type() == GroupEvent.Type.GROUP_ADD_FAILED) {
- log.warn("InnerGroupListener: Group ADD "
- + "failed event received in device {}", deviceId);
- }
- }
- }
-
- private class GroupChecker implements Runnable {
-
- @Override
- public void run() {
- Set<GroupKey> keys = pendingGroups
- .asMap()
- .keySet()
- .stream()
- .filter(key -> groupService.getGroup(deviceId, key) != null)
- .collect(Collectors.toSet());
-
- keys.stream()
- .forEach(key -> {
- NextObjective obj = pendingGroups
- .getIfPresent(key);
- if (obj == null) {
- return;
- }
- log.debug("Group verified: dev:{} gid:{} <<->> nextId:{}",
- deviceId,
- groupService.getGroup(deviceId, key).id(),
- obj.id());
- pass(obj);
- pendingGroups.invalidate(key);
- flowObjectiveStore.putNextGroup(
- obj.id(),
- new SpringOpenGroup(key, null));
- });
- }
- }
-
- /**
- * SpringOpenGroup can either serve as storage for a GroupKey which can be
- * used to fetch the group from the Group Service, or it can be serve as storage
- * for Traffic Treatments which can be used as flow actions. In the latter
- * case, we refer to this as a dummy group.
- *
- */
- private class SpringOpenGroup implements NextGroup {
- private final boolean dummy;
- private final GroupKey key;
- private final TrafficTreatment treatment;
-
- /**
- * Storage for a GroupKey or a TrafficTreatment. One of the params
- * to this constructor must be null.
- * @param key represents a GroupKey
- * @param treatment represents flow actions in a dummy group
- */
- public SpringOpenGroup(GroupKey key, TrafficTreatment treatment) {
- if (key == null) {
- this.key = new DefaultGroupKey(new byte[]{0});
- this.treatment = treatment;
- this.dummy = true;
- } else {
- this.key = key;
- this.treatment = DefaultTrafficTreatment.builder().build();
- this.dummy = false;
- }
- }
-
- @SuppressWarnings("unused")
- public GroupKey key() {
- return key;
- }
-
- @Override
- public byte[] data() {
- return appKryo.serialize(this);
- }
-
- }
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
deleted file mode 100644
index 91f2679c..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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 java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.behaviour.NextGroup;
-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.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.MplsCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupKey;
-
-/**
- * Spring-open driver implementation for Dell hardware switches.
- */
-public class SpringOpenTTPDell extends SpringOpenTTP {
-
- /* Table IDs to be used for Dell Open Segment Routers*/
- private static final int DELL_TABLE_VLAN = 17;
- private static final int DELL_TABLE_TMAC = 18;
- private static final int DELL_TABLE_IPV4_UNICAST = 30;
- private static final int DELL_TABLE_MPLS = 25;
- private static final int DELL_TABLE_ACL = 40;
-
- //TODO: Store this info in the distributed store.
- private MacAddress deviceTMac = null;
-
- public SpringOpenTTPDell() {
- super();
- vlanTableId = DELL_TABLE_VLAN;
- tmacTableId = DELL_TABLE_TMAC;
- ipv4UnicastTableId = DELL_TABLE_IPV4_UNICAST;
- mplsTableId = DELL_TABLE_MPLS;
- aclTableId = DELL_TABLE_ACL;
- }
-
- @Override
- protected void setTableMissEntries() {
- // No need to set table-miss-entries in Dell switches
- return;
- }
-
- @Override
- //Dell switches need ETH_DST based match condition in all IP table entries.
- //So this method overrides the default spring-open behavior and adds
- //ETH_DST match condition while pushing IP table flow rules
- protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
- log.debug("Processing specific");
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType = (EthTypeCriterion) selector
- .getCriterion(Criterion.Type.ETH_TYPE);
- if ((ethType == null) ||
- (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
- (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
- log.debug("processSpecific: Unsupported "
- + "forwarding objective criteraia");
- fail(fwd, ObjectiveError.UNSUPPORTED);
- return Collections.emptySet();
- }
-
- TrafficSelector.Builder filteredSelectorBuilder =
- DefaultTrafficSelector.builder();
- int forTableId = -1;
- if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
- if (deviceTMac == null) {
- log.debug("processSpecific: ETH_DST filtering "
- + "objective is not set which is required "
- + "before sending a IPv4 forwarding objective");
- //TODO: Map the error to more appropriate error code.
- fail(fwd, ObjectiveError.DEVICEMISSING);
- return Collections.emptySet();
- }
- filteredSelectorBuilder = filteredSelectorBuilder
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchEthDst(deviceTMac)
- .matchIPDst(((IPCriterion) selector
- .getCriterion(Criterion.Type.IPV4_DST))
- .ip());
- forTableId = ipv4UnicastTableId;
- log.debug("processing IPv4 specific forwarding objective");
- } else {
- filteredSelectorBuilder = filteredSelectorBuilder
- .matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(((MplsCriterion)
- selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
- //TODO: Add Match for BoS
- //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) {
- //}
- forTableId = mplsTableId;
- log.debug("processing MPLS specific forwarding objective");
- }
-
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment
- .builder();
- if (fwd.treatment() != null) {
- for (Instruction i : fwd.treatment().allInstructions()) {
- treatmentBuilder.add(i);
- }
- }
-
- if (fwd.nextId() != null) {
- NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
-
- if (next != null) {
- GroupKey key = appKryo.deserialize(next.data());
-
- Group group = groupService.getGroup(deviceId, key);
-
- if (group == null) {
- log.warn("The group left!");
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- treatmentBuilder.group(group.id());
- log.debug("Adding OUTGROUP action");
- } else {
- log.warn("processSpecific: No associated next objective object");
- fail(fwd, ObjectiveError.GROUPMISSING);
- return Collections.emptySet();
- }
- }
-
- TrafficSelector filteredSelector = filteredSelectorBuilder.build();
- TrafficTreatment treatment = treatmentBuilder.transition(aclTableId)
- .build();
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId()).withPriority(fwd.priority())
- .forDevice(deviceId).withSelector(filteredSelector)
- .withTreatment(treatment);
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- ruleBuilder.forTable(forTableId);
- return Collections.singletonList(ruleBuilder.build());
-
- }
-
- @Override
- //Dell switches need ETH_DST based match condition in all IP table entries.
- //So while processing the ETH_DST based filtering objective, store
- //the device MAC to be used locally to use it while pushing the IP rules.
- protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
- VlanIdCriterion vlanIdCriterion,
- FilteringObjective filt,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- // Store device termination Mac to be used in IP flow entries
- deviceTMac = ethCriterion.mac();
-
- log.debug("For now not adding any TMAC rules "
- + "into Dell switches as it is ignoring");
-
- return Collections.emptyList();
- }
-
- @Override
- protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
- FilteringObjective filt,
- VlanId assignedVlan,
- ApplicationId applicationId) {
- log.debug("For now not adding any VLAN rules "
- + "into Dell switches as it is ignoring");
-
- return Collections.emptyList();
- }
-} \ No newline at end of file
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java
deleted file mode 100644
index 880acf5d..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * 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.
- */
-
-/**
- * Implementations of the pipeline driver behaviours.
- */
-package org.onosproject.driver.pipeline; \ No newline at end of file