"nm-version-macros.h" is used directly by libnm-core and indirectly by
libnm and core.
Let's not have it randomly under shared/. Move it closer to where it's
used.
"shared/nm-meta-setting.[hc]" contains meta data about settings.
As such it is similarly used by libnm-core (as internal API) and
by clients (as extension of public API of libnm). However, it must
be compiled twice, because while it defines in both cases a
NMMetaSettingInfo type, these types are different between internal and
public API.
Hence, the files must also be compiled twice (and differently), once
against libnm-core and once against the client helper library.
Previously, the file was under "shared/", but there it's a bit odd
it doesn't clearly belong anywhere.
There are two goals here:
- copy the file to the two places where it is used. We also have
a "check-tree" unit test that ensures those files don't diverge in
the future.
- we no longer require CFLAGS set during built. Instead, the sources
should control the build. For that we have new (simple) headers
"nm-meta-setting-base.h" that define the right behavior for the
impl files.
There is still an ugliness (among several): the files must be named the
same for libnm-core and clients/common. Preferably, all our sources have
unique names, but that is not possible with this scheme (without
introducing other ugliness). To mitigate that, include the files only at
one exact place.
autotools projects commonly should include "config.h" as first header.
Also, commonly we need more headers, like glib.h or our nm_auto macros.
Hence, almost all our sources should as first include "nm-default.h".
However, as we build different parts, "nm-default.h" gets controlled
by the NETWORKMANAGER_COMPILATION define which autotools/meson needs
to specify in the build options.
That is confusing.
One advantage of that was, that theoretically the same sources can
be built twice, with different behavior. However, we should avoid doing
that altogether and build static libraries (once) that we link multiple
times.
Another advantage was that if NETWORKMANAGER_COMPILATION is for example
set to build a DAEMON source, there is a check that we don't include
private headers from libnm-core. However, that should be better solved
by not having public, internal and private headers in the same
directory.
Instead, introduce different "nm-default-*.h" headers that don't require
special defines and behave in a consistent way. This way, we require
fewer CFLAGS and it's immediately clear by looking at the source alone
which headers are included. Also, you will be easier see when a wrong
nm-default-*.h header gets included.
Introduce the first replacement. The others will follow.
Drop some "helper" variables that are only used once. These variables
spread out what is defined, and only make the meson file more complicated
to follow.
We want to use this by "shared/nm-platform", which should have
no dependency on "libnm-core".
Move "libnm-core/nm-ethtool-utils.h" to "libnm/nm-ethtool-utils.h" so
that it is only used by libnm. This file contains the defines for
the option names.
Also, symlink "libnm/nm-ethtool-utils.h" as "shared/nm-base/nm-ethtool-utils-base.h".
We want to use the same defines also internally. Since they are both
public API (must be in libnm) and should be in "shared/nm-base", this
is the way.
We want to move platform code to "shared/nm-platform". However, platform
code uses the logging infrastructure from the daemon, there is thus
an odd circular dependency.
Solve that by moving the "src/nm-logging.[hc]" to a new helper library
in "shared/nm-log-core".
NetworkManager core is huge. We should try to split out
parts that are independent.
Platform code is already mostly independent. But due to having it
under "src/", there is no strict separation/layering which determines
the parts that can work independently. So, while the code is mostly
independent (in practice), that is not obvious from looking at the
source tree. It thus still contributes to cognitive load.
Add a shared library "shared/nm-platform", which should have no
dependencies on libnm-core or NetworkManager core.
In a first step, move the netlink code there. More should follow.
Like the previous commit. Move code that depends on libnm out
of shared to avoid circular dependency.
Also add a readme file explaining the reason for existence of
the helper library.
Like the previous commit. Move code that depends on libnm-core out
of shared to avoid circular dependency.
Also add a readme file explaining the reason for existence of
the helper libraries nm-libnm-core-intern and nm-libnm-core-aux.
The "shared" directory is used by libnm-core, it should thus only depend on
code that is in the "shared" directory. Otherwise there is a circular
dependency, and meson's subdir() does not work nicely.
Also, libnm-core is really part of (and also an extension of) libnm-core,
so it belongs there.
I guess, the original idea was that this is also an extension for libnm,
so another project could take these utility functions (by copying them
into their source tree) and use them. That is still possible, it's
just that the sources are no longer under the shared directory.
Also add a readme to explain the non-obvious meaning of these files.
Originally, these files were part of libnm-core and linked together.
However, that is a licensing violation, because the code is GPL-2.0+
licensed, while libnm-core also gets linked with libnm (it must thus
be LGPL-2.1+). The original intent behind moving the code to "shared/"
was to avoid the licensing issue, but also to prepare when we would add
a separate, GPL licensed libnm-keyfile. However, currently we hope to
be able to relicense the code, so that it actually could be exposed as
part of libnm. This is work in progress at ([1]).
[1] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/ ## 517
Anyway, the current directory layout is problematic. libnm-keyfile
depends on libnm-core, while libnm-core depends on code under shared.
That means, there is a circular dependency and meson's subdir() does
not work well.
Move the code.
Keyfile support was initially added under GPL-2.0+ license as part of
core. It was moved to "libnm-core" in commit 59eb5312a5 ('keyfile: merge
branch 'th/libnm-keyfile-bgo744699'').
"libnm-core" is statically linked with by core and "libnm". In
the former case under terms of GPL-2.0+ (good) and in the latter case
under terms of LGPL-2.1+ (bad).
In fact, to this day, "libnm" doesn't actually use the code. The linker
will probably remove all the GPL-2.0+ symbols when compiled with
gc-sections or LTO. Still, linking them together in the first place
makes "libnm" only available under GPL code (despite the code
not actually being used).
Instead, move the GPL code to a separate static library
"shared/nm-keyfile/libnm-keyfile.la" and only link it to the part
that actually uses the code (and which is GPL licensed too).
This fixes the license violation.
Eventually, it would be very useful to be able to expose keyfile
handling via "libnm". However that is not straight forward due to the
licensing conflict.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/381
Move it to shared as it's useful for clients as well.
Move and rename nm_dbus_manager_new_auth_subject_from_context() and
nm_dbus_manager_new_auth_subject_from_message() in nm-dbus-manager.c
as they're needed there.
We have "shared/nm-libnm-core-aux", which is shared code that can be used
by anybody (including libnm-core, src, libnm and clients).
We have "clients/common", which are helper function for clients. But
that implies that the code is inside "clients". I think it would be
useful to have auxiliary code that extends libnm, but is not only
usable by code in "clients". In other words, "shared/nm-libnm-aux"
is a better place than "clients/common", and I think most of the
functionality form "clients/common" should move there.
"shared/nm-utils" got long renamed and split into separate parts. The remaining
tests are really to test nm-std-aux and nm-glib-aux (no libnm dependencies). Move
the tests to the appropriate place.
We have "nm-logging-fwd.h", which (as the name implies) is header-only.
Add instead a "nm-logging-base.c", which also contains implementation for
logging functions that are not only useful under "src/nm-logging.c"
We don't need such data duplicated. The build setup should
have only one configuration_data() for patching such values.
Now we only have one global, immutable data_conf dictionary with
configuration values. Note that none of the users of data_conf uses all
entries, but as the entries are basically only dependent on the
meson/configure option and valid for the entire project, this simplifies
to handling.
The `libnm-core` build file has been improved by applying a set of
changes:
- Indentation has been fixed to be consistent.
- Library variable names have been changed to `lib{name}` pattern
following their filename pattern.
- `shared` prefix has been removed from all variables using it.
- Dependencies have been reviewed to store the necessary data.
- The use of the libraries and dependencies created in this file
has been reviewed through the entire source code. This has
required the addition or the removal of different libraries and
dependencies in different targets.
- Some files used directly with the `files` function have been moved
to their nearest path build file because meson stores their full
path seamessly and they can be used anywhere later.
The `nm-default.h` header is used widely in the code by many
targets. This header includes different headers and needs different
libraries depending the compilation flags.
A new set of `*nm_default_dep` dependencies have been created to
ease the inclusion of different directorires and libraries.
This allows cleaner build files and avoiding linking unnecessary
libraries so this has been applied allowing the removal of some
dependencies involving the linking of unnecessary libraries.
The `shared` build file has been improved by applying a set of
changes:
- Indentation has been fixed to be consistent.
- Unused libraries and dependencies have been removed.
- Dependencies have been reviewed to store the necessary data.
- Set of objects used in targets have been grouped together.
- Header files have been removed from sources lists as it's
unnecessary.
- Library variable names have been changed to `lib{name}` pattern
following their filename pattern.
- `shared` prefix has been removed from all variables using it.
- `version_header` its related configuration `version_conf`
variables have been renamed to `nm_version_macro*` following
its input and final file names.
Functions derived from generators as `configure_file`,
`custom_target` and `i18n.merge_file` can use placeholders like
`@BASENAME@` that removes the extension from the input filename
string.
The output string has been replaced by this placeholder that
allows in some cases the use of less variables.
I'd like to refactor libnm's caching. Note that cached D-Bus objects
have repeated strings all over the place. For example every object will
have a set of D-Bus interfaces (strings) and properties (strings) and an
object path (which is referenced by other objects). We can save a lot of
redundant strings by deduplicating/interning them. Also, by interning
them, we can compare them using pointer equality.
Add a NMRefString implementation for this.
Maybe an alternative name would be NMInternedString or NMDedupString, because
this string gets always interned. There is no way to create a NMRefString
that is not interned. Still, NMRefString name sounds better. It is ref-counted
after all.
Notes:
- glib has GQuark and g_intern_string(). However, such strings cannot
be unrefered and are leaked indefinitely. It is thus unsuited for
anything but a fixed set of well-known strings.
- glib 2.58 adds GRefString, but we cannot use that because we
currently still use glib 2.40.
There are some differences:
- GRefString is just a typedef to char. That means, the glib API
exposes GRefString like regular character strings.
NMRefString intentionally does that not. This makes it slightly
less convenient to pass it to API that expects "const char *".
But it makes it clear to the reader, that an instance is in fact
a NMRefString, which means it indicates that the string is
interned and can be referenced without additional copy.
- GRefString can be optionally interned. That means you can
only use pointer equality for comparing values if you know
that the GRefString was created with g_ref_string_new_intern().
So, GRefString looks like a "const char *" pointer and even if
you know it's a GRefString, you might not know whether it is
interned. NMRefString is always interned, and you can always
compare it using pointer equality.
- In the past I already proposed a different implementation for a
ref-string. That made different choices. For example NMRefString
then was a typedef to "const char *", it did not support interning
but deduplication (without a global cache), ref/unref was not
thread safe (but then there was no global cache so that two threads
could still use the API independently).
The point is, there are various choices to make. GRefString, the
previous NMRefString implementation and the one here, all have pros and
cons. I think for the purpose where I intend NMRefString (dedup and
efficient comparison), it is a preferable implementation.
Ah, and of course NMRefString is an immutable string, which is a nice
property.
dns-domain.c contains useful functions for manipulating DNS names.
Add it to the systemd static library we build in shared/, similarly to
what we already do for other utility files that were originally in
src/systemd/src/basic/.
This is inspired by the existing systemd integration, with a few differences:
* This parses the WPAD option, which systemd requested, but did not use.
* We hook into the DAD handling, only making use of the configured address
once DAD has completed successfully, and declining the lease if it fails.
There are still many areas of possible improvement. In particular, we need
to ensure the parsing of all options are compliant, as n-dhcp4 treats all
options as opaque, unlike sd-dhcp4. We probably also need to look at how
to handle failures and retries (in particular if we decline a lease).
We need to query the current MTU at client startu, as well as the hardware
broadcast address. Both these are provided by the kernel over netlink, so
it should simply be a matter of hooking that up with NM's netlink layer.
Contribution under LGPL2.0+, in addition to stated licenses.
These tests cannot (easily) be under "shared/nm-libnm-core-aux/tests"
because libnm/libnm-core requires code under shared while
"nm-libnm-core-aux" requires libnm/libnm-core. With autotools that is
not problem, but with meson we include sub directories in a particular
order and there is no way to foward declare stuff (AFAIK). To avoid
the circular dependency, add the tests to "clients/common/tests", which
is always built last.
"libnm-core" implements common functionality for "NetworkManager" and
"libnm".
Note that clients like "nmcli" cannot access the internal API provided
by "libnm-core". So, if nmcli wants to do something that is also done by
"libnm-core", , "libnm", or "NetworkManager", the code would have to be
duplicated.
Instead, such code can be in "libnm-libnm-core-{intern|aux}.la".
Note that:
0) "libnm-libnm-core-intern.la" is used by libnm-core itsself.
On the other hand, "libnm-libnm-core-aux.la" is not used by
libnm-core, but provides utilities on top of it.
1) they both extend "libnm-core" with utlities that are not public
API of libnm itself. Maybe part of the code should one day become
public API of libnm. On the other hand, this is code for which
we may not want to commit to a stable interface or which we
don't want to provide as part of the API.
2) "libnm-libnm-core-intern.la" is statically linked by "libnm-core"
and thus directly available to "libnm" and "NetworkManager".
On the other hand, "libnm-libnm-core-aux.la" may be used by "libnm"
and "NetworkManager".
Both libraries may be statically linked by libnm clients (like
nmcli).
3) it must only use glib, libnm-glib-aux.la, and the public API
of libnm-core.
This is important: it must not use "libnm-core/nm-core-internal.h"
nor "libnm-core/nm-utils-private.h" so the static library is usable
by nmcli which couldn't access these.
Note that "shared/nm-meta-setting.c" is an entirely different case,
because it behaves differently depending on whether linking against
"libnm-core" or the client programs. As such, this file must be compiled
twice.
From the files under "shared/nm-utils" we build an internal library
that provides glib-based helper utilities.
Move the files of that basic library to a new subdirectory
"shared/nm-glib-aux" and rename the helper library "libnm-core-base.la"
to "libnm-glib-aux.la".
Reasons:
- the name "utils" is overused in our code-base. Everything's an
"utils". Give this thing a more distinct name.
- there were additional files under "shared/nm-utils", which are not
part of this internal library "libnm-utils-base.la". All the files
that are part of this library should be together in the same
directory, but files that are not, should not be there.
- the new name should better convey what this library is and what is isn't:
it's a set of utilities and helper functions that extend glib with
funcitonality that we commonly need.
There are still some files left under "shared/nm-utils". They have less
a unifying propose to be in their own directory, so I leave them there
for now. But at least they are separate from "shared/nm-glib-aux",
which has a very clear purpose.
We built (among others) two libraries from the sources in "shared/nm-utils":
"libnm-utils-base.la" and "libnm-utils-udev.la".
It's confusing. Instead use directories so there is a direct
correspondence between these internal libraries and the source files.
"shared/nm-utils" contains general purpose utility functions that only
depend on glib (and extend glib with some helper functions).
We will also add code that does not use glib, hence it would be good
if the part of "shared/nm-utils" that does not depend on glib, could be
used by these future projects.
Also, we use the term "utils" everywhere. While that covers the purpose
and content well, having everything called "nm-something-utils" is not
great. Instead, call this "nm-std-aux", inspired by "c-util/c-stdaux".