blob: 179e7931c420dc9f65dfe2ed0710324181e57fdf [file] [log] [blame]
Daniele Moro8d630f12021-06-15 20:53:22 +02001/*
2 * Copyright 2021-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.pipelines.fabric.impl.behaviour.upf;
18
19import org.apache.commons.lang3.tuple.Pair;
20import org.onlab.packet.Ip4Address;
21import org.onlab.util.ImmutableByteSequence;
22import org.onosproject.core.ApplicationId;
23import org.onosproject.net.DeviceId;
24import org.onosproject.net.behaviour.upf.ForwardingActionRule;
25import org.onosproject.net.behaviour.upf.GtpTunnel;
26import org.onosproject.net.behaviour.upf.PacketDetectionRule;
27import org.onosproject.net.behaviour.upf.UpfInterface;
28import org.onosproject.net.behaviour.upf.UpfProgrammableException;
29import org.onosproject.net.flow.DefaultFlowRule;
30import org.onosproject.net.flow.DefaultTrafficSelector;
31import org.onosproject.net.flow.DefaultTrafficTreatment;
32import org.onosproject.net.flow.FlowRule;
33import org.onosproject.net.flow.criteria.PiCriterion;
34import org.onosproject.net.pi.model.PiActionId;
35import org.onosproject.net.pi.model.PiTableId;
36import org.onosproject.net.pi.runtime.PiAction;
37import org.onosproject.net.pi.runtime.PiActionParam;
38import org.onosproject.net.pi.runtime.PiTableAction;
39
40import java.util.Arrays;
41
42import static org.onosproject.pipelines.fabric.FabricConstants.CTR_ID;
43import static org.onosproject.pipelines.fabric.FabricConstants.DROP;
44import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_DOWNLINK_PDRS;
45import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_FARS;
46import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_INTERFACES;
47import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR;
48import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_IFACE;
49import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_NORMAL_FAR;
50import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_PDR;
51import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_PDR_QOS;
52import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_LOAD_TUNNEL_FAR;
53import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_UPLINK_PDRS;
54import static org.onosproject.pipelines.fabric.FabricConstants.FAR_ID;
55import static org.onosproject.pipelines.fabric.FabricConstants.HDR_FAR_ID;
56import static org.onosproject.pipelines.fabric.FabricConstants.HDR_GTPU_IS_VALID;
Daniele Moro08c9e7f2021-07-28 18:53:34 +020057import static org.onosproject.pipelines.fabric.FabricConstants.HDR_HAS_QFI;
Daniele Moro8d630f12021-06-15 20:53:22 +020058import static org.onosproject.pipelines.fabric.FabricConstants.HDR_IPV4_DST_ADDR;
Daniele Moro08c9e7f2021-07-28 18:53:34 +020059import static org.onosproject.pipelines.fabric.FabricConstants.HDR_QFI;
Daniele Moro8d630f12021-06-15 20:53:22 +020060import static org.onosproject.pipelines.fabric.FabricConstants.HDR_TEID;
61import static org.onosproject.pipelines.fabric.FabricConstants.HDR_TUNNEL_IPV4_DST;
62import static org.onosproject.pipelines.fabric.FabricConstants.HDR_UE_ADDR;
63import static org.onosproject.pipelines.fabric.FabricConstants.NEEDS_GTPU_DECAP;
Daniele Moro08c9e7f2021-07-28 18:53:34 +020064import static org.onosproject.pipelines.fabric.FabricConstants.NEEDS_QFI_PUSH;
Daniele Moro8d630f12021-06-15 20:53:22 +020065import static org.onosproject.pipelines.fabric.FabricConstants.NOTIFY_CP;
Daniele Moro08c9e7f2021-07-28 18:53:34 +020066import static org.onosproject.pipelines.fabric.FabricConstants.QFI;
67import static org.onosproject.pipelines.fabric.FabricConstants.SLICE_ID;
Daniele Moro8d630f12021-06-15 20:53:22 +020068import static org.onosproject.pipelines.fabric.FabricConstants.SRC_IFACE;
Daniele Moro08c9e7f2021-07-28 18:53:34 +020069import static org.onosproject.pipelines.fabric.FabricConstants.TC;
Daniele Moro8d630f12021-06-15 20:53:22 +020070import static org.onosproject.pipelines.fabric.FabricConstants.TEID;
71import static org.onosproject.pipelines.fabric.FabricConstants.TUNNEL_DST_ADDR;
72import static org.onosproject.pipelines.fabric.FabricConstants.TUNNEL_SRC_ADDR;
73import static org.onosproject.pipelines.fabric.FabricConstants.TUNNEL_SRC_PORT;
Daniele Moro08c9e7f2021-07-28 18:53:34 +020074import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_QFI;
75import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_SLICE_ID;
76import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_TC;
77import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FALSE;
78import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.TRUE;
Daniele Moro8d630f12021-06-15 20:53:22 +020079
80/**
81 * Provides logic to translate UPF entities into pipeline-specific ones and vice-versa.
82 * Implementation should be stateless, with all state delegated to FabricUpfStore.
83 */
84public class FabricUpfTranslator {
85
86 // UPF related constants
87 public static final int INTERFACE_ACCESS = 1;
88 public static final int INTERFACE_CORE = 2;
89 public static final int INTERFACE_DBUF = 3;
90
91 private final FabricUpfStore fabricUpfStore;
92
93 public FabricUpfTranslator(FabricUpfStore fabricUpfStore) {
94 this.fabricUpfStore = fabricUpfStore;
95 }
96
97 /**
98 * Returns true if the given table entry is a Packet Detection Rule from the physical fabric pipeline, and
99 * false otherwise.
100 *
101 * @param entry the entry that may or may not be a fabric.p4 PDR
102 * @return true if the entry is a fabric.p4 PDR
103 */
104 public boolean isFabricPdr(FlowRule entry) {
105 return entry.table().equals(FABRIC_INGRESS_SPGW_UPLINK_PDRS)
106 || entry.table().equals(FABRIC_INGRESS_SPGW_DOWNLINK_PDRS);
107 }
108
109 /**
110 * Returns true if the given table entry is a Forwarding Action Rule from the physical fabric pipeline, and
111 * false otherwise.
112 *
113 * @param entry the entry that may or may not be a fabric.p4 FAR
114 * @return true if the entry is a fabric.p4 FAR
115 */
116 public boolean isFabricFar(FlowRule entry) {
117 return entry.table().equals(FABRIC_INGRESS_SPGW_FARS);
118 }
119
120 /**
121 * Returns true if the given table entry is an interface table entry from the fabric.p4 physical pipeline, and
122 * false otherwise.
123 *
124 * @param entry the entry that may or may not be a fabric.p4 UPF interface
125 * @return true if the entry is a fabric.p4 UPF interface
126 */
127 public boolean isFabricInterface(FlowRule entry) {
128 return entry.table().equals(FABRIC_INGRESS_SPGW_INTERFACES);
129 }
130
131
132 /**
133 * Translate a fabric.p4 PDR table entry to a PacketDetectionRule instance for easier handling.
134 *
135 * @param entry the fabric.p4 entry to translate
136 * @return the corresponding PacketDetectionRule
137 * @throws UpfProgrammableException if the entry cannot be translated
138 */
139 public PacketDetectionRule fabricEntryToPdr(FlowRule entry)
140 throws UpfProgrammableException {
141 var pdrBuilder = PacketDetectionRule.builder();
142 Pair<PiCriterion, PiTableAction> matchActionPair = FabricUpfTranslatorUtil.fabricEntryToPiPair(entry);
143 PiCriterion match = matchActionPair.getLeft();
144 PiAction action = (PiAction) matchActionPair.getRight();
145
146 // Grab keys and parameters that are present for all PDRs
147 int globalFarId = FabricUpfTranslatorUtil.getParamInt(action, FAR_ID);
148 UpfRuleIdentifier farId = fabricUpfStore.localFarIdOf(globalFarId);
pierventre1eb98712021-07-13 18:03:22 +0200149 if (farId == null) {
150 throw new UpfProgrammableException(String.format("Unable to find local far id of %s", globalFarId));
151 }
Daniele Moro8d630f12021-06-15 20:53:22 +0200152
Daniele Moro8d630f12021-06-15 20:53:22 +0200153 pdrBuilder.withCounterId(FabricUpfTranslatorUtil.getParamInt(action, CTR_ID))
154 .withLocalFarId(farId.getSessionLocalId())
155 .withSessionId(farId.getPfcpSessionId());
156
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200157 PiActionId actionId = action.id();
158 if (actionId.equals(FABRIC_INGRESS_SPGW_LOAD_PDR_QOS)) {
159 pdrBuilder.withQfi(FabricUpfTranslatorUtil.getParamByte(action, QFI));
160 if (FabricUpfTranslatorUtil.getParamByte(action, NEEDS_QFI_PUSH) == TRUE) {
161 pdrBuilder.withQfiPush();
162 }
163 }
164
Daniele Moro8d630f12021-06-15 20:53:22 +0200165 if (FabricUpfTranslatorUtil.fieldIsPresent(match, HDR_TEID)) {
166 // F-TEID is only present for GTP-matching PDRs
167 ImmutableByteSequence teid = FabricUpfTranslatorUtil.getFieldValue(match, HDR_TEID);
168 Ip4Address tunnelDst = FabricUpfTranslatorUtil.getFieldAddress(match, HDR_TUNNEL_IPV4_DST);
169 pdrBuilder.withTeid(teid)
170 .withTunnelDst(tunnelDst);
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200171 if (FabricUpfTranslatorUtil.fieldIsPresent(match, HDR_HAS_QFI) &&
172 FabricUpfTranslatorUtil.getFieldByte(match, HDR_HAS_QFI) == TRUE) {
173 pdrBuilder.withQfi(FabricUpfTranslatorUtil.getFieldByte(match, HDR_QFI));
174 pdrBuilder.withQfiMatch();
175 }
Daniele Moro8d630f12021-06-15 20:53:22 +0200176 } else if (FabricUpfTranslatorUtil.fieldIsPresent(match, HDR_UE_ADDR)) {
177 // And UE address is only present for non-GTP-matching PDRs
178 pdrBuilder.withUeAddr(FabricUpfTranslatorUtil.getFieldAddress(match, HDR_UE_ADDR));
179 } else {
180 throw new UpfProgrammableException("Read malformed PDR from dataplane!:" + entry);
181 }
182 return pdrBuilder.build();
183 }
184
185 /**
186 * Translate a fabric.p4 FAR table entry to a ForwardActionRule instance for easier handling.
187 *
188 * @param entry the fabric.p4 entry to translate
189 * @return the corresponding ForwardingActionRule
190 * @throws UpfProgrammableException if the entry cannot be translated
191 */
192 public ForwardingActionRule fabricEntryToFar(FlowRule entry)
193 throws UpfProgrammableException {
194 var farBuilder = ForwardingActionRule.builder();
195 Pair<PiCriterion, PiTableAction> matchActionPair = FabricUpfTranslatorUtil.fabricEntryToPiPair(entry);
196 PiCriterion match = matchActionPair.getLeft();
197 PiAction action = (PiAction) matchActionPair.getRight();
198
199 int globalFarId = FabricUpfTranslatorUtil.getFieldInt(match, HDR_FAR_ID);
200 UpfRuleIdentifier farId = fabricUpfStore.localFarIdOf(globalFarId);
pierventre1eb98712021-07-13 18:03:22 +0200201 if (farId == null) {
202 throw new UpfProgrammableException(String.format("Unable to find local far id of %s", globalFarId));
203 }
Daniele Moro8d630f12021-06-15 20:53:22 +0200204
205 boolean dropFlag = FabricUpfTranslatorUtil.getParamInt(action, DROP) > 0;
206 boolean notifyFlag = FabricUpfTranslatorUtil.getParamInt(action, NOTIFY_CP) > 0;
207
208 // Match keys
209 farBuilder.withSessionId(farId.getPfcpSessionId())
210 .setFarId(farId.getSessionLocalId());
211
212 // Parameters common to all types of FARs
213 farBuilder.setDropFlag(dropFlag)
214 .setNotifyFlag(notifyFlag);
215
216 PiActionId actionId = action.id();
217
218 if (actionId.equals(FABRIC_INGRESS_SPGW_LOAD_TUNNEL_FAR)
219 || actionId.equals(FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR)) {
220 // Grab parameters specific to encapsulating FARs if they're present
221 Ip4Address tunnelSrc = FabricUpfTranslatorUtil.getParamAddress(action, TUNNEL_SRC_ADDR);
222 Ip4Address tunnelDst = FabricUpfTranslatorUtil.getParamAddress(action, TUNNEL_DST_ADDR);
223 ImmutableByteSequence teid = FabricUpfTranslatorUtil.getParamValue(action, TEID);
224 short tunnelSrcPort = (short) FabricUpfTranslatorUtil.getParamInt(action, TUNNEL_SRC_PORT);
225
226 farBuilder.setBufferFlag(actionId.equals(FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR));
227
228 farBuilder.setTunnel(
229 GtpTunnel.builder()
230 .setSrc(tunnelSrc)
231 .setDst(tunnelDst)
232 .setTeid(teid)
233 .setSrcPort(tunnelSrcPort)
234 .build());
235 }
236 return farBuilder.build();
237 }
238
239 /**
240 * Translate a fabric.p4 interface table entry to a UpfInterface instance for easier handling.
241 *
242 * @param entry the fabric.p4 entry to translate
243 * @return the corresponding UpfInterface
244 * @throws UpfProgrammableException if the entry cannot be translated
245 */
246 public UpfInterface fabricEntryToInterface(FlowRule entry)
247 throws UpfProgrammableException {
248 Pair<PiCriterion, PiTableAction> matchActionPair = FabricUpfTranslatorUtil.fabricEntryToPiPair(entry);
249 PiCriterion match = matchActionPair.getLeft();
250 PiAction action = (PiAction) matchActionPair.getRight();
251
252 var ifaceBuilder = UpfInterface.builder()
253 .setPrefix(FabricUpfTranslatorUtil.getFieldPrefix(match, HDR_IPV4_DST_ADDR));
254
255 int interfaceType = FabricUpfTranslatorUtil.getParamInt(action, SRC_IFACE);
256 if (interfaceType == INTERFACE_ACCESS) {
257 ifaceBuilder.setAccess();
258 } else if (interfaceType == INTERFACE_CORE) {
259 ifaceBuilder.setCore();
260 } else if (interfaceType == INTERFACE_DBUF) {
261 ifaceBuilder.setDbufReceiver();
262 }
263 return ifaceBuilder.build();
264 }
265
266 /**
267 * Translate a ForwardingActionRule to a FlowRule to be inserted into the fabric.p4 pipeline.
268 * A side effect of calling this method is the FAR object's globalFarId is assigned if it was not already.
269 *
270 * @param far The FAR to be translated
271 * @param deviceId the ID of the device the FlowRule should be installed on
272 * @param appId the ID of the application that will insert the FlowRule
273 * @param priority the FlowRule's priority
274 * @return the FAR translated to a FlowRule
275 * @throws UpfProgrammableException if the FAR to be translated is malformed
276 */
277 public FlowRule farToFabricEntry(ForwardingActionRule far, DeviceId deviceId, ApplicationId appId, int priority)
278 throws UpfProgrammableException {
279 PiAction action;
280 if (!far.encaps()) {
281 action = PiAction.builder()
282 .withId(FABRIC_INGRESS_SPGW_LOAD_NORMAL_FAR)
283 .withParameters(Arrays.asList(
284 new PiActionParam(DROP, far.drops() ? 1 : 0),
285 new PiActionParam(NOTIFY_CP, far.notifies() ? 1 : 0)
286 ))
287 .build();
288
289 } else {
290 if (far.tunnelSrc() == null || far.tunnelDst() == null
291 || far.teid() == null || far.tunnel().srcPort() == null) {
292 throw new UpfProgrammableException(
293 "Not all action parameters present when translating " +
294 "intermediate encapsulating/buffering FAR to physical FAR!");
295 }
296 // TODO: copy tunnel destination port from logical switch write requests, instead of hardcoding 2152
297 PiActionId actionId = far.buffers() ? FABRIC_INGRESS_SPGW_LOAD_DBUF_FAR :
298 FABRIC_INGRESS_SPGW_LOAD_TUNNEL_FAR;
299 action = PiAction.builder()
300 .withId(actionId)
301 .withParameters(Arrays.asList(
302 new PiActionParam(DROP, far.drops() ? 1 : 0),
303 new PiActionParam(NOTIFY_CP, far.notifies() ? 1 : 0),
304 new PiActionParam(TEID, far.teid()),
305 new PiActionParam(TUNNEL_SRC_ADDR, far.tunnelSrc().toInt()),
306 new PiActionParam(TUNNEL_DST_ADDR, far.tunnelDst().toInt()),
307 new PiActionParam(TUNNEL_SRC_PORT, far.tunnel().srcPort())
308 ))
309 .build();
310 }
311 PiCriterion match = PiCriterion.builder()
312 .matchExact(HDR_FAR_ID, fabricUpfStore.globalFarIdOf(far.sessionId(), far.farId()))
313 .build();
314 return DefaultFlowRule.builder()
315 .forDevice(deviceId).fromApp(appId).makePermanent()
316 .forTable(FABRIC_INGRESS_SPGW_FARS)
317 .withSelector(DefaultTrafficSelector.builder().matchPi(match).build())
318 .withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build())
319 .withPriority(priority)
320 .build();
321 }
322
323 /**
324 * Translate a PacketDetectionRule to a FlowRule to be inserted into the fabric.p4 pipeline.
325 * A side effect of calling this method is the PDR object's globalFarId is assigned if it was not already.
326 *
327 * @param pdr The PDR to be translated
328 * @param deviceId the ID of the device the FlowRule should be installed on
329 * @param appId the ID of the application that will insert the FlowRule
330 * @param priority the FlowRule's priority
331 * @return the FAR translated to a FlowRule
332 * @throws UpfProgrammableException if the PDR to be translated is malformed
333 */
334 public FlowRule pdrToFabricEntry(PacketDetectionRule pdr, DeviceId deviceId, ApplicationId appId, int priority)
335 throws UpfProgrammableException {
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200336 final PiCriterion match;
337 final PiTableId tableId;
338 final PiAction action;
Daniele Moro8d630f12021-06-15 20:53:22 +0200339
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200340 final PiCriterion.Builder matchBuilder = PiCriterion.builder();
Daniele Moro8d630f12021-06-15 20:53:22 +0200341
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200342 PiAction.Builder actionBuilder = PiAction.builder()
Daniele Moro8d630f12021-06-15 20:53:22 +0200343 .withParameters(Arrays.asList(
344 new PiActionParam(CTR_ID, pdr.counterId()),
345 new PiActionParam(FAR_ID, fabricUpfStore.globalFarIdOf(pdr.sessionId(), pdr.farId())),
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200346 new PiActionParam(NEEDS_GTPU_DECAP, pdr.matchesEncapped() ?
347 TRUE : FALSE),
348 new PiActionParam(TC, DEFAULT_TC)
Daniele Moro8d630f12021-06-15 20:53:22 +0200349 ));
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200350 PiActionId actionId = FABRIC_INGRESS_SPGW_LOAD_PDR;
351 if (pdr.matchesEncapped()) {
352 tableId = FABRIC_INGRESS_SPGW_UPLINK_PDRS;
353 matchBuilder.matchExact(HDR_TEID, pdr.teid().asArray())
354 .matchExact(HDR_TUNNEL_IPV4_DST, pdr.tunnelDest().toInt());
355 if (pdr.matchQfi()) {
356 matchBuilder.matchExact(HDR_HAS_QFI, TRUE)
357 .matchExact(HDR_QFI, pdr.qfi());
358 } else {
359 matchBuilder.matchExact(HDR_HAS_QFI, FALSE)
360 .matchExact(HDR_QFI, DEFAULT_QFI);
361 if (pdr.hasQfi()) {
362 actionId = FABRIC_INGRESS_SPGW_LOAD_PDR_QOS;
363 actionBuilder.withParameter(new PiActionParam(QFI, pdr.qfi()))
364 .withParameter(new PiActionParam(NEEDS_QFI_PUSH, FALSE));
365 }
Daniele Moro8d630f12021-06-15 20:53:22 +0200366 }
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200367 } else if (pdr.matchesUnencapped()) {
368 tableId = FABRIC_INGRESS_SPGW_DOWNLINK_PDRS;
369 matchBuilder.matchExact(HDR_UE_ADDR, pdr.ueAddress().toInt());
370 if (pdr.hasQfi()) {
371 actionBuilder.withParameter(new PiActionParam(QFI, pdr.qfi()));
372 actionId = FABRIC_INGRESS_SPGW_LOAD_PDR_QOS;
373 }
374 actionBuilder.withParameter(
375 new PiActionParam(NEEDS_QFI_PUSH, pdr.pushQfi() ? TRUE : FALSE));
Daniele Moro8d630f12021-06-15 20:53:22 +0200376 } else {
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200377 throw new UpfProgrammableException("Flexible PDRs not yet supported! Cannot translate " + pdr);
Daniele Moro8d630f12021-06-15 20:53:22 +0200378 }
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200379 match = matchBuilder.build();
380 action = actionBuilder.withId(actionId)
381 .build();
Daniele Moro8d630f12021-06-15 20:53:22 +0200382 return DefaultFlowRule.builder()
383 .forDevice(deviceId).fromApp(appId).makePermanent()
384 .forTable(tableId)
385 .withSelector(DefaultTrafficSelector.builder().matchPi(match).build())
386 .withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build())
387 .withPriority(priority)
388 .build();
389 }
390
391 /**
392 * Translate a UpfInterface to a FlowRule to be inserted into the fabric.p4 pipeline.
393 *
394 * @param upfInterface The interface to be translated
395 * @param deviceId the ID of the device the FlowRule should be installed on
396 * @param appId the ID of the application that will insert the FlowRule
397 * @param priority the FlowRule's priority
398 * @return the UPF interface translated to a FlowRule
399 * @throws UpfProgrammableException if the interface cannot be translated
400 */
401 public FlowRule interfaceToFabricEntry(UpfInterface upfInterface, DeviceId deviceId,
402 ApplicationId appId, int priority)
403 throws UpfProgrammableException {
404 int interfaceTypeInt;
405 int gtpuValidity;
406 if (upfInterface.isDbufReceiver()) {
407 interfaceTypeInt = INTERFACE_DBUF;
408 gtpuValidity = 1;
409 } else if (upfInterface.isAccess()) {
410 interfaceTypeInt = INTERFACE_ACCESS;
411 gtpuValidity = 1;
412 } else {
413 interfaceTypeInt = INTERFACE_CORE;
414 gtpuValidity = 0;
415 }
416
417 PiCriterion match = PiCriterion.builder()
418 .matchLpm(HDR_IPV4_DST_ADDR,
419 upfInterface.prefix().address().toInt(),
420 upfInterface.prefix().prefixLength())
421 .matchExact(HDR_GTPU_IS_VALID, gtpuValidity)
422 .build();
423 PiAction action = PiAction.builder()
424 .withId(FABRIC_INGRESS_SPGW_LOAD_IFACE)
425 .withParameter(new PiActionParam(SRC_IFACE, interfaceTypeInt))
Daniele Moro08c9e7f2021-07-28 18:53:34 +0200426 .withParameter(new PiActionParam(SLICE_ID, DEFAULT_SLICE_ID))
Daniele Moro8d630f12021-06-15 20:53:22 +0200427 .build();
428 return DefaultFlowRule.builder()
429 .forDevice(deviceId).fromApp(appId).makePermanent()
430 .forTable(FABRIC_INGRESS_SPGW_INTERFACES)
431 .withSelector(DefaultTrafficSelector.builder().matchPi(match).build())
432 .withTreatment(DefaultTrafficTreatment.builder().piTableAction(action).build())
433 .withPriority(priority)
434 .build();
435 }
Daniele Moro8d630f12021-06-15 20:53:22 +0200436}