]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/network/netdev/macvlan.c
io.systemd.Unit.List fix context/runtime split (#38172)
[thirdparty/systemd.git] / src / network / netdev / macvlan.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <linux/if_arp.h>
4
5#include "sd-netlink.h"
6
7#include "conf-parser.h"
8#include "macvlan.h"
9#include "macvlan-util.h"
10#include "networkd-link.h"
11#include "networkd-network.h"
12#include "parse-util.h"
13#include "set.h"
14#include "string-util.h"
15
16typedef enum BCQueueThreshold {
17 BC_QUEUE_THRESHOLD_UNDEF = INT32_MIN,
18 BC_QUEUE_THRESHOLD_DISABLE = -1,
19} BCQueueThreshold;
20
21DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode);
22
23static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) {
24 assert(netdev);
25 assert(netdev->ifname);
26 assert(link);
27 assert(link->network);
28
29 MacVlan *m = netdev->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev);
30 int r;
31
32 if (m->mode == NETDEV_MACVLAN_MODE_SOURCE && !set_isempty(m->match_source_mac)) {
33 const struct ether_addr *mac_addr;
34
35 r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MACADDR_MODE, MACVLAN_MACADDR_SET);
36 if (r < 0)
37 return r;
38
39 r = sd_netlink_message_open_container(req, IFLA_MACVLAN_MACADDR_DATA);
40 if (r < 0)
41 return r;
42
43 SET_FOREACH(mac_addr, m->match_source_mac) {
44 r = sd_netlink_message_append_ether_addr(req, IFLA_MACVLAN_MACADDR, mac_addr);
45 if (r < 0)
46 return r;
47 }
48
49 r = sd_netlink_message_close_container(req);
50 if (r < 0)
51 return r;
52 }
53
54 if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) {
55 r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode);
56 if (r < 0)
57 return r;
58 }
59
60 /* set the nopromisc flag if Promiscuous= of the link is explicitly set to false */
61 if (m->mode == NETDEV_MACVLAN_MODE_PASSTHRU && link->network->promiscuous == 0) {
62 r = sd_netlink_message_append_u16(req, IFLA_MACVLAN_FLAGS, MACVLAN_FLAG_NOPROMISC);
63 if (r < 0)
64 return r;
65 }
66
67 if (m->bc_queue_length != UINT32_MAX) {
68 r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_BC_QUEUE_LEN, m->bc_queue_length);
69 if (r < 0)
70 return r;
71 }
72
73 if (m->bc_queue_threshold != BC_QUEUE_THRESHOLD_UNDEF) {
74 r = sd_netlink_message_append_s32(req, IFLA_MACVLAN_BC_CUTOFF, m->bc_queue_threshold);
75 if (r < 0)
76 return r;
77 }
78
79 return 0;
80}
81
82int config_parse_macvlan_broadcast_queue_size(
83 const char *unit,
84 const char *filename,
85 unsigned line,
86 const char *section,
87 unsigned section_line,
88 const char *lvalue,
89 int ltype,
90 const char *rvalue,
91 void *data,
92 void *userdata) {
93
94 assert(filename);
95 assert(section);
96 assert(lvalue);
97 assert(rvalue);
98 assert(data);
99
100 MacVlan *m = ASSERT_PTR(userdata);
101
102 if (isempty(rvalue)) {
103 m->bc_queue_length = UINT32_MAX;
104 return 0;
105 }
106
107 return config_parse_uint32_bounded(
108 unit, filename, line, section, section_line, lvalue, rvalue,
109 0, UINT32_MAX - 1, true,
110 &m->bc_queue_length);
111}
112
113int config_parse_macvlan_broadcast_queue_threshold(
114 const char *unit,
115 const char *filename,
116 unsigned line,
117 const char *section,
118 unsigned section_line,
119 const char *lvalue,
120 int ltype,
121 const char *rvalue,
122 void *data,
123 void *userdata) {
124
125 assert(filename);
126 assert(lvalue);
127 assert(rvalue);
128
129 int32_t v, *threshold = ASSERT_PTR(data);
130 int r;
131
132 if (isempty(rvalue)) {
133 *threshold = BC_QUEUE_THRESHOLD_UNDEF;
134 return 0;
135 }
136
137 if (streq(rvalue, "no")) {
138 *threshold = BC_QUEUE_THRESHOLD_DISABLE;
139 return 0;
140 }
141
142 r = safe_atoi32(rvalue, &v);
143 if (r < 0) {
144 log_syntax(unit, LOG_WARNING, filename, line, r,
145 "Failed to parse %s=, ignoring assignment: %s",
146 lvalue, rvalue);
147 return 0;
148 }
149 if (v < 0) {
150 log_syntax(unit, LOG_WARNING, filename, line, 0,
151 "Invalid %s= value specified, ignoring assignment: %s",
152 lvalue, rvalue);
153 return 0;
154 }
155
156 *threshold = v;
157 return 0;
158}
159
160static void macvlan_done(NetDev *netdev) {
161 MacVlan *m = ASSERT_PTR(netdev)->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev);
162
163 set_free(m->match_source_mac);
164}
165
166static void macvlan_init(NetDev *netdev) {
167 MacVlan *m = ASSERT_PTR(netdev)->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev);
168
169 m->mode = _NETDEV_MACVLAN_MODE_INVALID;
170 m->bc_queue_length = UINT32_MAX;
171 m->bc_queue_threshold = BC_QUEUE_THRESHOLD_UNDEF;
172}
173
174const NetDevVTable macvtap_vtable = {
175 .object_size = sizeof(MacVlan),
176 .init = macvlan_init,
177 .done = macvlan_done,
178 .sections = NETDEV_COMMON_SECTIONS "MACVTAP\0",
179 .fill_message_create = netdev_macvlan_fill_message_create,
180 .create_type = NETDEV_CREATE_STACKED,
181 .iftype = ARPHRD_ETHER,
182 .generate_mac = true,
183 .keep_existing = true,
184};
185
186const NetDevVTable macvlan_vtable = {
187 .object_size = sizeof(MacVlan),
188 .init = macvlan_init,
189 .done = macvlan_done,
190 .sections = NETDEV_COMMON_SECTIONS "MACVLAN\0",
191 .fill_message_create = netdev_macvlan_fill_message_create,
192 .create_type = NETDEV_CREATE_STACKED,
193 .iftype = ARPHRD_ETHER,
194 .generate_mac = true,
195 .keep_existing = true,
196};