blob: 978522498b5919b91ddd906b1ea33c524d104fdc [file] [log] [blame]
/*
* 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();
}
}