| /* |
| * Copyright 2018-present Open Networking Foundation |
| * |
| * 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. |
| |
| * This work was partially supported by EC H2020 project METRO-HAUL (761727). |
| */ |
| |
| package org.onosproject.drivers.odtn.openconfig; |
| |
| import org.onosproject.net.OchSignal; |
| import org.onosproject.net.PortNumber; |
| import org.onosproject.net.flow.DefaultFlowRule; |
| import org.onosproject.net.flow.FlowRule; |
| import org.onosproject.net.flow.criteria.Criterion; |
| import org.onosproject.net.flow.criteria.OchSignalCriterion; |
| import org.onosproject.net.flow.criteria.OchSignalTypeCriterion; |
| import org.onosproject.net.flow.criteria.PortCriterion; |
| import org.onosproject.net.flow.instructions.Instruction; |
| import org.onosproject.net.flow.instructions.Instructions; |
| import org.onosproject.net.flow.instructions.L0ModificationInstruction; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.List; |
| import java.util.Set; |
| |
| import static com.google.common.base.Preconditions.checkArgument; |
| |
| public class TerminalDeviceFlowRule extends DefaultFlowRule { |
| private static final Logger log = LoggerFactory.getLogger(TerminalDeviceFlowRule.class); |
| |
| public enum Type { |
| CLIENT_INGRESS, |
| CLIENT_EGRESS, |
| LINE_INGRESS, |
| LINE_EGRESS |
| } |
| |
| //As generated by the OpticalConnectivityIntentCompiler |
| private static final int NUM_CRITERIA_LINE_EGRESS_RULE = 3; |
| private static final int NUM_INSTRUCTIONS_LINE_EGRESS_RULE = 1; |
| private static final int NUM_CRITERIA_LINE_INGRESS_RULE = 1; |
| private static final int NUM_INSTRUCTIONS_LINE_INGRESS_RULE = 2; |
| |
| //As generated by the OpticalCoircuitIntentCompiler |
| private static final int NUM_CRITERIA_CLIENT_RULES = 1; |
| private static final int NUM_INSTRUCTIONS_CLIENT_RULES = 1; |
| |
| public Type type; |
| |
| private PortNumber inPortNumber; |
| private PortNumber outPortNumber; |
| private OchSignal ochSignal; |
| private String connectionName; |
| |
| |
| public TerminalDeviceFlowRule(FlowRule rule, List<PortNumber> linePorts) { |
| super(rule); |
| |
| Set<Criterion> criteria = rule.selector().criteria(); |
| List<Instruction> instructions = rule.treatment().immediate(); |
| |
| /*Rules for TerminalDevice are generated in OpticalPathIntentCompiler with two types of intents |
| --- OpticalConnectivity intent compilation generates following flow rules |
| OPTICAL LINE level at INGRESS node -- criteria: input port; output port, OChSignal; |
| OPTICAL LINE level at EGRESS node -- criteria: input port, OChSignal and OCh type; instruction: output port |
| --- OpticalCircuit intent compilation generates following flow rules |
| CLIENT PORT at INGRESS node -- criteria: input port (OduClt); instruction output port (Och) |
| CLIENT PORT at EGRESS node -- criteria: input port (Och); instruction output port (OduClt)*/ |
| |
| checkArgument((criteria.size() == NUM_CRITERIA_LINE_EGRESS_RULE) || |
| (criteria.size() == NUM_CRITERIA_LINE_INGRESS_RULE) || |
| (criteria.size() == NUM_CRITERIA_CLIENT_RULES), |
| "Wrong size of flow rule criteria for TerminalDevice size" + criteria.size()); |
| |
| checkArgument((instructions.size() == NUM_INSTRUCTIONS_LINE_EGRESS_RULE) || |
| (instructions.size() == NUM_INSTRUCTIONS_LINE_INGRESS_RULE) || |
| (instructions.size() == NUM_INSTRUCTIONS_CLIENT_RULES), |
| "Wrong size of flow rule instructions for TerminalDevice size " + instructions.size()); |
| |
| //This is EGRESS rule on the LINE side |
| if ((criteria.size() == NUM_CRITERIA_LINE_EGRESS_RULE) && |
| (instructions.size() == NUM_INSTRUCTIONS_LINE_EGRESS_RULE)) { |
| log.debug("Building the TerminalDeviceFlowRule for LINE_EGRESS"); |
| type = Type.LINE_EGRESS; |
| |
| criteria.forEach( |
| c -> checkArgument(c instanceof OchSignalCriterion || |
| c instanceof OchSignalTypeCriterion || |
| c instanceof PortCriterion, |
| "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria |
| ) |
| ); |
| instructions.forEach( |
| c -> checkArgument(c instanceof Instructions.OutputInstruction, |
| "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions |
| ) |
| ); |
| |
| ochSignal = criteria.stream() |
| .filter(c -> c instanceof OchSignalCriterion) |
| .map(c -> ((OchSignalCriterion) c).lambda()) |
| .findAny() |
| .orElse(null); |
| |
| inPortNumber = criteria.stream() |
| .filter(c -> c instanceof PortCriterion) |
| .map(c -> ((PortCriterion) c).port()) |
| .findAny() |
| .orElse(null); |
| |
| outPortNumber = ((Instructions.OutputInstruction) instructions.get(0)).port(); |
| |
| checkArgument(linePorts.contains(outPortNumber), |
| "Incompatible output port for DROP TerminalDevice"); |
| |
| } |
| |
| //This is INGRESS rule on the LINE side |
| if ((criteria.size() == NUM_CRITERIA_LINE_INGRESS_RULE) && |
| (instructions.size() == NUM_INSTRUCTIONS_LINE_INGRESS_RULE)) { |
| log.debug("Building the TerminalDeviceFlowRule LINE_INGRESS"); |
| type = Type.LINE_INGRESS; |
| |
| criteria.forEach( |
| c -> checkArgument( |
| c instanceof PortCriterion, |
| "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria |
| ) |
| ); |
| instructions.forEach( |
| c -> checkArgument(c.type() == Instruction.Type.L0MODIFICATION || |
| c.type() == Instruction.Type.OUTPUT, |
| "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions |
| ) |
| ); |
| |
| inPortNumber = criteria.stream() |
| .filter(c -> c instanceof PortCriterion) |
| .map(c -> ((PortCriterion) c).port()) |
| .findAny() |
| .orElse(null); |
| |
| checkArgument(linePorts.contains(inPortNumber), |
| "Incompatible input port for DROP TerminalDevice"); |
| |
| ochSignal = instructions.stream() |
| .filter(c -> c.type() == Instruction.Type.L0MODIFICATION) |
| .map(c -> ((L0ModificationInstruction.ModOchSignalInstruction) c).lambda()) |
| .findAny() |
| .orElse(null); |
| |
| outPortNumber = instructions.stream() |
| .filter(c -> c.type() == Instruction.Type.OUTPUT) |
| .map(c -> ((Instructions.OutputInstruction) c).port()) |
| .findAny() |
| .orElse(null); |
| } |
| |
| //This is INGRESS or EGRESS rule on the CLIENT side |
| if ((criteria.size() == NUM_CRITERIA_CLIENT_RULES) && |
| (instructions.size() == NUM_INSTRUCTIONS_CLIENT_RULES)) { |
| |
| criteria.forEach( |
| c -> checkArgument( |
| c instanceof PortCriterion, |
| "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria |
| ) |
| ); |
| instructions.forEach( |
| c -> checkArgument(c.type() == Instruction.Type.OUTPUT, |
| "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions |
| ) |
| ); |
| |
| inPortNumber = criteria.stream() |
| .filter(c -> c instanceof PortCriterion) |
| .map(c -> ((PortCriterion) c).port()) |
| .findAny() |
| .orElse(null); |
| |
| outPortNumber = instructions.stream() |
| .filter(c -> c.type() == Instruction.Type.OUTPUT) |
| .map(c -> ((Instructions.OutputInstruction) c).port()) |
| .findAny() |
| .orElse(null); |
| |
| ochSignal = null; |
| |
| if (linePorts.contains(outPortNumber)) { |
| type = Type.CLIENT_INGRESS; |
| } else { |
| type = Type.CLIENT_EGRESS; |
| } |
| } |
| |
| if (type == Type.LINE_EGRESS) { |
| connectionName = "LineEgress-LinePort-" + inPortNumber.toString() |
| + "-ochSig-" + ochSignal.centralFrequency().toString(); |
| } |
| if (type == Type.LINE_INGRESS) { |
| connectionName = "LineIngress-LinePort-" + outPortNumber.toString() |
| + "-ochSig-" + ochSignal.centralFrequency().toString(); |
| } |
| if (type == Type.CLIENT_EGRESS) { |
| connectionName = "ClientEgress-LinePort-" + inPortNumber.toString() |
| + "-ClientPort-" + outPortNumber.toString(); |
| } |
| if (type == Type.CLIENT_INGRESS) { |
| connectionName = "ClientIngress-ClientPort-" + inPortNumber.toString() |
| + "-LinePort-" + outPortNumber.toString(); |
| } |
| |
| log.info("TerminalFlowRule built with name {}", connectionName); |
| } |
| |
| public PortNumber inPort() { |
| return inPortNumber; |
| } |
| |
| public PortNumber outPort() { |
| return outPortNumber; |
| } |
| |
| public OchSignal ochSignal() { |
| return ochSignal; |
| } |
| |
| public String connectionName() { |
| return connectionName; |
| } |
| } |
| |