]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-link-bus.c
timesync: judging if network is online by networkd's address state
[thirdparty/systemd.git] / src / network / networkd-link-bus.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "bus-common-errors.h"
5 #include "bus-util.h"
6 #include "networkd-link-bus.h"
7 #include "networkd-link.h"
8 #include "networkd-manager.h"
9 #include "parse-util.h"
10 #include "strv.h"
11
12 BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
13 BUS_DEFINE_PROPERTY_GET_ENUM(property_get_carrier_state, link_carrier_state, LinkCarrierState);
14 BUS_DEFINE_PROPERTY_GET_ENUM(property_get_address_state, link_address_state, LinkAddressState);
15 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
16
17 static int property_get_bit_rates(
18 sd_bus *bus,
19 const char *path,
20 const char *interface,
21 const char *property,
22 sd_bus_message *reply,
23 void *userdata,
24 sd_bus_error *error) {
25
26 Link *link = userdata;
27 Manager *manager;
28 double tx, rx, interval_sec;
29
30 assert(bus);
31 assert(reply);
32 assert(userdata);
33
34 manager = link->manager;
35
36 if (!manager->use_speed_meter)
37 return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Speed meter is disabled.");
38
39 if (manager->speed_meter_usec_old == 0)
40 return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Speed meter is not active.");
41
42 if (!link->stats_updated)
43 return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Failed to measure bit-rates.");
44
45 assert(manager->speed_meter_usec_new > manager->speed_meter_usec_old);
46 interval_sec = (double) (manager->speed_meter_usec_new - manager->speed_meter_usec_old) / USEC_PER_SEC;
47
48 if (link->stats_new.tx_bytes > link->stats_old.tx_bytes)
49 tx = (link->stats_new.tx_bytes - link->stats_old.tx_bytes) / interval_sec;
50 else
51 tx = (UINT64_MAX - (link->stats_old.tx_bytes - link->stats_new.tx_bytes)) / interval_sec;
52
53 if (link->stats_new.rx_bytes > link->stats_old.rx_bytes)
54 rx = (link->stats_new.rx_bytes - link->stats_old.rx_bytes) / interval_sec;
55 else
56 rx = (UINT64_MAX - (link->stats_old.rx_bytes - link->stats_new.rx_bytes)) / interval_sec;
57
58 return sd_bus_message_append(reply, "(dd)", tx, rx);
59 }
60
61 const sd_bus_vtable link_vtable[] = {
62 SD_BUS_VTABLE_START(0),
63
64 SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
65 SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
66 SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
67 SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
68 SD_BUS_PROPERTY("BitRates", "(dd)", property_get_bit_rates, 0, 0),
69
70 SD_BUS_VTABLE_END
71 };
72
73 char *link_bus_path(Link *link) {
74 _cleanup_free_ char *ifindex = NULL;
75 char *p;
76 int r;
77
78 assert(link);
79 assert(link->ifindex > 0);
80
81 if (asprintf(&ifindex, "%d", link->ifindex) < 0)
82 return NULL;
83
84 r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p);
85 if (r < 0)
86 return NULL;
87
88 return p;
89 }
90
91 int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
92 _cleanup_strv_free_ char **l = NULL;
93 Manager *m = userdata;
94 unsigned c = 0;
95 Link *link;
96 Iterator i;
97
98 assert(bus);
99 assert(path);
100 assert(m);
101 assert(nodes);
102
103 l = new0(char*, hashmap_size(m->links) + 1);
104 if (!l)
105 return -ENOMEM;
106
107 HASHMAP_FOREACH(link, m->links, i) {
108 char *p;
109
110 p = link_bus_path(link);
111 if (!p)
112 return -ENOMEM;
113
114 l[c++] = p;
115 }
116
117 l[c] = NULL;
118 *nodes = TAKE_PTR(l);
119
120 return 1;
121 }
122
123 int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
124 _cleanup_free_ char *identifier = NULL;
125 Manager *m = userdata;
126 Link *link;
127 int ifindex, r;
128
129 assert(bus);
130 assert(path);
131 assert(interface);
132 assert(m);
133 assert(found);
134
135 r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
136 if (r <= 0)
137 return 0;
138
139 r = parse_ifindex(identifier, &ifindex);
140 if (r < 0)
141 return 0;
142
143 r = link_get(m, ifindex, &link);
144 if (r < 0)
145 return 0;
146
147 *found = link;
148
149 return 1;
150 }
151
152 int link_send_changed_strv(Link *link, char **properties) {
153 _cleanup_free_ char *p = NULL;
154
155 assert(link);
156 assert(link->manager);
157 assert(properties);
158
159 if (!link->manager->bus)
160 return 0;
161
162 p = link_bus_path(link);
163 if (!p)
164 return -ENOMEM;
165
166 return sd_bus_emit_properties_changed_strv(
167 link->manager->bus,
168 p,
169 "org.freedesktop.network1.Link",
170 properties);
171 }
172
173 int link_send_changed(Link *link, const char *property, ...) {
174 char **properties;
175
176 properties = strv_from_stdarg_alloca(property);
177
178 return link_send_changed_strv(link, properties);
179 }