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