IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
(cherry picked from commit 15b1304477)
Dracut documents the BOOTIF argument to be a MAC address and so we
accept one in any of the conventions we recognize. However, the PXE boot
loaders like to prepend a "01-" to denote an ethernet hardware type.
Accept that too.
https://bugzilla.redhat.com/show_bug.cgi?id=1726240
(cherry picked from commit 2952953a48)
Certain arguments (such as "nameserver") don't specify a connection they
apply to and using them would generate a default ethernet connection.
This is probably not the right thing to do.
(cherry picked from commit 6da2058237)
4 properties are not really relevant for an already activated connection
or it makes not sense to change them. These are connection.id, connection.uuid,
connection.autoconnect and connection.stable-id.
For convenience, we allow to reapply these. This way, one can take
a different setting (e.g. with a different connection.id or
connection.uuid) and reapply them, but such changes are silently
ignored.
However this was done wrongly. Instead of reverting the change to the new
applied connection, we would change the input connection.
This is bad, for example with
nmcli connection up uuid cb922f18-e99a-49c6-b200-1678b5070a82
nmcli connection modify cb922f18-e99a-49c6-b200-1678b5070a82 con-name "bogus"
nmcli device reapply eth0
the last re-apply would reset the settings-connection's connection ID to
what was before, while accepting the new name on the applied-connection
(while it should have been rejected).
Fixes: bf3b3d444c ('device: avoid changing immutable properties during reapply')
(cherry picked from commit adb51c2a7f)
NMDevicePPP only handles connections with the pppoe.parent property
set. match_connection() already checks this when we creating a new
device. We should also perform the same check in
check_connection_compatible().
Fixes: 6c3195931e ('core: implement activation of PPP devices')
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/203
(cherry picked from commit 17f4a1e794)
NMConnectivity can now distinguish between LIMITED and NONE connectivity
and it does so based on whether IP addresses and routes are configured.
Previously, NMConnectivity would not differenciate between limited and
no connectivity, which is why NMDevice added some additional logic on top
to coerce LIMITED to NONE (if the device is not logically connected).
But note that the connectivity state (whether a network is reachable on
an interface) depends on what is configured in kernel and whether the
internet is reachable on that interface. It does not depend on the
logical device state.
On the other hand, whether the device is configured in a manner to have
connectivity depends on the logical state of the device (as NetworkManager
is configuring the device).
So, in many cases, the logical state and the connectivity state agree now,
but for the right reasons.
This reverts commit 4c4dbcb78d.
(cherry picked from commit 5a416a9da1)
The platform is used to detect whether to skip the connectivity check right away.
It should be an optional argument, so one could avoid this pre-check.
(cherry picked from commit b626baa313)
If the interface has no carrier, no addresses or no routes there is no
point in starting a connectivity check on it because it will fail.
Moreover, doing the check on a device without routes causes the
addition of a negative entry in the ARP table for each of the
addresses associated with the connectivity check host; this can lead
to poor network performances.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/181
(cherry picked from commit 91d447df19)
pppd restores the previous settings for the serial port it uses right
before exiting. It is especially important to do so because otherwise
ModemManager is not able to recover the port as it can receive a hangup
event from the port due to CLOCAL not being restored. However, there is
currently a race condition that produces this issue. This is because
when PHASE_DEAD is notified, pppd still has not restored the port
settings - it does that a bit later, in the die() function.
This patch delays notifying PHASE_DEAD until when the exitnotify() hook
is called by pppd: when this happens the port settings have already been
restored.
There were previously efforts to fix this in commit fe090c34b7, so
PHASE_DEAD was used instead of PHASE_DISCONNECT to notify MM that the
port was disconnected, but that still early to ensure that the port
settings are restored.
The MM traces seen when the bug is triggered are:
ModemManager[2158]: <warn> (ttyACM1): could not re-acquire serial port lock: (5) Input/output error
ModemManager[2158]: <warn> Couldn't load Operator Code: 'Cannot run sequence: 'Could not open serial device ttyACM1: it has been forced close'
https://mail.gnome.org/archives/networkmanager-list/2019-June/msg00014.html
(cherry picked from commit a251712a72)
The values cached in the device may be stale when we start a new
activation because in a disconnected state we might have called
ip_config_merge_and_apply() which cached the main table value.
(cherry picked from commit 5be69ba794)
Before commit e3ac45c026 the reader set the private key in the
setting using the libnm function, which also set the key as client
certificate if it was in PKCS #12 format.
After the commit, existing connections with a PKCS #12 private key but
without a client certificate became invalid. Restore the old behavior.
Fixes: e3ac45c026 ('ifcfg-rh: don't use 802-1x certifcate setter functions')
(cherry picked from commit 9a410fc312)
The writer should only persist properties without too much additional
logic, which should be instead embedded in the setting itself.
(cherry picked from commit a995244e9b)
If we created a software interface it is because we already decided
that it should be managed, and so there is no point in waiting udev to
check that the interface is not udev-unmanaged.
We still wait udev for software interfaces created externally.
(cherry picked from commit 58db61545d)
An active connection started by user could be queued in state UNKNOWN
which means the device hasn't started activating yet. Eventually it
will, and we don't want to cancel the user activation because of an
internal autoconnection attempt.
(cherry picked from commit d33c995d45)
There was a special case for ensuring that the device's configuration
doesn't disappear when some factory is too late at recognizing the
device is just a component of another one.
It was always a bad idea. If the device already had an active
connection (such as for a generated default wired connection), it would
remain around, with a dangling reference to the device.
This effectively reverts commit 5ad69cb29b ('core: remove child devices
without deconfiguring them (bgo #738479)'). It's okay to do so, because
we now wouldn't deconfigure the device upon its removal anyway.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/151/
(cherry picked from commit ff2d0f5add)
This will be the default for Slackware 15.0 and on.
This should be safe for both master and 1.12.x stable branch, as
no existing Slackware releases are expected to run NM-1.12.x or
later.
Signed-off-by: Robby Workman <rworkman@slackware.com>
https://mail.gnome.org/archives/networkmanager-list/2019-May/msg00011.html
(cherry picked from commit e1df17e0ac)
In general, all fields of public NMPlatform* structs must be
plain/simple. Meaning: copying the struct must be possible without
caring about cloning/duplicating memory.
In other words, if there are fields which lifetime is limited,
then these fields cannot be inside the public part NMPlatform*.
That is why
- "NMPlatformLink.kind", "NMPlatformQdisc.kind", "NMPlatformTfilter.kind"
are set by platform code to an interned string (g_intern_string())
that has a static lifetime.
- the "ingress_qos_map" field is inside the ref-counted struct NMPObjectLnkVlan
and not NMPlatformLnkVlan. This field requires managing the lifetime
of the array and NMPlatformLnkVlan cannot provide that.
See also for example NMPClass.cmd_obj_copy() which can deep-copy an object.
But this is only suitable for fields in NMPObject*. The purpose of this
rule is that you always can safely copy a NMPlatform* struct without
worrying about the ownership and lifetime of the fields (the field's
lifetime is unlimited).
This rule and managing of resource lifetime is the main reason for the
NMPlatform*/NMPObject* split. NMPlatform* structs simply have no mechanism
for copying/releasing fields, that is why the NMPObject* counterpart exists
(which is ref-counted and has a copy and destructor function).
This is violated in tc_commit() for the "kind" strings. The lifetime
of these strings is tied to the setting instance.
We cannot intern the strings (because these are arbitrary strings
and interned strings are leaked indefinitely). We also cannot g_strdup()
the strings, because NMPlatform* is not supposed to own strings.
So, just add comments that warn about this ugliness.
The more correct solution would be to move the "kind" fields inside
NMPObjectQdisc and NMPObjectTfilter, but that is a lot of extra effort.
(cherry picked from commit f2ae994b23)
While nm_platform_link_get_ifindex() is documented to return 0 if the device
is not found, don't rely on it. Instead, check that a valid(!) ifindex was
returned, and only then set the ifindex. Otherwise leave it at zero. There
is of course no difference in practice, but we generally treat invalid ifindexes
as <= 0, so it's not immediately clear what nm_platform_link_get_ifindex()
returns to signal no device.
(cherry picked from commit 9eefe27a1c)
Also calling macros we commonly put a space between the macro name and
the parenthesis.
Also align the parameters. Otherwise it's hard to read for me.
(cherry picked from commit 9399297a82)
There is only one caller, hence it's simpler to see it all in one place.
I prefer this, because then I can read the code top to bottom and
see what's happening, without following helper functions.
Also, this way we can "reuse" the nla_put_failure label and assertion. Previously,
if the assertion was hit we would not rewind the buffer but continue
constructing the message (which is already borked). Not that it matters
too much, because this was on an "failed-assertion" code path.
(cherry picked from commit 04bd404dff)
These lines can be reached if the allocated buffer is too
small to hold the netlink message. That is actually a bug
that we need to fix. Assert.
(cherry picked from commit 3784a2a2ec)
Arguably, the structure is used inside a union with another (larger)
struct, hence no memory is saved.
In fact, it may well be slower performance wise to access a boolean bitfield
than a gboolean (int).
Still, boolean fields in structures should be bool:1 bitfields for
consistency.
(cherry picked from commit 36d6aa3bcd)
Kernel calls the netlink attribute TCA_FQ_CODEL_MEMORY_LIMIT. Likewise,
iproute2 calls this "memory_limit".
Rename because TC parameters are inherrently tied to the kernel
implementation and we should use the familiar name.
(cherry picked from commit 666d58802b)
iproute2 uses the special value ~0u to indicate not to set
TCA_FQ_CODEL_CE_THRESHOLD in RTM_NEWQDISC. When not explicitly
setting the value, kernel treats the threshold as disabled.
However note that 0xFFFFFFFFu is not an invalid threshold (as far as
kernel is concerned). Thus, we should not use that as value to indicate
that the value is unset. Note that iproute2 uses the special value ~0u
only internally thereby making it impossible to set the threshold to
0xFFFFFFFFu). But kernel does not have this limitation.
Maybe the cleanest way would be to add another field to NMPlatformQDisc:
guint32 ce_threshold;
bool ce_threshold_set:1;
that indicates whether the threshold is enable or not.
But note that kernel does:
static void codel_params_init(struct codel_params *params)
{
...
params->ce_threshold = CODEL_DISABLED_THRESHOLD;
static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
{
...
if (tb[TCA_FQ_CODEL_CE_THRESHOLD]) {
u64 val = nla_get_u32(tb[TCA_FQ_CODEL_CE_THRESHOLD]);
q->cparams.ce_threshold = (val * NSEC_PER_USEC) >> CODEL_SHIFT;
}
static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
{
...
if (q->cparams.ce_threshold != CODEL_DISABLED_THRESHOLD &&
nla_put_u32(skb, TCA_FQ_CODEL_CE_THRESHOLD,
codel_time_to_us(q->cparams.ce_threshold)))
goto nla_put_failure;
This means, kernel internally uses the special value 0x83126E97u to indicate
that the threshold is disabled (WTF). That is because
(((guint64) 0x83126E97u) * NSEC_PER_USEC) >> CODEL_SHIFT == CODEL_DISABLED_THRESHOLD
So in kernel API this value is reserved (and has a special meaning
to indicate that the threshold is disabled). So, instead of adding a
ce_threshold_set flag, use the same value that kernel anyway uses.
(cherry picked from commit 973db2d41b)
The memory-limit is an unsigned integer. It is ugly (if not wrong) to compare unsigned
values with "-1". When comparing with the default value we must also use an u32 type.
Instead add a define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET.
Note that like iproute2 we treat NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
to indicate to not set TCA_FQ_CODEL_MEMORY_LIMIT in RTM_NEWQDISC. This
special value is entirely internal to NetworkManager (or iproute2) and
kernel will then choose a default memory limit (of 32MB). So setting
NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET means to leave it to kernel to
choose a value (which then chooses 32MB).
See kernel's net/sched/sch_fq_codel.c:
static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
{
...
q->memory_limit = 32 << 20; /* 32 MBytes */
static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
...
if (tb[TCA_FQ_CODEL_MEMORY_LIMIT])
q->memory_limit = min(1U << 31, nla_get_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT]));
Note that not having zero as default value is problematic. In fields like
"NMPlatformIP4Route.table_coerced" and "NMPlatformRoutingRule.suppress_prefixlen_inverse"
we avoid this problem by storing a coerced value in the structure so that zero is still
the default. We don't do that here for memory-limit, so the caller must always explicitly
set the value.
(cherry picked from commit 46a904389b)
When using nm_utils_strbuf_*() API, the buffer gets always moved to the current
end. We must thus remember and return the original start of the buffer.
(cherry picked from commit b658e3da08)
In practice, there is no difference when representing 0 or 1 as signed/unsigned 32
bit integer. But still use the correct type that also kernel uses.
Also, the implicit conversation from uint32 to bool was correct already.
Still, explicitly convert the uint32 value to boolean in _new_from_nl_qdisc().
It's no change in behavior.
(cherry picked from commit a1099a1fab)
"NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE)" is quite a hack as it relies on
the implementation of the macro in a particular way. The problem is, that
NM_CMP_FIELD() uses typeof() which cannot be used with bitfields. So, the
nicer solution is to use NM_CMP_FIELD_UNSAFE() which exists exactly for bitfields
(it's "unsafe", because it evaluates arguments more than once as it avoids
the temporary variable with typeof()).
Same with nm_hash_update_vals() which uses typeof() to avoid evaluating
arguments more than once. But that again does not work with bitfields.
The "proper" way is to use NM_HASH_COMBINE_BOOLS().
(cherry picked from commit 47d8bee113)
Ooherwise, the file has wrong permissions:
# ls -la /var/lib/NetworkManager/secret_key
----r-xr-x. 1 root root 50 May 14 13:52 /var/lib/NetworkManager/secret_key
Luckily, /var/lib/NetworkManager should be already
# ls -lad /var/lib/NetworkManager
drwx------. 2 root root 8192 May 14 13:57 /var/lib/NetworkManager
which mitigates this a bit.
Fixes: dbcb1d6d97 ('core: let nm_utils_secret_key_read() handle failures internally')
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/175
(cherry picked from commit dc3a2f9bc4)