blob: a50d30c57b56935dee36bbfea7e16dbe02c26e68 [file] [log] [blame]
Jian Li4aa17642019-01-30 00:01:11 +09001/*
2 * Copyright 2019-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.k8snetworking.util;
17
18import org.onlab.packet.Ip4Address;
Jian Li2cc2b632019-02-18 00:56:40 +090019import org.onlab.packet.IpAddress;
20import org.onlab.packet.TpPort;
Jian Li4aa17642019-01-30 00:01:11 +090021import org.onosproject.net.Device;
22import org.onosproject.net.DeviceId;
Jian Li2cc2b632019-02-18 00:56:40 +090023import org.onosproject.net.behaviour.ExtensionSelectorResolver;
Jian Li4aa17642019-01-30 00:01:11 +090024import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
25import org.onosproject.net.device.DeviceService;
Jian Li2cc2b632019-02-18 00:56:40 +090026import org.onosproject.net.driver.DriverHandler;
27import org.onosproject.net.driver.DriverService;
28import org.onosproject.net.flow.TrafficTreatment;
29import org.onosproject.net.flow.criteria.ExtensionSelector;
30import org.onosproject.net.flow.criteria.ExtensionSelectorType;
Jian Li4aa17642019-01-30 00:01:11 +090031import org.onosproject.net.flow.instructions.ExtensionPropertyException;
32import org.onosproject.net.flow.instructions.ExtensionTreatment;
Jian Li2cc2b632019-02-18 00:56:40 +090033import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
34import org.onosproject.net.group.DefaultGroupBucket;
35import org.onosproject.net.group.GroupBucket;
36import org.onosproject.net.group.GroupDescription.Type;
Jian Li4aa17642019-01-30 00:01:11 +090037import org.slf4j.Logger;
38
Jian Li2cc2b632019-02-18 00:56:40 +090039import java.util.ArrayList;
40import java.util.List;
41
Jian Li5e8a22a2019-02-27 11:48:42 +090042import static org.onosproject.k8snetworking.api.Constants.DST;
43import static org.onosproject.k8snetworking.api.Constants.SRC;
Jian Li004526d2019-02-25 16:26:27 +090044import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD;
Jian Lieb488ea2019-04-16 01:50:02 +090045import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA;
46import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA;
47import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST;
Jian Li2cc2b632019-02-18 00:56:40 +090048import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE;
Jian Li4aa17642019-01-30 00:01:11 +090049import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
50import static org.slf4j.LoggerFactory.getLogger;
51
52/**
53 * Provides common methods to help populating flow rules for SONA applications.
54 */
55public final class RulePopulatorUtil {
56
57 private static final Logger log = getLogger(RulePopulatorUtil.class);
58
59 private static final String TUNNEL_DST = "tunnelDst";
60
Jian Li2cc2b632019-02-18 00:56:40 +090061 private static final String CT_FLAGS = "flags";
62 private static final String CT_ZONE = "zone";
63 private static final String CT_TABLE = "recircTable";
64 private static final String CT_STATE = "ctState";
65 private static final String CT_STATE_MASK = "ctStateMask";
66 private static final String CT_PRESENT_FLAGS = "presentFlags";
67 private static final String CT_IPADDRESS_MIN = "ipAddressMin";
68 private static final String CT_IPADDRESS_MAX = "ipAddressMax";
69 private static final String CT_PORT_MIN = "portMin";
70 private static final String CT_PORT_MAX = "portMax";
71 private static final String CT_NESTED_ACTIONS = "nestedActions";
72
73 public static final int CT_NAT_SRC_FLAG = 0;
74 public static final int CT_NAT_DST_FLAG = 1;
75 public static final int CT_NAT_PERSISTENT_FLAG = 2;
76 public static final int CT_NAT_PROTO_HASH_FLAG = 3;
77 public static final int CT_NAT_PROTO_RANDOM_FLAG = 4;
78
79 private static final int ADDRESS_V4_MIN_FLAG = 0;
80 private static final int ADDRESS_V4_MAX_FLAG = 1;
81 private static final int ADDRESS_V6_MIN_FLAG = 2;
82 private static final int ADDRESS_V6_MAX_FLAG = 3;
83 private static final int PORT_MIN_FLAG = 4;
84 private static final int PORT_MAX_FLAG = 5;
85
Jian Li004526d2019-02-25 16:26:27 +090086 private static final long CT_STATE_NONE = 0;
87 private static final long CT_STATE_NEW = 0x01;
88 private static final long CT_STATE_EST = 0x02;
89 private static final long CT_STATE_NOT_TRK = 0x20;
90 private static final long CT_STATE_TRK = 0x20;
Jian Li2cc2b632019-02-18 00:56:40 +090091
92 private static final String TABLE_EXTENSION = "table";
93
Jian Li004526d2019-02-25 16:26:27 +090094 private static final String OFF_SET_N_BITS = "ofsNbits";
95 private static final String DESTINATION = "dst";
96 private static final String VALUE = "value";
97
98 private static final int SRC_IP = 0x00000e04;
99 private static final int DST_IP = 0x00001004;
100
Jian Li004526d2019-02-25 16:26:27 +0900101 private static final int OFF_SET_BIT = 16;
102 private static final int REMAINDER_BIT = 16;
103
Jian Li2cc2b632019-02-18 00:56:40 +0900104 // not intended for direct invocation from external
Jian Li4aa17642019-01-30 00:01:11 +0900105 private RulePopulatorUtil() {
106 }
107
108 /**
Jian Li2cc2b632019-02-18 00:56:40 +0900109 * Returns a builder for OVS Connection Tracking feature actions.
110 *
111 * @param ds DriverService
112 * @param id DeviceId
113 * @return a builder for OVS Connection Tracking feature actions
114 */
115 public static NiciraConnTrackTreatmentBuilder
116 niciraConnTrackTreatmentBuilder(DriverService ds, DeviceId id) {
117 return new NiciraConnTrackTreatmentBuilder(ds, id);
118 }
119
120 /**
121 * Builds OVS ConnTrack matches.
122 *
123 * @param driverService driver service
124 * @param deviceId device ID
125 * @param ctState connection tracking sate masking value
126 * @param ctSateMask connection tracking sate masking value
127 * @return OVS ConnTrack extension match
128 */
129 public static ExtensionSelector buildCtExtensionSelector(DriverService driverService,
130 DeviceId deviceId,
131 long ctState,
132 long ctSateMask) {
133 DriverHandler handler = driverService.createHandler(deviceId);
134 ExtensionSelectorResolver esr = handler.behaviour(ExtensionSelectorResolver.class);
135
136 ExtensionSelector extensionSelector = esr.getExtensionSelector(
137 ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type());
138 try {
139 extensionSelector.setPropertyValue(CT_STATE, ctState);
140 extensionSelector.setPropertyValue(CT_STATE_MASK, ctSateMask);
141 } catch (Exception e) {
142 log.error("Failed to set nicira match CT state because of {}", e);
143 return null;
144 }
145
146 return extensionSelector;
147 }
148
149 /**
150 * Computes ConnTack State flag values.
151 *
152 * @param isTracking true for +trk, false for -trk
153 * @param isNew true for +new, false for -new
154 * @param isEstablished true for +est, false for -est
155 * @return ConnTrack State flags
156 */
157 public static long computeCtStateFlag(boolean isTracking,
158 boolean isNew,
159 boolean isEstablished) {
160 long ctStateFlag = 0x00;
161
162 if (isTracking) {
163 ctStateFlag = ctStateFlag | CT_STATE_TRK;
164 }
165
166 if (isNew) {
167 ctStateFlag = ctStateFlag | CT_STATE_TRK;
168 ctStateFlag = ctStateFlag | CT_STATE_NEW;
169 }
170
171 if (isEstablished) {
172 ctStateFlag = ctStateFlag | CT_STATE_TRK;
173 ctStateFlag = ctStateFlag | CT_STATE_EST;
174 }
175
176 return ctStateFlag;
177 }
178
179 /**
180 * Computes ConnTrack State mask values.
181 *
182 * @param isTracking true for setting +trk/-trk value, false for otherwise
183 * @param isNew true for setting +new/-new value, false for otherwise
184 * @param isEstablished true for setting +est/-est value, false for otherwise
185 * @return ConnTrack State Mask value
186 */
187 public static long computeCtMaskFlag(boolean isTracking,
188 boolean isNew,
189 boolean isEstablished) {
190 long ctMaskFlag = 0x00;
191
192 if (isTracking) {
193 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
194 }
195
196 if (isNew) {
197 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
198 ctMaskFlag = ctMaskFlag | CT_STATE_NEW;
199 }
200
201 if (isEstablished) {
202 ctMaskFlag = ctMaskFlag | CT_STATE_TRK;
203 ctMaskFlag = ctMaskFlag | CT_STATE_EST;
204 }
205
206 return ctMaskFlag;
207 }
208
209 /**
Jian Li4aa17642019-01-30 00:01:11 +0900210 * Returns tunnel destination extension treatment object.
211 *
212 * @param deviceService driver service
213 * @param deviceId device id to apply this treatment
214 * @param remoteIp tunnel destination ip address
215 * @return extension treatment
216 */
217 public static ExtensionTreatment buildExtension(DeviceService deviceService,
218 DeviceId deviceId,
219 Ip4Address remoteIp) {
220 Device device = deviceService.getDevice(deviceId);
Jian Lieb488ea2019-04-16 01:50:02 +0900221
222 if (!checkTreatmentResolver(device)) {
Jian Li4aa17642019-01-30 00:01:11 +0900223 return null;
224 }
225
226 if (device == null) {
227 return null;
228 }
229
230 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
231 ExtensionTreatment treatment =
232 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
233 try {
234 treatment.setPropertyValue(TUNNEL_DST, remoteIp);
235 return treatment;
236 } catch (ExtensionPropertyException e) {
237 log.warn("Failed to get tunnelDst extension treatment for {} " +
238 "because of {}", deviceId, e);
239 return null;
240 }
241 }
Jian Li2cc2b632019-02-18 00:56:40 +0900242
243 /**
244 * Returns the group bucket with given traffic treatment and group type.
245 *
246 * @param treatment traffic treatment
247 * @param type group type
248 * @param weight weight (only for select type)
249 * @return group bucket
250 */
251 public static GroupBucket buildGroupBucket(TrafficTreatment treatment,
252 Type type, short weight) {
253 switch (type) {
254 case ALL:
255 return DefaultGroupBucket.createAllGroupBucket(treatment);
256 case SELECT:
257 if (weight == -1) {
258 return DefaultGroupBucket.createSelectGroupBucket(treatment);
259 } else {
260 return DefaultGroupBucket.createSelectGroupBucket(treatment, weight);
261 }
262 case INDIRECT:
263 return DefaultGroupBucket.createIndirectGroupBucket(treatment);
264 default:
265 return null;
266 }
267 }
268
269 /**
270 * Returns the nicira resubmit extension treatment with given table ID.
271 *
Jian Li004526d2019-02-25 16:26:27 +0900272 * @param device device instance
Jian Li2cc2b632019-02-18 00:56:40 +0900273 * @param tableId table identifier
274 * @return resubmit extension treatment
275 */
276 public static ExtensionTreatment buildResubmitExtension(Device device, int tableId) {
Jian Lieb488ea2019-04-16 01:50:02 +0900277 if (!checkTreatmentResolver(device)) {
Jian Li2cc2b632019-02-18 00:56:40 +0900278 return null;
279 }
280
281 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
282 ExtensionTreatment treatment =
283 resolver.getExtensionInstruction(NICIRA_RESUBMIT_TABLE.type());
284
285 try {
286 treatment.setPropertyValue(TABLE_EXTENSION, ((short) tableId));
287 return treatment;
288 } catch (ExtensionPropertyException e) {
289 log.error("Failed to set nicira resubmit extension treatment for {}",
290 device.id());
291 return null;
292 }
293 }
294
295 /**
Jian Li004526d2019-02-25 16:26:27 +0900296 * Returns the nicira load extension treatment.
297 *
298 * @param device device instance
299 * @param ipType IP type (src|dst)
300 * @param shift shift (e.g., 10.10., 20.20.,)
301 * @return load extension treatment
302 */
303 public static ExtensionTreatment buildLoadExtension(Device device,
304 String ipType,
305 String shift) {
Jian Lieb488ea2019-04-16 01:50:02 +0900306 if (!checkTreatmentResolver(device)) {
Jian Li004526d2019-02-25 16:26:27 +0900307 return null;
308 }
309
310 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
311 ExtensionTreatment treatment =
312 resolver.getExtensionInstruction(NICIRA_LOAD.type());
313
314 long dst = 0L;
315
316 if (SRC.equalsIgnoreCase(ipType)) {
317 dst = SRC_IP;
318 } else if (DST.equals(ipType)) {
319 dst = DST_IP;
320 }
321
322 long value = calculateUpperBit(shift);
323
324 // we only rewrite the upper 16 bits with value (A.B.X.Y -> C.D.X.Y)
325 int ofsNbits = OFF_SET_BIT << 6 | (REMAINDER_BIT - 1);
326
327 try {
328 treatment.setPropertyValue(OFF_SET_N_BITS, ofsNbits);
329 treatment.setPropertyValue(DESTINATION, dst);
330 treatment.setPropertyValue(VALUE, value);
331 return treatment;
332 } catch (ExtensionPropertyException e) {
333 log.error("Failed to set nicira load extension treatment for {}",
334 device.id());
335 return null;
336 }
337 }
338
Jian Lieb488ea2019-04-16 01:50:02 +0900339
340 /**
341 * Returns the nicira move source MAC to destination MAC extension treatment.
342 *
343 * @param device device instance
344 * @return move extension treatment
345 */
346 public static ExtensionTreatment buildMoveEthSrcToDstExtension(Device device) {
347 if (!checkTreatmentResolver(device)) {
348 return null;
349 }
350
351 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
352 return resolver.getExtensionInstruction(NICIRA_MOV_ETH_SRC_TO_DST.type());
353 }
354
355 /**
356 * Returns the nicira move ARP SHA to THA extension treatment.
357 *
358 * @param device device instance
359 * @return move extension treatment
360 */
361 public static ExtensionTreatment buildMoveArpShaToThaExtension(Device device) {
362 if (!checkTreatmentResolver(device)) {
363 return null;
364 }
365
366 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
367 return resolver.getExtensionInstruction(NICIRA_MOV_ARP_SHA_TO_THA.type());
368 }
369
370 /**
371 * Returns the nicira move ARP SPA to TPA extension treatment.
372 *
373 * @param device device instance
374 * @return move extension treatment
375 */
376 public static ExtensionTreatment buildMoveArpSpaToTpaExtension(Device device) {
377 if (!checkTreatmentResolver(device)) {
378 return null;
379 }
380
381 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
382 return resolver.getExtensionInstruction(NICIRA_MOV_ARP_SPA_TO_TPA.type());
383 }
384
Jian Li004526d2019-02-25 16:26:27 +0900385 /**
386 * Calculate IP address upper string into integer.
387 *
388 * @param shift IP address upper two octets with dot
389 * @return calculated integer
390 */
391 private static int calculateUpperBit(String shift) {
392 String[] strArray = shift.split("\\.");
393
394 int firstOctet = Integer.valueOf(strArray[0]);
395 int secondOctet = Integer.valueOf(strArray[1]);
396
397 return firstOctet << 8 | secondOctet;
398 }
399
Jian Lieb488ea2019-04-16 01:50:02 +0900400 private static boolean checkTreatmentResolver(Device device) {
401 if (device == null || !device.is(ExtensionTreatmentResolver.class)) {
402 log.warn("Nicira extension treatment is not supported");
403 return false;
404 }
405
406 return true;
407 }
408
Jian Li004526d2019-02-25 16:26:27 +0900409 /**
Jian Li2cc2b632019-02-18 00:56:40 +0900410 * Builder class for OVS Connection Tracking feature actions.
411 */
412 public static final class NiciraConnTrackTreatmentBuilder {
413
414 private DriverService driverService;
415 private DeviceId deviceId;
416 private IpAddress natAddress = null;
Jian Lieb488ea2019-04-16 01:50:02 +0900417 private TpPort natPortMin = null;
418 private TpPort natPortMax = null;
Jian Li2cc2b632019-02-18 00:56:40 +0900419 private int zone;
420 private boolean commit;
421 private short table = -1;
422 private boolean natAction;
423 private int natFlag;
424
425 // private constructor
426 private NiciraConnTrackTreatmentBuilder(DriverService driverService,
427 DeviceId deviceId) {
428 this.driverService = driverService;
429 this.deviceId = deviceId;
430 }
431
432 /**
433 * Sets commit flag.
434 *
435 * @param c true if commit, false if not.
436 * @return NiciraConnTrackTreatmentBuilder object
437 */
438 public NiciraConnTrackTreatmentBuilder commit(boolean c) {
439 this.commit = c;
440 return this;
441 }
442
443 /**
444 * Sets zone number.
445 *
446 * @param z zone number
447 * @return NiciraConnTrackTreatmentBuilder object
448 */
449 public NiciraConnTrackTreatmentBuilder zone(int z) {
450 this.zone = z;
451 return this;
452 }
453
454 /**
455 * Sets recirculation table number.
456 *
457 * @param t table number to restart
458 * @return NiciraConnTrackTreatmentBuilder object
459 */
460 public NiciraConnTrackTreatmentBuilder table(short t) {
461 this.table = t;
462 return this;
463 }
464
465 /**
466 * Sets IP address for NAT.
467 *
468 * @param ip NAT IP address
469 * @return NiciraConnTrackTreatmentBuilder object
470 */
471 public NiciraConnTrackTreatmentBuilder natIp(IpAddress ip) {
472 this.natAddress = ip;
473 return this;
474 }
475
476 /**
Jian Lieb488ea2019-04-16 01:50:02 +0900477 * Sets min port for NAT.
Jian Li2cc2b632019-02-18 00:56:40 +0900478 *
479 * @param port port number
480 * @return NiciraConnTrackTreatmentBuilder object
481 */
Jian Lieb488ea2019-04-16 01:50:02 +0900482 public NiciraConnTrackTreatmentBuilder natPortMin(TpPort port) {
483 this.natPortMin = port;
484 return this;
485 }
486
487 /**
488 * Sets max port for NAT.
489 *
490 * @param port port number
491 * @return NiciraConnTrackTreatmentBuilder object
492 */
493 public NiciraConnTrackTreatmentBuilder natPortMax(TpPort port) {
494 this.natPortMax = port;
Jian Li2cc2b632019-02-18 00:56:40 +0900495 return this;
496 }
497
498 /**
499 * Sets NAT flags.
500 * SRC NAT: 1 << 0
501 * DST NAT: 1 << 1
502 * PERSISTENT NAT: 1 << 2
503 * PROTO_HASH NAT: 1 << 3
504 * PROTO_RANDOM NAT : 1 << 4
505 *
506 * @param flag flag value
507 * @return NiciraConnTrackTreatmentBuilder object
508 */
509 public NiciraConnTrackTreatmentBuilder natFlag(int flag) {
510 this.natFlag = 1 << flag;
511 return this;
512 }
513
514 /**
515 * Sets the flag for NAT action.
516 *
517 * @param nat nat action is included if true, no nat action otherwise
518 * @return NiciraConnTrackTreatmentBuilder object
519 */
520 public NiciraConnTrackTreatmentBuilder natAction(boolean nat) {
521 this.natAction = nat;
522 return this;
523 }
524
525 /**
526 * Builds extension treatment for OVS ConnTack and NAT feature.
527 *
528 * @return ExtensionTreatment object
529 */
530 public ExtensionTreatment build() {
531 DriverHandler handler = driverService.createHandler(deviceId);
532 ExtensionTreatmentResolver etr =
533 handler.behaviour(ExtensionTreatmentResolver.class);
534
535 ExtensionTreatment natTreatment = etr.getExtensionInstruction(
536 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type());
537 try {
538
Jian Lieb488ea2019-04-16 01:50:02 +0900539 if (natAddress == null && natPortMin == null && natPortMax == null) {
540 natTreatment.setPropertyValue(CT_FLAGS, 0);
541 natTreatment.setPropertyValue(CT_PRESENT_FLAGS, 0);
542 } else {
543 natTreatment.setPropertyValue(CT_FLAGS, this.natFlag);
Jian Li2cc2b632019-02-18 00:56:40 +0900544
Jian Lieb488ea2019-04-16 01:50:02 +0900545 natTreatment.setPropertyValue(CT_PRESENT_FLAGS,
546 buildPresentFlag((natPortMin != null && natPortMax != null),
547 natAddress != null));
548 }
Jian Li2cc2b632019-02-18 00:56:40 +0900549
550 if (natAddress != null) {
551 natTreatment.setPropertyValue(CT_IPADDRESS_MIN, natAddress);
552 natTreatment.setPropertyValue(CT_IPADDRESS_MAX, natAddress);
553 }
554
Jian Lieb488ea2019-04-16 01:50:02 +0900555 if (natPortMin != null) {
556 natTreatment.setPropertyValue(CT_PORT_MIN, natPortMin.toInt());
557 }
558
559 if (natPortMax != null) {
560 natTreatment.setPropertyValue(CT_PORT_MAX, natPortMax.toInt());
Jian Li2cc2b632019-02-18 00:56:40 +0900561 }
562
563 } catch (Exception e) {
564 log.error("Failed to set NAT due to error : {}", e);
565 return null;
566 }
567
568 ExtensionTreatment ctTreatment = etr.getExtensionInstruction(
569 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type());
570 try {
571 List<ExtensionTreatment> nat = new ArrayList<>();
572 if (natAction) {
573 nat.add(natTreatment);
574 }
575 ctTreatment.setPropertyValue(CT_FLAGS, commit ? 1 : 0);
576 ctTreatment.setPropertyValue(CT_ZONE, zone);
577 ctTreatment.setPropertyValue(CT_TABLE, table > -1 ? table : 0xff);
578 ctTreatment.setPropertyValue(CT_NESTED_ACTIONS, nat);
579 } catch (Exception e) {
580 log.error("Failed to set CT due to error : {}", e);
581 return null;
582 }
583
584 return ctTreatment;
585 }
586
587 private int buildPresentFlag(boolean isPortPresent, boolean isAddressPresent) {
588
589 int presentFlag = 0;
590
591 if (isPortPresent) {
592 presentFlag = 1 << PORT_MIN_FLAG | 1 << PORT_MAX_FLAG;
593 }
594
595 if (isAddressPresent) {
596 // TODO: need to support IPv6 address
597 presentFlag = presentFlag | 1 << ADDRESS_V4_MIN_FLAG | 1 << ADDRESS_V4_MAX_FLAG;
598 }
599
600 return presentFlag;
601 }
602 }
Jian Li4aa17642019-01-30 00:01:11 +0900603}