Add in support for network interface flags.#2037
Add in support for network interface flags.#2037giampaolo merged 4 commits intogiampaolo:masterfrom clalancette:clalancette/add-net-flags
Conversation
|
These flags are pretty useless since there are no exposed constants to compare them against ( ...similarly to What makes me skeptical about this is that most of the flags above seem to refer to the network interface itself, and not the individual addresses. E.g. associating "IFF_PROMISC", "IFF_PORTSEL" or "IFF_AUTOMEDIA" to a network address wouldn't make much sense. As such, perhaps the right place to do this is |
That's fine by me. I'll go ahead and implement it that way instead.
OK, that sounds good to me as well. I'll add a new extension API for getting the flags and add it to the |
|
And this has all been done in b75a234. Please take a look when you get a chance. |
|
I've now rebased this onto the latest, and resolved the conflicts in HISTORY.rst based on the release. This is ready for another review when you have time. |
|
Rebased onto the latest again. Please take a look. |
|
Friendly ping on this one; do you think we could get this in? |
|
Hi Chris and sorry for being late but life got busier. =) I re-read your patch and I'm happy to include this functionality. I don't like hard-coding C constants in python though. I prefer if that is done in C. I remember we do something like this in here: Line 730 in df3fba5 I guess you can do something like that and remove "," at the beginning/end of the resulting string if needed.
|
That is, return the raw flag integer as reported by getifaddrs() on POSIX-compatible systems. On Windows systems (and any other ones that do not support flags), return None instead. Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
Thanks for the feedback. I went through and rewrote most of it in C, but in a slightly different way (see 1a5842b). In particular, what I'm doing there is constructing a list of strings to return to the Python layer, which I can then easily combine using By the way, it turns out that it is much, much better to do this at the C layer. The |
docs/index.rst
Outdated
|
|
||
| .. versionchanged:: 5.7.3 `isup` on UNIX also checks whether the NIC is running. | ||
|
|
||
| .. versionchanged:: 5.9.1 *flags* field was added. |
There was a problem hiding this comment.
- .. versionchanged:: 5.9.1 *flags* field was added.
+ .. versionchanged:: 5.9.1 *flags* field was added on POSIX.
docs/index.rst
Outdated
| - **speed**: the NIC speed expressed in mega bits (MB), if it can't be | ||
| determined (e.g. 'localhost') it will be set to ``0``. | ||
| - **mtu**: NIC's maximum transmission unit expressed in bytes. | ||
| - **flags**: a string of comma-separate flags on the interface (may be ``None``). |
There was a problem hiding this comment.
- I think an empty string is better than None. This way anybody can do
if "running" in flagswithout pre-emptively checkingif flag is not None. - please also list all the possible strings values.
There was a problem hiding this comment.
Changed to an empty string everywhere below. Also listed all of the possible string values in e05f926.
psutil/_psaix.py
Outdated
|
|
||
| duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu, None) |
There was a problem hiding this comment.
Since psutil_net_if_is_running function was already working on AIX / SunOS, I guess you can enable this code on those platforms as well.
There was a problem hiding this comment.
I've enabled it for AIX, as it is basically the same code. That said, I don't have access to an AIX machine, so I can't verify it there.
See my comment below about SunOS.
psutil/_psbsd.py
Outdated
| flag_list = [] | ||
| for flagname, bit in _psposix.POSIX_NET_FLAGS: | ||
| if flags & (1 << bit): | ||
| flag_list.append(flagname) |
psutil/_psutil_posix.c
Outdated
|
|
||
| sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
| if (sock == -1) | ||
| return NULL; |
There was a problem hiding this comment.
You should add PyErr_SetFromErrno(PyExc_OSError);, then goto error;
psutil/_pswindows.py
Outdated
| if hasattr(_common, 'NicDuplex'): | ||
| duplex = _common.NicDuplex(duplex) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu, None) |
There was a problem hiding this comment.
let's return "" instead of None
psutil/_psbsd.py
Outdated
| if flags & (1 << bit): | ||
| flag_list.append(flagname) | ||
|
|
||
| output_flags = ','.join(flag_list) |
There was a problem hiding this comment.
please rename this variable to just flags
There was a problem hiding this comment.
So I kept this as output_flags currently, as we still need to use flags for the list of flags. I'm happy to change the name of both if you want, just let me know what you would prefer.
| debug(err) | ||
| else: | ||
| ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu) | ||
| output_flags = ','.join(flags) |
There was a problem hiding this comment.
please rename this variable to just flags
There was a problem hiding this comment.
Same comment here.
| if hasattr(_common, 'NicDuplex'): | ||
| duplex = _common.NicDuplex(duplex) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu) | ||
| output_flags = ','.join(flags) |
There was a problem hiding this comment.
please rename this variable to just flags
There was a problem hiding this comment.
Same comment here.
psutil/_pssunos.py
Outdated
| if hasattr(_common, 'NicDuplex'): | ||
| duplex = _common.NicDuplex(duplex) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu) | ||
| ret[name] = _common.snicstats(isup, duplex, speed, mtu, None) |
There was a problem hiding this comment.
let's enable this on sunos as well (see my previous comment)
There was a problem hiding this comment.
So SunOS is a completely different beast than Linux, BSD, macOS, or Windows. Looking at the code in
Line 1484 in 4446e3b
ioctl (it is using something called SIOCGLIFFLAGS), and then it verifies that data with another structure (kstat?). So I don't think I can easily enable SunOS, and I don't have access to a SunOS machine.
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
|
@giampaolo Thanks for the very detailed review! I've made a number of changes based on your review, though I opted not to make some of the changes you requested (individual comments have details why). Please take another look! |
docs/index.rst
Outdated
| - **speed**: the NIC speed expressed in mega bits (MB), if it can't be | ||
| determined (e.g. 'localhost') it will be set to ``0``. | ||
| - **mtu**: NIC's maximum transmission unit expressed in bytes. | ||
| - **flags**: a string of comma-separated flags on the interface (may be the empty string). |
docs/index.rst
Outdated
|
|
||
| .. versionchanged:: 5.7.3 `isup` on UNIX also checks whether the NIC is running. | ||
|
|
||
| .. versionchanged:: 5.9.1 *flags* field was added on POSIX. |
| } | ||
|
|
||
| return true; | ||
| } |
There was a problem hiding this comment.
I don't like doing the flag comparison / check in here (if flags & flag_to_check ...). That should happen in the main function. The utility function (this one) should only add the item to the dict.
Also, instead of return true or false I would just return 1 or 0_, which is consistent with the rest of the code base and avoids including <stdbool.h> (I have some memories of this header file causing problems on some platform).
There was a problem hiding this comment.
That's fair. I've switched this helper function to return an int, and I'm now doing the check in the main function. All in d83c959.
psutil/_psutil_posix.c
Outdated
|
|
||
| sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
| if (sock == -1) { | ||
| PyErr_SetFromErrno(PyExc_OSError); |
There was a problem hiding this comment.
Please use PyErr_SetFromOSErrnoWithSyscall("socket(SOCK_DGRAM)");.
Since in this function we can fail for 2 different reasons, this will tell where the error originated from (socket() instead of ioctl()).
(sorry, I know I told you to PyErr_SetFromErrno use this but I forgot we have PyErr_SetFromOSErrnoWithSyscall)
There was a problem hiding this comment.
No problem, it happens. Fixed in d83c959.
psutil/_psutil_posix.c
Outdated
| PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); | ||
| ret = ioctl(sock, SIOCGIFFLAGS, &ifr); | ||
| if (ret == -1) { | ||
| PyErr_SetFromErrno(PyExc_OSError); |
There was a problem hiding this comment.
Please use PyErr_SetFromOSErrnoWithSyscall("ioctl(SIOCGIFFLAGS)");.
| for name, stats in nics.items(): | ||
| self.assertIsInstance(name, str) | ||
| isup, duplex, speed, mtu = stats | ||
| isup, duplex, speed, mtu, flags = stats |
There was a problem hiding this comment.
please add:
self.assertIsInstance(flags, str)
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
|
Sorry for the delay here (I was on vacation). I've now gone through and fixed up all of the latest issues; please take another look! |
| ``pointopoint``, ``notrailers``, ``running``, ``noarp``, ``promisc``, | ||
| ``allmulti``, ``master``, ``slave``, ``multicast``, ``portsel``, | ||
| ``dynamic``, ``oactive``, ``simplex``, ``link0``, ``link1``, ``link2``, | ||
| and ``d2`` (some flags are only available on certain platforms). |
There was a problem hiding this comment.
Please add . Availability: POSIX. After merge I'll try to take a look on how feasible it is to do this on Windows.
There was a problem hiding this comment.
I've added it in 3082526 . Let me know if that is where you want it.
docs/index.rst
Outdated
|
|
||
| .. versionchanged:: 5.7.3 `isup` on UNIX also checks whether the NIC is running. | ||
|
|
||
| .. versionchanged:: 5.9.2 *flags* field was added on POSIX. |
There was a problem hiding this comment.
I released 5.9.2 yesterday. Please set this to 5.9.3.
psutil/_psutil_posix.c
Outdated
| #include <Python.h> | ||
| #include <errno.h> | ||
| #include <stdlib.h> | ||
| #include <stdbool.h> |
There was a problem hiding this comment.
I think you can remove this, right?
|
I added some final comments but overall it's good to go. |
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
Thanks! Besides your comments, I also made small changes in 3082526 that should hopefully make linting happier. |
|
Perfect. I'm happy with this change. Thanks. |
|
Thank you so much! I appreciate all of the good feedback and the merge of the PR. |
Summary
Description
Add in support for network interface flags.
That is, return the raw flag integer as reported by getifaddrs()
on POSIX-compatible systems. On Windows systems (and any other
ones that do not support flags), return None instead.
I was careful to add the
flagsfield to the end of thesnicaddrnamed tuple so that the API wouldn't be broken.Full disclosure: I've tested this on Linux and on macOS, and it seems to work OK on both of those. I have not tested on Windows, since I don't have a Windows machine handy.
I've made a few choices here that we could change:
net_if_addrs()as opposed tonet_if_stats()or adding a new API. That makes the most sense to me, but I'm happy to change it if you feel otherwise.getifaddrs()on POSIX. The meaning of each of the bits is standardized by POSIX, so it should be the same on all platforms that support this. That said, we could make this "nicer" and possibly more Pythonic by expanding those bitfields into human-readable flags.Signed-off-by: Chris Lalancette clalancette@openrobotics.org