summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS4
-rw-r--r--HISTORY.rst1
-rw-r--r--README.rst4
-rw-r--r--docs/index.rst14
-rw-r--r--psutil/_common.py3
-rw-r--r--psutil/_psaix.py7
-rw-r--r--psutil/_psbsd.py7
-rw-r--r--psutil/_pslinux.py7
-rw-r--r--psutil/_psosx.py7
-rw-r--r--psutil/_pssunos.py2
-rw-r--r--psutil/_psutil_posix.c201
-rw-r--r--psutil/_pswindows.py2
-rwxr-xr-xpsutil/tests/test_system.py3
13 files changed, 246 insertions, 16 deletions
diff --git a/CREDITS b/CREDITS
index c697e214..b212397e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -789,3 +789,7 @@ I: 2099
N: Torsten Blum
I: 2114
+
+N: Chris Lalancette
+W: https://github.com/clalancette
+I: 2037
diff --git a/HISTORY.rst b/HISTORY.rst
index 7767c08a..572c7f26 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -24,6 +24,7 @@
- 1053_: drop Python 2.6 support. (patches by Matthieu Darbois and Hugo van
Kemenade)
+- 2037_: Add additional flags to net_if_stats.
- 2050_, [Linux]: increase ``read(2)`` buffer size from 1k to 32k when reading
``/proc`` pseudo files line by line. This should help having more consistent
results.
diff --git a/README.rst b/README.rst
index 0e0a29af..5f0afcdf 100644
--- a/README.rst
+++ b/README.rst
@@ -252,8 +252,8 @@ Network
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
>>>
>>> psutil.net_if_stats()
- {'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536),
- 'wlan0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500)}
+ {'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536, flags='up,loopback,running'),
+ 'wlan0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500, flags='up,broadcast,running,multicast')}
>>>
Sensors
diff --git a/docs/index.rst b/docs/index.rst
index 8d663c7e..c30f7d6a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -735,13 +735,21 @@ 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-separated flags on the interface (may be an 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).
+
+ Availability: UNIX
Example:
>>> import psutil
>>> psutil.net_if_stats()
- {'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
- 'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
+ {'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500, flags='up,broadcast,running,multicast'),
+ 'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536, flags='up,loopback,running')}
Also see `nettop.py`_ and `ifconfig.py`_ for an example application.
@@ -749,6 +757,8 @@ Network
.. versionchanged:: 5.7.3 `isup` on UNIX also checks whether the NIC is running.
+ .. versionchanged:: 5.9.3 *flags* field was added on POSIX.
+
Sensors
-------
diff --git a/psutil/_common.py b/psutil/_common.py
index 9937eb83..3414e8ca 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -199,7 +199,8 @@ sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
snicaddr = namedtuple('snicaddr',
['family', 'address', 'netmask', 'broadcast', 'ptp'])
# psutil.net_if_stats()
-snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
+snicstats = namedtuple('snicstats',
+ ['isup', 'duplex', 'speed', 'mtu', 'flags'])
# psutil.cpu_stats()
scpustats = namedtuple(
'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'])
diff --git a/psutil/_psaix.py b/psutil/_psaix.py
index 9cc7d56e..2391478c 100644
--- a/psutil/_psaix.py
+++ b/psutil/_psaix.py
@@ -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.
@@ -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)
+ ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
return ret
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index 8672ca6e..a25c96cd 100644
--- a/psutil/_psbsd.py
+++ b/psutil/_psbsd.py
@@ -383,7 +383,7 @@ def net_if_stats():
for name in names:
try:
mtu = cext_posix.net_if_mtu(name)
- isup = cext_posix.net_if_is_running(name)
+ flags = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1279
@@ -392,7 +392,10 @@ def net_if_stats():
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
- ret[name] = _common.snicstats(isup, duplex, speed, mtu)
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ ret[name] = _common.snicstats(isup, duplex, speed, mtu,
+ output_flags)
return ret
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index e7cef439..57349889 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -1060,7 +1060,7 @@ def net_if_stats():
for name in names:
try:
mtu = cext_posix.net_if_mtu(name)
- isup = cext_posix.net_if_is_running(name)
+ flags = cext_posix.net_if_flags(name)
duplex, speed = cext.net_if_duplex_speed(name)
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1279
@@ -1069,7 +1069,10 @@ def net_if_stats():
else:
debug(err)
else:
- ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu)
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu,
+ output_flags)
return ret
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index ac8ecc53..58359bc9 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -263,7 +263,7 @@ def net_if_stats():
for name in names:
try:
mtu = cext_posix.net_if_mtu(name)
- isup = cext_posix.net_if_is_running(name)
+ flags = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1279
@@ -272,7 +272,10 @@ def net_if_stats():
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
- ret[name] = _common.snicstats(isup, duplex, speed, mtu)
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ ret[name] = _common.snicstats(isup, duplex, speed, mtu,
+ output_flags)
return ret
diff --git a/psutil/_pssunos.py b/psutil/_pssunos.py
index 69b579c5..541c1aa4 100644
--- a/psutil/_pssunos.py
+++ b/psutil/_pssunos.py
@@ -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)
+ ret[name] = _common.snicstats(isup, duplex, speed, mtu, '')
return ret
diff --git a/psutil/_psutil_posix.c b/psutil/_psutil_posix.c
index 04536614..7742eb41 100644
--- a/psutil/_psutil_posix.c
+++ b/psutil/_psutil_posix.c
@@ -429,6 +429,206 @@ error:
return PyErr_SetFromErrno(PyExc_OSError);
}
+static int
+append_flag(PyObject *py_retlist, const char * flag_name)
+{
+ PyObject *py_str = NULL;
+
+ py_str = PyUnicode_DecodeFSDefault(flag_name);
+ if (! py_str)
+ return 0;
+ if (PyList_Append(py_retlist, py_str)) {
+ Py_DECREF(py_str);
+ return 0;
+ }
+ Py_CLEAR(py_str);
+
+ return 1;
+}
+
+/*
+ * Get all of the NIC flags and return them.
+ */
+static PyObject *
+psutil_net_if_flags(PyObject *self, PyObject *args) {
+ char *nic_name;
+ int sock = -1;
+ int ret;
+ struct ifreq ifr;
+ PyObject *py_retlist = PyList_New(0);
+ short int flags;
+
+ if (py_retlist == NULL)
+ return NULL;
+
+ if (! PyArg_ParseTuple(args, "s", &nic_name))
+ goto error;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ PyErr_SetFromOSErrnoWithSyscall("socket(SOCK_DGRAM)");
+ goto error;
+ }
+
+ PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
+ ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
+ if (ret == -1) {
+ PyErr_SetFromOSErrnoWithSyscall("ioctl(SIOCGIFFLAGS)");
+ goto error;
+ }
+
+ close(sock);
+ sock = -1;
+
+ flags = ifr.ifr_flags & 0xFFFF;
+
+ // 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 (flags & IFF_UP)
+ if (!append_flag(py_retlist, "up"))
+ goto error;
+#endif
+#ifdef IFF_BROADCAST
+ // Available in (at least) Linux, macOS, AIX, BSD
+ if (flags & IFF_BROADCAST)
+ if (!append_flag(py_retlist, "broadcast"))
+ goto error;
+#endif
+#ifdef IFF_DEBUG
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_DEBUG)
+ if (!append_flag(py_retlist, "debug"))
+ goto error;
+#endif
+#ifdef IFF_LOOPBACK
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_LOOPBACK)
+ if (!append_flag(py_retlist, "loopback"))
+ goto error;
+#endif
+#ifdef IFF_POINTOPOINT
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_POINTOPOINT)
+ if (!append_flag(py_retlist, "pointopoint"))
+ goto error;
+#endif
+#ifdef IFF_NOTRAILERS
+ // Available in (at least) Linux, macOS, AIX
+ if (flags & IFF_NOTRAILERS)
+ if (!append_flag(py_retlist, "notrailers"))
+ goto error;
+#endif
+#ifdef IFF_RUNNING
+ // Available in (at least) Linux, macOS, AIX, BSD
+ if (flags & IFF_RUNNING)
+ if (!append_flag(py_retlist, "running"))
+ goto error;
+#endif
+#ifdef IFF_NOARP
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_NOARP)
+ if (!append_flag(py_retlist, "noarp"))
+ goto error;
+#endif
+#ifdef IFF_PROMISC
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_PROMISC)
+ if (!append_flag(py_retlist, "promisc"))
+ goto error;
+#endif
+#ifdef IFF_ALLMULTI
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_ALLMULTI)
+ if (!append_flag(py_retlist, "allmulti"))
+ goto error;
+#endif
+#ifdef IFF_MASTER
+ // Available in (at least) Linux
+ if (flags & IFF_MASTER)
+ if (!append_flag(py_retlist, "master"))
+ goto error;
+#endif
+#ifdef IFF_SLAVE
+ // Available in (at least) Linux
+ if (flags & IFF_SLAVE)
+ if (!append_flag(py_retlist, "slave"))
+ goto error;
+#endif
+#ifdef IFF_MULTICAST
+ // Available in (at least) Linux, macOS, BSD
+ if (flags & IFF_MULTICAST)
+ if (!append_flag(py_retlist, "multicast"))
+ goto error;
+#endif
+#ifdef IFF_PORTSEL
+ // Available in (at least) Linux
+ if (flags & IFF_PORTSEL)
+ if (!append_flag(py_retlist, "portsel"))
+ goto error;
+#endif
+#ifdef IFF_AUTOMEDIA
+ // Available in (at least) Linux
+ if (flags & IFF_AUTOMEDIA)
+ if (!append_flag(py_retlist, "automedia"))
+ goto error;
+#endif
+#ifdef IFF_DYNAMIC
+ // Available in (at least) Linux
+ if (flags & IFF_DYNAMIC)
+ if (!append_flag(py_retlist, "dynamic"))
+ goto error;
+#endif
+#ifdef IFF_OACTIVE
+ // Available in (at least) macOS, BSD
+ if (flags & IFF_OACTIVE)
+ if (!append_flag(py_retlist, "oactive"))
+ goto error;
+#endif
+#ifdef IFF_SIMPLEX
+ // Available in (at least) macOS, AIX, BSD
+ if (flags & IFF_SIMPLEX)
+ if (!append_flag(py_retlist, "simplex"))
+ goto error;
+#endif
+#ifdef IFF_LINK0
+ // Available in (at least) macOS, BSD
+ if (flags & IFF_LINK0)
+ if (!append_flag(py_retlist, "link0"))
+ goto error;
+#endif
+#ifdef IFF_LINK1
+ // Available in (at least) macOS, BSD
+ if (flags & IFF_LINK1)
+ if (!append_flag(py_retlist, "link1"))
+ goto error;
+#endif
+#ifdef IFF_LINK2
+ // Available in (at least) macOS, BSD
+ if (flags & IFF_LINK2)
+ if (!append_flag(py_retlist, "link2"))
+ goto error;
+#endif
+#ifdef IFF_D2
+ // Available in (at least) AIX
+ if (flags & IFF_D2)
+ if (!append_flag(py_retlist, "d2"))
+ goto error;
+#endif
+
+ return py_retlist;
+
+error:
+ Py_DECREF(py_retlist);
+ if (sock != -1)
+ close(sock);
+ return NULL;
+}
+
/*
* Inspect NIC flags, returns a bool indicating whether the NIC is
@@ -667,6 +867,7 @@ static PyMethodDef mod_methods[] = {
{"getpagesize", psutil_getpagesize_pywrapper, METH_VARARGS},
{"getpriority", psutil_posix_getpriority, METH_VARARGS},
{"net_if_addrs", psutil_net_if_addrs, METH_VARARGS},
+ {"net_if_flags", psutil_net_if_flags, METH_VARARGS},
{"net_if_is_running", psutil_net_if_is_running, METH_VARARGS},
{"net_if_mtu", psutil_net_if_mtu, METH_VARARGS},
{"setpriority", psutil_posix_setpriority, METH_VARARGS},
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 31edffc1..7d882b77 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -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)
+ ret[name] = _common.snicstats(isup, duplex, speed, mtu, '')
return ret
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index e130c935..d6b7a21a 100755
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -808,12 +808,13 @@ class TestNetAPIs(PsutilTestCase):
psutil.NIC_DUPLEX_UNKNOWN)
for name, stats in nics.items():
self.assertIsInstance(name, str)
- isup, duplex, speed, mtu = stats
+ isup, duplex, speed, mtu, flags = stats
self.assertIsInstance(isup, bool)
self.assertIn(duplex, all_duplexes)
self.assertIn(duplex, all_duplexes)
self.assertGreaterEqual(speed, 0)
self.assertGreaterEqual(mtu, 0)
+ self.assertIsInstance(flags, str)
@unittest.skipIf(not (LINUX or BSD or MACOS),
"LINUX or BSD or MACOS specific")