blob: 5ed475a269cda3f865038a3375a0b5da15cbcfe9 [file] [log] [blame]
Jonghwan Hyun722275f2018-05-14 15:44:56 -07001/*
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 */
16package org.onosproject.pipelines.basic;
17
18import com.google.common.collect.ImmutableBiMap;
19import com.google.common.collect.Sets;
20import org.apache.felix.scr.annotations.Reference;
21import org.apache.felix.scr.annotations.ReferenceCardinality;
22import org.onlab.util.ImmutableByteSequence;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070023import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
25import org.onosproject.inbandtelemetry.api.IntConfig;
26import org.onosproject.inbandtelemetry.api.IntIntent;
27import org.onosproject.inbandtelemetry.api.IntObjective;
28import org.onosproject.inbandtelemetry.api.IntProgrammable;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070029import org.onosproject.net.DeviceId;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070030import org.onosproject.net.PortNumber;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070031import org.onosproject.net.driver.AbstractHandlerBehaviour;
32import org.onosproject.net.flow.DefaultFlowRule;
33import org.onosproject.net.flow.DefaultTrafficSelector;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
35import org.onosproject.net.flow.FlowRule;
36import org.onosproject.net.flow.FlowRuleService;
Carmelo Casconefa421582018-09-13 10:05:57 -070037import org.onosproject.net.flow.TableId;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070038import org.onosproject.net.flow.TrafficSelector;
39import org.onosproject.net.flow.TrafficTreatment;
40import org.onosproject.net.flow.criteria.Criterion;
41import org.onosproject.net.flow.criteria.IPCriterion;
42import org.onosproject.net.flow.criteria.PiCriterion;
43import org.onosproject.net.flow.criteria.TcpPortCriterion;
44import org.onosproject.net.flow.criteria.UdpPortCriterion;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070045import org.onosproject.net.pi.model.PiActionId;
46import org.onosproject.net.pi.model.PiMatchFieldId;
47import org.onosproject.net.pi.model.PiTableId;
48import org.onosproject.net.pi.runtime.PiAction;
49import org.onosproject.net.pi.runtime.PiActionParam;
50import org.slf4j.Logger;
51
Jonghwan Hyun722275f2018-05-14 15:44:56 -070052import java.util.Set;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070053import java.util.stream.Collectors;
Carmelo Casconefa421582018-09-13 10:05:57 -070054import java.util.stream.StreamSupport;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070055
56import static org.slf4j.LoggerFactory.getLogger;
57
58public class IntProgrammableImpl extends AbstractHandlerBehaviour implements IntProgrammable {
59
60 // TODO: change this value to the value of diameter of a network.
61 private static final int MAXHOP = 64;
62 private static final int PORTMASK = 0xffff;
63 private static final int IDLE_TIMEOUT = 100;
64 private static final int PKT_INSTANCE_TYPE_INGRESS_CLONE = 1;
65 // Application name of the pipeline which adds this implementation to the pipeconf
66 private static final String PIPELINE_APP_NAME = "org.onosproject.pipelines.basic";
67 private final Logger log = getLogger(getClass());
68 private ApplicationId appId;
69
70 private static final Set<Criterion.Type> SUPPORTED_CRITERION = Sets.newHashSet(
71 Criterion.Type.IPV4_DST, Criterion.Type.IPV4_SRC,
72 Criterion.Type.UDP_SRC, Criterion.Type.UDP_DST,
73 Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
74 Criterion.Type.IP_PROTO);
75
Carmelo Casconefa421582018-09-13 10:05:57 -070076 private static final Set<PiTableId> TABLES_TO_CLEANUP = Sets.newHashSet(
77 IntConstants.TBL_INT_INSERT_ID,
78 IntConstants.TBL_INT_INST_0003_ID,
79 IntConstants.TBL_INT_INST_0407_ID,
80 IntConstants.TBL_SET_SOURCE_ID,
81 IntConstants.TBL_SET_SINK_ID,
82 IntConstants.TBL_INT_SOURCE_ID,
83 IntConstants.TBL_GENERATE_REPORT_ID);
84
Jonghwan Hyun722275f2018-05-14 15:44:56 -070085 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 private FlowRuleService flowRuleService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonghwan Hyun722275f2018-05-14 15:44:56 -070089 private CoreService coreService;
90
91 private DeviceId deviceId;
92 private static final int DEFAULT_PRIORITY = 10000;
93 private static final ImmutableBiMap<Integer, PiActionId> INST_0003_ACTION_MAP =
94 ImmutableBiMap.<Integer, PiActionId>builder()
95 .put(0, IntConstants.ACT_INT_SET_HEADER_0003_I0_ID)
96 .put(1, IntConstants.ACT_INT_SET_HEADER_0003_I1_ID)
97 .put(2, IntConstants.ACT_INT_SET_HEADER_0003_I2_ID)
98 .put(3, IntConstants.ACT_INT_SET_HEADER_0003_I3_ID)
99 .put(4, IntConstants.ACT_INT_SET_HEADER_0003_I4_ID)
100 .put(5, IntConstants.ACT_INT_SET_HEADER_0003_I5_ID)
101 .put(6, IntConstants.ACT_INT_SET_HEADER_0003_I6_ID)
102 .put(7, IntConstants.ACT_INT_SET_HEADER_0003_I7_ID)
103 .put(8, IntConstants.ACT_INT_SET_HEADER_0003_I8_ID)
104 .put(9, IntConstants.ACT_INT_SET_HEADER_0003_I9_ID)
105 .put(10, IntConstants.ACT_INT_SET_HEADER_0003_I10_ID)
106 .put(11, IntConstants.ACT_INT_SET_HEADER_0003_I11_ID)
107 .put(12, IntConstants.ACT_INT_SET_HEADER_0003_I12_ID)
108 .put(13, IntConstants.ACT_INT_SET_HEADER_0003_I13_ID)
109 .put(14, IntConstants.ACT_INT_SET_HEADER_0003_I14_ID)
110 .put(15, IntConstants.ACT_INT_SET_HEADER_0003_I15_ID)
111 .build();
112
113 private static final ImmutableBiMap<Integer, PiActionId> INST_0407_ACTION_MAP =
114 ImmutableBiMap.<Integer, PiActionId>builder()
115 .put(0, IntConstants.ACT_INT_SET_HEADER_0407_I0_ID)
116 .put(1, IntConstants.ACT_INT_SET_HEADER_0407_I1_ID)
117 .put(2, IntConstants.ACT_INT_SET_HEADER_0407_I2_ID)
118 .put(3, IntConstants.ACT_INT_SET_HEADER_0407_I3_ID)
119 .put(4, IntConstants.ACT_INT_SET_HEADER_0407_I4_ID)
120 .put(5, IntConstants.ACT_INT_SET_HEADER_0407_I5_ID)
121 .put(6, IntConstants.ACT_INT_SET_HEADER_0407_I6_ID)
122 .put(7, IntConstants.ACT_INT_SET_HEADER_0407_I7_ID)
123 .put(8, IntConstants.ACT_INT_SET_HEADER_0407_I8_ID)
124 .put(9, IntConstants.ACT_INT_SET_HEADER_0407_I9_ID)
125 .put(10, IntConstants.ACT_INT_SET_HEADER_0407_I10_ID)
126 .put(11, IntConstants.ACT_INT_SET_HEADER_0407_I11_ID)
127 .put(12, IntConstants.ACT_INT_SET_HEADER_0407_I12_ID)
128 .put(13, IntConstants.ACT_INT_SET_HEADER_0407_I13_ID)
129 .put(14, IntConstants.ACT_INT_SET_HEADER_0407_I14_ID)
130 .put(15, IntConstants.ACT_INT_SET_HEADER_0407_I15_ID)
131 .build();
132
133 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700134 public boolean init() {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700135 deviceId = this.data().deviceId();
136 flowRuleService = handler().get(FlowRuleService.class);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700137 coreService = handler().get(CoreService.class);
138 appId = coreService.getAppId(PIPELINE_APP_NAME);
139 if (appId == null) {
140 log.warn("Application ID is null. Cannot initialize INT-pipeline.");
Carmelo Casconefa421582018-09-13 10:05:57 -0700141 return false;
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700142 }
143
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700144 // process_int_transit.tb_int_insert
145 PiActionParam transitIdParam = new PiActionParam(
146 IntConstants.ACT_PRM_SWITCH_ID,
147 ImmutableByteSequence.copyFrom(
148 Integer.parseInt(deviceId.toString().substring(
149 deviceId.toString().length() - 2))));
150 PiAction transitAction = PiAction.builder()
151 .withId(IntConstants.ACT_INT_TRANSIT_ID)
152 .withParameter(transitIdParam)
153 .build();
154 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
155 .piTableAction(transitAction)
156 .build();
157
158 FlowRule transitFlowRule = DefaultFlowRule.builder()
159 .withTreatment(treatment)
160 .fromApp(appId)
161 .withPriority(DEFAULT_PRIORITY)
162 .makePermanent()
163 .forDevice(deviceId)
164 .forTable(IntConstants.TBL_INT_INSERT_ID)
165 .build();
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700166
Carmelo Casconefa421582018-09-13 10:05:57 -0700167 flowRuleService.applyFlowRules(transitFlowRule);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700168
169 // Populate tb_int_inst_0003 table
170 INST_0003_ACTION_MAP.forEach((matchValue, actionId) ->
171 populateInstTableEntry(IntConstants.TBL_INT_INST_0003_ID,
172 IntConstants.INT_HDR_INST_MASK_0003_ID,
173 matchValue,
174 actionId,
175 appId));
176 // Populate tb_int_inst_0407 table
177 INST_0407_ACTION_MAP.forEach((matchValue, actionId) ->
178 populateInstTableEntry(IntConstants.TBL_INT_INST_0407_ID,
179 IntConstants.INT_HDR_INST_MASK_0407_ID,
180 matchValue,
181 actionId,
182 appId));
Carmelo Casconefa421582018-09-13 10:05:57 -0700183
184 return true;
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700185 }
186
187 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700188 public boolean setSourcePort(PortNumber port) {
189 // process_set_source_sink.tb_set_source for each host-facing port
190 PiCriterion ingressCriterion = PiCriterion.builder()
191 .matchExact(BasicConstants.HDR_IN_PORT_ID, port.toLong())
192 .build();
193 TrafficSelector srcSelector = DefaultTrafficSelector.builder()
194 .matchPi(ingressCriterion)
195 .build();
196 PiAction setSourceAct = PiAction.builder()
197 .withId(IntConstants.ACT_INT_SET_SOURCE_ID)
198 .build();
199 TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
200 .piTableAction(setSourceAct)
201 .build();
202 FlowRule srcFlowRule = DefaultFlowRule.builder()
203 .withSelector(srcSelector)
204 .withTreatment(srcTreatment)
205 .fromApp(appId)
206 .withPriority(DEFAULT_PRIORITY)
207 .makePermanent()
208 .forDevice(deviceId)
209 .forTable(IntConstants.TBL_SET_SOURCE_ID)
210 .build();
211 flowRuleService.applyFlowRules(srcFlowRule);
212 return true;
213 }
214
215 @Override
216 public boolean setSinkPort(PortNumber port) {
217 // process_set_source_sink.tb_set_sink
218 PiCriterion egressCriterion = PiCriterion.builder()
219 .matchExact(IntConstants.HDR_OUT_PORT_ID, port.toLong())
220 .build();
221 TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
222 .matchPi(egressCriterion)
223 .build();
224 PiAction setSinkAct = PiAction.builder()
225 .withId(IntConstants.ACT_INT_SET_SINK_ID)
226 .build();
227 TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
228 .piTableAction(setSinkAct)
229 .build();
230 FlowRule sinkFlowRule = DefaultFlowRule.builder()
231 .withSelector(sinkSelector)
232 .withTreatment(sinkTreatment)
233 .fromApp(appId)
234 .withPriority(DEFAULT_PRIORITY)
235 .makePermanent()
236 .forDevice(deviceId)
237 .forTable(IntConstants.TBL_SET_SINK_ID)
238 .build();
239 flowRuleService.applyFlowRules(sinkFlowRule);
240 return true;
241 }
242
243 @Override
244 public boolean addIntObjective(IntObjective obj) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700245 // TODO: support different types of watchlist other than flow watchlist
246
Carmelo Casconefa421582018-09-13 10:05:57 -0700247 return processIntObjective(obj, true);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700248 }
249
250 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700251 public boolean removeIntObjective(IntObjective obj) {
252 return processIntObjective(obj, false);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700253 }
254
255 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700256 public boolean setupIntConfig(IntConfig config) {
257 return setupIntReportInternal(config);
258 }
259
260 @Override
261 public void cleanup() {
262 StreamSupport.stream(flowRuleService.getFlowEntries(
263 data().deviceId()).spliterator(), false)
264 .filter(f -> f.table().type() == TableId.Type.PIPELINE_INDEPENDENT)
265 .filter(f -> TABLES_TO_CLEANUP.contains((PiTableId) f.table()))
266 .forEach(flowRuleService::removeFlowRules);
267 }
268
269 @Override
270 public boolean supportsFunctionality(IntFunctionality functionality) {
271 switch (functionality) {
272 case SOURCE:
273 case SINK:
274 case TRANSIT:
275 return true;
276 default:
277 log.warn("Unknown functionality {}", functionality);
278 return false;
279 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700280 }
281
282 private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
283 int matchValue, PiActionId actionId, ApplicationId appId) {
284 PiCriterion instCriterion = PiCriterion.builder()
285 .matchExact(matchFieldId, matchValue)
286 .build();
287 TrafficSelector instSelector = DefaultTrafficSelector.builder()
288 .matchPi(instCriterion)
289 .build();
290 PiAction instAction = PiAction.builder()
291 .withId(actionId)
292 .build();
293 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
294 .piTableAction(instAction)
295 .build();
296
297 FlowRule instFlowRule = DefaultFlowRule.builder()
298 .withSelector(instSelector)
299 .withTreatment(instTreatment)
300 .withPriority(DEFAULT_PRIORITY)
301 .makePermanent()
302 .forDevice(deviceId)
303 .forTable(tableId)
304 .fromApp(appId)
305 .build();
306
307 flowRuleService.applyFlowRules(instFlowRule);
308 }
309
310 private FlowRule buildWatchlistEntry(IntObjective obj) {
311 coreService = handler().get(CoreService.class);
312 appId = coreService.getAppId(PIPELINE_APP_NAME);
313 if (appId == null) {
314 log.warn("Application ID is null. Cannot initialize INT-pipeline.");
315 return null;
316 }
317 int instructionBitmap = buildInstructionBitmap(obj.metadataTypes());
318 PiActionParam maxHopParam = new PiActionParam(
319 IntConstants.ACT_PRM_MAX_HOP_ID,
320 ImmutableByteSequence.copyFrom(MAXHOP));
321 PiActionParam instCntParam = new PiActionParam(
322 IntConstants.ACT_PRM_INS_CNT_ID,
323 ImmutableByteSequence.copyFrom(Integer.bitCount(instructionBitmap)));
324 PiActionParam inst0003Param = new PiActionParam(
325 IntConstants.ACT_PRM_INS_MASK0003_ID,
326 ImmutableByteSequence.copyFrom((instructionBitmap >> 12) & 0xF));
327 PiActionParam inst0407Param = new PiActionParam(
328 IntConstants.ACT_PRM_INS_MASK0407_ID,
329 ImmutableByteSequence.copyFrom((instructionBitmap >> 8) & 0xF));
330
331 PiAction intSourceAction = PiAction.builder()
332 .withId(IntConstants.ACT_INT_SOURCE_DSCP_ID)
333 .withParameter(maxHopParam)
334 .withParameter(instCntParam)
335 .withParameter(inst0003Param)
336 .withParameter(inst0407Param)
337 .build();
338
339 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
340 .piTableAction(intSourceAction)
341 .build();
342
343 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
344 for (Criterion criterion : obj.selector().criteria()) {
345 switch (criterion.type()) {
346 case IPV4_SRC:
347 sBuilder.matchIPSrc(((IPCriterion) criterion).ip());
348 break;
349 case IPV4_DST:
350 sBuilder.matchIPDst(((IPCriterion) criterion).ip());
351 break;
352 case TCP_SRC:
353 sBuilder.matchPi(
354 PiCriterion.builder().matchTernary(
355 IntConstants.LOCAL_META_SRC_PORT_ID,
356 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
357 .build());
358 break;
359 case UDP_SRC:
360 sBuilder.matchPi(
361 PiCriterion.builder().matchTernary(
362 IntConstants.LOCAL_META_SRC_PORT_ID,
363 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
364 .build());
365 break;
366 case TCP_DST:
367 sBuilder.matchPi(
368 PiCriterion.builder().matchTernary(
369 IntConstants.LOCAL_META_DST_PORT_ID,
370 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
371 .build());
372 break;
373 case UDP_DST:
374 sBuilder.matchPi(
375 PiCriterion.builder().matchTernary(
376 IntConstants.LOCAL_META_DST_PORT_ID,
377 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
378 .build());
379 break;
380 default:
381 log.warn("Unsupported criterion type: {}", criterion.type());
382 }
383 }
384
385 return DefaultFlowRule.builder()
386 .forDevice(this.data().deviceId())
387 .withSelector(sBuilder.build())
388 .withTreatment(instTreatment)
389 .withPriority(DEFAULT_PRIORITY)
390 .forTable(IntConstants.TBL_INT_SOURCE_ID)
391 .fromApp(appId)
392 .withIdleTimeout(IDLE_TIMEOUT)
393 .build();
394 }
395
396 private int buildInstructionBitmap(Set<IntIntent.IntMetadataType> metadataTypes) {
397 int instBitmap = 0;
398 for (IntIntent.IntMetadataType metadataType : metadataTypes) {
399 switch (metadataType) {
400 case SWITCH_ID:
401 instBitmap |= (1 << 15);
402 break;
403 case L1_PORT_ID:
404 instBitmap |= (1 << 14);
405 break;
406 case HOP_LATENCY:
407 instBitmap |= (1 << 13);
408 break;
409 case QUEUE_OCCUPANCY:
410 instBitmap |= (1 << 12);
411 break;
412 case INGRESS_TIMESTAMP:
413 instBitmap |= (1 << 11);
414 break;
415 case EGRESS_TIMESTAMP:
416 instBitmap |= (1 << 10);
417 break;
418 case L2_PORT_ID:
419 instBitmap |= (1 << 9);
420 break;
421 case EGRESS_TX_UTIL:
422 instBitmap |= (1 << 8);
423 break;
424 default:
425 log.info("Unsupported metadata type {}. Ignoring...", metadataType);
426 break;
427 }
428 }
429 return instBitmap;
430 }
431
432 /**
Carmelo Casconefa421582018-09-13 10:05:57 -0700433 * Returns a subset of Criterion from given selector, which is unsupported
434 * by this INT pipeline.
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700435 *
436 * @param selector a traffic selector
Carmelo Casconefa421582018-09-13 10:05:57 -0700437 * @return a subset of Criterion from given selector, unsupported by this
438 * INT pipeline, empty if all criteria are supported.
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700439 */
440 private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
441 return selector.criteria().stream()
442 .filter(criterion -> !SUPPORTED_CRITERION.contains(criterion.type()))
443 .collect(Collectors.toSet());
444 }
445
446 private boolean processIntObjective(IntObjective obj, boolean install) {
447 flowRuleService = handler().get(FlowRuleService.class);
448 deviceId = this.data().deviceId();
449 if (install && !unsupportedSelectors(obj.selector()).isEmpty()) {
450 log.warn("Device {} does not support criteria {} for INT.",
451 deviceId, unsupportedSelectors(obj.selector()));
452 return false;
453 }
454
455 FlowRule flowRule = buildWatchlistEntry(obj);
456 if (flowRule != null) {
457 if (install) {
458 flowRuleService.applyFlowRules(flowRule);
459 } else {
460 flowRuleService.removeFlowRules(flowRule);
461 }
462 log.debug("IntObjective {} has been {} {}",
463 obj, install ? "installed to" : "removed from", deviceId);
464 return true;
465 } else {
466 log.warn("Failed to {} IntObjective {} on {}",
467 install ? "install" : "remove", obj, deviceId);
468 return false;
469 }
470 }
471
472 private boolean setupIntReportInternal(IntConfig cfg) {
473 flowRuleService = handler().get(FlowRuleService.class);
474
475 FlowRule reportRule = buildReportEntry(cfg, PKT_INSTANCE_TYPE_INGRESS_CLONE);
476 if (reportRule != null) {
477 flowRuleService.applyFlowRules(reportRule);
478 log.info("Report entry {} has been added to {}", reportRule, this.data().deviceId());
479 return true;
480 } else {
481 log.warn("Failed to add report entry on {}", this.data().deviceId());
482 return false;
483 }
484 }
485
486 private FlowRule buildReportEntry(IntConfig cfg, int type) {
487 coreService = handler().get(CoreService.class);
488 appId = coreService.getAppId(PIPELINE_APP_NAME);
489 if (appId == null) {
490 log.warn("Application ID is null. Cannot build report entry.");
491 return null;
492 }
493
494 PiCriterion instTypeCriterion = PiCriterion.builder()
495 .matchExact(IntConstants.STD_META_INSTANCE_TYPE_ID, type)
496 .build();
497 TrafficSelector selector = DefaultTrafficSelector.builder()
498 .matchPi(instTypeCriterion)
499 .build();
500 PiActionParam srcMacParam = new PiActionParam(
501 IntConstants.ACT_PRM_SRC_MAC_ID,
502 ImmutableByteSequence.copyFrom(cfg.sinkMac().toBytes()));
503 PiActionParam nextHopMacParam = new PiActionParam(
504 IntConstants.ACT_PRM_MON_MAC_ID,
505 ImmutableByteSequence.copyFrom(cfg.collectorNextHopMac().toBytes()));
506 PiActionParam srcIpParam = new PiActionParam(
507 IntConstants.ACT_PRM_SRC_IP_ID,
508 ImmutableByteSequence.copyFrom(cfg.sinkIp().toOctets()));
509 PiActionParam monIpParam = new PiActionParam(
510 IntConstants.ACT_PRM_MON_IP_ID,
511 ImmutableByteSequence.copyFrom(cfg.collectorIp().toOctets()));
512 PiActionParam monPortParam = new PiActionParam(
513 IntConstants.ACT_PRM_MON_PORT_ID,
514 ImmutableByteSequence.copyFrom(cfg.collectorPort().toInt()));
515 PiAction reportAction = PiAction.builder()
516 .withId(IntConstants.ACT_DO_REPORT_ENCAP_ID)
517 .withParameter(srcMacParam)
518 .withParameter(nextHopMacParam)
519 .withParameter(srcIpParam)
520 .withParameter(monIpParam)
521 .withParameter(monPortParam)
522 .build();
523 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
524 .piTableAction(reportAction)
525 .build();
526
527 return DefaultFlowRule.builder()
528 .withSelector(selector)
529 .withTreatment(treatment)
530 .fromApp(appId)
531 .withPriority(DEFAULT_PRIORITY)
532 .makePermanent()
533 .forDevice(this.data().deviceId())
534 .forTable(IntConstants.TBL_GENERATE_REPORT_ID)
535 .build();
536 }
537
538}