blob: 9a81e4c6c7a3bfbcbac7a8cd1cc1d32228b9b200 [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
Jonghwan Hyun722275f2018-05-14 15:44:56 -070018import com.google.common.collect.Sets;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070019import org.osgi.service.component.annotations.Reference;
20import org.osgi.service.component.annotations.ReferenceCardinality;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070021import org.onlab.util.ImmutableByteSequence;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070022import org.onosproject.core.ApplicationId;
23import org.onosproject.core.CoreService;
24import org.onosproject.inbandtelemetry.api.IntConfig;
25import org.onosproject.inbandtelemetry.api.IntIntent;
26import org.onosproject.inbandtelemetry.api.IntObjective;
27import org.onosproject.inbandtelemetry.api.IntProgrammable;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070028import org.onosproject.net.DeviceId;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070029import org.onosproject.net.PortNumber;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070030import org.onosproject.net.driver.AbstractHandlerBehaviour;
31import org.onosproject.net.flow.DefaultFlowRule;
32import org.onosproject.net.flow.DefaultTrafficSelector;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.FlowRule;
35import org.onosproject.net.flow.FlowRuleService;
Carmelo Casconefa421582018-09-13 10:05:57 -070036import org.onosproject.net.flow.TableId;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070037import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
39import org.onosproject.net.flow.criteria.Criterion;
40import org.onosproject.net.flow.criteria.IPCriterion;
41import org.onosproject.net.flow.criteria.PiCriterion;
42import org.onosproject.net.flow.criteria.TcpPortCriterion;
43import org.onosproject.net.flow.criteria.UdpPortCriterion;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070044import org.onosproject.net.pi.model.PiActionId;
45import org.onosproject.net.pi.model.PiMatchFieldId;
46import org.onosproject.net.pi.model.PiTableId;
47import org.onosproject.net.pi.runtime.PiAction;
48import org.onosproject.net.pi.runtime.PiActionParam;
49import org.slf4j.Logger;
50
Jonghwan Hyun722275f2018-05-14 15:44:56 -070051import java.util.Set;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070052import java.util.stream.Collectors;
Carmelo Casconefa421582018-09-13 10:05:57 -070053import java.util.stream.StreamSupport;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070054
55import static org.slf4j.LoggerFactory.getLogger;
56
57public class IntProgrammableImpl extends AbstractHandlerBehaviour implements IntProgrammable {
58
59 // TODO: change this value to the value of diameter of a network.
60 private static final int MAXHOP = 64;
61 private static final int PORTMASK = 0xffff;
62 private static final int IDLE_TIMEOUT = 100;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070063 // Application name of the pipeline which adds this implementation to the pipeconf
64 private static final String PIPELINE_APP_NAME = "org.onosproject.pipelines.basic";
65 private final Logger log = getLogger(getClass());
66 private ApplicationId appId;
67
68 private static final Set<Criterion.Type> SUPPORTED_CRITERION = Sets.newHashSet(
69 Criterion.Type.IPV4_DST, Criterion.Type.IPV4_SRC,
70 Criterion.Type.UDP_SRC, Criterion.Type.UDP_DST,
71 Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
72 Criterion.Type.IP_PROTO);
73
Carmelo Casconefa421582018-09-13 10:05:57 -070074 private static final Set<PiTableId> TABLES_TO_CLEANUP = Sets.newHashSet(
Jonghwan Hyunc235d462019-01-30 23:31:48 +090075 IntConstants.INGRESS_PROCESS_INT_SOURCE_TB_INT_SOURCE,
76 IntConstants.INGRESS_PROCESS_INT_SOURCE_SINK_TB_SET_SOURCE,
77 IntConstants.INGRESS_PROCESS_INT_SOURCE_SINK_TB_SET_SINK,
78 IntConstants.EGRESS_PROCESS_INT_TRANSIT_TB_INT_INSERT,
79 IntConstants.EGRESS_PROCESS_INT_REPORT_TB_GENERATE_REPORT);
Carmelo Casconefa421582018-09-13 10:05:57 -070080
Ray Milkeyd84f89b2018-08-17 14:54:17 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonghwan Hyun722275f2018-05-14 15:44:56 -070082 private FlowRuleService flowRuleService;
83
Ray Milkeyd84f89b2018-08-17 14:54:17 -070084 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonghwan Hyun722275f2018-05-14 15:44:56 -070085 private CoreService coreService;
86
87 private DeviceId deviceId;
88 private static final int DEFAULT_PRIORITY = 10000;
Jonghwan Hyun722275f2018-05-14 15:44:56 -070089
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +090090 private boolean setupBehaviour() {
Jonghwan Hyun722275f2018-05-14 15:44:56 -070091 deviceId = this.data().deviceId();
92 flowRuleService = handler().get(FlowRuleService.class);
Jonghwan Hyun722275f2018-05-14 15:44:56 -070093 coreService = handler().get(CoreService.class);
94 appId = coreService.getAppId(PIPELINE_APP_NAME);
95 if (appId == null) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +090096 log.warn("Application ID is null. Cannot initialize behaviour.");
97 return false;
98 }
99 return true;
100 }
101
102 @Override
103 public boolean init() {
104 if (!setupBehaviour()) {
Carmelo Casconefa421582018-09-13 10:05:57 -0700105 return false;
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700106 }
107
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700108 PiActionParam transitIdParam = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900109 IntConstants.SWITCH_ID,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700110 ImmutableByteSequence.copyFrom(
111 Integer.parseInt(deviceId.toString().substring(
112 deviceId.toString().length() - 2))));
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900113 TrafficSelector selector = DefaultTrafficSelector.builder()
114 .matchPi(PiCriterion.builder().matchExact(
115 IntConstants.HDR_INT_IS_VALID, (byte) 0x01)
116 .build())
117 .build();
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700118 PiAction transitAction = PiAction.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900119 .withId(IntConstants.EGRESS_PROCESS_INT_TRANSIT_INIT_METADATA)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700120 .withParameter(transitIdParam)
121 .build();
122 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
123 .piTableAction(transitAction)
124 .build();
125
126 FlowRule transitFlowRule = DefaultFlowRule.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900127 .withSelector(selector)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700128 .withTreatment(treatment)
129 .fromApp(appId)
130 .withPriority(DEFAULT_PRIORITY)
131 .makePermanent()
132 .forDevice(deviceId)
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900133 .forTable(IntConstants.EGRESS_PROCESS_INT_TRANSIT_TB_INT_INSERT)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700134 .build();
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700135
Carmelo Casconefa421582018-09-13 10:05:57 -0700136 flowRuleService.applyFlowRules(transitFlowRule);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700137
Carmelo Casconefa421582018-09-13 10:05:57 -0700138 return true;
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700139 }
140
141 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700142 public boolean setSourcePort(PortNumber port) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900143 if (!setupBehaviour()) {
144 return false;
145 }
146
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900147 // process_int_source_sink.tb_set_source for each host-facing port
Carmelo Casconefa421582018-09-13 10:05:57 -0700148 PiCriterion ingressCriterion = PiCriterion.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900149 .matchExact(IntConstants.HDR_STANDARD_METADATA_INGRESS_PORT, port.toLong())
Carmelo Casconefa421582018-09-13 10:05:57 -0700150 .build();
151 TrafficSelector srcSelector = DefaultTrafficSelector.builder()
152 .matchPi(ingressCriterion)
153 .build();
154 PiAction setSourceAct = PiAction.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900155 .withId(IntConstants.INGRESS_PROCESS_INT_SOURCE_SINK_INT_SET_SOURCE)
Carmelo Casconefa421582018-09-13 10:05:57 -0700156 .build();
157 TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
158 .piTableAction(setSourceAct)
159 .build();
160 FlowRule srcFlowRule = DefaultFlowRule.builder()
161 .withSelector(srcSelector)
162 .withTreatment(srcTreatment)
163 .fromApp(appId)
164 .withPriority(DEFAULT_PRIORITY)
165 .makePermanent()
166 .forDevice(deviceId)
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900167 .forTable(IntConstants.INGRESS_PROCESS_INT_SOURCE_SINK_TB_SET_SOURCE)
Carmelo Casconefa421582018-09-13 10:05:57 -0700168 .build();
169 flowRuleService.applyFlowRules(srcFlowRule);
170 return true;
171 }
172
173 @Override
174 public boolean setSinkPort(PortNumber port) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900175 if (!setupBehaviour()) {
176 return false;
177 }
178
Carmelo Casconefa421582018-09-13 10:05:57 -0700179 // process_set_source_sink.tb_set_sink
180 PiCriterion egressCriterion = PiCriterion.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900181 .matchExact(IntConstants.HDR_STANDARD_METADATA_EGRESS_SPEC, port.toLong())
Carmelo Casconefa421582018-09-13 10:05:57 -0700182 .build();
183 TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
184 .matchPi(egressCriterion)
185 .build();
186 PiAction setSinkAct = PiAction.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900187 .withId(IntConstants.INGRESS_PROCESS_INT_SOURCE_SINK_INT_SET_SINK)
Carmelo Casconefa421582018-09-13 10:05:57 -0700188 .build();
189 TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
190 .piTableAction(setSinkAct)
191 .build();
192 FlowRule sinkFlowRule = DefaultFlowRule.builder()
193 .withSelector(sinkSelector)
194 .withTreatment(sinkTreatment)
195 .fromApp(appId)
196 .withPriority(DEFAULT_PRIORITY)
197 .makePermanent()
198 .forDevice(deviceId)
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900199 .forTable(IntConstants.INGRESS_PROCESS_INT_SOURCE_SINK_TB_SET_SINK)
Carmelo Casconefa421582018-09-13 10:05:57 -0700200 .build();
201 flowRuleService.applyFlowRules(sinkFlowRule);
202 return true;
203 }
204
205 @Override
206 public boolean addIntObjective(IntObjective obj) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700207 // TODO: support different types of watchlist other than flow watchlist
208
Carmelo Casconefa421582018-09-13 10:05:57 -0700209 return processIntObjective(obj, true);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700210 }
211
212 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700213 public boolean removeIntObjective(IntObjective obj) {
214 return processIntObjective(obj, false);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700215 }
216
217 @Override
Carmelo Casconefa421582018-09-13 10:05:57 -0700218 public boolean setupIntConfig(IntConfig config) {
219 return setupIntReportInternal(config);
220 }
221
222 @Override
223 public void cleanup() {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900224 if (!setupBehaviour()) {
225 return;
226 }
227
Carmelo Casconefa421582018-09-13 10:05:57 -0700228 StreamSupport.stream(flowRuleService.getFlowEntries(
229 data().deviceId()).spliterator(), false)
230 .filter(f -> f.table().type() == TableId.Type.PIPELINE_INDEPENDENT)
231 .filter(f -> TABLES_TO_CLEANUP.contains((PiTableId) f.table()))
232 .forEach(flowRuleService::removeFlowRules);
233 }
234
235 @Override
236 public boolean supportsFunctionality(IntFunctionality functionality) {
237 switch (functionality) {
238 case SOURCE:
239 case SINK:
240 case TRANSIT:
241 return true;
242 default:
243 log.warn("Unknown functionality {}", functionality);
244 return false;
245 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700246 }
247
248 private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
249 int matchValue, PiActionId actionId, ApplicationId appId) {
250 PiCriterion instCriterion = PiCriterion.builder()
251 .matchExact(matchFieldId, matchValue)
252 .build();
253 TrafficSelector instSelector = DefaultTrafficSelector.builder()
254 .matchPi(instCriterion)
255 .build();
256 PiAction instAction = PiAction.builder()
257 .withId(actionId)
258 .build();
259 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
260 .piTableAction(instAction)
261 .build();
262
263 FlowRule instFlowRule = DefaultFlowRule.builder()
264 .withSelector(instSelector)
265 .withTreatment(instTreatment)
266 .withPriority(DEFAULT_PRIORITY)
267 .makePermanent()
268 .forDevice(deviceId)
269 .forTable(tableId)
270 .fromApp(appId)
271 .build();
272
273 flowRuleService.applyFlowRules(instFlowRule);
274 }
275
276 private FlowRule buildWatchlistEntry(IntObjective obj) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700277 int instructionBitmap = buildInstructionBitmap(obj.metadataTypes());
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900278 PiActionParam hopMetaLenParam = new PiActionParam(
279 IntConstants.HOP_METADATA_LEN,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700280 ImmutableByteSequence.copyFrom(Integer.bitCount(instructionBitmap)));
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900281 PiActionParam hopCntParam = new PiActionParam(
282 IntConstants.REMAINING_HOP_CNT,
283 ImmutableByteSequence.copyFrom(MAXHOP));
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700284 PiActionParam inst0003Param = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900285 IntConstants.INS_MASK0003,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700286 ImmutableByteSequence.copyFrom((instructionBitmap >> 12) & 0xF));
287 PiActionParam inst0407Param = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900288 IntConstants.INS_MASK0407,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700289 ImmutableByteSequence.copyFrom((instructionBitmap >> 8) & 0xF));
290
291 PiAction intSourceAction = PiAction.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900292 .withId(IntConstants.INGRESS_PROCESS_INT_SOURCE_INT_SOURCE_DSCP)
293 .withParameter(hopMetaLenParam)
294 .withParameter(hopCntParam)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700295 .withParameter(inst0003Param)
296 .withParameter(inst0407Param)
297 .build();
298
299 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
300 .piTableAction(intSourceAction)
301 .build();
302
303 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
304 for (Criterion criterion : obj.selector().criteria()) {
305 switch (criterion.type()) {
306 case IPV4_SRC:
307 sBuilder.matchIPSrc(((IPCriterion) criterion).ip());
308 break;
309 case IPV4_DST:
310 sBuilder.matchIPDst(((IPCriterion) criterion).ip());
311 break;
312 case TCP_SRC:
313 sBuilder.matchPi(
314 PiCriterion.builder().matchTernary(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900315 IntConstants.HDR_LOCAL_METADATA_L4_SRC_PORT,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700316 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
317 .build());
318 break;
319 case UDP_SRC:
320 sBuilder.matchPi(
321 PiCriterion.builder().matchTernary(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900322 IntConstants.HDR_LOCAL_METADATA_L4_SRC_PORT,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700323 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
324 .build());
325 break;
326 case TCP_DST:
327 sBuilder.matchPi(
328 PiCriterion.builder().matchTernary(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900329 IntConstants.HDR_LOCAL_METADATA_L4_DST_PORT,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700330 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
331 .build());
332 break;
333 case UDP_DST:
334 sBuilder.matchPi(
335 PiCriterion.builder().matchTernary(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900336 IntConstants.HDR_LOCAL_METADATA_L4_DST_PORT,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700337 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
338 .build());
339 break;
340 default:
341 log.warn("Unsupported criterion type: {}", criterion.type());
342 }
343 }
344
345 return DefaultFlowRule.builder()
346 .forDevice(this.data().deviceId())
347 .withSelector(sBuilder.build())
348 .withTreatment(instTreatment)
349 .withPriority(DEFAULT_PRIORITY)
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900350 .forTable(IntConstants.INGRESS_PROCESS_INT_SOURCE_TB_INT_SOURCE)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700351 .fromApp(appId)
352 .withIdleTimeout(IDLE_TIMEOUT)
353 .build();
354 }
355
356 private int buildInstructionBitmap(Set<IntIntent.IntMetadataType> metadataTypes) {
357 int instBitmap = 0;
358 for (IntIntent.IntMetadataType metadataType : metadataTypes) {
359 switch (metadataType) {
360 case SWITCH_ID:
361 instBitmap |= (1 << 15);
362 break;
363 case L1_PORT_ID:
364 instBitmap |= (1 << 14);
365 break;
366 case HOP_LATENCY:
367 instBitmap |= (1 << 13);
368 break;
369 case QUEUE_OCCUPANCY:
370 instBitmap |= (1 << 12);
371 break;
372 case INGRESS_TIMESTAMP:
373 instBitmap |= (1 << 11);
374 break;
375 case EGRESS_TIMESTAMP:
376 instBitmap |= (1 << 10);
377 break;
378 case L2_PORT_ID:
379 instBitmap |= (1 << 9);
380 break;
381 case EGRESS_TX_UTIL:
382 instBitmap |= (1 << 8);
383 break;
384 default:
385 log.info("Unsupported metadata type {}. Ignoring...", metadataType);
386 break;
387 }
388 }
389 return instBitmap;
390 }
391
392 /**
Carmelo Casconefa421582018-09-13 10:05:57 -0700393 * Returns a subset of Criterion from given selector, which is unsupported
394 * by this INT pipeline.
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700395 *
396 * @param selector a traffic selector
Carmelo Casconefa421582018-09-13 10:05:57 -0700397 * @return a subset of Criterion from given selector, unsupported by this
398 * INT pipeline, empty if all criteria are supported.
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700399 */
400 private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
401 return selector.criteria().stream()
402 .filter(criterion -> !SUPPORTED_CRITERION.contains(criterion.type()))
403 .collect(Collectors.toSet());
404 }
405
406 private boolean processIntObjective(IntObjective obj, boolean install) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900407 if (!setupBehaviour()) {
408 return false;
409 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700410 if (install && !unsupportedSelectors(obj.selector()).isEmpty()) {
411 log.warn("Device {} does not support criteria {} for INT.",
412 deviceId, unsupportedSelectors(obj.selector()));
413 return false;
414 }
415
416 FlowRule flowRule = buildWatchlistEntry(obj);
417 if (flowRule != null) {
418 if (install) {
419 flowRuleService.applyFlowRules(flowRule);
420 } else {
421 flowRuleService.removeFlowRules(flowRule);
422 }
423 log.debug("IntObjective {} has been {} {}",
424 obj, install ? "installed to" : "removed from", deviceId);
425 return true;
426 } else {
427 log.warn("Failed to {} IntObjective {} on {}",
428 install ? "install" : "remove", obj, deviceId);
429 return false;
430 }
431 }
432
433 private boolean setupIntReportInternal(IntConfig cfg) {
Jonghwan Hyun435ec7b2018-11-13 16:42:00 +0900434 if (!setupBehaviour()) {
435 return false;
436 }
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700437
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900438 FlowRule reportRule = buildReportEntry(cfg);
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700439 if (reportRule != null) {
440 flowRuleService.applyFlowRules(reportRule);
441 log.info("Report entry {} has been added to {}", reportRule, this.data().deviceId());
442 return true;
443 } else {
444 log.warn("Failed to add report entry on {}", this.data().deviceId());
445 return false;
446 }
447 }
448
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900449 private FlowRule buildReportEntry(IntConfig cfg) {
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700450 TrafficSelector selector = DefaultTrafficSelector.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900451 .matchPi(PiCriterion.builder().matchExact(
452 IntConstants.HDR_INT_IS_VALID, (byte) 0x01)
453 .build())
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700454 .build();
455 PiActionParam srcMacParam = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900456 IntConstants.SRC_MAC,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700457 ImmutableByteSequence.copyFrom(cfg.sinkMac().toBytes()));
458 PiActionParam nextHopMacParam = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900459 IntConstants.MON_MAC,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700460 ImmutableByteSequence.copyFrom(cfg.collectorNextHopMac().toBytes()));
461 PiActionParam srcIpParam = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900462 IntConstants.SRC_IP,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700463 ImmutableByteSequence.copyFrom(cfg.sinkIp().toOctets()));
464 PiActionParam monIpParam = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900465 IntConstants.MON_IP,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700466 ImmutableByteSequence.copyFrom(cfg.collectorIp().toOctets()));
467 PiActionParam monPortParam = new PiActionParam(
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900468 IntConstants.MON_PORT,
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700469 ImmutableByteSequence.copyFrom(cfg.collectorPort().toInt()));
470 PiAction reportAction = PiAction.builder()
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900471 .withId(IntConstants.EGRESS_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700472 .withParameter(srcMacParam)
473 .withParameter(nextHopMacParam)
474 .withParameter(srcIpParam)
475 .withParameter(monIpParam)
476 .withParameter(monPortParam)
477 .build();
478 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
479 .piTableAction(reportAction)
480 .build();
481
482 return DefaultFlowRule.builder()
483 .withSelector(selector)
484 .withTreatment(treatment)
485 .fromApp(appId)
486 .withPriority(DEFAULT_PRIORITY)
487 .makePermanent()
488 .forDevice(this.data().deviceId())
Jonghwan Hyunc235d462019-01-30 23:31:48 +0900489 .forTable(IntConstants.EGRESS_PROCESS_INT_REPORT_TB_GENERATE_REPORT)
Jonghwan Hyun722275f2018-05-14 15:44:56 -0700490 .build();
491 }
492
493}