Skip to content

Use D-Bus library to communicate with NetworkManager and explicitly disconnect Wi-Fi #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

applemayexist
Copy link
Contributor

@applemayexist applemayexist commented Oct 30, 2024

This MR:

  • Uses libsystemd's D-Bus library to communicate with NetworkManager.
    • This avoids many syscalls from spawning nmcli processes, and those processes having to reconnect to D-Bus. Instead, we just keep one connection for the life of the wpa_supplicant process. Is this a hot path of the code? No, so it probably doesn't matter. But there's no reason I can't optimise it anyway!
    • More importantly, this is more direct communication with NetworkManager, so if nmcli isn't present, we can still know that NetworkManager is running and we can still tell it to stop managing our Wi-Fi adapter. Possibly useful for running in some sort of container that doesn't have NetworkManager installed, but does have access to the host D-Bus (though some polkit stuff would probably have to be figured out for that idk).
  • Disconnects the Wi-Fi connection of the adapter we intend to use before unmanaging it. This way, iwd should not be an issue, and it avoids having to completely stop iwd (so it can still manage other adapters). This should close Support iwd #15. Also, save the connection and reconnect after remanaging the interface with NetworkManager.

Some current issues:

  • NetworkManager seems to forget about disconnecting the interface if it receives a request to unmanage the interface right after the first request. I've fixed this by waiting for NetworkManager to confirm via signal that it has disconnected the device. However, there are still some issues I haven't figured out (it isn't reapplying the network config, why!?!!??!)
  • During testing on a system with NetworkManager+iwd, this code failed to tell NetworkManager to remanage the network. This happened because I store the object path of the interface so we don't have to make another D-Bus call later on to figure out what the path is. However, during this testing, NetworkManager decided to move the interface to a new object path, hence invalidating the "cached" one. I'm guessing it did this because (due to the issue above) iwd and wpa_supplicant_drc were fighting to control the interface? Anyway, I'm assuming this isn't common (and shouldn't happen once I fix the above issue), so instead of just not remembering the object path, I'll make it check again if the call failed with the "cached" object path.

It's also important to mention that this code uses GCC's __attribute__((cleanup(x))), so that I don't have to remember to free memory, and forget a couple of paths bc I'm very lazy. Clang supports this as well of course. I hope this is not an issue, however I understand if it is and can rip it out.

@applemayexist applemayexist force-pushed the sd-bus branch 5 times, most recently from b1a7d32 to 75e5e1e Compare November 4, 2024 13:28
@jacnils
Copy link

jacnils commented Nov 13, 2024

Is the systemd dependency this pull request would introduce really desirable though?

@applemayexist
Copy link
Contributor Author

applemayexist commented Nov 13, 2024

libelogind can be used in place of libsystemd

@applemayexist
Copy link
Contributor Author

And it is not a requirement on systemd (the init system), just on its utility library. It can even be statically linked (though for whatever reason no distro builds the static lib).

@jacnils
Copy link

jacnils commented Nov 13, 2024

I apologize for the misinformation, I assumed the library was dependent on systemd itself.

@applemayexist
Copy link
Contributor Author

I apologize for the misinformation, I assumed the library was dependent on systemd itself.

No problem! It's a reasonable assumption to make, but it just ain't so.

This avoids the overhead of spawning a process, a process which:
- uses a less efficient D-Bus library
- gathers more information than is needed by vanilla

This should hopefully speed things up the tiniest bit. It also no longer relies
on the presence of nmcli in path to tell if NetworkManager is present/running.

Note that I am using __attribute__((__cleanup__(x))), which is a GNU extension
(also supported by clang and ICC), as this saves me having to remember to free
everything, and should help prevent memory leaks. I hope this is not an issue.
Print errors from sd_bus calls. If the error is only available as an int, we
don't use strerror, as the information from that usually is not very helpful
to the user since D-Bus is too complex to represent its errors with traditional
POSIX errnos.
iwd, when managed by NetworkManager, does not automatically disconnect from the
network when we tell NetworkManager to unmanage the network, unlike
wpa_supplicant. A workaround for this is to just tell NetworkManager to
disconnect from the network, and it will tell iwd to do so.

We also store the network configuration until (our) shutdown so it can be
reapplied, as NetworkManager doesn't seem to autoconnect to the same network
after you disconnect, even if it has stopped and started managing the network.
@itsmattkc
Copy link
Contributor

This is obsoleted by 89f25ee

@itsmattkc itsmattkc closed this Mar 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support iwd
3 participants