]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-link-bus.c
Merge pull request #12762 from yuwata/network-introduce-carrier-and-network-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 interval_sec;
29 uint64_t tx, rx;
30
31 assert(bus);
32 assert(reply);
33 assert(userdata);
34
35 manager = link->manager;
36
37 if (!manager->use_speed_meter)
38 return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Speed meter is disabled.");
39
40 if (manager->speed_meter_usec_old == 0)
41 return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Speed meter is not active.");
42
43 if (!link->stats_updated)
44 return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Failed to measure bit-rates.");
45
46 assert(manager->speed_meter_usec_new > manager->speed_meter_usec_old);
47 interval_sec = (manager->speed_meter_usec_new - manager->speed_meter_usec_old) / USEC_PER_SEC;
48
49 if (link->stats_new.tx_bytes > link->stats_old.tx_bytes)
50 tx = (uint64_t) ((link->stats_new.tx_bytes - link->stats_old.tx_bytes) / interval_sec);
51 else
52 tx = (uint64_t) ((UINT64_MAX - (link->stats_old.tx_bytes - link->stats_new.tx_bytes)) / interval_sec);
53
54 if (link->stats_new.rx_bytes > link->stats_old.rx_bytes)
55 rx = (uint64_t) ((link->stats_new.rx_bytes - link->stats_old.rx_bytes) / interval_sec);
56 else
57 rx = (uint64_t) ((UINT64_MAX - (link->stats_old.rx_bytes - link->stats_new.rx_bytes)) / interval_sec);
58
59 return sd_bus_message_append(reply, "(tt)", tx, rx);
60 }
61
62 const sd_bus_vtable link_vtable[] = {
63 SD_BUS_VTABLE_START(0),
64
65 SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
66 SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
67 SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
68 SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
69 SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),
70
71 SD_BUS_VTABLE_END
72 };
73
74 char *link_bus_path(Link *link) {
75 _cleanup_free_ char *ifindex = NULL;
76 char *p;
77 int r;
78
79 assert(link);
80 assert(link->ifindex > 0);
81
82 if (asprintf(&ifindex, "%d", link->ifindex) < 0)
83 return NULL;
84
85 r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p);
86 if (r < 0)
87 return NULL;
88
89 return p;
90 }
91
92 int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
93 _cleanup_strv_free_ char **l = NULL;
94 Manager *m = userdata;
95 unsigned c = 0;
96 Link *link;
97 Iterator i;
98
99 assert(bus);
100 assert(path);
101 assert(m);
102 assert(nodes);
103
104 l = new0(char*, hashmap_size(m->links) + 1);
105 if (!l)
106 return -ENOMEM;
107
108 HASHMAP_FOREACH(link, m->links, i) {
109 char *p;
110
111 p = link_bus_path(link);
112 if (!p)
113 return -ENOMEM;
114
115 l[c++] = p;
116 }
117
118 l[c] = NULL;
119 *nodes = TAKE_PTR(l);
120
121 return 1;
122 }
123
124 int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
125 _cleanup_free_ char *identifier = NULL;
126 Manager *m = userdata;
127 Link *link;
128 int ifindex, r;
129
130 assert(bus);
131 assert(path);
132 assert(interface);
133 assert(m);
134 assert(found);
135
136 r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
137 if (r <= 0)
138 return 0;
139
140 r = parse_ifindex(identifier, &ifindex);
141 if (r < 0)
142 return 0;
143
144 r = link_get(m, ifindex, &link);
145 if (r < 0)
146 return 0;
147
148 *found = link;
149
150 return 1;
151 }
152
153 int link_send_changed_strv(Link *link, char **properties) {
154 _cleanup_free_ char *p = NULL;
155
156 assert(link);
157 assert(link->manager);
158 assert(properties);
159
160 if (!link->manager->bus)
161 return 0;
162
163 p = link_bus_path(link);
164 if (!p)
165 return -ENOMEM;
166
167 return sd_bus_emit_properties_changed_strv(
168 link->manager->bus,
169 p,
170 "org.freedesktop.network1.Link",
171 properties);
172 }
173
174 int link_send_changed(Link *link, const char *property, ...) {
175 char **properties;
176
177 properties = strv_from_stdarg_alloca(property);
178
179 return link_send_changed_strv(link, properties);
180 }