Commit graph

17 commits

Author SHA1 Message Date
Thomas Haller
f0442a47ed all: avoid calling g_free on a const pointer with g_clear_pointer()
With g_clear_pointer(pptr, g_free), pptr is cast to a non-const pointer,
and hence there is no compiler warning about calling g_free() in a const
pointer. However, it still feels ugly to pass a const pointer to
g_clear_pointer(). We should either add an explicity cast, or just
make the pointer non-const.

I guess part of the problem is that C's "const char *" means that the
string itself is immutable, but also that it cannot be freed. We most
often want a different semantic: the string itself is immutable after
being initialized once, but the memory itself can and will be freed.
Such a notion of immutable C strings cannot be expressed.

For that, just remove the "const" from the declarations. Although we
don't want to modify the (content of the) string, it's still more a
mutable string.

Only in _vt_cmd_obj_copy_lnk_vlan(), add an explicity cast but keep the
type as const. The reason is, that we really want that NMPObject
instances are immutable (in the sense that they don't modify while
existing), but that doesn't mean the memory cannot be freed.
2018-03-19 15:45:46 +01:00
Thomas Haller
297d4985ab core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.

Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.

This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.

This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.

Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.

Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.

Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.

Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.

Numbers (for contrib/rpm --without debug on x86_64):

- the patch changes the code size of NetworkManager by
  - 2809360 bytes
  + 2537528 bytes (-9.7%)

- Runtime measurements are harder because there is a large variance
  during testing. In other words, the numbers are not reproducible.
  Currently, the implementation performs no caching of GVariants at all,
  but it would be rather simple to add it, if that turns out to be
  useful.
  Anyway, without strong claim, it seems that the new form tends to
  perform slightly better. That would be no surprise.

  $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .;  done)
  - real    1m39.355s
  + real    1m37.432s

  $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
  - real    0m26.843s
  + real    0m25.281s

- Regarding RSS size, just looking at the processes in similar
  conditions, doesn't give a large difference. On my system they
  consume about 19MB RSS. It seems that the new version has a
  slightly smaller RSS size.
  - 19356 RSS
  + 18660 RSS
2018-03-12 18:37:08 +01:00
Beniamino Galvani
878a3a4125 ovs: don't consume error in method callback
The error should be freed by callback functions, but only
_monitor_bridges_cb() actually does it. Simplify this by letting the
caller own the error.

Fixes: 830a5a14cb
2018-02-21 14:04:21 +01:00
Beniamino Galvani
cf79615169 ovs: add error code for callbacks to indicate NM is quitting
When NM quits it destroys all singletons including NMOvsdb, which
invokes callbacks for every pending method call. In the shutdown,
extra care must be taken to not access objects that are already in a
inconsistent state; for example here, the callback changes the device
state, and this causes an access to data that has already been
cleared:

 #0  _g_log_abort (breakpoint=breakpoint@entry=1) at gmessages.c:554
 #1  g_logv (log_domain=0x5635653b6817 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffb4b2c1e0) at gmessages.c:1362
 #2  g_log (log_domain=log_domain@entry=0x5635653b6817 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7fbb3f58fa4a "%s: assertion '%s' failed") at gmessages.c:1403
 #3  g_return_if_fail_warning (log_domain=log_domain@entry=0x5635653b6817 "NetworkManager", pretty_function=pretty_function@entry=0x5635653b6b00 <__func__.34463> "nm_device_factory_manager_find_factory_for_connection", expression=expression@entry=0x5635653b6719 "factories_by_setting") at gmessages.c:2702
 #4  nm_device_factory_manager_find_factory_for_connection (connection=connection@entry=0x56356627e0e0) at src/devices/nm-device-factory.c:243
 #5  nm_manager_get_connection_iface (self=0x563566241080 [NMManager], connection=connection@entry=0x56356627e0e0, out_parent=out_parent@entry=0x0, error=error@entry=0x0) at src/nm-manager.c:1458
 #6  check_connection_compatible (self=<optimized out>, connection=0x56356627e0e0) at src/devices/nm-device.c:4679
 #7  check_connection_compatible (device=0x56356647b1b0 [NMDeviceOvsInterface], connection=0x56356627e0e0) at src/devices/ovs/nm-device-ovs-interface.c:95
 #8  _nm_device_check_connection_available (self=0x56356647b1b0 [NMDeviceOvsInterface], connection=0x56356627e0e0, flags=NM_DEVICE_CHECK_CON_AVAILABLE_NONE, specific_object=0x0) at src/devices/nm-device.c:12102
 #9  nm_device_check_connection_available (self=self@entry=0x56356647b1b0 [NMDeviceOvsInterface], connection=0x56356627e0e0, flags=flags@entry=NM_DEVICE_CHECK_CON_AVAILABLE_NONE, specific_object=specific_object@entry=0x0) at src/devices/nm-device.c:12131
 #10 nm_device_recheck_available_connections (self=self@entry=0x56356647b1b0 [NMDeviceOvsInterface]) at src/devices/nm-device.c:12238
 #11 _set_state_full (self=self@entry=0x56356647b1b0 [NMDeviceOvsInterface], state=state@entry=NM_DEVICE_STATE_FAILED, reason=reason@entry=NM_DEVICE_STATE_REASON_OVSDB_FAILED, quitting=quitting@entry=0) at src/devices/nm-device.c:13065
 #12 nm_device_state_changed (self=self@entry=0x56356647b1b0 [NMDeviceOvsInterface], state=state@entry=NM_DEVICE_STATE_FAILED, reason=reason@entry=NM_DEVICE_STATE_REASON_OVSDB_FAILED) at src/devices/nm-device.c:13328
 #13 del_iface_cb (error=<optimized out>, user_data=0x56356647b1b0) at src/devices/ovs/nm-device-ovs-port.c:160
 #14 _transact_cb (self=self@entry=0x5635662b9ba0 [NMOvsdb], result=result@entry=0x0, error=0x563566259a10, user_data=user_data@entry=0x5635662ff320) at src/devices/ovs/nm-ovsdb.c:1449
 #15 ovsdb_disconnect (self=self@entry=0x5635662b9ba0 [NMOvsdb]) at src/devices/ovs/nm-ovsdb.c:1331
 #16 dispose (object=0x5635662b9ba0 [NMOvsdb]) at src/devices/ovs/nm-ovsdb.c:1558
 #17 g_object_unref (_object=0x5635662b9ba0) at gobject.c:3293
 #18 _nm_singleton_instance_destroy () at src/nm-core-utils.c:138
 #19 _dl_fini () at dl-fini.c:253
 #20 __run_exit_handlers (status=status@entry=0, listp=0x7fbb3e1ad6c8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:77
 #21 __GI_exit (status=status@entry=0) at exit.c:99
 #22 main (argc=1, argv=0x7fffb4b2cc38) at src/main.c:468

Add a new error code to indicate to callbacks that we are quitting and
no further action must be taken. This is preferable to having
additional references because it allows us to free the resources owned
by callbacks immediately, while references can easily create loops.

https://bugzilla.redhat.com/show_bug.cgi?id=1543871
2018-02-21 11:44:25 +01:00
Thomas Haller
574f2744dc ovs/trivial: fix indentation 2018-02-09 22:07:28 +01:00
Thomas Haller
782578122c ovs: fix compiler error for passing NMDevice pointer to NM_DEVICE_OVS_INTERFACE_GET_PRIVATE()
NM_DEVICE_OVS_INTERFACE_GET_PRIVATE() is implemented via the _NM_GET_PRIVATE()
macro. This macro uses C11's _Generic() to provide additional compiler checks
when casting from an incompatible pointer type.

As such,

  NMDevice *device = ...;
  NMDeviceOvsInterfacePrivate *priv;

  priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device);

causes a compilation error:

    error: ‘_Generic’ selector of type ‘NMDevice * {aka struct _NMDevice *}’ is not compatible with any association

One workaround would be to cast the pointer first:

  priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE ((NMDeviceOvsInterface *) device);

A better fix is to mark NMDevice as a compatible pointer in _NM_GET_PRIVATE(),
which this patch does.

Previously, this went unnoticed, because due to bug "a43bf3388 build: fix configure
check for CC support of _Generic() and __auto_type", we failed to detect support
for _Generic() when compiling with -Werror. That essentially disables this check,
and NM_DEVICE_OVS_INTERFACE_GET_PRIVATE() would do a direct cast.

A workaround for this build failure might be to build with -Werror, which accidentally
results in not using _Generic().

https://bugzilla.gnome.org/show_bug.cgi?id=793183

Fixes: 8ad310f8e3
2018-02-05 13:59:15 +01:00
Lubomir Rintel
8ad310f8e3 ovs-interface: avoid starting ip[46] configuration more than once
OvsInterface can postpone the stage3_ip[46]_config until the link
actually appears. It ought to restart the stage only when the link
appears, not upon further changes to it (which would trip an assertion
when starting the DHCP client while one already exists).

https://bugzilla.redhat.com/show_bug.cgi?id=1540063
2018-02-05 10:57:16 +01:00
Thomas Haller
34cb6f9877 build/meson: use variables for ldflags and linker-script 2018-01-11 12:46:01 +01:00
Thomas Haller
349861ceec build/meson: unconditionally use linker version scripts
We also unconditionally use them with autotools.
Also, the detection for have_version_script does
not seem correct to me. At least, it didn't work
with clang.
2018-01-10 12:31:44 +01:00
Iñigo Martínez
5e16bcf268 meson: Improve dependency system
Some targets are missing dependencies on some generated sources in
the meson port. These makes the build to fail due to missing source
files on a highly parallelized build.

These dependencies have been resolved by taking advantage of meson's
internal dependencies which can be used to pass source files,
include directories, libraries and compiler flags.

One of such internal dependencies called `core_dep` was already in
use. However, in order to avoid any confusion with another new
internal dependency called `nm_core_dep`, which is used to include
directories and source files from the `libnm-core` directory, the
`core_dep` dependency has been renamed to `nm_dep`.

These changes have allowed minimizing the build details which are
inherited by using those dependencies. The parallelized build has
also been improved.
2018-01-10 12:20:17 +01:00
Iñigo Martínez
03637ad8b5 build: add initial support for meson build system
meson is a build system focused on speed an ease of use, which
helps speeding up the software development. This patch adds meson
support along autotools.

[thaller@redhat.com: rebased patch and adjusted for iwd support]

https://mail.gnome.org/archives/networkmanager-list/2017-December/msg00022.html
2017-12-13 15:48:50 +01:00
Thomas Haller
595aaf0f3e all: update compatiblity for older libjansson versions
- nm-ovsdb.c uses json_load_callback(), which is jansson v2.4.
  Hence, it cannot build the OVS plugin in our Travis-CI, which is
  still on Ubuntu Precise. Disable building the plugin in travis and
  add a compiler warning when building against an older version.

- since jansson v2.3, there is json_object_key_to_iter() to implement
  the for-each macros. Use it in json_object_foreach_safe() when
  available.
2017-11-09 17:34:39 +01:00
Thomas Haller
650a47e16c all: use nm-jansson.h 2017-11-09 17:32:22 +01:00
Thomas Haller
76b913a210 ovs: add backward compatibility wrapper for json_object_foreach() macro 2017-10-31 20:02:48 +01:00
Lubomir Rintel
47ebb98630 devices/ovs/ovsdb: fix 32bit builds
So that we work well on VAXen.
2017-10-31 10:57:05 +01:00
Lubomir Rintel
eee1553288 devices/ovs/ovsdb: fix build with old Jansson 2017-10-31 09:21:30 +01:00
Lubomir Rintel
830a5a14cb device: add support for OpenVSwitch devices 2017-10-30 21:46:55 +01:00