/* * 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.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.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 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 processEthDstFilter(Criterion c, FilteringObjective filt, ApplicationId applicationId) { // Store device termination Mac to be used in IP flow entries EthCriterion e = (EthCriterion) c; deviceTMac = e.mac(); log.debug("For now not adding any TMAC rules " + "into Dell switches as it is ignoring"); return Collections.emptyList(); } @Override protected List processVlanIdFilter(Criterion c, FilteringObjective filt, ApplicationId applicationId) { log.debug("For now not adding any VLAN rules " + "into Dell switches as it is ignoring"); return Collections.emptyList(); } }