Skip to content

Commit dca9f75

Browse files
AaronCoplannks5295
authored andcommitted
Use JSON Config Files to Launch NFs (#229)
ONVM now supports JSON config files, which can be loaded through the API provided in onvm_config_common.h. This allows various settings of either the ONVM manager or NFs to be set in a JSON config file and loaded into code, as opposed to needing to be passed in via the command line. Usage: * All example NFs now support passing DPDK and ONVM arguments in a config file by using the -F config.json flag when running an NF executable or a go.sh script. See docs/examples.md for more details. API Changes: * nflib.c was not changed from an NF-developer standpoint, but it was modified to include a check for the -F flag, which indicates that a config file should be read to launch an NF. API Additions: * `cJSON* onvm_config_parse_file(const char* filename)` - Reads a JSON config and stores the contents in a cJSON struct. For further reference on cJSON `int onvm_config_create_nf_arg_list(cJSON* config, int* argc, char** argv[])` - Given a cJSON struct and pointers to the original command line arguments, generate a new argc and argv using the config file values. Commit log: * Updated example Makefiles to include JSON. * Created config parsing files. * Added function definitions for config helpers. * Updated bridge Makefile to fix compile error. Also added helper functions to onvm_config_common.c * Updated license information. * Added documentation for config file API * Modified API to return status codes instead of values - Returns 0 or -1 depending on success - Functions take a pointer to hold result * Modified API to reflect new config structure * *DOES NOT RUN* Added function to create DPDK arg list from config file - Currently has a buffer overflow error - No support for overriding arguments * Added functions to build a full command-line string from config file - Separate functions to build each piece - NOTE: more testing is required, does not run as expected * CURRENTLY CRASHES: Finished arg parsing for dpdk, onvm, and the nf * Fixed segfaulting problem, triple pointer was not correctly dereferenced * Finished initial NF config loading system * Modified config library to accept file name for NF-specific args * Fixed Makefile and NF args not being loaded from config file * Previous merge conflict resolution broke Makefiles. This resolves that * Reverted config API back and fixed retval in nflib * Removed new code from speed tester * Fixed function protoype * Added new functions for requested config settings and removed commented code * Renamed config file and fixed crashing problem * Fixed check for setting instance id * Renamed config file * Style changes * Added go script support for launching * Added go script support for basic monitor and speed tester * Updated go scripts and READMEs for first half of NFs * Finished go scripts and documentation for second half of NFs and docs folder * Updated NF_dev docs to include sample JSON file * Made requested changes to Neel's comments * Replaced strings with macros and changed error messages * Adde call to cJSON_Delete(), should fix memory leak * Added ability to replace config settings with command line options * Fixed bug with arg replacement, style changes are in progress * Added additional comments and removed unnecessary API functions * Fixed go scripts to support command-line replacement * Updated config documentation * Updated description of file * Fixed NF_dev typos * Moved example_config to outer examples folder and deleted all others * Updated all READMEs to include more accurate config section * Added info about launching NFs with config files * Added info to releases.md
1 parent 6d74c95 commit dca9f75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1258
-22
lines changed

docs/Examples.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
openNetVM Examples
22
==
33

4+
NF Config Files
5+
--
6+
Due to a feature in NFLib, all network functions support launching from a JSON config file that
7+
contains ONVM and DPDK arguments. An example of this can be seen
8+
[here](../examples/example_config.json). In addition, the values
9+
specified in the config file can be overwritten by passing them at the
10+
command line. The general structure for launching an NF from a config file is
11+
`./go -F <CONFIG_FILE.json> <DPDK ARGS> -- <ONVM ARGS> -- <NF ARGS>`.
12+
Any args specified in `<DPDK args>` or `<ONVM ARGS>` will replace the
13+
corresponding args in the config file. **An important note:** If no DPDK
14+
or ONVM args are passed, **but** NF args are required, the `-- --` is
15+
still required. For documentation on developing with config files, see
16+
[NF_Dev](NF_Dev.md)
17+
418
Linear NF Chain
519
--
620
In this example, we will be setting up a chain of NFs. The length of the chain is determined by our system's CPU architecture. Some of the commands used in this example are specific to our system; in the cases where we refer to core lists or number of NFs, please run the [Core Helper Script][cores] to get your numbers.
@@ -102,7 +116,16 @@ In this example, we can set up a circular chain of NFs. Here, traffic does not
102116
- Second, start up 1 speed_tester NF and have it forward to service ID 2.
103117
- `# ./examples/speed_tester/go.sh 14 1 2 -c 16000`
104118
4. We now have a speed_tester sending packets to service ID 2 who then forwards packets back to service ID 1, the speed_tester. This is a circular chain of NFs.
105-
119+
120+
121+
NF Config Files
122+
--
123+
All NFs support launching from a JSON config file. By specifying `-F`
124+
and then a JSON file in either `go.sh` or the NF binary file directly,
125+
the NF will pull all ONVM and DPDK settings from the file instead of the
126+
command line. See the `example_config.json` file in each NF directory
127+
for an example on how to structure the file and all options that can be
128+
set.
106129

107130

108131
[cores]: ../scripts/corehelper.py

docs/NF_Dev.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,48 @@ The openNetVM Packet Helper Library provides an abstraction to support developme
5252
- Print the whole packet or individual headers of the packet. These functions can be found [here][onvm_pkt_helper.h:L86].
5353

5454

55+
Config File Library
56+
--
57+
58+
The openNetVM Config File Library provides an abstraction that allows
59+
NFs to load values from a JSON config file. While NFLib automatically
60+
loads all DPDK and ONVM arguments when `-F` is passed, a developer can
61+
add config support directly within the NF to support passing additional
62+
values.
63+
64+
- NOTE: unless otherwise specified, all DPDK and ONVM arguments are **required**
65+
- `onvm_config_parse_file(const char* filename)`: Load a JSON config file, and return a pointer to the cJSON struct.
66+
- This is utilized to launch NFs using values specified in a config
67+
file.
68+
`onvm_config_parse_file` can be found [here][onvm_config_common.h:L51]
69+
- Additional config options can be loaded from within the NF, using cJSON. For further reference on how to access the values from the cJSON object, see the [cJSON docs](https://github.com/DaveGamble/cJSON)
70+
71+
### Sample Config File
72+
```
73+
{
74+
"dpdk": {
75+
"corelist": [STRING: corelist],
76+
"memory_channels": [INT: number of memory channels],
77+
"portmask": [INT: portmask]
78+
},
79+
80+
"onvm": {
81+
"output": [STRING: output loc, either stdout or web],
82+
"serviceid": [INT: service ID for NF],
83+
"instanceid": [OPTIONAL, INT: this optional arg sets the instance ID of the NF]
84+
}
85+
}
86+
```
87+
5588
[onvm_mgr]: ../onvm/onvm_mgr
5689
[onvm_nflib]: ../onvm/onvm_nflib
5790
[onvm_nflib.h]: ../onvm/onvm_nflib/onvm_nflib.h
5891
[onvm_pkt_helper.h:L56]: ../onvm/onvm_nflib/onvm_pkt_helper.h#L56
5992
[onvm_pkt_helper.h:L59]: ../onvm/onvm_nflib/onvm_pkt_helper.h#L59
6093
[onvm_pkt_helper.h:L74]: ../onvm/onvm_nflib/onvm_pkt_helper.h#L74
6194
[onvm_pkt_helper.h:L86]: ../onvm/onvm_nflib/onvm_pkt_helper.h#L86
95+
[onvm_config_common.h:L51]: ../onvm/onvm_nflib/onvm_config_common.h#L51
96+
[onvm_config_common.h:L108]: ../onvm/onvm_nflib/onvm_config_common.h#L108
6297
[onvm_common.h:L51]: ../onvm/onvm_nflib/onvm_common.h#L51
6398
[onvm_common.h:L55]: ../onvm/onvm_nflib/onvm_common.h#L55
6499
[forward]: ../examples/simple_forward/forward.c#L82

docs/Releases.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ The prior code relied on global data structures that do not work in a multi-thre
3737
`int onvm_nflib_return_pkt(struct onvm_nf_info *nf_info, struct rte_mbuf* pkt)`
3838
- `int pkt_handler_func(struct rte_mbuf* pkt, struct onvm_pkt_meta* action)` ->
3939
`int pkt_handler_func(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, __attribute__ ((unused)) struct onvm_nf_info *nf_info)`
40-
- `int callback_handler_func(void)` -> `int callback_handler_func(__attribute__ ((unused)) struct onvm_nf_info *nf_info)`
41-
40+
- `int callback_handler_func(void)` -> `int callback_handler_func(__attribute__ ((unused)) struct onvm_nf_info *nf_info)`
41+
4242
**API Additions:**
4343
- `int onvm_nflib_scale(struct onvm_nf_scale_info *scale_info)` launches another NF based on the provided config
4444
- `struct onvm_nf_scale_info * onvm_nflib_get_empty_scaling_config(struct onvm_nf_info *parent_info)` for getting a basic empty scaling config
@@ -53,6 +53,19 @@ The console stats display has been improved to aggregate stats when running mult
5353
- For verbose mode run the manager with `-v` flag
5454
- For raw stats dump use the `-vv` flag
5555

56+
### Config File Support:
57+
ONVM now supports JSON config files, which can be loaded through the API provided in `onvm_config_common.h`. This allows various settings of either the ONVM manager or NFs to be set in a JSON config file and loaded into code, as opposed to needing to be passed in via the command line.
58+
59+
**Usage:**
60+
- All example NFs now support passing DPDK and ONVM arguments in a config file by using the `-F config.json` flag when running an NF executable or a `go.sh` script. See `docs/examples.md` for more details.
61+
62+
**API Changes:**
63+
- `nflib.c` was not changed from an NF-developer standpoint, but it was modified to include a check for the `-F` flag, which indicates that a config file should be read to launch an NF.
64+
65+
**API Additions:**
66+
- `cJSON* onvm_config_parse_file(const char* filename)` - Reads a JSON config and stores the contents in a cJSON struct. For further reference on cJSON, see its [documentation](https://github.com/DaveGamble/cJSON).
67+
- `int onvm_config_create_nf_arg_list(cJSON* config, int* argc, char** argv[])`: Given a cJSON struct and pointers to the original command line arguments, generate a new `argc` and `argv` using the config file values.
68+
5669
## v18.05 (5/31/18): Bug Fixes, Latency Measurements, and Docker Image
5770
This release adds a feature to the Speed Tester example NF to support latency measurements by using the `-l` flag. Latency is calculated by writing a timestamp into the packet body and comparing this value when the packet is returned to the Speed Tester NF. A sample use case is to run 3 speed tester NFs configured to send in a chain, with the last NF sending back to the first. The first NF can use the `-l` flag to measure latency for this chain. Note that only one NF in a chain should be using the flag since otherwise timestamp information written to the packet will conflict.
5871

examples/aes_decrypt/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ ONVM= $(SRCDIR)/../../onvm
5656
CFLAGS += $(WERROR_FLAGS) -O3 $(USER_FLAGS)
5757

5858
CFLAGS += -I$(ONVM)/onvm_nflib
59+
CFLAGS += -I$(ONVM)/lib
5960
LDFLAGS += $(ONVM)/onvm_nflib/$(RTE_TARGET)/libonvm.a
61+
LDFLAGS += $(ONVM)/lib/$(RTE_TARGET)/lib/libonvmhelper.a -lm
6062

6163
# workaround for a gcc bug with noreturn attribute
6264
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603

examples/aes_decrypt/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,11 @@ Example
3434
./examples/aes_encrypt/go.sh 5 1 2
3535
./examples/aes_decrypt/go.sh 6 2 3
3636
./examples/bridge/go.sh 7 3
37+
38+
39+
Config File Support
40+
---
41+
This NF supports the NF generating arguments from a config file. For
42+
additional reading, see [Examples.md](../../docs/Examples.md)
43+
44+
See `../example_config.json` for all possible options that can be set.

examples/aes_decrypt/go.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,35 @@
22

33
function usage {
44
echo "$0 CPU-LIST SERVICE-ID DST [-p PRINT] [-n NF-ID]"
5+
echo "$0 -F config.json [remaining NF args]"
6+
echo ""
57
echo "$0 3 0 1 --> core 3, Service ID 0, and forwards to service 1"
8+
echo "$0 -F example_config.json -- -- -d 1 --> loads settings from example_config.json and forwards to Service ID 1"
69
echo "$0 3,7,9 1 2 --> cores 3,7, and 9 with Service ID 1, and forwards to service id 2"
710
echo "$0 -p 1000 -n 6 3,7,9 1 2 --> cores 3,7, and 9 with Service ID 1, Print Rate of 1000, instance ID 6, and forwards to service id 2"
811
exit 1
912
}
1013

1114
SCRIPT=$(readlink -f "$0");
1215
SCRIPTPATH=$(dirname "$SCRIPT");
16+
17+
if [ -z $1 ]
18+
then
19+
usage
20+
fi
21+
22+
if [ $1 = "-F" ]
23+
then
24+
config=$2
25+
shift 2
26+
echo $config
27+
echo "$@"
28+
exec sudo $SCRIPTPATH/build/app/aesdecrypt -F $config "$@"
29+
elif [ $1 = "-F" ]
30+
then
31+
usage
32+
fi
33+
1334
cpu=$1
1435
service=$2
1536
dst=$3

examples/aes_encrypt/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ ONVM= $(SRCDIR)/../../onvm
5656
CFLAGS += $(WERROR_FLAGS) -O3 $(USER_FLAGS)
5757

5858
CFLAGS += -I$(ONVM)/onvm_nflib
59+
CFLAGS += -I$(ONVM)/lib
5960
LDFLAGS += $(ONVM)/onvm_nflib/$(RTE_TARGET)/libonvm.a
61+
LDFLAGS += $(ONVM)/lib/$(RTE_TARGET)/lib/libonvmhelper.a -lm
6062

6163
# workaround for a gcc bug with noreturn attribute
6264
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603

examples/aes_encrypt/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ cd aes_encrypt
2121
2222
OR
2323
24+
./go -F CONFIG_FILE -- -- -d DST [-p PRINT_DELAY]
25+
26+
OR
27+
2428
sudo ./build/aesencrypt -l CORELIST -n 3 --proc-type=secondary -- -r SERVICE_ID -- -d DST [-p PRINT_DELAY]
2529
```
2630

@@ -34,3 +38,10 @@ Example
3438
./examples/aes_encrypt/go.sh 5 1 2
3539
./examples/aes_decrypt/go.sh 6 2 3
3640
./examples/bridge/go.sh 7 3
41+
42+
Config File Support
43+
--
44+
This NF supports the NF generating arguments from a config file. For
45+
additional reading, see [Examples.md](../../docs/Examples.md)
46+
47+
See `../example_config.json` for all possible options that can be set.

examples/aes_encrypt/go.sh

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,35 @@
22

33
function usage {
44
echo "$0 CPU-LIST SERVICE-ID DST [-p PRINT] [-n NF-ID]"
5+
echo "$0 -F CONFIG [remaining NF args]"
6+
echo ""
57
echo "$0 3 0 1 --> core 3, Service ID 0, and forwards to service 1"
8+
echo "$0 -F example_config.json -- -- -d 1 --> loads settings from example_config.json, forwards to service ID 1"
69
echo "$0 3,7,9 1 2 --> cores 3,7, and 9 with Service ID 1, and forwards to service id 2"
710
echo "$0 -p 1000 -n 6 3,7,9 1 2 --> cores 3,7, and 9 with Service ID 1, Print Rate of 1000, instance ID 6, and forwards to service id 2"
811
exit 1
912
}
1013

1114
SCRIPT=$(readlink -f "$0");
1215
SCRIPTPATH=$(dirname "$SCRIPT");
16+
17+
if [ -z $1 ]
18+
then
19+
usage
20+
fi
21+
22+
if [ $1 = "-F" ]
23+
then
24+
config=$2
25+
shift 2
26+
echo $config
27+
echo "$@"
28+
exec sudo $SCRIPTPATH/build/app/aesencrypt -F $config "$@"
29+
elif [ $1 = "-F" ]
30+
then
31+
usage
32+
fi
33+
1334
cpu=$1
1435
service=$2
1536
dst=$3
@@ -18,7 +39,7 @@ shift 3
1839

1940
if [ -z $dst ]
2041
then
21-
usage
42+
usage
2243
fi
2344

2445
while getopts ":p:n:" opt; do

examples/arp_response/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ ONVM= $(SRCDIR)/../../onvm
5555
CFLAGS += $(WERROR_FLAGS) -O3 $(USER_FLAGS)
5656

5757
CFLAGS += -I$(ONVM)/onvm_nflib
58+
CFLAGS += -I$(ONVM)/lib
5859
LDFLAGS += $(ONVM)/onvm_nflib/$(RTE_TARGET)/libonvm.a
60+
LDFLAGS += $(ONVM)/lib/$(RTE_TARGET)/lib/libonvmhelper.a -lm
5961

6062
include $(RTE_SDK)/mk/rte.extapp.mk

examples/arp_response/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ print]
1111
1212
OR
1313
14+
./go -F CONFIG_FILE -- -- -d DESTINATION_ID -s SOURCE_IP_LIST [-p enable print]
15+
16+
OR
17+
1418
sudo ./build/monitor -l CORELIST -n NUM_MEMORY_CHANNELS --proc-type=secondary -- -r SERVICE_ID -- -d DESTINATION_ID -s SOURCE_IP_LIST [-p ENABLE PRINT]
1519
```
1620

@@ -19,3 +23,10 @@ App Specific Arguments
1923
- `-d <destination_id>`: the NF will send non-ARP packets to the NF at this service ID, e.g. `-d 2` sends packets to service ID 2
2024
- `-s <source_ip_list>`: the NF will map each comma separated IP (no spaces) to the corresponding port. Example: `-s 10.0.0.31,11.0.0.31` maps port 0 to 10.0.0.31, and port 1 to 11.0.0.31. If 0.0.0.0 is inputted, the IP will be 0. If too few IPs are inputted, the remaining ports will be ignored.
2125
- `-p`: Enables printing of log information
26+
27+
Config File Support
28+
--
29+
This NF supports the NF generating arguments from a config file. For
30+
additional reading, see [Examples.md](../../docs/Examples.md)
31+
32+
See `../example_config.json` for all possible options that can be set.

examples/arp_response/go.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,31 @@
22

33
function usage {
44
echo "$0 CPU-LIST SERVICE-ID DST-SERVICE-ID -s SOURCE-IP"
5+
echo "$0 -F CONFIG-FILE -- -- -d DST -s SOURCE-IP"
6+
echo ""
57
echo "$0 4 1 2 -s 10.0.0.31,11.0.0.31 --> core 4, Service ID 1, Destination ID 2, Port 0: 10.0.0.31, Port 1: 11.0.0.31"
8+
echo "$0 -F example_config.json 1 -s 10.0.0.31,11.0.0.31 --> loads settings from example_config.json, destination ID 1, Port 0: 10.0.0.31, Port 1: 11.0.0.31"
69
exit 1
710
}
811

912
SCRIPT=$(readlink -f "$0")
1013
SCRIPTPATH=$(dirname "$SCRIPT")
14+
15+
if [ -z $1 ]
16+
then
17+
usage
18+
fi
19+
20+
if [ $1 = "-F" ]
21+
then
22+
config=$2
23+
shift 2
24+
exec sudo $SCRIPTPATH/build/app/arp_response -F $config "$@"
25+
elif [ $1 = "-F" ]
26+
then
27+
usage
28+
fi
29+
1130
cpu=$1
1231
service=$2
1332
dst=$3

examples/basic_monitor/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ SRCS-y := monitor.c
5252
# OpenNetVM path
5353
ONVM= $(SRCDIR)/../../onvm
5454

55-
CFLAGS += $(WERROR_FLAGS) -O3
55+
CFLAGS += $(WERROR_FLAGS) -O3 -g
5656

5757
CFLAGS += -I$(ONVM)/onvm_nflib
58+
CFLAGS += -I$(ONVM)/lib
5859
LDFLAGS += $(ONVM)/onvm_nflib/$(RTE_TARGET)/libonvm.a
60+
LDFLAGS += $(ONVM)/lib/$(RTE_TARGET)/lib/libonvmhelper.a -lm
5961

6062
include $(RTE_SDK)/mk/rte.extapp.mk

examples/basic_monitor/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,20 @@ cd basic_monitor
1212
1313
OR
1414
15+
./go.sh -F CONFIG_FILE -- -- [-p PRINT_DELAY]
16+
17+
OR
18+
1519
sudo ./build/monitor -l CORELIST -n NUM_MEMORY_CHANNELS --proc-type=secondary -- -r SERVICE_ID -- [-p PRINT_DELAY]
1620
```
1721

1822
App Specific Arguments
1923
--
2024
- `-p <print_delay>`: number of packets between each print, e.g. `-p 1` prints every packets.
25+
26+
Config File Support
27+
--
28+
This NF supports the NF generating arguments from a config file. For
29+
additional reading, see [Examples.md](../../docs/Examples.md)
30+
31+
See `../example_config.json` for all possible options that can be set.

examples/basic_monitor/go.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,30 @@
22

33
function usage {
44
echo "$0 CPU-LIST SERVICE-ID [-p PRINT] [-n NF-ID]"
5+
echo "$0 -F config.json -p 1"
6+
echo ""
57
echo "$0 3 0 --> core 3, Service ID 0"
68
echo "$0 3,7,9 1 --> cores 3,7, and 9 with Service ID 1"
9+
echo "$0 -F config.json -p 2 --> loads values from config.json and print rate of 2"
710
echo "$0 -p 1000 -n 6 3,7,9 1 --> cores 3,7, and 9 with Service ID 1 and Print Rate of 1000 and instance ID 6"
811
exit 1
912
}
1013

1114
SCRIPT=$(readlink -f "$0")
1215
SCRIPTPATH=$(dirname "$SCRIPT")
16+
17+
if [ -z $1 ]
18+
then
19+
usage
20+
fi
21+
22+
if [ $1 = "-F" ]
23+
then
24+
config=$2
25+
shift 2
26+
exec sudo $SCRIPTPATH/build/app/monitor -F $config "$@"
27+
fi
28+
1329
cpu=$1
1430
service=$2
1531

examples/basic_monitor/monitor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, __attribute__((
177177

178178
int main(int argc, char *argv[]) {
179179
int arg_offset;
180-
181180
const char *progname = argv[0];
182181

183182
if ((arg_offset = onvm_nflib_init(argc, argv, NF_TAG, &nf_info)) < 0)
184183
return -1;
184+
185185
argc -= arg_offset;
186186
argv += arg_offset;
187187

0 commit comments

Comments
 (0)