module/network: Add link stats

Exports two new tags from network module, `ul-speed` and `dl-speed`.
Because these work through polling, poll-interval must be set.
Otherwise, these two tags always will be 0.
This commit is contained in:
Johannes 2022-04-30 05:08:05 +02:00
parent eb5cb9869c
commit 03e1c7dc13
4 changed files with 81 additions and 4 deletions

View file

@ -22,6 +22,8 @@
* river: support for the new “mode” event present in version 3 of the
river status manager protocol, in the form of a new tag, _”mode”_,
in the `title` particle.
* network: request link stats and expose under tags `dl-speed` and
`ul-speed` when `poll-interval` is set.
[153]: https://codeberg.org/dnkl/yambar/issues/153

View file

@ -51,6 +51,12 @@ address.
| tx-bitrate
: int
: TX bitrate in bits/s
| dl-speed
: int
: Download speed in bits/s
| ul-speed
: int
: Upload speed in bits/s
# CONFIGURATION
@ -66,7 +72,8 @@ address.
| poll-interval
: int
: no
: Periodically (in seconds) update the signal and rx+tx bitrate tags.
: Periodically (in seconds) update the signal, rx+tx bitrate, and
ul+dl speed tags.
# EXAMPLES

View file

@ -185,6 +185,7 @@ bar:
ipv4 == "": {string: {text: , font: *awesome, foreground: ffffff66}}
- network:
name: wlp2s0
poll-interval: 1
content:
map:
default: {string: {text: , font: *awesome, foreground: ffffff66}}
@ -194,11 +195,12 @@ bar:
map:
default:
- string: {text: , font: *awesome}
- string: {text: "{ssid}"}
- string: {text: "{ssid} {dl-speed:mb}/{ul-speed:mb} Mb/s"}
conditions:
ipv4 == "":
- string: {text: , font: *awesome, foreground: ffffff66}
- string: {text: "{ssid}", foreground: ffffff66}
- string: {text: "{ssid} {dl-speed:mb}/{ul-speed:mb} Mb/s", foreground: ffffff66}
- alsa:
card: hw:PCH
mixer: Master

View file

@ -31,6 +31,11 @@
#define UNUSED __attribute__((unused))
struct rt_stats_msg {
struct rtmsg rth;
struct rtnl_link_stats64 stats;
};
struct af_addr {
int family;
union {
@ -68,6 +73,12 @@ struct private {
int signal_strength_dbm;
uint32_t rx_bitrate;
uint32_t tx_bitrate;
uint64_t ul_speed;
uint64_t ul_bits;
uint64_t dl_speed;
uint64_t dl_bits;
};
static void
@ -145,8 +156,10 @@ content(struct module *mod)
tag_new_int(mod, "signal", m->signal_strength_dbm),
tag_new_int(mod, "rx-bitrate", m->rx_bitrate),
tag_new_int(mod, "tx-bitrate", m->tx_bitrate),
tag_new_float(mod, "dl-speed", m->dl_speed),
tag_new_float(mod, "ul-speed", m->ul_speed),
},
.count = 11,
.count = 13,
};
mtx_unlock(&mod->lock);
@ -252,6 +265,36 @@ send_rt_request(struct private *m, int request)
return true;
}
static bool
send_rt_getstats_request(struct private *m)
{
struct {
struct nlmsghdr hdr;
struct if_stats_msg rt;
} req = {
.hdr = {
.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt)),
.nlmsg_type = RTM_GETSTATS,
.nlmsg_flags = NLM_F_REQUEST,
.nlmsg_seq = 1,
.nlmsg_pid = nl_pid_value(),
},
.rt = {
.ifindex = m->ifindex,
.filter_mask = IFLA_STATS_LINK_64,
.family = AF_UNSPEC,
},
};
if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) {
LOG_ERRNO("%s: failed to send netlink RT getstats request (%d)",
m->iface, RTM_GETSTATS);
return false;
}
return true;
}
static bool
send_ctrl_get_family_request(struct private *m)
{
@ -929,6 +972,23 @@ netlink_receive_messages(int sock, void **reply, size_t *len)
return true;
}
static void
handle_stats(struct module *mod, struct rt_stats_msg *msg)
{
struct private *m = mod->private;
uint64_t ul_bits = msg->stats.tx_bytes*8;
uint64_t dl_bits = msg->stats.rx_bytes*8;
if (m->ul_bits != 0) {
m->ul_speed = (ul_bits - m->ul_bits) / m->poll_interval;
}
if (m->dl_bits != 0) {
m->dl_speed = (dl_bits - m->dl_bits) / m->poll_interval;
}
m->ul_bits = ul_bits;
m->dl_bits = dl_bits;
}
static bool
parse_rt_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
{
@ -967,6 +1027,11 @@ parse_rt_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
handle_address(mod, hdr->nlmsg_type, msg, msg_len);
break;
}
case RTM_NEWSTATS: {
struct rt_stats_msg *msg = NLMSG_DATA(hdr);
handle_stats(mod, msg);
break;
}
case NLMSG_ERROR:{
const struct nlmsgerr *err = NLMSG_DATA(hdr);
@ -1200,6 +1265,7 @@ run(struct module *mod)
}
send_nl80211_get_station(m);
send_rt_getstats_request(m);
}
}