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