After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 746566 - get rid of default-unmanaged
get rid of default-unmanaged
Status: RESOLVED FIXED
Product: NetworkManager
Classification: Platform
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: NetworkManager maintainer(s)
NetworkManager maintainer(s)
Depends on:
Blocks: 680909 nm-1-2 746440
 
 
Reported: 2015-03-21 11:19 UTC by Lubomir Rintel
Modified: 2016-02-15 20:46 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Lubomir Rintel 2015-03-21 11:19:21 UTC
Discussion in bug #731014

Two options:

1.) Make everything default-unmanaged -- allow activation from UNMANAGED state

2.) Remove default-unamnaged and change Device.Managed property to read-write.
Comment 2 Thomas Haller 2015-05-05 22:40:18 UTC
(In reply to Lubomir Rintel from comment #0)
> Discussion in bug #731014
> 
> Two options:
> 
> 1.) Make everything default-unmanaged -- allow activation from UNMANAGED
> state
> 
> 2.) Remove default-unamnaged and change Device.Managed property to
> read-write.

the branch goes with 2.), right? That seems better to me.






>> device: allow modifying Managed property


+    case PROP_MANAGED:
...
+         } else {
+              if (priv->state != NM_DEVICE_STATE_UNMANAGED)
+                   nm_device_state_changed (self,
+                                            NM_DEVICE_STATE_UNMANAGED,
+                                            NM_DEVICE_STATE_REASON_USER_REQUESTED);
+         }


can you just transition the device from any state to unmanged?

For example, from ACTIVATED, don't you first have to cycle through NM_DEVICE_STATE_DEACTIVATING, etc?

I must admit, I still don't get this state change logic...





"TODO: is UNMANAGED_USER appropriate for generic / veth?"

I'd say so. This looks right to me.
Comment 3 Thomas Haller 2015-06-02 14:40:28 UTC
I took lr/default-unmanaged-bgo746566 and rebased it on master.
I want to use this as a base for doing bug 746440.

The original version is still at lr/default-unmanaged-bgo746566-1.


Did a few changes too...
Comment 4 Thomas Haller 2015-06-02 16:08:33 UTC
>> cli: add nmcli device set command

+                  "ARGUMENTS := <ifname> { SETTING, [ SETTING ... ] }\n"

as passing multiple settings does not mean that those settings are set atomically together, so I don't think there is much value in accepting multiple settings.

It complicates stuff, but is not much better (atomic) then:
  nmcli device set managed on &&
  nmcli device set autoconnect on
Comment 5 Thomas Haller 2015-09-15 14:10:39 UTC
Rebased and heavily reworked the branch.

Up to the last patch, they seem good to me. The last need more thought (but already review too).



343d0a2 device: remove default-unmanaged
1322fcd device/trivial: rename nm_device_get_unmanaged_flag() to nm_device_get_unmanaged()
1804b08 device/trivial: rename nm_device_set_initial_unmanaged_flag() to nm_device_set_unmanaged_initial()
746c64f cli: add nmcli device set command
7450cac cli,trivial: move nmc_switch_parse_on_off
6bfaeae libnm,libnm-glib: add Device.Manager setter
0a6d940 device: allow modifying Managed property
56609c6 device: add explicit NM_UNMANAGED_LOOPBACK flag for not managing "lo"
cb102b3 core: refactor setting of D-Bus properties via NMManager
143856e core: refactor NMBusManager to hold reference to NMExportedObject directly
2333126 core: forward declare NMExportedObject in "nm-types.h"



The first 3 patches fix a bug in NMManager handling setting properties via D-Bus.
Comment 6 Dan Winship 2015-09-15 15:15:23 UTC
143856e core: refactor NMBusManager to hold reference to NMExportedObject directly

>@@ -547,12 +598,17 @@ nm_bus_manager_dispose (GObject *object)

>+			g_hash_table_iter_remove (&iter);
>+		}
> 
> 		g_hash_table_destroy (priv->exported);

Removing each element as you go, when you're planning to destroy the whole hash table afterward anyway, just makes things slower, right?

>-object_destroyed (NMBusManager *self, gpointer object)
>+object_destroyed (NMBusManager *self, NMExportedObject *object) {
>-	g_hash_table_remove (NM_BUS_MANAGER_GET_PRIVATE (self)->exported, object);
>+	nm_assert_exported (self, NULL, object);
>+
>+	g_hash_table_remove (NM_BUS_MANAGER_GET_PRIVATE (self)->exported,
>+	                     nm_exported_object_get_path (object));

This is wrong; when a weak-notify function is called, the object has already been destroyed. The original code was fine because we were only using the pointer value of the object, not dereferencing it, but the new code will crash.

Since you didn't notice any crash, that implies that this code is never actually getting run. Which seems to be true; nm_exported_object_dispose() always unexports the device if it had been exported, so we never hit the case where an object is freed while it's still exported. So probably this can just go away.



cb102b3 core: refactor setting of D-Bus properties via NMManager

>    - set the property on the proper D-Bus skeleton interface instead
>      setting it directly on the exported-object.

You don't need to do that; NMExportedObject sets up GBindings between the object's properties and its skeletons' properties.



6bfaeae libnm,libnm-glib: add Device.Manager setter

I wouldn't add it to libnm-glib... Also, typo "Manager"


(Didn't look at the rest of the commits.)
Comment 7 Thomas Haller 2015-09-15 17:09:48 UTC
(In reply to Dan Winship from comment #6)
> 143856e core: refactor NMBusManager to hold reference to NMExportedObject
> directly
> 
> >@@ -547,12 +598,17 @@ nm_bus_manager_dispose (GObject *object)
> 
> >+			g_hash_table_iter_remove (&iter);
> >+		}
> > 
> > 		g_hash_table_destroy (priv->exported);
> 
> Removing each element as you go, when you're planning to destroy the whole
> hash table afterward anyway, just makes things slower, right?

dropped the g_h_t_iter_remove().


> >-object_destroyed (NMBusManager *self, gpointer object)
> >+object_destroyed (NMBusManager *self, NMExportedObject *object) {
> >-	g_hash_table_remove (NM_BUS_MANAGER_GET_PRIVATE (self)->exported, object);
> >+	nm_assert_exported (self, NULL, object);
> >+
> >+	g_hash_table_remove (NM_BUS_MANAGER_GET_PRIVATE (self)->exported,
> >+	                     nm_exported_object_get_path (object));
> 
> This is wrong; when a weak-notify function is called, the object has already
> been destroyed. The original code was fine because we were only using the
> pointer value of the object, not dereferencing it, but the new code will
> crash.

A weak-notify is called before starting to destroy the object. The object is still valid at that point and priv->path must sill be set.

Anyway, there was a bug here, and I just removed the weak-ref.


> Since you didn't notice any crash, that implies that this code is never
> actually getting run. Which seems to be true; nm_exported_object_dispose()
> always unexports the device if it had been exported, so we never hit the
> case where an object is freed while it's still exported. So probably this
> can just go away.


> cb102b3 core: refactor setting of D-Bus properties via NMManager
> 
> >    - set the property on the proper D-Bus skeleton interface instead
> >      setting it directly on the exported-object.
> 
> You don't need to do that; NMExportedObject sets up GBindings between the
> object's properties and its skeletons' properties.

I wanted to do it to ensure we set the right property (like, two D-Bus interfaces could have identically named properties, that map to different NMObject-properties.

But I just remove that.


> 6bfaeae libnm,libnm-glib: add Device.Manager setter
> 
> I wouldn't add it to libnm-glib... Also, typo "Manager"

it's a very old patch...


fixup follows (soon)
Comment 8 Dan Winship 2015-09-16 13:04:45 UTC
(In reply to Thomas Haller from comment #7)
> A weak-notify is called before starting to destroy the object. The object is
> still valid at that point and priv->path must sill be set.

Hm... while it happens that currently the weaknotify is called before finalize(), I'm not sure that was always the case, and you shouldn't depend on it. The docs say: "Since the object is already being finalized when the #GWeakNotify is called, there's not much you could do with the object, apart from e.g. using its address as hash-index or the like.". (Note that the prototype for a GWeakNotify refers to the object as "GObject *where_the_object_was".)

> > You don't need to do that; NMExportedObject sets up GBindings between the
> > object's properties and its skeletons' properties.
> 
> I wanted to do it to ensure we set the right property (like, two D-Bus
> interfaces could have identically named properties, that map to different
> NMObject-properties.

We don't have any support for non-standard D-Bus-property-name-to-GObject-property-name mappings, so if the properties had the same D-Bus property name, they'd have to have the same GObject property name too, and GObject wouldn't let you do that.
Comment 9 Thomas Haller 2015-09-16 14:45:58 UTC
merged an early part of the branch that fixes setting D-Bus properties:

http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=08916936bce4c8ac36156c040999add99175b455

... and included two non-controversial(?) patches.


Rest is again on review...
Comment 10 Dan Williams 2015-09-17 20:50:54 UTC
All the patches up to the WIP "device: remove default-unmanaged" patch look OK to me.

For the WIP patch the general approach seems OK to me, but I'm having some trouble figuring out from the patch how NM_UNMANAGED_USER gets flipped when the device is manually activated?
Comment 11 Thomas Haller 2015-09-18 11:23:59 UTC
merged all but the last patch of lr/default-unmanaged-bgo746566

http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=3a680392323f314f368807ff279618e69ac49623
Comment 12 Dan Winship 2015-09-18 12:24:31 UTC
(In reply to Dan Williams from comment #10)
> For the WIP patch the general approach seems OK to me, but I'm having some
> trouble figuring out from the patch how NM_UNMANAGED_USER gets flipped when
> the device is manually activated?

Haven't looked at all of this branch, but in my old danw/no-default-unmanaged branch the idea was that automatic-manage-on-activate would go away, because it was so complicated and buggy, and you'd have to explicitly make the device managed first before you could activate it.
Comment 13 Thomas Haller 2015-09-21 12:57:35 UTC
(In reply to Dan Winship from comment #12)
> (In reply to Dan Williams from comment #10)
> > For the WIP patch the general approach seems OK to me, but I'm having some
> > trouble figuring out from the patch how NM_UNMANAGED_USER gets flipped when
> > the device is manually activated?

indeed, it's not there (yet).


> Haven't looked at all of this branch, but in my old
> danw/no-default-unmanaged branch the idea was that
> automatic-manage-on-activate would go away, because it was so complicated
> and buggy, and you'd have to explicitly make the device managed first before
> you could activate it.

I imagined, if the user activates a connection that is unmanaged-user, we clear the unmanaged-user flag, and start activation -- provided the device is not unmanaged for other reasons.

When the interface deactivates, it would not go back to unmanaged automatically but stay disconnected/managed.


(v2 will follow)
Comment 14 Thomas Haller 2015-11-18 14:06:17 UTC
Please review lr/default-unmanaged-bgo746566 branch. See also: https://mail.gnome.org/archives/networkmanager-list/2015-November/msg00031.html
Comment 15 Beniamino Galvani 2015-11-24 08:40:32 UTC
> device: remove default-unmanaged and refactor unamanged flags

+       if (for_user_request) {
+
+               /* @for_user_request can make the result only ~more~ managed.
+                * If the flags already indicate a managed state for a non-user-request,
+                * then it is also managed for an explict user-request. */
+               if (_get_managed (flags, mask, FALSE))
+                       return TRUE;

At first sight this doesn't seem to be required because when
@for_user_request is set the remaining code in the "if" makes the
device "more managed".

Also, pushed a fixup.

Otherwise looks pretty good.
Comment 16 Thomas Haller 2015-11-24 10:06:41 UTC
(In reply to Beniamino Galvani from comment #15)
> > device: remove default-unmanaged and refactor unamanged flags
> 
> +       if (for_user_request) {
> +
> +               /* @for_user_request can make the result only ~more~ managed.
> +                * If the flags already indicate a managed state for a
> non-user-request,
> +                * then it is also managed for an explict user-request. */
> +               if (_get_managed (flags, mask, FALSE))
> +                       return TRUE;
> 
> At first sight this doesn't seem to be required because when
> @for_user_request is set the remaining code in the "if" makes the
> device "more managed".

Indeed, I was aware of that. Removing this code would make no difference. I did it because I wanted the invariant (that for-user-request means "more-managed") be expressed explicitly.

Also, when refactoring the code below, the invariant cannot break. So, I'd keep it, but add a code comment about that.
Comment 17 Beniamino Galvani 2015-11-24 17:19:08 UTC
(In reply to Thomas Haller from comment #16)
> Also, when refactoring the code below, the invariant cannot break. So, I'd
> keep it, but add a code comment about that.

Ah, ok. I agree then.
Comment 18 Thomas Haller 2015-12-04 16:58:06 UTC
rebased on master.

(merged an early part)
Comment 19 Dan Williams 2015-12-18 22:47:39 UTC
Overall looks OK.  There are two things that are now broken though, and that's explicit activation of default-unmanaged devices and management of unmanaged devices with connections.

-----------------------------
reproduce for default-unmanaged activation

1) add ENV{INTERFACE}=="foobar0", ENV{NM_UNMANAGED}="1" to /lib/udev/rules.d/85-nm-unmanaged.rules  (this simulates the old default-unmanaged)
2) udevadm control --reload
3) brctl addbr foobar0 - note that the device is (correctly) unmanaged due to !IFF_UP and externally created
4) ip link set dev foobar0 up - note that device is *still* unmanaged due to the udev rules
5) create a bridge connection for "foobar0":
DEVICE=foobar0
STP=no
TYPE=Bridge
ONBOOT=no
IPADDR=1.2.3.4
PREFIX=24
NAME=foobar0
6) nmcli con reload
7) nmcli dev show foobar0 -- note there are no available connections which I think is wrong; with default-unmanaged devices previously they are available when the device is unmanaged because you need to support 'nmcli con up' and devices cannot (and sholdn't) be allowed to activate when no connections are available on them
7) nmcli con up foobar0
8) crash

In this case, and previously with defualt-unmanaged devices, the device should be available for activation but that doesn't happen because the device has no available-connections.

-------------------------------------
Mis-management of devices with connections

This is probably caused by some missing code in my original dcbw/devices-for-all branch, or maybe a forgotten assumption in the new code.  But try this:

1) add ENV{INTERFACE}=="foobar0", ENV{NM_UNMANAGED}="1" to /lib/udev/rules.d/85-nm-unmanaged.rules
2) udevadm control --reload
3) create a bridge connection for "foobar0":
DEVICE=foobar0
STP=no
TYPE=Bridge
ONBOOT=no
IPADDR=1.2.3.4
PREFIX=24
NAME=foobar0
4) nmcli con reload
6) brctl addbr foobar0 - note that the device is (correctly) unmanaged due to !IFF_UP
7) ip link set dev foobar0 up - device now becomes managed, even though no explicit action has been taken

I think here the issue is that the IFF_UP checking bits in device_link_changed() aren't properly accounting for externally-created, because the device already exists (unrealized) due to dcbw/devices-for-all and the connection existing before the brctl addbr.
Comment 20 Dan Williams 2016-01-12 21:26:44 UTC
Does the re-push of the branch fix both of the above issues?
Comment 21 Dan Williams 2016-01-12 23:32:35 UTC
First patches look fine to me.

nm_device_set_unmanaged_flags() is a bit confusing to me; I think it would clearer to split the state change variant from the non-state-change variant.  So have a base nm_device_set_unmanaged_flags_simple() or something and then the normal nm_device_set_unmanaged_flags() that does change state.  That way we don't need the fake DEVICE_STATE_REASON value either?  Something like http://fpaste.org/310027/45264029/ perhaps.

Maybe nm_device_set_unmanaged_flags_user_udev() -> nm_device_update_unmanaged_flags_user_udev() since you can't pass flags directly into that function?

The FORGET operation isn't used; remove it?
Comment 22 Thomas Haller 2016-01-13 16:49:04 UTC
(In reply to Dan Williams from comment #21)

> nm_device_set_unmanaged_flags() is a bit confusing to me; I think it would
> clearer to split the state change variant from the non-state-change variant.
> So have a base nm_device_set_unmanaged_flags_simple() or something and then
> the normal nm_device_set_unmanaged_flags() that does change state.  That way
> we don't need the fake DEVICE_STATE_REASON value either?  Something like
> http://fpaste.org/310027/45264029/ perhaps.

Split and renamed functions.

Now we have plain getter/setter for flags:

  nm_device_get_unmanaged_flags()
  nm_device_set_unmanaged_flags()

then setting flags, and possibly doing a state change:

  nm_device_set_unmanaged_by_*().



> Maybe nm_device_set_unmanaged_flags_user_udev() ->
> nm_device_update_unmanaged_flags_user_udev() since you can't pass flags
> directly into that function?

I renamed it to nm_device_set_unmanaged_by_user_config().
The first part of the name is to match the nm_device_set_unmanaged_by_* pattern.
The *_user_config() part is because it set NM_UNMANAGED_USER_CONFIG flag.


> The FORGET operation isn't used; remove it?

Used now.
Comment 23 Thomas Haller 2016-01-14 18:20:13 UTC
Repushed, latest and greatest.
Comment 24 Thomas Haller 2016-01-18 11:00:56 UTC
merged another early part of the branch that fixes bugs on master (related to realizing devices): http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=320a3dee14d3d3675379861a7ed07a98544349f5
Comment 25 Dan Williams 2016-01-23 02:48:39 UTC
I like this latest version.  But one issue I see is that non-platform devices are not correctly managed in realize_start_setup().

You can reproduce this with:

modprobe atmtcp
atmtcp virtual listen

and not how the atm0 device never gets managed.  I think this is because of:

	nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT,
	                               !plink || !plink->initialized);

for these devices, plink == NULL, so they will always have PLATFORM_INIT set.  The logic should be:

	nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT,
	                               plink ? !plink->initialized : FALSE);

to ensure that non-platform devices get the PLATFORM_INIT flag cleared when they are realized.

For the splitting of the functions from the earlier comment, I was thinking more that nm_device_set_unmanaged_flags() would do the switch statement and basic logging, and the state-change-triggering function would do all the rest of the stuff but call nm_device_set_unmanaged_flags() in between.  But this way is OK too I guess.
Comment 26 Thomas Haller 2016-01-23 15:04:06 UTC
(In reply to Dan Williams from comment #25)
> I like this latest version.  But one issue I see is that non-platform
> devices are not correctly managed in realize_start_setup().
> 
> You can reproduce this with:
> 
> modprobe atmtcp
> atmtcp virtual listen
> 
> and not how the atm0 device never gets managed.  I think this is because of:
> 
> 	nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT,
> 	                               !plink || !plink->initialized);
> 
> for these devices, plink == NULL, so they will always have PLATFORM_INIT
> set.  The logic should be:
> 
> 	nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT,
> 	                               plink ? !plink->initialized : FALSE);
> 
> to ensure that non-platform devices get the PLATFORM_INIT flag cleared when
> they are realized.

fixed.



> For the splitting of the functions from the earlier comment, I was thinking
> more that nm_device_set_unmanaged_flags() would do the switch statement and
> basic logging, and the state-change-triggering function would do all the
> rest of the stuff but call nm_device_set_unmanaged_flags() in between.  But
> this way is OK too I guess.

I got that, but I wanted to do logging in one line telling which flags change, but also whether we change state (and the reason).

For that I pass @reason and @allow_state_transition down to _set_unmanaged_flags(). As there are really only two callers of _set_unmanaged_flags(), I figured this is the cleanest solution. 




Repushed, but still needs more testing.
Comment 27 Dan Williams 2016-02-11 21:17:07 UTC
In _nm_device_check_connection_available(), should the early-return when the device isn't realized also ensure the device is a software/virtual device?  Hardware devices obviously cannot have any available connections until they are realized...

Also now in _set_state_full() the code allows re-entering the UNAVAILABLE state for all cases, where previously it was just for missing firmware.  What is that necessary?  The only reason it's necessary for missing firmware is that devices are typically opened during UNAVAILABLE and that's where the firmware error would happen (ENOENT from IFF_UP), and to get that to happen again we need to redo the IFF_UP when firmware directory changes.  But why would we re-enter UNAVAILABLE from normal cases?
Comment 28 Thomas Haller 2016-02-12 09:14:18 UTC
(In reply to Dan Williams from comment #27)
> In _nm_device_check_connection_available(), should the early-return when the
> device isn't realized also ensure the device is a software/virtual device? 
> Hardware devices obviously cannot have any available connections until they
> are realized...

Fixup added.


> Also now in _set_state_full() the code allows re-entering the UNAVAILABLE
> state for all cases, where previously it was just for missing firmware. 
> What is that necessary?  The only reason it's necessary for missing firmware
> is that devices are typically opened during UNAVAILABLE and that's where the
> firmware error would happen (ENOENT from IFF_UP), and to get that to happen
> again we need to redo the IFF_UP when firmware directory changes.  But why
> would we re-enter UNAVAILABLE from normal cases?

There was a reason why I did that, but I forgot. I reverted it for now, let's see how tests work.


Repushed.