Skip to content

Commit b75a234

Browse files
committed
Switch to putting the flags in net_if_stats
Signed-off-by: Chris Lalancette <[email protected]>
1 parent f549c75 commit b75a234

15 files changed

+124
-51
lines changed

HISTORY.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ XXXX-XX-XX
1818
on some Linux distros) to real root device path.
1919
- 2005_: PSUTIL_DEBUG mode now prints file name and line number of the debug
2020
messages coming from C extension modules.
21-
- 2037_: Add additional flags to net_if_addrs.
21+
- 2037_: Add additional flags to net_if_stats.
2222

2323
**Bug fixes**
2424

README.rst

+8-8
Original file line numberDiff line numberDiff line change
@@ -243,16 +243,16 @@ Network
243243
...]
244244
>>>
245245
>>> psutil.net_if_addrs()
246-
{'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),
247-
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None, flags=73),
248-
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)],
249-
'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),
250-
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None, flags=4163),
251-
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)]}
246+
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
247+
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
248+
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
249+
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
250+
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
251+
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
252252
>>>
253253
>>> psutil.net_if_stats()
254-
{'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536),
255-
'wlan0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500)}
254+
{'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536, flags='up,loopback,running'),
255+
'wlan0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500, flags='up,broadcast,running,multicast')}
256256
>>>
257257
258258
Sensors

docs/index.rst

+12-13
Original file line numberDiff line numberDiff line change
@@ -681,19 +681,17 @@ Network
681681
- **ptp**: stands for "point to point"; it's the destination address on a
682682
point to point interface (typically a VPN). *broadcast* and *ptp* are
683683
mutually exclusive. May be ``None``.
684-
- **flags**: an integer defining the network flags, like those returned
685-
from `getifaddrs` on POSIX (may be ``None``).
686684

687685
Example::
688686

689687
>>> import psutil
690688
>>> psutil.net_if_addrs()
691-
{'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),
692-
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None, flags=73),
693-
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)],
694-
'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),
695-
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None, flags=4163),
696-
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)]}
689+
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
690+
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
691+
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
692+
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
693+
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
694+
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
697695
>>>
698696

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

710708
.. note::
711-
*broadcast*, *ptp*, and *flags* are not supported on Windows and are always ``None``.
709+
*broadcast* and *ptp* are not supported on Windows and are always ``None``.
712710

713711
.. versionadded:: 3.0.0
714712

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

720-
.. versionchanged:: 5.9.0 *flags* field was added.
721-
722718
.. function:: net_if_stats()
723719

724720
Return information about each NIC (network interface card) installed on the
@@ -733,20 +729,23 @@ Network
733729
- **speed**: the NIC speed expressed in mega bits (MB), if it can't be
734730
determined (e.g. 'localhost') it will be set to ``0``.
735731
- **mtu**: NIC's maximum transmission unit expressed in bytes.
732+
- **flags**: a string of comma-separate flags on the interface (may be ``None``).
736733

737734
Example:
738735

739736
>>> import psutil
740737
>>> psutil.net_if_stats()
741-
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
742-
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
738+
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500, flags='up,broadcast,running,multicast'),
739+
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536, flags='up,loopback,running')}
743740

744741
Also see `nettop.py`_ and `ifconfig.py`_ for an example application.
745742

746743
.. versionadded:: 3.0.0
747744

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

747+
.. versionchanged:: 5.9.0 *flags* field was added.
748+
750749
Sensors
751750
-------
752751

psutil/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2185,7 +2185,7 @@ def net_if_addrs():
21852185
rawlist = _psplatform.net_if_addrs()
21862186
rawlist.sort(key=lambda x: x[1]) # sort by family
21872187
ret = collections.defaultdict(list)
2188-
for name, fam, addr, mask, broadcast, ptp, flags in rawlist:
2188+
for name, fam, addr, mask, broadcast, ptp in rawlist:
21892189
if has_enums:
21902190
try:
21912191
fam = socket.AddressFamily(fam)
@@ -2205,7 +2205,7 @@ def net_if_addrs():
22052205
separator = ":" if POSIX else "-"
22062206
while addr.count(separator) < 5:
22072207
addr += "%s00" % separator
2208-
ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp, flags))
2208+
ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp))
22092209
return dict(ret)
22102210

22112211

psutil/_common.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,9 @@ class BatteryTime(enum.IntEnum):
195195
'status', 'pid'])
196196
# psutil.net_if_addrs()
197197
snicaddr = namedtuple('snicaddr',
198-
['family', 'address', 'netmask', 'broadcast', 'ptp', 'flags'])
198+
['family', 'address', 'netmask', 'broadcast', 'ptp'])
199199
# psutil.net_if_stats()
200-
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
200+
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu', 'flags'])
201201
# psutil.cpu_stats()
202202
scpustats = namedtuple(
203203
'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'])

psutil/_psaix.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ def net_if_stats():
258258
duplex = re_result.group(2)
259259

260260
duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN)
261-
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
261+
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
262262
return ret
263263

264264

psutil/_psbsd.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ def net_if_stats():
351351
for name in names:
352352
try:
353353
mtu = cext_posix.net_if_mtu(name)
354-
isup = cext_posix.net_if_is_running(name)
354+
flags = cext_posix.net_if_flags(name)
355355
duplex, speed = cext_posix.net_if_duplex_speed(name)
356356
except OSError as err:
357357
# https://github.com/giampaolo/psutil/issues/1279
@@ -360,7 +360,14 @@ def net_if_stats():
360360
else:
361361
if hasattr(_common, 'NicDuplex'):
362362
duplex = _common.NicDuplex(duplex)
363-
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
363+
flag_list = []
364+
for flagname, bit in _psposix.POSIX_NET_FLAGS:
365+
if flags & (1 << bit):
366+
flag_list.append(flagname)
367+
368+
output_flags = ','.join(flag_list)
369+
isup = 'running' in output_flags
370+
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
364371
return ret
365372

366373

psutil/_pslinux.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@ def net_if_stats():
10781078
for name in names:
10791079
try:
10801080
mtu = cext_posix.net_if_mtu(name)
1081-
isup = cext_posix.net_if_is_running(name)
1081+
flags = cext_posix.net_if_flags(name)
10821082
duplex, speed = cext.net_if_duplex_speed(name)
10831083
except OSError as err:
10841084
# https://github.com/giampaolo/psutil/issues/1279
@@ -1087,7 +1087,14 @@ def net_if_stats():
10871087
else:
10881088
debug(err)
10891089
else:
1090-
ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu)
1090+
flag_list = []
1091+
for flagname, bit in _psposix.POSIX_NET_FLAGS:
1092+
if flags & (1 << bit):
1093+
flag_list.append(flagname)
1094+
1095+
output_flags = ','.join(flag_list)
1096+
isup = 'running' in output_flags
1097+
ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu, output_flags)
10911098
return ret
10921099

10931100

psutil/_psosx.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def net_if_stats():
263263
for name in names:
264264
try:
265265
mtu = cext_posix.net_if_mtu(name)
266-
isup = cext_posix.net_if_is_running(name)
266+
flags = cext_posix.net_if_flags(name)
267267
duplex, speed = cext_posix.net_if_duplex_speed(name)
268268
except OSError as err:
269269
# https://github.com/giampaolo/psutil/issues/1279
@@ -272,7 +272,14 @@ def net_if_stats():
272272
else:
273273
if hasattr(_common, 'NicDuplex'):
274274
duplex = _common.NicDuplex(duplex)
275-
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
275+
flag_list = []
276+
for flagname, bit in _psposix.POSIX_NET_FLAGS:
277+
if flags & (1 << bit):
278+
flag_list.append(flagname)
279+
280+
output_flags = ','.join(flag_list)
281+
isup = 'running' in output_flags
282+
ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
276283
return ret
277284

278285

psutil/_psposix.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,33 @@
2929
enum = None
3030

3131

32-
__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
32+
__all__ = ['POSIX_NET_FLAGS', 'pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
33+
34+
35+
# This is a list of the standard POSIX interface flags.
36+
# For each flag, we have its bit position in the bitfield,
37+
# and its human-readable name.
38+
POSIX_NET_FLAGS = [
39+
('up', 0),
40+
('broadcast', 1),
41+
('debug', 2),
42+
('loopback', 3),
43+
44+
('ptp', 4),
45+
('notrailers', 5),
46+
('running', 6),
47+
('noarp', 7),
48+
49+
('promisc', 8),
50+
('allmulti', 9),
51+
('master', 10),
52+
('slave', 11),
53+
54+
('multicast', 12),
55+
('portsel', 13),
56+
('automedia', 14),
57+
('dynamic', 15),
58+
]
3359

3460

3561
def pid_exists(pid):

psutil/_pssunos.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def net_if_stats():
293293
isup, duplex, speed, mtu = items
294294
if hasattr(_common, 'NicDuplex'):
295295
duplex = _common.NicDuplex(duplex)
296-
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
296+
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
297297
return ret
298298

299299

psutil/_psutil_posix.c

+37-8
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
305305
PyObject *py_netmask = NULL;
306306
PyObject *py_broadcast = NULL;
307307
PyObject *py_ptp = NULL;
308-
PyObject *py_flags = NULL;
309308

310309
if (py_retlist == NULL)
311310
return NULL;
@@ -346,19 +345,16 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
346345
py_ptp = Py_None;
347346
}
348347

349-
py_flags = PyLong_FromUnsignedLong(ifa->ifa_flags & 0xFFFF);
350-
351348
if ((py_broadcast == NULL) || (py_ptp == NULL))
352349
goto error;
353350
py_tuple = Py_BuildValue(
354-
"(siOOOOO)",
351+
"(siOOOO)",
355352
ifa->ifa_name,
356353
family,
357354
py_address,
358355
py_netmask,
359356
py_broadcast,
360-
py_ptp,
361-
py_flags
357+
py_ptp
362358
);
363359

364360
if (! py_tuple)
@@ -370,7 +366,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
370366
Py_CLEAR(py_netmask);
371367
Py_CLEAR(py_broadcast);
372368
Py_CLEAR(py_ptp);
373-
Py_CLEAR(py_flags);
374369
}
375370

376371
freeifaddrs(ifaddr);
@@ -385,7 +380,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
385380
Py_XDECREF(py_netmask);
386381
Py_XDECREF(py_broadcast);
387382
Py_XDECREF(py_ptp);
388-
Py_XDECREF(py_flags);
389383
return NULL;
390384
}
391385

@@ -436,6 +430,39 @@ psutil_net_if_mtu(PyObject *self, PyObject *args) {
436430
}
437431

438432

433+
/*
434+
* Get all of the NIC flags and return them.
435+
*/
436+
static PyObject *
437+
psutil_net_if_flags(PyObject *self, PyObject *args) {
438+
char *nic_name;
439+
int sock = -1;
440+
int ret;
441+
struct ifreq ifr;
442+
443+
if (! PyArg_ParseTuple(args, "s", &nic_name))
444+
return NULL;
445+
446+
sock = socket(AF_INET, SOCK_DGRAM, 0);
447+
if (sock == -1)
448+
goto error;
449+
450+
PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
451+
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
452+
if (ret == -1)
453+
goto error;
454+
455+
close(sock);
456+
457+
return Py_BuildValue("O", PyLong_FromUnsignedLong(ifr.ifr_flags & 0xFFFF));
458+
459+
error:
460+
if (sock != -1)
461+
close(sock);
462+
return PyErr_SetFromErrno(PyExc_OSError);
463+
}
464+
465+
439466
/*
440467
* Inspect NIC flags, returns a bool indicating whether the NIC is
441468
* running. References:
@@ -678,6 +705,8 @@ static PyMethodDef mod_methods[] = {
678705
"Retrieve NICs information"},
679706
{"net_if_mtu", psutil_net_if_mtu, METH_VARARGS,
680707
"Retrieve NIC MTU"},
708+
{"net_if_flags", psutil_net_if_flags, METH_VARARGS,
709+
"Get all of the flags on the NIC."},
681710
{"net_if_is_running", psutil_net_if_is_running, METH_VARARGS,
682711
"Return True if the NIC is running."},
683712
{"getpagesize", psutil_getpagesize_pywrapper, METH_VARARGS,

psutil/_pswindows.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ def net_if_stats():
386386
isup, duplex, speed, mtu = items
387387
if hasattr(_common, 'NicDuplex'):
388388
duplex = _common.NicDuplex(duplex)
389-
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
389+
ret[name] = _common.snicstats(isup, duplex, speed, mtu, None)
390390
return ret
391391

392392

psutil/arch/windows/net.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -201,16 +201,14 @@ psutil_net_if_addrs(PyObject *self, PyObject *args) {
201201
Py_INCREF(Py_None);
202202
Py_INCREF(Py_None);
203203
Py_INCREF(Py_None);
204-
Py_INCREF(Py_None);
205204
py_tuple = Py_BuildValue(
206-
"(OiOOOOO)",
205+
"(OiOOOO)",
207206
py_nic_name,
208207
-1, // this will be converted later to AF_LINK
209208
py_mac_address,
210209
Py_None, // netmask (not supported)
211210
Py_None, // broadcast (not supported)
212-
Py_None, // ptp (not supported on Windows)
213-
Py_None // flags (not supported)
211+
Py_None // ptp (not supported on Windows)
214212
);
215213
if (! py_tuple)
216214
goto error;

0 commit comments

Comments
 (0)