L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
options.cc
1/*
2 * Copyright (C) 2016-2017, 2019, 2022-2024 Kernkonzept GmbH.
3 * Author(s): Jean Wolter <jean.wolter@kernkonzept.com>
4 * Manuel von Oltersdorff-Kalettka <manuel.kalettka@kernkonzept.de>
5 *
6 * License: see LICENSE.spdx (in this directory or the directories above)
7 */
8
9#include <getopt.h>
10#include <stdlib.h>
11#include <cstring>
12#include <type_traits>
13
14#include <l4/cxx/exceptions>
15#include <l4/re/error_helper>
16#include <l4/re/env>
17
18#include "debug.h"
19#include "options.h"
20
21bool
22parse_int_optstring(char const *optstring, int *out)
23{
24 char *endp;
25
26 errno = 0;
27 long num = strtol(optstring, &endp, 10);
28
29 // check that long can be converted to int
30 if (errno || *endp != '\0' || num < INT_MIN || num > INT_MAX)
31 return false;
32
33 *out = num;
34
35 return true;
36}
37
38static int
39verbosity_mask_from_string(char const *str, unsigned *mask)
40{
41 if (strcmp("quiet", str) == 0)
42 {
43 *mask = Dbg::Quiet;
44 return 0;
45 }
46 if (strcmp("warn", str) == 0)
47 {
48 *mask = Dbg::Warn;
49 return 0;
50 }
51 if (strcmp("info", str) == 0)
52 {
53 *mask = Dbg::Warn | Dbg::Info;
54 return 0;
55 }
56 if (strcmp("debug", str) == 0)
57 {
58 *mask = Dbg::Warn | Dbg::Info | Dbg::Debug;
59 return 0;
60 }
61 if (strcmp("trace", str) == 0)
62 {
63 *mask = Dbg::Warn | Dbg::Info | Dbg::Debug | Dbg::Trace;
64 return 0;
65 }
66
67 return -L4_ENOENT;
68}
69
99static void
100set_verbosity(char const *str)
101{
102 unsigned mask;
103 if (verbosity_mask_from_string(str, &mask) == 0)
104 {
105 Dbg::set_verbosity(mask);
106 return;
107 }
108
109 static char const *const components[] =
110 { "core", "virtio", "port", "request", "queue", "packet" };
111
112 static_assert(std::extent<decltype(components)>::value == Dbg::Max_component,
113 "Component names must match 'enum Component'.");
114
115 for (unsigned i = 0; i < Dbg::Max_component; ++i)
116 {
117 auto len = strlen(components[i]);
118 if (strncmp(components[i], str, len) == 0 && str[len] == '='
119 && verbosity_mask_from_string(str + len + 1, &mask) == 0)
120 {
121 Dbg::set_verbosity(i, mask);
122 return;
123 }
124 }
125}
126
127int
128Options::parse_cmd_line(int argc, char **argv,
129 std::shared_ptr<Ds_vector> trusted_dataspaces)
130{
131 int opt, index;
132
133 struct option options[] =
134 {
135 {"size", 1, 0, 's' }, // size of in/out queue == #buffers in queue
136 {"ports", 1, 0, 'p' }, // number of ports
137 {"mac", 0, 0, 'm' }, // switch sets MAC address for each client
138 {"debug", 1, 0, 'D' }, // configure debug levels
139 {"verbose", 0, 0, 'v' },
140 {"quiet", 0, 0, 'q' },
141 {"register-ds", 1, 0, 'd' }, // register a trusted dataspace
142 {0, 0, 0, 0}
143 };
144
145 unsigned long verbosity = Dbg::Warn;
146
147 Dbg info(Dbg::Core, Dbg::Info);
148
149 Dbg::set_verbosity(Dbg::Core, Dbg::Info);
150 info.printf("Arguments:\n");
151 for (int i = 0; i < argc; ++i)
152 info.printf("\t%s\n", argv[i]);
153
154 Dbg::set_verbosity(verbosity);
155 while ( (opt = getopt_long(argc, argv, "s:p:mqvD:d:", options, &index)) != -1)
156 {
157 switch (opt)
158 {
159 case 's':
160
161 // QueueNumMax must be power of 2 between 1 and 0x8000
162 if (!parse_int_optstring(optarg, &_virtq_max_num)
163 || _virtq_max_num < 1 || _virtq_max_num > 32768
164 || (_virtq_max_num & (_virtq_max_num - 1)))
165 {
166 Err().printf("Max number of virtqueue buffers must be power of 2"
167 " between 1 and 32768. Invalid value %i or argument "
168 "%s\n",
169 _virtq_max_num, optarg);
170 return -1;
171 }
172 info.printf("Max number of buffers in virtqueue: %i\n",
173 _virtq_max_num);
174 break;
175 case 'p':
176 if (parse_int_optstring(optarg, &_max_ports))
177 info.printf("Max number of ports: %u\n", _max_ports);
178 else
179 {
180 Err().printf("Invalid number of ports argument: %s\n", optarg);
181 return -1;
182 }
183 break;
184 case 'q':
185 verbosity = Dbg::Quiet;
186 Dbg::set_verbosity(verbosity);
187 break;
188 case 'v':
189 verbosity = (verbosity << 1) | 1;
190 Dbg::set_verbosity(verbosity);
191 break;
192 case 'D':
193 set_verbosity(optarg);
194 break;
195 case 'm':
196 info.printf("Assigning mac addresses\n");
197 _assign_mac = true;
198 break;
199 case 'd':
200 {
202 L4Re::chkcap(L4Re::Env::env()->get_cap<L4Re::Dataspace>(optarg),
203 "Find a dataspace capability.\n");
204 trusted_dataspaces->push_back(ds);
205 break;
206 }
207 default:
208 Err().printf("Unknown command line option '%c' (%d)\n", opt, opt);
209 return -1;
210 }
211 }
212 return 0;
213}
214
215static Options options;
216
217Options const *
218Options::get_options()
219{ return &options; }
220
221Options const *
222Options::parse_options(int argc, char **argv,
223 std::shared_ptr<Ds_vector> trusted_dataspaces)
224{
225 if (options.parse_cmd_line(argc, argv, trusted_dataspaces) < 0)
226 return nullptr;
227
228 return &options;
229}
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:95
C++ interface for capabilities.
Definition capability.h:219
Environment interface.
Error helper.
Base exceptions.
getopt
@ L4_ENOENT
No such entity.
Definition err.h:34
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:149
Debug C interface.