| /* |
| * Copyright 2014-2016 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.drivers.corsa; |
| |
| import org.onlab.packet.Ethernet; |
| import org.onlab.packet.IPv4; |
| import org.onlab.packet.MacAddress; |
| import org.onlab.packet.VlanId; |
| 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.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.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.ForwardingObjective; |
| import org.onosproject.net.flowobjective.ObjectiveError; |
| import org.slf4j.Logger; |
| |
| import java.util.Collection; |
| import java.util.Collections; |
| |
| import static org.slf4j.LoggerFactory.getLogger; |
| |
| /** |
| * OpenvSwitch emulation of the Corsa pipeline handler. |
| */ |
| public class OvsCorsaPipeline extends AbstractCorsaPipeline { |
| |
| private final Logger log = getLogger(getClass()); |
| |
| 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; |
| |
| @Override |
| protected Collection<FlowRule> processArpTraffic(ForwardingObjective fwd, FlowRule.Builder rule) { |
| log.warn("Driver automatically handles ARP packets by punting to controller " |
| + " from ETHER table"); |
| pass(fwd); |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| protected Collection<FlowRule> processLinkDiscovery(ForwardingObjective fwd, FlowRule.Builder rule) { |
| log.warn("Driver currently does not currently handle LLDP packets"); |
| fail(fwd, ObjectiveError.UNSUPPORTED); |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| protected Collection<FlowRule> processIpTraffic(ForwardingObjective fwd, FlowRule.Builder rule) { |
| IPCriterion ipSrc = (IPCriterion) fwd.selector() |
| .getCriterion(Criterion.Type.IPV4_SRC); |
| if (ipSrc != null) { |
| log.warn("Driver does not currently handle matching Src IP"); |
| fail(fwd, ObjectiveError.UNSUPPORTED); |
| return Collections.emptySet(); |
| } |
| IPCriterion ipDst = (IPCriterion) fwd.selector() |
| .getCriterion(Criterion.Type.IPV4_DST); |
| if (ipDst != null) { |
| log.error("Driver handles Dst IP matching as specific forwarding " |
| + "objective, not versatile"); |
| fail(fwd, ObjectiveError.UNSUPPORTED); |
| return Collections.emptySet(); |
| } |
| IPProtocolCriterion ipProto = (IPProtocolCriterion) fwd.selector() |
| .getCriterion(Criterion.Type.IP_PROTO); |
| 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(); |
| } |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| protected FlowRule.Builder processSpecificRoutingRule(FlowRule.Builder rb) { |
| return rb.forTable(FIB_TABLE); |
| } |
| |
| @Override |
| protected FlowRule.Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) { |
| 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); |
| return DefaultFlowRule.builder() |
| .withSelector(selector.build()) |
| .withTreatment(treatment.build()) |
| .withPriority(HIGHEST_PRIORITY) |
| .makePermanent() |
| .forTable(FIB_TABLE); |
| } |
| |
| @Override |
| protected FlowRule.Builder processVlanFiler(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) { |
| log.debug("adding rule for VLAN: {}", vlan.vlanId()); |
| TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); |
| selector.matchVlanId(vlan.vlanId()); |
| selector.matchInPort(port.port()); |
| treatment.transition(ETHER_TABLE); |
| treatment.deferred().popVlan(); |
| return DefaultFlowRule.builder() |
| .forDevice(deviceId) |
| .withSelector(selector.build()) |
| .withTreatment(treatment.build()) |
| .withPriority(CONTROLLER_PRIORITY) |
| .makePermanent() |
| .forTable(VLAN_TABLE); |
| } |
| |
| |
| protected FlowRule.Builder processEthFiler(FilteringObjective filt, EthCriterion eth, PortCriterion port) { |
| log.debug("adding rule for MAC: {}", eth.mac()); |
| TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); |
| selector.matchEthDst(eth.mac()); |
| treatment.transition(VLAN_MPLS_TABLE); |
| return DefaultFlowRule.builder() |
| .forDevice(deviceId) |
| .withSelector(selector.build()) |
| .withTreatment(treatment.build()) |
| .withPriority(CONTROLLER_PRIORITY) |
| .makePermanent() |
| .forTable(MAC_TABLE); |
| } |
| |
| @Override |
| protected 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(); |
| processFlowRule(true, rule, "Provisioned mac table transition"); |
| |
| //Drop rule |
| processTableMissDrop(true, MAC_TABLE, "Provisioned mac table drop action"); |
| |
| } |
| |
| 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(); |
| |
| processFlowRule(true, rule, "Provisioned vlan/mpls table"); |
| } |
| |
| private void processVlanTable(boolean install) { |
| processTableMissDrop(true, VLAN_TABLE, "Provisioned vlan table"); |
| } |
| |
| private void processEtherTable(boolean install) { |
| TrafficSelector.Builder selector = DefaultTrafficSelector.builder() |
| .matchEthType(Ethernet.TYPE_ARP); |
| TrafficTreatment.Builder treatment = DefaultTrafficTreatment |
| .builder() |
| .punt(); |
| |
| FlowRule rule = DefaultFlowRule.builder() |
| .forDevice(deviceId) |
| .withSelector(selector.build()) |
| .withTreatment(treatment.build()) |
| .withPriority(CONTROLLER_PRIORITY) |
| .fromApp(appId) |
| .makePermanent() |
| .forTable(ETHER_TABLE).build(); |
| |
| processFlowRule(true, rule, "Provisioned ether table"); |
| selector = DefaultTrafficSelector.builder() |
| .matchEthType(Ethernet.TYPE_IPV4); |
| treatment = DefaultTrafficTreatment.builder() |
| .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(); |
| processFlowRule(true, rule, "Provisioned ether table"); |
| |
| //Drop rule |
| processTableMissDrop(true, VLAN_TABLE, "Provisioned ether table"); |
| |
| } |
| |
| private void processCosTable(boolean install) { |
| TrafficTreatment.Builder treatment = DefaultTrafficTreatment |
| .builder() |
| .transition(FIB_TABLE); |
| TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| |
| FlowRule rule = DefaultFlowRule.builder() |
| .forDevice(deviceId) |
| .withSelector(selector.build()) |
| .withTreatment(treatment.build()) |
| .withPriority(DROP_PRIORITY) |
| .fromApp(appId) |
| .makePermanent() |
| .forTable(COS_MAP_TABLE).build(); |
| processFlowRule(true, rule, "Provisioned cos table"); |
| |
| } |
| |
| private void processFibTable(boolean install) { |
| processTableMissDrop(true, FIB_TABLE, "Provisioned FIB table"); |
| } |
| |
| private void processLocalTable(boolean install) { |
| TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| |
| TrafficTreatment.Builder treatment = DefaultTrafficTreatment |
| .builder() |
| .punt(); |
| |
| FlowRule rule = DefaultFlowRule.builder() |
| .forDevice(deviceId) |
| .withSelector(selector.build()) |
| .withTreatment(treatment.build()) |
| .withPriority(CONTROLLER_PRIORITY) |
| .fromApp(appId) |
| .makePermanent() |
| .forTable(LOCAL_TABLE).build(); |
| |
| processFlowRule(true, rule, "Provisioned Local table"); |
| } |
| |
| |
| } |