blob: 020629d0e39d6e99c944e6790e0681a5c12803ca [file] [log] [blame]
pier9469f3e2019-04-17 17:05:08 +02001/*
2 * Copyright 2019-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
17package org.onosproject.driver.pipeline.ofdpa;
18
19import org.onlab.packet.Ethernet;
20import org.onlab.packet.IpPrefix;
21import org.onlab.packet.MacAddress;
22import org.onlab.packet.VlanId;
23import org.onosproject.net.driver.Driver;
24import org.onosproject.net.flow.TrafficSelector;
25import org.onosproject.net.flow.TrafficTreatment;
26import org.onosproject.net.flow.criteria.Criterion;
27import org.onosproject.net.flow.criteria.EthCriterion;
28import org.onosproject.net.flow.criteria.EthTypeCriterion;
29import org.onosproject.net.flow.criteria.ExtensionCriterion;
30import org.onosproject.net.flow.criteria.ExtensionSelector;
31import org.onosproject.net.flow.criteria.IPCriterion;
32import org.onosproject.net.flow.criteria.MplsBosCriterion;
33import org.onosproject.net.flow.criteria.VlanIdCriterion;
34import org.onosproject.net.flow.instructions.Instruction;
35import org.onosproject.net.flow.instructions.Instructions;
36import org.onosproject.net.flow.instructions.L2ModificationInstruction;
37import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
38import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
39import org.onosproject.net.flowobjective.FilteringObjective;
40import org.onosproject.net.flowobjective.ForwardingObjective;
41import org.onosproject.net.flowobjective.Objective;
42import org.onosproject.net.flowobjective.ObjectiveError;
43
44import static org.onosproject.net.behaviour.Pipeliner.ACCUMULATOR_ENABLED;
Daniele Morofa382c22019-07-12 17:58:54 -070045import static org.onosproject.net.flow.criteria.Criterion.Type.*;
pier9469f3e2019-04-17 17:05:08 +020046import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
47import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
48import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
49
50public final class OfdpaPipelineUtility {
51
52 private OfdpaPipelineUtility() {
53 // Utility classes should not have a public or default constructor.
54 }
55
56 // Ofdpa specific tables number
pierventre4b72c472020-05-22 09:42:31 -070057 public static final int PORT_TABLE = 0;
58 public static final int VLAN_TABLE = 10;
pier9469f3e2019-04-17 17:05:08 +020059 static final int VLAN_1_TABLE = 11;
60 static final int MPLS_L2_PORT_FLOW_TABLE = 13;
61 static final int MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE = 16;
pierventre4b72c472020-05-22 09:42:31 -070062 public static final int TMAC_TABLE = 20;
63 public static final int UNICAST_ROUTING_TABLE = 30;
64 public static final int MULTICAST_ROUTING_TABLE = 40;
65 public static final int MPLS_TABLE_0 = 23;
66 public static final int MPLS_TABLE_1 = 24;
67 public static final int MPLS_L3_TYPE_TABLE = 27;
68 public static final int MPLS_TYPE_TABLE = 29;
69 public static final int BRIDGING_TABLE = 50;
pier9469f3e2019-04-17 17:05:08 +020070 public static final int ACL_TABLE = 60;
71 static final int EGRESS_VLAN_FLOW_TABLE = 210;
72 static final int EGRESS_DSCP_PCP_REMARK_FLOW_TABLE = 230;
73 static final int EGRESS_TPID_FLOW_TABLE = 235;
74 static final int MAC_LEARNING_TABLE = 254;
75
76 // OF max port number
77 static final long OFPP_MAX = 0xffffff00L;
78
79 // Priority values
80 static final int HIGHEST_PRIORITY = 0xffff;
81 static final int DEFAULT_PRIORITY = 0x8000;
82 static final int LOWEST_PRIORITY = 0x0;
83
84 // MPLS L2 table values
85 static final int MPLS_L2_PORT_PRIORITY = 2;
86 static final int MPLS_TUNNEL_ID_BASE = 0x10000;
87 static final int MPLS_TUNNEL_ID_MAX = 0x1FFFF;
88 static final int MPLS_UNI_PORT_MAX = 0x0000FFFF;
89 static final int MPLS_NNI_PORT_BASE = 0x00020000;
90 static final int MPLS_NNI_PORT_MAX = 0x0002FFFF;
91
92 // Egress table values
93 static final short ALLOW_VLAN_TRANSLATION = 1;
94 static final int COPY_FIELD_NBITS = 12;
95 static final int COPY_FIELD_OFFSET = 0;
96
97 // Flow retry values
98 static final int MAX_RETRY_ATTEMPTS = 10;
99 static final int RETRY_MS = 1000;
100
101 //////////////////////////////
102 // Helper and utility methods
103 //////////////////////////////
104
105 /**
106 * Check whether the accumulator is enabled or not.
107 * @param pipeline the pipeline
108 * @return true if the accumulator is enabled. Otherwise not
109 */
110 static boolean isAccumulatorEnabled(Ofdpa2Pipeline pipeline) {
111 Driver driver = pipeline.data().driver();
112 // we cannot determine the property
113 if (driver == null) {
114 return false;
115 }
116 return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED));
117 }
118
119 static void pass(Objective obj) {
120 obj.context().ifPresent(context -> context.onSuccess(obj));
121 }
122
123 static void fail(Objective obj, ObjectiveError error) {
124 obj.context().ifPresent(context -> context.onError(obj, error));
125 }
126
127 /**
128 * Returns true iff the given selector matches on BOS==true, indicating that
129 * the selector is trying to match on a label that is bottom-of-stack.
130 *
131 * @param selector the given match
132 * @return true iff BoS==true; false if BOS==false, or BOS matching is not
133 * expressed in the given selector
134 */
135 static boolean isMplsBos(TrafficSelector selector) {
136 MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
137 return bosCriterion != null && bosCriterion.mplsBos();
138 }
139
140 /**
141 * Returns true iff the given selector matches on BOS==false, indicating
142 * that the selector is trying to match on a label that is not the
143 * bottom-of-stack label.
144 *
145 * @param selector the given match
146 * @return true iff BoS==false;
147 * false if BOS==true, or BOS matching is not expressed in the given selector
148 */
149 static boolean isNotMplsBos(TrafficSelector selector) {
150 MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
151 return bosCriterion != null && !bosCriterion.mplsBos();
152 }
153
154 /**
155 * Returns true iff the forwarding objective includes a treatment to pop the
156 * MPLS label.
157 *
158 * @param fwd the given forwarding objective
159 * @return true iff mpls pop treatment exists
160 */
161 static boolean isMplsPop(ForwardingObjective fwd) {
162 if (fwd.treatment() != null) {
163 for (Instruction instr : fwd.treatment().allInstructions()) {
164 if (instr instanceof L2ModificationInstruction
165 && ((L2ModificationInstruction) instr)
166 .subtype() == L2SubType.MPLS_POP) {
167 return true;
168 }
169 }
170 }
171 return false;
172 }
173
174 /**
175 * Returns true iff the given selector matches on ethtype==ipv6, indicating
176 * that the selector is trying to match on ipv6 traffic.
177 *
178 * @param selector the given match
179 * @return true iff ethtype==ipv6; false otherwise
180 */
181 static boolean isIpv6(TrafficSelector selector) {
182 EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) selector.getCriterion(ETH_TYPE);
183 return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6;
184 }
185
186 /**
187 * Reads vlan id from selector.
188 *
189 * @param selector the given match
190 * @return the vlan id if found. null otherwise
191 */
192 static VlanId readVlanFromSelector(TrafficSelector selector) {
193 if (selector == null) {
194 return null;
195 }
196 Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
197 return (criterion == null)
198 ? null : ((VlanIdCriterion) criterion).vlanId();
199 }
200
201 /**
202 * Reads eth dst from selector.
203 *
204 * @param selector the given match
205 * @return the eth dst if found. null otherwise
206 */
207 static MacAddress readEthDstFromSelector(TrafficSelector selector) {
208 if (selector == null) {
209 return null;
210 }
211 Criterion criterion = selector.getCriterion(Criterion.Type.ETH_DST);
212 return (criterion == null)
213 ? null : ((EthCriterion) criterion).mac();
214 }
215
216 /**
217 * Reads ipv4 dst from selector.
218 *
219 * @param selector the given match
220 * @return the ipv4 dst if found. null otherwise
221 */
222 static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
223 if (selector == null) {
224 return null;
225 }
226 Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
227 return (criterion == null) ? null : ((IPCriterion) criterion).ip();
228 }
229
230 /**
231 * Reads vlan id from treatment.
232 *
233 * @param treatment the given actions
234 * @return the vlan id if found. null otherwise
235 */
236 static VlanId readVlanFromTreatment(TrafficTreatment treatment) {
237 if (treatment == null) {
238 return null;
239 }
240 for (Instruction i : treatment.allInstructions()) {
241 if (i instanceof ModVlanIdInstruction) {
242 return ((ModVlanIdInstruction) i).vlanId();
243 }
244 }
245 return null;
246 }
247
248 /**
249 * Reads eth dst from treatment.
250 *
251 * @param treatment the given actions
252 * @return the eth dst if found. null otherwise
253 */
254 static MacAddress readEthDstFromTreatment(TrafficTreatment treatment) {
255 if (treatment == null) {
256 return null;
257 }
258 for (Instruction i : treatment.allInstructions()) {
259 if (i instanceof ModEtherInstruction) {
260 ModEtherInstruction modEtherInstruction = (ModEtherInstruction) i;
261 if (modEtherInstruction.subtype() == L2SubType.ETH_DST) {
262 return modEtherInstruction.mac();
263 }
264 }
265 }
266 return null;
267 }
268
269 /**
270 * Reads extensions from selector.
271 * @param selector the given match
272 * @return the extensions if found. null otherwise
273 */
274 static ExtensionSelector readExtensionFromSelector(TrafficSelector selector) {
275 if (selector == null) {
276 return null;
277 }
278 ExtensionCriterion criterion = (ExtensionCriterion) selector.getCriterion(Criterion.Type.EXTENSION);
279 return (criterion == null) ? null : criterion.extensionSelector();
280 }
281
282 /**
283 * Determines if the filtering objective will be used for a pseudowire.
284 *
285 * @param filteringObjective the filtering objective
286 * @return True if objective was created for a pseudowire, false otherwise.
287 */
288 static boolean isPseudowire(FilteringObjective filteringObjective) {
289 if (filteringObjective.meta() != null) {
290 TrafficTreatment treatment = filteringObjective.meta();
291 for (Instruction instr : treatment.immediate()) {
292 if (instr.type().equals(Instruction.Type.L2MODIFICATION)) {
293
294 L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr;
295 if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) {
296 return true;
297 }
298 }
299 }
300 }
301 return false;
302 }
303
304 /**
305 * Utility function to get the mod tunnel id instruction
306 * if present.
307 *
308 * @param treatment the treatment to analyze
309 * @return the mod tunnel id instruction if present,
310 * otherwise null
311 */
312 static ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) {
313 if (treatment == null) {
314 return null;
315 }
316 L2ModificationInstruction l2ModificationInstruction;
317 for (Instruction instruction : treatment.allInstructions()) {
318 if (instruction.type() == L2MODIFICATION) {
319 l2ModificationInstruction = (L2ModificationInstruction) instruction;
320 if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) {
321 return (ModTunnelIdInstruction) l2ModificationInstruction;
322 }
323 }
324 }
325 return null;
326 }
327
328 /**
329 * Utility function to get the output instruction
330 * if present.
331 *
332 * @param treatment the treatment to analyze
333 * @return the output instruction if present,
334 * otherwise null
335 */
336 static Instructions.OutputInstruction getOutputInstruction(TrafficTreatment treatment) {
337 if (treatment == null) {
338 return null;
339 }
340 for (Instruction instruction : treatment.allInstructions()) {
341 if (instruction.type() == Instruction.Type.OUTPUT) {
342 return (Instructions.OutputInstruction) instruction;
343 }
344 }
345 return null;
346 }
347
348 /**
349 * Determines if the filtering objective will be used for double-tagged packets.
350 *
351 * @param fob Filtering objective
352 * @return True if the objective was created for double-tagged packets, false otherwise.
353 */
354 static boolean isDoubleTagged(FilteringObjective fob) {
355 return fob.meta() != null &&
356 fob.meta().allInstructions().stream().anyMatch(inst -> inst.type() == L2MODIFICATION
357 && ((L2ModificationInstruction) inst).subtype() == L2SubType.VLAN_POP) &&
Daniele Morofa382c22019-07-12 17:58:54 -0700358 fob.conditions().stream().anyMatch(criterion -> criterion.type() == VLAN_VID) &&
359 fob.conditions().stream().anyMatch(criterion -> criterion.type() == INNER_VLAN_VID);
pier9469f3e2019-04-17 17:05:08 +0200360 }
361
362}