]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | typedef enum BCQueueThreshold { | |
17 | BC_QUEUE_THRESHOLD_UNDEF = INT32_MIN, | |
18 | BC_QUEUE_THRESHOLD_DISABLE = -1, | |
19 | } BCQueueThreshold; | |
20 | ||
21 | DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode); | |
22 | ||
23 | static 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 | ||
82 | int 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 | ||
113 | int 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 | ||
160 | static 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 | ||
166 | static 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 | ||
174 | const 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 | ||
186 | const 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 | }; |