]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
0372cb2b | 2 | |
1cf40697 | 3 | #include <linux/if_arp.h> |
baa3fadf DDM |
4 | |
5 | #include "sd-netlink.h" | |
0372cb2b | 6 | |
0372cb2b | 7 | #include "conf-parser.h" |
737f1405 | 8 | #include "macvlan.h" |
d5167480 | 9 | #include "macvlan-util.h" |
0ee78fc9 | 10 | #include "networkd-link.h" |
17a6a4ae | 11 | #include "networkd-network.h" |
dca0a4e1 | 12 | #include "parse-util.h" |
baa3fadf DDM |
13 | #include "set.h" |
14 | #include "string-util.h" | |
0372cb2b | 15 | |
9adafedd SS |
16 | typedef enum BCQueueThreshold { |
17 | BC_QUEUE_THRESHOLD_UNDEF = INT32_MIN, | |
18 | BC_QUEUE_THRESHOLD_DISABLE = -1, | |
19 | } BCQueueThreshold; | |
20 | ||
42efe5be | 21 | DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode); |
0372cb2b | 22 | |
1c4baffc | 23 | static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { |
0372cb2b | 24 | assert(netdev); |
0372cb2b | 25 | assert(netdev->ifname); |
117843fe | 26 | assert(link); |
17a6a4ae | 27 | assert(link->network); |
0372cb2b | 28 | |
117843fe ZJS |
29 | MacVlan *m = netdev->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev); |
30 | int r; | |
f33ff02b | 31 | |
0d0de133 | 32 | if (m->mode == NETDEV_MACVLAN_MODE_SOURCE && !set_isempty(m->match_source_mac)) { |
0d0de133 AŠ |
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) | |
5b80ecea | 37 | return r; |
0d0de133 AŠ |
38 | |
39 | r = sd_netlink_message_open_container(req, IFLA_MACVLAN_MACADDR_DATA); | |
40 | if (r < 0) | |
5b80ecea | 41 | return r; |
0d0de133 | 42 | |
90e74a66 | 43 | SET_FOREACH(mac_addr, m->match_source_mac) { |
0d0de133 AŠ |
44 | r = sd_netlink_message_append_ether_addr(req, IFLA_MACVLAN_MACADDR, mac_addr); |
45 | if (r < 0) | |
5b80ecea | 46 | return r; |
0d0de133 AŠ |
47 | } |
48 | ||
49 | r = sd_netlink_message_close_container(req); | |
50 | if (r < 0) | |
5b80ecea | 51 | return r; |
0d0de133 AŠ |
52 | } |
53 | ||
aa9f1140 | 54 | if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) { |
1c4baffc | 55 | r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode); |
c8a09ef4 | 56 | if (r < 0) |
5b80ecea | 57 | return r; |
0372cb2b TG |
58 | } |
59 | ||
17a6a4ae TY |
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) | |
5b80ecea | 64 | return r; |
17a6a4ae TY |
65 | } |
66 | ||
dca0a4e1 SS |
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) | |
5b80ecea | 70 | return r; |
dca0a4e1 SS |
71 | } |
72 | ||
9adafedd SS |
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 | ||
dca0a4e1 SS |
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 | ||
dca0a4e1 SS |
94 | assert(filename); |
95 | assert(section); | |
96 | assert(lvalue); | |
97 | assert(rvalue); | |
98 | assert(data); | |
dca0a4e1 | 99 | |
851cdffd ZJS |
100 | MacVlan *m = ASSERT_PTR(userdata); |
101 | ||
dca0a4e1 SS |
102 | if (isempty(rvalue)) { |
103 | m->bc_queue_length = UINT32_MAX; | |
104 | return 0; | |
105 | } | |
106 | ||
851cdffd ZJS |
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); | |
aa9f1140 | 111 | } |
0372cb2b | 112 | |
9adafedd SS |
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 | ||
117843fe ZJS |
160 | static void macvlan_done(NetDev *netdev) { |
161 | MacVlan *m = ASSERT_PTR(netdev)->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev); | |
0d0de133 | 162 | |
c6df73ca | 163 | set_free(m->match_source_mac); |
0d0de133 AŠ |
164 | } |
165 | ||
117843fe ZJS |
166 | static void macvlan_init(NetDev *netdev) { |
167 | MacVlan *m = ASSERT_PTR(netdev)->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev); | |
aa9f1140 TG |
168 | |
169 | m->mode = _NETDEV_MACVLAN_MODE_INVALID; | |
dca0a4e1 | 170 | m->bc_queue_length = UINT32_MAX; |
9adafedd | 171 | m->bc_queue_threshold = BC_QUEUE_THRESHOLD_UNDEF; |
0372cb2b | 172 | } |
3be1d7e0 | 173 | |
f33ff02b SS |
174 | const NetDevVTable macvtap_vtable = { |
175 | .object_size = sizeof(MacVlan), | |
176 | .init = macvlan_init, | |
0d0de133 | 177 | .done = macvlan_done, |
130b812f | 178 | .sections = NETDEV_COMMON_SECTIONS "MACVTAP\0", |
f33ff02b SS |
179 | .fill_message_create = netdev_macvlan_fill_message_create, |
180 | .create_type = NETDEV_CREATE_STACKED, | |
9f0cf80d | 181 | .iftype = ARPHRD_ETHER, |
daf0f8ca | 182 | .generate_mac = true, |
422b7c85 | 183 | .keep_existing = true, |
f33ff02b SS |
184 | }; |
185 | ||
3be1d7e0 | 186 | const NetDevVTable macvlan_vtable = { |
aa9f1140 TG |
187 | .object_size = sizeof(MacVlan), |
188 | .init = macvlan_init, | |
0d0de133 | 189 | .done = macvlan_done, |
130b812f | 190 | .sections = NETDEV_COMMON_SECTIONS "MACVLAN\0", |
aa9f1140 TG |
191 | .fill_message_create = netdev_macvlan_fill_message_create, |
192 | .create_type = NETDEV_CREATE_STACKED, | |
9f0cf80d | 193 | .iftype = ARPHRD_ETHER, |
daf0f8ca | 194 | .generate_mac = true, |
422b7c85 | 195 | .keep_existing = true, |
3be1d7e0 | 196 | }; |