Skip to content

Commit

Permalink
Switch to putting the flags in net_if_stats
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Lalancette <[email protected]>
  • Loading branch information
clalancette committed Dec 21, 2021
1 parent f549c75 commit b75a234
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 51 deletions.
2 changes: 1 addition & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ XXXX-XX-XX
on some Linux distros) to real root device path.
- 2005_: PSUTIL_DEBUG mode now prints file name and line number of the debug
messages coming from C extension modules.
- 2037_: Add additional flags to net_if_addrs.
- 2037_: Add additional flags to net_if_stats.

**Bug fixes**

Expand Down
16 changes: 8 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -243,16 +243,16 @@ Network
...]
>>>
>>> psutil.net_if_addrs()
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None, flags=73),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None, flags=73),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None, flags=73)],
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None, flags=4163),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None, flags=4163),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None, flags=4163)]}
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
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
Expand Down
25 changes: 12 additions & 13 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -681,19 +681,17 @@ Network
- **ptp**: stands for "point to point"; it's the destination address on a
point to point interface (typically a VPN). *broadcast* and *ptp* are
mutually exclusive. May be ``None``.
- **flags**: an integer defining the network flags, like those returned
from `getifaddrs` on POSIX (may be ``None``).

Example::

>>> import psutil
>>> psutil.net_if_addrs()
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None, flags=73),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None, flags=73),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None, flags=73)],
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None, flags=4163),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None, flags=4163),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None, flags=4163)]}
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
>>>

See also `nettop.py`_ and `ifconfig.py`_ for an example application.
Expand All @@ -708,7 +706,7 @@ Network
interface (that's why dict values are lists).

.. note::
*broadcast*, *ptp*, and *flags* are not supported on Windows and are always ``None``.
*broadcast* and *ptp* are not supported on Windows and are always ``None``.

.. versionadded:: 3.0.0

Expand All @@ -717,8 +715,6 @@ Network
.. versionchanged:: 4.4.0 added support for *netmask* field on Windows which
is no longer ``None``.

.. versionchanged:: 5.9.0 *flags* field was added.

.. function:: net_if_stats()

Return information about each NIC (network interface card) installed on the
Expand All @@ -733,20 +729,23 @@ 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``).

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.

.. versionadded:: 3.0.0

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

.. versionchanged:: 5.9.0 *flags* field was added.

Sensors
-------

Expand Down
4 changes: 2 additions & 2 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2185,7 +2185,7 @@ def net_if_addrs():
rawlist = _psplatform.net_if_addrs()
rawlist.sort(key=lambda x: x[1]) # sort by family
ret = collections.defaultdict(list)
for name, fam, addr, mask, broadcast, ptp, flags in rawlist:
for name, fam, addr, mask, broadcast, ptp in rawlist:
if has_enums:
try:
fam = socket.AddressFamily(fam)
Expand All @@ -2205,7 +2205,7 @@ def net_if_addrs():
separator = ":" if POSIX else "-"
while addr.count(separator) < 5:
addr += "%s00" % separator
ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp, flags))
ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp))
return dict(ret)


Expand Down
4 changes: 2 additions & 2 deletions psutil/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ class BatteryTime(enum.IntEnum):
'status', 'pid'])
# psutil.net_if_addrs()
snicaddr = namedtuple('snicaddr',
['family', 'address', 'netmask', 'broadcast', 'ptp', 'flags'])
['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'])
Expand Down
2 changes: 1 addition & 1 deletion psutil/_psaix.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def net_if_stats():
duplex = re_result.group(2)

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)
return ret


Expand Down
11 changes: 9 additions & 2 deletions psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,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
Expand All @@ -360,7 +360,14 @@ def net_if_stats():
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
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
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
return ret


Expand Down
11 changes: 9 additions & 2 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,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
Expand All @@ -1087,7 +1087,14 @@ def net_if_stats():
else:
debug(err)
else:
ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu)
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
ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu, output_flags)
return ret


Expand Down
11 changes: 9 additions & 2 deletions psutil/_psosx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -272,7 +272,14 @@ def net_if_stats():
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
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
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
return ret


Expand Down
28 changes: 27 additions & 1 deletion psutil/_psposix.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,33 @@
enum = None


__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
__all__ = ['POSIX_NET_FLAGS', 'pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']


# This is a list of the standard POSIX interface flags.
# For each flag, we have its bit position in the bitfield,
# and its human-readable name.
POSIX_NET_FLAGS = [
('up', 0),
('broadcast', 1),
('debug', 2),
('loopback', 3),

('ptp', 4),
('notrailers', 5),
('running', 6),
('noarp', 7),

('promisc', 8),
('allmulti', 9),
('master', 10),
('slave', 11),

('multicast', 12),
('portsel', 13),
('automedia', 14),
('dynamic', 15),
]


def pid_exists(pid):
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)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
return ret


Expand Down
45 changes: 37 additions & 8 deletions psutil/_psutil_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
PyObject *py_netmask = NULL;
PyObject *py_broadcast = NULL;
PyObject *py_ptp = NULL;
PyObject *py_flags = NULL;

if (py_retlist == NULL)
return NULL;
Expand Down Expand Up @@ -346,19 +345,16 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
py_ptp = Py_None;
}

py_flags = PyLong_FromUnsignedLong(ifa->ifa_flags & 0xFFFF);

if ((py_broadcast == NULL) || (py_ptp == NULL))
goto error;
py_tuple = Py_BuildValue(
"(siOOOOO)",
"(siOOOO)",
ifa->ifa_name,
family,
py_address,
py_netmask,
py_broadcast,
py_ptp,
py_flags
py_ptp
);

if (! py_tuple)
Expand All @@ -370,7 +366,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
Py_CLEAR(py_netmask);
Py_CLEAR(py_broadcast);
Py_CLEAR(py_ptp);
Py_CLEAR(py_flags);
}

freeifaddrs(ifaddr);
Expand All @@ -385,7 +380,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
Py_XDECREF(py_netmask);
Py_XDECREF(py_broadcast);
Py_XDECREF(py_ptp);
Py_XDECREF(py_flags);
return NULL;
}

Expand Down Expand Up @@ -436,6 +430,39 @@ psutil_net_if_mtu(PyObject *self, PyObject *args) {
}


/*
* 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;

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

sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
goto error;

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

close(sock);

return Py_BuildValue("O", PyLong_FromUnsignedLong(ifr.ifr_flags & 0xFFFF));

error:
if (sock != -1)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
}


/*
* Inspect NIC flags, returns a bool indicating whether the NIC is
* running. References:
Expand Down Expand Up @@ -678,6 +705,8 @@ static PyMethodDef mod_methods[] = {
"Retrieve NICs information"},
{"net_if_mtu", psutil_net_if_mtu, METH_VARARGS,
"Retrieve NIC MTU"},
{"net_if_flags", psutil_net_if_flags, METH_VARARGS,
"Get all of the flags on the NIC."},
{"net_if_is_running", psutil_net_if_is_running, METH_VARARGS,
"Return True if the NIC is running."},
{"getpagesize", psutil_getpagesize_pywrapper, METH_VARARGS,
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)
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
return ret


Expand Down
6 changes: 2 additions & 4 deletions psutil/arch/windows/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,14 @@ psutil_net_if_addrs(PyObject *self, PyObject *args) {
Py_INCREF(Py_None);
Py_INCREF(Py_None);
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_tuple = Py_BuildValue(
"(OiOOOOO)",
"(OiOOOO)",
py_nic_name,
-1, // this will be converted later to AF_LINK
py_mac_address,
Py_None, // netmask (not supported)
Py_None, // broadcast (not supported)
Py_None, // ptp (not supported on Windows)
Py_None // flags (not supported)
Py_None // ptp (not supported on Windows)
);
if (! py_tuple)
goto error;
Expand Down
Loading

0 comments on commit b75a234

Please sign in to comment.