Skip to content

Commit

Permalink
Fixes from review.
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
  • Loading branch information
clalancette committed Aug 18, 2022
1 parent 1a5842b commit e05f926
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 76 deletions.
9 changes: 7 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,12 @@ Network
- **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``).
- **flags**: a string of comma-separated flags on the interface (may be the empty string).
Possible flags are: ``up``, ``broadcast``, ``debug``, ``loopback``,
``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).

Example:

Expand All @@ -750,7 +755,7 @@ Network

.. versionchanged:: 5.7.3 `isup` on UNIX also checks whether the NIC is running.

.. versionchanged:: 5.9.1 *flags* field was added.
.. versionchanged:: 5.9.1 *flags* field was added on POSIX.

Sensors
-------
Expand Down
7 changes: 5 additions & 2 deletions psutil/_psaix.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ def net_if_stats():
names = set([x[0] for x in net_if_addrs()])
ret = {}
for name in names:
isup, mtu = cext.net_if_stats(name)
mtu = cext_posix.net_if_mtu(name)
flags = cext_posix.net_if_flags(name)

# try to get speed and duplex
# TODO: rewrite this in C (entstat forks, so use truss -f to follow.
Expand All @@ -257,8 +258,10 @@ def net_if_stats():
speed = int(re_result.group(1))
duplex = re_result.group(2)

output_flags = ','.join(flags)
isup = 'running' in flags
duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
return ret


Expand Down
9 changes: 2 additions & 7 deletions psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,13 +390,8 @@ def net_if_stats():
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
flag_list = []
for flagname, bit in _psposix.POSIX_NET_FLAGS:
if flags & (1 << bit):
flag_list.append(flagname)

output_flags = ','.join(flag_list)
isup = 'running' in output_flags
output_flags = ','.join(flags)
isup = 'running' in flags
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
return ret

Expand Down
2 changes: 1 addition & 1 deletion psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ def net_if_stats():
debug(err)
else:
output_flags = ','.join(flags)
isup = 'running' in output_flags
isup = 'running' in flags
ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu, output_flags)
return ret

Expand Down
2 changes: 1 addition & 1 deletion psutil/_psosx.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def net_if_stats():
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
output_flags = ','.join(flags)
isup = 'running' in output_flags
isup = 'running' in flags
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
return ret

Expand Down
2 changes: 1 addition & 1 deletion psutil/_pssunos.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def net_if_stats():
isup, duplex, speed, mtu = items
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, '')
return ret


Expand Down
203 changes: 142 additions & 61 deletions psutil/_psutil_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <Python.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <signal.h>
Expand Down Expand Up @@ -429,6 +430,24 @@ psutil_net_if_mtu(PyObject *self, PyObject *args) {
return PyErr_SetFromErrno(PyExc_OSError);
}

static bool
check_and_append_iff_flag(PyObject *py_retlist, short int flags, short int flag_to_check, const char * flag_name)
{
PyObject *py_str = NULL;

if (flags & flag_to_check) {
py_str = PyUnicode_DecodeFSDefault(flag_name);
if (! py_str)
return false;
if (PyList_Append(py_retlist, py_str)) {
Py_DECREF(py_str);
return false;
}
Py_CLEAR(py_str);
}

return true;
}

/*
* Get all of the NIC flags and return them.
Expand All @@ -440,89 +459,151 @@ psutil_net_if_flags(PyObject *self, PyObject *args) {
int ret;
struct ifreq ifr;
PyObject *py_retlist = PyList_New(0);
PyObject *py_flag = NULL;
short int flags;

if (py_retlist == NULL)
return NULL;

if (! PyArg_ParseTuple(args, "s", &nic_name))
return NULL;
goto error;

sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
return NULL;
if (sock == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}

PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
if (ret == -1)
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}

close(sock);
sock = -1;

flags = ifr.ifr_flags & 0xFFFF;

if (flags & IFF_UP) {
py_flag = PyUnicode_DecodeFSDefault("up");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_BROADCAST) {
py_flag = PyUnicode_DecodeFSDefault("broadcast");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_DEBUG) {
py_flag = PyUnicode_DecodeFSDefault("debug");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_LOOPBACK) {
py_flag = PyUnicode_DecodeFSDefault("loopback");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_POINTOPOINT) {
py_flag = PyUnicode_DecodeFSDefault("pointopoint");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_NOTRAILERS) {
py_flag = PyUnicode_DecodeFSDefault("notrailers");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_RUNNING) {
py_flag = PyUnicode_DecodeFSDefault("running");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_NOARP) {
py_flag = PyUnicode_DecodeFSDefault("noarp");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_PROMISC) {
py_flag = PyUnicode_DecodeFSDefault("promisc");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_ALLMULTI) {
py_flag = PyUnicode_DecodeFSDefault("allmulti");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
if (flags & IFF_MULTICAST) {
py_flag = PyUnicode_DecodeFSDefault("multicast");
if (PyList_Append(py_retlist, py_flag))
goto error;
}
// Linux/glibc IFF flags: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/gnu/net/if.h;h=251418f82331c0426e58707fe4473d454893b132;hb=HEAD
// macOS IFF flags: https://opensource.apple.com/source/xnu/xnu-792/bsd/net/if.h.auto.html
// AIX IFF flags: https://www.ibm.com/support/pages/how-hexadecimal-flags-displayed-ifconfig-are-calculated
// FreeBSD IFF flags: https://www.freebsd.org/cgi/man.cgi?query=if_allmulti&apropos=0&sektion=0&manpath=FreeBSD+10-current&format=html

#ifdef IFF_UP
// Available in (at least) Linux, macOS, AIX, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_UP, "up"))
goto error;
#endif
#ifdef IFF_BROADCAST
// Available in (at least) Linux, macOS, AIX, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_BROADCAST, "broadcast"))
goto error;
#endif
#ifdef IFF_DEBUG
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_DEBUG, "debug"))
goto error;
#endif
#ifdef IFF_LOOPBACK
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_LOOPBACK, "loopback"))
goto error;
#endif
#ifdef IFF_POINTOPOINT
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_POINTOPOINT, "pointopoint"))
goto error;
#endif
#ifdef IFF_NOTRAILERS
// Available in (at least) Linux, macOS, AIX
if (!check_and_append_iff_flag(py_retlist, flags, IFF_NOTRAILERS, "notrailers"))
goto error;
#endif
#ifdef IFF_RUNNING
// Available in (at least) Linux, macOS, AIX, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_RUNNING, "running"))
goto error;
#endif
#ifdef IFF_NOARP
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_NOARP, "noarp"))
goto error;
#endif
#ifdef IFF_PROMISC
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_PROMISC, "promisc"))
goto error;
#endif
#ifdef IFF_ALLMULTI
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_ALLMULTI, "allmulti"))
goto error;
#endif
#ifdef IFF_MASTER
// Available in (at least) Linux
if (!check_and_append_iff_flag(py_retlist, flags, IFF_MASTER, "master"))
goto error;
#endif
#ifdef IFF_SLAVE
// Available in (at least) Linux
if (!check_and_append_iff_flag(py_retlist, flags, IFF_SLAVE, "slave"))
goto error;
#endif
#ifdef IFF_MULTICAST
// Available in (at least) Linux, macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_MULTICAST, "multicast"))
goto error;
#endif
#ifdef IFF_PORTSEL
// Available in (at least) Linux
if (!check_and_append_iff_flag(py_retlist, flags, IFF_PORTSEL, "portsel"))
goto error;
#endif
#ifdef IFF_AUTOMEDIA
// Available in (at least) Linux
if (!check_and_append_iff_flag(py_retlist, flags, IFF_AUTOMEDIA, "automedia"))
goto error;
#endif
#ifdef IFF_DYNAMIC
// Available in (at least) Linux
if (!check_and_append_iff_flag(py_retlist, flags, IFF_DYNAMIC, "dynamic"))
goto error;
#endif
#ifdef IFF_OACTIVE
// Available in (at least) macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_OACTIVE, "oactive"))
goto error;
#endif
#ifdef IFF_SIMPLEX
// Available in (at least) macOS, AIX, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_SIMPLEX, "simplex"))
goto error;
#endif
#ifdef IFF_LINK0
// Available in (at least) macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_LINK0, "link0"))
goto error;
#endif
#ifdef IFF_LINK1
// Available in (at least) macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_LINK1, "link1"))
goto error;
#endif
#ifdef IFF_LINK2
// Available in (at least) macOS, BSD
if (!check_and_append_iff_flag(py_retlist, flags, IFF_LINK2, "link2"))
goto error;
#endif
#ifdef IFF_D2
// Available in (at least) AIX
if (!check_and_append_iff_flag(py_retlist, flags, IFF_D2, "d2"))
goto error;
#endif

return py_retlist;

error:
Py_XDECREF(py_flag);
Py_DECREF(py_retlist);
if (sock != -1)
close(sock);
Expand Down
2 changes: 1 addition & 1 deletion psutil/_pswindows.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ def net_if_stats():
isup, duplex, speed, mtu = items
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, '')
return ret


Expand Down

0 comments on commit e05f926

Please sign in to comment.