Merge ~ubuntu-core-dev/ubuntu/+source/systemd:lp1664844-hirsute into ~ubuntu-core-dev/ubuntu/+source/systemd:ubuntu-hirsute
- Git
- lp:~ubuntu-core-dev/ubuntu/+source/systemd
- lp1664844-hirsute
- Merge into ubuntu-hirsute
Proposed by
Łukasz Zemczak
Status: | Merged |
---|---|
Merged at revision: | 85b4a5ba7086f93859e13d7b025212c383043b67 |
Proposed branch: | ~ubuntu-core-dev/ubuntu/+source/systemd:lp1664844-hirsute |
Merge into: | ~ubuntu-core-dev/ubuntu/+source/systemd:ubuntu-hirsute |
Diff against target: |
622 lines (+588/-0) 5 files modified
debian/changelog (+10/-0) debian/patches/lp1664844/0001-network-add-ActivationPolicy-configuration-parameter.patch (+344/-0) debian/patches/lp1664844/0002-test-add-ActivationPolicy-unit-tests.patch (+121/-0) debian/patches/lp1664844/0003-save-link-activation-policy-to-state-file-and-displa.patch (+110/-0) debian/patches/series (+3/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dan Streetman | Approve | ||
Balint Reczey | Approve | ||
Dimitri John Ledkov | Pending | ||
Review via email: mp+402646@code.launchpad.net |
Commit message
add support for configuring the activation policy for an interface
Description of the change
add support for configuring the activation policy for an interface
To post a comment you must log in.
Revision history for this message
Balint Reczey (rbalint) wrote : | # |
Also please don't use this central repository for bugfix branches, it is big enough with the release branches already.
Revision history for this message
Łukasz Zemczak (sil2100) wrote : | # |
Did a quick sanity test with a dummy interface on multipass using test packages from a bileto PPA (https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index 5efa976..161740e 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,13 @@ |
6 | +systemd (247.3-3ubuntu4) UNRELEASED; urgency=medium |
7 | + |
8 | + * d/p/lp1664844/0001-network-add-ActivationPolicy-configuration-parameter.patch, |
9 | + d/p/lp1664844/0002-test-add-ActivationPolicy-unit-tests.patch, |
10 | + d/p/lp1664844/0003-save-link-activation-policy-to-state-file-and-displa.patch: |
11 | + - add support for configuring the activation policy for an interface |
12 | + (LP: #1664844) |
13 | + |
14 | + -- Łukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com> Wed, 12 May 2021 11:56:50 +0200 |
15 | + |
16 | systemd (247.3-3ubuntu3) hirsute; urgency=medium |
17 | |
18 | * Make systemd-rfkill work with latest Linux kernels (LP: #1921696) |
19 | diff --git a/debian/patches/lp1664844/0001-network-add-ActivationPolicy-configuration-parameter.patch b/debian/patches/lp1664844/0001-network-add-ActivationPolicy-configuration-parameter.patch |
20 | new file mode 100644 |
21 | index 0000000..08a8fb5 |
22 | --- /dev/null |
23 | +++ b/debian/patches/lp1664844/0001-network-add-ActivationPolicy-configuration-parameter.patch |
24 | @@ -0,0 +1,344 @@ |
25 | +From 61135582e0b2e847e49c96af05e4d101323ce00c Mon Sep 17 00:00:00 2001 |
26 | +From: Dan Streetman <ddstreet@canonical.com> |
27 | +Date: Thu, 18 Jun 2020 16:09:40 -0400 |
28 | +Subject: [PATCH 1/3] network: add ActivationPolicy= configuration parameter |
29 | +Origin: upstream, https://github.com/systemd/systemd/pull/16228 |
30 | +Bug-Ubuntu: https://bugs.launchpad.net/netplan/+bug/1664844 |
31 | + |
32 | +This parameter allows configuring the activation policy for an interface, |
33 | +meaning how it manages the interface's administrative state (IFF_UP flag). |
34 | +The policy can be configured to bring the interface either up or down when |
35 | +the interface is (re)configured, to always force the interface either up or |
36 | +down, or to never change the interface administrative state. |
37 | + |
38 | +If the interface is bound with BindCarrier=, its administrative state is |
39 | +controlled by the interface(s) it's bound to, and this parameter is forced |
40 | +to 'bound'. |
41 | + |
42 | +This changes the default behavior of how systemd-networkd sets the IFF_UP |
43 | +flag; previously, it was set up (if not already up) every time the |
44 | +link_joined() function was called. Now, with the default ActivationPolicy= |
45 | +setting of 'up', it will only set the IFF_UP flag once, the first time |
46 | +link_joined() is called, during an interface's configuration; and on |
47 | +the first link_joined() call each time the interface is reconfigured. |
48 | + |
49 | +Fixes: #3031 |
50 | +Fixes: #17437 |
51 | +--- |
52 | + man/systemd.network.xml | 39 ++++++++++++- |
53 | + src/network/networkd-link.c | 58 ++++++++++++++++++- |
54 | + src/network/networkd-link.h | 1 + |
55 | + src/network/networkd-network-gperf.gperf | 1 + |
56 | + src/network/networkd-network.c | 40 ++++++++++++- |
57 | + src/network/networkd-network.h | 16 +++++ |
58 | + .../fuzz-network-parser/directives.network | 1 + |
59 | + 7 files changed, 148 insertions(+), 8 deletions(-) |
60 | + |
61 | +--- a/man/systemd.network.xml |
62 | ++++ b/man/systemd.network.xml |
63 | +@@ -228,6 +228,36 @@ |
64 | + if <literal>RequiredForOnline=no</literal>.</para> |
65 | + </listitem> |
66 | + </varlistentry> |
67 | ++ <varlistentry> |
68 | ++ <term><varname>ActivationPolicy=</varname></term> |
69 | ++ <listitem> |
70 | ++ <para>Specifies the policy for <command>systemd-networkd</command> managing the link |
71 | ++ administrative state. Specifically, this controls how <command>systemd-networkd</command> |
72 | ++ changes the network device's <literal>IFF_UP</literal> flag, which is sometimes |
73 | ++ controlled by system administrators by running e.g., <command>ip set dev eth0 up</command> |
74 | ++ or <command>ip set dev eth0 down</command>, and can also be changed with |
75 | ++ <command>networkctl up eth0</command> or <command>networkctl down eth0</command>.</para> |
76 | ++ |
77 | ++ <para>Takes one of <literal>up</literal>, <literal>always-up</literal>, |
78 | ++ <literal>manual</literal>, <literal>always-down</literal>, <literal>down</literal>, |
79 | ++ or <literal>bound</literal>. When <literal>manual</literal>, <command>systemd-networkd</command> |
80 | ++ will not change the link's admin state automatically; the system administrator must bring the |
81 | ++ interface up or down manually, as desired. When <literal>up</literal> (the default) or |
82 | ++ <literal>always-up</literal>, or <literal>down</literal> or <literal>always-down</literal>, |
83 | ++ <command>systemd-networkd</command> will set the link up or down, respectively, |
84 | ++ when the interface is (re)configured. When <literal>always-up</literal> or |
85 | ++ <literal>always-down</literal>, <command>systemd-networkd</command> will set the link up |
86 | ++ or down, respectively, any time <command>systemd-networkd</command> detects a change in |
87 | ++ the administrative state. When <varname>BindCarrier=</varname> is also set, this is |
88 | ++ automatically set to <literal>bound</literal> and any other value is ignored.</para> |
89 | ++ |
90 | ++ <para>The administrative state is not the same as the carrier state, so using |
91 | ++ <literal>always-up</literal> does not mean the link will never lose carrier. The link |
92 | ++ carrier depends on both the administrative state as well as the network device's physical |
93 | ++ connection. However, to avoid reconfiguration failures, when using <literal>always-up</literal>, |
94 | ++ <varname>IgnoreCarrierLoss=</varname> is forced to true.</para> |
95 | ++ </listitem> |
96 | ++ </varlistentry> |
97 | + </variablelist> |
98 | + </refsect1> |
99 | + |
100 | +@@ -573,8 +603,9 @@ |
101 | + <listitem> |
102 | + <para>A link name or a list of link names. When set, controls the behavior of the current |
103 | + link. When all links in the list are in an operational down state, the current link is brought |
104 | +- down. When at least one link has carrier, the current interface is brought up. |
105 | +- </para> |
106 | ++ down. When at least one link has carrier, the current interface is brought up.</para> |
107 | ++ |
108 | ++ <para>This forces <varname>ActivationPolicy=</varname> to be set to <literal>bound</literal>.</para> |
109 | + </listitem> |
110 | + </varlistentry> |
111 | + <varlistentry> |
112 | +@@ -947,6 +978,10 @@ |
113 | + of the interface even if its carrier is lost. When unset, the value specified with |
114 | + <option>ConfigureWithoutCarrier=</option> is used. |
115 | + </para> |
116 | ++ |
117 | ++ <para>When <varname>ActivationPolicy=</varname> is set to <literal>always-up</literal>, this |
118 | ++ is forced to <literal>true</literal>. |
119 | ++ </para> |
120 | + </listitem> |
121 | + </varlistentry> |
122 | + <varlistentry> |
123 | +--- a/src/network/networkd-link.c |
124 | ++++ b/src/network/networkd-link.c |
125 | +@@ -1812,17 +1812,38 @@ |
126 | + assert(link); |
127 | + assert(link->network); |
128 | + |
129 | +- if (!hashmap_isempty(link->bound_to_links)) { |
130 | ++ switch (link->network->activation_policy) { |
131 | ++ case ACTIVATION_POLICY_BOUND: |
132 | + r = link_handle_bound_to_list(link); |
133 | + if (r < 0) |
134 | + return r; |
135 | +- } else if (!(link->flags & IFF_UP)) { |
136 | ++ break; |
137 | ++ case ACTIVATION_POLICY_UP: |
138 | ++ if (link->activated) |
139 | ++ break; |
140 | ++ _fallthrough_; |
141 | ++ case ACTIVATION_POLICY_ALWAYS_UP: |
142 | + r = link_up(link); |
143 | + if (r < 0) { |
144 | + link_enter_failed(link); |
145 | + return r; |
146 | + } |
147 | ++ break; |
148 | ++ case ACTIVATION_POLICY_DOWN: |
149 | ++ if (link->activated) |
150 | ++ break; |
151 | ++ _fallthrough_; |
152 | ++ case ACTIVATION_POLICY_ALWAYS_DOWN: |
153 | ++ r = link_down(link, NULL); |
154 | ++ if (r < 0) { |
155 | ++ link_enter_failed(link); |
156 | ++ return r; |
157 | ++ } |
158 | ++ break; |
159 | ++ default: |
160 | ++ break; |
161 | + } |
162 | ++ link->activated = true; |
163 | + |
164 | + if (link->network->bridge) { |
165 | + r = link_set_bridge(link); |
166 | +@@ -2216,6 +2237,7 @@ |
167 | + return r; |
168 | + |
169 | + link_set_state(link, LINK_STATE_INITIALIZED); |
170 | ++ link->activated = false; |
171 | + link_dirty(link); |
172 | + |
173 | + /* link_configure_duid() returns 0 if it requests product UUID. In that case, |
174 | +@@ -2687,6 +2709,16 @@ |
175 | + static int link_admin_state_up(Link *link) { |
176 | + int r; |
177 | + |
178 | ++ assert(link); |
179 | ++ |
180 | ++ if (!link->network) |
181 | ++ return 0; |
182 | ++ |
183 | ++ if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN) { |
184 | ++ log_link_info(link, "ActivationPolicy is \"always-off\", forcing link down"); |
185 | ++ return link_down(link, NULL); |
186 | ++ } |
187 | ++ |
188 | + /* We set the ipv6 mtu after the device mtu, but the kernel resets |
189 | + * ipv6 mtu on NETDEV_UP, so we need to reset it. The check for |
190 | + * ipv6_mtu_set prevents this from trying to set it too early before |
191 | +@@ -2701,6 +2733,21 @@ |
192 | + return 0; |
193 | + } |
194 | + |
195 | ++static int link_admin_state_down(Link *link) { |
196 | ++ |
197 | ++ assert(link); |
198 | ++ |
199 | ++ if (!link->network) |
200 | ++ return 0; |
201 | ++ |
202 | ++ if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) { |
203 | ++ log_link_info(link, "ActivationPolicy is \"always-on\", forcing link up"); |
204 | ++ return link_up(link); |
205 | ++ } |
206 | ++ |
207 | ++ return 0; |
208 | ++} |
209 | ++ |
210 | + int link_update(Link *link, sd_netlink_message *m) { |
211 | + _cleanup_strv_free_ char **s = NULL; |
212 | + hw_addr_data hw_addr; |
213 | +@@ -2813,9 +2860,14 @@ |
214 | + r = link_admin_state_up(link); |
215 | + if (r < 0) |
216 | + return r; |
217 | +- } else if (link_was_admin_up && !(link->flags & IFF_UP)) |
218 | ++ } else if (link_was_admin_up && !(link->flags & IFF_UP)) { |
219 | + log_link_info(link, "Link DOWN"); |
220 | + |
221 | ++ r = link_admin_state_down(link); |
222 | ++ if (r < 0) |
223 | ++ return r; |
224 | ++ } |
225 | ++ |
226 | + r = link_update_lldp(link); |
227 | + if (r < 0) |
228 | + return r; |
229 | +--- a/src/network/networkd-link.h |
230 | ++++ b/src/network/networkd-link.h |
231 | +@@ -130,6 +130,7 @@ |
232 | + bool setting_genmode:1; |
233 | + bool ipv6_mtu_set:1; |
234 | + bool bridge_mdb_configured:1; |
235 | ++ bool activated:1; |
236 | + |
237 | + sd_dhcp_server *dhcp_server; |
238 | + |
239 | +--- a/src/network/networkd-network-gperf.gperf |
240 | ++++ b/src/network/networkd-network-gperf.gperf |
241 | +@@ -63,6 +63,7 @@ |
242 | + Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast) |
243 | + Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast) |
244 | + Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged) |
245 | ++Link.ActivationPolicy, config_parse_activation_policy, 0, offsetof(Network, activation_policy) |
246 | + Link.RequiredForOnline, config_parse_required_for_online, 0, 0 |
247 | + SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0 |
248 | + SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, 0 |
249 | +--- a/src/network/networkd-network.c |
250 | ++++ b/src/network/networkd-network.c |
251 | +@@ -238,9 +238,6 @@ |
252 | + if (network->dhcp_use_gateway < 0) |
253 | + network->dhcp_use_gateway = network->dhcp_use_routes; |
254 | + |
255 | +- if (network->ignore_carrier_loss < 0) |
256 | +- network->ignore_carrier_loss = network->configure_without_carrier; |
257 | +- |
258 | + if (network->dhcp_critical >= 0) { |
259 | + if (network->keep_configuration >= 0) |
260 | + log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. " |
261 | +@@ -252,6 +249,30 @@ |
262 | + network->keep_configuration = KEEP_CONFIGURATION_NO; |
263 | + } |
264 | + |
265 | ++ if (!strv_isempty(network->bind_carrier)) { |
266 | ++ if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND)) |
267 | ++ log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. " |
268 | ++ "Setting ActivationPolicy=bound.", network->filename); |
269 | ++ network->activation_policy = ACTIVATION_POLICY_BOUND; |
270 | ++ } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) { |
271 | ++ log_warning("%s: ActivationPolicy=bound requires BindCarrier=. " |
272 | ++ "Ignoring ActivationPolicy=bound.", network->filename); |
273 | ++ network->activation_policy = ACTIVATION_POLICY_UP; |
274 | ++ } |
275 | ++ |
276 | ++ if (network->activation_policy == _ACTIVATION_POLICY_INVALID) |
277 | ++ network->activation_policy = ACTIVATION_POLICY_UP; |
278 | ++ |
279 | ++ if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) { |
280 | ++ if (network->ignore_carrier_loss == false) |
281 | ++ log_warning("%s: IgnoreCarrierLoss=false conflicts with ActivationPolicy=always-up. " |
282 | ++ "Setting IgnoreCarrierLoss=true.", network->filename); |
283 | ++ network->ignore_carrier_loss = true; |
284 | ++ } |
285 | ++ |
286 | ++ if (network->ignore_carrier_loss < 0) |
287 | ++ network->ignore_carrier_loss = network->configure_without_carrier; |
288 | ++ |
289 | + if (network->keep_configuration < 0) |
290 | + network->keep_configuration = KEEP_CONFIGURATION_NO; |
291 | + |
292 | +@@ -329,6 +350,7 @@ |
293 | + |
294 | + .required_for_online = true, |
295 | + .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT, |
296 | ++ .activation_policy = _ACTIVATION_POLICY_INVALID, |
297 | + .arp = -1, |
298 | + .multicast = -1, |
299 | + .allmulticast = -1, |
300 | +@@ -1238,3 +1260,15 @@ |
301 | + |
302 | + DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode); |
303 | + DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode, ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode, "Failed to parse IPv6 link local address generation mode"); |
304 | ++ |
305 | ++static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = { |
306 | ++ [ACTIVATION_POLICY_UP] = "up", |
307 | ++ [ACTIVATION_POLICY_ALWAYS_UP] = "always-up", |
308 | ++ [ACTIVATION_POLICY_MANUAL] = "manual", |
309 | ++ [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down", |
310 | ++ [ACTIVATION_POLICY_DOWN] = "down", |
311 | ++ [ACTIVATION_POLICY_BOUND] = "bound", |
312 | ++}; |
313 | ++ |
314 | ++DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy); |
315 | ++DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy"); |
316 | +--- a/src/network/networkd-network.h |
317 | ++++ b/src/network/networkd-network.h |
318 | +@@ -46,6 +46,17 @@ |
319 | + _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID = -1 |
320 | + } IPv6LinkLocalAddressGenMode; |
321 | + |
322 | ++typedef enum ActivationPolicy { |
323 | ++ ACTIVATION_POLICY_UP, |
324 | ++ ACTIVATION_POLICY_ALWAYS_UP, |
325 | ++ ACTIVATION_POLICY_MANUAL, |
326 | ++ ACTIVATION_POLICY_ALWAYS_DOWN, |
327 | ++ ACTIVATION_POLICY_DOWN, |
328 | ++ ACTIVATION_POLICY_BOUND, |
329 | ++ _ACTIVATION_POLICY_MAX, |
330 | ++ _ACTIVATION_POLICY_INVALID = -1 |
331 | ++} ActivationPolicy; |
332 | ++ |
333 | + typedef struct Manager Manager; |
334 | + |
335 | + typedef struct NetworkDHCPServerEmitAddress { |
336 | +@@ -98,6 +109,7 @@ |
337 | + bool unmanaged; |
338 | + bool required_for_online; /* Is this network required to be considered online? */ |
339 | + LinkOperationalStateRange required_operstate_for_online; |
340 | ++ ActivationPolicy activation_policy; |
341 | + |
342 | + /* misc settings */ |
343 | + bool configure_without_carrier; |
344 | +@@ -330,6 +342,7 @@ |
345 | + CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online); |
346 | + CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration); |
347 | + CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode); |
348 | ++CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy); |
349 | + |
350 | + const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); |
351 | + |
352 | +@@ -338,3 +351,6 @@ |
353 | + |
354 | + const char* ipv6_link_local_address_gen_mode_to_string(IPv6LinkLocalAddressGenMode s) _const_; |
355 | + IPv6LinkLocalAddressGenMode ipv6_link_local_address_gen_mode_from_string(const char *s) _pure_; |
356 | ++ |
357 | ++const char* activation_policy_to_string(ActivationPolicy i) _const_; |
358 | ++ActivationPolicy activation_policy_from_string(const char *s) _pure_; |
359 | +--- a/test/fuzz/fuzz-network-parser/directives.network |
360 | ++++ b/test/fuzz/fuzz-network-parser/directives.network |
361 | +@@ -30,6 +30,7 @@ |
362 | + MACAddress= |
363 | + PermanentMACAddress= |
364 | + [Link] |
365 | ++ActivationPolicy= |
366 | + RequiredForOnline= |
367 | + ARP= |
368 | + AllMulticast= |
369 | diff --git a/debian/patches/lp1664844/0002-test-add-ActivationPolicy-unit-tests.patch b/debian/patches/lp1664844/0002-test-add-ActivationPolicy-unit-tests.patch |
370 | new file mode 100644 |
371 | index 0000000..80a31ef |
372 | --- /dev/null |
373 | +++ b/debian/patches/lp1664844/0002-test-add-ActivationPolicy-unit-tests.patch |
374 | @@ -0,0 +1,121 @@ |
375 | +From 2236d75df955118ad5d84c5ab787484c0921dfda Mon Sep 17 00:00:00 2001 |
376 | +From: Dan Streetman <ddstreet@canonical.com> |
377 | +Date: Thu, 18 Jun 2020 18:31:18 -0400 |
378 | +Subject: [PATCH 2/3] test: add ActivationPolicy= unit tests |
379 | +Origin: upstream, https://github.com/systemd/systemd/pull/16228 |
380 | +Bug-Ubuntu: https://bugs.launchpad.net/netplan/+bug/1664844 |
381 | + |
382 | +--- |
383 | + .../conf/25-activation-policy.network | 6 +++ |
384 | + .../always-down.conf | 2 + |
385 | + .../always-up.conf | 2 + |
386 | + .../25-activation-policy.network.d/down.conf | 2 + |
387 | + .../manual.conf | 2 + |
388 | + .../25-activation-policy.network.d/up.conf | 2 + |
389 | + test/test-network/systemd-networkd-tests.py | 48 +++++++++++++++++++ |
390 | + 7 files changed, 64 insertions(+) |
391 | + create mode 100644 test/test-network/conf/25-activation-policy.network |
392 | + create mode 100644 test/test-network/conf/25-activation-policy.network.d/always-down.conf |
393 | + create mode 100644 test/test-network/conf/25-activation-policy.network.d/always-up.conf |
394 | + create mode 100644 test/test-network/conf/25-activation-policy.network.d/down.conf |
395 | + create mode 100644 test/test-network/conf/25-activation-policy.network.d/manual.conf |
396 | + create mode 100644 test/test-network/conf/25-activation-policy.network.d/up.conf |
397 | + |
398 | +--- /dev/null |
399 | ++++ b/test/test-network/conf/25-activation-policy.network |
400 | +@@ -0,0 +1,6 @@ |
401 | ++[Match] |
402 | ++Name=test1 |
403 | ++ |
404 | ++[Network] |
405 | ++Address=192.168.10.30/24 |
406 | ++Gateway=192.168.10.1 |
407 | +--- /dev/null |
408 | ++++ b/test/test-network/conf/25-activation-policy.network.d/always-down.conf |
409 | +@@ -0,0 +1,2 @@ |
410 | ++[Link] |
411 | ++ActivationPolicy=always-down |
412 | +--- /dev/null |
413 | ++++ b/test/test-network/conf/25-activation-policy.network.d/always-up.conf |
414 | +@@ -0,0 +1,2 @@ |
415 | ++[Link] |
416 | ++ActivationPolicy=always-up |
417 | +--- /dev/null |
418 | ++++ b/test/test-network/conf/25-activation-policy.network.d/down.conf |
419 | +@@ -0,0 +1,2 @@ |
420 | ++[Link] |
421 | ++ActivationPolicy=down |
422 | +--- /dev/null |
423 | ++++ b/test/test-network/conf/25-activation-policy.network.d/manual.conf |
424 | +@@ -0,0 +1,2 @@ |
425 | ++[Link] |
426 | ++ActivationPolicy=manual |
427 | +--- /dev/null |
428 | ++++ b/test/test-network/conf/25-activation-policy.network.d/up.conf |
429 | +@@ -0,0 +1,2 @@ |
430 | ++[Link] |
431 | ++ActivationPolicy=up |
432 | +--- a/test/test-network/systemd-networkd-tests.py |
433 | ++++ b/test/test-network/systemd-networkd-tests.py |
434 | +@@ -1745,6 +1745,7 @@ |
435 | + '25-address-peer-ipv4.network', |
436 | + '25-address-preferred-lifetime-zero.network', |
437 | + '25-address-static.network', |
438 | ++ '25-activation-policy.network', |
439 | + '25-bind-carrier.network', |
440 | + '25-bond-active-backup-slave.netdev', |
441 | + '25-fibrule-invert.network', |
442 | +@@ -2609,6 +2610,53 @@ |
443 | + self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') |
444 | + self.wait_operstate('test1', 'routable') |
445 | + |
446 | ++ def _test_activation_policy(self, test): |
447 | ++ self.setUp() |
448 | ++ conffile = '25-activation-policy.network' |
449 | ++ if test: |
450 | ++ conffile = f'{conffile}.d/{test}.conf' |
451 | ++ copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False) |
452 | ++ start_networkd() |
453 | ++ |
454 | ++ always = test.startswith('always') |
455 | ++ if test == 'manual': |
456 | ++ initial_up = 'UP' in check_output('ip link show test1') |
457 | ++ else: |
458 | ++ initial_up = not test.endswith('down') # note: default is up |
459 | ++ expect_up = initial_up |
460 | ++ next_up = not expect_up |
461 | ++ |
462 | ++ # if initial expected state is down, must wait for setup_state to reach configuring |
463 | ++ # so systemd-networkd considers it 'activated' |
464 | ++ setup_state = None if initial_up else 'configuring' |
465 | ++ |
466 | ++ for iteration in range(4): |
467 | ++ with self.subTest(iteration=iteration, expect_up=expect_up): |
468 | ++ operstate = 'routable' if expect_up else 'off' |
469 | ++ self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20) |
470 | ++ setup_state = None |
471 | ++ |
472 | ++ if expect_up: |
473 | ++ self.assertIn('UP', check_output('ip link show test1')) |
474 | ++ self.assertIn('192.168.10.30/24', check_output('ip address show test1')) |
475 | ++ self.assertIn('default via 192.168.10.1', check_output('ip route show')) |
476 | ++ else: |
477 | ++ self.assertIn('DOWN', check_output('ip link show test1')) |
478 | ++ |
479 | ++ if next_up: |
480 | ++ check_output('ip link set dev test1 up') |
481 | ++ else: |
482 | ++ check_output('ip link set dev test1 down') |
483 | ++ expect_up = initial_up if always else next_up |
484 | ++ next_up = not next_up |
485 | ++ |
486 | ++ self.tearDown() |
487 | ++ |
488 | ++ def test_activation_policy(self): |
489 | ++ for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']: |
490 | ++ with self.subTest(test=test): |
491 | ++ self._test_activation_policy(test) |
492 | ++ |
493 | + def test_domain(self): |
494 | + copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network') |
495 | + start_networkd() |
496 | diff --git a/debian/patches/lp1664844/0003-save-link-activation-policy-to-state-file-and-displa.patch b/debian/patches/lp1664844/0003-save-link-activation-policy-to-state-file-and-displa.patch |
497 | new file mode 100644 |
498 | index 0000000..be89aae |
499 | --- /dev/null |
500 | +++ b/debian/patches/lp1664844/0003-save-link-activation-policy-to-state-file-and-displa.patch |
501 | @@ -0,0 +1,110 @@ |
502 | +From a853652ae983699460b160bc2bf72f6fae0bfcd6 Mon Sep 17 00:00:00 2001 |
503 | +From: Dan Streetman <ddstreet@canonical.com> |
504 | +Date: Thu, 13 Aug 2020 11:52:53 -0400 |
505 | +Subject: [PATCH 3/3] save link activation policy to state file and display in |
506 | + networkctl |
507 | +Origin: upstream, https://github.com/systemd/systemd/pull/16228 |
508 | +Bug-Ubuntu: https://bugs.launchpad.net/netplan/+bug/1664844 |
509 | + |
510 | +--- |
511 | + src/libsystemd/sd-network/sd-network.c | 21 +++++++++++++++++++++ |
512 | + src/network/networkctl.c | 12 +++++++++++- |
513 | + src/network/networkd-link.c | 3 +++ |
514 | + src/systemd/sd-network.h | 5 +++++ |
515 | + test/test-network/systemd-networkd-tests.py | 1 + |
516 | + 5 files changed, 41 insertions(+), 1 deletion(-) |
517 | + |
518 | +--- a/src/libsystemd/sd-network/sd-network.c |
519 | ++++ b/src/libsystemd/sd-network/sd-network.c |
520 | +@@ -212,6 +212,27 @@ |
521 | + return 0; |
522 | + } |
523 | + |
524 | ++_public_ int sd_network_link_get_activation_policy(int ifindex, char **policy) { |
525 | ++ _cleanup_free_ char *s = NULL; |
526 | ++ int r; |
527 | ++ |
528 | ++ assert_return(policy, -EINVAL); |
529 | ++ |
530 | ++ r = network_link_get_string(ifindex, "ACTIVATION_POLICY", &s); |
531 | ++ if (r < 0) { |
532 | ++ if (r != -ENODATA) |
533 | ++ return r; |
534 | ++ |
535 | ++ /* For compatibility, assuming up. */ |
536 | ++ s = strdup("up"); |
537 | ++ if (!s) |
538 | ++ return -ENOMEM; |
539 | ++ } |
540 | ++ |
541 | ++ *policy = TAKE_PTR(s); |
542 | ++ return 0; |
543 | ++} |
544 | ++ |
545 | + _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { |
546 | + return network_link_get_string(ifindex, "LLMNR", llmnr); |
547 | + } |
548 | +--- a/src/network/networkctl.c |
549 | ++++ b/src/network/networkctl.c |
550 | +@@ -1390,7 +1390,7 @@ |
551 | + |
552 | + _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL; |
553 | + _cleanup_free_ char *t = NULL, *network = NULL, *iaid = NULL, *duid = NULL, |
554 | +- *setup_state = NULL, *operational_state = NULL, *lease_file = NULL; |
555 | ++ *setup_state = NULL, *operational_state = NULL, *lease_file = NULL, *activation_policy = NULL; |
556 | + const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL, |
557 | + *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; |
558 | + _cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL; |
559 | +@@ -2065,6 +2065,16 @@ |
560 | + if (r < 0) |
561 | + return r; |
562 | + |
563 | ++ r = sd_network_link_get_activation_policy(info->ifindex, &activation_policy); |
564 | ++ if (r >= 0) { |
565 | ++ r = table_add_many(table, |
566 | ++ TABLE_EMPTY, |
567 | ++ TABLE_STRING, "Activation Policy:", |
568 | ++ TABLE_STRING, activation_policy); |
569 | ++ if (r < 0) |
570 | ++ return table_log_add_error(r); |
571 | ++ } |
572 | ++ |
573 | + if (lease) { |
574 | + const void *client_id; |
575 | + size_t client_id_len; |
576 | +--- a/src/network/networkd-link.c |
577 | ++++ b/src/network/networkd-link.c |
578 | +@@ -3040,6 +3040,9 @@ |
579 | + st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "", |
580 | + st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : ""); |
581 | + |
582 | ++ fprintf(f, "ACTIVATION_POLICY=%s\n", |
583 | ++ activation_policy_to_string(link->network->activation_policy)); |
584 | ++ |
585 | + fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); |
586 | + |
587 | + /************************************************************/ |
588 | +--- a/src/systemd/sd-network.h |
589 | ++++ b/src/systemd/sd-network.h |
590 | +@@ -103,6 +103,11 @@ |
591 | + */ |
592 | + int sd_network_link_get_required_for_online(int ifindex); |
593 | + |
594 | ++/* Get activation policy for ifindex. |
595 | ++ * Possible values are as specified for ActivationPolicy= |
596 | ++ */ |
597 | ++int sd_network_link_get_activation_policy(int ifindex, char **policy); |
598 | ++ |
599 | + /* Get path to .network file applied to link */ |
600 | + int sd_network_link_get_network_file(int ifindex, char **filename); |
601 | + |
602 | +--- a/test/test-network/systemd-networkd-tests.py |
603 | ++++ b/test/test-network/systemd-networkd-tests.py |
604 | +@@ -2931,6 +2931,7 @@ |
605 | + self.assertRegex(data, r'OPER_STATE=routable') |
606 | + self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes') |
607 | + self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable') |
608 | ++ self.assertRegex(data, r'ACTIVATION_POLICY=up') |
609 | + self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network') |
610 | + self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com') |
611 | + self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') |
612 | diff --git a/debian/patches/series b/debian/patches/series |
613 | index afeff62..b220c6e 100644 |
614 | --- a/debian/patches/series |
615 | +++ b/debian/patches/series |
616 | @@ -62,3 +62,6 @@ lp1887744-basic-unit-file-when-loading-linked-unit-files-use-l.patch |
617 | lp1921696/rfkill-improve-error-logging.patch |
618 | lp1921696/rfkill-use-short-writes-and-accept-long-reads.patch |
619 | LoadCredentials-do-not-assert-on-invalid-syntax.patch |
620 | +lp1664844/0001-network-add-ActivationPolicy-configuration-parameter.patch |
621 | +lp1664844/0002-test-add-ActivationPolicy-unit-tests.patch |
622 | +lp1664844/0003-save-link-activation-policy-to-state-file-and-displa.patch |
LGTM, but adding Dan if there is anything I missed.