/* * Copyright 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.oplink; import org.onlab.util.Frequency; import org.onosproject.core.CoreService; import org.onosproject.driver.extensions.OplinkAttenuation; import org.onosproject.net.ChannelSpacing; import org.onosproject.net.GridType; import org.onosproject.net.Lambda; import org.onosproject.net.OchSignalType; import org.onosproject.net.PortNumber; import org.onosproject.net.driver.HandlerBehaviour; import org.onosproject.net.flow.DefaultFlowRule; import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.FlowEntry; import org.onosproject.net.flow.FlowRule; 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.OchSignalCriterion; import org.onosproject.net.flow.criteria.PortCriterion; import org.onosproject.net.flow.instructions.Instruction; import org.onosproject.net.flow.instructions.Instructions; import java.util.List; import java.util.Set; /** * Oplink optical utilities. */ public final class OplinkOpticalUtility { // Lambda information supported by device. public static final GridType GRID_TYPE = GridType.DWDM; public static final int SLOT_GRANULARITY = 4; // Channel spacing is 50GHz, 12.5GHz * 4 public static final ChannelSpacing CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ; // Start frequency supported by device. public static final Frequency START_CENTER_FREQ = Frequency.ofGHz(191_350); // Stop frequency supported by device. public static final Frequency STOP_CENTER_FREQ = Frequency.ofGHz(196_100); // Power multiply factor, the power accuracy supported by device is 0.01dBm. // Transforms the double typed number to long typed power for ONOS. public static final int POWER_MULTIPLIER = 100; // Attenuation range supported by device, [0, 25dB]. public static final long MIN_ATTENUATION = 0L; public static final long MAX_ATTENUATION = 2500L; // Default attenuation value if the attenuation instruction is not found. private static final int DEFAULT_ATT = 0; // Default flow priority for an extra flow. private static final int DEFAULT_PRIORITY = 88; // Default application name. private static final String DEFAULT_APP = "org.onosproject.drivers.oplink"; private OplinkOpticalUtility() { } /** * Transforms a flow FlowRule object to an OplinkCrossConnect object. * @param behaviour the parent driver handler * @param rule FlowRule object * @return cross connect object */ public static OplinkCrossConnect fromFlowRule(HandlerBehaviour behaviour, FlowRule rule) { // TrafficSelector Set<Criterion> criterions = rule.selector().criteria(); int channel = criterions.stream() .filter(c -> c instanceof OchSignalCriterion) .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier()) .findAny() .orElse(null); PortNumber inPort = criterions.stream() .filter(c -> c instanceof PortCriterion) .map(c -> ((PortCriterion) c).port()) .findAny() .orElse(null); // TrafficTreatment List<Instruction> instructions = rule.treatment().immediate(); PortNumber outPort = instructions.stream() .filter(c -> c instanceof Instructions.OutputInstruction) .map(c -> ((Instructions.OutputInstruction) c).port()) .findAny() .orElse(null); int attenuation = instructions.stream() .filter(c -> c instanceof Instructions.ExtensionInstructionWrapper) .map(c -> ((Instructions.ExtensionInstructionWrapper) c).extensionInstruction()) .filter(c -> c instanceof OplinkAttenuation) .map(c -> ((OplinkAttenuation) c).getAttenuation()) .findAny() .orElse(DEFAULT_ATT); return new OplinkCrossConnect(inPort, outPort, channel, attenuation); } /** * Finds the FlowRule from flow rule store by the given cross connect information. * Returns an extra flow to remove the flow by ONOS if not found. * @param behaviour the parent driver handler * @param cfg cross connect information * @return the flow rule */ public static FlowRule toFlowRule(HandlerBehaviour behaviour, OplinkCrossConnect cfg) { return toFlowRule(behaviour, cfg.getInPort(), cfg.getOutPort(), cfg.getChannel()); } /** * Finds the FlowRule from flow rule store by the given ports and channel. * Returns an extra flow to remove the flow by ONOS if not found. * @param behaviour the parent driver handler * @param inPort the input port * @param outPort the output port * @param channel the specified channel * @return the flow rule */ public static FlowRule toFlowRule(HandlerBehaviour behaviour, PortNumber inPort, PortNumber outPort, Integer channel) { FlowRuleService service = behaviour.handler().get(FlowRuleService.class); Iterable<FlowEntry> entries = service.getFlowEntries(behaviour.data().deviceId()); // Try to Find the flow from flow rule store. for (FlowEntry entry : entries) { Set<Criterion> criterions = entry.selector().criteria(); // input port PortNumber ip = criterions.stream() .filter(c -> c instanceof PortCriterion) .map(c -> ((PortCriterion) c).port()) .findAny() .orElse(null); // channel Integer ch = criterions.stream() .filter(c -> c instanceof OchSignalCriterion) .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier()) .findAny() .orElse(null); // output port PortNumber op = entry.treatment().immediate().stream() .filter(c -> c instanceof Instructions.OutputInstruction) .map(c -> ((Instructions.OutputInstruction) c).port()) .findAny() .orElse(null); if (inPort.equals(ip) && channel.equals(ch) && outPort.equals(op)) { // Find the flow. return entry; } } // Cannot find the flow from store. So report an extra flow to remove the flow by ONOS. TrafficSelector selector = DefaultTrafficSelector.builder() .matchInPort(inPort) .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID)) .add(Criteria.matchLambda(Lambda.ochSignal(GRID_TYPE, CHANNEL_SPACING, channel, SLOT_GRANULARITY))) .build(); TrafficTreatment treatment = DefaultTrafficTreatment.builder() .setOutput(outPort) .build(); return DefaultFlowRule.builder() .forDevice(behaviour.data().deviceId()) .withSelector(selector) .withTreatment(treatment) .withPriority(DEFAULT_PRIORITY) .fromApp(behaviour.handler().get(CoreService.class).getAppId(DEFAULT_APP)) .build(); } }