mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
NetUsage: finish module
This commit is contained in:
@@ -558,6 +558,7 @@
|
||||
"media",
|
||||
"memory",
|
||||
"monitor",
|
||||
"netusage",
|
||||
"opencl",
|
||||
"opengl",
|
||||
"os",
|
||||
@@ -1019,6 +1020,36 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "Network throughput (usage)",
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "netusage"
|
||||
},
|
||||
"namePrefix": {
|
||||
"title": "Show IPs with given name prefix only",
|
||||
"type": "string"
|
||||
},
|
||||
"defaultRouteOnly": {
|
||||
"title": "Show ips that are used for default routing only",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "OpenGL",
|
||||
"properties": {
|
||||
|
||||
@@ -61,7 +61,7 @@ void ffPrepareCommandOption(FFdata* data)
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETUSAGE_MODULE_NAME))
|
||||
ffPrepareNetUsage();
|
||||
ffPrepareNetUsage(&instance.config.netUsage);
|
||||
|
||||
if(instance.config.multithreading)
|
||||
{
|
||||
|
||||
@@ -112,6 +112,14 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
}
|
||||
case 'n': case 'N': {
|
||||
if (ffStrEqualsIgnCase(type, FF_NETUSAGE_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseNetUsageJsonObject(&cfg->netUsage, module);
|
||||
ffPrepareNetUsage(&cfg->netUsage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'p': case 'P': {
|
||||
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME))
|
||||
{
|
||||
|
||||
@@ -2,31 +2,33 @@
|
||||
|
||||
#include "common/time.h"
|
||||
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result);
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options);
|
||||
|
||||
static FFlist ioCounters1;
|
||||
static uint64_t time1;
|
||||
|
||||
void ffPrepareNetUsage(void)
|
||||
void ffPrepareNetUsage(FFNetUsageOptions* options)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters));
|
||||
ffNetUsageGetIoCounters(&ioCounters1);
|
||||
ffNetUsageGetIoCounters(&ioCounters1, options);
|
||||
time1 = ffTimeGetNow();
|
||||
}
|
||||
|
||||
const char* ffDetectNetUsage(FFlist* result)
|
||||
const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options)
|
||||
{
|
||||
const char* error = NULL;
|
||||
if (time1 == 0)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters));
|
||||
error = ffNetUsageGetIoCounters(&ioCounters1);
|
||||
error = ffNetUsageGetIoCounters(&ioCounters1, options);
|
||||
if (error)
|
||||
return error;
|
||||
time1 = ffTimeGetNow();
|
||||
ffTimeSleep(1000);
|
||||
}
|
||||
|
||||
if (ioCounters1.length == 0)
|
||||
return "No network interfaces found";
|
||||
|
||||
uint64_t time2 = ffTimeGetNow();
|
||||
while (time2 - time1 < 1000)
|
||||
{
|
||||
@@ -34,7 +36,7 @@ const char* ffDetectNetUsage(FFlist* result)
|
||||
time2 = ffTimeGetNow();
|
||||
}
|
||||
|
||||
error = ffNetUsageGetIoCounters(result);
|
||||
error = ffNetUsageGetIoCounters(result, options);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
typedef struct FFNetUsageIoCounters
|
||||
{
|
||||
FFstrbuf name;
|
||||
bool defaultRoute;
|
||||
uint64_t txBytes;
|
||||
uint64_t rxBytes;
|
||||
uint64_t txPackets;
|
||||
@@ -13,4 +14,4 @@ typedef struct FFNetUsageIoCounters
|
||||
uint64_t txDrops;
|
||||
} FFNetUsageIoCounters;
|
||||
|
||||
const char* ffDetectNetUsage(FFlist* result);
|
||||
const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "netusage.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <net/if.h>
|
||||
@@ -10,7 +11,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options)
|
||||
{
|
||||
size_t bufSize = 0;
|
||||
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0)
|
||||
@@ -20,6 +21,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) < 0)
|
||||
return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) failed";
|
||||
|
||||
const char* defaultRouteIface = ffNetifGetDefaultRoute();
|
||||
|
||||
for (struct if_msghdr2* ifm = buf;
|
||||
ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize);
|
||||
ifm = (struct if_msghdr2*) ((uint8_t*) ifm + ifm->ifm_msglen))
|
||||
@@ -29,9 +32,19 @@ const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1);
|
||||
assert(sdl->sdl_family == AF_LINK);
|
||||
if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue;
|
||||
FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result);
|
||||
|
||||
sdl->sdl_data[sdl->sdl_nlen] = 0;
|
||||
|
||||
bool isDefaultRoute = ffStrEquals(sdl->sdl_data, defaultRouteIface);
|
||||
if(options->defaultRouteOnly && !isDefaultRoute)
|
||||
continue;
|
||||
|
||||
if (options->namePrefix.length && strncmp(sdl->sdl_data, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result);
|
||||
*counters = (FFNetUsageIoCounters) {
|
||||
.name = ffStrbufCreateNS(sdl->sdl_nlen, sdl->sdl_data),
|
||||
.txBytes = ifm->ifm_data.ifi_obytes,
|
||||
.rxBytes = ifm->ifm_data.ifi_ibytes,
|
||||
.txPackets = ifm->ifm_data.ifi_opackets,
|
||||
@@ -40,9 +53,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
.rxErrors = ifm->ifm_data.ifi_ierrors,
|
||||
.txDrops = 0, // unsupported
|
||||
.rxDrops = ifm->ifm_data.ifi_iqdrops,
|
||||
.defaultRoute = isDefaultRoute,
|
||||
};
|
||||
|
||||
ffStrbufInitNS(&counters->name, sdl->sdl_nlen, sdl->sdl_data);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include "netusage.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net");
|
||||
if (!dirp) return "opendir(\"/sys/class/net\") == NULL";
|
||||
@@ -12,20 +14,30 @@ const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
const char* defaultRouteIface = ffNetifGetDefaultRoute();
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
bool isDefaultRoute = ffStrEquals(entry->d_name, defaultRouteIface);
|
||||
if(options->defaultRouteOnly && !isDefaultRoute)
|
||||
continue;
|
||||
|
||||
if (options->namePrefix.length && strncmp(entry->d_name, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
ffStrbufSetF(&path, "/sys/class/net/%s/operstate", entry->d_name);
|
||||
if(!ffReadFileBuffer(path.chars, &buffer) || !ffStrbufEqualS(&buffer, "up"))
|
||||
continue;
|
||||
|
||||
FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result);
|
||||
ffStrbufInitS(&counters->name, entry->d_name);
|
||||
counters->defaultRoute = isDefaultRoute;
|
||||
|
||||
ffStrbufSetF(&path, "/sys/class/net/%s/statistics/");
|
||||
ffStrbufSetF(&path, "/sys/class/net/%s/statistics/", entry->d_name);
|
||||
uint32_t statLen = path.length;
|
||||
|
||||
ffStrbufAppendS(&path, "rx_bytes");
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "netusage.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options)
|
||||
{
|
||||
IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL;
|
||||
|
||||
@@ -37,14 +37,26 @@ const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
return "GetAdaptersAddresses() failed";
|
||||
}
|
||||
|
||||
uint32_t defaultRouteIfIndex = ffNetifGetDefaultRoute();
|
||||
|
||||
// Iterate through all of the adapters
|
||||
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
|
||||
{
|
||||
bool isDefaultRoute = adapter->IfIndex == defaultRouteIfIndex;
|
||||
if (options->defaultRouteOnly && !isDefaultRoute)
|
||||
continue;
|
||||
|
||||
char name[128];
|
||||
WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL);
|
||||
if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex };
|
||||
if (GetIfEntry2(&ifRow) == NO_ERROR)
|
||||
{
|
||||
FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result);
|
||||
*counters = (FFNetUsageIoCounters) {
|
||||
.name = ffStrbufCreateS(name),
|
||||
.txBytes = ifRow.OutOctets,
|
||||
.rxBytes = ifRow.InOctets,
|
||||
.txPackets = (ifRow.OutUcastPkts + ifRow.OutNUcastPkts),
|
||||
@@ -53,8 +65,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result)
|
||||
.txErrors = ifRow.OutErrors,
|
||||
.rxDrops = ifRow.InDiscards,
|
||||
.txDrops = ifRow.OutDiscards,
|
||||
.defaultRoute = isDefaultRoute,
|
||||
};
|
||||
ffStrbufSetWS(&counters->name, adapter->FriendlyName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* in
|
||||
void ffPrintNetUsage(FFNetUsageOptions* options)
|
||||
{
|
||||
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters));
|
||||
const char* error = ffDetectNetUsage(&result);
|
||||
const char* error = ffDetectNetUsage(&result, options);
|
||||
|
||||
if(error)
|
||||
{
|
||||
@@ -63,6 +63,8 @@ void ffPrintNetUsage(FFNetUsageOptions* options)
|
||||
ffStrbufAppendS(&buffer, "/s (in) - ");
|
||||
ffParseSize(inf->txBytes, &buffer);
|
||||
ffStrbufAppendS(&buffer, "/s (out)");
|
||||
if (!options->defaultRouteOnly && inf->defaultRoute)
|
||||
ffStrbufAppendS(&buffer, " *");
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
else
|
||||
@@ -82,16 +84,25 @@ void ffPrintNetUsage(FFNetUsageOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_UINT64, &inf->txErrors},
|
||||
{FF_FORMAT_ARG_TYPE_UINT64, &inf->rxDrops},
|
||||
{FF_FORMAT_ARG_TYPE_UINT64, &inf->txDrops},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &inf->defaultRoute},
|
||||
});
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result)
|
||||
{
|
||||
ffStrbufDestroy(&inf->name);
|
||||
}
|
||||
}
|
||||
|
||||
void ffInitNetUsageOptions(FFNetUsageOptions* options)
|
||||
{
|
||||
ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETUSAGE_MODULE_NAME, ffParseNetUsageCommandOptions, ffParseNetUsageJsonObject, ffPrintNetUsage, ffGenerateNetUsageJson);
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
|
||||
ffStrbufInit(&options->namePrefix);
|
||||
options->defaultRouteOnly = false;
|
||||
}
|
||||
|
||||
bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value)
|
||||
@@ -101,12 +112,25 @@ bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key,
|
||||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
|
||||
return true;
|
||||
|
||||
if (ffStrEqualsIgnCase(subKey, "name-prefix"))
|
||||
{
|
||||
ffOptionParseString(key, value, &options->namePrefix);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(subKey, "default-route-only"))
|
||||
{
|
||||
options->defaultRouteOnly = ffOptionParseBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffDestroyNetUsageOptions(FFNetUsageOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
ffStrbufDestroy(&options->namePrefix);
|
||||
}
|
||||
|
||||
void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module)
|
||||
@@ -122,14 +146,26 @@ void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "namePrefix"))
|
||||
{
|
||||
ffStrbufSetS(&options->namePrefix, yyjson_get_str(val));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "defaultRouteOnly"))
|
||||
{
|
||||
options->defaultRouteOnly = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_NETUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
|
||||
void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters));
|
||||
const char* error = ffDetectNetUsage(&result);
|
||||
const char* error = ffDetectNetUsage(&result, options);
|
||||
|
||||
if(error)
|
||||
{
|
||||
@@ -150,6 +186,11 @@ void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_m
|
||||
yyjson_mut_obj_add_uint(doc, obj, "txErrors", counter->txErrors);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "rxDrops", counter->rxDrops);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", counter->defaultRoute);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result)
|
||||
{
|
||||
ffStrbufDestroy(&inf->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define FF_NETUSAGE_MODULE_NAME "NetUsage"
|
||||
|
||||
void ffPrepareNetUsage();
|
||||
void ffPrepareNetUsage(FFNetUsageOptions* options);
|
||||
|
||||
void ffPrintNetUsage(FFNetUsageOptions* options);
|
||||
void ffInitNetUsageOptions(FFNetUsageOptions* options);
|
||||
|
||||
@@ -8,4 +8,7 @@ typedef struct FFNetUsageOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFstrbuf namePrefix;
|
||||
bool defaultRouteOnly;
|
||||
} FFNetUsageOptions;
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
|
||||
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
|
||||
void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
|
||||
FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
|
||||
|
||||
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
|
||||
void ffStrbufTrimRight(FFstrbuf* strbuf, char c);
|
||||
|
||||
Reference in New Issue
Block a user