blob: fb6eeadc65b77d3c6c2de82c91bce90034ea2f20 [file] [log] [blame]
alessio0a0f3342019-10-28 16:58:01 +01001/*
2 * Copyright 2018-present Open Networking Foundation
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 * This work was partially supported by EC H2020 project METRO-HAUL (761727).
17 */
18
19package org.onosproject.drivers.odtn.openconfig;
20
21import org.onosproject.net.OchSignal;
22import org.onosproject.net.PortNumber;
23import org.onosproject.net.flow.DefaultFlowRule;
24import org.onosproject.net.flow.FlowRule;
25import org.onosproject.net.flow.criteria.Criterion;
26import org.onosproject.net.flow.criteria.OchSignalCriterion;
27import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
28import org.onosproject.net.flow.criteria.PortCriterion;
29import org.onosproject.net.flow.instructions.Instruction;
30import org.onosproject.net.flow.instructions.Instructions;
31import org.onosproject.net.flow.instructions.L0ModificationInstruction;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35import java.util.List;
36import java.util.Set;
37
38import static com.google.common.base.Preconditions.checkArgument;
39
40public class TerminalDeviceFlowRule extends DefaultFlowRule {
41 private static final Logger log = LoggerFactory.getLogger(TerminalDeviceFlowRule.class);
42
43 public enum Type {
44 CLIENT_INGRESS,
45 CLIENT_EGRESS,
46 LINE_INGRESS,
47 LINE_EGRESS
48 }
49
50 //As generated by the OpticalConnectivityIntentCompiler
51 private static final int NUM_CRITERIA_LINE_EGRESS_RULE = 3;
52 private static final int NUM_INSTRUCTIONS_LINE_EGRESS_RULE = 1;
53 private static final int NUM_CRITERIA_LINE_INGRESS_RULE = 1;
54 private static final int NUM_INSTRUCTIONS_LINE_INGRESS_RULE = 2;
55
56 //As generated by the OpticalCoircuitIntentCompiler
57 private static final int NUM_CRITERIA_CLIENT_RULES = 1;
58 private static final int NUM_INSTRUCTIONS_CLIENT_RULES = 1;
59
60 public Type type;
61
62 private PortNumber inPortNumber;
63 private PortNumber outPortNumber;
64 private OchSignal ochSignal;
65 private String connectionName;
66
67
68 public TerminalDeviceFlowRule(FlowRule rule, List<PortNumber> linePorts) {
69 super(rule);
70
71 Set<Criterion> criteria = rule.selector().criteria();
72 List<Instruction> instructions = rule.treatment().immediate();
73
74 /*Rules for TerminalDevice are generated in OpticalPathIntentCompiler with two types of intents
75 --- OpticalConnectivity intent compilation generates following flow rules
76 OPTICAL LINE level at INGRESS node -- criteria: input port; output port, OChSignal;
77 OPTICAL LINE level at EGRESS node -- criteria: input port, OChSignal and OCh type; instruction: output port
78 --- OpticalCircuit intent compilation generates following flow rules
79 CLIENT PORT at INGRESS node -- criteria: input port (OduClt); instruction output port (Och)
80 CLIENT PORT at EGRESS node -- criteria: input port (Och); instruction output port (OduClt)*/
81
82 checkArgument((criteria.size() == NUM_CRITERIA_LINE_EGRESS_RULE) ||
83 (criteria.size() == NUM_CRITERIA_LINE_INGRESS_RULE) ||
84 (criteria.size() == NUM_CRITERIA_CLIENT_RULES),
85 "Wrong size of flow rule criteria for TerminalDevice size" + criteria.size());
86
87 checkArgument((instructions.size() == NUM_INSTRUCTIONS_LINE_EGRESS_RULE) ||
88 (instructions.size() == NUM_INSTRUCTIONS_LINE_INGRESS_RULE) ||
89 (instructions.size() == NUM_INSTRUCTIONS_CLIENT_RULES),
90 "Wrong size of flow rule instructions for TerminalDevice size " + instructions.size());
91
92 //This is EGRESS rule on the LINE side
93 if ((criteria.size() == NUM_CRITERIA_LINE_EGRESS_RULE) &&
94 (instructions.size() == NUM_INSTRUCTIONS_LINE_EGRESS_RULE)) {
95 log.debug("Building the TerminalDeviceFlowRule for LINE_EGRESS");
96 type = Type.LINE_EGRESS;
97
98 criteria.forEach(
99 c -> checkArgument(c instanceof OchSignalCriterion ||
100 c instanceof OchSignalTypeCriterion ||
101 c instanceof PortCriterion,
102 "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria
103 )
104 );
105 instructions.forEach(
106 c -> checkArgument(c instanceof Instructions.OutputInstruction,
107 "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions
108 )
109 );
110
111 ochSignal = criteria.stream()
112 .filter(c -> c instanceof OchSignalCriterion)
113 .map(c -> ((OchSignalCriterion) c).lambda())
114 .findAny()
115 .orElse(null);
116
117 inPortNumber = criteria.stream()
118 .filter(c -> c instanceof PortCriterion)
119 .map(c -> ((PortCriterion) c).port())
120 .findAny()
121 .orElse(null);
122
123 outPortNumber = ((Instructions.OutputInstruction) instructions.get(0)).port();
124
125 checkArgument(linePorts.contains(outPortNumber),
126 "Incompatible output port for DROP TerminalDevice");
127
128 }
129
130 //This is INGRESS rule on the LINE side
131 if ((criteria.size() == NUM_CRITERIA_LINE_INGRESS_RULE) &&
132 (instructions.size() == NUM_INSTRUCTIONS_LINE_INGRESS_RULE)) {
133 log.debug("Building the TerminalDeviceFlowRule LINE_INGRESS");
134 type = Type.LINE_INGRESS;
135
136 criteria.forEach(
137 c -> checkArgument(
138 c instanceof PortCriterion,
139 "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria
140 )
141 );
142 instructions.forEach(
143 c -> checkArgument(c.type() == Instruction.Type.L0MODIFICATION ||
144 c.type() == Instruction.Type.OUTPUT,
145 "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions
146 )
147 );
148
149 inPortNumber = criteria.stream()
150 .filter(c -> c instanceof PortCriterion)
151 .map(c -> ((PortCriterion) c).port())
152 .findAny()
153 .orElse(null);
154
155 checkArgument(linePorts.contains(inPortNumber),
156 "Incompatible input port for DROP TerminalDevice");
157
158 ochSignal = instructions.stream()
159 .filter(c -> c.type() == Instruction.Type.L0MODIFICATION)
160 .map(c -> ((L0ModificationInstruction.ModOchSignalInstruction) c).lambda())
161 .findAny()
162 .orElse(null);
163
164 outPortNumber = instructions.stream()
165 .filter(c -> c.type() == Instruction.Type.OUTPUT)
166 .map(c -> ((Instructions.OutputInstruction) c).port())
167 .findAny()
168 .orElse(null);
169 }
170
171 //This is INGRESS or EGRESS rule on the CLIENT side
172 if ((criteria.size() == NUM_CRITERIA_CLIENT_RULES) &&
173 (instructions.size() == NUM_INSTRUCTIONS_CLIENT_RULES)) {
174
175 criteria.forEach(
176 c -> checkArgument(
177 c instanceof PortCriterion,
178 "Incompatible flow rule criteria for ADD TerminalDevice: " + criteria
179 )
180 );
181 instructions.forEach(
182 c -> checkArgument(c.type() == Instruction.Type.OUTPUT,
183 "Incompatible flow rule instruction for ADD TerminalDevice: " + instructions
184 )
185 );
186
187 inPortNumber = criteria.stream()
188 .filter(c -> c instanceof PortCriterion)
189 .map(c -> ((PortCriterion) c).port())
190 .findAny()
191 .orElse(null);
192
193 outPortNumber = instructions.stream()
194 .filter(c -> c.type() == Instruction.Type.OUTPUT)
195 .map(c -> ((Instructions.OutputInstruction) c).port())
196 .findAny()
197 .orElse(null);
198
199 ochSignal = null;
200
201 if (linePorts.contains(outPortNumber)) {
202 type = Type.CLIENT_INGRESS;
203 } else {
204 type = Type.CLIENT_EGRESS;
205 }
206 }
207
208 if (type == Type.LINE_EGRESS) {
209 connectionName = "LineEgress-LinePort-" + inPortNumber.toString()
210 + "-ochSig-" + ochSignal.centralFrequency().toString();
211 }
212 if (type == Type.LINE_INGRESS) {
213 connectionName = "LineIngress-LinePort-" + outPortNumber.toString()
214 + "-ochSig-" + ochSignal.centralFrequency().toString();
215 }
216 if (type == Type.CLIENT_EGRESS) {
217 connectionName = "ClientEgress-LinePort-" + inPortNumber.toString()
218 + "-ClientPort-" + outPortNumber.toString();
219 }
220 if (type == Type.CLIENT_INGRESS) {
221 connectionName = "ClientIngress-ClientPort-" + inPortNumber.toString()
222 + "-LinePort-" + outPortNumber.toString();
223 }
224
225 log.info("TerminalFlowRule built with name {}", connectionName);
226 }
227
228 public PortNumber inPort() {
229 return inPortNumber;
230 }
231
232 public PortNumber outPort() {
233 return outPortNumber;
234 }
235
236 public OchSignal ochSignal() {
237 return ochSignal;
238 }
239
240 public String connectionName() {
241 return connectionName;
242 }
243}
244