blob: 5d95abdbad4f2ec1aa23c232e479bfb5b96fa57c [file] [log] [blame]
Jonghwan Hyuned478dc2018-08-06 15:35:18 +09001/*
2 * Copyright 2017-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.fabric;
17
18import com.google.common.collect.ImmutableBiMap;
19import com.google.common.collect.Sets;
Jonghwan Hyuned478dc2018-08-06 15:35:18 +090020import org.onlab.util.ImmutableByteSequence;
21import org.onlab.util.SharedExecutors;
22import 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;
28import org.onosproject.net.ConnectPoint;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.Port;
31import org.onosproject.net.PortNumber;
32import org.onosproject.net.device.DeviceService;
33import org.onosproject.net.driver.AbstractHandlerBehaviour;
34import org.onosproject.net.flow.DefaultFlowRule;
35import org.onosproject.net.flow.DefaultTrafficSelector;
36import org.onosproject.net.flow.DefaultTrafficTreatment;
37import org.onosproject.net.flow.FlowRule;
38import org.onosproject.net.flow.FlowRuleService;
39import org.onosproject.net.flow.TrafficSelector;
40import org.onosproject.net.flow.TrafficTreatment;
41import org.onosproject.net.flow.criteria.Criterion;
42import org.onosproject.net.flow.criteria.IPCriterion;
43import org.onosproject.net.flow.criteria.PiCriterion;
44import org.onosproject.net.flow.criteria.TcpPortCriterion;
45import org.onosproject.net.flow.criteria.UdpPortCriterion;
46import org.onosproject.net.host.HostService;
47import org.onosproject.net.pi.model.PiActionId;
48import org.onosproject.net.pi.model.PiMatchFieldId;
49import org.onosproject.net.pi.model.PiTableId;
50import org.onosproject.net.pi.runtime.PiAction;
51import org.onosproject.net.pi.runtime.PiActionParam;
52import org.slf4j.Logger;
53
54import java.util.ArrayList;
55import java.util.List;
56import java.util.Set;
57import java.util.concurrent.CompletableFuture;
58import java.util.stream.Collectors;
59
60import static org.slf4j.LoggerFactory.getLogger;
61
62public class IntProgrammableImpl extends AbstractHandlerBehaviour implements IntProgrammable {
63 // TODO: change this value to the value of diameter of a network.
64 private static final int MAXHOP = 64;
65 private static final int PORTMASK = 0xffff;
66 private static final int IDLE_TIMEOUT = 100;
67 private static final int PKT_INSTANCE_TYPE_INGRESS_CLONE = 1;
68 // Application name of the pipeline which adds this implementation to the pipeconf
69 private static final String PIPELINE_APP_NAME = "org.onosproject.pipelines.fabric";
70 private final Logger log = getLogger(getClass());
71 private ApplicationId appId;
72
73 private static final Set<Criterion.Type> SUPPORTED_CRITERION = Sets.newHashSet(
74 Criterion.Type.IPV4_DST, Criterion.Type.IPV4_SRC,
75 Criterion.Type.UDP_SRC, Criterion.Type.UDP_DST,
76 Criterion.Type.TCP_SRC, Criterion.Type.TCP_DST,
77 Criterion.Type.IP_PROTO);
78
Jonghwan Hyuned478dc2018-08-06 15:35:18 +090079 private FlowRuleService flowRuleService;
Jonghwan Hyuned478dc2018-08-06 15:35:18 +090080 private HostService hostService;
Jonghwan Hyuned478dc2018-08-06 15:35:18 +090081 private CoreService coreService;
82
83 private DeviceId deviceId;
84 private static final int DEFAULT_PRIORITY = 10000;
85 private static final ImmutableBiMap<Integer, PiActionId> INST_0003_ACTION_MAP =
86 ImmutableBiMap.<Integer, PiActionId>builder()
Carmelo Cascone79a3a312018-08-16 17:14:43 -070087 .put(0, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I0)
88 .put(1, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I1)
89 .put(2, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I2)
90 .put(3, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I3)
91 .put(4, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I4)
92 .put(5, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I5)
93 .put(6, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I6)
94 .put(7, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I7)
95 .put(8, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I8)
96 .put(9, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I9)
97 .put(10, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I10)
98 .put(11, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I11)
99 .put(12, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I12)
100 .put(13, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I13)
101 .put(14, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I14)
102 .put(15, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0003_I15)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900103 .build();
104
105 private static final ImmutableBiMap<Integer, PiActionId> INST_0407_ACTION_MAP =
106 ImmutableBiMap.<Integer, PiActionId>builder()
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700107 .put(0, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I0)
108 .put(1, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I1)
109 .put(2, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I2)
110 .put(3, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I3)
111 .put(4, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I4)
112 .put(5, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I5)
113 .put(6, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I6)
114 .put(7, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I7)
115 .put(8, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I8)
116 .put(9, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I9)
117 .put(10, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I10)
118 .put(11, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I11)
119 .put(12, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I12)
120 .put(13, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I13)
121 .put(14, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I14)
122 .put(15, FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INT_SET_HEADER_0407_I15)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900123 .build();
124
125 @Override
126 public void init() {
127 deviceId = this.data().deviceId();
128 flowRuleService = handler().get(FlowRuleService.class);
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700129 DeviceService deviceService = handler().get(DeviceService.class);
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900130 hostService = handler().get(HostService.class);
131 coreService = handler().get(CoreService.class);
132 appId = coreService.getAppId(PIPELINE_APP_NAME);
133 if (appId == null) {
134 log.warn("Application ID is null. Cannot initialize INT-pipeline.");
135 return;
136 }
137
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700138 Set<PortNumber> hostPorts = deviceService.getPorts(deviceId).stream()
139 .filter(port -> hostService.getConnectedHosts(
140 new ConnectPoint(deviceId, port.number())).size() > 0
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900141 ).map(Port::number).collect(Collectors.toSet());
142 List<FlowRule> flowRules = new ArrayList<>();
143
144 // process_int_transit.tb_int_insert
145 PiActionParam transitIdParam = new PiActionParam(
146 FabricConstants.SWITCH_ID,
147 ImmutableByteSequence.copyFrom(
148 Integer.parseInt(deviceId.toString().substring(
149 deviceId.toString().length() - 2))));
150 PiAction transitAction = PiAction.builder()
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700151 .withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_INIT_METADATA)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900152 .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)
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700164 .forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INSERT)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900165 .build();
166 flowRules.add(transitFlowRule);
167
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700168 for (PortNumber portNumber : hostPorts) {
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900169 // process_set_source_sink.tb_set_source for each host-facing port
170 PiCriterion ingressCriterion = PiCriterion.builder()
171 .matchExact(FabricConstants.STANDARD_METADATA_INGRESS_PORT, portNumber.toLong())
172 .build();
173 TrafficSelector srcSelector = DefaultTrafficSelector.builder()
174 .matchPi(ingressCriterion)
175 .build();
176 PiAction setSourceAct = PiAction.builder()
177 .withId(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SOURCE)
178 .build();
179 TrafficTreatment srcTreatment = DefaultTrafficTreatment.builder()
180 .piTableAction(setSourceAct)
181 .build();
182 FlowRule srcFlowRule = DefaultFlowRule.builder()
183 .withSelector(srcSelector)
184 .withTreatment(srcTreatment)
185 .fromApp(appId)
186 .withPriority(DEFAULT_PRIORITY)
187 .makePermanent()
188 .forDevice(deviceId)
189 .forTable(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SOURCE)
190 .build();
191 flowRules.add(srcFlowRule);
192
193 // process_set_source_sink.tb_set_sink
194 PiCriterion egressCriterion = PiCriterion.builder()
195 .matchExact(FabricConstants.STANDARD_METADATA_EGRESS_PORT, portNumber.toLong())
196 .build();
197 TrafficSelector sinkSelector = DefaultTrafficSelector.builder()
198 .matchPi(egressCriterion)
199 .build();
200 PiAction setSinkAct = PiAction.builder()
201 .withId(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_INT_SET_SINK)
202 .build();
203 TrafficTreatment sinkTreatment = DefaultTrafficTreatment.builder()
204 .piTableAction(setSinkAct)
205 .build();
206 FlowRule sinkFlowRule = DefaultFlowRule.builder()
207 .withSelector(sinkSelector)
208 .withTreatment(sinkTreatment)
209 .fromApp(appId)
210 .withPriority(DEFAULT_PRIORITY)
211 .makePermanent()
212 .forDevice(deviceId)
213 .forTable(FabricConstants.FABRIC_INGRESS_PROCESS_SET_SOURCE_SINK_TB_SET_SINK)
214 .build();
215 flowRules.add(sinkFlowRule);
216 }
217 flowRules.forEach(flowRule -> flowRuleService.applyFlowRules(flowRule));
218
219 // Populate tb_int_inst_0003 table
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700220 INST_0003_ACTION_MAP.forEach((matchValue, actionId) -> populateInstTableEntry(
221 FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INST_0003,
222 FabricConstants.HDR_INT_HEADER_INSTRUCTION_MASK_0003,
223 matchValue,
224 actionId,
225 appId));
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900226 // Populate tb_int_inst_0407 table
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700227 INST_0407_ACTION_MAP.forEach((matchValue, actionId) -> populateInstTableEntry(
228 FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_TRANSIT_TB_INT_INST_0407,
229 FabricConstants.HDR_INT_HEADER_INSTRUCTION_MASK_0407,
230 matchValue,
231 actionId,
232 appId));
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900233 }
234
235 @Override
236 public CompletableFuture<Boolean> addIntObjective(IntObjective obj) {
237 // TODO: support different types of watchlist other than flow watchlist
238
239 return CompletableFuture.supplyAsync(
240 () -> processIntObjective(obj, true),
241 SharedExecutors.getPoolThreadExecutor()
242 );
243 }
244
245 @Override
246 public CompletableFuture<Boolean> removeIntObjective(IntObjective obj) {
247 return CompletableFuture.supplyAsync(
248 () -> processIntObjective(obj, false),
249 SharedExecutors.getPoolThreadExecutor()
250 );
251 }
252
253 @Override
254 public CompletableFuture<Boolean> setupIntConfig(IntConfig config) {
255 return CompletableFuture.supplyAsync(
256 () -> setupIntReportInternal(config),
257 SharedExecutors.getPoolThreadExecutor()
258 );
259 }
260
261 private void populateInstTableEntry(PiTableId tableId, PiMatchFieldId matchFieldId,
262 int matchValue, PiActionId actionId, ApplicationId appId) {
263 PiCriterion instCriterion = PiCriterion.builder()
264 .matchExact(matchFieldId, matchValue)
265 .build();
266 TrafficSelector instSelector = DefaultTrafficSelector.builder()
267 .matchPi(instCriterion)
268 .build();
269 PiAction instAction = PiAction.builder()
270 .withId(actionId)
271 .build();
272 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
273 .piTableAction(instAction)
274 .build();
275
276 FlowRule instFlowRule = DefaultFlowRule.builder()
277 .withSelector(instSelector)
278 .withTreatment(instTreatment)
279 .withPriority(DEFAULT_PRIORITY)
280 .makePermanent()
281 .forDevice(deviceId)
282 .forTable(tableId)
283 .fromApp(appId)
284 .build();
285
286 flowRuleService.applyFlowRules(instFlowRule);
287 }
288
289 private FlowRule buildWatchlistEntry(IntObjective obj) {
290 coreService = handler().get(CoreService.class);
291 appId = coreService.getAppId(PIPELINE_APP_NAME);
292 if (appId == null) {
293 log.warn("Application ID is null. Cannot initialize INT-pipeline.");
294 return null;
295 }
296 int instructionBitmap = buildInstructionBitmap(obj.metadataTypes());
297 PiActionParam maxHopParam = new PiActionParam(
298 FabricConstants.MAX_HOP,
299 ImmutableByteSequence.copyFrom(MAXHOP));
300 PiActionParam instCntParam = new PiActionParam(
301 FabricConstants.INS_CNT,
302 ImmutableByteSequence.copyFrom(Integer.bitCount(instructionBitmap)));
303 PiActionParam inst0003Param = new PiActionParam(
304 FabricConstants.INS_MASK0003,
305 ImmutableByteSequence.copyFrom((instructionBitmap >> 12) & 0xF));
306 PiActionParam inst0407Param = new PiActionParam(
307 FabricConstants.INS_MASK0407,
308 ImmutableByteSequence.copyFrom((instructionBitmap >> 8) & 0xF));
309
310 PiAction intSourceAction = PiAction.builder()
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700311 .withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_INT_SOURCE_DSCP)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900312 .withParameter(maxHopParam)
313 .withParameter(instCntParam)
314 .withParameter(inst0003Param)
315 .withParameter(inst0407Param)
316 .build();
317
318 TrafficTreatment instTreatment = DefaultTrafficTreatment.builder()
319 .piTableAction(intSourceAction)
320 .build();
321
322 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
323 for (Criterion criterion : obj.selector().criteria()) {
324 switch (criterion.type()) {
325 case IPV4_SRC:
326 sBuilder.matchIPSrc(((IPCriterion) criterion).ip());
327 break;
328 case IPV4_DST:
329 sBuilder.matchIPDst(((IPCriterion) criterion).ip());
330 break;
331 case TCP_SRC:
332 sBuilder.matchPi(
333 PiCriterion.builder().matchTernary(
334 FabricConstants.FABRIC_METADATA_L4_SRC_PORT,
335 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
336 .build());
337 break;
338 case UDP_SRC:
339 sBuilder.matchPi(
340 PiCriterion.builder().matchTernary(
341 FabricConstants.FABRIC_METADATA_L4_SRC_PORT,
342 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
343 .build());
344 break;
345 case TCP_DST:
346 sBuilder.matchPi(
347 PiCriterion.builder().matchTernary(
348 FabricConstants.FABRIC_METADATA_L4_DST_PORT,
349 ((TcpPortCriterion) criterion).tcpPort().toInt(), PORTMASK)
350 .build());
351 break;
352 case UDP_DST:
353 sBuilder.matchPi(
354 PiCriterion.builder().matchTernary(
355 FabricConstants.FABRIC_METADATA_L4_DST_PORT,
356 ((UdpPortCriterion) criterion).udpPort().toInt(), PORTMASK)
357 .build());
358 break;
359 default:
360 log.warn("Unsupported criterion type: {}", criterion.type());
361 }
362 }
363
364 return DefaultFlowRule.builder()
365 .forDevice(this.data().deviceId())
366 .withSelector(sBuilder.build())
367 .withTreatment(instTreatment)
368 .withPriority(DEFAULT_PRIORITY)
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700369 .forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_SOURCE_TB_INT_SOURCE)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900370 .fromApp(appId)
371 .withIdleTimeout(IDLE_TIMEOUT)
372 .build();
373 }
374
375 private int buildInstructionBitmap(Set<IntIntent.IntMetadataType> metadataTypes) {
376 int instBitmap = 0;
377 for (IntIntent.IntMetadataType metadataType : metadataTypes) {
378 switch (metadataType) {
379 case SWITCH_ID:
380 instBitmap |= (1 << 15);
381 break;
382 case L1_PORT_ID:
383 instBitmap |= (1 << 14);
384 break;
385 case HOP_LATENCY:
386 instBitmap |= (1 << 13);
387 break;
388 case QUEUE_OCCUPANCY:
389 instBitmap |= (1 << 12);
390 break;
391 case INGRESS_TIMESTAMP:
392 instBitmap |= (1 << 11);
393 break;
394 case EGRESS_TIMESTAMP:
395 instBitmap |= (1 << 10);
396 break;
397 case L2_PORT_ID:
398 instBitmap |= (1 << 9);
399 break;
400 case EGRESS_TX_UTIL:
401 instBitmap |= (1 << 8);
402 break;
403 default:
404 log.info("Unsupported metadata type {}. Ignoring...", metadataType);
405 break;
406 }
407 }
408 return instBitmap;
409 }
410
411 /**
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700412 * Returns a subset of Criterion from given selector, which is unsupported
413 * by this INT pipeline.
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900414 *
415 * @param selector a traffic selector
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700416 * @return a subset of Criterion from given selector, unsupported by this
417 * INT pipeline, empty if all criteria are supported.
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900418 */
419 private Set<Criterion> unsupportedSelectors(TrafficSelector selector) {
420 return selector.criteria().stream()
421 .filter(criterion -> !SUPPORTED_CRITERION.contains(criterion.type()))
422 .collect(Collectors.toSet());
423 }
424
425 private boolean processIntObjective(IntObjective obj, boolean install) {
426 flowRuleService = handler().get(FlowRuleService.class);
427 deviceId = this.data().deviceId();
428 if (install && !unsupportedSelectors(obj.selector()).isEmpty()) {
429 log.warn("Device {} does not support criteria {} for INT.",
430 deviceId, unsupportedSelectors(obj.selector()));
431 return false;
432 }
433
434 FlowRule flowRule = buildWatchlistEntry(obj);
435 if (flowRule != null) {
436 if (install) {
437 flowRuleService.applyFlowRules(flowRule);
438 } else {
439 flowRuleService.removeFlowRules(flowRule);
440 }
441 log.debug("IntObjective {} has been {} {}",
442 obj, install ? "installed to" : "removed from", deviceId);
443 return true;
444 } else {
445 log.warn("Failed to {} IntObjective {} on {}",
446 install ? "install" : "remove", obj, deviceId);
447 return false;
448 }
449 }
450
451 private boolean setupIntReportInternal(IntConfig cfg) {
452 flowRuleService = handler().get(FlowRuleService.class);
453
454 FlowRule reportRule = buildReportEntry(cfg, PKT_INSTANCE_TYPE_INGRESS_CLONE);
455 if (reportRule != null) {
456 flowRuleService.applyFlowRules(reportRule);
457 log.info("Report entry {} has been added to {}", reportRule, this.data().deviceId());
458 return true;
459 } else {
460 log.warn("Failed to add report entry on {}", this.data().deviceId());
461 return false;
462 }
463 }
464
465 private FlowRule buildReportEntry(IntConfig cfg, int type) {
466 coreService = handler().get(CoreService.class);
467 appId = coreService.getAppId(PIPELINE_APP_NAME);
468 if (appId == null) {
469 log.warn("Application ID is null. Cannot build report entry.");
470 return null;
471 }
472
473 PiActionParam srcMacParam = new PiActionParam(
474 FabricConstants.SRC_MAC,
475 ImmutableByteSequence.copyFrom(cfg.sinkMac().toBytes()));
476 PiActionParam nextHopMacParam = new PiActionParam(
477 FabricConstants.MON_MAC,
478 ImmutableByteSequence.copyFrom(cfg.collectorNextHopMac().toBytes()));
479 PiActionParam srcIpParam = new PiActionParam(
480 FabricConstants.SRC_IP,
481 ImmutableByteSequence.copyFrom(cfg.sinkIp().toOctets()));
482 PiActionParam monIpParam = new PiActionParam(
483 FabricConstants.MON_IP,
484 ImmutableByteSequence.copyFrom(cfg.collectorIp().toOctets()));
485 PiActionParam monPortParam = new PiActionParam(
486 FabricConstants.MON_PORT,
487 ImmutableByteSequence.copyFrom(cfg.collectorPort().toInt()));
488 PiAction reportAction = PiAction.builder()
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700489 .withId(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_DO_REPORT_ENCAPSULATION)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900490 .withParameter(srcMacParam)
491 .withParameter(nextHopMacParam)
492 .withParameter(srcIpParam)
493 .withParameter(monIpParam)
494 .withParameter(monPortParam)
495 .build();
496 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
497 .piTableAction(reportAction)
498 .build();
499
500 return DefaultFlowRule.builder()
501 .withTreatment(treatment)
502 .fromApp(appId)
503 .withPriority(DEFAULT_PRIORITY)
504 .makePermanent()
505 .forDevice(this.data().deviceId())
Carmelo Cascone79a3a312018-08-16 17:14:43 -0700506 .forTable(FabricConstants.FABRIC_EGRESS_PROCESS_INT_MAIN_PROCESS_INT_REPORT_TB_GENERATE_REPORT)
Jonghwan Hyuned478dc2018-08-06 15:35:18 +0900507 .build();
508 }
509
510}