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