summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* xxxxxxth/cli-globals-2Thomas Haller2020-04-0413-1181/+1596
|
* cli: merge branch 'th/cli-globals'Thomas Haller2020-04-049-49/+78
|\
| * cli: hide nm_cli global variable from public headersThomas Haller2020-04-043-5/+2
| |
| * cli: avoid using nm_cli global variable in print_data()Thomas Haller2020-04-044-21/+41
| |
| * cli: avoid passing full NmCli global variable to nm_cli_spawn_pager()Thomas Haller2020-04-045-12/+20
| | | | | | | | | | | | | | | | We should not use global variables, and we should minimize the state that we pass around. Instead of requiring the full NmCli struct in nm_cli_spawn_pager(), pass only the necessary data. This reduces our use of global variables.
| * cli: make nmc_meta_environment_arg const pointerThomas Haller2020-04-044-8/+8
| | | | | | | | | | Of course, we later pass the point on, where we need to cast the constness away again. This is more a reminder that we aren't suppost to change the variable.
| * cli: add and use nm_cli_global_readline global variableThomas Haller2020-04-044-6/+10
|/ | | | | | | | | We should try to avoid access to global variables. For libreadline callbacks we still need a global variable. Introduce a global variable nm_cli_global_readline, specially for this use. It makes the places clear where we use it, and discourages the use at other places, where we better avoid global variables.
* merge branch 'th/strbuf-v2'Thomas Haller2020-04-0411-71/+686
|\ | | | | | | https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/432
| * shared: use NMStrBuf in _nm_utils_enum_to_str_full()th/strbuf-v2Thomas Haller2020-04-031-10/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Just for showcase and to hit the code from the unit-tests that we have. Also, just to show, the following runs about 25 % faster than before, which isn't bad for such a simple replacement. { GType gtype = nm_test_general_color_flags_get_type (); const int N_RUN = 1000000; int i_run; guint8 c = 0; for (i_run = 0; i_run < N_RUN; i_run++) { gs_free char *str = NULL; str = _nm_utils_enum_to_str_full (gtype, i_run % 10, ",", NULL); c += str[0]; } return c % 3; } $ perf stat -r 200 -B libnm-core/tests/test-general Before: Performance counter stats for 'libnm-core/tests/test-general' (200 runs): 204.48 msec task-clock:u # 0.997 CPUs utilized ( +- 0.53% ) 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 267 page-faults:u # 0.001 M/sec ( +- 0.05% ) 702,987,494 cycles:u # 3.438 GHz ( +- 0.54% ) 1,698,874,415 instructions:u # 2.42 insn per cycle ( +- 0.00% ) 410,394,229 branches:u # 2006.970 M/sec ( +- 0.00% ) 1,770,484 branch-misses:u # 0.43% of all branches ( +- 0.40% ) 0.20502 +- 0.00108 seconds time elapsed ( +- 0.53% ) After: Performance counter stats for 'libnm-core/tests/test-general' (200 runs): 155.71 msec task-clock:u # 0.996 CPUs utilized ( +- 0.50% ) 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 266 page-faults:u # 0.002 M/sec ( +- 0.05% ) 539,994,118 cycles:u # 3.468 GHz ( +- 0.49% ) 1,116,016,733 instructions:u # 2.07 insn per cycle ( +- 0.00% ) 283,974,158 branches:u # 1823.760 M/sec ( +- 0.00% ) 1,377,786 branch-misses:u # 0.49% of all branches ( +- 0.43% ) 0.156255 +- 0.000786 seconds time elapsed ( +- 0.50% )
| * shared: pre-allocate GString with 16 bytes for _nm_utils_enum_to_str_full()Thomas Haller2020-04-031-1/+1
| | | | | | | | | | | | | | In the next commit, GString will be replaced by NMStrBuf. Then, we will pre-allocate a string buffer with 16 bytes, and measure the performance difference. To have it comparable, adjust the pre-allocation size also with GString.
| * shared: use NMStrBuf for implementing nm_utils_str_utf8safe_unescape()Thomas Haller2020-04-031-9/+8
| |
| * shared: use nm_utils_buf_utf8safe_unescape() for ↵Thomas Haller2020-04-031-6/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | nm_utils_str_utf8safe_unescape() nm_utils_buf_utf8safe_unescape() is almost the same as g_strcompress(), with the only difference is that if the string contains NUL escapes "\000", it will be handled correctly. In other words, g_strcompress() and nm_utils_str_utf8safe_unescape() can only unescape values, that contain no NUL escapes. That's why we added our own binary unescape function. As we already have our g_strcompress() variant, use it. It just gives it more testing and usage. Also, we have full control over it's behavior. For example, g_strcompress() issues a g_warning() when encountering a trailing '\\'. I think this makes it unsuitable to unescape untrusted data. Either the function should fail, or just make the best of it. Currently, our implementation does the latter.
| * shared: add NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET flagThomas Haller2020-04-033-16/+22
| | | | | | | | | | The new flag tells that as we re-allocate data buffers during escaping, we bzero the memory to avoid leaking secrets.
| * shared: add NMStrBuf utilThomas Haller2020-04-033-0/+276
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Our own implementation of a string buffer like GString. Advantages (in decreasing relevance): - Since we are in control, we can easily let it nm_explicit_bzero() the memory. The regular GString API cannot be used in such a case. While nm_explicit_bzero() may or may not be of questionable benefit, the problem is that if the underlying API counteracts the aim of clearing memory, it gets impossible. As API like NMStrBuf supports it, clearing memory is a easy as enable the right flag. This would for example be useful for example when we read passwords from a file or file descriptor (e.g. try_spawn_vpn_auth_helper()). - We have API like nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size); which accept a fixed size output buffer. This has the problem of how choosing the right sized buffer. With NMStrBuf such API could be instead nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, NMStrBuf *buf); which can automatically grow (using heap allocation). It would be easy to extend NMStrBuf to use a fixed buffer or limiting the maximum string length. The point is, that the to-string API wouldn't have to change. Depending on the NMStrBuf passed in, you can fill an unbounded heap allocated string, a heap allocated string up to a fixed length, or a static string of fixed length. NMStrBuf currently only implements the unbounded heap allocate string case, but it would be simple to extend. Note that we already have API like nm_utils_strbuf_*() to fill a buffer of fixed size. GString is not useable for that (efficiently), hence this API exists. NMStrBuf could be easily extended to replace this API without usability or performance penalty. So, while this adds one new API, it could replace other APIs. - GString always requires a heap allocation for the container. In by far most of the cases where we use GString, we use it to simply construct a string dynamically. There is zero use for this overhead. If one really needs a heap allocated buffer, NMStrBuf can easily embedded in a malloc'ed memory and boxed that way. - GString API supports inserting and removing range. We almost never make use of that. We only require append-only, which is simple to implement. - GString needs to NUL terminate the buffer on every append. It has unnecessary overhead for allowing a usage of where intermediate buffer contents are valid strings too. That is not the case with NMStrBuf: the API requires the user to call nm_str_buf_get_str() or nm_str_buf_finalize(). In most cases, you would only access the string once at the end, and not while constructing it. - GString always grows the buffer size by doubling it. I don't think that is optimal. I don't think there is one optimal approach for how to grow the buffer, it depends on the usage patterns. However, trying to make an optimal choice here makes a difference. QT also thinks so, and I adopted their approach in nm_utils_get_next_realloc_size().
| * shared: add nm_utils_get_next_realloc_size() helperThomas Haller2020-04-033-0/+222
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When growing a buffer by appending a previously unknown number of elements, the often preferable strategy is growing it exponentially, so that the amortized runtime and re-allocation costs scale linearly. GString just always increases the buffer length to the next power of two. That works. I think there is value in trying to find an optimal next size. Because while it doesn't matter in terms of asymptotic behavior, in practice a better choice should make a difference. This is inspired by what QT does ([1]), to take more care when growing the buffers: - QString allocates 4 characters at a time until it reaches size 20. - From 20 to 4084, it advances by doubling the size each time. More precisely, it advances to the next power of two, minus 12. (Some memory allocators perform worst when requested exact powers of two, because they use a few bytes per block for book-keeping.) - From 4084 on, it advances by blocks of 2048 characters (4096 bytes). This makes sense because modern operating systems don't copy the entire data when reallocating a buffer; the physical memory pages are simply reordered, and only the data on the first and last pages actually needs to be copied. Note that a QT is talking about 12 characters, so we use 24 bytes head room. [1] https://doc.qt.io/qt-5/containers.html#growth-strategies
| * shared: use nm_secret_mem_try_realloc_take() in nm_utils_fd_get_contents()Thomas Haller2020-04-031-29/+3
| |
| * shared: add nm_secret_mem_realloc() helpersThomas Haller2020-04-031-0/+121
| |
| * shared: use G_UNLIKELY() macro for unlikely branch in nm_explicit_bzero()Thomas Haller2020-04-031-1/+1
| |
| * shared/tests: add nmtst_get_rand_size()Thomas Haller2020-04-031-0/+10
|/
* wifi: merge branch 'th/fix-wifi-scan-1'Thomas Haller2020-04-0315-399/+481
|\ | | | | | | https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/445
| * wifi: rework scanning-prohibited tracking for Wi-Fi companion and OLPC deviceThomas Haller2020-04-033-48/+86
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was previously tracked via a signal "scanning-prohibited". However, I think it was buggy, because the signal didn't specify a GSignalAccumulator, so when a NMDeviceOlpcMesh registered a handler, NMDeviceWifi.scanning_prohibited() was ignored. In theory, a GObject signal decouples the target and source of the signal and is more abstract. But more abstraction is worse, if there is exactly one target who cares about this signal: the OLPC mesh. And that target is well known at compile time. So, don't pretend that NMDeviceWifi or NMDeviceOlpcMesh aren't aware that they are together in this. Another downside of the signal is that you don't know when scanning gets unblocked. You can only poll and asked whether it is blocked, but there was no mechanism how NMDeviceWifi would be notified when scanning is no longer blocked. Rework this. Instead, the OLPC mesh explicitly registers and unregisters its blocking state with nm_device_wifi_scanning_prohibited_track().
| * wifi: add and use nm_device_wifi_get_scanning()Thomas Haller2020-04-033-7/+16
| | | | | | | | | | Don't read GObject properties. It's inefficient and harder to track who calls who.
| * wifi/iwd: drop unused signal NM_DEVICE_IWD_SCANNING_PROHIBITEDThomas Haller2020-04-032-33/+3
| |
| * wifi: rename scan-interval variable to indicate they are in secondsThomas Haller2020-04-031-21/+21
| |
| * wifi: parse RequestScan D-Bus arguments before authenticating requestThomas Haller2020-04-031-23/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It feels better to first parse input arguments before authenticating. One argument for otherwise would be that we shouldn't reveal any information about the request before authenticating it. Meaning: every request (even with invalid arguments) should fail with permission-denied. However, I prefer this for minor reasons: - what makes a valid request is no secret. And if somebody makes an invalid request, it should fail with invalid-arguments first. - we possibly can short cut the expensive authentication process, where we ask PolicyKit. - by extracting the options variant early and only pass on the SSIDs array, we handle the encoding of the options array earlier and where it belongs: closer to the D-Bus request that defines the meaning of the argument. Also, change the failure reason to return invalid-argument.
| * wifi: drop workaround for bad values in nm_platform_wifi_get_quality()Thomas Haller2020-04-031-6/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was first introduced by commit 4ed4b491fa75 ('2005-12-31 Dan Williams <dcbw@redhat.com>'), a very long time ago. It got reworked several times, but I don't think this code makes sense anymore. So, if nm_platform_wifi_get_quality() returns an error, we would ignore it for three times, until we would set the strength to the error code (presumably -1). Why? If we cannot read the strength via nl80211/WEXT, then we should just keep whatever we got from supplicant. Drop this. Also, only accept the percentage if it is in a valid range from 0 to 100%. If the driver (or platform code) gives us numbers out of that range, we have no idea what their meaning is. In that case, the value must be fixed in the lower layers, that knows how to convert the value from the actual meaning to the requested percentage.
| * wifi: cleanup periodic_update() in "nm-device-wifi.c"Thomas Haller2020-04-032-28/+41
| |
| * wifi/trivial: rename function nm_supplicant_interface_state_is_operational() ↵Thomas Haller2020-04-035-12/+12
| | | | | | | | from upper case name
| * wifi: fix and improve handling of Wi-Fi scanning stateThomas Haller2020-04-033-81/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In NMSupplicantInterface, we determine whether we currently are scanning both on the "scanning" supplicant state and the "Scanning" property. Extend that. If we currently are scanning and are about to clear the scanning state, then pretend to still scan as long as we are still initializing BSS instances. What otherwise happens is that we declare that we finished scanning, but the NMWifiAP instances are not yet ready. The result is, that `nmcli device wifi` will already start printing the scan list, when we didn't yet fully process all access points. Now, _notify_maybe_scanning() will delay switching the scanning state to disabled, as long as we have BSS initializing (bss_initializing_lst_head). Also, ignore the "ScanDone" signal. It's redundant to the "Scanning" property anyway. Also, only set priv->last_scan_msec when we switch the scanning state off. That is the right (and only) place where the last-scan timestamp needs updating.
| * wifi: print age of Wi-Fi access point with milliseconds precisionThomas Haller2020-04-034-19/+31
| | | | | | | | | | For a computer a second is a really long time. Rounding times to seconds feels unnecessarily inaccurate.
| * wifi/trivial: rename field NMDeviceWifiPrivate.last_scan to last_scan_msecThomas Haller2020-04-031-6/+7
| |
| * supplicant: cleanup notify signals for combined properties in supplicant (2)Thomas Haller2020-04-031-42/+37
| |
| * supplicant: cleanup notify signals for combined properties in supplicantThomas Haller2020-04-031-30/+43
| | | | | | | | | | | | | | | | | | | | | | Certain properties (for example "scanning") are combined from multiple other properties. So, we want to notify a changed signal, exactly when something relevant changes. We also may not want to emit a signal while we are still in the middle of changing multiple properties together. Only at certain places we want to check and emit the signal. Simplify the implementation for that by tracking the property value that we currently expose, and keeping state about when it changes.
| * supplicant: log message whenever we request scanningThomas Haller2020-04-031-4/+6
| | | | | | | | It's important to clearly see in the log when we actually request a scan.
| * cli: fix `nmcli device wifi list --rescan=yes` to waitThomas Haller2020-04-031-2/+1
| | | | | | | | Fixes: db396cea9d37 ('cli: rework do_device_wifi_list() to scan and print Wi-Fi list')
| * shared: cleanup _get_hash_key_init() and better explain the reasoningThomas Haller2020-04-032-44/+49
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - add more code comments - refactor the code flow in _get_hash_key_init() to follow a simpler code path. - use c_siphash_hash() instead of 3 separate steps. - Drop "?: static_seed" from nm_hash_static(). It's not useful, because the only _get_hash_key() for which _get_hash_key()^static_seed is zero is ~static_seed. That means, only one value of all the static seeds can result in zero here. At that point, we can just coerce that value to 3679500967u directly.
| * shared: add nm_pgbytes_hash()/nm_pgbytes_equal()Thomas Haller2020-04-032-0/+27
| | | | | | | | | | | | | | For hashing of a pointer to a GBytes*. This is useful if your key is a GBytes array, and the first field in your to be hashed struct.
| * shared: add nm_hash_mem() helperThomas Haller2020-04-031-0/+12
| |
| * shared: accept empty buffer for nm_hash_update()Thomas Haller2020-04-031-2/+1
|/ | | | | There is no need to reject empty buffers. c_siphash_append() handles them gracefully.
* IPv6 SLAAC: Honor small PIO Valid LifetimesFernando Gont2020-04-022-26/+18
| | | | | | | | | | | | | | | This commit implements Section 4.2 of <https://tools.ietf.org/html/draft-gont-6man-slaac-renum-05>, to improve the reaction of IPv6 SLAAC to renumbering events. Namely: * It honors PIO Valid Lifetimes < 2 hours, deviating from item "e)" (pp. 19-20) of Section 5.5.3 of RFC4862. [thaller@redhat.com: squash commits and adjust unit test] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/454
* gitlab-ci: use old meson version on Ubuntu 16.04 to work with ninja-1.5.1Thomas Haller2020-04-021-1/+2
| | | | | | | | | | | | | | | | | | | | Meson 0.54.0 requires ninja-1.7 ([1]). On Ubuntu 16.04, we now would get meson 0.54.0 via pip3, but ninja-1.5.1 via apt. That doesn't work anymore. We could install ninja via pip3, but of course, doing that on other Debian/Ubuntu versions fails due to ... I don't even want to know. So, instead use an old meson version on Ubuntu 16.04, which is known to still work with the ninja provided by the packaging system. We anyway don't want to test the same meson/ninja versions on all our Ubuntu/Debian images. The point of having different images is to build with different software versions. If `pip3 install` gives us the same everywhere, it isn't very useful. https://mesonbuild.com/Release-notes-for-0-54-0.html#ninja-version-requirement-bumped-to-17
* contrib/rpm: avoid bare words in spec fileThomas Haller2020-04-021-2/+2
| | | | | | | error: bare words are no longer supported, please use "...": "x" != x error: ^ error: /root/nm-build/NetworkManager/contrib/fedora/rpm/NetworkManager.20200402-030113.Hk7EGs/SPECS/NetworkManager.spec:32: bad %if condition: "x" != x ERROR: rpmbuild FAILED
* gitlab-ci: set DEBIAN_FRONTEND=noninteractive for `apt-get install`Thomas Haller2020-04-021-2/+2
| | | | | Otherwise, installing a package might prompt for the user to type something, breaking the CI build.
* all: merge branch 'th/strtoll-workaround'Thomas Haller2020-04-029-35/+186
|\ | | | | | | | | | | https://bugzilla.redhat.com/show_bug.cgi?id=1797915 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/456
| * all: use wrappers for g_ascii_strtoll(), g_ascii_strtoull(), g_ascii_strtod()th/strtoll-workaroundThomas Haller2020-04-013-24/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Sometimes these function may set errno to unexpected values like EAGAIN. This causes confusion. Avoid that by using our own wrappers that retry in that case. For example, in rhbz#1797915 we have failures like: errno = 0; v = g_ascii_strtoll ("10", 0, &end); if (errno != 0) g_assert_not_reached (); as g_ascii_strtoll() would return 10, but also set errno to EAGAIN. Work around that by using wrapper functions that retry. This certainly should be fixed in glib (or glibc), but the issues are severe enough to warrant a workaround. Note that our workarounds are very defensive. We only retry 2 times, if we get an unexpected errno value. This is in the hope to recover from a spurious EAGAIN. It won't recover from other errors. https://bugzilla.redhat.com/show_bug.cgi?id=1797915
| * shared: add nm_g_ascii_strtoull() to workaround bugThomas Haller2020-04-012-0/+53
| |
| * shared: add nm_g_ascii_strtod() to workaround bugThomas Haller2020-04-012-0/+40
| |
| * shared: add nm_g_ascii_strtoll() to workaround bugThomas Haller2020-04-012-0/+70
| |
| * device/bluetooth: avoid g_ascii_strtoull() to parse capabilitiesThomas Haller2020-04-011-1/+1
| | | | | | | | | | Avoid g_ascii_strtoull() calling directly. It has subtle issues, which is why we have a wrapper for it.
| * ifupdown: use _nm_utils_ascii_str_to_int64() for converting netmask to stringThomas Haller2020-04-011-7/+4
| |