]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-speed-meter.c
Merge pull request #12750 from keszybz/tmpfiles-c-copy
[thirdparty/systemd.git] / src / network / networkd-speed-meter.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4
5 #include "sd-event.h"
6 #include "sd-netlink.h"
7
8 #include "networkd-link-bus.h"
9 #include "networkd-link.h"
10 #include "networkd-manager.h"
11 #include "networkd-speed-meter.h"
12
13 static int process_message(Manager *manager, sd_netlink_message *message) {
14 uint16_t type;
15 int ifindex, r;
16 Link *link;
17
18 r = sd_netlink_message_get_type(message, &type);
19 if (r < 0)
20 return r;
21
22 if (type != RTM_NEWLINK)
23 return 0;
24
25 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
26 if (r < 0)
27 return r;
28
29 link = hashmap_get(manager->links, INT_TO_PTR(ifindex));
30 if (!link)
31 return -ENODEV;
32
33 link->stats_old = link->stats_new;
34
35 r = sd_netlink_message_read(message, IFLA_STATS64, sizeof link->stats_new, &link->stats_new);
36 if (r < 0)
37 return r;
38
39 link->stats_updated = true;
40
41 return 0;
42 }
43
44 static int speed_meter_handler(sd_event_source *s, uint64_t usec, void *userdata) {
45 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
46 Manager *manager = userdata;
47 sd_netlink_message *i;
48 usec_t usec_now;
49 Iterator j;
50 Link *link;
51 int r;
52
53 assert(s);
54 assert(userdata);
55
56 r = sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &usec_now);
57 if (r < 0)
58 return r;
59
60 r = sd_event_source_set_time(s, usec_now + manager->speed_meter_interval_usec);
61 if (r < 0)
62 return r;
63
64 manager->speed_meter_usec_old = manager->speed_meter_usec_new;
65 manager->speed_meter_usec_new = usec_now;
66
67 HASHMAP_FOREACH(link, manager->links, j)
68 link->stats_updated = false;
69
70 r = sd_rtnl_message_new_link(manager->rtnl, &req, RTM_GETLINK, 0);
71 if (r < 0) {
72 log_warning_errno(r, "Failed to allocate RTM_GETLINK netlink message, ignoring: %m");
73 return 0;
74 }
75
76 r = sd_netlink_message_request_dump(req, true);
77 if (r < 0) {
78 log_warning_errno(r, "Failed to set dump flag, ignoring: %m");
79 return 0;
80 }
81
82 r = sd_netlink_call(manager->rtnl, req, 0, &reply);
83 if (r < 0) {
84 log_warning_errno(r, "Failed to call RTM_GETLINK, ignoring: %m");
85 return 0;
86 }
87
88 for (i = reply; i; i = sd_netlink_message_next(i))
89 (void) process_message(manager, i);
90
91 return 0;
92 }
93
94 int manager_start_speed_meter(Manager *manager) {
95 _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
96 int r;
97
98 assert(manager);
99 assert(manager->event);
100
101 if (!manager->use_speed_meter)
102 return 0;
103
104 r = sd_event_add_time(manager->event, &s, CLOCK_MONOTONIC, 0, 0, speed_meter_handler, manager);
105 if (r < 0)
106 return r;
107
108 r = sd_event_source_set_enabled(s, SD_EVENT_ON);
109 if (r < 0)
110 return r;
111
112 manager->speed_meter_event_source = TAKE_PTR(s);
113 return 0;
114 }