Merge ~danilogondolfo/netplan/+git/ubuntu:mantic_0_107_1_sru into ~ubuntu-core-dev/netplan/+git/ubuntu:ubuntu-mantic

Proposed by Danilo Egea Gondolfo
Status: Merged
Merged at revision: a28328d79bc426adf65bc6026cb81174174072de
Proposed branch: ~danilogondolfo/netplan/+git/ubuntu:mantic_0_107_1_sru
Merge into: ~ubuntu-core-dev/netplan/+git/ubuntu:ubuntu-mantic
Diff against target: 7418 lines (+4749/-562)
62 files modified
Doxyfile (+2688/-0)
debian/changelog (+69/-0)
debian/control (+2/-1)
debian/extra/PLACEHOLDER (+4/-0)
debian/netplan.io.preinst (+17/-0)
debian/patches/0001-parse-nm-wg-append-the-correct-prefix-to-IPv6-addres.patch (+77/-0)
debian/patches/0007-tests-assert-generated-.service-files-in-assert_srio.patch (+26/-0)
debian/patches/0008-tests-sriov-test-if-the-generated-netplan-rebind-ser.patch (+57/-0)
debian/patches/0009-sriov-don-t-generate-duplicate-entries-in-the-rebind.patch (+96/-0)
debian/patches/lp2041727/0004-cli-utils-introduce-systemctl_is_installed-helper.patch (+63/-0)
debian/patches/lp2041727/0005-Update-ovs.py-to-check-if-ovsdb-server.service-is-in.patch (+75/-0)
debian/patches/series (+6/-11)
debian/rules (+0/-4)
debian/tests/prep-testbed.sh (+3/-0)
dev/null (+0/-371)
doc/apidoc/inc-netplan.md (+4/-0)
doc/apidoc/inc-parse-nm.md (+4/-0)
doc/apidoc/inc-parse.md (+4/-0)
doc/apidoc/inc-types.md (+4/-0)
doc/apidoc/inc-util.md (+4/-0)
doc/apidoc/index.md (+52/-0)
doc/conf.py (+29/-1)
doc/contribute-docs.md (+26/-0)
doc/howto.md (+1/-0)
doc/netplan-everywhere.md (+54/-60)
doc/netplan-yaml.md (+5/-3)
doc/reference.md (+3/-3)
doc/requirements.txt (+1/-0)
doc/spelling_wordlist.txt (+36/-4)
examples/bonding.yaml (+1/-0)
examples/wpa3_enterprise.yaml (+26/-0)
include/netplan.h (+4/-0)
include/parse-nm.h (+4/-0)
include/parse.h (+4/-0)
include/types.h (+4/-0)
include/util.h (+21/-0)
netplan_cli/cli/commands/apply.py (+19/-1)
netplan_cli/cli/commands/try_command.py (+1/-2)
netplan_cli/cli/utils.py (+14/-0)
src/abi.h (+14/-0)
src/names.c (+4/-0)
src/netplan.c (+7/-1)
src/networkd.c (+77/-39)
src/nm.c (+49/-6)
src/parse-nm.c (+43/-6)
src/parse.c (+76/-18)
src/types-internal.h (+3/-0)
src/types.c (+3/-1)
src/util-internal.h (+3/-0)
src/util.c (+10/-0)
src/validation.c (+2/-4)
tests/generator/test_auth.py (+5/-2)
tests/generator/test_common.py (+88/-3)
tests/generator/test_tunnels.py (+9/-12)
tests/generator/test_wifis.py (+372/-8)
tests/integration/ovs.py (+4/-1)
tests/integration/regressions.py (+27/-0)
tests/integration/routing.py (+1/-0)
tests/integration/tunnels.py (+43/-0)
tests/parser/test_keyfile.py (+370/-0)
tests/test_libnetplan.py (+19/-0)
tests/test_utils.py (+12/-0)
Reviewer Review Type Date Requested Status
Lukas Märdian Approve
Ubuntu Core Development Team Pending
Review via email: mp+462773@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Lukas Märdian (slyon) wrote :

* rm .pyc/__pycache__ in python3-netplan.preinst? => Do we want/need this in Noble, too? (Can you create a Salsa MR against debian/unstable?)
* d/control: We might want to keep the openvswitch-switch <!nocheck> build-depends on armhf, as it's still built on Mantic
=> This would allow getting rid of debian/patches/0002-ovs-disable-StartLimitBurst-in-the-ovs-cleanup-servi.patch, too. IMO
=> non-blocking: As the OVS autopkgtests are skipped on armhf, too, due to missing kernel module in the container
* note (non-blocking): The 0.107.1-3ubuntu0.23.10.1 version string is (currently) bigger than what we have in noble-release, but this will be resolved by 1.0-1 in noble-proposed (stuck due to armhf time_t)
=> We should probably keep this version string as-is

LGTM! I'm just slightly concerned about the first bullet point and a little bit about the 2nd (for not reducing OVS test coverage on armhf)

review: Approve
Revision history for this message
Lukas Märdian (slyon) wrote :

We discussed the .preinst situation out-of-band and agreed that python3-netplan does not own any files in /usr/share/netplan, so should not touch those and the script should stay within the netplan.io binary.

Builds are looking good in https://launchpad.net/~danilogondolfo/+archive/ubuntu/netplan-sru/+packages

Revision history for this message
Danilo Egea Gondolfo (danilogondolfo) wrote :

I also submitted the netplan.io.preinst script to Debian https://salsa.debian.org/debian/netplan.io/-/merge_requests/12

Revision history for this message
Lukas Märdian (slyon) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/Doxyfile b/Doxyfile
2new file mode 100644
3index 0000000..19db167
4--- /dev/null
5+++ b/Doxyfile
6@@ -0,0 +1,2688 @@
7+# Doxyfile 1.9.4
8+
9+# This file describes the settings to be used by the documentation system
10+# doxygen (www.doxygen.org) for a project.
11+#
12+# All text after a double hash (##) is considered a comment and is placed in
13+# front of the TAG it is preceding.
14+#
15+# All text after a single hash (#) is considered a comment and will be ignored.
16+# The format is:
17+# TAG = value [value, ...]
18+# For lists, items can also be appended using:
19+# TAG += value [value, ...]
20+# Values that contain spaces should be placed between quotes (\" \").
21+#
22+# Note:
23+#
24+# Use doxygen to compare the used configuration file with the template
25+# configuration file:
26+# doxygen -x [configFile]
27+# Use doxygen to compare the used configuration file with the template
28+# configuration file without replacing the environment variables:
29+# doxygen -x_noenv [configFile]
30+
31+#---------------------------------------------------------------------------
32+# Project related configuration options
33+#---------------------------------------------------------------------------
34+
35+# This tag specifies the encoding used for all characters in the configuration
36+# file that follow. The default is UTF-8 which is also the encoding used for all
37+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
38+# iconv built into libc) for the transcoding. See
39+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
40+# The default value is: UTF-8.
41+
42+DOXYFILE_ENCODING = UTF-8
43+
44+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
45+# double-quotes, unless you are using Doxywizard) that should identify the
46+# project for which the documentation is generated. This name is used in the
47+# title of most generated pages and in a few other places.
48+# The default value is: My Project.
49+
50+PROJECT_NAME = "Netplan"
51+
52+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
53+# could be handy for archiving the generated documentation or if some version
54+# control system is used.
55+
56+PROJECT_NUMBER =
57+
58+# Using the PROJECT_BRIEF tag one can provide an optional one line description
59+# for a project that appears at the top of each page and should give viewer a
60+# quick idea about the purpose of the project. Keep the description short.
61+
62+PROJECT_BRIEF =
63+
64+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
65+# in the documentation. The maximum height of the logo should not exceed 55
66+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
67+# the logo to the output directory.
68+
69+PROJECT_LOGO =
70+
71+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
72+# into which the generated documentation will be written. If a relative path is
73+# entered, it will be relative to the location where doxygen was started. If
74+# left blank the current directory will be used.
75+
76+OUTPUT_DIRECTORY =
77+
78+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
79+# sub-directories (in 2 levels) under the output directory of each output format
80+# and will distribute the generated files over these directories. Enabling this
81+# option can be useful when feeding doxygen a huge amount of source files, where
82+# putting all generated files in the same directory would otherwise causes
83+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
84+# control the number of sub-directories.
85+# The default value is: NO.
86+
87+CREATE_SUBDIRS = NO
88+
89+# Controls the number of sub-directories that will be created when
90+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
91+# level increment doubles the number of directories, resulting in 4096
92+# directories at level 8 which is the default and also the maximum value. The
93+# sub-directories are organized in 2 levels, the first level always has a fixed
94+# numer of 16 directories.
95+# Minimum value: 0, maximum value: 8, default value: 8.
96+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
97+
98+CREATE_SUBDIRS_LEVEL = 8
99+
100+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
101+# characters to appear in the names of generated files. If set to NO, non-ASCII
102+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
103+# U+3044.
104+# The default value is: NO.
105+
106+ALLOW_UNICODE_NAMES = NO
107+
108+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
109+# documentation generated by doxygen is written. Doxygen will use this
110+# information to generate all constant output in the proper language.
111+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
112+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
113+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
114+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
115+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
116+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
117+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
118+# Swedish, Turkish, Ukrainian and Vietnamese.
119+# The default value is: English.
120+
121+OUTPUT_LANGUAGE = English
122+
123+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
124+# descriptions after the members that are listed in the file and class
125+# documentation (similar to Javadoc). Set to NO to disable this.
126+# The default value is: YES.
127+
128+BRIEF_MEMBER_DESC = YES
129+
130+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
131+# description of a member or function before the detailed description
132+#
133+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
134+# brief descriptions will be completely suppressed.
135+# The default value is: YES.
136+
137+REPEAT_BRIEF = YES
138+
139+# This tag implements a quasi-intelligent brief description abbreviator that is
140+# used to form the text in various listings. Each string in this list, if found
141+# as the leading text of the brief description, will be stripped from the text
142+# and the result, after processing the whole list, is used as the annotated
143+# text. Otherwise, the brief description is used as-is. If left blank, the
144+# following values are used ($name is automatically replaced with the name of
145+# the entity):The $name class, The $name widget, The $name file, is, provides,
146+# specifies, contains, represents, a, an and the.
147+
148+ABBREVIATE_BRIEF = "The $name class" \
149+ "The $name widget" \
150+ "The $name file" \
151+ is \
152+ provides \
153+ specifies \
154+ contains \
155+ represents \
156+ a \
157+ an \
158+ the
159+
160+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
161+# doxygen will generate a detailed section even if there is only a brief
162+# description.
163+# The default value is: NO.
164+
165+ALWAYS_DETAILED_SEC = NO
166+
167+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
168+# inherited members of a class in the documentation of that class as if those
169+# members were ordinary class members. Constructors, destructors and assignment
170+# operators of the base classes will not be shown.
171+# The default value is: NO.
172+
173+INLINE_INHERITED_MEMB = NO
174+
175+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
176+# before files name in the file list and in the header files. If set to NO the
177+# shortest path that makes the file name unique will be used
178+# The default value is: YES.
179+
180+FULL_PATH_NAMES = YES
181+
182+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
183+# Stripping is only done if one of the specified strings matches the left-hand
184+# part of the path. The tag can be used to show relative paths in the file list.
185+# If left blank the directory from which doxygen is run is used as the path to
186+# strip.
187+#
188+# Note that you can specify absolute paths here, but also relative paths, which
189+# will be relative from the directory where doxygen is started.
190+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
191+
192+STRIP_FROM_PATH =
193+
194+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
195+# path mentioned in the documentation of a class, which tells the reader which
196+# header file to include in order to use a class. If left blank only the name of
197+# the header file containing the class definition is used. Otherwise one should
198+# specify the list of include paths that are normally passed to the compiler
199+# using the -I flag.
200+
201+STRIP_FROM_INC_PATH =
202+
203+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
204+# less readable) file names. This can be useful is your file systems doesn't
205+# support long names like on DOS, Mac, or CD-ROM.
206+# The default value is: NO.
207+
208+SHORT_NAMES = NO
209+
210+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
211+# first line (until the first dot) of a Javadoc-style comment as the brief
212+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
213+# style comments (thus requiring an explicit @brief command for a brief
214+# description.)
215+# The default value is: NO.
216+
217+JAVADOC_AUTOBRIEF = NO
218+
219+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
220+# such as
221+# /***************
222+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
223+# Javadoc-style will behave just like regular comments and it will not be
224+# interpreted by doxygen.
225+# The default value is: NO.
226+
227+JAVADOC_BANNER = NO
228+
229+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
230+# line (until the first dot) of a Qt-style comment as the brief description. If
231+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
232+# requiring an explicit \brief command for a brief description.)
233+# The default value is: NO.
234+
235+QT_AUTOBRIEF = NO
236+
237+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
238+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
239+# a brief description. This used to be the default behavior. The new default is
240+# to treat a multi-line C++ comment block as a detailed description. Set this
241+# tag to YES if you prefer the old behavior instead.
242+#
243+# Note that setting this tag to YES also means that rational rose comments are
244+# not recognized any more.
245+# The default value is: NO.
246+
247+MULTILINE_CPP_IS_BRIEF = NO
248+
249+# By default Python docstrings are displayed as preformatted text and doxygen's
250+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
251+# doxygen's special commands can be used and the contents of the docstring
252+# documentation blocks is shown as doxygen documentation.
253+# The default value is: YES.
254+
255+PYTHON_DOCSTRING = YES
256+
257+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
258+# documentation from any documented member that it re-implements.
259+# The default value is: YES.
260+
261+INHERIT_DOCS = YES
262+
263+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
264+# page for each member. If set to NO, the documentation of a member will be part
265+# of the file/class/namespace that contains it.
266+# The default value is: NO.
267+
268+SEPARATE_MEMBER_PAGES = NO
269+
270+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
271+# uses this value to replace tabs by spaces in code fragments.
272+# Minimum value: 1, maximum value: 16, default value: 4.
273+
274+TAB_SIZE = 4
275+
276+# This tag can be used to specify a number of aliases that act as commands in
277+# the documentation. An alias has the form:
278+# name=value
279+# For example adding
280+# "sideeffect=@par Side Effects:^^"
281+# will allow you to put the command \sideeffect (or @sideeffect) in the
282+# documentation, which will result in a user-defined paragraph with heading
283+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
284+# to insert newlines (in the resulting output). You can put ^^ in the value part
285+# of an alias to insert a newline as if a physical newline was in the original
286+# file. When you need a literal { or } or , in the value part of an alias you
287+# have to escape them by means of a backslash (\), this can lead to conflicts
288+# with the commands \{ and \} for these it is advised to use the version @{ and
289+# @} or use a double escape (\\{ and \\})
290+
291+ALIASES =
292+
293+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
294+# only. Doxygen will then generate output that is more tailored for C. For
295+# instance, some of the names that are used will be different. The list of all
296+# members will be omitted, etc.
297+# The default value is: NO.
298+
299+OPTIMIZE_OUTPUT_FOR_C = NO
300+
301+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
302+# Python sources only. Doxygen will then generate output that is more tailored
303+# for that language. For instance, namespaces will be presented as packages,
304+# qualified scopes will look different, etc.
305+# The default value is: NO.
306+
307+OPTIMIZE_OUTPUT_JAVA = NO
308+
309+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
310+# sources. Doxygen will then generate output that is tailored for Fortran.
311+# The default value is: NO.
312+
313+OPTIMIZE_FOR_FORTRAN = NO
314+
315+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
316+# sources. Doxygen will then generate output that is tailored for VHDL.
317+# The default value is: NO.
318+
319+OPTIMIZE_OUTPUT_VHDL = NO
320+
321+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
322+# sources only. Doxygen will then generate output that is more tailored for that
323+# language. For instance, namespaces will be presented as modules, types will be
324+# separated into more groups, etc.
325+# The default value is: NO.
326+
327+OPTIMIZE_OUTPUT_SLICE = NO
328+
329+# Doxygen selects the parser to use depending on the extension of the files it
330+# parses. With this tag you can assign which parser to use for a given
331+# extension. Doxygen has a built-in mapping, but you can override or extend it
332+# using this tag. The format is ext=language, where ext is a file extension, and
333+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
334+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
335+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
336+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
337+# tries to guess whether the code is fixed or free formatted code, this is the
338+# default for Fortran type files). For instance to make doxygen treat .inc files
339+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
340+# use: inc=Fortran f=C.
341+#
342+# Note: For files without extension you can use no_extension as a placeholder.
343+#
344+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
345+# the files are not read by doxygen. When specifying no_extension you should add
346+# * to the FILE_PATTERNS.
347+#
348+# Note see also the list of default file extension mappings.
349+
350+EXTENSION_MAPPING =
351+
352+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
353+# according to the Markdown format, which allows for more readable
354+# documentation. See https://daringfireball.net/projects/markdown/ for details.
355+# The output of markdown processing is further processed by doxygen, so you can
356+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
357+# case of backward compatibilities issues.
358+# The default value is: YES.
359+
360+MARKDOWN_SUPPORT = YES
361+
362+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
363+# to that level are automatically included in the table of contents, even if
364+# they do not have an id attribute.
365+# Note: This feature currently applies only to Markdown headings.
366+# Minimum value: 0, maximum value: 99, default value: 5.
367+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
368+
369+TOC_INCLUDE_HEADINGS = 5
370+
371+# When enabled doxygen tries to link words that correspond to documented
372+# classes, or namespaces to their corresponding documentation. Such a link can
373+# be prevented in individual cases by putting a % sign in front of the word or
374+# globally by setting AUTOLINK_SUPPORT to NO.
375+# The default value is: YES.
376+
377+AUTOLINK_SUPPORT = YES
378+
379+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
380+# to include (a tag file for) the STL sources as input, then you should set this
381+# tag to YES in order to let doxygen match functions declarations and
382+# definitions whose arguments contain STL classes (e.g. func(std::string);
383+# versus func(std::string) {}). This also make the inheritance and collaboration
384+# diagrams that involve STL classes more complete and accurate.
385+# The default value is: NO.
386+
387+BUILTIN_STL_SUPPORT = NO
388+
389+# If you use Microsoft's C++/CLI language, you should set this option to YES to
390+# enable parsing support.
391+# The default value is: NO.
392+
393+CPP_CLI_SUPPORT = NO
394+
395+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
396+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
397+# will parse them like normal C++ but will assume all classes use public instead
398+# of private inheritance when no explicit protection keyword is present.
399+# The default value is: NO.
400+
401+SIP_SUPPORT = NO
402+
403+# For Microsoft's IDL there are propget and propput attributes to indicate
404+# getter and setter methods for a property. Setting this option to YES will make
405+# doxygen to replace the get and set methods by a property in the documentation.
406+# This will only work if the methods are indeed getting or setting a simple
407+# type. If this is not the case, or you want to show the methods anyway, you
408+# should set this option to NO.
409+# The default value is: YES.
410+
411+IDL_PROPERTY_SUPPORT = YES
412+
413+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
414+# tag is set to YES then doxygen will reuse the documentation of the first
415+# member in the group (if any) for the other members of the group. By default
416+# all members of a group must be documented explicitly.
417+# The default value is: NO.
418+
419+DISTRIBUTE_GROUP_DOC = NO
420+
421+# If one adds a struct or class to a group and this option is enabled, then also
422+# any nested class or struct is added to the same group. By default this option
423+# is disabled and one has to add nested compounds explicitly via \ingroup.
424+# The default value is: NO.
425+
426+GROUP_NESTED_COMPOUNDS = NO
427+
428+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
429+# (for instance a group of public functions) to be put as a subgroup of that
430+# type (e.g. under the Public Functions section). Set it to NO to prevent
431+# subgrouping. Alternatively, this can be done per class using the
432+# \nosubgrouping command.
433+# The default value is: YES.
434+
435+SUBGROUPING = YES
436+
437+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
438+# are shown inside the group in which they are included (e.g. using \ingroup)
439+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
440+# and RTF).
441+#
442+# Note that this feature does not work in combination with
443+# SEPARATE_MEMBER_PAGES.
444+# The default value is: NO.
445+
446+INLINE_GROUPED_CLASSES = NO
447+
448+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
449+# with only public data fields or simple typedef fields will be shown inline in
450+# the documentation of the scope in which they are defined (i.e. file,
451+# namespace, or group documentation), provided this scope is documented. If set
452+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
453+# Man pages) or section (for LaTeX and RTF).
454+# The default value is: NO.
455+
456+INLINE_SIMPLE_STRUCTS = NO
457+
458+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
459+# enum is documented as struct, union, or enum with the name of the typedef. So
460+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
461+# with name TypeT. When disabled the typedef will appear as a member of a file,
462+# namespace, or class. And the struct will be named TypeS. This can typically be
463+# useful for C code in case the coding convention dictates that all compound
464+# types are typedef'ed and only the typedef is referenced, never the tag name.
465+# The default value is: NO.
466+
467+TYPEDEF_HIDES_STRUCT = NO
468+
469+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
470+# cache is used to resolve symbols given their name and scope. Since this can be
471+# an expensive process and often the same symbol appears multiple times in the
472+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
473+# doxygen will become slower. If the cache is too large, memory is wasted. The
474+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
475+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
476+# symbols. At the end of a run doxygen will report the cache usage and suggest
477+# the optimal cache size from a speed point of view.
478+# Minimum value: 0, maximum value: 9, default value: 0.
479+
480+LOOKUP_CACHE_SIZE = 0
481+
482+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
483+# during processing. When set to 0 doxygen will based this on the number of
484+# cores available in the system. You can set it explicitly to a value larger
485+# than 0 to get more control over the balance between CPU load and processing
486+# speed. At this moment only the input processing can be done using multiple
487+# threads. Since this is still an experimental feature the default is set to 1,
488+# which effectively disables parallel processing. Please report any issues you
489+# encounter. Generating dot graphs in parallel is controlled by the
490+# DOT_NUM_THREADS setting.
491+# Minimum value: 0, maximum value: 32, default value: 1.
492+
493+NUM_PROC_THREADS = 1
494+
495+#---------------------------------------------------------------------------
496+# Build related configuration options
497+#---------------------------------------------------------------------------
498+
499+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
500+# documentation are documented, even if no documentation was available. Private
501+# class members and static file members will be hidden unless the
502+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
503+# Note: This will also disable the warnings about undocumented members that are
504+# normally produced when WARNINGS is set to YES.
505+# The default value is: NO.
506+
507+EXTRACT_ALL = NO
508+
509+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
510+# be included in the documentation.
511+# The default value is: NO.
512+
513+EXTRACT_PRIVATE = NO
514+
515+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
516+# methods of a class will be included in the documentation.
517+# The default value is: NO.
518+
519+EXTRACT_PRIV_VIRTUAL = NO
520+
521+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
522+# scope will be included in the documentation.
523+# The default value is: NO.
524+
525+EXTRACT_PACKAGE = NO
526+
527+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
528+# included in the documentation.
529+# The default value is: NO.
530+
531+EXTRACT_STATIC = NO
532+
533+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
534+# locally in source files will be included in the documentation. If set to NO,
535+# only classes defined in header files are included. Does not have any effect
536+# for Java sources.
537+# The default value is: YES.
538+
539+EXTRACT_LOCAL_CLASSES = YES
540+
541+# This flag is only useful for Objective-C code. If set to YES, local methods,
542+# which are defined in the implementation section but not in the interface are
543+# included in the documentation. If set to NO, only methods in the interface are
544+# included.
545+# The default value is: NO.
546+
547+EXTRACT_LOCAL_METHODS = NO
548+
549+# If this flag is set to YES, the members of anonymous namespaces will be
550+# extracted and appear in the documentation as a namespace called
551+# 'anonymous_namespace{file}', where file will be replaced with the base name of
552+# the file that contains the anonymous namespace. By default anonymous namespace
553+# are hidden.
554+# The default value is: NO.
555+
556+EXTRACT_ANON_NSPACES = NO
557+
558+# If this flag is set to YES, the name of an unnamed parameter in a declaration
559+# will be determined by the corresponding definition. By default unnamed
560+# parameters remain unnamed in the output.
561+# The default value is: YES.
562+
563+RESOLVE_UNNAMED_PARAMS = YES
564+
565+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
566+# undocumented members inside documented classes or files. If set to NO these
567+# members will be included in the various overviews, but no documentation
568+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
569+# The default value is: NO.
570+
571+HIDE_UNDOC_MEMBERS = NO
572+
573+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
574+# undocumented classes that are normally visible in the class hierarchy. If set
575+# to NO, these classes will be included in the various overviews. This option
576+# has no effect if EXTRACT_ALL is enabled.
577+# The default value is: NO.
578+
579+HIDE_UNDOC_CLASSES = NO
580+
581+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
582+# declarations. If set to NO, these declarations will be included in the
583+# documentation.
584+# The default value is: NO.
585+
586+HIDE_FRIEND_COMPOUNDS = NO
587+
588+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
589+# documentation blocks found inside the body of a function. If set to NO, these
590+# blocks will be appended to the function's detailed documentation block.
591+# The default value is: NO.
592+
593+HIDE_IN_BODY_DOCS = NO
594+
595+# The INTERNAL_DOCS tag determines if documentation that is typed after a
596+# \internal command is included. If the tag is set to NO then the documentation
597+# will be excluded. Set it to YES to include the internal documentation.
598+# The default value is: NO.
599+
600+INTERNAL_DOCS = NO
601+
602+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
603+# able to match the capabilities of the underlying filesystem. In case the
604+# filesystem is case sensitive (i.e. it supports files in the same directory
605+# whose names only differ in casing), the option must be set to YES to properly
606+# deal with such files in case they appear in the input. For filesystems that
607+# are not case sensitive the option should be set to NO to properly deal with
608+# output files written for symbols that only differ in casing, such as for two
609+# classes, one named CLASS and the other named Class, and to also support
610+# references to files without having to specify the exact matching casing. On
611+# Windows (including Cygwin) and MacOS, users should typically set this option
612+# to NO, whereas on Linux or other Unix flavors it should typically be set to
613+# YES.
614+# The default value is: system dependent.
615+
616+CASE_SENSE_NAMES = YES
617+
618+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
619+# their full class and namespace scopes in the documentation. If set to YES, the
620+# scope will be hidden.
621+# The default value is: NO.
622+
623+HIDE_SCOPE_NAMES = NO
624+
625+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
626+# append additional text to a page's title, such as Class Reference. If set to
627+# YES the compound reference will be hidden.
628+# The default value is: NO.
629+
630+HIDE_COMPOUND_REFERENCE= NO
631+
632+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
633+# will show which file needs to be included to use the class.
634+# The default value is: YES.
635+
636+SHOW_HEADERFILE = YES
637+
638+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
639+# the files that are included by a file in the documentation of that file.
640+# The default value is: YES.
641+
642+SHOW_INCLUDE_FILES = YES
643+
644+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
645+# grouped member an include statement to the documentation, telling the reader
646+# which file to include in order to use the member.
647+# The default value is: NO.
648+
649+SHOW_GROUPED_MEMB_INC = NO
650+
651+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
652+# files with double quotes in the documentation rather than with sharp brackets.
653+# The default value is: NO.
654+
655+FORCE_LOCAL_INCLUDES = NO
656+
657+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
658+# documentation for inline members.
659+# The default value is: YES.
660+
661+INLINE_INFO = YES
662+
663+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
664+# (detailed) documentation of file and class members alphabetically by member
665+# name. If set to NO, the members will appear in declaration order.
666+# The default value is: YES.
667+
668+SORT_MEMBER_DOCS = YES
669+
670+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
671+# descriptions of file, namespace and class members alphabetically by member
672+# name. If set to NO, the members will appear in declaration order. Note that
673+# this will also influence the order of the classes in the class list.
674+# The default value is: NO.
675+
676+SORT_BRIEF_DOCS = NO
677+
678+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
679+# (brief and detailed) documentation of class members so that constructors and
680+# destructors are listed first. If set to NO the constructors will appear in the
681+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
682+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
683+# member documentation.
684+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
685+# detailed member documentation.
686+# The default value is: NO.
687+
688+SORT_MEMBERS_CTORS_1ST = NO
689+
690+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
691+# of group names into alphabetical order. If set to NO the group names will
692+# appear in their defined order.
693+# The default value is: NO.
694+
695+SORT_GROUP_NAMES = NO
696+
697+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
698+# fully-qualified names, including namespaces. If set to NO, the class list will
699+# be sorted only by class name, not including the namespace part.
700+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
701+# Note: This option applies only to the class list, not to the alphabetical
702+# list.
703+# The default value is: NO.
704+
705+SORT_BY_SCOPE_NAME = NO
706+
707+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
708+# type resolution of all parameters of a function it will reject a match between
709+# the prototype and the implementation of a member function even if there is
710+# only one candidate or it is obvious which candidate to choose by doing a
711+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
712+# accept a match between prototype and implementation in such cases.
713+# The default value is: NO.
714+
715+STRICT_PROTO_MATCHING = NO
716+
717+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
718+# list. This list is created by putting \todo commands in the documentation.
719+# The default value is: YES.
720+
721+GENERATE_TODOLIST = YES
722+
723+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
724+# list. This list is created by putting \test commands in the documentation.
725+# The default value is: YES.
726+
727+GENERATE_TESTLIST = YES
728+
729+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
730+# list. This list is created by putting \bug commands in the documentation.
731+# The default value is: YES.
732+
733+GENERATE_BUGLIST = YES
734+
735+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
736+# the deprecated list. This list is created by putting \deprecated commands in
737+# the documentation.
738+# The default value is: YES.
739+
740+GENERATE_DEPRECATEDLIST= YES
741+
742+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
743+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
744+# ... \endcond blocks.
745+
746+ENABLED_SECTIONS =
747+
748+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
749+# initial value of a variable or macro / define can have for it to appear in the
750+# documentation. If the initializer consists of more lines than specified here
751+# it will be hidden. Use a value of 0 to hide initializers completely. The
752+# appearance of the value of individual variables and macros / defines can be
753+# controlled using \showinitializer or \hideinitializer command in the
754+# documentation regardless of this setting.
755+# Minimum value: 0, maximum value: 10000, default value: 30.
756+
757+MAX_INITIALIZER_LINES = 30
758+
759+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
760+# the bottom of the documentation of classes and structs. If set to YES, the
761+# list will mention the files that were used to generate the documentation.
762+# The default value is: YES.
763+
764+SHOW_USED_FILES = YES
765+
766+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
767+# will remove the Files entry from the Quick Index and from the Folder Tree View
768+# (if specified).
769+# The default value is: YES.
770+
771+SHOW_FILES = YES
772+
773+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
774+# page. This will remove the Namespaces entry from the Quick Index and from the
775+# Folder Tree View (if specified).
776+# The default value is: YES.
777+
778+SHOW_NAMESPACES = YES
779+
780+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
781+# doxygen should invoke to get the current version for each file (typically from
782+# the version control system). Doxygen will invoke the program by executing (via
783+# popen()) the command command input-file, where command is the value of the
784+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
785+# by doxygen. Whatever the program writes to standard output is used as the file
786+# version. For an example see the documentation.
787+
788+FILE_VERSION_FILTER =
789+
790+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
791+# by doxygen. The layout file controls the global structure of the generated
792+# output files in an output format independent way. To create the layout file
793+# that represents doxygen's defaults, run doxygen with the -l option. You can
794+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
795+# will be used as the name of the layout file. See also section "Changing the
796+# layout of pages" for information.
797+#
798+# Note that if you run doxygen from a directory containing a file called
799+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
800+# tag is left empty.
801+
802+LAYOUT_FILE =
803+
804+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
805+# the reference definitions. This must be a list of .bib files. The .bib
806+# extension is automatically appended if omitted. This requires the bibtex tool
807+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
808+# For LaTeX the style of the bibliography can be controlled using
809+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
810+# search path. See also \cite for info how to create references.
811+
812+CITE_BIB_FILES =
813+
814+#---------------------------------------------------------------------------
815+# Configuration options related to warning and progress messages
816+#---------------------------------------------------------------------------
817+
818+# The QUIET tag can be used to turn on/off the messages that are generated to
819+# standard output by doxygen. If QUIET is set to YES this implies that the
820+# messages are off.
821+# The default value is: NO.
822+
823+QUIET = NO
824+
825+# The WARNINGS tag can be used to turn on/off the warning messages that are
826+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
827+# this implies that the warnings are on.
828+#
829+# Tip: Turn warnings on while writing the documentation.
830+# The default value is: YES.
831+
832+WARNINGS = YES
833+
834+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
835+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
836+# will automatically be disabled.
837+# The default value is: YES.
838+
839+WARN_IF_UNDOCUMENTED = YES
840+
841+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
842+# potential errors in the documentation, such as documenting some parameters in
843+# a documented function twice, or documenting parameters that don't exist or
844+# using markup commands wrongly.
845+# The default value is: YES.
846+
847+WARN_IF_DOC_ERROR = YES
848+
849+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
850+# function parameter documentation. If set to NO, doxygen will accept that some
851+# parameters have no documentation without warning.
852+# The default value is: YES.
853+
854+WARN_IF_INCOMPLETE_DOC = YES
855+
856+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
857+# are documented, but have no documentation for their parameters or return
858+# value. If set to NO, doxygen will only warn about wrong parameter
859+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
860+# set to YES then this flag will automatically be disabled. See also
861+# WARN_IF_INCOMPLETE_DOC
862+# The default value is: NO.
863+
864+WARN_NO_PARAMDOC = NO
865+
866+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
867+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
868+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
869+# at the end of the doxygen process doxygen will return with a non-zero status.
870+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
871+# The default value is: NO.
872+
873+WARN_AS_ERROR = NO
874+
875+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
876+# can produce. The string should contain the $file, $line, and $text tags, which
877+# will be replaced by the file and line number from which the warning originated
878+# and the warning text. Optionally the format may contain $version, which will
879+# be replaced by the version of the file (if it could be obtained via
880+# FILE_VERSION_FILTER)
881+# See also: WARN_LINE_FORMAT
882+# The default value is: $file:$line: $text.
883+
884+WARN_FORMAT = "$file:$line: $text"
885+
886+# In the $text part of the WARN_FORMAT command it is possible that a reference
887+# to a more specific place is given. To make it easier to jump to this place
888+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
889+# Example:
890+# WARN_LINE_FORMAT = "'vi $file +$line'"
891+# See also: WARN_FORMAT
892+# The default value is: at line $line of file $file.
893+
894+WARN_LINE_FORMAT = "at line $line of file $file"
895+
896+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
897+# messages should be written. If left blank the output is written to standard
898+# error (stderr). In case the file specified cannot be opened for writing the
899+# warning and error messages are written to standard error. When as file - is
900+# specified the warning and error messages are written to standard output
901+# (stdout).
902+
903+WARN_LOGFILE =
904+
905+#---------------------------------------------------------------------------
906+# Configuration options related to the input files
907+#---------------------------------------------------------------------------
908+
909+# The INPUT tag is used to specify the files and/or directories that contain
910+# documented source files. You may enter file names like myfile.cpp or
911+# directories like /usr/src/myproject. Separate the files or directories with
912+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
913+# Note: If this tag is empty the current directory is searched.
914+
915+INPUT = src/ include/
916+
917+# This tag can be used to specify the character encoding of the source files
918+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
919+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
920+# documentation (see:
921+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
922+# The default value is: UTF-8.
923+
924+INPUT_ENCODING = UTF-8
925+
926+# If the value of the INPUT tag contains directories, you can use the
927+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
928+# *.h) to filter out the source-files in the directories.
929+#
930+# Note that for custom extensions or not directly supported extensions you also
931+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
932+# read by doxygen.
933+#
934+# Note the list of default checked file patterns might differ from the list of
935+# default file extension mappings.
936+#
937+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
938+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
939+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
940+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
941+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
942+# *.vhdl, *.ucf, *.qsf and *.ice.
943+
944+#FILE_PATTERNS = *.c *.h
945+
946+# The RECURSIVE tag can be used to specify whether or not subdirectories should
947+# be searched for input files as well.
948+# The default value is: NO.
949+
950+RECURSIVE = YES
951+
952+# The EXCLUDE tag can be used to specify files and/or directories that should be
953+# excluded from the INPUT source files. This way you can easily exclude a
954+# subdirectory from a directory tree whose root is specified with the INPUT tag.
955+#
956+# Note that relative paths are relative to the directory from which doxygen is
957+# run.
958+
959+EXCLUDE =
960+
961+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
962+# directories that are symbolic links (a Unix file system feature) are excluded
963+# from the input.
964+# The default value is: NO.
965+
966+EXCLUDE_SYMLINKS = NO
967+
968+# If the value of the INPUT tag contains directories, you can use the
969+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
970+# certain files from those directories.
971+#
972+# Note that the wildcards are matched against the file with absolute path, so to
973+# exclude all test directories for example use the pattern */test/*
974+
975+EXCLUDE_PATTERNS = */tests/* */doc/*
976+
977+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
978+# (namespaces, classes, functions, etc.) that should be excluded from the
979+# output. The symbol name can be a fully qualified name, a word, or if the
980+# wildcard * is used, a substring. Examples: ANamespace, AClass,
981+# ANamespace::AClass, ANamespace::*Test
982+#
983+# Note that the wildcards are matched against the file with absolute path, so to
984+# exclude all test directories use the pattern */test/*
985+
986+EXCLUDE_SYMBOLS =
987+
988+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
989+# that contain example code fragments that are included (see the \include
990+# command).
991+
992+EXAMPLE_PATH =
993+
994+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
995+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
996+# *.h) to filter out the source-files in the directories. If left blank all
997+# files are included.
998+
999+EXAMPLE_PATTERNS = *
1000+
1001+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
1002+# searched for input files to be used with the \include or \dontinclude commands
1003+# irrespective of the value of the RECURSIVE tag.
1004+# The default value is: NO.
1005+
1006+EXAMPLE_RECURSIVE = NO
1007+
1008+# The IMAGE_PATH tag can be used to specify one or more files or directories
1009+# that contain images that are to be included in the documentation (see the
1010+# \image command).
1011+
1012+IMAGE_PATH =
1013+
1014+# The INPUT_FILTER tag can be used to specify a program that doxygen should
1015+# invoke to filter for each input file. Doxygen will invoke the filter program
1016+# by executing (via popen()) the command:
1017+#
1018+# <filter> <input-file>
1019+#
1020+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
1021+# name of an input file. Doxygen will then use the output that the filter
1022+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
1023+# will be ignored.
1024+#
1025+# Note that the filter must not add or remove lines; it is applied before the
1026+# code is scanned, but not when the output code is generated. If lines are added
1027+# or removed, the anchors will not be placed correctly.
1028+#
1029+# Note that for custom extensions or not directly supported extensions you also
1030+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
1031+# properly processed by doxygen.
1032+
1033+INPUT_FILTER =
1034+
1035+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
1036+# basis. Doxygen will compare the file name with each pattern and apply the
1037+# filter if there is a match. The filters are a list of the form: pattern=filter
1038+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
1039+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
1040+# patterns match the file name, INPUT_FILTER is applied.
1041+#
1042+# Note that for custom extensions or not directly supported extensions you also
1043+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
1044+# properly processed by doxygen.
1045+
1046+FILTER_PATTERNS =
1047+
1048+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
1049+# INPUT_FILTER) will also be used to filter the input files that are used for
1050+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
1051+# The default value is: NO.
1052+
1053+FILTER_SOURCE_FILES = NO
1054+
1055+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
1056+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
1057+# it is also possible to disable source filtering for a specific pattern using
1058+# *.ext= (so without naming a filter).
1059+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
1060+
1061+FILTER_SOURCE_PATTERNS =
1062+
1063+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
1064+# is part of the input, its contents will be placed on the main page
1065+# (index.html). This can be useful if you have a project on for instance GitHub
1066+# and want to reuse the introduction page also for the doxygen output.
1067+
1068+USE_MDFILE_AS_MAINPAGE =
1069+
1070+#---------------------------------------------------------------------------
1071+# Configuration options related to source browsing
1072+#---------------------------------------------------------------------------
1073+
1074+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
1075+# generated. Documented entities will be cross-referenced with these sources.
1076+#
1077+# Note: To get rid of all source code in the generated output, make sure that
1078+# also VERBATIM_HEADERS is set to NO.
1079+# The default value is: NO.
1080+
1081+SOURCE_BROWSER = NO
1082+
1083+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
1084+# classes and enums directly into the documentation.
1085+# The default value is: NO.
1086+
1087+INLINE_SOURCES = NO
1088+
1089+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
1090+# special comment blocks from generated source code fragments. Normal C, C++ and
1091+# Fortran comments will always remain visible.
1092+# The default value is: YES.
1093+
1094+STRIP_CODE_COMMENTS = YES
1095+
1096+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
1097+# entity all documented functions referencing it will be listed.
1098+# The default value is: NO.
1099+
1100+REFERENCED_BY_RELATION = NO
1101+
1102+# If the REFERENCES_RELATION tag is set to YES then for each documented function
1103+# all documented entities called/used by that function will be listed.
1104+# The default value is: NO.
1105+
1106+REFERENCES_RELATION = NO
1107+
1108+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
1109+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
1110+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
1111+# link to the documentation.
1112+# The default value is: YES.
1113+
1114+REFERENCES_LINK_SOURCE = YES
1115+
1116+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
1117+# source code will show a tooltip with additional information such as prototype,
1118+# brief description and links to the definition and documentation. Since this
1119+# will make the HTML file larger and loading of large files a bit slower, you
1120+# can opt to disable this feature.
1121+# The default value is: YES.
1122+# This tag requires that the tag SOURCE_BROWSER is set to YES.
1123+
1124+SOURCE_TOOLTIPS = YES
1125+
1126+# If the USE_HTAGS tag is set to YES then the references to source code will
1127+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
1128+# source browser. The htags tool is part of GNU's global source tagging system
1129+# (see https://www.gnu.org/software/global/global.html). You will need version
1130+# 4.8.6 or higher.
1131+#
1132+# To use it do the following:
1133+# - Install the latest version of global
1134+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
1135+# - Make sure the INPUT points to the root of the source tree
1136+# - Run doxygen as normal
1137+#
1138+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
1139+# tools must be available from the command line (i.e. in the search path).
1140+#
1141+# The result: instead of the source browser generated by doxygen, the links to
1142+# source code will now point to the output of htags.
1143+# The default value is: NO.
1144+# This tag requires that the tag SOURCE_BROWSER is set to YES.
1145+
1146+USE_HTAGS = NO
1147+
1148+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
1149+# verbatim copy of the header file for each class for which an include is
1150+# specified. Set to NO to disable this.
1151+# See also: Section \class.
1152+# The default value is: YES.
1153+
1154+VERBATIM_HEADERS = YES
1155+
1156+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
1157+# clang parser (see:
1158+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
1159+# performance. This can be particularly helpful with template rich C++ code for
1160+# which doxygen's built-in parser lacks the necessary type information.
1161+# Note: The availability of this option depends on whether or not doxygen was
1162+# generated with the -Duse_libclang=ON option for CMake.
1163+# The default value is: NO.
1164+
1165+CLANG_ASSISTED_PARSING = NO
1166+
1167+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
1168+# tag is set to YES then doxygen will add the directory of each input to the
1169+# include path.
1170+# The default value is: YES.
1171+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
1172+
1173+CLANG_ADD_INC_PATHS = YES
1174+
1175+# If clang assisted parsing is enabled you can provide the compiler with command
1176+# line options that you would normally use when invoking the compiler. Note that
1177+# the include paths will already be set by doxygen for the files and directories
1178+# specified with INPUT and INCLUDE_PATH.
1179+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
1180+
1181+CLANG_OPTIONS =
1182+
1183+# If clang assisted parsing is enabled you can provide the clang parser with the
1184+# path to the directory containing a file called compile_commands.json. This
1185+# file is the compilation database (see:
1186+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
1187+# options used when the source files were built. This is equivalent to
1188+# specifying the -p option to a clang tool, such as clang-check. These options
1189+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
1190+# will be added as well.
1191+# Note: The availability of this option depends on whether or not doxygen was
1192+# generated with the -Duse_libclang=ON option for CMake.
1193+
1194+CLANG_DATABASE_PATH =
1195+
1196+#---------------------------------------------------------------------------
1197+# Configuration options related to the alphabetical class index
1198+#---------------------------------------------------------------------------
1199+
1200+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
1201+# compounds will be generated. Enable this if the project contains a lot of
1202+# classes, structs, unions or interfaces.
1203+# The default value is: YES.
1204+
1205+ALPHABETICAL_INDEX = YES
1206+
1207+# In case all classes in a project start with a common prefix, all classes will
1208+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
1209+# can be used to specify a prefix (or a list of prefixes) that should be ignored
1210+# while generating the index headers.
1211+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1212+
1213+IGNORE_PREFIX =
1214+
1215+#---------------------------------------------------------------------------
1216+# Configuration options related to the HTML output
1217+#---------------------------------------------------------------------------
1218+
1219+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
1220+# The default value is: YES.
1221+
1222+GENERATE_HTML = YES
1223+
1224+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
1225+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1226+# it.
1227+# The default directory is: html.
1228+# This tag requires that the tag GENERATE_HTML is set to YES.
1229+
1230+HTML_OUTPUT = html
1231+
1232+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
1233+# generated HTML page (for example: .htm, .php, .asp).
1234+# The default value is: .html.
1235+# This tag requires that the tag GENERATE_HTML is set to YES.
1236+
1237+HTML_FILE_EXTENSION = .html
1238+
1239+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
1240+# each generated HTML page. If the tag is left blank doxygen will generate a
1241+# standard header.
1242+#
1243+# To get valid HTML the header file that includes any scripts and style sheets
1244+# that doxygen needs, which is dependent on the configuration options used (e.g.
1245+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
1246+# default header using
1247+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
1248+# YourConfigFile
1249+# and then modify the file new_header.html. See also section "Doxygen usage"
1250+# for information on how to generate the default header that doxygen normally
1251+# uses.
1252+# Note: The header is subject to change so you typically have to regenerate the
1253+# default header when upgrading to a newer version of doxygen. For a description
1254+# of the possible markers and block names see the documentation.
1255+# This tag requires that the tag GENERATE_HTML is set to YES.
1256+
1257+HTML_HEADER =
1258+
1259+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
1260+# generated HTML page. If the tag is left blank doxygen will generate a standard
1261+# footer. See HTML_HEADER for more information on how to generate a default
1262+# footer and what special commands can be used inside the footer. See also
1263+# section "Doxygen usage" for information on how to generate the default footer
1264+# that doxygen normally uses.
1265+# This tag requires that the tag GENERATE_HTML is set to YES.
1266+
1267+HTML_FOOTER =
1268+
1269+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
1270+# sheet that is used by each HTML page. It can be used to fine-tune the look of
1271+# the HTML output. If left blank doxygen will generate a default style sheet.
1272+# See also section "Doxygen usage" for information on how to generate the style
1273+# sheet that doxygen normally uses.
1274+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
1275+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
1276+# obsolete.
1277+# This tag requires that the tag GENERATE_HTML is set to YES.
1278+
1279+HTML_STYLESHEET =
1280+
1281+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1282+# cascading style sheets that are included after the standard style sheets
1283+# created by doxygen. Using this option one can overrule certain style aspects.
1284+# This is preferred over using HTML_STYLESHEET since it does not replace the
1285+# standard style sheet and is therefore more robust against future updates.
1286+# Doxygen will copy the style sheet files to the output directory.
1287+# Note: The order of the extra style sheet files is of importance (e.g. the last
1288+# style sheet in the list overrules the setting of the previous ones in the
1289+# list). For an example see the documentation.
1290+# This tag requires that the tag GENERATE_HTML is set to YES.
1291+
1292+HTML_EXTRA_STYLESHEET =
1293+
1294+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1295+# other source files which should be copied to the HTML output directory. Note
1296+# that these files will be copied to the base HTML output directory. Use the
1297+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
1298+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
1299+# files will be copied as-is; there are no commands or markers available.
1300+# This tag requires that the tag GENERATE_HTML is set to YES.
1301+
1302+HTML_EXTRA_FILES =
1303+
1304+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1305+# will adjust the colors in the style sheet and background images according to
1306+# this color. Hue is specified as an angle on a color-wheel, see
1307+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
1308+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
1309+# purple, and 360 is red again.
1310+# Minimum value: 0, maximum value: 359, default value: 220.
1311+# This tag requires that the tag GENERATE_HTML is set to YES.
1312+
1313+HTML_COLORSTYLE_HUE = 220
1314+
1315+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
1316+# in the HTML output. For a value of 0 the output will use gray-scales only. A
1317+# value of 255 will produce the most vivid colors.
1318+# Minimum value: 0, maximum value: 255, default value: 100.
1319+# This tag requires that the tag GENERATE_HTML is set to YES.
1320+
1321+HTML_COLORSTYLE_SAT = 100
1322+
1323+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
1324+# luminance component of the colors in the HTML output. Values below 100
1325+# gradually make the output lighter, whereas values above 100 make the output
1326+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
1327+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
1328+# change the gamma.
1329+# Minimum value: 40, maximum value: 240, default value: 80.
1330+# This tag requires that the tag GENERATE_HTML is set to YES.
1331+
1332+HTML_COLORSTYLE_GAMMA = 80
1333+
1334+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1335+# page will contain the date and time when the page was generated. Setting this
1336+# to YES can help to show when doxygen was last run and thus if the
1337+# documentation is up to date.
1338+# The default value is: NO.
1339+# This tag requires that the tag GENERATE_HTML is set to YES.
1340+
1341+HTML_TIMESTAMP = NO
1342+
1343+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
1344+# documentation will contain a main index with vertical navigation menus that
1345+# are dynamically created via JavaScript. If disabled, the navigation index will
1346+# consists of multiple levels of tabs that are statically embedded in every HTML
1347+# page. Disable this option to support browsers that do not have JavaScript,
1348+# like the Qt help browser.
1349+# The default value is: YES.
1350+# This tag requires that the tag GENERATE_HTML is set to YES.
1351+
1352+HTML_DYNAMIC_MENUS = YES
1353+
1354+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
1355+# documentation will contain sections that can be hidden and shown after the
1356+# page has loaded.
1357+# The default value is: NO.
1358+# This tag requires that the tag GENERATE_HTML is set to YES.
1359+
1360+HTML_DYNAMIC_SECTIONS = NO
1361+
1362+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
1363+# shown in the various tree structured indices initially; the user can expand
1364+# and collapse entries dynamically later on. Doxygen will expand the tree to
1365+# such a level that at most the specified number of entries are visible (unless
1366+# a fully collapsed tree already exceeds this amount). So setting the number of
1367+# entries 1 will produce a full collapsed tree by default. 0 is a special value
1368+# representing an infinite number of entries and will result in a full expanded
1369+# tree by default.
1370+# Minimum value: 0, maximum value: 9999, default value: 100.
1371+# This tag requires that the tag GENERATE_HTML is set to YES.
1372+
1373+HTML_INDEX_NUM_ENTRIES = 100
1374+
1375+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
1376+# generated that can be used as input for Apple's Xcode 3 integrated development
1377+# environment (see:
1378+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
1379+# create a documentation set, doxygen will generate a Makefile in the HTML
1380+# output directory. Running make will produce the docset in that directory and
1381+# running make install will install the docset in
1382+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
1383+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
1384+# genXcode/_index.html for more information.
1385+# The default value is: NO.
1386+# This tag requires that the tag GENERATE_HTML is set to YES.
1387+
1388+GENERATE_DOCSET = NO
1389+
1390+# This tag determines the name of the docset feed. A documentation feed provides
1391+# an umbrella under which multiple documentation sets from a single provider
1392+# (such as a company or product suite) can be grouped.
1393+# The default value is: Doxygen generated docs.
1394+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1395+
1396+DOCSET_FEEDNAME = "Doxygen generated docs"
1397+
1398+# This tag determines the URL of the docset feed. A documentation feed provides
1399+# an umbrella under which multiple documentation sets from a single provider
1400+# (such as a company or product suite) can be grouped.
1401+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1402+
1403+DOCSET_FEEDURL =
1404+
1405+# This tag specifies a string that should uniquely identify the documentation
1406+# set bundle. This should be a reverse domain-name style string, e.g.
1407+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
1408+# The default value is: org.doxygen.Project.
1409+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1410+
1411+DOCSET_BUNDLE_ID = org.doxygen.Project
1412+
1413+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
1414+# the documentation publisher. This should be a reverse domain-name style
1415+# string, e.g. com.mycompany.MyDocSet.documentation.
1416+# The default value is: org.doxygen.Publisher.
1417+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1418+
1419+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
1420+
1421+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
1422+# The default value is: Publisher.
1423+# This tag requires that the tag GENERATE_DOCSET is set to YES.
1424+
1425+DOCSET_PUBLISHER_NAME = Publisher
1426+
1427+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
1428+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
1429+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
1430+# on Windows. In the beginning of 2021 Microsoft took the original page, with
1431+# a.o. the download links, offline the HTML help workshop was already many years
1432+# in maintenance mode). You can download the HTML help workshop from the web
1433+# archives at Installation executable (see:
1434+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
1435+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
1436+#
1437+# The HTML Help Workshop contains a compiler that can convert all HTML output
1438+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
1439+# files are now used as the Windows 98 help format, and will replace the old
1440+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
1441+# HTML files also contain an index, a table of contents, and you can search for
1442+# words in the documentation. The HTML workshop also contains a viewer for
1443+# compressed HTML files.
1444+# The default value is: NO.
1445+# This tag requires that the tag GENERATE_HTML is set to YES.
1446+
1447+GENERATE_HTMLHELP = NO
1448+
1449+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
1450+# file. You can add a path in front of the file if the result should not be
1451+# written to the html output directory.
1452+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1453+
1454+CHM_FILE =
1455+
1456+# The HHC_LOCATION tag can be used to specify the location (absolute path
1457+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
1458+# doxygen will try to run the HTML help compiler on the generated index.hhp.
1459+# The file has to be specified with full path.
1460+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1461+
1462+HHC_LOCATION =
1463+
1464+# The GENERATE_CHI flag controls if a separate .chi index file is generated
1465+# (YES) or that it should be included in the main .chm file (NO).
1466+# The default value is: NO.
1467+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1468+
1469+GENERATE_CHI = NO
1470+
1471+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
1472+# and project file content.
1473+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1474+
1475+CHM_INDEX_ENCODING =
1476+
1477+# The BINARY_TOC flag controls whether a binary table of contents is generated
1478+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
1479+# enables the Previous and Next buttons.
1480+# The default value is: NO.
1481+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1482+
1483+BINARY_TOC = NO
1484+
1485+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
1486+# the table of contents of the HTML help documentation and to the tree view.
1487+# The default value is: NO.
1488+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1489+
1490+TOC_EXPAND = NO
1491+
1492+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
1493+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
1494+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
1495+# (.qch) of the generated HTML documentation.
1496+# The default value is: NO.
1497+# This tag requires that the tag GENERATE_HTML is set to YES.
1498+
1499+GENERATE_QHP = NO
1500+
1501+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
1502+# the file name of the resulting .qch file. The path specified is relative to
1503+# the HTML output folder.
1504+# This tag requires that the tag GENERATE_QHP is set to YES.
1505+
1506+QCH_FILE =
1507+
1508+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
1509+# Project output. For more information please see Qt Help Project / Namespace
1510+# (see:
1511+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
1512+# The default value is: org.doxygen.Project.
1513+# This tag requires that the tag GENERATE_QHP is set to YES.
1514+
1515+QHP_NAMESPACE = org.doxygen.Project
1516+
1517+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
1518+# Help Project output. For more information please see Qt Help Project / Virtual
1519+# Folders (see:
1520+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
1521+# The default value is: doc.
1522+# This tag requires that the tag GENERATE_QHP is set to YES.
1523+
1524+QHP_VIRTUAL_FOLDER = doc
1525+
1526+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
1527+# filter to add. For more information please see Qt Help Project / Custom
1528+# Filters (see:
1529+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
1530+# This tag requires that the tag GENERATE_QHP is set to YES.
1531+
1532+QHP_CUST_FILTER_NAME =
1533+
1534+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
1535+# custom filter to add. For more information please see Qt Help Project / Custom
1536+# Filters (see:
1537+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
1538+# This tag requires that the tag GENERATE_QHP is set to YES.
1539+
1540+QHP_CUST_FILTER_ATTRS =
1541+
1542+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
1543+# project's filter section matches. Qt Help Project / Filter Attributes (see:
1544+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
1545+# This tag requires that the tag GENERATE_QHP is set to YES.
1546+
1547+QHP_SECT_FILTER_ATTRS =
1548+
1549+# The QHG_LOCATION tag can be used to specify the location (absolute path
1550+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
1551+# run qhelpgenerator on the generated .qhp file.
1552+# This tag requires that the tag GENERATE_QHP is set to YES.
1553+
1554+QHG_LOCATION =
1555+
1556+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
1557+# generated, together with the HTML files, they form an Eclipse help plugin. To
1558+# install this plugin and make it available under the help contents menu in
1559+# Eclipse, the contents of the directory containing the HTML and XML files needs
1560+# to be copied into the plugins directory of eclipse. The name of the directory
1561+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
1562+# After copying Eclipse needs to be restarted before the help appears.
1563+# The default value is: NO.
1564+# This tag requires that the tag GENERATE_HTML is set to YES.
1565+
1566+GENERATE_ECLIPSEHELP = NO
1567+
1568+# A unique identifier for the Eclipse help plugin. When installing the plugin
1569+# the directory name containing the HTML and XML files should also have this
1570+# name. Each documentation set should have its own identifier.
1571+# The default value is: org.doxygen.Project.
1572+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
1573+
1574+ECLIPSE_DOC_ID = org.doxygen.Project
1575+
1576+# If you want full control over the layout of the generated HTML pages it might
1577+# be necessary to disable the index and replace it with your own. The
1578+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
1579+# of each HTML page. A value of NO enables the index and the value YES disables
1580+# it. Since the tabs in the index contain the same information as the navigation
1581+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
1582+# The default value is: NO.
1583+# This tag requires that the tag GENERATE_HTML is set to YES.
1584+
1585+DISABLE_INDEX = NO
1586+
1587+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1588+# structure should be generated to display hierarchical information. If the tag
1589+# value is set to YES, a side panel will be generated containing a tree-like
1590+# index structure (just like the one that is generated for HTML Help). For this
1591+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
1592+# (i.e. any modern browser). Windows users are probably better off using the
1593+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
1594+# further fine tune the look of the index (see "Fine-tuning the output"). As an
1595+# example, the default style sheet generated by doxygen has an example that
1596+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
1597+# Since the tree basically has the same information as the tab index, you could
1598+# consider setting DISABLE_INDEX to YES when enabling this option.
1599+# The default value is: NO.
1600+# This tag requires that the tag GENERATE_HTML is set to YES.
1601+
1602+GENERATE_TREEVIEW = NO
1603+
1604+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
1605+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
1606+# area (value NO) or if it should extend to the full height of the window (value
1607+# YES). Setting this to YES gives a layout similar to
1608+# https://docs.readthedocs.io with more room for contents, but less room for the
1609+# project logo, title, and description. If either GENERATE_TREEVIEW or
1610+# DISABLE_INDEX is set to NO, this option has no effect.
1611+# The default value is: NO.
1612+# This tag requires that the tag GENERATE_HTML is set to YES.
1613+
1614+FULL_SIDEBAR = NO
1615+
1616+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
1617+# doxygen will group on one line in the generated HTML documentation.
1618+#
1619+# Note that a value of 0 will completely suppress the enum values from appearing
1620+# in the overview section.
1621+# Minimum value: 0, maximum value: 20, default value: 4.
1622+# This tag requires that the tag GENERATE_HTML is set to YES.
1623+
1624+ENUM_VALUES_PER_LINE = 4
1625+
1626+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
1627+# to set the initial width (in pixels) of the frame in which the tree is shown.
1628+# Minimum value: 0, maximum value: 1500, default value: 250.
1629+# This tag requires that the tag GENERATE_HTML is set to YES.
1630+
1631+TREEVIEW_WIDTH = 250
1632+
1633+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
1634+# external symbols imported via tag files in a separate window.
1635+# The default value is: NO.
1636+# This tag requires that the tag GENERATE_HTML is set to YES.
1637+
1638+EXT_LINKS_IN_WINDOW = NO
1639+
1640+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
1641+# addresses.
1642+# The default value is: YES.
1643+# This tag requires that the tag GENERATE_HTML is set to YES.
1644+
1645+OBFUSCATE_EMAILS = YES
1646+
1647+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
1648+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
1649+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
1650+# the HTML output. These images will generally look nicer at scaled resolutions.
1651+# Possible values are: png (the default) and svg (looks nicer but requires the
1652+# pdf2svg or inkscape tool).
1653+# The default value is: png.
1654+# This tag requires that the tag GENERATE_HTML is set to YES.
1655+
1656+HTML_FORMULA_FORMAT = png
1657+
1658+# Use this tag to change the font size of LaTeX formulas included as images in
1659+# the HTML documentation. When you change the font size after a successful
1660+# doxygen run you need to manually remove any form_*.png images from the HTML
1661+# output directory to force them to be regenerated.
1662+# Minimum value: 8, maximum value: 50, default value: 10.
1663+# This tag requires that the tag GENERATE_HTML is set to YES.
1664+
1665+FORMULA_FONTSIZE = 10
1666+
1667+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
1668+# generated for formulas are transparent PNGs. Transparent PNGs are not
1669+# supported properly for IE 6.0, but are supported on all modern browsers.
1670+#
1671+# Note that when changing this option you need to delete any form_*.png files in
1672+# the HTML output directory before the changes have effect.
1673+# The default value is: YES.
1674+# This tag requires that the tag GENERATE_HTML is set to YES.
1675+
1676+FORMULA_TRANSPARENT = YES
1677+
1678+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
1679+# to create new LaTeX commands to be used in formulas as building blocks. See
1680+# the section "Including formulas" for details.
1681+
1682+FORMULA_MACROFILE =
1683+
1684+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1685+# https://www.mathjax.org) which uses client side JavaScript for the rendering
1686+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
1687+# installed or if you want to formulas look prettier in the HTML output. When
1688+# enabled you may also need to install MathJax separately and configure the path
1689+# to it using the MATHJAX_RELPATH option.
1690+# The default value is: NO.
1691+# This tag requires that the tag GENERATE_HTML is set to YES.
1692+
1693+USE_MATHJAX = NO
1694+
1695+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
1696+# Note that the different versions of MathJax have different requirements with
1697+# regards to the different settings, so it is possible that also other MathJax
1698+# settings have to be changed when switching between the different MathJax
1699+# versions.
1700+# Possible values are: MathJax_2 and MathJax_3.
1701+# The default value is: MathJax_2.
1702+# This tag requires that the tag USE_MATHJAX is set to YES.
1703+
1704+MATHJAX_VERSION = MathJax_2
1705+
1706+# When MathJax is enabled you can set the default output format to be used for
1707+# the MathJax output. For more details about the output format see MathJax
1708+# version 2 (see:
1709+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
1710+# (see:
1711+# http://docs.mathjax.org/en/latest/web/components/output.html).
1712+# Possible values are: HTML-CSS (which is slower, but has the best
1713+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
1714+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
1715+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
1716+# is the name for Mathjax version 3, for MathJax version 2 this will be
1717+# translated into HTML-CSS) and SVG.
1718+# The default value is: HTML-CSS.
1719+# This tag requires that the tag USE_MATHJAX is set to YES.
1720+
1721+MATHJAX_FORMAT = HTML-CSS
1722+
1723+# When MathJax is enabled you need to specify the location relative to the HTML
1724+# output directory using the MATHJAX_RELPATH option. The destination directory
1725+# should contain the MathJax.js script. For instance, if the mathjax directory
1726+# is located at the same level as the HTML output directory, then
1727+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
1728+# Content Delivery Network so you can quickly see the result without installing
1729+# MathJax. However, it is strongly recommended to install a local copy of
1730+# MathJax from https://www.mathjax.org before deployment. The default value is:
1731+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
1732+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
1733+# This tag requires that the tag USE_MATHJAX is set to YES.
1734+
1735+MATHJAX_RELPATH =
1736+
1737+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1738+# extension names that should be enabled during MathJax rendering. For example
1739+# for MathJax version 2 (see
1740+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
1741+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
1742+# For example for MathJax version 3 (see
1743+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
1744+# MATHJAX_EXTENSIONS = ams
1745+# This tag requires that the tag USE_MATHJAX is set to YES.
1746+
1747+MATHJAX_EXTENSIONS =
1748+
1749+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
1750+# of code that will be used on startup of the MathJax code. See the MathJax site
1751+# (see:
1752+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
1753+# example see the documentation.
1754+# This tag requires that the tag USE_MATHJAX is set to YES.
1755+
1756+MATHJAX_CODEFILE =
1757+
1758+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
1759+# the HTML output. The underlying search engine uses javascript and DHTML and
1760+# should work on any modern browser. Note that when using HTML help
1761+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
1762+# there is already a search function so this one should typically be disabled.
1763+# For large projects the javascript based search engine can be slow, then
1764+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
1765+# search using the keyboard; to jump to the search box use <access key> + S
1766+# (what the <access key> is depends on the OS and browser, but it is typically
1767+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
1768+# key> to jump into the search results window, the results can be navigated
1769+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
1770+# the search. The filter options can be selected when the cursor is inside the
1771+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
1772+# to select a filter and <Enter> or <escape> to activate or cancel the filter
1773+# option.
1774+# The default value is: YES.
1775+# This tag requires that the tag GENERATE_HTML is set to YES.
1776+
1777+SEARCHENGINE = YES
1778+
1779+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
1780+# implemented using a web server instead of a web client using JavaScript. There
1781+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
1782+# setting. When disabled, doxygen will generate a PHP script for searching and
1783+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
1784+# and searching needs to be provided by external tools. See the section
1785+# "External Indexing and Searching" for details.
1786+# The default value is: NO.
1787+# This tag requires that the tag SEARCHENGINE is set to YES.
1788+
1789+SERVER_BASED_SEARCH = NO
1790+
1791+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
1792+# script for searching. Instead the search results are written to an XML file
1793+# which needs to be processed by an external indexer. Doxygen will invoke an
1794+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1795+# search results.
1796+#
1797+# Doxygen ships with an example indexer (doxyindexer) and search engine
1798+# (doxysearch.cgi) which are based on the open source search engine library
1799+# Xapian (see:
1800+# https://xapian.org/).
1801+#
1802+# See the section "External Indexing and Searching" for details.
1803+# The default value is: NO.
1804+# This tag requires that the tag SEARCHENGINE is set to YES.
1805+
1806+EXTERNAL_SEARCH = NO
1807+
1808+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
1809+# which will return the search results when EXTERNAL_SEARCH is enabled.
1810+#
1811+# Doxygen ships with an example indexer (doxyindexer) and search engine
1812+# (doxysearch.cgi) which are based on the open source search engine library
1813+# Xapian (see:
1814+# https://xapian.org/). See the section "External Indexing and Searching" for
1815+# details.
1816+# This tag requires that the tag SEARCHENGINE is set to YES.
1817+
1818+SEARCHENGINE_URL =
1819+
1820+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
1821+# search data is written to a file for indexing by an external tool. With the
1822+# SEARCHDATA_FILE tag the name of this file can be specified.
1823+# The default file is: searchdata.xml.
1824+# This tag requires that the tag SEARCHENGINE is set to YES.
1825+
1826+SEARCHDATA_FILE = searchdata.xml
1827+
1828+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
1829+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
1830+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
1831+# projects and redirect the results back to the right project.
1832+# This tag requires that the tag SEARCHENGINE is set to YES.
1833+
1834+EXTERNAL_SEARCH_ID =
1835+
1836+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
1837+# projects other than the one defined by this configuration file, but that are
1838+# all added to the same external search index. Each project needs to have a
1839+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
1840+# to a relative location where the documentation can be found. The format is:
1841+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
1842+# This tag requires that the tag SEARCHENGINE is set to YES.
1843+
1844+EXTRA_SEARCH_MAPPINGS =
1845+
1846+#---------------------------------------------------------------------------
1847+# Configuration options related to the LaTeX output
1848+#---------------------------------------------------------------------------
1849+
1850+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
1851+# The default value is: YES.
1852+
1853+GENERATE_LATEX = NO
1854+
1855+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
1856+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1857+# it.
1858+# The default directory is: latex.
1859+# This tag requires that the tag GENERATE_LATEX is set to YES.
1860+
1861+LATEX_OUTPUT = latex
1862+
1863+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1864+# invoked.
1865+#
1866+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
1867+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
1868+# chosen this is overwritten by pdflatex. For specific output languages the
1869+# default can have been set differently, this depends on the implementation of
1870+# the output language.
1871+# This tag requires that the tag GENERATE_LATEX is set to YES.
1872+
1873+LATEX_CMD_NAME =
1874+
1875+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
1876+# index for LaTeX.
1877+# Note: This tag is used in the Makefile / make.bat.
1878+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
1879+# (.tex).
1880+# The default file is: makeindex.
1881+# This tag requires that the tag GENERATE_LATEX is set to YES.
1882+
1883+MAKEINDEX_CMD_NAME = makeindex
1884+
1885+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
1886+# generate index for LaTeX. In case there is no backslash (\) as first character
1887+# it will be automatically added in the LaTeX code.
1888+# Note: This tag is used in the generated output file (.tex).
1889+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
1890+# The default value is: makeindex.
1891+# This tag requires that the tag GENERATE_LATEX is set to YES.
1892+
1893+LATEX_MAKEINDEX_CMD = makeindex
1894+
1895+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
1896+# documents. This may be useful for small projects and may help to save some
1897+# trees in general.
1898+# The default value is: NO.
1899+# This tag requires that the tag GENERATE_LATEX is set to YES.
1900+
1901+COMPACT_LATEX = NO
1902+
1903+# The PAPER_TYPE tag can be used to set the paper type that is used by the
1904+# printer.
1905+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
1906+# 14 inches) and executive (7.25 x 10.5 inches).
1907+# The default value is: a4.
1908+# This tag requires that the tag GENERATE_LATEX is set to YES.
1909+
1910+PAPER_TYPE = a4
1911+
1912+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1913+# that should be included in the LaTeX output. The package can be specified just
1914+# by its name or with the correct syntax as to be used with the LaTeX
1915+# \usepackage command. To get the times font for instance you can specify :
1916+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
1917+# To use the option intlimits with the amsmath package you can specify:
1918+# EXTRA_PACKAGES=[intlimits]{amsmath}
1919+# If left blank no extra packages will be included.
1920+# This tag requires that the tag GENERATE_LATEX is set to YES.
1921+
1922+EXTRA_PACKAGES =
1923+
1924+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
1925+# the generated LaTeX document. The header should contain everything until the
1926+# first chapter. If it is left blank doxygen will generate a standard header. It
1927+# is highly recommended to start with a default header using
1928+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
1929+# and then modify the file new_header.tex. See also section "Doxygen usage" for
1930+# information on how to generate the default header that doxygen normally uses.
1931+#
1932+# Note: Only use a user-defined header if you know what you are doing!
1933+# Note: The header is subject to change so you typically have to regenerate the
1934+# default header when upgrading to a newer version of doxygen. The following
1935+# commands have a special meaning inside the header (and footer): For a
1936+# description of the possible markers and block names see the documentation.
1937+# This tag requires that the tag GENERATE_LATEX is set to YES.
1938+
1939+LATEX_HEADER =
1940+
1941+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
1942+# the generated LaTeX document. The footer should contain everything after the
1943+# last chapter. If it is left blank doxygen will generate a standard footer. See
1944+# LATEX_HEADER for more information on how to generate a default footer and what
1945+# special commands can be used inside the footer. See also section "Doxygen
1946+# usage" for information on how to generate the default footer that doxygen
1947+# normally uses. Note: Only use a user-defined footer if you know what you are
1948+# doing!
1949+# This tag requires that the tag GENERATE_LATEX is set to YES.
1950+
1951+LATEX_FOOTER =
1952+
1953+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1954+# LaTeX style sheets that are included after the standard style sheets created
1955+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
1956+# will copy the style sheet files to the output directory.
1957+# Note: The order of the extra style sheet files is of importance (e.g. the last
1958+# style sheet in the list overrules the setting of the previous ones in the
1959+# list).
1960+# This tag requires that the tag GENERATE_LATEX is set to YES.
1961+
1962+LATEX_EXTRA_STYLESHEET =
1963+
1964+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1965+# other source files which should be copied to the LATEX_OUTPUT output
1966+# directory. Note that the files will be copied as-is; there are no commands or
1967+# markers available.
1968+# This tag requires that the tag GENERATE_LATEX is set to YES.
1969+
1970+LATEX_EXTRA_FILES =
1971+
1972+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
1973+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
1974+# contain links (just like the HTML output) instead of page references. This
1975+# makes the output suitable for online browsing using a PDF viewer.
1976+# The default value is: YES.
1977+# This tag requires that the tag GENERATE_LATEX is set to YES.
1978+
1979+PDF_HYPERLINKS = YES
1980+
1981+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
1982+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
1983+# files. Set this option to YES, to get a higher quality PDF documentation.
1984+#
1985+# See also section LATEX_CMD_NAME for selecting the engine.
1986+# The default value is: YES.
1987+# This tag requires that the tag GENERATE_LATEX is set to YES.
1988+
1989+USE_PDFLATEX = YES
1990+
1991+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
1992+# command to the generated LaTeX files. This will instruct LaTeX to keep running
1993+# if errors occur, instead of asking the user for help.
1994+# The default value is: NO.
1995+# This tag requires that the tag GENERATE_LATEX is set to YES.
1996+
1997+LATEX_BATCHMODE = NO
1998+
1999+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
2000+# index chapters (such as File Index, Compound Index, etc.) in the output.
2001+# The default value is: NO.
2002+# This tag requires that the tag GENERATE_LATEX is set to YES.
2003+
2004+LATEX_HIDE_INDICES = NO
2005+
2006+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
2007+# bibliography, e.g. plainnat, or ieeetr. See
2008+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
2009+# The default value is: plain.
2010+# This tag requires that the tag GENERATE_LATEX is set to YES.
2011+
2012+LATEX_BIB_STYLE = plain
2013+
2014+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
2015+# page will contain the date and time when the page was generated. Setting this
2016+# to NO can help when comparing the output of multiple runs.
2017+# The default value is: NO.
2018+# This tag requires that the tag GENERATE_LATEX is set to YES.
2019+
2020+LATEX_TIMESTAMP = NO
2021+
2022+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
2023+# path from which the emoji images will be read. If a relative path is entered,
2024+# it will be relative to the LATEX_OUTPUT directory. If left blank the
2025+# LATEX_OUTPUT directory will be used.
2026+# This tag requires that the tag GENERATE_LATEX is set to YES.
2027+
2028+LATEX_EMOJI_DIRECTORY =
2029+
2030+#---------------------------------------------------------------------------
2031+# Configuration options related to the RTF output
2032+#---------------------------------------------------------------------------
2033+
2034+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
2035+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
2036+# readers/editors.
2037+# The default value is: NO.
2038+
2039+GENERATE_RTF = NO
2040+
2041+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
2042+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
2043+# it.
2044+# The default directory is: rtf.
2045+# This tag requires that the tag GENERATE_RTF is set to YES.
2046+
2047+RTF_OUTPUT = rtf
2048+
2049+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
2050+# documents. This may be useful for small projects and may help to save some
2051+# trees in general.
2052+# The default value is: NO.
2053+# This tag requires that the tag GENERATE_RTF is set to YES.
2054+
2055+COMPACT_RTF = NO
2056+
2057+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
2058+# contain hyperlink fields. The RTF file will contain links (just like the HTML
2059+# output) instead of page references. This makes the output suitable for online
2060+# browsing using Word or some other Word compatible readers that support those
2061+# fields.
2062+#
2063+# Note: WordPad (write) and others do not support links.
2064+# The default value is: NO.
2065+# This tag requires that the tag GENERATE_RTF is set to YES.
2066+
2067+RTF_HYPERLINKS = NO
2068+
2069+# Load stylesheet definitions from file. Syntax is similar to doxygen's
2070+# configuration file, i.e. a series of assignments. You only have to provide
2071+# replacements, missing definitions are set to their default value.
2072+#
2073+# See also section "Doxygen usage" for information on how to generate the
2074+# default style sheet that doxygen normally uses.
2075+# This tag requires that the tag GENERATE_RTF is set to YES.
2076+
2077+RTF_STYLESHEET_FILE =
2078+
2079+# Set optional variables used in the generation of an RTF document. Syntax is
2080+# similar to doxygen's configuration file. A template extensions file can be
2081+# generated using doxygen -e rtf extensionFile.
2082+# This tag requires that the tag GENERATE_RTF is set to YES.
2083+
2084+RTF_EXTENSIONS_FILE =
2085+
2086+#---------------------------------------------------------------------------
2087+# Configuration options related to the man page output
2088+#---------------------------------------------------------------------------
2089+
2090+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
2091+# classes and files.
2092+# The default value is: NO.
2093+
2094+GENERATE_MAN = NO
2095+
2096+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
2097+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
2098+# it. A directory man3 will be created inside the directory specified by
2099+# MAN_OUTPUT.
2100+# The default directory is: man.
2101+# This tag requires that the tag GENERATE_MAN is set to YES.
2102+
2103+MAN_OUTPUT = man
2104+
2105+# The MAN_EXTENSION tag determines the extension that is added to the generated
2106+# man pages. In case the manual section does not start with a number, the number
2107+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
2108+# optional.
2109+# The default value is: .3.
2110+# This tag requires that the tag GENERATE_MAN is set to YES.
2111+
2112+MAN_EXTENSION = .3
2113+
2114+# The MAN_SUBDIR tag determines the name of the directory created within
2115+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
2116+# MAN_EXTENSION with the initial . removed.
2117+# This tag requires that the tag GENERATE_MAN is set to YES.
2118+
2119+MAN_SUBDIR =
2120+
2121+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
2122+# will generate one additional man file for each entity documented in the real
2123+# man page(s). These additional files only source the real man page, but without
2124+# them the man command would be unable to find the correct page.
2125+# The default value is: NO.
2126+# This tag requires that the tag GENERATE_MAN is set to YES.
2127+
2128+MAN_LINKS = NO
2129+
2130+#---------------------------------------------------------------------------
2131+# Configuration options related to the XML output
2132+#---------------------------------------------------------------------------
2133+
2134+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
2135+# captures the structure of the code including all documentation.
2136+# The default value is: NO.
2137+
2138+GENERATE_XML = YES
2139+
2140+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
2141+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
2142+# it.
2143+# The default directory is: xml.
2144+# This tag requires that the tag GENERATE_XML is set to YES.
2145+
2146+XML_OUTPUT = doxyxml
2147+
2148+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
2149+# listings (including syntax highlighting and cross-referencing information) to
2150+# the XML output. Note that enabling this will significantly increase the size
2151+# of the XML output.
2152+# The default value is: YES.
2153+# This tag requires that the tag GENERATE_XML is set to YES.
2154+
2155+XML_PROGRAMLISTING = YES
2156+
2157+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
2158+# namespace members in file scope as well, matching the HTML output.
2159+# The default value is: NO.
2160+# This tag requires that the tag GENERATE_XML is set to YES.
2161+
2162+XML_NS_MEMB_FILE_SCOPE = NO
2163+
2164+#---------------------------------------------------------------------------
2165+# Configuration options related to the DOCBOOK output
2166+#---------------------------------------------------------------------------
2167+
2168+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
2169+# that can be used to generate PDF.
2170+# The default value is: NO.
2171+
2172+GENERATE_DOCBOOK = NO
2173+
2174+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
2175+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
2176+# front of it.
2177+# The default directory is: docbook.
2178+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
2179+
2180+DOCBOOK_OUTPUT = docbook
2181+
2182+#---------------------------------------------------------------------------
2183+# Configuration options for the AutoGen Definitions output
2184+#---------------------------------------------------------------------------
2185+
2186+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
2187+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
2188+# the structure of the code including all documentation. Note that this feature
2189+# is still experimental and incomplete at the moment.
2190+# The default value is: NO.
2191+
2192+GENERATE_AUTOGEN_DEF = NO
2193+
2194+#---------------------------------------------------------------------------
2195+# Configuration options related to the Perl module output
2196+#---------------------------------------------------------------------------
2197+
2198+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
2199+# file that captures the structure of the code including all documentation.
2200+#
2201+# Note that this feature is still experimental and incomplete at the moment.
2202+# The default value is: NO.
2203+
2204+GENERATE_PERLMOD = NO
2205+
2206+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
2207+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
2208+# output from the Perl module output.
2209+# The default value is: NO.
2210+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
2211+
2212+PERLMOD_LATEX = NO
2213+
2214+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
2215+# formatted so it can be parsed by a human reader. This is useful if you want to
2216+# understand what is going on. On the other hand, if this tag is set to NO, the
2217+# size of the Perl module output will be much smaller and Perl will parse it
2218+# just the same.
2219+# The default value is: YES.
2220+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
2221+
2222+PERLMOD_PRETTY = YES
2223+
2224+# The names of the make variables in the generated doxyrules.make file are
2225+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
2226+# so different doxyrules.make files included by the same Makefile don't
2227+# overwrite each other's variables.
2228+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
2229+
2230+PERLMOD_MAKEVAR_PREFIX =
2231+
2232+#---------------------------------------------------------------------------
2233+# Configuration options related to the preprocessor
2234+#---------------------------------------------------------------------------
2235+
2236+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
2237+# C-preprocessor directives found in the sources and include files.
2238+# The default value is: YES.
2239+
2240+ENABLE_PREPROCESSING = YES
2241+
2242+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
2243+# in the source code. If set to NO, only conditional compilation will be
2244+# performed. Macro expansion can be done in a controlled way by setting
2245+# EXPAND_ONLY_PREDEF to YES.
2246+# The default value is: NO.
2247+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2248+
2249+MACRO_EXPANSION = NO
2250+
2251+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
2252+# the macro expansion is limited to the macros specified with the PREDEFINED and
2253+# EXPAND_AS_DEFINED tags.
2254+# The default value is: NO.
2255+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2256+
2257+EXPAND_ONLY_PREDEF = NO
2258+
2259+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
2260+# INCLUDE_PATH will be searched if a #include is found.
2261+# The default value is: YES.
2262+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2263+
2264+SEARCH_INCLUDES = YES
2265+
2266+# The INCLUDE_PATH tag can be used to specify one or more directories that
2267+# contain include files that are not input files but should be processed by the
2268+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
2269+# RECURSIVE has no effect here.
2270+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
2271+
2272+INCLUDE_PATH =
2273+
2274+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
2275+# patterns (like *.h and *.hpp) to filter out the header-files in the
2276+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
2277+# used.
2278+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2279+
2280+INCLUDE_FILE_PATTERNS =
2281+
2282+# The PREDEFINED tag can be used to specify one or more macro names that are
2283+# defined before the preprocessor is started (similar to the -D option of e.g.
2284+# gcc). The argument of the tag is a list of macros of the form: name or
2285+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
2286+# is assumed. To prevent a macro definition from being undefined via #undef or
2287+# recursively expanded use the := operator instead of the = operator.
2288+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2289+
2290+PREDEFINED =
2291+
2292+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
2293+# tag can be used to specify a list of macro names that should be expanded. The
2294+# macro definition that is found in the sources will be used. Use the PREDEFINED
2295+# tag if you want to use a different macro definition that overrules the
2296+# definition found in the source code.
2297+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2298+
2299+EXPAND_AS_DEFINED =
2300+
2301+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
2302+# remove all references to function-like macros that are alone on a line, have
2303+# an all uppercase name, and do not end with a semicolon. Such function macros
2304+# are typically used for boiler-plate code, and will confuse the parser if not
2305+# removed.
2306+# The default value is: YES.
2307+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2308+
2309+SKIP_FUNCTION_MACROS = YES
2310+
2311+#---------------------------------------------------------------------------
2312+# Configuration options related to external references
2313+#---------------------------------------------------------------------------
2314+
2315+# The TAGFILES tag can be used to specify one or more tag files. For each tag
2316+# file the location of the external documentation should be added. The format of
2317+# a tag file without this location is as follows:
2318+# TAGFILES = file1 file2 ...
2319+# Adding location for the tag files is done as follows:
2320+# TAGFILES = file1=loc1 "file2 = loc2" ...
2321+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
2322+# section "Linking to external documentation" for more information about the use
2323+# of tag files.
2324+# Note: Each tag file must have a unique name (where the name does NOT include
2325+# the path). If a tag file is not located in the directory in which doxygen is
2326+# run, you must also specify the path to the tagfile here.
2327+
2328+TAGFILES =
2329+
2330+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
2331+# tag file that is based on the input files it reads. See section "Linking to
2332+# external documentation" for more information about the usage of tag files.
2333+
2334+GENERATE_TAGFILE =
2335+
2336+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
2337+# the class index. If set to NO, only the inherited external classes will be
2338+# listed.
2339+# The default value is: NO.
2340+
2341+ALLEXTERNALS = NO
2342+
2343+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
2344+# in the modules index. If set to NO, only the current project's groups will be
2345+# listed.
2346+# The default value is: YES.
2347+
2348+EXTERNAL_GROUPS = YES
2349+
2350+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
2351+# the related pages index. If set to NO, only the current project's pages will
2352+# be listed.
2353+# The default value is: YES.
2354+
2355+EXTERNAL_PAGES = YES
2356+
2357+#---------------------------------------------------------------------------
2358+# Configuration options related to the dot tool
2359+#---------------------------------------------------------------------------
2360+
2361+# You can include diagrams made with dia in doxygen documentation. Doxygen will
2362+# then run dia to produce the diagram and insert it in the documentation. The
2363+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
2364+# If left empty dia is assumed to be found in the default search path.
2365+
2366+DIA_PATH =
2367+
2368+# If set to YES the inheritance and collaboration graphs will hide inheritance
2369+# and usage relations if the target is undocumented or is not a class.
2370+# The default value is: YES.
2371+
2372+HIDE_UNDOC_RELATIONS = YES
2373+
2374+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
2375+# available from the path. This tool is part of Graphviz (see:
2376+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
2377+# Bell Labs. The other options in this section have no effect if this option is
2378+# set to NO
2379+# The default value is: YES.
2380+
2381+HAVE_DOT = YES
2382+
2383+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
2384+# to run in parallel. When set to 0 doxygen will base this on the number of
2385+# processors available in the system. You can set it explicitly to a value
2386+# larger than 0 to get control over the balance between CPU load and processing
2387+# speed.
2388+# Minimum value: 0, maximum value: 32, default value: 0.
2389+# This tag requires that the tag HAVE_DOT is set to YES.
2390+
2391+DOT_NUM_THREADS = 0
2392+
2393+# When you want a differently looking font in the dot files that doxygen
2394+# generates you can specify the font name using DOT_FONTNAME. You need to make
2395+# sure dot is able to find the font, which can be done by putting it in a
2396+# standard location or by setting the DOTFONTPATH environment variable or by
2397+# setting DOT_FONTPATH to the directory containing the font.
2398+# The default value is: Helvetica.
2399+# This tag requires that the tag HAVE_DOT is set to YES.
2400+
2401+DOT_FONTNAME = Helvetica
2402+
2403+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
2404+# dot graphs.
2405+# Minimum value: 4, maximum value: 24, default value: 10.
2406+# This tag requires that the tag HAVE_DOT is set to YES.
2407+
2408+DOT_FONTSIZE = 10
2409+
2410+# By default doxygen will tell dot to use the default font as specified with
2411+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
2412+# the path where dot can find it using this tag.
2413+# This tag requires that the tag HAVE_DOT is set to YES.
2414+
2415+DOT_FONTPATH =
2416+
2417+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
2418+# graph for each documented class showing the direct and indirect inheritance
2419+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
2420+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
2421+# to TEXT the direct and indirect inheritance relations will be shown as texts /
2422+# links.
2423+# Possible values are: NO, YES, TEXT and GRAPH.
2424+# The default value is: YES.
2425+
2426+CLASS_GRAPH = YES
2427+
2428+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
2429+# graph for each documented class showing the direct and indirect implementation
2430+# dependencies (inheritance, containment, and class references variables) of the
2431+# class with other documented classes.
2432+# The default value is: YES.
2433+# This tag requires that the tag HAVE_DOT is set to YES.
2434+
2435+COLLABORATION_GRAPH = YES
2436+
2437+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
2438+# groups, showing the direct groups dependencies. See also the chapter Grouping
2439+# in the manual.
2440+# The default value is: YES.
2441+# This tag requires that the tag HAVE_DOT is set to YES.
2442+
2443+GROUP_GRAPHS = YES
2444+
2445+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
2446+# collaboration diagrams in a style similar to the OMG's Unified Modeling
2447+# Language.
2448+# The default value is: NO.
2449+# This tag requires that the tag HAVE_DOT is set to YES.
2450+
2451+UML_LOOK = NO
2452+
2453+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
2454+# class node. If there are many fields or methods and many nodes the graph may
2455+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
2456+# number of items for each type to make the size more manageable. Set this to 0
2457+# for no limit. Note that the threshold may be exceeded by 50% before the limit
2458+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
2459+# but if the number exceeds 15, the total amount of fields shown is limited to
2460+# 10.
2461+# Minimum value: 0, maximum value: 100, default value: 10.
2462+# This tag requires that the tag UML_LOOK is set to YES.
2463+
2464+UML_LIMIT_NUM_FIELDS = 10
2465+
2466+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
2467+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
2468+# tag is set to YES, doxygen will add type and arguments for attributes and
2469+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
2470+# will not generate fields with class member information in the UML graphs. The
2471+# class diagrams will look similar to the default class diagrams but using UML
2472+# notation for the relationships.
2473+# Possible values are: NO, YES and NONE.
2474+# The default value is: NO.
2475+# This tag requires that the tag UML_LOOK is set to YES.
2476+
2477+DOT_UML_DETAILS = NO
2478+
2479+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
2480+# to display on a single line. If the actual line length exceeds this threshold
2481+# significantly it will wrapped across multiple lines. Some heuristics are apply
2482+# to avoid ugly line breaks.
2483+# Minimum value: 0, maximum value: 1000, default value: 17.
2484+# This tag requires that the tag HAVE_DOT is set to YES.
2485+
2486+DOT_WRAP_THRESHOLD = 17
2487+
2488+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
2489+# collaboration graphs will show the relations between templates and their
2490+# instances.
2491+# The default value is: NO.
2492+# This tag requires that the tag HAVE_DOT is set to YES.
2493+
2494+TEMPLATE_RELATIONS = NO
2495+
2496+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
2497+# YES then doxygen will generate a graph for each documented file showing the
2498+# direct and indirect include dependencies of the file with other documented
2499+# files.
2500+# The default value is: YES.
2501+# This tag requires that the tag HAVE_DOT is set to YES.
2502+
2503+INCLUDE_GRAPH = YES
2504+
2505+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
2506+# set to YES then doxygen will generate a graph for each documented file showing
2507+# the direct and indirect include dependencies of the file with other documented
2508+# files.
2509+# The default value is: YES.
2510+# This tag requires that the tag HAVE_DOT is set to YES.
2511+
2512+INCLUDED_BY_GRAPH = YES
2513+
2514+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
2515+# dependency graph for every global function or class method.
2516+#
2517+# Note that enabling this option will significantly increase the time of a run.
2518+# So in most cases it will be better to enable call graphs for selected
2519+# functions only using the \callgraph command. Disabling a call graph can be
2520+# accomplished by means of the command \hidecallgraph.
2521+# The default value is: NO.
2522+# This tag requires that the tag HAVE_DOT is set to YES.
2523+
2524+CALL_GRAPH = NO
2525+
2526+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
2527+# dependency graph for every global function or class method.
2528+#
2529+# Note that enabling this option will significantly increase the time of a run.
2530+# So in most cases it will be better to enable caller graphs for selected
2531+# functions only using the \callergraph command. Disabling a caller graph can be
2532+# accomplished by means of the command \hidecallergraph.
2533+# The default value is: NO.
2534+# This tag requires that the tag HAVE_DOT is set to YES.
2535+
2536+CALLER_GRAPH = NO
2537+
2538+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
2539+# hierarchy of all classes instead of a textual one.
2540+# The default value is: YES.
2541+# This tag requires that the tag HAVE_DOT is set to YES.
2542+
2543+GRAPHICAL_HIERARCHY = YES
2544+
2545+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
2546+# dependencies a directory has on other directories in a graphical way. The
2547+# dependency relations are determined by the #include relations between the
2548+# files in the directories.
2549+# The default value is: YES.
2550+# This tag requires that the tag HAVE_DOT is set to YES.
2551+
2552+DIRECTORY_GRAPH = YES
2553+
2554+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
2555+# of child directories generated in directory dependency graphs by dot.
2556+# Minimum value: 1, maximum value: 25, default value: 1.
2557+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
2558+
2559+DIR_GRAPH_MAX_DEPTH = 1
2560+
2561+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
2562+# generated by dot. For an explanation of the image formats see the section
2563+# output formats in the documentation of the dot tool (Graphviz (see:
2564+# http://www.graphviz.org/)).
2565+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2566+# to make the SVG files visible in IE 9+ (other browsers do not have this
2567+# requirement).
2568+# Possible values are: png, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd,
2569+# gif, gif:cairo, gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd,
2570+# png:cairo, png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
2571+# png:gdiplus:gdiplus.
2572+# The default value is: png.
2573+# This tag requires that the tag HAVE_DOT is set to YES.
2574+
2575+DOT_IMAGE_FORMAT = png
2576+
2577+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
2578+# enable generation of interactive SVG images that allow zooming and panning.
2579+#
2580+# Note that this requires a modern browser other than Internet Explorer. Tested
2581+# and working are Firefox, Chrome, Safari, and Opera.
2582+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
2583+# the SVG files visible. Older versions of IE do not have SVG support.
2584+# The default value is: NO.
2585+# This tag requires that the tag HAVE_DOT is set to YES.
2586+
2587+INTERACTIVE_SVG = NO
2588+
2589+# The DOT_PATH tag can be used to specify the path where the dot tool can be
2590+# found. If left blank, it is assumed the dot tool can be found in the path.
2591+# This tag requires that the tag HAVE_DOT is set to YES.
2592+
2593+DOT_PATH =
2594+
2595+# The DOTFILE_DIRS tag can be used to specify one or more directories that
2596+# contain dot files that are included in the documentation (see the \dotfile
2597+# command).
2598+# This tag requires that the tag HAVE_DOT is set to YES.
2599+
2600+DOTFILE_DIRS =
2601+
2602+# The MSCFILE_DIRS tag can be used to specify one or more directories that
2603+# contain msc files that are included in the documentation (see the \mscfile
2604+# command).
2605+
2606+MSCFILE_DIRS =
2607+
2608+# The DIAFILE_DIRS tag can be used to specify one or more directories that
2609+# contain dia files that are included in the documentation (see the \diafile
2610+# command).
2611+
2612+DIAFILE_DIRS =
2613+
2614+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
2615+# path where java can find the plantuml.jar file or to the filename of jar file
2616+# to be used. If left blank, it is assumed PlantUML is not used or called during
2617+# a preprocessing step. Doxygen will generate a warning when it encounters a
2618+# \startuml command in this case and will not generate output for the diagram.
2619+
2620+PLANTUML_JAR_PATH =
2621+
2622+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
2623+# configuration file for plantuml.
2624+
2625+PLANTUML_CFG_FILE =
2626+
2627+# When using plantuml, the specified paths are searched for files specified by
2628+# the !include statement in a plantuml block.
2629+
2630+PLANTUML_INCLUDE_PATH =
2631+
2632+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2633+# that will be shown in the graph. If the number of nodes in a graph becomes
2634+# larger than this value, doxygen will truncate the graph, which is visualized
2635+# by representing a node as a red box. Note that doxygen if the number of direct
2636+# children of the root node in a graph is already larger than
2637+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
2638+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2639+# Minimum value: 0, maximum value: 10000, default value: 50.
2640+# This tag requires that the tag HAVE_DOT is set to YES.
2641+
2642+DOT_GRAPH_MAX_NODES = 50
2643+
2644+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
2645+# generated by dot. A depth value of 3 means that only nodes reachable from the
2646+# root by following a path via at most 3 edges will be shown. Nodes that lay
2647+# further from the root node will be omitted. Note that setting this option to 1
2648+# or 2 may greatly reduce the computation time needed for large code bases. Also
2649+# note that the size of a graph can be further restricted by
2650+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
2651+# Minimum value: 0, maximum value: 1000, default value: 0.
2652+# This tag requires that the tag HAVE_DOT is set to YES.
2653+
2654+MAX_DOT_GRAPH_DEPTH = 0
2655+
2656+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
2657+# background. This is disabled by default, because dot on Windows does not seem
2658+# to support this out of the box.
2659+#
2660+# Warning: Depending on the platform used, enabling this option may lead to
2661+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
2662+# read).
2663+# The default value is: NO.
2664+# This tag requires that the tag HAVE_DOT is set to YES.
2665+
2666+DOT_TRANSPARENT = NO
2667+
2668+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
2669+# files in one run (i.e. multiple -o and -T options on the command line). This
2670+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
2671+# this, this feature is disabled by default.
2672+# The default value is: NO.
2673+# This tag requires that the tag HAVE_DOT is set to YES.
2674+
2675+DOT_MULTI_TARGETS = NO
2676+
2677+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
2678+# explaining the meaning of the various boxes and arrows in the dot generated
2679+# graphs.
2680+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
2681+# graphical representation for inheritance and collaboration diagrams is used.
2682+# The default value is: YES.
2683+# This tag requires that the tag HAVE_DOT is set to YES.
2684+
2685+GENERATE_LEGEND = YES
2686+
2687+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
2688+# files that are used to generate the various graphs.
2689+#
2690+# Note: This setting is not only used for dot files but also for msc temporary
2691+# files.
2692+# The default value is: YES.
2693+
2694+DOT_CLEANUP = YES
2695diff --git a/debian/changelog b/debian/changelog
2696index 6774ec3..180b2d4 100644
2697--- a/debian/changelog
2698+++ b/debian/changelog
2699@@ -1,3 +1,72 @@
2700+netplan.io (0.107.1-3ubuntu0.23.10.1) mantic; urgency=medium
2701+
2702+ * Backport netplan.io 0.107.1-3 to 23.10 (LP: #2058051):
2703+ - wifi: add support for WPA3-Enterprise (LP: #2029876) (!402)
2704+ - wifi: support WPA2 and WPA3 Personal simultaneously (!404)
2705+ - added mii-monitor-interval example (!411)
2706+ - docs: Add "Contribute Documentation" how-to
2707+ - auth: add support for LEAP and EAP-PWD (!415)
2708+ - tests: Add autopkgtest for (LP: #1959570) (!419)
2709+ - wifi: make it possible to have a psk and an eap password simultaneously
2710+ (!416)
2711+ - doc: Set-up some basic Doxygen project (!423)
2712+ - doc: Make Sphinx to handle autodoxygen project, using breathe (!423)
2713+ - doc: create libnetplan apidoc structure (!423)
2714+ - inc: Start documenting public API (!423)
2715+ - doc: Update 'Netplan everywhere' for 23.10 (!418)
2716+ Bug fixes:
2717+ - test:ovs: Avoid NetworkManager taking contol, breaking a test
2718+ - parse: allow COMMON_LINK_HANDLERS for VRFs (!401)
2719+ - util: don't return a placeholder netdef in the iterator (!406)
2720+ - tunnels/validation: do not error out if "local" is not defined (!407)
2721+ - tests: add some integration tests without the local address (!407)
2722+ - wireguard: ignore empty endpoints (LP: #2038811) (!414)
2723+ - parse: improve the parsing of access-points (LP: #1809994) (!413)
2724+ - wifi: replace the previously defined AP with the new one (!413)
2725+ - doc: spelling check improvements (!417)
2726+ - Fix permissions on folder '/run/NetworkManager/' (!422)
2727+ - cli:try: avoid linting error for type hints (Closes: #1058524) (!422)
2728+ - nm-parse: always read the PSK into the new psk variable (!416)
2729+ - networkd: fix formatting (!424)
2730+ - networkd: replace deprecated CriticalConnection= by KeepConfiguration=
2731+ (!424)
2732+ - networkd: move KeepConfiguration= into [Network] section
2733+ - apply: bring "lo" back up if it's managed by NM (!408)
2734+ - apply: don't assume the NM loopback connection is called "lo" (!408)
2735+ * Drop patches merged upstream:
2736+ - lp1809994/0010-parse-improve-the-parsing-of-access-points-LP-180999.patch
2737+ - lp1809994/0011-wifi-replace-the-previously-defined-AP-with-the-new-.patch
2738+ - lp2039821/0008-wireguard-ignore-empty-endpoints.patch
2739+ - lp2039825/0009-auth-add-support-for-LEAP-and-EAP-PWD.patch
2740+ * Add patches for bug fixes from netplan.io 1.0-1:
2741+ - lp2041727/0004-cli-utils-introduce-systemctl_is_installed-helper.patch
2742+ cli:utils: introduce systemctl_is_installed helper (LP: #2041727) (!421)
2743+ - lp2041727/0005-Update-ovs.py-to-check-if-ovsdb-server.service-is-in.patch
2744+ Check if ovsdb-server.service is active before displaying warning
2745+ (LP: #2041727) (!421)
2746+ - d/p/0007-tests-assert-generated-.service-files-in-assert_srio.patch,
2747+ d/p/0008-tests-sriov-test-if-the-generated-netplan-rebind-ser.patch,
2748+ d/p/0009-sriov-don-t-generate-duplicate-entries-in-the-rebind.patch:
2749+ Don't generate duplicate entries in the netplan-sriov-rebind.service
2750+ (!437)
2751+ * Drop patches not required for 23.10:
2752+ - debian/patches/python-limited-stable-api.patch
2753+ * debian/netplan.io.preinst:
2754+ - This preinst script is intended to cleanup the .pyc files from
2755+ share/netplan/netplan. This directory is supposed to be removed after
2756+ the upgrade from netplan.io 0.106.1 to 0.107, as the Python code
2757+ was moved to it's own python3-netplan package, but it's left behind
2758+ due to Python cached files.
2759+ * Drop changes related to usr-merge and not required for 23.10:
2760+ - debian/netplan-generator.dirs
2761+ - debian/netplan-generator.install
2762+ - debian/netplan-generator.postinst
2763+ - debian/netplan-generator.preinst
2764+ * debian/netplan-generator.lintian-overrides:
2765+ - Drop overrides file. It wasn't really silencing any lintian warnings.
2766+
2767+ -- Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com> Wed, 13 Mar 2024 09:38:15 +0000
2768+
2769 netplan.io (0.107-5ubuntu0.2) mantic; urgency=medium
2770
2771 * lp1809994/0010-parse-improve-the-parsing-of-access-points-LP-180999.patch:
2772diff --git a/debian/control b/debian/control
2773index 74d2604..bc358c7 100644
2774--- a/debian/control
2775+++ b/debian/control
2776@@ -27,7 +27,8 @@ Build-Depends:
2777 libcmocka-dev,
2778 libpython3-dev,
2779 libsystemd-dev,
2780- systemd,
2781+ systemd <!nocheck>,
2782+ systemd-dev,
2783 dbus-x11 <!nocheck>,
2784 pyflakes3 <!nocheck>,
2785 pycodestyle <!nocheck> | pep8 <!nocheck>,
2786diff --git a/debian/extra/PLACEHOLDER b/debian/extra/PLACEHOLDER
2787new file mode 100644
2788index 0000000..fb20d88
2789--- /dev/null
2790+++ b/debian/extra/PLACEHOLDER
2791@@ -0,0 +1,4 @@
2792+This is a placeholder file to avoid an empty [/usr]/lib/netplan/ directory
2793+to be removed during a package upgrade involving the usrmerge transition.
2794+
2795+See https://bugs.debian.org/1060661 for more context.
2796diff --git a/debian/netplan-generator.lintian-overrides b/debian/netplan-generator.lintian-overrides
2797deleted file mode 100644
2798index 7225e61..0000000
2799--- a/debian/netplan-generator.lintian-overrides
2800+++ /dev/null
2801@@ -1,2 +0,0 @@
2802-# false positive
2803-netplan-generator: package-contains-empty-directory [usr/lib/netplan/]
2804diff --git a/debian/netplan.io.preinst b/debian/netplan.io.preinst
2805new file mode 100644
2806index 0000000..9a508f1
2807--- /dev/null
2808+++ b/debian/netplan.io.preinst
2809@@ -0,0 +1,17 @@
2810+#!/bin/sh
2811+
2812+set -e
2813+
2814+# Cleanup .pyc cached files from netplan.io versions older than 0.107-3.
2815+# After 0.107-3, the noncli-related code was moved away from
2816+# share/netplan/netplan, thanks to the new python3-netplan package,
2817+# but dpkg would leave this directory behind due to the .pyc files.
2818+# Cleaning it up here will leave the directory empty so dpkg will remove
2819+# it properly during the update process.
2820+
2821+if [ -d /usr/share/netplan/netplan ]; then
2822+ find /usr/share/netplan/netplan/ -name '*.pyc' -delete
2823+ find /usr/share/netplan/netplan/ -name '__pycache__' -delete
2824+fi
2825+
2826+#DEBHELPER#
2827diff --git a/debian/patches/0001-parse-allow-COMMON_LINK_HANDLERS-for-VRFs-LP-2031421.patch b/debian/patches/0001-parse-allow-COMMON_LINK_HANDLERS-for-VRFs-LP-2031421.patch
2828deleted file mode 100644
2829index ea670f6..0000000
2830--- a/debian/patches/0001-parse-allow-COMMON_LINK_HANDLERS-for-VRFs-LP-2031421.patch
2831+++ /dev/null
2832@@ -1,41 +0,0 @@
2833-From: =?utf-8?q?Lukas_M=C3=A4rdian?= <slyon@ubuntu.com>
2834-Date: Mon, 21 Aug 2023 15:59:42 +0200
2835-Subject: parse: allow COMMON_LINK_HANDLERS for VRFs (LP: #2031421,
2836- Closes: #1049432)
2837-
2838-Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1049432
2839-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2031421
2840-Forwarded: https://github.com/canonical/netplan/pull/401
2841-
2842-This is to fix test failures with latest NetworkManager v1.44, after they
2843-slightly changed behavior:
2844-https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/commit/dabfa26a41edc7911a45a4689d555e8f055b0373
2845----
2846- src/parse.c | 1 +
2847- tests/integration/routing.py | 1 +
2848- 2 files changed, 2 insertions(+)
2849-
2850-diff --git a/src/parse.c b/src/parse.c
2851-index b930b75..a1730e5 100644
2852---- a/src/parse.c
2853-+++ b/src/parse.c
2854-@@ -2864,6 +2864,7 @@ static const mapping_entry_handler vlan_def_handlers[] = {
2855- };
2856-
2857- static const mapping_entry_handler vrf_def_handlers[] = {
2858-+ COMMON_LINK_HANDLERS,
2859- COMMON_BACKEND_HANDLERS,
2860- {"renderer", YAML_SCALAR_NODE, {.generic=handle_netdef_renderer}, NULL},
2861- {"interfaces", YAML_SEQUENCE_NODE, {.generic=handle_vrf_interfaces}, NULL},
2862-diff --git a/tests/integration/routing.py b/tests/integration/routing.py
2863-index f29b012..f63be36 100644
2864---- a/tests/integration/routing.py
2865-+++ b/tests/integration/routing.py
2866-@@ -295,6 +295,7 @@ class _CommonTests():
2867- table: 1000
2868- vrfs:
2869- vrf0:
2870-+ addresses: [10.10.10.20/24]
2871- table: 1000
2872- interfaces: [%(ec)s]
2873- routes:
2874diff --git a/debian/patches/0001-parse-nm-wg-append-the-correct-prefix-to-IPv6-addres.patch b/debian/patches/0001-parse-nm-wg-append-the-correct-prefix-to-IPv6-addres.patch
2875new file mode 100644
2876index 0000000..58ee85f
2877--- /dev/null
2878+++ b/debian/patches/0001-parse-nm-wg-append-the-correct-prefix-to-IPv6-addres.patch
2879@@ -0,0 +1,77 @@
2880+From: Danilo Egea Gondolfo <danilogondolfo@gmail.com>
2881+Date: Thu, 4 Jan 2024 14:35:43 +0000
2882+Subject: parse-nm/wg: append the correct prefix to IPv6 addresses (#428)
2883+
2884+When the prefix is omitted for IPs in the allowed-ips list, we were
2885+appending a /32 to them without checking the address family.
2886+
2887+IPv6 addresses will have a /128 appended to them if it's not present.
2888+
2889+See LP: #2046158
2890+
2891+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/network-manager/+bug/2046158
2892+Origin: https://github.com/canonical/netplan/pull/428
2893+Forwarded: not-needed
2894+---
2895+ src/parse-nm.c | 15 +++++++++------
2896+ tests/parser/test_keyfile.py | 6 ++++--
2897+ 2 files changed, 13 insertions(+), 8 deletions(-)
2898+
2899+diff --git a/src/parse-nm.c b/src/parse-nm.c
2900+index 2e9a264..10f1780 100644
2901+--- a/src/parse-nm.c
2902++++ b/src/parse-nm.c
2903+@@ -543,13 +543,16 @@ parse_tunnels(GKeyFile* kf, NetplanNetDefinition* nd)
2904+ /*
2905+ * NM doesn't care if the prefix was omitted.
2906+ * Even though the WG manual says it requires the prefix,
2907+- * if it's omitted in its config file it will default to /32
2908+- * so we should do the same here and append a /32 if it's not present,
2909+- * otherwise we will generate a YAML that will fail validation.
2910++ * if it's omitted in its config file it will default to /32 for IPv4
2911++ * and /128 for IPv6 so we should do the same here and append a /32 or /128
2912++ * if it's not present, otherwise we will generate a YAML that will fail validation.
2913+ */
2914+- if (!g_strrstr(ip, "/"))
2915+- address = g_strdup_printf("%s/32", ip);
2916+- else
2917++ if (!g_strrstr(ip, "/")) {
2918++ if (is_ip4_address(ip))
2919++ address = g_strdup_printf("%s/32", ip);
2920++ else
2921++ address = g_strdup_printf("%s/128", ip);
2922++ } else
2923+ address = g_strdup(ip);
2924+ g_array_append_val(wireguard_peer->allowed_ips, address);
2925+ }
2926+diff --git a/tests/parser/test_keyfile.py b/tests/parser/test_keyfile.py
2927+index ae4d8d1..1351840 100644
2928+--- a/tests/parser/test_keyfile.py
2929++++ b/tests/parser/test_keyfile.py
2930+@@ -1963,7 +1963,8 @@ method=auto\n'''.format(UUID), regenerate=False)
2931+
2932+ def test_wireguard_allowed_ips_without_prefix(self):
2933+ '''
2934+- When the IP prefix is not present we should default to /32
2935++ When the IP prefix is not present we should default to /32 for IPv4
2936++ and /128 for IPv6.
2937+ '''
2938+ self.generate_from_keyfile('''[connection]
2939+ id=wg0
2940+@@ -1976,7 +1977,7 @@ private-key=aPUcp5vHz8yMLrzk8SsDyYnV33IhE/k20e52iKJFV0A=
2941+
2942+ [wireguard-peer.cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI=]
2943+ endpoint=1.2.3.4:12345
2944+-allowed-ips=192.168.0.10
2945++allowed-ips=192.168.0.10;2001::1;
2946+
2947+ [ipv4]
2948+ method=auto\n'''.format(UUID), regenerate=False)
2949+@@ -1995,6 +1996,7 @@ method=auto\n'''.format(UUID), regenerate=False)
2950+ public: "cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI="
2951+ allowed-ips:
2952+ - "192.168.0.10/32"
2953++ - "2001::1/128"
2954+ networkmanager:
2955+ uuid: "{}"
2956+ name: "wg0"
2957diff --git a/debian/patches/0002-test-ovs-Avoid-NetworkManager-taking-contol-breaking.patch b/debian/patches/0002-test-ovs-Avoid-NetworkManager-taking-contol-breaking.patch
2958deleted file mode 100644
2959index f12a5f3..0000000
2960--- a/debian/patches/0002-test-ovs-Avoid-NetworkManager-taking-contol-breaking.patch
2961+++ /dev/null
2962@@ -1,28 +0,0 @@
2963-From: =?utf-8?q?Lukas_M=C3=A4rdian?= <slyon@ubuntu.com>
2964-Date: Mon, 21 Aug 2023 14:56:46 +0200
2965-Subject: test:ovs: Avoid NetworkManager taking contol, breaking a test
2966-
2967-Forwarded: not-needed
2968-Origin: https://github.com/canonical/netplan/commit/c33175cbb16dd154f87b51f5ea1cb2c936564a19
2969----
2970- tests/integration/ovs.py | 5 ++++-
2971- 1 file changed, 4 insertions(+), 1 deletion(-)
2972-
2973-diff --git a/tests/integration/ovs.py b/tests/integration/ovs.py
2974-index 958800c..834a7bd 100644
2975---- a/tests/integration/ovs.py
2976-+++ b/tests/integration/ovs.py
2977-@@ -76,9 +76,12 @@ class _CommonTests():
2978- openvswitch:
2979- ports:
2980- - [patch0-1, patch1-0]
2981-+ ethernets:
2982-+ # define this eth to avoid NM taking control and breaking the following .generate_and_settle()
2983-+ %(ec)s: {}
2984- bridges:
2985- ovs0: {interfaces: [patch0-1]}
2986-- ovs1: {interfaces: [patch1-0]}''')
2987-+ ovs1: {interfaces: [patch1-0]}''' % {'ec': self.dev_e_client})
2988- self.generate_and_settle(['ovs0', 'ovs1'])
2989- # Basic verification that the bridges/ports/interfaces are there in OVS
2990- out = subprocess.check_output(['ovs-vsctl', '-t', '5', 'show'])
2991diff --git a/debian/patches/0003-util-don-t-return-a-placeholder-netdef-in-the-iterat.patch b/debian/patches/0003-util-don-t-return-a-placeholder-netdef-in-the-iterat.patch
2992deleted file mode 100644
2993index dab37df..0000000
2994--- a/debian/patches/0003-util-don-t-return-a-placeholder-netdef-in-the-iterat.patch
2995+++ /dev/null
2996@@ -1,54 +0,0 @@
2997-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
2998-Date: Thu, 31 Aug 2023 15:22:00 +0100
2999-Subject: util: don't return a placeholder netdef in the iterator
3000-
3001-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2034024
3002-Origin: https://github.com/canonical/netplan/pull/406
3003----
3004- src/util.c | 2 ++
3005- tests/test_libnetplan.py | 19 +++++++++++++++++++
3006- 2 files changed, 21 insertions(+)
3007-
3008-diff --git a/src/util.c b/src/util.c
3009-index d4fcc26..b9b621c 100644
3010---- a/src/util.c
3011-+++ b/src/util.c
3012-@@ -895,6 +895,8 @@ _netplan_netdef_pertype_iter_next(struct netdef_pertype_iter* it)
3013-
3014- while (g_hash_table_iter_next(&it->iter, &key, &value)) {
3015- NetplanNetDefinition* netdef = value;
3016-+ if (netdef->type == NETPLAN_DEF_TYPE_NM_PLACEHOLDER_)
3017-+ continue;
3018- if (it->type == NETPLAN_DEF_TYPE_NONE || netdef->type == it->type)
3019- return netdef;
3020- }
3021-diff --git a/tests/test_libnetplan.py b/tests/test_libnetplan.py
3022-index 84944a8..134cfa0 100644
3023---- a/tests/test_libnetplan.py
3024-+++ b/tests/test_libnetplan.py
3025-@@ -189,6 +189,25 @@ class TestNetdefIterator(TestBase):
3026- dhcp4: false''')
3027- self.assertSetEqual(set(["eth0", "br0"]), set(d.id for d in netplan.netdef.NetDefinitionIterator(state, None)))
3028-
3029-+ def test_iter_all_types_with_placeholder(self):
3030-+ state = state_from_yaml(self.confdir, '''network:
3031-+ renderer: NetworkManager
3032-+ ethernets:
3033-+ eth0:
3034-+ dhcp4: false
3035-+ virtual-ethernets:
3036-+ # Netplan will create a placeholder netdef for veth321
3037-+ veth123:
3038-+ peer: veth321
3039-+ bridges:
3040-+ br0:
3041-+ dhcp4: false''')
3042-+
3043-+ # We call the property "type" here so it will try to translate the netdef type to a string
3044-+ # and crash if it's a placeholder
3045-+ expected = {"ethernets", "virtual-ethernets", "bridges"}
3046-+ self.assertSetEqual(expected, set(d.type for d in netplan.netdef.NetDefinitionIterator(state, None)))
3047-+
3048- def test_iter_ethernets(self):
3049- state = state_from_yaml(self.confdir, '''network:
3050- ethernets:
3051diff --git a/debian/patches/0007-tests-assert-generated-.service-files-in-assert_srio.patch b/debian/patches/0007-tests-assert-generated-.service-files-in-assert_srio.patch
3052new file mode 100644
3053index 0000000..b9c0dc7
3054--- /dev/null
3055+++ b/debian/patches/0007-tests-assert-generated-.service-files-in-assert_srio.patch
3056@@ -0,0 +1,26 @@
3057+From: Danilo Egea Gondolfo <danilogondolfo@gmail.com>
3058+Date: Tue, 23 Jan 2024 13:39:45 +0000
3059+Subject: tests: assert generated .service files in assert_sriov
3060+
3061+We are not checking if the systemd units generated are correct.
3062+
3063+Origin: https://github.com/canonical/netplan/pull/437
3064+---
3065+ tests/generator/base.py | 7 +++++++
3066+ 1 file changed, 7 insertions(+)
3067+
3068+diff --git a/tests/generator/base.py b/tests/generator/base.py
3069+index b7bf4f9..7795d40 100644
3070+--- a/tests/generator/base.py
3071++++ b/tests/generator/base.py
3072+@@ -491,3 +491,10 @@ class TestBase(unittest.TestCase):
3073+ self.assertEqual(set(os.path.basename(file) for file in sriov_systemd_dir),
3074+ {'netplan-sriov-' + f for f in file_contents_map})
3075+ self.assertEqual(set(os.listdir(self.workdir.name)) - {'lib'}, {'etc', 'run'})
3076++
3077++ for file in sriov_systemd_dir:
3078++ basename = os.path.basename(file)
3079++ with open(file, 'r') as f:
3080++ contents = f.read()
3081++ map_contents = file_contents_map.get(basename.replace('netplan-sriov-', ''))
3082++ self.assertEqual(map_contents, contents)
3083diff --git a/debian/patches/0008-tests-sriov-test-if-the-generated-netplan-rebind-ser.patch b/debian/patches/0008-tests-sriov-test-if-the-generated-netplan-rebind-ser.patch
3084new file mode 100644
3085index 0000000..6aab075
3086--- /dev/null
3087+++ b/debian/patches/0008-tests-sriov-test-if-the-generated-netplan-rebind-ser.patch
3088@@ -0,0 +1,57 @@
3089+From: Danilo Egea Gondolfo <danilogondolfo@gmail.com>
3090+Date: Tue, 23 Jan 2024 13:41:27 +0000
3091+Subject: tests/sriov: test if the generated netplan-rebind service is correct
3092+
3093+This test is currently failing due to interface duplicates being added
3094+to the list.
3095+
3096+Origin: https://github.com/canonical/netplan/pull/437
3097+---
3098+ tests/test_sriov.py | 36 ++++++++++++++++++++++++++++++++++++
3099+ 1 file changed, 36 insertions(+)
3100+
3101+--- a/tests/test_sriov.py
3102++++ b/tests/test_sriov.py
3103+@@ -879,6 +879,42 @@
3104+ ExecStart=/usr/sbin/netplan rebind enblue engreen
3105+ '''})
3106+
3107++ def test_rebind_service_generation(self):
3108++ self.generate('''network:
3109++ version: 2
3110++ ethernets:
3111++ engreen:
3112++ embedded-switch-mode: switchdev
3113++ delay-virtual-functions-rebind: true
3114++ enblue:
3115++ match: {driver: fake_driver}
3116++ set-name: enblue
3117++ embedded-switch-mode: legacy
3118++ delay-virtual-functions-rebind: true
3119++ virtual-function-count: 4
3120++ sriov_blue_vf0:
3121++ link: enblue
3122++ sriov_blue_vf1:
3123++ link: enblue
3124++ sriov_blue_vf1:
3125++ link: enblue
3126++ sriov_green_vf0:
3127++ link: engreen
3128++ sriov_green_vf1:
3129++ link: engreen
3130++ sriov_green_vf2:
3131++ link: engreen''')
3132++ self.assert_sriov({'rebind.service': '''[Unit]
3133++Description=(Re-)bind SR-IOV Virtual Functions to their driver
3134++After=network.target
3135++After=sys-subsystem-net-devices-enblue.device
3136++After=sys-subsystem-net-devices-engreen.device
3137++
3138++[Service]
3139++Type=oneshot
3140++ExecStart=/usr/sbin/netplan rebind enblue engreen
3141++'''})
3142++
3143+ def test_rebind_not_delayed(self):
3144+ self.generate('''network:
3145+ version: 2
3146diff --git a/debian/patches/0009-sriov-don-t-generate-duplicate-entries-in-the-rebind.patch b/debian/patches/0009-sriov-don-t-generate-duplicate-entries-in-the-rebind.patch
3147new file mode 100644
3148index 0000000..3f596b6
3149--- /dev/null
3150+++ b/debian/patches/0009-sriov-don-t-generate-duplicate-entries-in-the-rebind.patch
3151@@ -0,0 +1,96 @@
3152+From: Danilo Egea Gondolfo <danilogondolfo@gmail.com>
3153+Date: Tue, 23 Jan 2024 14:13:13 +0000
3154+Subject: sriov: don't generate duplicate entries in the rebind.service file
3155+
3156+When multiple VFs are present in the configuration, we end up generating
3157+many duplicates in the netplan-sriov-rebind.service file.
3158+
3159+Use a hash set to store the PFs and automatically deduplicate entries.
3160+
3161+Origin: https://github.com/canonical/netplan/pull/437
3162+---
3163+ src/sriov.c | 35 ++++++++++++++++++++---------------
3164+ 1 file changed, 20 insertions(+), 15 deletions(-)
3165+
3166+diff --git a/src/sriov.c b/src/sriov.c
3167+index 7d4944b..f8117f7 100644
3168+--- a/src/sriov.c
3169++++ b/src/sriov.c
3170+@@ -27,28 +27,34 @@
3171+ #include "sriov.h"
3172+
3173+ static gboolean
3174+-write_sriov_rebind_systemd_unit(const GString* pfs, const char* rootdir, GError** error)
3175++write_sriov_rebind_systemd_unit(GHashTable* pfs, const char* rootdir, GError** error)
3176+ {
3177+ g_autofree gchar* id_escaped = NULL;
3178+ g_autofree char* link = g_strjoin(NULL, rootdir ?: "", "/run/systemd/system/multi-user.target.wants/netplan-sriov-rebind.service", NULL);
3179+ g_autofree char* path = g_strjoin(NULL, "/run/systemd/system/netplan-sriov-rebind.service", NULL);
3180+- gchar** split = NULL;
3181++
3182++ GHashTableIter iter;
3183++ gpointer key;
3184++ GString* interfaces = g_string_new("");
3185+
3186+ GString* s = g_string_new("[Unit]\n");
3187+ g_string_append(s, "Description=(Re-)bind SR-IOV Virtual Functions to their driver\n");
3188+ g_string_append_printf(s, "After=network.target\n");
3189+
3190+ /* Run after udev */
3191+- split = g_strsplit(pfs->str, " ", 0);
3192+- for (unsigned i = 0; split[i]; ++i)
3193+- g_string_append_printf(s, "After=sys-subsystem-net-devices-%s.device\n",
3194+- split[i]);
3195+- g_strfreev(split);
3196++ g_hash_table_iter_init(&iter, pfs);
3197++ while (g_hash_table_iter_next (&iter, &key, NULL)) {
3198++ const gchar* id = key;
3199++ g_string_append_printf(s, "After=sys-subsystem-net-devices-%s.device\n", id);
3200++ g_string_append_printf(interfaces, "%s ", id);
3201++ }
3202+
3203+ g_string_append(s, "\n[Service]\nType=oneshot\n");
3204+- g_string_append_printf(s, "ExecStart=" SBINDIR "/netplan rebind %s\n", pfs->str);
3205++ g_string_truncate(interfaces, interfaces->len-1); /* cut trailing whitespace */
3206++ g_string_append_printf(s, "ExecStart=" SBINDIR "/netplan rebind %s\n", interfaces->str);
3207+
3208+ g_string_free_to_file(s, rootdir, path, NULL);
3209++ g_string_free(interfaces, TRUE);
3210+
3211+ safe_mkdir_p_dir(link);
3212+ if (symlink(path, link) < 0 && errno != EEXIST) {
3213+@@ -73,7 +79,7 @@ netplan_state_finish_sriov_write(const NetplanState* np_state, const char* rootd
3214+ gboolean ret = TRUE;
3215+
3216+ if (np_state) {
3217+- GString* pfs = g_string_new(NULL);
3218++ GHashTable* rebind_pfs = g_hash_table_new(g_str_hash, g_str_equal);
3219+ /* Find netdev interface names for SR-IOV PFs*/
3220+ for (GList* iterator = np_state->netdefs_ordered; iterator; iterator = iterator->next) {
3221+ def = (NetplanNetDefinition*) iterator->data;
3222+@@ -88,20 +94,19 @@ netplan_state_finish_sriov_write(const NetplanState* np_state, const char* rootd
3223+
3224+ if (pf && pf->sriov_delay_virtual_functions_rebind) {
3225+ if (pf->set_name)
3226+- g_string_append_printf(pfs, "%s ", pf->set_name);
3227++ g_hash_table_add(rebind_pfs, pf->set_name);
3228+ else if (!pf->has_match) /* netdef_id == interface name */
3229+- g_string_append_printf(pfs, "%s ", pf->id);
3230++ g_hash_table_add(rebind_pfs, pf->id);
3231+ else
3232+ g_warning("%s: Cannot rebind SR-IOV virtual functions, unknown interface name. "
3233+ "Use 'netplan rebind <IFACE>' to rebind manually or use the 'set-name' stanza.",
3234+ pf->id);
3235+ }
3236+ }
3237+- if (pfs->len > 0) {
3238+- g_string_truncate(pfs, pfs->len-1); /* cut trailing whitespace */
3239+- ret = write_sriov_rebind_systemd_unit(pfs, rootdir, NULL);
3240++ if (g_hash_table_size(rebind_pfs) > 0) {
3241++ ret = write_sriov_rebind_systemd_unit(rebind_pfs, rootdir, NULL);
3242+ }
3243+- g_string_free(pfs, TRUE);
3244++ g_hash_table_destroy(rebind_pfs);
3245+ }
3246+
3247+ if (any_sriov) {
3248diff --git a/debian/patches/lp1809994/0010-parse-improve-the-parsing-of-access-points-LP-180999.patch b/debian/patches/lp1809994/0010-parse-improve-the-parsing-of-access-points-LP-180999.patch
3249deleted file mode 100644
3250index 85392c7..0000000
3251--- a/debian/patches/lp1809994/0010-parse-improve-the-parsing-of-access-points-LP-180999.patch
3252+++ /dev/null
3253@@ -1,197 +0,0 @@
3254-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3255-Date: Fri, 6 Oct 2023 11:42:36 +0100
3256-Subject: parse: improve the parsing of access-points (LP: #1809994)
3257-
3258-When the parser requires a second pass, it will report access-points it
3259-already parsed as duplicates and error out.
3260-
3261-With this change, access-points will be stored in a local hash table,
3262-which will be used to find duplicates in the same netdef, and moved to
3263-the netdef->access_points hash table in the end. Access-points already
3264-present in the netdef hash table will be considered already parsed and
3265-skipped.
3266-
3267-Add a test to check the problem is fixed and another one to test if
3268-merging the access-points when the same interface is present in multiple
3269-files is working properly.
3270-
3271-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/1809994
3272-Origin: https://github.com/canonical/netplan/pull/413
3273----
3274- src/parse.c | 45 +++++++++++++++++++---------
3275- src/types-internal.h | 3 ++
3276- src/types.c | 2 +-
3277- tests/generator/test_common.py | 54 ++++++++++++++++++++++++++++++++++
3278- 4 files changed, 89 insertions(+), 15 deletions(-)
3279-
3280---- a/src/parse.c
3281-+++ b/src/parse.c
3282-@@ -59,6 +59,9 @@
3283-
3284- NetplanParser global_parser = {0};
3285-
3286-+static gboolean
3287-+insert_kv_into_hash(void *key, void *value, void *hash);
3288-+
3289- /**
3290- * Load YAML file into a yaml_document_t.
3291- *
3292-@@ -1404,11 +1407,13 @@
3293- static gboolean
3294- handle_wifi_access_points(NetplanParser* npp, yaml_node_t* node, const char* key_prefix, __unused const void* data, GError** error)
3295- {
3296-+ GHashTable* access_points = g_hash_table_new(g_str_hash, g_str_equal);
3297-+
3298- for (yaml_node_pair_t* entry = node->data.mapping.pairs.start; entry < node->data.mapping.pairs.top; entry++) {
3299- NetplanWifiAccessPoint *access_point = NULL;
3300- g_autofree char* full_key = NULL;
3301- yaml_node_t* key, *value;
3302-- gboolean ret = TRUE;
3303-+ const gchar* ssid;
3304-
3305- key = yaml_document_get_node(&npp->doc, entry->key);
3306- assert_type(npp, key, YAML_SCALAR_NODE);
3307-@@ -1421,31 +1426,43 @@
3308- continue;
3309- }
3310-
3311-+ ssid = scalar(key);
3312-+
3313-+ /* Skip access-points that already exist in the netdef */
3314-+ if (npp->current.netdef->access_points && g_hash_table_contains(npp->current.netdef->access_points, ssid))
3315-+ continue;
3316-+
3317-+ /* Check if there's already an SSID with that name in the list of APs we are parsing */
3318-+ if (g_hash_table_contains(access_points, ssid)) {
3319-+ g_hash_table_foreach(access_points, free_access_point, NULL);
3320-+ g_hash_table_destroy(access_points);
3321-+ return yaml_error(npp, key, error, "%s: Duplicate access point SSID '%s'", npp->current.netdef->id, ssid);
3322-+ }
3323-+
3324- g_assert(access_point == NULL);
3325- access_point = g_new0(NetplanWifiAccessPoint, 1);
3326-- access_point->ssid = g_strdup(scalar(key));
3327-+ access_point->ssid = g_strdup(ssid);
3328- g_debug("%s: adding wifi AP '%s'", npp->current.netdef->id, access_point->ssid);
3329-
3330-- /* Check if there's already an SSID with that name */
3331-- // FIXME: This check fails on multi-pass parsing, e.g. when defined in
3332-- // the same YAML file with a set of virtual-ethernets peers.
3333-- if (npp->current.netdef->access_points &&
3334-- g_hash_table_lookup(npp->current.netdef->access_points, access_point->ssid)) {
3335-- ret = yaml_error(npp, key, error, "%s: Duplicate access point SSID '%s'", npp->current.netdef->id, access_point->ssid);
3336-- }
3337--
3338- npp->current.access_point = access_point;
3339-- if (!ret || !process_mapping(npp, value, full_key, wifi_access_point_handlers, NULL, error)) {
3340-+ if (!process_mapping(npp, value, full_key, wifi_access_point_handlers, NULL, error)) {
3341- access_point_clear(&npp->current.access_point, npp->current.backend);
3342-+ g_hash_table_foreach(access_points, free_access_point, NULL);
3343-+ g_hash_table_destroy(access_points);
3344- return FALSE;
3345- }
3346-
3347-+ g_hash_table_insert(access_points, access_point->ssid, access_point);
3348-+ npp->current.access_point = NULL;
3349-+ }
3350-+
3351-+ if (g_hash_table_size(access_points) > 0) {
3352- if (!npp->current.netdef->access_points)
3353- npp->current.netdef->access_points = g_hash_table_new(g_str_hash, g_str_equal);
3354-- g_hash_table_insert(npp->current.netdef->access_points, access_point->ssid, access_point);
3355-- npp->current.access_point = NULL;
3356-+ g_hash_table_foreach_steal(access_points, insert_kv_into_hash, npp->current.netdef->access_points);
3357-+ mark_data_as_dirty(npp, &npp->current.netdef->access_points);
3358- }
3359-- mark_data_as_dirty(npp, &npp->current.netdef->access_points);
3360-+ g_hash_table_destroy(access_points);
3361- return TRUE;
3362- }
3363-
3364---- a/src/types-internal.h
3365-+++ b/src/types-internal.h
3366-@@ -313,3 +313,6 @@
3367-
3368- void
3369- free_address_options(void* ptr);
3370-+
3371-+void
3372-+free_access_point(void* key, void* value, void* data);
3373---- a/src/types.c
3374-+++ b/src/types.c
3375-@@ -200,7 +200,7 @@
3376- * @data: pointer to a NetplanBackend value representing the renderer context in which
3377- * to interpret the processed object, especially regarding the backend settings
3378- */
3379--static void
3380-+void
3381- free_access_point(__unused void* key, void* value, __unused void* data)
3382- {
3383- NetplanWifiAccessPoint* ap = value;
3384---- a/tests/generator/test_common.py
3385-+++ b/tests/generator/test_common.py
3386-@@ -1557,6 +1557,28 @@
3387- ''',
3388- 'eth0.network': ND_EMPTY % ('eth0', 'no') + 'Bond=aggi\n'})
3389-
3390-+ def test_check_parser_second_pass_will_not_lead_to_duplicate_access_point(self):
3391-+ '''
3392-+ When the parser needs more than one pass we shouldn't
3393-+ try to load the same access-point again from wifi devices.
3394-+ Testcase for LP: #1809994'''
3395-+
3396-+ self.generate('''network:
3397-+ bridges:
3398-+ br0:
3399-+ interfaces:
3400-+ - eth0
3401-+ ethernets:
3402-+ eth0:
3403-+ dhcp4: false
3404-+ wifis:
3405-+ wlan0:
3406-+ dhcp4: true
3407-+ access-points:
3408-+ "mywifi":
3409-+ password: "aaaaaaaa"
3410-+''')
3411-+
3412-
3413- class TestMerging(TestBase):
3414- '''multiple *.yaml merging'''
3415-@@ -1740,3 +1762,35 @@
3416- ''',
3417- 'enyellow.network': ND_DHCP4 % 'enyellow',
3418- 'enblue.network': ND_DHCP4 % 'enblue'})
3419-+
3420-+ def test_wifi_access_points_merging(self):
3421-+ self.generate('''network:
3422-+ version: 2
3423-+ wifis:
3424-+ wlan0:
3425-+ dhcp4: true
3426-+ access-points:
3427-+ "mywifi":
3428-+ password: "aaaaaaaa"''',
3429-+ confs={'newwifi': '''network:
3430-+ version: 2
3431-+ wifis:
3432-+ wlan0:
3433-+ dhcp4: true
3434-+ access-points:
3435-+ "mynewwifi":
3436-+ password: "aaaaaaaa"'''})
3437-+
3438-+ self.assert_wpa_supplicant("wlan0", """ctrl_interface=/run/wpa_supplicant
3439-+
3440-+network={
3441-+ ssid="mynewwifi"
3442-+ key_mgmt=WPA-PSK
3443-+ psk="aaaaaaaa"
3444-+}
3445-+network={
3446-+ ssid="mywifi"
3447-+ key_mgmt=WPA-PSK
3448-+ psk="aaaaaaaa"
3449-+}
3450-+""")
3451diff --git a/debian/patches/lp1809994/0011-wifi-replace-the-previously-defined-AP-with-the-new-.patch b/debian/patches/lp1809994/0011-wifi-replace-the-previously-defined-AP-with-the-new-.patch
3452deleted file mode 100644
3453index c03521e..0000000
3454--- a/debian/patches/lp1809994/0011-wifi-replace-the-previously-defined-AP-with-the-new-.patch
3455+++ /dev/null
3456@@ -1,79 +0,0 @@
3457-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3458-Date: Thu, 12 Oct 2023 18:07:31 +0100
3459-Subject: wifi: replace the previously defined AP with the new one
3460-
3461-If we find an AP with the same name in the same interface, we drop the
3462-first one and use the new one. This is done to maintain the documented
3463-behavior of respecting the order in which the files are parsed. We still
3464-need to implement support for merging AP settings.
3465-
3466-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/1809994
3467-Origin: https://github.com/canonical/netplan/pull/413
3468----
3469- src/parse.c | 17 +++++++++++++----
3470- tests/generator/test_common.py | 30 ++++++++++++++++++++++++++++++
3471- 2 files changed, 43 insertions(+), 4 deletions(-)
3472-
3473---- a/src/parse.c
3474-+++ b/src/parse.c
3475-@@ -1428,11 +1428,20 @@
3476-
3477- ssid = scalar(key);
3478-
3479-- /* Skip access-points that already exist in the netdef */
3480-- if (npp->current.netdef->access_points && g_hash_table_contains(npp->current.netdef->access_points, ssid))
3481-- continue;
3482-+ /*
3483-+ * Delete the access-point if it already exists in the netdef and let the new
3484-+ * one be added. It has the side effect of reprocessing APs if the parser requires a
3485-+ * second pass.
3486-+ *
3487-+ * TODO: implement support for merging AP settings if they were previously defined
3488-+ */
3489-+ if (npp->current.netdef->access_points && g_hash_table_contains(npp->current.netdef->access_points, ssid)) {
3490-+ NetplanWifiAccessPoint *ap = g_hash_table_lookup(npp->current.netdef->access_points, ssid);
3491-+ g_hash_table_remove(npp->current.netdef->access_points, ssid);
3492-+ free_access_point(NULL, ap, NULL);
3493-+ }
3494-
3495-- /* Check if there's already an SSID with that name in the list of APs we are parsing */
3496-+ /* Check if the SSID was already defined in the same netdef in this YAML file we are parsing */
3497- if (g_hash_table_contains(access_points, ssid)) {
3498- g_hash_table_foreach(access_points, free_access_point, NULL);
3499- g_hash_table_destroy(access_points);
3500---- a/tests/generator/test_common.py
3501-+++ b/tests/generator/test_common.py
3502-@@ -1794,3 +1794,33 @@
3503- psk="aaaaaaaa"
3504- }
3505- """)
3506-+
3507-+ def test_wifi_access_points_overwriting(self):
3508-+ ''' If we find an AP that is already defined we drop the first one.
3509-+ XXX: this test must be removed once we implement support for AP merging
3510-+ '''
3511-+ self.generate('''network:
3512-+ version: 2
3513-+ wifis:
3514-+ wlan0:
3515-+ dhcp4: true
3516-+ access-points:
3517-+ "mywifi":
3518-+ password: "aaaaaaaa"''',
3519-+ confs={'newwifi': '''network:
3520-+ version: 2
3521-+ wifis:
3522-+ wlan0:
3523-+ dhcp4: true
3524-+ access-points:
3525-+ "mywifi":
3526-+ password: "bbbbbbbb"'''})
3527-+
3528-+ self.assert_wpa_supplicant("wlan0", """ctrl_interface=/run/wpa_supplicant
3529-+
3530-+network={
3531-+ ssid="mywifi"
3532-+ key_mgmt=WPA-PSK
3533-+ psk="bbbbbbbb"
3534-+}
3535-+""")
3536diff --git a/debian/patches/lp2034067/0004-tunnels-validation-do-not-error-out-if-local-is-not-.patch b/debian/patches/lp2034067/0004-tunnels-validation-do-not-error-out-if-local-is-not-.patch
3537deleted file mode 100644
3538index e65fc4e..0000000
3539--- a/debian/patches/lp2034067/0004-tunnels-validation-do-not-error-out-if-local-is-not-.patch
3540+++ /dev/null
3541@@ -1,98 +0,0 @@
3542-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3543-Date: Fri, 1 Sep 2023 15:30:46 +0100
3544-Subject: tunnels/validation: do not error out if "local" is not defined
3545-
3546-The "local" IP property is not required by backends so we shouldn't
3547-error out if it's not defined.
3548-
3549-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2034067
3550-Origin: https://github.com/canonical/netplan/pull/407
3551----
3552- src/networkd.c | 3 ++-
3553- src/nm.c | 3 ++-
3554- src/validation.c | 6 ++----
3555- tests/generator/test_tunnels.py | 12 ------------
3556- 4 files changed, 6 insertions(+), 18 deletions(-)
3557-
3558-diff --git a/src/networkd.c b/src/networkd.c
3559-index 602b472..325197d 100644
3560---- a/src/networkd.c
3561-+++ b/src/networkd.c
3562-@@ -141,7 +141,8 @@ write_tunnel_params(GString* s, const NetplanNetDefinition* def)
3563- g_string_printf(params, "Independent=true\n");
3564- if (def->tunnel.mode == NETPLAN_TUNNEL_MODE_IPIP6 || def->tunnel.mode == NETPLAN_TUNNEL_MODE_IP6IP6)
3565- g_string_append_printf(params, "Mode=%s\n", netplan_tunnel_mode_name(def->tunnel.mode));
3566-- g_string_append_printf(params, "Local=%s\n", def->tunnel.local_ip);
3567-+ if (def->tunnel.local_ip)
3568-+ g_string_append_printf(params, "Local=%s\n", def->tunnel.local_ip);
3569- g_string_append_printf(params, "Remote=%s\n", def->tunnel.remote_ip);
3570- if (def->tunnel_ttl)
3571- g_string_append_printf(params, "TTL=%u\n", def->tunnel_ttl);
3572-diff --git a/src/nm.c b/src/nm.c
3573-index a8ae1a6..c9279d4 100644
3574---- a/src/nm.c
3575-+++ b/src/nm.c
3576-@@ -393,7 +393,8 @@ static void
3577- write_tunnel_params(const NetplanNetDefinition* def, GKeyFile *kf)
3578- {
3579- g_key_file_set_integer(kf, "ip-tunnel", "mode", def->tunnel.mode);
3580-- g_key_file_set_string(kf, "ip-tunnel", "local", def->tunnel.local_ip);
3581-+ if (def->tunnel.local_ip)
3582-+ g_key_file_set_string(kf, "ip-tunnel", "local", def->tunnel.local_ip);
3583- g_key_file_set_string(kf, "ip-tunnel", "remote", def->tunnel.remote_ip);
3584- if (def->tunnel_ttl)
3585- g_key_file_set_uint64(kf, "ip-tunnel", "ttl", def->tunnel_ttl);
3586-diff --git a/src/validation.c b/src/validation.c
3587-index 76fe1bb..4e37213 100644
3588---- a/src/validation.c
3589-+++ b/src/validation.c
3590-@@ -241,8 +241,6 @@ validate_tunnel_grammar(const NetplanParser* npp, NetplanNetDefinition* nd, yaml
3591-
3592- /* Validate local/remote IPs */
3593- if (nd->tunnel.mode != NETPLAN_TUNNEL_MODE_VXLAN) {
3594-- if (!nd->tunnel.local_ip)
3595-- return yaml_error(npp, node, error, "%s: missing 'local' property for tunnel", nd->id);
3596- if (!nd->tunnel.remote_ip)
3597- return yaml_error(npp, node, error, "%s: missing 'remote' property for tunnel", nd->id);
3598- }
3599-@@ -255,7 +253,7 @@ validate_tunnel_grammar(const NetplanParser* npp, NetplanNetDefinition* nd, yaml
3600- case NETPLAN_TUNNEL_MODE_IP6GRE:
3601- case NETPLAN_TUNNEL_MODE_IP6GRETAP:
3602- case NETPLAN_TUNNEL_MODE_VTI6:
3603-- if (!is_ip6_address(nd->tunnel.local_ip))
3604-+ if (nd->tunnel.local_ip && !is_ip6_address(nd->tunnel.local_ip))
3605- return yaml_error(npp, node, error, "%s: 'local' must be a valid IPv6 address for this tunnel type", nd->id);
3606- if (!is_ip6_address(nd->tunnel.remote_ip))
3607- return yaml_error(npp, node, error, "%s: 'remote' must be a valid IPv6 address for this tunnel type", nd->id);
3608-@@ -268,7 +266,7 @@ validate_tunnel_grammar(const NetplanParser* npp, NetplanNetDefinition* nd, yaml
3609- break;
3610-
3611- default:
3612-- if (!is_ip4_address(nd->tunnel.local_ip))
3613-+ if (nd->tunnel.local_ip && !is_ip4_address(nd->tunnel.local_ip))
3614- return yaml_error(npp, node, error, "%s: 'local' must be a valid IPv4 address for this tunnel type", nd->id);
3615- if (!is_ip4_address(nd->tunnel.remote_ip))
3616- return yaml_error(npp, node, error, "%s: 'remote' must be a valid IPv4 address for this tunnel type", nd->id);
3617-diff --git a/tests/generator/test_tunnels.py b/tests/generator/test_tunnels.py
3618-index eec7b00..7a76de7 100644
3619---- a/tests/generator/test_tunnels.py
3620-+++ b/tests/generator/test_tunnels.py
3621-@@ -1643,18 +1643,6 @@ class TestConfigErrors(TestBase):
3622- out = self.generate(config, expect_fail=True)
3623- self.assertIn("Error in network definition: address '10.10.10.10/21' should not include /prefixlength", out)
3624-
3625-- def test_missing_local_ip(self):
3626-- """Fail if local IP is missing"""
3627-- config = '''network:
3628-- version: 2
3629-- tunnels:
3630-- tun0:
3631-- mode: gre
3632-- remote: 20.20.20.20
3633--'''
3634-- out = self.generate(config, expect_fail=True)
3635-- self.assertIn("Error in network definition: tun0: missing 'local' property for tunnel", out)
3636--
3637- def test_missing_remote_ip(self):
3638- """Fail if remote IP is missing"""
3639- config = '''network:
3640diff --git a/debian/patches/lp2034067/0005-tests-add-some-integration-tests-without-the-local-a.patch b/debian/patches/lp2034067/0005-tests-add-some-integration-tests-without-the-local-a.patch
3641deleted file mode 100644
3642index c99bc4d..0000000
3643--- a/debian/patches/lp2034067/0005-tests-add-some-integration-tests-without-the-local-a.patch
3644+++ /dev/null
3645@@ -1,81 +0,0 @@
3646-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3647-Date: Fri, 1 Sep 2023 17:48:30 +0100
3648-Subject: tests: add some integration tests without the local address
3649-
3650-Copy a few tunnels common tests and remove the local address to ensure
3651-both backends will work fine.
3652-
3653-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2034067
3654-Origin: https://github.com/canonical/netplan/pull/407
3655----
3656- tests/integration/tunnels.py | 43 +++++++++++++++++++++++++++++++++++++++++++
3657- 1 file changed, 43 insertions(+)
3658-
3659-diff --git a/tests/integration/tunnels.py b/tests/integration/tunnels.py
3660-index a915554..bdacb55 100644
3661---- a/tests/integration/tunnels.py
3662-+++ b/tests/integration/tunnels.py
3663-@@ -45,6 +45,20 @@ class _CommonTests():
3664- self.generate_and_settle(['sit-tun0'])
3665- self.assert_iface('sit-tun0', ['sit-tun0@NONE', 'link.* 192.168.5.1 peer 99.99.99.99'])
3666-
3667-+ def test_tunnel_sit_without_local_address(self):
3668-+ self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'sit-tun0'], stderr=subprocess.DEVNULL)
3669-+ with open(self.config, 'w') as f:
3670-+ f.write('''network:
3671-+ renderer: %(r)s
3672-+ version: 2
3673-+ tunnels:
3674-+ sit-tun0:
3675-+ mode: sit
3676-+ remote: 99.99.99.99
3677-+''' % {'r': self.backend})
3678-+ self.generate_and_settle(['sit-tun0'])
3679-+ self.assert_iface('sit-tun0', ['sit-tun0@NONE', 'link.* 0.0.0.0 peer 99.99.99.99'])
3680-+
3681- def test_tunnel_ipip(self):
3682- self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'tun0'], stderr=subprocess.DEVNULL)
3683- with open(self.config, 'w') as f:
3684-@@ -61,6 +75,21 @@ class _CommonTests():
3685- self.generate_and_settle(['tun0'])
3686- self.assert_iface('tun0', ['tun0@NONE', 'link.* 192.168.5.1 peer 99.99.99.99'])
3687-
3688-+ def test_tunnel_ipip_without_local_address(self):
3689-+ self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'tun0'], stderr=subprocess.DEVNULL)
3690-+ with open(self.config, 'w') as f:
3691-+ f.write('''network:
3692-+ renderer: %(r)s
3693-+ version: 2
3694-+ tunnels:
3695-+ tun0:
3696-+ mode: ipip
3697-+ remote: 99.99.99.99
3698-+ ttl: 64
3699-+''' % {'r': self.backend})
3700-+ self.generate_and_settle(['tun0'])
3701-+ self.assert_iface('tun0', ['tun0@NONE', 'link.* 0.0.0.0 peer 99.99.99.99'])
3702-+
3703- def test_tunnel_wireguard(self):
3704- self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'wg0'], stderr=subprocess.DEVNULL)
3705- self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'wg1'], stderr=subprocess.DEVNULL)
3706-@@ -142,6 +171,20 @@ class _CommonTests():
3707- self.generate_and_settle(['tun0'])
3708- self.assert_iface('tun0', ['tun0@NONE', 'link.* 192.168.5.1 peer 99.99.99.99'])
3709-
3710-+ def test_tunnel_gre_without_local_address(self):
3711-+ self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'tun0'], stderr=subprocess.DEVNULL)
3712-+ with open(self.config, 'w') as f:
3713-+ f.write('''network:
3714-+ renderer: %(r)s
3715-+ version: 2
3716-+ tunnels:
3717-+ tun0:
3718-+ mode: gre
3719-+ remote: 99.99.99.99
3720-+''' % {'r': self.backend})
3721-+ self.generate_and_settle(['tun0'])
3722-+ self.assert_iface('tun0', ['tun0@NONE', 'link.* 0.0.0.0 peer 99.99.99.99'])
3723-+
3724- def test_tunnel_gre6(self):
3725- self.addCleanup(subprocess.call, ['ip', 'link', 'delete', 'tun0'], stderr=subprocess.DEVNULL)
3726- with open(self.config, 'w') as f:
3727diff --git a/debian/patches/lp2034595/0006-apply-bring-lo-back-up-if-it-s-managed-by-NM.patch b/debian/patches/lp2034595/0006-apply-bring-lo-back-up-if-it-s-managed-by-NM.patch
3728deleted file mode 100644
3729index 030036b..0000000
3730--- a/debian/patches/lp2034595/0006-apply-bring-lo-back-up-if-it-s-managed-by-NM.patch
3731+++ /dev/null
3732@@ -1,52 +0,0 @@
3733-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3734-Date: Tue, 5 Sep 2023 18:03:10 +0100
3735-Subject: apply: bring "lo" back up if it's managed by NM
3736-
3737-Origin: https://github.com/canonical/netplan/pull/408
3738-Bug: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2034595
3739-
3740-NM is not bringing it back automatically after we flush its addresses.
3741-It's not clear if it's a bug or intended behavior.
3742----
3743- netplan_cli/cli/commands/apply.py | 16 +++++++++++++++-
3744- 1 file changed, 15 insertions(+), 1 deletion(-)
3745-
3746-diff --git a/netplan_cli/cli/commands/apply.py b/netplan_cli/cli/commands/apply.py
3747-index 8bf8a94..181e400 100644
3748---- a/netplan_cli/cli/commands/apply.py
3749-+++ b/netplan_cli/cli/commands/apply.py
3750-@@ -286,12 +286,18 @@ class NetplanApply(utils.NetplanCommand):
3751- if restart_nm:
3752- # Flush all IP addresses of NM managed interfaces, to avoid NM creating
3753- # new, non netplan-* connection profiles, using the existing IPs.
3754-- for iface in utils.nm_interfaces(restart_nm_glob, devices):
3755-+ nm_interfaces = utils.nm_interfaces(restart_nm_glob, devices)
3756-+ for iface in nm_interfaces:
3757- utils.ip_addr_flush(iface)
3758- # clear NM state, especially the [device].managed=true config, as that might have been
3759- # re-set via an udev rule setting "NM_UNMANAGED=1"
3760- shutil.rmtree('/run/NetworkManager/devices', ignore_errors=True)
3761- utils.systemctl_network_manager('start', sync=sync)
3762-+ # If 'lo' is in the nm_interfaces set we flushed it's IPs (see above) and will need to bring it
3763-+ # back manually. For that, we need NM up and ready to accept commands
3764-+ if 'lo' in nm_interfaces:
3765-+ sync = True
3766-+
3767- if sync:
3768- # 'nmcli' could be /usr/bin/nmcli or
3769- # /snap/bin/nmcli -> /snap/bin/network-manager.nmcli
3770-@@ -309,6 +315,14 @@ class NetplanApply(utils.NetplanCommand):
3771- break
3772- time.sleep(0.5)
3773-
3774-+ # If "lo" is managed by NM through Netplan, apply will flush its addresses and NM
3775-+ # will not bring it back automatically like other connections.
3776-+ # This is a possible scenario with netplan-everywhere. If a user tries to change the 'lo'
3777-+ # connection with nmcli for example, NM will create a persistent nmconnection file and emit a YAML for it.
3778-+ if 'lo' in nm_interfaces:
3779-+ cmd = ['nmcli', 'con', 'up', 'lo']
3780-+ subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
3781-+
3782- @staticmethod
3783- def is_composite_member(composites, phy):
3784- """
3785diff --git a/debian/patches/lp2034595/0007-apply-don-t-assume-the-NM-loopback-connection-is-cal.patch b/debian/patches/lp2034595/0007-apply-don-t-assume-the-NM-loopback-connection-is-cal.patch
3786deleted file mode 100644
3787index ca364c9..0000000
3788--- a/debian/patches/lp2034595/0007-apply-don-t-assume-the-NM-loopback-connection-is-cal.patch
3789+++ /dev/null
3790@@ -1,108 +0,0 @@
3791-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3792-Date: Thu, 7 Sep 2023 14:10:54 +0100
3793-Subject: apply: don't assume the NM loopback connection is called "lo"
3794-
3795-Origin: https://github.com/canonical/netplan/pull/408
3796-Bug: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2034595
3797-
3798-It might have any name, so we need to get the connection name
3799-dynamically.
3800----
3801- netplan_cli/cli/commands/apply.py | 18 +++++++++++-------
3802- netplan_cli/cli/utils.py | 14 ++++++++++++++
3803- tests/test_utils.py | 12 ++++++++++++
3804- 3 files changed, 37 insertions(+), 7 deletions(-)
3805-
3806-diff --git a/netplan_cli/cli/commands/apply.py b/netplan_cli/cli/commands/apply.py
3807-index 181e400..066f496 100644
3808---- a/netplan_cli/cli/commands/apply.py
3809-+++ b/netplan_cli/cli/commands/apply.py
3810-@@ -176,9 +176,12 @@ class NetplanApply(utils.NetplanCommand):
3811- else:
3812- logging.debug('no netplan generated networkd configuration exists')
3813-
3814-+ loopback_connection = ''
3815- if restart_nm:
3816- logging.debug('netplan generated NM configuration changed, restarting NM')
3817- if utils.nm_running():
3818-+ if 'lo' in nm_ifaces:
3819-+ loopback_connection = utils.nm_get_connection_for_interface('lo')
3820- # restarting NM does not cause new config to be applied, need to shut down devices first
3821- for device in devices:
3822- if device not in nm_ifaces:
3823-@@ -293,8 +296,10 @@ class NetplanApply(utils.NetplanCommand):
3824- # re-set via an udev rule setting "NM_UNMANAGED=1"
3825- shutil.rmtree('/run/NetworkManager/devices', ignore_errors=True)
3826- utils.systemctl_network_manager('start', sync=sync)
3827-- # If 'lo' is in the nm_interfaces set we flushed it's IPs (see above) and will need to bring it
3828-- # back manually. For that, we need NM up and ready to accept commands
3829-+
3830-+ # If 'lo' is in the nm_interfaces set we flushed it's IPs (see above) and disconnected it.
3831-+ # NM will not bring it back automatically after restarting and we need to do that manually.
3832-+ # For that, we need NM up and ready to accept commands
3833- if 'lo' in nm_interfaces:
3834- sync = True
3835-
3836-@@ -315,13 +320,12 @@ class NetplanApply(utils.NetplanCommand):
3837- break
3838- time.sleep(0.5)
3839-
3840-- # If "lo" is managed by NM through Netplan, apply will flush its addresses and NM
3841-- # will not bring it back automatically like other connections.
3842-+ # If "lo" is managed by NM through Netplan, apply will flush its addresses and disconnect it.
3843-+ # NM will not bring it back automatically.
3844- # This is a possible scenario with netplan-everywhere. If a user tries to change the 'lo'
3845- # connection with nmcli for example, NM will create a persistent nmconnection file and emit a YAML for it.
3846-- if 'lo' in nm_interfaces:
3847-- cmd = ['nmcli', 'con', 'up', 'lo']
3848-- subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
3849-+ if 'lo' in nm_interfaces and loopback_connection:
3850-+ utils.nm_bring_interface_up(loopback_connection)
3851-
3852- @staticmethod
3853- def is_composite_member(composites, phy):
3854-diff --git a/netplan_cli/cli/utils.py b/netplan_cli/cli/utils.py
3855-index d0a85df..a5f60c9 100644
3856---- a/netplan_cli/cli/utils.py
3857-+++ b/netplan_cli/cli/utils.py
3858-@@ -78,6 +78,20 @@ def nm_interfaces(paths, devices):
3859- return interfaces
3860-
3861-
3862-+def nm_get_connection_for_interface(interface: str) -> str:
3863-+ output = nmcli_out(['-m', 'tabular', '-f', 'GENERAL.CONNECTION', 'device', 'show', interface])
3864-+ lines = output.strip().split('\n')
3865-+ connection = lines[1]
3866-+ return connection if connection != '--' else ''
3867-+
3868-+
3869-+def nm_bring_interface_up(connection: str) -> None: # pragma: nocover (must be covered by NM autopkgtests)
3870-+ try:
3871-+ nmcli(['connection', 'up', connection])
3872-+ except subprocess.CalledProcessError:
3873-+ pass
3874-+
3875-+
3876- def systemctl_network_manager(action, sync=False):
3877- # If the network-manager snap is installed use its service
3878- # name rather than the one of the deb packaged NetworkManager
3879-diff --git a/tests/test_utils.py b/tests/test_utils.py
3880-index ec57087..b2a1657 100644
3881---- a/tests/test_utils.py
3882-+++ b/tests/test_utils.py
3883-@@ -371,3 +371,15 @@ class TestUtils(unittest.TestCase):
3884- self.assertEqual(self.mock_cmd.calls(), [
3885- ['ip', 'addr', 'flush', 'eth42']
3886- ])
3887-+
3888-+ @patch('netplan_cli.cli.utils.nmcli_out')
3889-+ def test_nm_get_connection_for_interface(self, nmcli):
3890-+ nmcli.return_value = 'CONNECTION \nlo \n'
3891-+ out = utils.nm_get_connection_for_interface('lo')
3892-+ self.assertEqual(out, 'lo')
3893-+
3894-+ @patch('netplan_cli.cli.utils.nmcli_out')
3895-+ def test_nm_get_connection_for_interface_no_connection(self, nmcli):
3896-+ nmcli.return_value = 'CONNECTION \n-- \n'
3897-+ out = utils.nm_get_connection_for_interface('asd0')
3898-+ self.assertEqual(out, '')
3899diff --git a/debian/patches/lp2039821/0008-wireguard-ignore-empty-endpoints.patch b/debian/patches/lp2039821/0008-wireguard-ignore-empty-endpoints.patch
3900deleted file mode 100644
3901index e2b3892..0000000
3902--- a/debian/patches/lp2039821/0008-wireguard-ignore-empty-endpoints.patch
3903+++ /dev/null
3904@@ -1,117 +0,0 @@
3905-From 1758948e6cb064b9b00ba3b42ce36ea9546d4773 Mon Sep 17 00:00:00 2001
3906-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
3907-Date: Tue, 10 Oct 2023 11:06:51 +0100
3908-Subject: wireguard: ignore empty endpoints
3909-
3910-The Network Manager GUI will emit 'Endpoint=' if it's not specified when
3911-creating the tunnel. libnetplan is generating 'endpoint: ""' in this case
3912-and the parser is returning an error.
3913-
3914-In nm-parse, if Endpoint is either empty or NULL we'll just not read it. In
3915-the parser, if we find 'endpoint: ""', we'll just ignore it as if it
3916-were not defined.
3917-
3918-See LP: #2038811
3919-
3920-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2039821
3921-Origin: https://github.com/canonical/netplan/pull/414
3922----
3923- src/parse-nm.c | 6 +++++-
3924- src/parse.c | 5 +++++
3925- tests/generator/test_tunnels.py | 9 ++++++++
3926- tests/parser/test_keyfile.py | 37 +++++++++++++++++++++++++++++++++
3927- 4 files changed, 56 insertions(+), 1 deletion(-)
3928-
3929---- a/src/parse-nm.c
3930-+++ b/src/parse-nm.c
3931-@@ -552,7 +552,11 @@
3932- }
3933-
3934- /* Handle endpoint */
3935-- wireguard_peer->endpoint = g_key_file_get_string(kf, group, "endpoint", NULL);
3936-+ gchar* endpoint = g_key_file_get_string(kf, group, "endpoint", NULL);
3937-+ if (endpoint && g_strcmp0(endpoint, "")) {
3938-+ /* Only set the endpoint if it's not NULL nor an empty string */
3939-+ wireguard_peer->endpoint = endpoint;
3940-+ }
3941- _kf_clear_key(kf, group, "endpoint");
3942-
3943- g_array_append_val(nd->wireguard_peers, wireguard_peer);
3944---- a/src/parse.c
3945-+++ b/src/parse.c
3946-@@ -2445,6 +2445,11 @@
3947- char* address;
3948- guint64 port_num;
3949-
3950-+ /* If endpoint is an empty string just ignore it */
3951-+ if (!g_strcmp0(scalar(node), "")) {
3952-+ return TRUE;
3953-+ }
3954-+
3955- endpoint = g_strdup(scalar(node));
3956- /* absolute minimal length of endpoint is 3 chars: 'h:8' */
3957- if (strlen(endpoint) < 3) {
3958---- a/tests/generator/test_tunnels.py
3959-+++ b/tests/generator/test_tunnels.py
3960-@@ -309,6 +309,15 @@
3961- out = self.generate(config, expect_fail=True)
3962- self.assertIn("Error in network definition: wg0: a public key is required.", out)
3963-
3964-+ def test_empty_string_as_endpoint_should_be_ignored(self):
3965-+ """[wireguard] If the endpoint key is present but set to '' it should just be ignored"""
3966-+ config = prepare_wg_config(listen=12345, privkey='KPt9BzQjejRerEv8RMaFlpsD675gNexELOQRXt/AcH0=',
3967-+ peers=[{'public-key': 'rlbInAj0qV69CysWPQY7KEBnKxpYCpaWqOs/dLevdWc=',
3968-+ 'allowed-ips': '[0.0.0.0/0, "2001:fe:ad:de:ad:be:ef:1/24"]',
3969-+ 'keepalive': 14,
3970-+ 'endpoint': '\"\"'}], renderer=self.backend)
3971-+ self.generate(config, skip_generated_yaml_validation=True)
3972-+
3973- def test_vxlan_port_range_fail(self):
3974- out = self.generate('''network:
3975- tunnels:
3976---- a/tests/parser/test_keyfile.py
3977-+++ b/tests/parser/test_keyfile.py
3978-@@ -1591,6 +1591,43 @@
3979- connection.interface-name: "wg0"
3980- '''.format(UUID, UUID)})
3981-
3982-+ def test_wireguard_with_empty_endpoint(self):
3983-+ self.generate_from_keyfile('''[connection]
3984-+id=wg0
3985-+type=wireguard
3986-+uuid={}
3987-+interface-name=wg0
3988-+
3989-+[wireguard]
3990-+private-key=aPUcp5vHz8yMLrzk8SsDyYnV33IhE/k20e52iKJFV0A=
3991-+
3992-+[wireguard-peer.cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI=]
3993-+endpoint=
3994-+allowed-ips=192.168.0.0/24;
3995-+
3996-+[ipv4]
3997-+method=auto\n'''.format(UUID), regenerate=False)
3998-+ self.assert_netplan({UUID: '''network:
3999-+ version: 2
4000-+ tunnels:
4001-+ NM-{}:
4002-+ renderer: NetworkManager
4003-+ dhcp4: true
4004-+ mode: "wireguard"
4005-+ keys:
4006-+ private: "aPUcp5vHz8yMLrzk8SsDyYnV33IhE/k20e52iKJFV0A="
4007-+ peers:
4008-+ - keys:
4009-+ public: "cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI="
4010-+ allowed-ips:
4011-+ - "192.168.0.0/24"
4012-+ networkmanager:
4013-+ uuid: "{}"
4014-+ name: "wg0"
4015-+ passthrough:
4016-+ connection.interface-name: "wg0"
4017-+'''.format(UUID, UUID)})
4018-+
4019- def test_wireguard_allowed_ips_without_prefix(self):
4020- '''
4021- When the IP prefix is not present we should default to /32
4022diff --git a/debian/patches/lp2039825/0009-auth-add-support-for-LEAP-and-EAP-PWD.patch b/debian/patches/lp2039825/0009-auth-add-support-for-LEAP-and-EAP-PWD.patch
4023deleted file mode 100644
4024index d13d07e..0000000
4025--- a/debian/patches/lp2039825/0009-auth-add-support-for-LEAP-and-EAP-PWD.patch
4026+++ /dev/null
4027@@ -1,371 +0,0 @@
4028-From 4a5a9ed735688c3c19cd86d6638ec4ff5bdf17e4 Mon Sep 17 00:00:00 2001
4029-From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
4030-Date: Tue, 10 Oct 2023 16:21:53 +0100
4031-Subject: auth: add support for LEAP and EAP-PWD
4032-
4033-This changes add support for the LEAP and PWD EAP authentication methods
4034-for NetworkManager, wpa_supplicant (networkd) and the keyfile parser.
4035-
4036-Using these method through the NM GUI is causing problems because
4037-libnetplan will generate a broken keyfile. See LP: #2038811
4038-
4039-Note that the NM GUI supports more methods not recognized by netplan and
4040-we probably should also implement them later.
4041-
4042-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2039825
4043-Origin: https://github.com/canonical/netplan/pull/415
4044----
4045- doc/netplan-yaml.md | 3 +-
4046- src/abi.h | 2 +
4047- src/names.c | 2 +
4048- src/networkd.c | 8 +++
4049- src/nm.c | 6 ++
4050- src/parse-nm.c | 4 ++
4051- src/parse.c | 4 ++
4052- tests/generator/test_wifis.py | 124 ++++++++++++++++++++++++++++++++++
4053- tests/parser/test_keyfile.py | 100 +++++++++++++++++++++++++++
4054- 9 files changed, 252 insertions(+), 1 deletion(-)
4055-
4056---- a/src/abi.h
4057-+++ b/src/abi.h
4058-@@ -116,6 +116,8 @@
4059- NETPLAN_AUTH_EAP_TLS,
4060- NETPLAN_AUTH_EAP_PEAP,
4061- NETPLAN_AUTH_EAP_TTLS,
4062-+ NETPLAN_AUTH_EAP_LEAP,
4063-+ NETPLAN_AUTH_EAP_PWD,
4064- NETPLAN_AUTH_EAP_METHOD_MAX,
4065- } NetplanAuthEAPMethod;
4066-
4067---- a/src/names.c
4068-+++ b/src/names.c
4069-@@ -70,6 +70,8 @@
4070- [NETPLAN_AUTH_EAP_TLS] = "tls",
4071- [NETPLAN_AUTH_EAP_PEAP] = "peap",
4072- [NETPLAN_AUTH_EAP_TTLS] = "ttls",
4073-+ [NETPLAN_AUTH_EAP_LEAP] = "leap",
4074-+ [NETPLAN_AUTH_EAP_PWD] = "pwd",
4075- };
4076-
4077- static const char* const
4078---- a/src/networkd.c
4079-+++ b/src/networkd.c
4080-@@ -1082,6 +1082,14 @@
4081- g_string_append(s, " eap=TTLS\n");
4082- break;
4083-
4084-+ case NETPLAN_AUTH_EAP_LEAP:
4085-+ g_string_append(s, " eap=LEAP\n");
4086-+ break;
4087-+
4088-+ case NETPLAN_AUTH_EAP_PWD:
4089-+ g_string_append(s, " eap=PWD\n");
4090-+ break;
4091-+
4092- default: break; // LCOV_EXCL_LINE
4093- }
4094-
4095---- a/src/nm.c
4096-+++ b/src/nm.c
4097-@@ -417,6 +417,12 @@
4098- case NETPLAN_AUTH_EAP_TTLS:
4099- g_key_file_set_string(kf, "802-1x", "eap", "ttls");
4100- break;
4101-+ case NETPLAN_AUTH_EAP_LEAP:
4102-+ g_key_file_set_string(kf, "802-1x", "eap", "leap");
4103-+ break;
4104-+ case NETPLAN_AUTH_EAP_PWD:
4105-+ g_key_file_set_string(kf, "802-1x", "eap", "pwd");
4106-+ break;
4107- default: break; // LCOV_EXCL_LINE
4108- }
4109-
4110---- a/src/parse-nm.c
4111-+++ b/src/parse-nm.c
4112-@@ -386,6 +386,10 @@
4113- auth->eap_method = NETPLAN_AUTH_EAP_PEAP;
4114- } else if (g_strcmp0(first_method, "ttls") == 0) {
4115- auth->eap_method = NETPLAN_AUTH_EAP_TTLS;
4116-+ } else if (g_strcmp0(first_method, "leap") == 0) {
4117-+ auth->eap_method = NETPLAN_AUTH_EAP_LEAP;
4118-+ } else if (g_strcmp0(first_method, "pwd") == 0) {
4119-+ auth->eap_method = NETPLAN_AUTH_EAP_PWD;
4120- }
4121-
4122- /* If "method" (which is a list separated by ";") has more than one value,
4123---- a/src/parse.c
4124-+++ b/src/parse.c
4125-@@ -935,6 +935,10 @@
4126- auth->eap_method = NETPLAN_AUTH_EAP_PEAP;
4127- else if (strcmp(scalar(node), "ttls") == 0)
4128- auth->eap_method = NETPLAN_AUTH_EAP_TTLS;
4129-+ else if (strcmp(scalar(node), "leap") == 0)
4130-+ auth->eap_method = NETPLAN_AUTH_EAP_LEAP;
4131-+ else if (strcmp(scalar(node), "pwd") == 0)
4132-+ auth->eap_method = NETPLAN_AUTH_EAP_PWD;
4133- else
4134- return yaml_error(npp, node, error, "unknown EAP method '%s'", scalar(node));
4135- return TRUE;
4136---- a/tests/generator/test_wifis.py
4137-+++ b/tests/generator/test_wifis.py
4138-@@ -363,6 +363,54 @@
4139- }
4140- """)
4141-
4142-+ def test_wifi_ieee8021x_eap_leap(self):
4143-+ self.generate('''network:
4144-+ version: 2
4145-+ wifis:
4146-+ wl0:
4147-+ access-points:
4148-+ homenet:
4149-+ auth:
4150-+ key-management: 802.1x
4151-+ method: leap
4152-+ identity: some-id
4153-+ password: "********"''')
4154-+
4155-+ self.assert_wpa_supplicant("wl0", """ctrl_interface=/run/wpa_supplicant
4156-+
4157-+network={
4158-+ ssid="homenet"
4159-+ key_mgmt=IEEE8021X
4160-+ eap=LEAP
4161-+ identity="some-id"
4162-+ password="********"
4163-+}
4164-+""")
4165-+
4166-+ def test_wifi_ieee8021x_eap_pwd(self):
4167-+ self.generate('''network:
4168-+ version: 2
4169-+ wifis:
4170-+ wl0:
4171-+ access-points:
4172-+ homenet:
4173-+ auth:
4174-+ key-management: 802.1x
4175-+ method: pwd
4176-+ identity: some-id
4177-+ password: "********"''')
4178-+
4179-+ self.assert_wpa_supplicant("wl0", """ctrl_interface=/run/wpa_supplicant
4180-+
4181-+network={
4182-+ ssid="homenet"
4183-+ key_mgmt=IEEE8021X
4184-+ eap=PWD
4185-+ identity="some-id"
4186-+ password="********"
4187-+}
4188-+""")
4189-+
4190-
4191- class TestNetworkManager(TestBase):
4192-
4193-@@ -703,6 +751,82 @@
4194- psk=********
4195- '''})
4196-
4197-+ def test_wifi_ieee8021x_leap(self):
4198-+ self.generate('''network:
4199-+ version: 2
4200-+ renderer: NetworkManager
4201-+ wifis:
4202-+ wl0:
4203-+ access-points:
4204-+ homenet:
4205-+ auth:
4206-+ key-management: 802.1x
4207-+ method: leap
4208-+ identity: "some-id"
4209-+ password: "**********"''')
4210-+
4211-+ self.assert_nm({'wl0-homenet': '''[connection]
4212-+id=netplan-wl0-homenet
4213-+type=wifi
4214-+interface-name=wl0
4215-+
4216-+[ipv4]
4217-+method=link-local
4218-+
4219-+[ipv6]
4220-+method=ignore
4221-+
4222-+[wifi]
4223-+ssid=homenet
4224-+mode=infrastructure
4225-+
4226-+[wifi-security]
4227-+key-mgmt=ieee8021x
4228-+
4229-+[802-1x]
4230-+eap=leap
4231-+identity=some-id
4232-+password=**********
4233-+'''})
4234-+
4235-+ def test_wifi_ieee8021x_pwd(self):
4236-+ self.generate('''network:
4237-+ version: 2
4238-+ renderer: NetworkManager
4239-+ wifis:
4240-+ wl0:
4241-+ access-points:
4242-+ homenet:
4243-+ auth:
4244-+ key-management: 802.1x
4245-+ method: pwd
4246-+ identity: "some-id"
4247-+ password: "**********"''')
4248-+
4249-+ self.assert_nm({'wl0-homenet': '''[connection]
4250-+id=netplan-wl0-homenet
4251-+type=wifi
4252-+interface-name=wl0
4253-+
4254-+[ipv4]
4255-+method=link-local
4256-+
4257-+[ipv6]
4258-+method=ignore
4259-+
4260-+[wifi]
4261-+ssid=homenet
4262-+mode=infrastructure
4263-+
4264-+[wifi-security]
4265-+key-mgmt=ieee8021x
4266-+
4267-+[802-1x]
4268-+eap=pwd
4269-+identity=some-id
4270-+password=**********
4271-+'''})
4272-+
4273- def test_wifi_wowlan(self):
4274- self.generate('''network:
4275- version: 2
4276---- a/tests/parser/test_keyfile.py
4277-+++ b/tests/parser/test_keyfile.py
4278-@@ -526,6 +526,106 @@
4279- def test_keyfile_type_wifi_eap_ttls(self):
4280- self._template_keyfile_type_wifi_eap('ttls')
4281-
4282-+ def test_keyfile_type_wifi_eap_leap(self):
4283-+ self._template_keyfile_type_wifi_eap('leap')
4284-+
4285-+ def test_keyfile_type_wifi_eap_pwd(self):
4286-+ self._template_keyfile_type_wifi_eap('pwd')
4287-+
4288-+ def test_keyfile_wifi_eap_leap(self):
4289-+ self.generate_from_keyfile('''[connection]
4290-+type=wifi
4291-+uuid={}
4292-+permissions=
4293-+id=myid with spaces
4294-+interface-name=eth0
4295-+
4296-+[wifi]
4297-+ssid=SOME-SSID
4298-+mode=infrastructure
4299-+
4300-+[wifi-security]
4301-+key-mgmt=ieee8021x
4302-+
4303-+[802-1x]
4304-+eap=leap
4305-+identity=some-id
4306-+password=v3rys3cr3t!
4307-+
4308-+[ipv4]
4309-+method=auto'''.format(UUID))
4310-+ self.assert_netplan({UUID: '''network:
4311-+ version: 2
4312-+ wifis:
4313-+ NM-{}:
4314-+ renderer: NetworkManager
4315-+ match:
4316-+ name: "eth0"
4317-+ dhcp4: true
4318-+ access-points:
4319-+ "SOME-SSID":
4320-+ auth:
4321-+ key-management: "802.1x"
4322-+ method: "leap"
4323-+ identity: "some-id"
4324-+ password: "v3rys3cr3t!"
4325-+ networkmanager:
4326-+ uuid: "{}"
4327-+ name: "myid with spaces"
4328-+ passthrough:
4329-+ connection.permissions: ""
4330-+ networkmanager:
4331-+ uuid: "{}"
4332-+ name: "myid with spaces"
4333-+'''.format(UUID, UUID, UUID)})
4334-+
4335-+ def test_keyfile_wifi_eap_pwd(self):
4336-+ self.generate_from_keyfile('''[connection]
4337-+type=wifi
4338-+uuid={}
4339-+permissions=
4340-+id=myid with spaces
4341-+interface-name=eth0
4342-+
4343-+[wifi]
4344-+ssid=SOME-SSID
4345-+mode=infrastructure
4346-+
4347-+[wifi-security]
4348-+key-mgmt=ieee8021x
4349-+
4350-+[802-1x]
4351-+eap=pwd
4352-+identity=some-id
4353-+password=v3rys3cr3t!
4354-+
4355-+[ipv4]
4356-+method=auto'''.format(UUID))
4357-+ self.assert_netplan({UUID: '''network:
4358-+ version: 2
4359-+ wifis:
4360-+ NM-{}:
4361-+ renderer: NetworkManager
4362-+ match:
4363-+ name: "eth0"
4364-+ dhcp4: true
4365-+ access-points:
4366-+ "SOME-SSID":
4367-+ auth:
4368-+ key-management: "802.1x"
4369-+ method: "pwd"
4370-+ identity: "some-id"
4371-+ password: "v3rys3cr3t!"
4372-+ networkmanager:
4373-+ uuid: "{}"
4374-+ name: "myid with spaces"
4375-+ passthrough:
4376-+ connection.permissions: ""
4377-+ networkmanager:
4378-+ uuid: "{}"
4379-+ name: "myid with spaces"
4380-+'''.format(UUID, UUID, UUID)})
4381-+
4382- def _template_keyfile_type_wifi(self, nd_mode, nm_mode):
4383- self.generate_from_keyfile('''[connection]
4384- type=wifi
4385---- a/doc/netplan-yaml.md
4386-+++ b/doc/netplan-yaml.md
4387-@@ -862,8 +862,9 @@
4388-
4389- - **method** (scalar)
4390-
4391-- > The EAP method to use. The supported EAP methods are `tls` (TLS),
4392-- > `peap` (Protected EAP), and `ttls` (Tunneled TLS).
4393-+ > The EAP method to use. The supported EAP methods are `tls` (TLS),
4394-+ > `peap` (Protected EAP), `leap` (Lightweight EAP), `pwd` (EAP Password)
4395-+ > and `ttls` (Tunneled TLS).
4396-
4397- - **identity** (scalar)
4398-
4399diff --git a/debian/patches/lp2041727/0004-cli-utils-introduce-systemctl_is_installed-helper.patch b/debian/patches/lp2041727/0004-cli-utils-introduce-systemctl_is_installed-helper.patch
4400new file mode 100644
4401index 0000000..2ac4c6b
4402--- /dev/null
4403+++ b/debian/patches/lp2041727/0004-cli-utils-introduce-systemctl_is_installed-helper.patch
4404@@ -0,0 +1,63 @@
4405+From: =?utf-8?q?Lukas_M=C3=A4rdian?= <slyon@ubuntu.com>
4406+Date: Thu, 25 Jan 2024 12:40:06 +0100
4407+Subject: cli:utils: introduce systemctl_is_installed helper
4408+
4409+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2041727
4410+Origin: https://github.com/canonical/netplan/pull/421
4411+---
4412+ netplan_cli/cli/utils.py | 10 ++++++++++
4413+ tests/test_utils.py | 20 ++++++++++++++++++++
4414+ 2 files changed, 30 insertions(+)
4415+
4416+diff --git a/netplan_cli/cli/utils.py b/netplan_cli/cli/utils.py
4417+index a5f60c9..f913630 100644
4418+--- a/netplan_cli/cli/utils.py
4419++++ b/netplan_cli/cli/utils.py
4420+@@ -148,6 +148,16 @@ def systemctl_is_masked(unit_pattern):
4421+ return False
4422+
4423+
4424++def systemctl_is_installed(unit_pattern):
4425++ '''Return True if returncode is other than "not-found" (4)'''
4426++ res = subprocess.run(['systemctl', 'is-enabled', unit_pattern],
4427++ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
4428++ text=True)
4429++ if res.returncode != 4:
4430++ return True
4431++ return False
4432++
4433++
4434+ def systemctl_daemon_reload():
4435+ '''Reload systemd unit files from disk and re-calculate its dependencies'''
4436+ subprocess.check_call(['systemctl', 'daemon-reload'])
4437+diff --git a/tests/test_utils.py b/tests/test_utils.py
4438+index b2a1657..eefd334 100644
4439+--- a/tests/test_utils.py
4440++++ b/tests/test_utils.py
4441+@@ -354,6 +354,26 @@ class TestUtils(unittest.TestCase):
4442+ ['systemctl', 'is-enabled', 'some.service']
4443+ ])
4444+
4445++ def test_systemctl_is_installed(self):
4446++ self.mock_cmd = MockCmd('systemctl')
4447++ self.mock_cmd.set_returncode(0)
4448++ path_env = os.environ['PATH']
4449++ os.environ['PATH'] = os.path.dirname(self.mock_cmd.path) + os.pathsep + path_env
4450++ self.assertTrue(utils.systemctl_is_installed('some.service'))
4451++ self.assertEqual(self.mock_cmd.calls(), [
4452++ ['systemctl', 'is-enabled', 'some.service']
4453++ ])
4454++
4455++ def test_systemctl_is_installed_false(self):
4456++ self.mock_cmd = MockCmd('systemctl')
4457++ self.mock_cmd.set_returncode(4)
4458++ path_env = os.environ['PATH']
4459++ os.environ['PATH'] = os.path.dirname(self.mock_cmd.path) + os.pathsep + path_env
4460++ self.assertFalse(utils.systemctl_is_installed('some.service'))
4461++ self.assertEqual(self.mock_cmd.calls(), [
4462++ ['systemctl', 'is-enabled', 'some.service']
4463++ ])
4464++
4465+ def test_systemctl_daemon_reload(self):
4466+ self.mock_cmd = MockCmd('systemctl')
4467+ path_env = os.environ['PATH']
4468diff --git a/debian/patches/lp2041727/0005-Update-ovs.py-to-check-if-ovsdb-server.service-is-in.patch b/debian/patches/lp2041727/0005-Update-ovs.py-to-check-if-ovsdb-server.service-is-in.patch
4469new file mode 100644
4470index 0000000..472c6bc
4471--- /dev/null
4472+++ b/debian/patches/lp2041727/0005-Update-ovs.py-to-check-if-ovsdb-server.service-is-in.patch
4473@@ -0,0 +1,75 @@
4474+From: Tom <96974474+viciousdrop@users.noreply.github.com>
4475+Date: Mon, 6 Nov 2023 20:38:14 +0800
4476+Subject: Update ovs.py to check if ovsdb-server.service is installed before
4477+ throwing an error
4478+
4479+Adopted changes outlined in this bug
4480+Credit: https://github.com/brianfinley
4481+https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2041727
4482+"WARNING:root:Cannot call Open vSwitch: ovsdb-server.service is not running."
4483+
4484+Co-Authored-by: Lukas Märdian <slyon@ubuntu.com>
4485+
4486+This patch also includes a trivial change from
4487+https://github.com/canonical/netplan/commit/95e4d51435c2e9c9a6b7382e39c0306200ee1b9b
4488+
4489+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2041727
4490+Origin: https://github.com/canonical/netplan/pull/421
4491+---
4492+ netplan_cli/cli/commands/apply.py | 4 +++-
4493+ netplan_cli/cli/ovs.py | 9 ++++++++-
4494+ 2 files changed, 11 insertions(+), 2 deletions(-)
4495+
4496+diff --git a/netplan_cli/cli/commands/apply.py b/netplan_cli/cli/commands/apply.py
4497+index 066f496..9c88a3c 100644
4498+--- a/netplan_cli/cli/commands/apply.py
4499++++ b/netplan_cli/cli/commands/apply.py
4500+@@ -31,7 +31,7 @@ import time
4501+ from .. import utils
4502+ from ...configmanager import ConfigManager, ConfigurationError
4503+ from ..sriov import apply_sriov_config
4504+-from ..ovs import OvsDbServerNotRunning, apply_ovs_cleanup
4505++from ..ovs import OvsDbServerNotRunning, OvsDbServerNotInstalled, apply_ovs_cleanup
4506+
4507+
4508+ OVS_CLEANUP_SERVICE = 'netplan-ovs-cleanup.service'
4509+@@ -433,3 +433,5 @@ class NetplanApply(utils.NetplanCommand):
4510+ sys.exit(1)
4511+ except OvsDbServerNotRunning as e:
4512+ logging.warning('Cannot call Open vSwitch: {}.'.format(e))
4513++ except OvsDbServerNotInstalled as e:
4514++ logging.debug('Cannot call Open vSwitch: %s.', e)
4515+diff --git a/netplan_cli/cli/ovs.py b/netplan_cli/cli/ovs.py
4516+index 0ba0482..0caab72 100644
4517+--- a/netplan_cli/cli/ovs.py
4518++++ b/netplan_cli/cli/ovs.py
4519+@@ -20,7 +20,7 @@ import os
4520+ import subprocess
4521+ import re
4522+
4523+-from .utils import systemctl_is_active
4524++from .utils import systemctl_is_active, systemctl_is_installed
4525+
4526+ OPENVSWITCH_OVS_VSCTL = '/usr/bin/ovs-vsctl'
4527+ OPENVSWITCH_OVSDB_SERVER_UNIT = 'ovsdb-server.service'
4528+@@ -43,6 +43,10 @@ class OvsDbServerNotRunning(Exception):
4529+ pass
4530+
4531+
4532++class OvsDbServerNotInstalled(Exception):
4533++ pass
4534++
4535++
4536+ def _del_col(type, iface, column, value):
4537+ """Cleanup values from a column (i.e. "column=value")"""
4538+ default = DEFAULTS.get(column)
4539+@@ -125,6 +129,9 @@ def apply_ovs_cleanup(config_manager, ovs_old, ovs_current): # pragma: nocover
4540+ Also filter for individual settings tagged netplan/<column>[/<key]=value
4541+ in external-ids and clear them if they have been set by netplan.
4542+ """
4543++ if not systemctl_is_installed(OPENVSWITCH_OVSDB_SERVER_UNIT):
4544++ raise OvsDbServerNotInstalled("Cannot apply OVS cleanup: %s is 'not-found'" %
4545++ OPENVSWITCH_OVSDB_SERVER_UNIT)
4546+ if not systemctl_is_active(OPENVSWITCH_OVSDB_SERVER_UNIT):
4547+ raise OvsDbServerNotRunning('{} is not running'.format(OPENVSWITCH_OVSDB_SERVER_UNIT))
4548+
4549diff --git a/debian/patches/series b/debian/patches/series
4550index 4d9d078..8021670 100644
4551--- a/debian/patches/series
4552+++ b/debian/patches/series
4553@@ -1,11 +1,6 @@
4554-0001-parse-allow-COMMON_LINK_HANDLERS-for-VRFs-LP-2031421.patch
4555-0002-test-ovs-Avoid-NetworkManager-taking-contol-breaking.patch
4556-0003-util-don-t-return-a-placeholder-netdef-in-the-iterat.patch
4557-lp2034067/0004-tunnels-validation-do-not-error-out-if-local-is-not-.patch
4558-lp2034067/0005-tests-add-some-integration-tests-without-the-local-a.patch
4559-lp2034595/0006-apply-bring-lo-back-up-if-it-s-managed-by-NM.patch
4560-lp2034595/0007-apply-don-t-assume-the-NM-loopback-connection-is-cal.patch
4561-lp2039821/0008-wireguard-ignore-empty-endpoints.patch
4562-lp2039825/0009-auth-add-support-for-LEAP-and-EAP-PWD.patch
4563-lp1809994/0010-parse-improve-the-parsing-of-access-points-LP-180999.patch
4564-lp1809994/0011-wifi-replace-the-previously-defined-AP-with-the-new-.patch
4565+0001-parse-nm-wg-append-the-correct-prefix-to-IPv6-addres.patch
4566+lp2041727/0004-cli-utils-introduce-systemctl_is_installed-helper.patch
4567+lp2041727/0005-Update-ovs.py-to-check-if-ovsdb-server.service-is-in.patch
4568+0007-tests-assert-generated-.service-files-in-assert_srio.patch
4569+0008-tests-sriov-test-if-the-generated-netplan-rebind-ser.patch
4570+0009-sriov-don-t-generate-duplicate-entries-in-the-rebind.patch
4571diff --git a/debian/rules b/debian/rules
4572index 6f54c41..2780683 100755
4573--- a/debian/rules
4574+++ b/debian/rules
4575@@ -19,7 +19,3 @@ execute_after_dh_auto_install:
4576 rm -rf debian/tmp/usr/lib/python3/dist-packages/netplan/__pycache__/
4577 # Drop legacy symlink
4578 rm debian/tmp/lib/netplan/generate
4579- # Fix non-usrmerged paths & drop legacy symlink
4580- # rm -rf debian/tmp/lib
4581- # mkdir -p debian/tmp/usr/lib/systemd/system-generators
4582- # ln -s /usr/libexec/netplan/generate debian/tmp/usr/lib/systemd/system-generators/netplan
4583diff --git a/debian/tests/prep-testbed.sh b/debian/tests/prep-testbed.sh
4584index 6729083..0866460 100755
4585--- a/debian/tests/prep-testbed.sh
4586+++ b/debian/tests/prep-testbed.sh
4587@@ -5,6 +5,9 @@ if [ "$(systemctl is-active NetworkManager.service)" = active ]; then
4588 systemctl stop NetworkManager.service
4589 fi
4590
4591+# Make sure the system is ready before starting our tests
4592+systemctl daemon-reload
4593+
4594 # only relevant on Debian
4595 dpkg-vendor --is Debian || exit 0
4596
4597diff --git a/doc/apidoc/inc-netplan.md b/doc/apidoc/inc-netplan.md
4598new file mode 100644
4599index 0000000..cdee9bf
4600--- /dev/null
4601+++ b/doc/apidoc/inc-netplan.md
4602@@ -0,0 +1,4 @@
4603+# netplan.h
4604+
4605+```{autodoxygenfile} include/netplan.h
4606+```
4607diff --git a/doc/apidoc/inc-parse-nm.md b/doc/apidoc/inc-parse-nm.md
4608new file mode 100644
4609index 0000000..3129f1d
4610--- /dev/null
4611+++ b/doc/apidoc/inc-parse-nm.md
4612@@ -0,0 +1,4 @@
4613+# parse-nm.h
4614+
4615+```{autodoxygenfile} include/parse-nm.h
4616+```
4617diff --git a/doc/apidoc/inc-parse.md b/doc/apidoc/inc-parse.md
4618new file mode 100644
4619index 0000000..733585a
4620--- /dev/null
4621+++ b/doc/apidoc/inc-parse.md
4622@@ -0,0 +1,4 @@
4623+# parse.h
4624+
4625+```{autodoxygenfile} include/parse.h
4626+```
4627diff --git a/doc/apidoc/inc-types.md b/doc/apidoc/inc-types.md
4628new file mode 100644
4629index 0000000..767296e
4630--- /dev/null
4631+++ b/doc/apidoc/inc-types.md
4632@@ -0,0 +1,4 @@
4633+# types.h
4634+
4635+```{autodoxygenfile} include/types.h
4636+```
4637diff --git a/doc/apidoc/inc-util.md b/doc/apidoc/inc-util.md
4638new file mode 100644
4639index 0000000..7fc3c0c
4640--- /dev/null
4641+++ b/doc/apidoc/inc-util.md
4642@@ -0,0 +1,4 @@
4643+# util.h
4644+
4645+```{autodoxygenfile} include/util.h
4646+```
4647diff --git a/doc/apidoc/index.md b/doc/apidoc/index.md
4648new file mode 100644
4649index 0000000..927ef3d
4650--- /dev/null
4651+++ b/doc/apidoc/index.md
4652@@ -0,0 +1,52 @@
4653+# Reference: libnetplan API
4654+
4655+## Public headers
4656+```{toctree}
4657+---
4658+maxdepth: 1
4659+---
4660+inc-netplan
4661+```
4662+> ```{autodoxygenfile} include/netplan.h
4663+> :sections: briefdescription
4664+> ```
4665+
4666+```{toctree}
4667+---
4668+maxdepth: 1
4669+---
4670+inc-parse-nm
4671+```
4672+> ```{autodoxygenfile} include/parse-nm.h
4673+> :sections: briefdescription
4674+> ```
4675+
4676+```{toctree}
4677+---
4678+maxdepth: 1
4679+---
4680+inc-parse
4681+```
4682+> ```{autodoxygenfile} include/parse.h
4683+> :sections: briefdescription
4684+> ```
4685+
4686+```{toctree}
4687+---
4688+maxdepth: 1
4689+---
4690+inc-types
4691+```
4692+> ```{autodoxygenfile} include/types.h
4693+> :sections: briefdescription
4694+> ```
4695+
4696+```{toctree}
4697+---
4698+maxdepth: 1
4699+---
4700+inc-util
4701+```
4702+> ```{autodoxygenfile} include/util.h
4703+> :sections: briefdescription
4704+> ```
4705\ No newline at end of file
4706diff --git a/doc/conf.py b/doc/conf.py
4707index 8e5aef7..061173e 100644
4708--- a/doc/conf.py
4709+++ b/doc/conf.py
4710@@ -27,10 +27,32 @@ author = 'Netplan team'
4711 # Add any Sphinx extension module names here, as strings. They can be
4712 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
4713 # ones.
4714-extensions = ['sphinx_design', 'myst_parser', 'sphinx_copybutton']
4715+extensions = ['sphinx_design', 'myst_parser', 'sphinx_copybutton', 'sphinxcontrib.spelling', 'breathe']
4716 myst_enable_extensions = ["colon_fence"]
4717 smartquotes_action = 'qe'
4718
4719+# Doxygen
4720+# https://breathe.readthedocs.io/en/latest/directives.html
4721+# breathe_projects = {"Netplan": "../doxyxml/"}
4722+breathe_projects_source = {"auto-apidoc": ("../", [
4723+ "include/netplan.h",
4724+ "include/parse-nm.h",
4725+ "include/parse.h",
4726+ "include/types.h",
4727+ "include/util.h",
4728+ "src/error.c",
4729+ "src/names.c",
4730+ "src/netplan.c",
4731+ "src/parse-nm.c",
4732+ "src/parse.c",
4733+ "src/types.c",
4734+ "src/util.c",
4735+ "src/validation.c",
4736+ ])}
4737+# breathe_doxygen_config_options =
4738+# breathe_doxygen_aliases =
4739+breathe_default_project = "auto-apidoc"
4740+
4741 # Add any paths that contain templates here, relative to this directory.
4742 templates_path = ['_templates']
4743
4744@@ -57,3 +79,9 @@ html_logo = 'netplan.svg'
4745
4746 # -- Options for MyST --------------------------------------------------------
4747 myst_title_to_header = True
4748+suppress_warnings = ['myst.xref_missing']
4749+
4750+# Spelling
4751+spelling_lang = 'en_US'
4752+tokenizer_lang = 'en_US'
4753+spelling_show_suggestions = True
4754diff --git a/doc/contribute-docs.md b/doc/contribute-docs.md
4755new file mode 100644
4756index 0000000..fc7e459
4757--- /dev/null
4758+++ b/doc/contribute-docs.md
4759@@ -0,0 +1,26 @@
4760+# Contribute Documentation
4761+
4762+## Reporting an issue
4763+
4764+If you find any issue in Netplan's documentation please [file a bugreport](https://bugs.launchpad.net/netplan/+filebug?field.tags=documentation)
4765+about it in our bugtracker at Launchpad. Remember adding a `documentation` tag
4766+to it.
4767+
4768+## Modifying documentation online
4769+
4770+Each documentation page, rendered on the web contains an "Edit this page" at
4771+the top-right of every page, besides the documentation title. Clicking this
4772+button will lead you to the GitHub web-editor where you can easily propose
4773+changes to the corresponding page.
4774+
4775+Please remember to first check the [latest version](https://netplan.readthedocs.io/en/latest/)
4776+of our documentation and make your proposal based on that revision.
4777+
4778+## Creating a pull-request
4779+
4780+If you want to follow a git development workflow, you can also checkout the
4781+[Netplan repository](https://github.com/canonical/netplan) and contribute your
4782+changes as [pull-requests](https://github.com/canonical/netplan/pulls), putting
4783+the `documentation` label for better visibility.
4784+
4785+Please see the `doc/` and `examples/` directories for relevant files.
4786diff --git a/doc/howto.md b/doc/howto.md
4787index 5c46a86..dd8d00d 100644
4788--- a/doc/howto.md
4789+++ b/doc/howto.md
4790@@ -4,4 +4,5 @@
4791 examples
4792 dbus-config
4793 netplan-everywhere
4794+contribute-docs
4795 ```
4796diff --git a/doc/netplan-everywhere.md b/doc/netplan-everywhere.md
4797index 1ae30ca..ae346fe 100644
4798--- a/doc/netplan-everywhere.md
4799+++ b/doc/netplan-everywhere.md
4800@@ -1,6 +1,6 @@
4801 # Desktop integration
4802
4803-## NetworkManager YAML settings backend (Netplan everywhere)
4804+## NetworkManager YAML settings backend
4805
4806 NetworkManager is the tool used by Ubuntu Desktop systems to manage
4807 network devices such as Ethernet and Wifi adapters. While it is a great
4808@@ -8,85 +8,79 @@ tool for the job and users can directly use it through the command line
4809 and the graphical interfaces to configure their devices, Ubuntu has its
4810 own way of describing and storing network configuration via Netplan.
4811
4812-On Ubuntu, NetworkManager uses (or will use, depending on when you are
4813-reading this) Netplan's APIs to save the configuration created by the
4814-user using any of its interfaces. Our goal is to have a centralized place
4815-to store network configuration. In the Desktop it's convenient to use
4816-graphical tools for configuration when they are available, so nothing will
4817-change from the user perspective, only the way the configuration is
4818-handled under the hood.
4819+On Ubuntu 23.10 "Mantic Minotaur" and later, NetworkManager uses Netplan APIs
4820+to save the configuration created using any of its graphical or programmatic
4821+interfaces. This leads to having a centralized location to store network
4822+configuration. On the Desktop, it's convenient to use graphical tools for
4823+configuration when they are available, so nothing changes from the user
4824+perspective; only the way the system handles the configuration in the background.
4825
4826-For more information on Netplan, check https://netplan.io/
4827+For more information on Netplan, see [https://netplan.io](https://netplan.io).
4828
4829-For more information on NetworkManager, check https://networkmanager.dev/
4830+For more information on NetworkManager, see [https://networkmanager.dev](https://networkmanager.dev).
4831
4832 ## How it works
4833
4834 Every time a non-temporary connection is created in NetworkManager, instead
4835-of persisting the original .nmconnection file, it will create a Netplan YAML
4836-at `/etc/netplan` called `90-NM-<connection UUID>.yaml`. After creating the
4837-file, NetworkManager will call the Netplan generator to emit the configuration
4838-for that connection. Connections that are temporary, like the ones created
4839-for virtual network interfaces when you connect to a VPN for example, are not
4840-persisted as Netplan files. The reason for that is that these interfaces are
4841-usually managed by external services and we don't want to cause any unexpected
4842-change that would affect them.
4843+of persisting the original `.nmconnection` file, it creates a Netplan YAML
4844+file in `/etc/netplan/` called `90-NM-<connection UUID>.yaml`. After creating
4845+the file, NetworkManager calls the Netplan generator to provide the
4846+configuration for that connection. Connections that are temporary, like the ones
4847+created for virtual network interfaces when you connect to a VPN for example,
4848+are not persisted as Netplan files. The reason for that is that these interfaces
4849+are usually managed by external services and we don't want to cause any
4850+unexpected change that would affect them.
4851
4852-## How to install it
4853+## How to use
4854
4855-### Creating a backup of your current configuration
4856-
4857-The new NetworkManager will remove connection profiles that you eventually
4858-modify from `/etc/NetworkManager`. So you might want to create a copy of all
4859-your connection profiles before installing the new network-manager package:
4860+### Installing NetworkManager
4861
4862+The NetworkManager 1.44.2 package containing the Netplan integration patch
4863+is available by default in Ubuntu 23.10 "Mantic Minotaur" and later as part of
4864+the official Ubuntu archive.
4865 ```
4866-$ mkdir ~/NetworkManager.bak && cd ~/NetworkManager.bak/
4867-$ sudo cp -r /etc/NetworkManager/system-connections .
4868+$ sudo apt update
4869+$ sudo apt install network-manager
4870 ```
4871
4872-In any case, a backup will be created automatically for you at
4873-`/root/NetworkManager.bak` during package installation.
4874-
4875-And also keep a copy of all the original network-manager related packages in
4876-case you want to revert to the previous installation:
4877+### User interface
4878
4879-```
4880-$ apt download gir1.2-nm-1.0 libnm0 network-manager network-manager-config-connectivity-ubuntu
4881-```
4882+From this point on, Netplan is aware of all your network configuration and
4883+you can query it using its CLI tools, such as `sudo netplan get` or `sudo
4884+netplan status`. All while keeping untouched the traditional way of modifying
4885+it using NetworkManager (graphical UI, GNOME Quick Settings, `nmcli`,
4886+`nmtui`, D-Bus APIs, ...).
4887
4888-### Installing NetworkManager
4889+### Management of connection profiles
4890
4891-The NetworkManager 1.42.0 package containing the Netplan integration patch
4892-is currently available as a PPA. In order to install it, you will need to
4893-have `netplan.io >= 0.106` installed in your system (it is available in Lunar).
4894+The NetworkManager-Netplan integration imports connection profiles from
4895+`/etc/NetworkManager/system-connections/` to Netplan during the installation
4896+process. It automatically creates a copy of all your connection profiles during
4897+the installation of the new network-manager package in
4898+`/root/NetworkManager.bak/system-connections/`. The same migration happens
4899+in the background whenever you add or modify any connection profile.
4900
4901+You can observe this migration on the `apt-get`` command line. Watch for
4902+logs like the following:
4903 ```
4904-$ sudo add-apt-repository ppa:canonical-foundations/networkmanager-netplan
4905-$ sudo apt update
4906-$ sudo apt install network-manager
4907+Setting up network-manager (1.44.2-1ubuntu1.2) ...
4908+Migrating HomeNet (9d087126-ae71-4992-9e0a-18c5ea92a4ed) to /etc/netplan
4909+Migrating eduroam (37d643bb-d81d-4186-9402-7b47632c59b1) to /etc/netplan
4910+Migrating DebConf (f862be9c-fb06-4c0f-862f-c8e210ca4941) to /etc/netplan
4911 ```
4912
4913-## How connections are managed from now on
4914-
4915-After installing the new NetworkManager, your existing connection profiles
4916-will not be imported to Netplan YAML files, only new connections and the
4917-existing ones you eventually modify.
4918-
4919-For example, if you have a Wifi connection, you will find the connection
4920-profile file at `/etc/NetworkManager/system-connections`. If you modify it
4921-using one of the NetworkManager's interfaces (or delete and create a new one),
4922-the respective file will be removed from `/etc/NetworkManager/system-connections`,
4923-a Netplan YAML called `90-NM-<connection UUID>.yaml` will be created at
4924-`/etc/netplan` and a new profile will be generated and stored at
4925-`/run/NetworkManager/system-connections`.
4926+For example, if you have a Wifi connection, you will not find the connection
4927+profile file at `/etc/NetworkManager/system-connections/` anymore. Instead,
4928+the system removes the profile file, and Netplan creates a new YAML file called
4929+`90-NM-<connection UUID>.yaml` in `/etc/netplan/` and generates a new ephemeral
4930+profile in `/run/NetworkManager/system-connections/`.
4931
4932 ## Limitation
4933
4934-Netplan doesn't yet support all the configuration available in
4935+Netplan doesn't yet support all the configuration options available in
4936 NetworkManager (or doesn't know how to interpret some of the keywords
4937 found in the keyfile). After creating a new connection you might find
4938-a section called "passthrough" in your YAML file, like in the example below:
4939+a section called `passthrough` in your YAML file, like in the example below:
4940
4941 ```yaml
4942 network:
4943@@ -113,12 +107,12 @@ network:
4944 proxy._: ""
4945 ```
4946
4947-All the configuration under the "passthrough" mapping will be added to
4948+All the configuration under the `passthrough` mapping is added to
4949 the `.nmconnection` file as they are.
4950
4951-In cases where the connection type is not supported by Netplan the
4952-`nm-devices` network type will be used. The example below is an OpenVPN
4953-client connection, which is not supported by Netplan at the moment.
4954+In cases where the connection type is not supported by Netplan, the system uses
4955+the `nm-devices` network type. The example below is an OpenVPN client
4956+connection, which is not supported by Netplan at the moment.
4957
4958 ```yaml
4959 network:
4960diff --git a/doc/netplan-yaml.md b/doc/netplan-yaml.md
4961index 11e7c41..23513c8 100644
4962--- a/doc/netplan-yaml.md
4963+++ b/doc/netplan-yaml.md
4964@@ -850,8 +850,9 @@ interfaces, as well as individual wifi networks, by means of the `auth` block.
4965
4966 > The supported key management modes are `none` (no key management);
4967 > `psk` (WPA with pre-shared key, common for home wifi); `eap` (WPA
4968- > with EAP, common for enterprise wifi); `sae` (used by WPA3); and `802.1x`
4969- > (used primarily for wired Ethernet connections).
4970+ > with EAP, common for enterprise wifi); `eap-sha256` (used with WPA3-Enterprise);
4971+ > `eap-suite-b-192` (used with WPA3-Enterprise); `sae` (used by WPA3);
4972+ > and `802.1x` (used primarily for wired Ethernet connections).
4973
4974 - **password** (scalar)
4975
4976@@ -863,7 +864,8 @@ interfaces, as well as individual wifi networks, by means of the `auth` block.
4977 - **method** (scalar)
4978
4979 > The EAP method to use. The supported EAP methods are `tls` (TLS),
4980- > `peap` (Protected EAP), and `ttls` (Tunneled TLS).
4981+ > `peap` (Protected EAP), `leap` (Lightweight EAP), `pwd` (EAP Password)
4982+ > and `ttls` (Tunneled TLS).
4983
4984 - **identity** (scalar)
4985
4986diff --git a/doc/reference.md b/doc/reference.md
4987index fe049d5..bf11582 100644
4988--- a/doc/reference.md
4989+++ b/doc/reference.md
4990@@ -20,8 +20,8 @@ maxdepth: 1
4991 netplan-yaml
4992 ```
4993
4994-## API specification
4995-`libnetplan` is a component of the Netplan. project that contains the logic for
4996+## libnetplan API
4997+`libnetplan` is a component of the Netplan project that contains the logic for
4998 data parsing, validation and generation. It is build as a dynamic `.so` library
4999 that can be used from different binaries (like Netplan’s `generate`,
5000 `netplan-dbus`, the `netplan apply/try/get/set/...` CLI or via the corresponding
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches