blob: 304e9b62aca1af88121fcf269ea2d4c7ac9a9647 [file] [log] [blame]
Jian Li858ccd72021-02-04 17:25:01 +09001/*
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 */
16package org.onosproject.kubevirtnetworking.util;
17
Jian Li8f944d42021-03-23 00:43:29 +090018import com.google.common.collect.Maps;
Jian Li858ccd72021-02-04 17:25:01 +090019import org.onlab.packet.Ip4Address;
Daniel Parka8968802021-02-25 09:14:22 +090020import org.onlab.packet.IpAddress;
21import org.onlab.packet.TpPort;
Jian Li858ccd72021-02-04 17:25:01 +090022import org.onosproject.net.Device;
23import org.onosproject.net.DeviceId;
Jian Li8f944d42021-03-23 00:43:29 +090024import org.onosproject.net.behaviour.ExtensionSelectorResolver;
Jian Li858ccd72021-02-04 17:25:01 +090025import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
26import org.onosproject.net.device.DeviceService;
Daniel Parka8968802021-02-25 09:14:22 +090027import org.onosproject.net.driver.DriverHandler;
28import org.onosproject.net.driver.DriverService;
Jian Li8f944d42021-03-23 00:43:29 +090029import org.onosproject.net.flow.criteria.ExtensionSelector;
30import org.onosproject.net.flow.criteria.ExtensionSelectorType;
Jian Li858ccd72021-02-04 17:25:01 +090031import org.onosproject.net.flow.instructions.ExtensionPropertyException;
32import org.onosproject.net.flow.instructions.ExtensionTreatment;
Daniel Parka8968802021-02-25 09:14:22 +090033import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
Jian Li858ccd72021-02-04 17:25:01 +090034import org.slf4j.Logger;
35
Daniel Parka8968802021-02-25 09:14:22 +090036import java.util.ArrayList;
37import java.util.List;
Jian Li8f944d42021-03-23 00:43:29 +090038import java.util.Map;
39import java.util.Objects;
Daniel Parka8968802021-02-25 09:14:22 +090040
Jian Li858ccd72021-02-04 17:25:01 +090041import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD;
42import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA;
43import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA;
44import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST;
45import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST;
46import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
47import static org.slf4j.LoggerFactory.getLogger;
48
49/**
50 * Provides common methods to help populating flow rules for SONA applications.
51 */
52public final class RulePopulatorUtil {
53
54 private static final Logger log = getLogger(RulePopulatorUtil.class);
55
56 private static final int OFF_SET_BIT = 0;
57 private static final int REMAINDER_BIT = 8;
58
59 private static final String OFF_SET_N_BITS = "ofsNbits";
60 private static final String DESTINATION = "dst";
61 private static final String VALUE = "value";
62 private static final String TUNNEL_DST = "tunnelDst";
63
Daniel Parka8968802021-02-25 09:14:22 +090064 private static final String CT_FLAGS = "flags";
65 private static final String CT_ZONE = "zone";
66 private static final String CT_TABLE = "recircTable";
67 private static final String CT_STATE = "ctState";
68 private static final String CT_STATE_MASK = "ctStateMask";
69 private static final String CT_PRESENT_FLAGS = "presentFlags";
70 private static final String CT_IPADDRESS_MIN = "ipAddressMin";
71 private static final String CT_IPADDRESS_MAX = "ipAddressMax";
72 private static final String CT_PORT_MIN = "portMin";
73 private static final String CT_PORT_MAX = "portMax";
74 private static final String CT_NESTED_ACTIONS = "nestedActions";
75
76 public static final int CT_NAT_SRC_FLAG = 0;
77 public static final int CT_NAT_DST_FLAG = 1;
78 public static final int CT_NAT_PERSISTENT_FLAG = 2;
79 public static final int CT_NAT_PROTO_HASH_FLAG = 3;
80 public static final int CT_NAT_PROTO_RANDOM_FLAG = 4;
81
82 private static final int ADDRESS_V4_MIN_FLAG = 0;
83 private static final int ADDRESS_V4_MAX_FLAG = 1;
84 private static final int ADDRESS_V6_MIN_FLAG = 2;
85 private static final int ADDRESS_V6_MAX_FLAG = 3;
86 private static final int PORT_MIN_FLAG = 4;
87 private static final int PORT_MAX_FLAG = 5;
88
89 private static final String STR_ZERO = "0";
90 private static final String STR_ONE = "1";
91 private static final String STR_PADDING = "0000000000000000";
92 private static final int MASK_BEGIN_IDX = 0;
93 private static final int MASK_MAX_IDX = 16;
94 private static final int MASK_RADIX = 2;
95 private static final int PORT_RADIX = 16;
96
97 // Refer to http://openvswitch.org/support/dist-docs/ovs-fields.7.txt for the values
98 public static final long CT_STATE_NONE = 0;
99 public static final long CT_STATE_NEW = 0x01;
100 public static final long CT_STATE_EST = 0x02;
101 public static final long CT_STATE_NOT_TRK = 0x20;
102 public static final long CT_STATE_TRK = 0x20;
103
Jian Li858ccd72021-02-04 17:25:01 +0900104 // layer 3 nicira fields
105 private static final int NXM_OF_IP_SRC = 0x00000e04;
106 private static final int NXM_OF_IP_DST = 0x00001004;
107 private static final int NXM_OF_IP_PROT = 0x00000c01;
108
109 public static final int NXM_NX_IP_TTL = 0x00013a01;
110 public static final int NXM_NX_IP_FRAG = 0x00013401;
111 public static final int NXM_OF_ARP_OP = 0x00001e02;
112 public static final int NXM_OF_ARP_SPA = 0x00002004;
113 public static final int NXM_OF_ARP_TPA = 0x00002204;
114 public static final int NXM_NX_ARP_SHA = 0x00012206;
115 public static final int NXM_NX_ARP_THA = 0x00012406;
116
117 // layer 4 nicira fields
118 public static final int NXM_OF_TCP_SRC = 0x00001202;
119 public static final int NXM_OF_TCP_DST = 0x00001402;
120 public static final int NXM_NX_TCP_FLAGS = 0x00014402;
121 public static final int NXM_OF_UDP_SRC = 0x00001602;
122 public static final int NXM_OF_UDP_DST = 0x00001802;
123
124 public static final int NXM_OF_ICMP_TYPE = 0x00001a01;
125 public static final int NXM_OF_ICMP_CODE = 0x00001c01;
126
Daniel Parka8968802021-02-25 09:14:22 +0900127
Jian Li858ccd72021-02-04 17:25:01 +0900128 private RulePopulatorUtil() {
129 }
130
131 /**
132 * Returns the nicira load extension treatment.
133 *
134 * @param device device instance
135 * @param field field code
136 * @param value value to load
137 * @return load extension treatment
138 */
139 public static ExtensionTreatment buildLoadExtension(Device device,
140 long field,
141 long value) {
142 if (!checkTreatmentResolver(device)) {
143 return null;
144 }
145
146 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
147 ExtensionTreatment treatment =
148 resolver.getExtensionInstruction(NICIRA_LOAD.type());
149
150 int ofsNbits = OFF_SET_BIT << 6 | (REMAINDER_BIT - 1);
151
152 try {
153 treatment.setPropertyValue(OFF_SET_N_BITS, ofsNbits);
154 treatment.setPropertyValue(DESTINATION, field);
155 treatment.setPropertyValue(VALUE, value);
156 return treatment;
157 } catch (ExtensionPropertyException e) {
158 log.error("Failed to set nicira load extension treatment for {}",
159 device.id());
160 return null;
161 }
162 }
163
164 /**
165 * Returns the nicira move source MAC to destination MAC extension treatment.
166 *
167 * @param device device instance
168 * @return move extension treatment
169 */
170 public static ExtensionTreatment buildMoveEthSrcToDstExtension(Device device) {
171 if (!checkTreatmentResolver(device)) {
172 return null;
173 }
174
175 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
176 return resolver.getExtensionInstruction(NICIRA_MOV_ETH_SRC_TO_DST.type());
177 }
178
179 /**
180 * Returns the nicira move source IP to destination IP extension treatment.
181 *
182 * @param device device instance
183 * @return move extension treatment
184 */
185 public static ExtensionTreatment buildMoveIpSrcToDstExtension(Device device) {
186 if (!checkTreatmentResolver(device)) {
187 return null;
188 }
189
190 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
191 return resolver.getExtensionInstruction(NICIRA_MOV_IP_SRC_TO_DST.type());
192 }
193
194 /**
195 * Returns the nicira move ARP SHA to THA extension treatment.
196 *
197 * @param device device instance
198 * @return move extension treatment
199 */
200 public static ExtensionTreatment buildMoveArpShaToThaExtension(Device device) {
201 if (!checkTreatmentResolver(device)) {
202 return null;
203 }
204
205 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
206 return resolver.getExtensionInstruction(NICIRA_MOV_ARP_SHA_TO_THA.type());
207 }
208
209 /**
210 * Returns the nicira move ARP SPA to TPA extension treatment.
211 *
212 * @param device device instance
213 * @return move extension treatment
214 */
215 public static ExtensionTreatment buildMoveArpSpaToTpaExtension(Device device) {
216 if (!checkTreatmentResolver(device)) {
217 return null;
218 }
219
220 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
221 return resolver.getExtensionInstruction(NICIRA_MOV_ARP_SPA_TO_TPA.type());
222 }
223
224 private static boolean checkTreatmentResolver(Device device) {
225 if (device == null || !device.is(ExtensionTreatmentResolver.class)) {
226 log.warn("Nicira extension treatment is not supported");
227 return false;
228 }
229
230 return true;
231 }
232
233 /**
234 * Returns tunnel destination extension treatment object.
235 *
236 * @param deviceService driver service
237 * @param deviceId device id to apply this treatment
238 * @param remoteIp tunnel destination ip address
239 * @return extension treatment
240 */
241 public static ExtensionTreatment buildExtension(DeviceService deviceService,
242 DeviceId deviceId,
243 Ip4Address remoteIp) {
244 Device device = deviceService.getDevice(deviceId);
245 if (!checkTreatmentResolver(device)) {
246 return null;
247 }
248
249 if (device == null) {
250 return null;
251 }
252
253 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
254 ExtensionTreatment treatment =
255 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
256 try {
257 treatment.setPropertyValue(TUNNEL_DST, remoteIp);
258 return treatment;
259 } catch (ExtensionPropertyException e) {
260 log.warn("Failed to get tunnelDst extension treatment for {} " +
261 "because of {}", deviceId, e);
262 return null;
263 }
264 }
Daniel Parka8968802021-02-25 09:14:22 +0900265
Jian Li8f944d42021-03-23 00:43:29 +0900266
267 /**
268 * Builds OVS ConnTrack matches.
269 *
270 * @param driverService driver service
271 * @param deviceId device ID
272 * @param ctState connection tracking sate masking value
273 * @param ctSateMask connection tracking sate masking value
274 * @return OVS ConnTrack extension match
275 */
276 public static ExtensionSelector buildCtExtensionSelector(DriverService driverService,
277 DeviceId deviceId,
278 long ctState,
279 long ctSateMask) {
280 DriverHandler handler = driverService.createHandler(deviceId);
281 ExtensionSelectorResolver esr = handler.behaviour(ExtensionSelectorResolver.class);
282
283 ExtensionSelector extensionSelector = esr.getExtensionSelector(
284 ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type());
285 try {
286 extensionSelector.setPropertyValue(CT_STATE, ctState);
287 extensionSelector.setPropertyValue(CT_STATE_MASK, ctSateMask);
288 } catch (Exception e) {
289 log.error("Failed to set nicira match CT state because of {}", e);
290 return null;
291 }
292
293 return extensionSelector;
294 }
295
296 /**
297 * Computes ConnTack State flag values.
298 *
299 * @param isTracking true for +trk, false for -trk
300 * @param isNew true for +new, false for nothing
301 * @param isEstablished true for +est, false for nothing
302 * @return ConnTrack State flags
303 */
304 public static long computeCtStateFlag(boolean isTracking,
305 boolean isNew,
306 boolean isEstablished) {
307 long ctMaskFlag = 0x00;
308
309 if (isTracking) {
310 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
311 }
312
313 if (isNew) {
314 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
315 ctMaskFlag = ctMaskFlag | CT_STATE_NEW;
316 }
317
318 if (isEstablished) {
319 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
320 ctMaskFlag = ctMaskFlag | CT_STATE_EST;
321 }
322
323 return ctMaskFlag;
324 }
325
326 /**
327 * Computes ConnTrack State mask values.
328 *
329 * @param isTracking true for setting +trk/-trk value, false for otherwise
330 * @param isNew true for setting +new value, false for otherwise
331 * @param isEstablished true for setting +est value, false for otherwise
332 * @return ConnTrack State Mask value
333 */
334 public static long computeCtMaskFlag(boolean isTracking,
335 boolean isNew,
336 boolean isEstablished) {
337 long ctMaskFlag = 0x00;
338
339 if (isTracking) {
340 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
341 }
342
343 if (isNew) {
344 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
345 ctMaskFlag = ctMaskFlag | CT_STATE_NEW;
346 }
347
348 if (isEstablished) {
349 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
350 ctMaskFlag = ctMaskFlag | CT_STATE_EST;
351 }
352
353 return ctMaskFlag;
354 }
355
356 /**
357 * Computes port and port mask value from port min/max values.
358 *
359 * @param portMin port min value
360 * @param portMax port max value
361 * @return Port Mask value
362 */
363 public static Map<TpPort, TpPort> buildPortRangeMatches(int portMin, int portMax) {
364
365 boolean processing = true;
366 int start = portMin;
367 Map<TpPort, TpPort> portMaskMap = Maps.newHashMap();
368 while (processing) {
369 String minStr = Integer.toBinaryString(start);
370 String binStrMinPadded = STR_PADDING.substring(minStr.length()) + minStr;
371
372 int mask = testMasks(binStrMinPadded, start, portMax);
373 int maskStart = binLower(binStrMinPadded, mask);
374 int maskEnd = binHigher(binStrMinPadded, mask);
375
376 log.debug("start : {} port/mask = {} / {} ", start, getMask(mask), maskStart);
377 portMaskMap.put(TpPort.tpPort(maskStart), TpPort.tpPort(
378 Integer.parseInt(Objects.requireNonNull(getMask(mask)), PORT_RADIX)));
379
380 start = maskEnd + 1;
381 if (start > portMax) {
382 processing = false;
383 }
384 }
385
386 return portMaskMap;
387 }
388
389 private static int binLower(String binStr, int bits) {
390 StringBuilder outBin = new StringBuilder(
391 binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
392 for (int i = 0; i < bits; i++) {
393 outBin.append(STR_ZERO);
394 }
395
396 return Integer.parseInt(outBin.toString(), MASK_RADIX);
397 }
398
399 private static int binHigher(String binStr, int bits) {
400 StringBuilder outBin = new StringBuilder(
401 binStr.substring(MASK_BEGIN_IDX, MASK_MAX_IDX - bits));
402 for (int i = 0; i < bits; i++) {
403 outBin.append(STR_ONE);
404 }
405
406 return Integer.parseInt(outBin.toString(), MASK_RADIX);
407 }
408
409 private static int testMasks(String binStr, int start, int end) {
410 int mask = MASK_BEGIN_IDX;
411 for (; mask <= MASK_MAX_IDX; mask++) {
412 int maskStart = binLower(binStr, mask);
413 int maskEnd = binHigher(binStr, mask);
414 if (maskStart < start || maskEnd > end) {
415 return mask - 1;
416 }
417 }
418
419 return mask;
420 }
421
422 private static String getMask(int bits) {
423 switch (bits) {
424 case 0: return "ffff";
425 case 1: return "fffe";
426 case 2: return "fffc";
427 case 3: return "fff8";
428 case 4: return "fff0";
429 case 5: return "ffe0";
430 case 6: return "ffc0";
431 case 7: return "ff80";
432 case 8: return "ff00";
433 case 9: return "fe00";
434 case 10: return "fc00";
435 case 11: return "f800";
436 case 12: return "f000";
437 case 13: return "e000";
438 case 14: return "c000";
439 case 15: return "8000";
440 case 16: return "0000";
441 default: return null;
442 }
443 }
444
Daniel Parka8968802021-02-25 09:14:22 +0900445 public static NiciraConnTrackTreatmentBuilder niciraConnTrackTreatmentBuilder(DriverService ds, DeviceId id) {
446 return new NiciraConnTrackTreatmentBuilder(ds, id);
447 }
448 /**
449 * Builder class for OVS Connection Tracking feature actions.
450 */
451 public static final class NiciraConnTrackTreatmentBuilder {
452
453 private DriverService driverService;
454 private DeviceId deviceId;
455 private IpAddress natAddress = null;
456 private TpPort natPortMin = null;
457 private TpPort natPortMax = null;
458 private int zone;
459 private boolean commit;
460 private short table = -1;
461 private boolean natAction;
462 private int natFlag;
463
464 // private constructor
465 private NiciraConnTrackTreatmentBuilder(DriverService driverService,
466 DeviceId deviceId) {
467 this.driverService = driverService;
468 this.deviceId = deviceId;
469 }
470
471 /**
472 * Sets commit flag.
473 *
474 * @param c true if commit, false if not.
475 * @return NiriraConnTrackTreatmentBuilder object
476 */
477 public NiciraConnTrackTreatmentBuilder commit(boolean c) {
478 this.commit = c;
479 return this;
480 }
481
482 /**
483 * Sets zone number.
484 *
485 * @param z zone number
486 * @return NiriraConnTrackTreatmentBuilder object
487 */
488 public NiciraConnTrackTreatmentBuilder zone(int z) {
489 this.zone = z;
490 return this;
491 }
492
493 /**
494 * Sets recirculation table number.
495 *
496 * @param t table number to restart
497 * @return NiriraConnTrackTreatmentBuilder object
498 */
499 public NiciraConnTrackTreatmentBuilder table(short t) {
500 this.table = t;
501 return this;
502 }
503
504 /**
505 * Sets IP address for NAT.
506 *
507 * @param ip NAT IP address
508 * @return NiriraConnTrackTreatmentBuilder object
509 */
510 public NiciraConnTrackTreatmentBuilder natIp(IpAddress ip) {
511 this.natAddress = ip;
512 return this;
513 }
514
515 /**
516 * Sets min port for NAT.
517 *
518 * @param port port number
519 * @return NiciraConnTrackTreatmentBuilder object
520 */
521 public NiciraConnTrackTreatmentBuilder natPortMin(TpPort port) {
522 this.natPortMin = port;
523 return this;
524 }
525
526 /**
527 * Sets max port for NAT.
528 *
529 * @param port port number
530 * @return NiciraConnTrackTreatmentBuilder object
531 */
532 public NiciraConnTrackTreatmentBuilder natPortMax(TpPort port) {
533 this.natPortMax = port;
534 return this;
535 }
536
537 /**
538 * Sets NAT flags.
539 * SRC NAT: 1 << 0
540 * DST NAT: 1 << 1
541 * PERSISTENT NAT: 1 << 2
542 * PROTO_HASH NAT: 1 << 3
543 * PROTO_RANDOM NAT : 1 << 4
544 *
545 * @param flag flag value
546 * @return NiciraConnTrackTreatmentBuilder object
547 */
548 public NiciraConnTrackTreatmentBuilder natFlag(int flag) {
549 this.natFlag = 1 << flag;
550 return this;
551 }
552
553 /**
554 * Sets the flag for NAT action.
555 *
556 * @param nat nat action is included if true, no nat action otherwise
557 * @return NiriraConnTrackTreatmentBuilder object
558 */
559 public NiciraConnTrackTreatmentBuilder natAction(boolean nat) {
560 this.natAction = nat;
561 return this;
562 }
563
564 /**
565 * Builds extension treatment for OVS ConnTack and NAT feature.
566 *
567 * @return ExtensionTreatment object
568 */
569 public ExtensionTreatment build() {
570 DriverHandler handler = driverService.createHandler(deviceId);
571 ExtensionTreatmentResolver etr =
572 handler.behaviour(ExtensionTreatmentResolver.class);
573
574 ExtensionTreatment natTreatment = etr.getExtensionInstruction(
575 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type());
576 try {
577
578 if (natAddress == null && natPortMin == null && natPortMax == null) {
579 natTreatment.setPropertyValue(CT_FLAGS, 0);
580 natTreatment.setPropertyValue(CT_PRESENT_FLAGS, 0);
581 } else {
582 natTreatment.setPropertyValue(CT_FLAGS, this.natFlag);
583
584 natTreatment.setPropertyValue(CT_PRESENT_FLAGS,
585 buildPresentFlag((natPortMin != null && natPortMax != null),
586 natAddress != null));
587 }
588
589 if (natAddress != null) {
590 natTreatment.setPropertyValue(CT_IPADDRESS_MIN, natAddress);
591 natTreatment.setPropertyValue(CT_IPADDRESS_MAX, natAddress);
592 }
593
594 if (natPortMin != null) {
595 natTreatment.setPropertyValue(CT_PORT_MIN, natPortMin.toInt());
596 }
597
598 if (natPortMax != null) {
599 natTreatment.setPropertyValue(CT_PORT_MAX, natPortMax.toInt());
600 }
601
602 } catch (Exception e) {
603 log.error("Failed to set NAT due to error : {}", e);
604 return null;
605 }
606
607 ExtensionTreatment ctTreatment = etr.getExtensionInstruction(
608 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type());
609 try {
610 List<ExtensionTreatment> nat = new ArrayList<>();
611 if (natAction) {
612 nat.add(natTreatment);
613 }
614 ctTreatment.setPropertyValue(CT_FLAGS, commit ? 1 : 0);
615 ctTreatment.setPropertyValue(CT_ZONE, zone);
616 ctTreatment.setPropertyValue(CT_TABLE, table > -1 ? table : 0xff);
617 ctTreatment.setPropertyValue(CT_NESTED_ACTIONS, nat);
618 } catch (Exception e) {
619 log.error("Failed to set CT due to error : {}", e);
620 return null;
621 }
622
623 return ctTreatment;
624 }
625
626 private int buildPresentFlag(boolean isPortPresent, boolean isAddressPresent) {
627
628 int presentFlag = 0;
629
630 if (isPortPresent) {
631 presentFlag = 1 << PORT_MIN_FLAG | 1 << PORT_MAX_FLAG;
632 }
633
634 if (isAddressPresent) {
635 // TODO: need to support IPv6 address
636 presentFlag = presentFlag | 1 << ADDRESS_V4_MIN_FLAG | 1 << ADDRESS_V4_MAX_FLAG;
637 }
638
639 return presentFlag;
640 }
641 }
Jian Li858ccd72021-02-04 17:25:01 +0900642}