blob: 6a363f27d1364231daf01f14d7149209507d0ace [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;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070020import org.osgi.service.component.annotations.Reference;
21import org.osgi.service.component.annotations.ReferenceCardinality;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070022import 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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070085 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonghwan Hyun722275f2018-05-14 15:44:56 -070086 private FlowRuleService flowRuleService;
87
Ray Milkeyd84f89b2018-08-17 14:54:17 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY)
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
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900133 private boolean setupBehaviour() {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700134 deviceId = this.data().deviceId();
135 flowRuleService = handler().get(FlowRuleService.class);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700136 coreService = handler().get(CoreService.class);
137 appId = coreService.getAppId(PIPELINE_APP_NAME);
138 if (appId == null) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900139 log.warn("Application ID is null. Cannot initialize behaviour.");
140 return false;
141 }
142 return true;
143 }
144
145 @Override
146 public boolean init() {
147 if (!setupBehaviour()) {
Carmelo Casconefa421582018-09-13 10:05:57 -0700148 return false;
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700149 }
150
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700151 // process_int_transit.tb_int_insert
152 PiActionParam transitIdParam = new PiActionParam(
153 IntConstants.ACT_PRM_SWITCH_ID,
154 ImmutableByteSequence.copyFrom(
155 Integer.parseInt(deviceId.toString().substring(
156 deviceId.toString().length() - 2))));
157 PiAction transitAction = PiAction.builder()
158 .withId(IntConstants.ACT_INT_TRANSIT_ID)
159 .withParameter(transitIdParam)
160 .build();
161 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
162 .piTableAction(transitAction)
163 .build();
164
165 FlowRule transitFlowRule = DefaultFlowRule.builder()
166 .withTreatment(treatment)
167 .fromApp(appId)
168 .withPriority(DEFAULT_PRIORITY)
169 .makePermanent()
170 .forDevice(deviceId)
171 .forTable(IntConstants.TBL_INT_INSERT_ID)
172 .build();
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700173
Carmelo Casconefa421582018-09-13 10:05:57 -0700174 flowRuleService.applyFlowRules(transitFlowRule);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700175
176 // Populate tb_int_inst_0003 table
177 INST_0003_ACTION_MAP.forEach((matchValue, actionId) ->
178 populateInstTableEntry(IntConstants.TBL_INT_INST_0003_ID,
179 IntConstants.INT_HDR_INST_MASK_0003_ID,
180 matchValue,
181 actionId,
182 appId));
183 // Populate tb_int_inst_0407 table
184 INST_0407_ACTION_MAP.forEach((matchValue, actionId) ->
185 populateInstTableEntry(IntConstants.TBL_INT_INST_0407_ID,
186 IntConstants.INT_HDR_INST_MASK_0407_ID,
187 matchValue,
188 actionId,
189 appId));
Carmelo Casconefa421582018-09-13 10:05:57 -0700190
191 return true;
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700192 }
193
194 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700195 public boolean setSourcePort(PortNumber port) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900196 if (!setupBehaviour()) {
197 return false;
198 }
199
Carmelo Casconefa421582018-09-13 10:05:57 -0700200 // process_set_source_sink.tb_set_source for each host-facing port
201 PiCriterion ingressCriterion = PiCriterion.builder()
202 .matchExact(BasicConstants.HDR_IN_PORT_ID, port.toLong())
203 .build();
204 TrafficSelector srcSelector = DefaultTrafficSelector.builder()
205 .matchPi(ingressCriterion)
206 .build();
207 PiAction setSourceAct = PiAction.builder()
208 .withId(IntConstants.ACT_INT_SET_SOURCE_ID)
209 .build();
210 TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
211 .piTableAction(setSourceAct)
212 .build();
213 FlowRule srcFlowRule = DefaultFlowRule.builder()
214 .withSelector(srcSelector)
215 .withTreatment(srcTreatment)
216 .fromApp(appId)
217 .withPriority(DEFAULT_PRIORITY)
218 .makePermanent()
219 .forDevice(deviceId)
220 .forTable(IntConstants.TBL_SET_SOURCE_ID)
221 .build();
222 flowRuleService.applyFlowRules(srcFlowRule);
223 return true;
224 }
225
226 @Override
227 public boolean setSinkPort(PortNumber port) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900228 if (!setupBehaviour()) {
229 return false;
230 }
231
Carmelo Casconefa421582018-09-13 10:05:57 -0700232 // process_set_source_sink.tb_set_sink
233 PiCriterion egressCriterion = PiCriterion.builder()
234 .matchExact(IntConstants.HDR_OUT_PORT_ID, port.toLong())
235 .build();
236 TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
237 .matchPi(egressCriterion)
238 .build();
239 PiAction setSinkAct = PiAction.builder()
240 .withId(IntConstants.ACT_INT_SET_SINK_ID)
241 .build();
242 TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
243 .piTableAction(setSinkAct)
244 .build();
245 FlowRule sinkFlowRule = DefaultFlowRule.builder()
246 .withSelector(sinkSelector)
247 .withTreatment(sinkTreatment)
248 .fromApp(appId)
249 .withPriority(DEFAULT_PRIORITY)
250 .makePermanent()
251 .forDevice(deviceId)
252 .forTable(IntConstants.TBL_SET_SINK_ID)
253 .build();
254 flowRuleService.applyFlowRules(sinkFlowRule);
255 return true;
256 }
257
258 @Override
259 public boolean addIntObjective(IntObjective obj) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700260 // TODO: support different types of watchlist other than flow watchlist
261
Carmelo Casconefa421582018-09-13 10:05:57 -0700262 return processIntObjective(obj, true);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700263 }
264
265 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700266 public boolean removeIntObjective(IntObjective obj) {
267 return processIntObjective(obj, false);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700268 }
269
270 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700271 public boolean setupIntConfig(IntConfig config) {
272 return setupIntReportInternal(config);
273 }
274
275 @Override
276 public void cleanup() {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900277 if (!setupBehaviour()) {
278 return;
279 }
280
Carmelo Casconefa421582018-09-13 10:05:57 -0700281 StreamSupport.stream(flowRuleService.getFlowEntries(
282 data().deviceId()).spliterator(), false)
283 .filter(f -> f.table().type() == TableId.Type.PIPELINE_INDEPENDENT)
284 .filter(f -> TABLES_TO_CLEANUP.contains((PiTableId) f.table()))
285 .forEach(flowRuleService::removeFlowRules);
286 }
287
288 @Override
289 public boolean supportsFunctionality(IntFunctionality functionality) {
290 switch (functionality) {
291 case SOURCE:
292 case SINK:
293 case TRANSIT:
294 return true;
295 default:
296 log.warn("Unknown functionality {}", functionality);
297 return false;
298 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700299 }
300
301 private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
302 int matchValue, PiActionId actionId, ApplicationId appId) {
303 PiCriterion instCriterion = PiCriterion.builder()
304 .matchExact(matchFieldId, matchValue)
305 .build();
306 TrafficSelector instSelector = DefaultTrafficSelector.builder()
307 .matchPi(instCriterion)
308 .build();
309 PiAction instAction = PiAction.builder()
310 .withId(actionId)
311 .build();
312 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
313 .piTableAction(instAction)
314 .build();
315
316 FlowRule instFlowRule = DefaultFlowRule.builder()
317 .withSelector(instSelector)
318 .withTreatment(instTreatment)
319 .withPriority(DEFAULT_PRIORITY)
320 .makePermanent()
321 .forDevice(deviceId)
322 .forTable(tableId)
323 .fromApp(appId)
324 .build();
325
326 flowRuleService.applyFlowRules(instFlowRule);
327 }
328
329 private FlowRule buildWatchlistEntry(IntObjective obj) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700330 int instructionBitmap = buildInstructionBitmap(obj.metadataTypes());
331 PiActionParam maxHopParam = new PiActionParam(
332 IntConstants.ACT_PRM_MAX_HOP_ID,
333 ImmutableByteSequence.copyFrom(MAXHOP));
334 PiActionParam instCntParam = new PiActionParam(
335 IntConstants.ACT_PRM_INS_CNT_ID,
336 ImmutableByteSequence.copyFrom(Integer.bitCount(instructionBitmap)));
337 PiActionParam inst0003Param = new PiActionParam(
338 IntConstants.ACT_PRM_INS_MASK0003_ID,
339 ImmutableByteSequence.copyFrom((instructionBitmap >> 12) & 0xF));
340 PiActionParam inst0407Param = new PiActionParam(
341 IntConstants.ACT_PRM_INS_MASK0407_ID,
342 ImmutableByteSequence.copyFrom((instructionBitmap >> 8) & 0xF));
343
344 PiAction intSourceAction = PiAction.builder()
345 .withId(IntConstants.ACT_INT_SOURCE_DSCP_ID)
346 .withParameter(maxHopParam)
347 .withParameter(instCntParam)
348 .withParameter(inst0003Param)
349 .withParameter(inst0407Param)
350 .build();
351
352 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
353 .piTableAction(intSourceAction)
354 .build();
355
356 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
357 for (Criterion criterion : obj.selector().criteria()) {
358 switch (criterion.type()) {
359 case IPV4_SRC:
360 sBuilder.matchIPSrc(((IPCriterion) criterion).ip());
361 break;
362 case IPV4_DST:
363 sBuilder.matchIPDst(((IPCriterion) criterion).ip());
364 break;
365 case TCP_SRC:
366 sBuilder.matchPi(
367 PiCriterion.builder().matchTernary(
368 IntConstants.LOCAL_META_SRC_PORT_ID,
369 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
370 .build());
371 break;
372 case UDP_SRC:
373 sBuilder.matchPi(
374 PiCriterion.builder().matchTernary(
375 IntConstants.LOCAL_META_SRC_PORT_ID,
376 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
377 .build());
378 break;
379 case TCP_DST:
380 sBuilder.matchPi(
381 PiCriterion.builder().matchTernary(
382 IntConstants.LOCAL_META_DST_PORT_ID,
383 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
384 .build());
385 break;
386 case UDP_DST:
387 sBuilder.matchPi(
388 PiCriterion.builder().matchTernary(
389 IntConstants.LOCAL_META_DST_PORT_ID,
390 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
391 .build());
392 break;
393 default:
394 log.warn("Unsupported criterion type: {}", criterion.type());
395 }
396 }
397
398 return DefaultFlowRule.builder()
399 .forDevice(this.data().deviceId())
400 .withSelector(sBuilder.build())
401 .withTreatment(instTreatment)
402 .withPriority(DEFAULT_PRIORITY)
403 .forTable(IntConstants.TBL_INT_SOURCE_ID)
404 .fromApp(appId)
405 .withIdleTimeout(IDLE_TIMEOUT)
406 .build();
407 }
408
409 private int buildInstructionBitmap(Set<IntIntent.IntMetadataType> metadataTypes) {
410 int instBitmap = 0;
411 for (IntIntent.IntMetadataType metadataType : metadataTypes) {
412 switch (metadataType) {
413 case SWITCH_ID:
414 instBitmap |= (1 << 15);
415 break;
416 case L1_PORT_ID:
417 instBitmap |= (1 << 14);
418 break;
419 case HOP_LATENCY:
420 instBitmap |= (1 << 13);
421 break;
422 case QUEUE_OCCUPANCY:
423 instBitmap |= (1 << 12);
424 break;
425 case INGRESS_TIMESTAMP:
426 instBitmap |= (1 << 11);
427 break;
428 case EGRESS_TIMESTAMP:
429 instBitmap |= (1 << 10);
430 break;
431 case L2_PORT_ID:
432 instBitmap |= (1 << 9);
433 break;
434 case EGRESS_TX_UTIL:
435 instBitmap |= (1 << 8);
436 break;
437 default:
438 log.info("Unsupported metadata type {}. Ignoring...", metadataType);
439 break;
440 }
441 }
442 return instBitmap;
443 }
444
445 /**
Carmelo Casconefa421582018-09-13 10:05:57 -0700446 * Returns a subset of Criterion from given selector, which is unsupported
447 * by this INT pipeline.
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700448 *
449 * @param selector a traffic selector
Carmelo Casconefa421582018-09-13 10:05:57 -0700450 * @return a subset of Criterion from given selector, unsupported by this
451 * INT pipeline, empty if all criteria are supported.
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700452 */
453 private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
454 return selector.criteria().stream()
455 .filter(criterion -> !SUPPORTED_CRITERION.contains(criterion.type()))
456 .collect(Collectors.toSet());
457 }
458
459 private boolean processIntObjective(IntObjective obj, boolean install) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900460 if (!setupBehaviour()) {
461 return false;
462 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700463 if (install && !unsupportedSelectors(obj.selector()).isEmpty()) {
464 log.warn("Device {} does not support criteria {} for INT.",
465 deviceId, unsupportedSelectors(obj.selector()));
466 return false;
467 }
468
469 FlowRule flowRule = buildWatchlistEntry(obj);
470 if (flowRule != null) {
471 if (install) {
472 flowRuleService.applyFlowRules(flowRule);
473 } else {
474 flowRuleService.removeFlowRules(flowRule);
475 }
476 log.debug("IntObjective {} has been {} {}",
477 obj, install ? "installed to" : "removed from", deviceId);
478 return true;
479 } else {
480 log.warn("Failed to {} IntObjective {} on {}",
481 install ? "install" : "remove", obj, deviceId);
482 return false;
483 }
484 }
485
486 private boolean setupIntReportInternal(IntConfig cfg) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900487 if (!setupBehaviour()) {
488 return false;
489 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700490
491 FlowRule reportRule = buildReportEntry(cfg, PKT_INSTANCE_TYPE_INGRESS_CLONE);
492 if (reportRule != null) {
493 flowRuleService.applyFlowRules(reportRule);
494 log.info("Report entry {} has been added to {}", reportRule, this.data().deviceId());
495 return true;
496 } else {
497 log.warn("Failed to add report entry on {}", this.data().deviceId());
498 return false;
499 }
500 }
501
502 private FlowRule buildReportEntry(IntConfig cfg, int type) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700503 PiCriterion instTypeCriterion = PiCriterion.builder()
504 .matchExact(IntConstants.STD_META_INSTANCE_TYPE_ID, type)
505 .build();
506 TrafficSelector selector = DefaultTrafficSelector.builder()
507 .matchPi(instTypeCriterion)
508 .build();
509 PiActionParam srcMacParam = new PiActionParam(
510 IntConstants.ACT_PRM_SRC_MAC_ID,
511 ImmutableByteSequence.copyFrom(cfg.sinkMac().toBytes()));
512 PiActionParam nextHopMacParam = new PiActionParam(
513 IntConstants.ACT_PRM_MON_MAC_ID,
514 ImmutableByteSequence.copyFrom(cfg.collectorNextHopMac().toBytes()));
515 PiActionParam srcIpParam = new PiActionParam(
516 IntConstants.ACT_PRM_SRC_IP_ID,
517 ImmutableByteSequence.copyFrom(cfg.sinkIp().toOctets()));
518 PiActionParam monIpParam = new PiActionParam(
519 IntConstants.ACT_PRM_MON_IP_ID,
520 ImmutableByteSequence.copyFrom(cfg.collectorIp().toOctets()));
521 PiActionParam monPortParam = new PiActionParam(
522 IntConstants.ACT_PRM_MON_PORT_ID,
523 ImmutableByteSequence.copyFrom(cfg.collectorPort().toInt()));
524 PiAction reportAction = PiAction.builder()
525 .withId(IntConstants.ACT_DO_REPORT_ENCAP_ID)
526 .withParameter(srcMacParam)
527 .withParameter(nextHopMacParam)
528 .withParameter(srcIpParam)
529 .withParameter(monIpParam)
530 .withParameter(monPortParam)
531 .build();
532 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
533 .piTableAction(reportAction)
534 .build();
535
536 return DefaultFlowRule.builder()
537 .withSelector(selector)
538 .withTreatment(treatment)
539 .fromApp(appId)
540 .withPriority(DEFAULT_PRIORITY)
541 .makePermanent()
542 .forDevice(this.data().deviceId())
543 .forTable(IntConstants.TBL_GENERATE_REPORT_ID)
544 .build();
545 }
546
547}