1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/if_arp.h>
5 #include "sd-netlink.h"
7 #include "conf-parser.h"
9 #include "macvlan-util.h"
10 #include "networkd-link.h"
11 #include "networkd-network.h"
12 #include "parse-util.h"
14 #include "string-util.h"
16 typedef enum BCQueueThreshold
{
17 BC_QUEUE_THRESHOLD_UNDEF
= INT32_MIN
,
18 BC_QUEUE_THRESHOLD_DISABLE
= -1,
21 DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode
, macvlan_mode
, MacVlanMode
);
23 static int netdev_macvlan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*req
) {
25 assert(netdev
->ifname
);
27 assert(link
->network
);
29 MacVlan
*m
= netdev
->kind
== NETDEV_KIND_MACVLAN
? MACVLAN(netdev
) : MACVTAP(netdev
);
32 if (m
->mode
== NETDEV_MACVLAN_MODE_SOURCE
&& !set_isempty(m
->match_source_mac
)) {
33 const struct ether_addr
*mac_addr
;
35 r
= sd_netlink_message_append_u32(req
, IFLA_MACVLAN_MACADDR_MODE
, MACVLAN_MACADDR_SET
);
39 r
= sd_netlink_message_open_container(req
, IFLA_MACVLAN_MACADDR_DATA
);
43 SET_FOREACH(mac_addr
, m
->match_source_mac
) {
44 r
= sd_netlink_message_append_ether_addr(req
, IFLA_MACVLAN_MACADDR
, mac_addr
);
49 r
= sd_netlink_message_close_container(req
);
54 if (m
->mode
!= _NETDEV_MACVLAN_MODE_INVALID
) {
55 r
= sd_netlink_message_append_u32(req
, IFLA_MACVLAN_MODE
, m
->mode
);
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
);
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
);
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
);
82 int config_parse_macvlan_broadcast_queue_size(
87 unsigned section_line
,
100 MacVlan
*m
= ASSERT_PTR(userdata
);
102 if (isempty(rvalue
)) {
103 m
->bc_queue_length
= UINT32_MAX
;
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
);
113 int config_parse_macvlan_broadcast_queue_threshold(
115 const char *filename
,
118 unsigned section_line
,
129 int32_t v
, *threshold
= ASSERT_PTR(data
);
132 if (isempty(rvalue
)) {
133 *threshold
= BC_QUEUE_THRESHOLD_UNDEF
;
137 if (streq(rvalue
, "no")) {
138 *threshold
= BC_QUEUE_THRESHOLD_DISABLE
;
142 r
= safe_atoi32(rvalue
, &v
);
144 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
145 "Failed to parse %s=, ignoring assignment: %s",
150 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
151 "Invalid %s= value specified, ignoring assignment: %s",
160 static void macvlan_done(NetDev
*netdev
) {
161 MacVlan
*m
= ASSERT_PTR(netdev
)->kind
== NETDEV_KIND_MACVLAN
? MACVLAN(netdev
) : MACVTAP(netdev
);
163 set_free(m
->match_source_mac
);
166 static void macvlan_init(NetDev
*netdev
) {
167 MacVlan
*m
= ASSERT_PTR(netdev
)->kind
== NETDEV_KIND_MACVLAN
? MACVLAN(netdev
) : MACVTAP(netdev
);
169 m
->mode
= _NETDEV_MACVLAN_MODE_INVALID
;
170 m
->bc_queue_length
= UINT32_MAX
;
171 m
->bc_queue_threshold
= BC_QUEUE_THRESHOLD_UNDEF
;
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,
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,