Several properties like "connection.type" are enum-like and only take a few
known values. We can use a NMRefString to share their instances.
Currently nm_setting_duplicate() does not yet explicitly handle direct properties.
But it should, because it can handle them more efficiently. If it would do that, it
would be very cheap to "copy" a NMRefString. But even with the current implementation
will the result be deduplicated.
"wireguard.private-key" is special, because the setter does some unusual
normalization. To implement that, we need to use "direct_hook.set_string_func".
We want that our properties have little special cases and follow a
few common behaviors. For example, we have string properties, and those
should mostly behave the same (e.g. by being "direct-string"
properties).
That is already not fully enough, because we have slightly different
behaviors. For example, we have string properties that should have their
whitespace stripped, that should be ascii case down converted, that
should be normalized IP or MAC addresses. So far, that was expressed via
simple fields in NMSettInfoProperty, like NMSettInfoProperty's
direct_set_string_ascii_strdown field.
But that is not enough. In particular, for "wireguard.private-key" we
perform a different kind of normalization (base64 parsing, and taking
care not to leak secret in memory). It seems to special to add a boolean
flag "direct_set_string_wireguard_private_key".
Instead, add a hook that can cover that.
We need a hook, because we want one setter implementation throughout. Commonly,
we have at least two setters: the GObject set_property() and from D-Bus.
Both should call into the same underlying implementation, to avoid code
duplication. For that, the tweaked behavior must be "down", that is at
the deepest point in the call stack where we set the string. That's why
we need the hook. The alternative would be two special implementation
for GObject and D-Bus setters (and in the future we might add setters
from keyfile).
Both callers themselves needed to call _nm_setting_get_private(),
only to pass it to _property_direct_set_string().
Instead, pass the necessary parameters to _property_direct_set_string(),
so it can do that itself.
This additional parameters will be necessary when we add a hook for
setting the string.
We cache the virtual-iface-name. The caching is also part of the API as
nm_setting_infiniband_get_virtual_interface_name() returns a const
string.
As the value is computed and based on the parent and the p-key, we must
clear the cache when the parent or p-key changes (or detect that it's
invalid).
Previously, we were simply clearing the value in the set_property() function,
which is the only setter of these two properties. If we make these
properties "direct properties", then they will be directly set via
from_dbus_fcn() which bypasses the GObject setter. Which is a problem
for the cache invalidation.
We could either not make those properties direct properties. The problem
is that direct properties are nice, and they will in the future
implement further optimizations for them. Also, they are the default
implementation, and it seems clearer to build something on top of that,
instead of deviating from the default.
Instead, let the caching detect when the value needs to be regenerated.
This seems a questionable thing to do, and should be made clearer by
having a parameter (that makes you think about what is happening here).
Also, the normalization for vxlan.remote does not perform this mapping,
so the parameter is there so that the approach can handle both flavors.
Let's sprinkle some snake ointment.
This is questionable, because we copy secrets all over the place where
we their deallocation (and clearing) is not in our control. For example,
the GValue setter/getter copies the string (but does not clean the
secret). Also, when converting the property to a GVariant, we won't
clear it. So this does not catch a lot of cases.
Still, if we can with relative ease avoid leaking the string at some
places, do it.
libnm's data structures are commonly not thread safe (like
NMConnection). However, it must be possible that all operations can
operate on *different* data in a thread safe manner. That means, we need
to take care about our global variables.
nm_utils_ssid_to_utf8() uses a list of encodings, which gets cached.
- replace the GHashTables with a static list. Since it doesn't cost
anything, make the list sorted and look it up via binary search.
nm_hash_str() has the proper name and signature for that it does.
That is, it has a "nm_hash_*" prefix and the parameter is of type
"const char *".
nm_hash_str() has this name because it is primarily about hashing.
For hash tables, glib has g_str_hash() and g_str_equal(). We want
to replace g_str_hash() with our implementation (nm_hash_str()) because
that uses siphash24 with a random seed.
But in those cases we want to use the more familiar name "nm_str_hash()",
which reminds of g_str_hash() and follows the pattern of g_str_equal().
Thus:
g_hash_table_new(nm_str_hash, g_str_equal);
is preferable over
g_hash_table_new(nm_hash_str, g_str_equal);
Hence, we have (and had) nm_str_hash() effectively an alias to
nm_hash_str.
The question is: which name is preferable? Or should they be both present
for their slightly distinct uses? The approach taken here is to have
both names, to reflect their purpose better.
But as the usage of nm_str_hash is as function pointer for GHashTable, it was
not an inline function and we'd pay a small overhead with this approach of
aliasing. Avoid that overhead by defining nm_str_hash with the C
preprocessor.
For similar reasons, do that for nm_direct_hash.
The force-commit flag is used to force the commit of an address or a
route from DHCP/RA even when it was removed from platform externally
(for example because it expired). Routes generated from the l3cd
should also have the flag set.
Without this, NM properly re-adds the DHCP address after the lease is
lost and obtained again, but fails to add the prefix-route.
Fixes: 2838b1c5e8 ('core: track force-commit flag for l3cd and platform objects')
https://bugzilla.redhat.com/show_bug.cgi?id=2033991https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1049
Consider externally removed IPv4LL bad, proceed as if a collision was
detected. Otherwise we trip an assert:
<trace> [1641816260.3963] l3cfg[b8bf8cd16ec4732e,ifindex=47]: emit signal (platform-change-on-idle, obj-type-flags=0x14)
**
nm:ERROR:src/core/nm-l3-ipv4ll.c:888:_ipv4ll_state_change: code should not be reached
Aborted (core dumped)
#3 0x00007f41621d020e in g_assertion_message_expr (domain=domain@entry=0x5559cd829140 "nm",
file=file@entry=0x5559cd823e51 "src/core/nm-l3-ipv4ll.c",
line=line@entry=888, func=func@entry=0x5559cd824d30 <__func__.38810> "_ipv4ll_state_change",
expr=expr@entry=0x0) at gtestutils.c:2556
#4 0x00005559cd719686 in _ipv4ll_state_change (self=0x5559cef886c0,
is_on_idle_handler=0) at src/core/nm-l3-ipv4ll.c:888
#8 0x00007f41626a5093 in <emit signal ??? on instance 0x5559ceffaa30 [NML3Cfg]>
(instance=instance@entry=0x5559ceffaa30, signal_id=<optimized out>,
detail=detail@entry=0) at gsignal.c:3448
#9 0x00005559cd511a03 in _nm_l3cfg_emit_signal_notify
(self=self@entry=0x5559ceffaa30 [NML3Cfg], notify_data=notify_data@entry=0x7ffd1caa8640)
at src/core/nm-l3cfg.c:576
#10 0x00005559cd5122dc in _nm_l3cfg_emit_signal_notify_acd_event (self=0x5559ceffaa30 [NML3Cfg],
acd_data=<optimized out>) at src/core/nm-l3cfg.c:2008
#11 0x00005559cd512463 in _nm_l3cfg_emit_signal_notify_acd_event_all
(self=0x5559ceffaa30 [NML3Cfg]) at src/core/nm-l3cfg.c:2041
#12 0x00005559cd5194ef in _l3_acd_nacd_event (fd=<optimized out>, condition=<optimized out>,
user_data=<optimized out>) at src/core/nm-l3cfg.c:1536
#13 0x00007f41621a895d in g_main_dispatch (context=0x5559ceec8bc0) at gmain.c:3193
#14 0x00007f41621a895d in g_main_context_dispatch (context=context@entry=0x5559ceec8bc0)
at gmain.c:3873
#15 0x00007f41621a8d18 in g_main_context_iterate (context=0x5559ceec8bc0, block=block@entry=1,
dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3946
#16 0x00007f41621a9042 in g_main_loop_run (loop=0x5559ceea40f0) at gmain.c:4142
#17 0x00005559cd47c7a4 in main (argc=<optimized out>, argv=<optimized out>)
at src/core/main.c:511
https://bugzilla.redhat.com/show_bug.cgi?id=2028404https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1059
Try to debug a hang in platform code, presumably during poll().
This logging seems useful for debugging this particular issue,
but it might be useful in general.
If the ovs interface goes away, the ifindex gets zeroed out and l3cfg is
cleaned. We can't follow up with IP configuration. Bad things happen if
we try to:
#0 0x00007f769734c895 in _g_log_abort (breakpoint=1) at gmessages.c:580
#1 0x00007f769734db98 in g_logv (log_domain=0x55b2472d8840 "nm",
log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>,
args=args@entry=0x7fff4041b9d0) at gmessages.c:1391
#2 0x00007f769734dd63 in g_log (log_domain=log_domain@entry=0x55b2472d8840 "nm",
log_level=log_level@entry=G_LOG_LEVEL_CRITICAL,
format=format@entry=0x7f769739a620 "%s: assertion '%s' failed") at gmessages.c:1432
#3 0x00007f769734e59d in g_return_if_fail_warning
(log_domain=log_domain@entry=0x55b2472d8840 "nm",
pretty_function=pretty_function@entry=0x55b2472d5fe0 <__func__.39677> "nm_lndp_ndisc_new",
expression=expression@entry=0x55b2472d5fa3 "NM_IS_L3CFG(config->l3cfg)")
at gmessages.c:2809
#4 0x000055b2471ce3fa in nm_lndp_ndisc_new (config=config@entry=0x7fff4041bb30)
at src/core/ndisc/nm-lndp-ndisc.c:680
#5 0x000055b247123b32 in _dev_ipac6_start (self=self@entry=0x55b248078360 [NMDeviceOvsInterface])
at src/core/devices/nm-device.c:11287
#6 0x000055b2471232f8 in _dev_ipac6_start_continue (self=0x55b248078360 [NMDeviceOvsInterface])
at src/core/devices/nm-device.c:11338
#7 0x000055b2471232f8 in _dev_ipll6_set_llstate (self=0x55b248078360 [NMDeviceOvsInterface],
llstate=<optimized out>, lladdr=<optimized out>) at src/core/devices/nm-device.c:10541
#8 0x000055b2471c9e8b in _emit_changed_on_idle_cb (user_data=user_data@entry=0x55b24807bdd0)
at src/core/nm-l3-ipv6ll.c:221
#9 0x00007f769734327b in g_idle_dispatch (source=0x55b248119200,
callback=0x55b2471c9ce0 <_emit_changed_on_idle_cb>,
user_data=0x55b24807bdd0) at gmain.c:5579
#10 0x00007f769734695d in g_main_dispatch (context=0x55b247f56bc0) at gmain.c:3193
#11 0x00007f769734695d in g_main_context_dispatch (context=context@entry=0x55b247f56bc0)
at gmain.c:3873
#12 0x00007f7697346d18 in g_main_context_iterate (context=0x55b247f56bc0,
block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3946
#13 0x00007f7697347042 in g_main_loop_run (loop=0x55b247f320f0) at gmain.c:4142
#14 0x000055b246f26b64 in main (argc=<optimized out>,
argv=<optimized out>) at src/core/main.c:511
https://bugzilla.redhat.com/show_bug.cgi?id=2012934https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1044
Fixes-test: @ovs_cloned_mac_set_on_iface
If the ovs interface goes away, the ifindex gets zeroed out and l3cfg is
cleaned. Avoid starting ac6 in that case -- add checks similar to what
we do for ll6.
Bad things happen otherwise:
#0 0x00007f769734c895 in _g_log_abort (breakpoint=1) at gmessages.c:580
#1 0x00007f769734db98 in g_logv (log_domain=0x55b2472d8840 "nm",
log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>,
args=args@entry=0x7fff4041b9d0) at gmessages.c:1391
#2 0x00007f769734dd63 in g_log (log_domain=log_domain@entry=0x55b2472d8840 "nm",
log_level=log_level@entry=G_LOG_LEVEL_CRITICAL,
format=format@entry=0x7f769739a620 "%s: assertion '%s' failed") at gmessages.c:1432
#3 0x00007f769734e59d in g_return_if_fail_warning
(log_domain=log_domain@entry=0x55b2472d8840 "nm",
pretty_function=pretty_function@entry=0x55b2472d5fe0 <__func__.39677> "nm_lndp_ndisc_new",
expression=expression@entry=0x55b2472d5fa3 "NM_IS_L3CFG(config->l3cfg)")
at gmessages.c:2809
#4 0x000055b2471ce3fa in nm_lndp_ndisc_new (config=config@entry=0x7fff4041bb30)
at src/core/ndisc/nm-lndp-ndisc.c:680
#5 0x000055b247123b32 in _dev_ipac6_start (self=self@entry=0x55b248078360 [NMDeviceOvsInterface])
at src/core/devices/nm-device.c:11287
#6 0x000055b2471232f8 in _dev_ipac6_start_continue (self=0x55b248078360 [NMDeviceOvsInterface])
at src/core/devices/nm-device.c:11338
#7 0x000055b2471232f8 in _dev_ipll6_set_llstate (self=0x55b248078360 [NMDeviceOvsInterface],
llstate=<optimized out>, lladdr=<optimized out>) at src/core/devices/nm-device.c:10541
#8 0x000055b2471c9e8b in _emit_changed_on_idle_cb (user_data=user_data@entry=0x55b24807bdd0)
at src/core/nm-l3-ipv6ll.c:221
#9 0x00007f769734327b in g_idle_dispatch (source=0x55b248119200,
callback=0x55b2471c9ce0 <_emit_changed_on_idle_cb>,
user_data=0x55b24807bdd0) at gmain.c:5579
#10 0x00007f769734695d in g_main_dispatch (context=0x55b247f56bc0) at gmain.c:3193
#11 0x00007f769734695d in g_main_context_dispatch (context=context@entry=0x55b247f56bc0)
at gmain.c:3873
#12 0x00007f7697346d18 in g_main_context_iterate (context=0x55b247f56bc0,
block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3946
#13 0x00007f7697347042 in g_main_loop_run (loop=0x55b247f320f0) at gmain.c:4142
#14 0x000055b246f26b64 in main (argc=<optimized out>,
argv=<optimized out>) at src/core/main.c:511
We need to first free "priv->bzobjs", which then will unlink all bzobjs
from the lists. The assert needs to go after.
https://bugzilla.redhat.com/show_bug.cgi?id=2028427
Fixes: 4154d9618c ('bluetooth: refactor BlueZ handling and let NMBluezManager cache ObjectManager data')
NMSettingOvsDpdk does not have a verify() implementation that would prevent
the devargs property from being NULL. We must thus anticipate and handle
a NULL value.
Fixes: ae4152120a ('ovs/ovsdb: add support for setting dpdk devargs option')