summaryrefslogtreecommitdiffstats
path: root/darwin
diff options
context:
space:
mode:
authorUeiWang <weiwang.ueiwaon@gmail.com>2023-05-12 22:47:29 +0800
committerBenBE <BenBE@geshi.org>2023-12-29 14:35:04 +0100
commit7ee92be6fdf8d3718202ab42aefb028d3a7eac94 (patch)
tree0236884c47b5f6a49bf8c4f52b6e1e07d6aefee7 /darwin
parent6490590dc8510ea1cc89cec666020c83af1046b5 (diff)
Darwin: add NetworkIOMeter support
Diffstat (limited to 'darwin')
-rw-r--r--darwin/Platform.c66
1 files changed, 63 insertions, 3 deletions
diff --git a/darwin/Platform.c b/darwin/Platform.c
index f72f8aec..387910e1 100644
--- a/darwin/Platform.c
+++ b/darwin/Platform.c
@@ -14,6 +14,10 @@ in the source distribution for its full text.
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <sys/socket.h>
#include <sys/_types/_mach_port_t.h>
#include <CoreFoundation/CFBase.h>
@@ -138,6 +142,7 @@ const MeterClass* const Platform_meterTypes[] = {
&ZfsArcMeter_class,
&ZfsCompressedArcMeter_class,
&DiskIOMeter_class,
+ &NetworkIOMeter_class,
&FileDescriptorMeter_class,
&BlankMeter_class,
NULL
@@ -467,10 +472,65 @@ bool Platform_getDiskIO(DiskIOData* data) {
return true;
}
+/* Caution: Given that interfaces are dynamic, and it is not possible to get statistics on interfaces that no longer exist,
+ if some interface disappears between the time of two samples, the values of the second sample may be lower than those of
+ the first one. */
bool Platform_getNetworkIO(NetworkIOData* data) {
- // TODO
- (void)data;
- return false;
+ int mib[6] = {CTL_NET,
+ PF_ROUTE, /* routing messages */
+ 0, /* protocal number, currently always 0 */
+ 0, /* select all address families */
+ NET_RT_IFLIST2, /* interface list with addresses */
+ 0};
+
+ for (size_t retry = 0; retry < 4; retry++) {
+ size_t len = 0;
+
+ /* Determine len */
+ if (sysctl(mib, ARRAYSIZE(mib), NULL, &len, NULL, 0) < 0 || len == 0)
+ return false;
+
+ len += 16 * retry * retry * sizeof(struct if_msghdr2);
+ char *buf = xMalloc(len);
+
+ if (sysctl(mib, ARRAYSIZE(mib), buf, &len, NULL, 0) < 0) {
+ free(buf);
+ if (errno == ENOMEM && retry < 3)
+ continue;
+ else
+ return false;
+ }
+
+ uint64_t bytesReceived_sum = 0, packetsReceived_sum = 0, bytesTransmitted_sum = 0, packetsTransmitted_sum = 0;
+
+ for (char *next = buf; next < buf + len;) {
+ void *tmp = (void*) next;
+ struct if_msghdr *ifm = (struct if_msghdr*) tmp;
+
+ next += ifm->ifm_msglen;
+
+ if (ifm->ifm_type != RTM_IFINFO2)
+ continue;
+
+ struct if_msghdr2 *ifm2 = (struct if_msghdr2*) ifm;
+
+ if (ifm2->ifm_data.ifi_type != IFT_LOOP) { /* do not count loopback traffic */
+ bytesReceived_sum += ifm2->ifm_data.ifi_ibytes;
+ packetsReceived_sum += ifm2->ifm_data.ifi_ipackets;
+ bytesTransmitted_sum += ifm2->ifm_data.ifi_obytes;
+ packetsTransmitted_sum += ifm2->ifm_data.ifi_opackets;
+ }
+ }
+
+ data->bytesReceived = bytesReceived_sum;
+ data->packetsReceived = packetsReceived_sum;
+ data->bytesTransmitted = bytesTransmitted_sum;
+ data->packetsTransmitted = packetsTransmitted_sum;
+
+ free(buf);
+ }
+
+ return true;
}
void Platform_getBattery(double* percent, ACPresence* isOnAC) {

© 2014-2024 Faster IT GmbH | imprint | privacy policy