Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include "sd-netlink.h"
4 : :
5 : : #include "alloc-util.h"
6 : : #include "bond.h"
7 : : #include "conf-parser.h"
8 : : #include "ether-addr-util.h"
9 : : #include "extract-word.h"
10 : : #include "netlink-util.h"
11 : : #include "networkd-manager.h"
12 : : #include "string-table.h"
13 : : #include "string-util.h"
14 : :
15 : : /*
16 : : * Number of seconds between instances where the bonding
17 : : * driver sends learning packets to each slaves peer switch
18 : : */
19 : : #define LEARNING_PACKETS_INTERVAL_MIN_SEC (1 * USEC_PER_SEC)
20 : : #define LEARNING_PACKETS_INTERVAL_MAX_SEC (0x7fffffff * USEC_PER_SEC)
21 : :
22 : : /* Number of IGMP membership reports to be issued after
23 : : * a failover event.
24 : : */
25 : : #define RESEND_IGMP_MIN 0
26 : : #define RESEND_IGMP_MAX 255
27 : : #define RESEND_IGMP_DEFAULT 1
28 : :
29 : : /*
30 : : * Number of packets to transmit through a slave before
31 : : * moving to the next one.
32 : : */
33 : : #define PACKETS_PER_SLAVE_MIN 0
34 : : #define PACKETS_PER_SLAVE_MAX 65535
35 : : #define PACKETS_PER_SLAVE_DEFAULT 1
36 : :
37 : : /*
38 : : * Number of peer notifications (gratuitous ARPs and
39 : : * unsolicited IPv6 Neighbor Advertisements) to be issued after a
40 : : * failover event.
41 : : */
42 : : #define GRATUITOUS_ARP_MIN 0
43 : : #define GRATUITOUS_ARP_MAX 255
44 : : #define GRATUITOUS_ARP_DEFAULT 1
45 : :
46 : : static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = {
47 : : [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr",
48 : : [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup",
49 : : [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor",
50 : : [NETDEV_BOND_MODE_BROADCAST] = "broadcast",
51 : : [NETDEV_BOND_MODE_802_3AD] = "802.3ad",
52 : : [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb",
53 : : [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb",
54 : : };
55 : :
56 [ + + + + ]: 72 : DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode);
57 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode");
# # # # #
# # # ]
58 : :
59 : : static const char* const bond_xmit_hash_policy_table[_NETDEV_BOND_XMIT_HASH_POLICY_MAX] = {
60 : : [NETDEV_BOND_XMIT_HASH_POLICY_LAYER2] = "layer2",
61 : : [NETDEV_BOND_XMIT_HASH_POLICY_LAYER34] = "layer3+4",
62 : : [NETDEV_BOND_XMIT_HASH_POLICY_LAYER23] = "layer2+3",
63 : : [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23] = "encap2+3",
64 : : [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34] = "encap3+4",
65 : : };
66 : :
67 [ + + + + ]: 56 : DEFINE_STRING_TABLE_LOOKUP(bond_xmit_hash_policy, BondXmitHashPolicy);
68 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_xmit_hash_policy,
# # # # #
# # # ]
69 : : bond_xmit_hash_policy,
70 : : BondXmitHashPolicy,
71 : : "Failed to parse bond transmit hash policy")
72 : :
73 : : static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = {
74 : : [NETDEV_BOND_LACP_RATE_SLOW] = "slow",
75 : : [NETDEV_BOND_LACP_RATE_FAST] = "fast",
76 : : };
77 : :
78 [ + + + + ]: 32 : DEFINE_STRING_TABLE_LOOKUP(bond_lacp_rate, BondLacpRate);
79 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_lacp_rate, bond_lacp_rate, BondLacpRate, "Failed to parse bond lacp rate")
# # # # #
# # # ]
80 : :
81 : : static const char* const bond_ad_select_table[_NETDEV_BOND_AD_SELECT_MAX] = {
82 : : [NETDEV_BOND_AD_SELECT_STABLE] = "stable",
83 : : [NETDEV_BOND_AD_SELECT_BANDWIDTH] = "bandwidth",
84 : : [NETDEV_BOND_AD_SELECT_COUNT] = "count",
85 : : };
86 : :
87 [ + + + + ]: 40 : DEFINE_STRING_TABLE_LOOKUP(bond_ad_select, BondAdSelect);
88 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_ad_select, bond_ad_select, BondAdSelect, "Failed to parse bond AD select");
# # # # #
# # # ]
89 : :
90 : : static const char* const bond_fail_over_mac_table[_NETDEV_BOND_FAIL_OVER_MAC_MAX] = {
91 : : [NETDEV_BOND_FAIL_OVER_MAC_NONE] = "none",
92 : : [NETDEV_BOND_FAIL_OVER_MAC_ACTIVE] = "active",
93 : : [NETDEV_BOND_FAIL_OVER_MAC_FOLLOW] = "follow",
94 : : };
95 : :
96 [ + + + + ]: 40 : DEFINE_STRING_TABLE_LOOKUP(bond_fail_over_mac, BondFailOverMac);
97 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_fail_over_mac, bond_fail_over_mac, BondFailOverMac, "Failed to parse bond fail over MAC");
# # # # #
# # # ]
98 : :
99 : : static const char *const bond_arp_validate_table[_NETDEV_BOND_ARP_VALIDATE_MAX] = {
100 : : [NETDEV_BOND_ARP_VALIDATE_NONE] = "none",
101 : : [NETDEV_BOND_ARP_VALIDATE_ACTIVE]= "active",
102 : : [NETDEV_BOND_ARP_VALIDATE_BACKUP]= "backup",
103 : : [NETDEV_BOND_ARP_VALIDATE_ALL]= "all",
104 : : };
105 : :
106 [ + + + + ]: 48 : DEFINE_STRING_TABLE_LOOKUP(bond_arp_validate, BondArpValidate);
107 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_validate, bond_arp_validate, BondArpValidate, "Failed to parse bond arp validate");
# # # # #
# # # ]
108 : :
109 : : static const char *const bond_arp_all_targets_table[_NETDEV_BOND_ARP_ALL_TARGETS_MAX] = {
110 : : [NETDEV_BOND_ARP_ALL_TARGETS_ANY] = "any",
111 : : [NETDEV_BOND_ARP_ALL_TARGETS_ALL] = "all",
112 : : };
113 : :
114 [ + + + + ]: 32 : DEFINE_STRING_TABLE_LOOKUP(bond_arp_all_targets, BondArpAllTargets);
115 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_all_targets, bond_arp_all_targets, BondArpAllTargets, "Failed to parse bond Arp all targets");
# # # # #
# # # ]
116 : :
117 : : static const char *const bond_primary_reselect_table[_NETDEV_BOND_PRIMARY_RESELECT_MAX] = {
118 : : [NETDEV_BOND_PRIMARY_RESELECT_ALWAYS] = "always",
119 : : [NETDEV_BOND_PRIMARY_RESELECT_BETTER]= "better",
120 : : [NETDEV_BOND_PRIMARY_RESELECT_FAILURE]= "failure",
121 : : };
122 : :
123 [ + + + + ]: 40 : DEFINE_STRING_TABLE_LOOKUP(bond_primary_reselect, BondPrimaryReselect);
124 [ # # # # : 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_primary_reselect, bond_primary_reselect, BondPrimaryReselect, "Failed to parse bond primary reselect");
# # # # #
# # # ]
125 : :
126 : 0 : static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
127 : : Bond *b;
128 : : int r;
129 : :
130 [ # # ]: 0 : assert(netdev);
131 [ # # ]: 0 : assert(!link);
132 [ # # ]: 0 : assert(m);
133 : :
134 : 0 : b = BOND(netdev);
135 : :
136 [ # # ]: 0 : assert(b);
137 : :
138 [ # # ]: 0 : if (b->mode != _NETDEV_BOND_MODE_INVALID) {
139 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_MODE, b->mode);
140 [ # # ]: 0 : if (r < 0)
141 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MODE attribute: %m");
142 : : }
143 : :
144 [ # # ]: 0 : if (b->xmit_hash_policy != _NETDEV_BOND_XMIT_HASH_POLICY_INVALID) {
145 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_XMIT_HASH_POLICY, b->xmit_hash_policy);
146 [ # # ]: 0 : if (r < 0)
147 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_XMIT_HASH_POLICY attribute: %m");
148 : : }
149 : :
150 [ # # ]: 0 : if (b->lacp_rate != _NETDEV_BOND_LACP_RATE_INVALID &&
151 [ # # ]: 0 : b->mode == NETDEV_BOND_MODE_802_3AD) {
152 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_LACP_RATE, b->lacp_rate);
153 [ # # ]: 0 : if (r < 0)
154 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_LACP_RATE attribute: %m");
155 : : }
156 : :
157 [ # # ]: 0 : if (b->miimon != 0) {
158 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_MIIMON, b->miimon / USEC_PER_MSEC);
159 [ # # ]: 0 : if (r < 0)
160 [ # # ]: 0 : log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_BOND_MIIMON attribute: %m");
161 : : }
162 : :
163 [ # # ]: 0 : if (b->downdelay != 0) {
164 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_DOWNDELAY, b->downdelay / USEC_PER_MSEC);
165 [ # # ]: 0 : if (r < 0)
166 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_DOWNDELAY attribute: %m");
167 : : }
168 : :
169 [ # # ]: 0 : if (b->updelay != 0) {
170 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_UPDELAY, b->updelay / USEC_PER_MSEC);
171 [ # # ]: 0 : if (r < 0)
172 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_UPDELAY attribute: %m");
173 : : }
174 : :
175 [ # # ]: 0 : if (b->arp_interval != 0) {
176 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_INTERVAL, b->arp_interval / USEC_PER_MSEC);
177 [ # # ]: 0 : if (r < 0)
178 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_INTERVAL attribute: %m");
179 : :
180 [ # # ]: 0 : if (b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC &&
181 [ # # ]: 0 : b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC) {
182 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC);
183 [ # # ]: 0 : if (r < 0)
184 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_LP_INTERVAL attribute: %m");
185 : : }
186 : : }
187 : :
188 [ # # ]: 0 : if (b->ad_select != _NETDEV_BOND_AD_SELECT_INVALID &&
189 [ # # ]: 0 : b->mode == NETDEV_BOND_MODE_802_3AD) {
190 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_SELECT, b->ad_select);
191 [ # # ]: 0 : if (r < 0)
192 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_SELECT attribute: %m");
193 : : }
194 : :
195 [ # # ]: 0 : if (b->fail_over_mac != _NETDEV_BOND_FAIL_OVER_MAC_INVALID &&
196 [ # # ]: 0 : b->mode == NETDEV_BOND_MODE_ACTIVE_BACKUP) {
197 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_FAIL_OVER_MAC, b->fail_over_mac);
198 [ # # ]: 0 : if (r < 0)
199 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %m");
200 : : }
201 : :
202 [ # # ]: 0 : if (b->arp_validate != _NETDEV_BOND_ARP_VALIDATE_INVALID) {
203 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_VALIDATE, b->arp_validate);
204 [ # # ]: 0 : if (r < 0)
205 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m");
206 : : }
207 : :
208 [ # # ]: 0 : if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) {
209 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets);
210 [ # # ]: 0 : if (r < 0)
211 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m");
212 : : }
213 : :
214 [ # # ]: 0 : if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) {
215 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_PRIMARY_RESELECT, b->primary_reselect);
216 [ # # ]: 0 : if (r < 0)
217 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PRIMARY_RESELECT attribute: %m");
218 : : }
219 : :
220 [ # # ]: 0 : if (b->resend_igmp <= RESEND_IGMP_MAX) {
221 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_RESEND_IGMP, b->resend_igmp);
222 [ # # ]: 0 : if (r < 0)
223 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_RESEND_IGMP attribute: %m");
224 : : }
225 : :
226 [ # # ]: 0 : if (b->packets_per_slave <= PACKETS_PER_SLAVE_MAX &&
227 [ # # ]: 0 : b->mode == NETDEV_BOND_MODE_BALANCE_RR) {
228 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_PACKETS_PER_SLAVE, b->packets_per_slave);
229 [ # # ]: 0 : if (r < 0)
230 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %m");
231 : : }
232 : :
233 [ # # ]: 0 : if (b->num_grat_arp <= GRATUITOUS_ARP_MAX) {
234 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_NUM_PEER_NOTIF, b->num_grat_arp);
235 [ # # ]: 0 : if (r < 0)
236 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %m");
237 : : }
238 : :
239 [ # # ]: 0 : if (b->min_links != 0) {
240 : 0 : r = sd_netlink_message_append_u32(m, IFLA_BOND_MIN_LINKS, b->min_links);
241 [ # # ]: 0 : if (r < 0)
242 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m");
243 : : }
244 : :
245 [ # # ]: 0 : if (b->ad_actor_sys_prio != 0) {
246 : 0 : r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_ACTOR_SYS_PRIO, b->ad_actor_sys_prio);
247 [ # # ]: 0 : if (r < 0)
248 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYS_PRIO attribute: %m");
249 : : }
250 : :
251 [ # # ]: 0 : if (b->ad_user_port_key != 0) {
252 : 0 : r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_USER_PORT_KEY, b->ad_user_port_key);
253 [ # # ]: 0 : if (r < 0)
254 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_USER_PORT_KEY attribute: %m");
255 : : }
256 : :
257 [ # # ]: 0 : if (!ether_addr_is_null(&b->ad_actor_system)) {
258 : 0 : r = sd_netlink_message_append_ether_addr(m, IFLA_BOND_AD_ACTOR_SYSTEM, &b->ad_actor_system);
259 [ # # ]: 0 : if (r < 0)
260 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYSTEM attribute: %m");
261 : : }
262 : :
263 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active);
264 [ # # ]: 0 : if (r < 0)
265 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m");
266 : :
267 [ # # ]: 0 : if (b->tlb_dynamic_lb >= 0) {
268 : 0 : r = sd_netlink_message_append_u8(m, IFLA_BOND_TLB_DYNAMIC_LB, b->tlb_dynamic_lb);
269 [ # # ]: 0 : if (r < 0)
270 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_TLB_DYNAMIC_LB attribute: %m");
271 : : }
272 : :
273 [ # # # # ]: 0 : if (b->arp_interval > 0 && !ordered_set_isempty(b->arp_ip_targets)) {
274 : : Iterator i;
275 : : void *val;
276 : 0 : int n = 0;
277 : :
278 : 0 : r = sd_netlink_message_open_container(m, IFLA_BOND_ARP_IP_TARGET);
279 [ # # ]: 0 : if (r < 0)
280 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %m");
281 : :
282 [ # # ]: 0 : ORDERED_SET_FOREACH(val, b->arp_ip_targets, i) {
283 : 0 : r = sd_netlink_message_append_u32(m, n++, PTR_TO_UINT32(val));
284 [ # # ]: 0 : if (r < 0)
285 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m");
286 : : }
287 : :
288 : 0 : r = sd_netlink_message_close_container(m);
289 [ # # ]: 0 : if (r < 0)
290 [ # # ]: 0 : return log_netdev_error_errno(netdev, r, "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %m");
291 : : }
292 : :
293 : 0 : return 0;
294 : : }
295 : :
296 : 0 : static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
297 : : int r;
298 : :
299 [ # # ]: 0 : assert(m);
300 [ # # ]: 0 : assert(link);
301 [ # # ]: 0 : assert(link->ifname);
302 : :
303 [ # # # # ]: 0 : if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
304 : 0 : return 1;
305 : :
306 : 0 : r = sd_netlink_message_get_errno(m);
307 [ # # ]: 0 : if (r < 0) {
308 [ # # # # ]: 0 : log_link_warning_errno(link, r, "Could not set bonding interface: %m");
309 : 0 : return 1;
310 : : }
311 : :
312 : 0 : return 1;
313 : : }
314 : :
315 : 0 : int link_set_bond(Link *link) {
316 : 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
317 : : int r;
318 : :
319 [ # # ]: 0 : assert(link);
320 [ # # ]: 0 : assert(link->network);
321 : :
322 : 0 : r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
323 [ # # ]: 0 : if (r < 0)
324 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
325 : :
326 : 0 : r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
327 [ # # ]: 0 : if (r < 0)
328 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not set netlink flags: %m");
329 : :
330 : 0 : r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
331 [ # # ]: 0 : if (r < 0)
332 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
333 : :
334 : 0 : r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
335 [ # # ]: 0 : if (r < 0)
336 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
337 : :
338 [ # # ]: 0 : if (link->network->active_slave) {
339 : 0 : r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
340 [ # # ]: 0 : if (r < 0)
341 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
342 : : }
343 : :
344 [ # # ]: 0 : if (link->network->primary_slave) {
345 : 0 : r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
346 [ # # ]: 0 : if (r < 0)
347 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
348 : : }
349 : :
350 : 0 : r = sd_netlink_message_close_container(req);
351 [ # # ]: 0 : if (r < 0)
352 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
353 : :
354 : 0 : r = sd_netlink_message_close_container(req);
355 [ # # ]: 0 : if (r < 0)
356 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
357 : :
358 : 0 : r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
359 : : link_netlink_destroy_callback, link);
360 [ # # ]: 0 : if (r < 0)
361 [ # # # # ]: 0 : return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
362 : :
363 : 0 : link_ref(link);
364 : :
365 : 0 : return r;
366 : : }
367 : :
368 : 0 : int config_parse_arp_ip_target_address(
369 : : const char *unit,
370 : : const char *filename,
371 : : unsigned line,
372 : : const char *section,
373 : : unsigned section_line,
374 : : const char *lvalue,
375 : : int ltype,
376 : : const char *rvalue,
377 : : void *data,
378 : : void *userdata) {
379 : :
380 : 0 : Bond *b = userdata;
381 : : int r;
382 : :
383 [ # # ]: 0 : assert(filename);
384 [ # # ]: 0 : assert(lvalue);
385 [ # # ]: 0 : assert(rvalue);
386 [ # # ]: 0 : assert(data);
387 : :
388 [ # # ]: 0 : if (isempty(rvalue)) {
389 : 0 : b->arp_ip_targets = ordered_set_free(b->arp_ip_targets);
390 : 0 : return 0;
391 : : }
392 : :
393 : 0 : for (;;) {
394 [ # # # ]: 0 : _cleanup_free_ char *n = NULL;
395 : : union in_addr_union ip;
396 : :
397 : 0 : r = extract_first_word(&rvalue, &n, NULL, 0);
398 [ # # ]: 0 : if (r < 0) {
399 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r,
400 : : "Failed to parse Bond ARP ip target address, ignoring assignment: %s",
401 : : rvalue);
402 : 0 : return 0;
403 : : }
404 [ # # ]: 0 : if (r == 0)
405 : 0 : return 0;
406 : :
407 : 0 : r = in_addr_from_string(AF_INET, n, &ip);
408 [ # # ]: 0 : if (r < 0) {
409 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r,
410 : : "Bond ARP ip target address is invalid, ignoring assignment: %s", n);
411 : 0 : continue;
412 : : }
413 : :
414 : 0 : r = ordered_set_ensure_allocated(&b->arp_ip_targets, NULL);
415 [ # # ]: 0 : if (r < 0)
416 : 0 : return log_oom();
417 : :
418 [ # # ]: 0 : if (ordered_set_size(b->arp_ip_targets) >= NETDEV_BOND_ARP_TARGETS_MAX) {
419 [ # # ]: 0 : log_syntax(unit, LOG_WARNING, filename, line, 0,
420 : : "Too many ARP ip targets are specified. The maximum number is %d. Ignoring assignment: %s",
421 : : NETDEV_BOND_ARP_TARGETS_MAX, n);
422 : 0 : continue;
423 : : }
424 : :
425 : 0 : r = ordered_set_put(b->arp_ip_targets, UINT32_TO_PTR(ip.in.s_addr));
426 [ # # ]: 0 : if (r == -EEXIST)
427 [ # # ]: 0 : log_syntax(unit, LOG_WARNING, filename, line, r,
428 : : "Bond ARP ip target address is duplicated, ignoring assignment: %s", n);
429 [ # # ]: 0 : if (r < 0)
430 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r,
431 : : "Failed to store bond ARP ip target address '%s', ignoring assignment: %m", n);
432 : : }
433 : : }
434 : :
435 : 0 : int config_parse_ad_actor_sys_prio(
436 : : const char *unit,
437 : : const char *filename,
438 : : unsigned line,
439 : : const char *section,
440 : : unsigned section_line,
441 : : const char *lvalue,
442 : : int ltype,
443 : : const char *rvalue,
444 : : void *data,
445 : : void *userdata) {
446 : 0 : Bond *b = userdata;
447 : : uint16_t v;
448 : : int r;
449 : :
450 [ # # ]: 0 : assert(filename);
451 [ # # ]: 0 : assert(lvalue);
452 [ # # ]: 0 : assert(rvalue);
453 [ # # ]: 0 : assert(data);
454 : :
455 : 0 : r = safe_atou16(rvalue, &v);
456 [ # # ]: 0 : if (r < 0) {
457 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r,
458 : : "Failed to parse actor system priority '%s', ignoring: %m", rvalue);
459 : 0 : return 0;
460 : : }
461 : :
462 [ # # ]: 0 : if (v == 0) {
463 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, 0,
464 : : "Failed to parse actor system priority '%s'. Range is [1,65535], ignoring.",
465 : : rvalue);
466 : 0 : return 0;
467 : : }
468 : :
469 : 0 : b->ad_actor_sys_prio = v;
470 : :
471 : 0 : return 0;
472 : : }
473 : :
474 : 0 : int config_parse_ad_user_port_key(
475 : : const char *unit,
476 : : const char *filename,
477 : : unsigned line,
478 : : const char *section,
479 : : unsigned section_line,
480 : : const char *lvalue,
481 : : int ltype,
482 : : const char *rvalue,
483 : : void *data,
484 : : void *userdata) {
485 : 0 : Bond *b = userdata;
486 : : uint16_t v;
487 : : int r;
488 : :
489 [ # # ]: 0 : assert(filename);
490 [ # # ]: 0 : assert(lvalue);
491 [ # # ]: 0 : assert(rvalue);
492 [ # # ]: 0 : assert(data);
493 : :
494 : 0 : r = safe_atou16(rvalue, &v);
495 [ # # ]: 0 : if (r < 0) {
496 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r,
497 : : "Failed to parse user port key '%s', ignoring: %m", rvalue);
498 : 0 : return 0;
499 : : }
500 : :
501 [ # # ]: 0 : if (v > 1023) {
502 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, 0,
503 : : "Failed to parse user port key '%s'. Range is [0…1023], ignoring.", rvalue);
504 : 0 : return 0;
505 : : }
506 : :
507 : 0 : b->ad_user_port_key = v;
508 : :
509 : 0 : return 0;
510 : : }
511 : :
512 : 0 : int config_parse_ad_actor_system(
513 : : const char *unit,
514 : : const char *filename,
515 : : unsigned line,
516 : : const char *section,
517 : : unsigned section_line,
518 : : const char *lvalue,
519 : : int ltype,
520 : : const char *rvalue,
521 : : void *data,
522 : : void *userdata) {
523 : 0 : Bond *b = userdata;
524 : : struct ether_addr n;
525 : : int r;
526 : :
527 [ # # ]: 0 : assert(filename);
528 [ # # ]: 0 : assert(lvalue);
529 [ # # ]: 0 : assert(rvalue);
530 [ # # ]: 0 : assert(data);
531 : :
532 : 0 : r = ether_addr_from_string(rvalue, &n);
533 [ # # ]: 0 : if (r < 0) {
534 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r,
535 : : "Not a valid MAC address %s. Ignoring assignment: %m",
536 : : rvalue);
537 : 0 : return 0;
538 : : }
539 [ # # # # ]: 0 : if (ether_addr_is_null(&n) || (n.ether_addr_octet[0] & 0x01)) {
540 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, 0,
541 : : "Not a valid MAC address %s, can not be null or multicast. Ignoring assignment.",
542 : : rvalue);
543 : 0 : return 0;
544 : : }
545 : :
546 : 0 : b->ad_actor_system = n;
547 : :
548 : 0 : return 0;
549 : : }
550 : :
551 : 0 : static void bond_done(NetDev *netdev) {
552 : : Bond *b;
553 : :
554 [ # # ]: 0 : assert(netdev);
555 : 0 : b = BOND(netdev);
556 [ # # ]: 0 : assert(b);
557 : :
558 : 0 : ordered_set_free(b->arp_ip_targets);
559 : 0 : }
560 : :
561 : 0 : static void bond_init(NetDev *netdev) {
562 : : Bond *b;
563 : :
564 [ # # ]: 0 : assert(netdev);
565 : :
566 : 0 : b = BOND(netdev);
567 : :
568 [ # # ]: 0 : assert(b);
569 : :
570 : 0 : b->mode = _NETDEV_BOND_MODE_INVALID;
571 : 0 : b->xmit_hash_policy = _NETDEV_BOND_XMIT_HASH_POLICY_INVALID;
572 : 0 : b->lacp_rate = _NETDEV_BOND_LACP_RATE_INVALID;
573 : 0 : b->ad_select = _NETDEV_BOND_AD_SELECT_INVALID;
574 : 0 : b->fail_over_mac = _NETDEV_BOND_FAIL_OVER_MAC_INVALID;
575 : 0 : b->arp_validate = _NETDEV_BOND_ARP_VALIDATE_INVALID;
576 : 0 : b->arp_all_targets = _NETDEV_BOND_ARP_ALL_TARGETS_INVALID;
577 : 0 : b->primary_reselect = _NETDEV_BOND_PRIMARY_RESELECT_INVALID;
578 : :
579 : 0 : b->all_slaves_active = false;
580 : 0 : b->tlb_dynamic_lb = -1;
581 : :
582 : 0 : b->resend_igmp = RESEND_IGMP_DEFAULT;
583 : 0 : b->packets_per_slave = PACKETS_PER_SLAVE_DEFAULT;
584 : 0 : b->num_grat_arp = GRATUITOUS_ARP_DEFAULT;
585 : 0 : b->lp_interval = LEARNING_PACKETS_INTERVAL_MIN_SEC;
586 : 0 : }
587 : :
588 : : const NetDevVTable bond_vtable = {
589 : : .object_size = sizeof(Bond),
590 : : .init = bond_init,
591 : : .done = bond_done,
592 : : .sections = "Match\0NetDev\0Bond\0",
593 : : .fill_message_create = netdev_bond_fill_message_create,
594 : : .create_type = NETDEV_CREATE_MASTER,
595 : : .generate_mac = true,
596 : : };
|