MaoLu | 819fde2 | 2017-04-20 17:17:49 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Open Networking Laboratory |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package org.onosproject.drivers.oplink; |
| 18 | |
MaoLu | e00b742 | 2017-05-11 20:27:35 -0700 | [diff] [blame^] | 19 | import com.google.common.collect.Range; |
MaoLu | 819fde2 | 2017-04-20 17:17:49 -0700 | [diff] [blame] | 20 | import org.onlab.util.Frequency; |
| 21 | import org.onosproject.core.CoreService; |
| 22 | import org.onosproject.driver.extensions.OplinkAttenuation; |
| 23 | import org.onosproject.net.ChannelSpacing; |
| 24 | import org.onosproject.net.GridType; |
| 25 | import org.onosproject.net.Lambda; |
| 26 | import org.onosproject.net.OchSignalType; |
| 27 | import org.onosproject.net.PortNumber; |
| 28 | import org.onosproject.net.driver.HandlerBehaviour; |
| 29 | import org.onosproject.net.flow.DefaultFlowRule; |
| 30 | import org.onosproject.net.flow.DefaultTrafficSelector; |
| 31 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 32 | import org.onosproject.net.flow.FlowEntry; |
| 33 | import org.onosproject.net.flow.FlowRule; |
| 34 | import org.onosproject.net.flow.FlowRuleService; |
| 35 | import org.onosproject.net.flow.TrafficSelector; |
| 36 | import org.onosproject.net.flow.TrafficTreatment; |
| 37 | import org.onosproject.net.flow.criteria.Criteria; |
| 38 | import org.onosproject.net.flow.criteria.Criterion; |
| 39 | import org.onosproject.net.flow.criteria.OchSignalCriterion; |
| 40 | import org.onosproject.net.flow.criteria.PortCriterion; |
| 41 | import org.onosproject.net.flow.instructions.Instruction; |
| 42 | import org.onosproject.net.flow.instructions.Instructions; |
| 43 | |
| 44 | import java.util.List; |
| 45 | import java.util.Set; |
| 46 | |
| 47 | /** |
| 48 | * Oplink optical utilities. |
| 49 | */ |
| 50 | public final class OplinkOpticalUtility { |
| 51 | |
| 52 | // Lambda information supported by device. |
| 53 | public static final GridType GRID_TYPE = GridType.DWDM; |
| 54 | public static final int SLOT_GRANULARITY = 4; |
| 55 | // Channel spacing is 50GHz, 12.5GHz * 4 |
| 56 | public static final ChannelSpacing CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ; |
| 57 | // Start frequency supported by device. |
| 58 | public static final Frequency START_CENTER_FREQ = Frequency.ofGHz(191_350); |
| 59 | // Stop frequency supported by device. |
| 60 | public static final Frequency STOP_CENTER_FREQ = Frequency.ofGHz(196_100); |
| 61 | |
| 62 | // Power multiply factor, the power accuracy supported by device is 0.01dBm. |
| 63 | // Transforms the double typed number to long typed power for ONOS. |
| 64 | public static final int POWER_MULTIPLIER = 100; |
MaoLu | e00b742 | 2017-05-11 20:27:35 -0700 | [diff] [blame^] | 65 | // Attenuation range supported by device, [0, 25.5dB]. |
| 66 | public static final Range<Long> RANGE_ATT = Range.closed(0L, 2550L); |
| 67 | // General power range for fiber switch, [-60dBm, 60dBm]. |
| 68 | public static final Range<Long> RANGE_GENERAL = Range.closed(-6000L, 6000L); |
MaoLu | 819fde2 | 2017-04-20 17:17:49 -0700 | [diff] [blame] | 69 | |
| 70 | // Default attenuation value if the attenuation instruction is not found. |
| 71 | private static final int DEFAULT_ATT = 0; |
| 72 | // Default flow priority for an extra flow. |
| 73 | private static final int DEFAULT_PRIORITY = 88; |
| 74 | // Default application name. |
| 75 | private static final String DEFAULT_APP = "org.onosproject.drivers.oplink"; |
| 76 | |
| 77 | private OplinkOpticalUtility() { |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * Transforms a flow FlowRule object to an OplinkCrossConnect object. |
| 82 | * @param behaviour the parent driver handler |
| 83 | * @param rule FlowRule object |
| 84 | * @return cross connect object |
| 85 | */ |
| 86 | public static OplinkCrossConnect fromFlowRule(HandlerBehaviour behaviour, FlowRule rule) { |
| 87 | // TrafficSelector |
| 88 | Set<Criterion> criterions = rule.selector().criteria(); |
| 89 | int channel = criterions.stream() |
| 90 | .filter(c -> c instanceof OchSignalCriterion) |
| 91 | .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier()) |
| 92 | .findAny() |
| 93 | .orElse(null); |
| 94 | PortNumber inPort = criterions.stream() |
| 95 | .filter(c -> c instanceof PortCriterion) |
| 96 | .map(c -> ((PortCriterion) c).port()) |
| 97 | .findAny() |
| 98 | .orElse(null); |
| 99 | // TrafficTreatment |
| 100 | List<Instruction> instructions = rule.treatment().immediate(); |
| 101 | PortNumber outPort = instructions.stream() |
| 102 | .filter(c -> c instanceof Instructions.OutputInstruction) |
| 103 | .map(c -> ((Instructions.OutputInstruction) c).port()) |
| 104 | .findAny() |
| 105 | .orElse(null); |
| 106 | int attenuation = instructions.stream() |
| 107 | .filter(c -> c instanceof Instructions.ExtensionInstructionWrapper) |
| 108 | .map(c -> ((Instructions.ExtensionInstructionWrapper) c).extensionInstruction()) |
| 109 | .filter(c -> c instanceof OplinkAttenuation) |
| 110 | .map(c -> ((OplinkAttenuation) c).getAttenuation()) |
| 111 | .findAny() |
| 112 | .orElse(DEFAULT_ATT); |
| 113 | return new OplinkCrossConnect(inPort, outPort, channel, attenuation); |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Finds the FlowRule from flow rule store by the given cross connect information. |
| 118 | * Returns an extra flow to remove the flow by ONOS if not found. |
| 119 | * @param behaviour the parent driver handler |
| 120 | * @param cfg cross connect information |
| 121 | * @return the flow rule |
| 122 | */ |
| 123 | public static FlowRule toFlowRule(HandlerBehaviour behaviour, OplinkCrossConnect cfg) { |
| 124 | return toFlowRule(behaviour, cfg.getInPort(), cfg.getOutPort(), cfg.getChannel()); |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Finds the FlowRule from flow rule store by the given ports and channel. |
| 129 | * Returns an extra flow to remove the flow by ONOS if not found. |
| 130 | * @param behaviour the parent driver handler |
| 131 | * @param inPort the input port |
| 132 | * @param outPort the output port |
| 133 | * @param channel the specified channel |
| 134 | * @return the flow rule |
| 135 | */ |
| 136 | public static FlowRule toFlowRule(HandlerBehaviour behaviour, PortNumber inPort, |
| 137 | PortNumber outPort, Integer channel) { |
| 138 | FlowRuleService service = behaviour.handler().get(FlowRuleService.class); |
| 139 | Iterable<FlowEntry> entries = service.getFlowEntries(behaviour.data().deviceId()); |
| 140 | // Try to Find the flow from flow rule store. |
| 141 | for (FlowEntry entry : entries) { |
| 142 | Set<Criterion> criterions = entry.selector().criteria(); |
| 143 | // input port |
| 144 | PortNumber ip = criterions.stream() |
| 145 | .filter(c -> c instanceof PortCriterion) |
| 146 | .map(c -> ((PortCriterion) c).port()) |
| 147 | .findAny() |
| 148 | .orElse(null); |
| 149 | // channel |
| 150 | Integer ch = criterions.stream() |
| 151 | .filter(c -> c instanceof OchSignalCriterion) |
| 152 | .map(c -> ((OchSignalCriterion) c).lambda().spacingMultiplier()) |
| 153 | .findAny() |
| 154 | .orElse(null); |
| 155 | // output port |
| 156 | PortNumber op = entry.treatment().immediate().stream() |
| 157 | .filter(c -> c instanceof Instructions.OutputInstruction) |
| 158 | .map(c -> ((Instructions.OutputInstruction) c).port()) |
| 159 | .findAny() |
| 160 | .orElse(null); |
| 161 | if (inPort.equals(ip) && channel.equals(ch) && outPort.equals(op)) { |
| 162 | // Find the flow. |
| 163 | return entry; |
| 164 | } |
| 165 | } |
| 166 | // Cannot find the flow from store. So report an extra flow to remove the flow by ONOS. |
| 167 | TrafficSelector selector = DefaultTrafficSelector.builder() |
| 168 | .matchInPort(inPort) |
| 169 | .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID)) |
| 170 | .add(Criteria.matchLambda(Lambda.ochSignal(GRID_TYPE, CHANNEL_SPACING, channel, SLOT_GRANULARITY))) |
| 171 | .build(); |
| 172 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 173 | .setOutput(outPort) |
| 174 | .build(); |
| 175 | return DefaultFlowRule.builder() |
| 176 | .forDevice(behaviour.data().deviceId()) |
| 177 | .withSelector(selector) |
| 178 | .withTreatment(treatment) |
| 179 | .withPriority(DEFAULT_PRIORITY) |
| 180 | .fromApp(behaviour.handler().get(CoreService.class).getAppId(DEFAULT_APP)) |
| 181 | .build(); |
| 182 | |
| 183 | } |
| 184 | } |