From 7346f122fd361406a5c016bcc8b62d9383c128af Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 14 Oct 2024 15:48:51 +0200 Subject: [PATCH 1/4] confd: allow all container networks to set interface name Unlock setting a custom interface name inside the container. This aids se-cases where this is needed and provide a better user experience, for example when upgrading containers. Not having to reboot the host just to activate an upgrated container. Fixes #708 Signed-off-by: Joachim Wiberg --- doc/container.md | 12 +++++++++++- src/confd/yang/containers.inc | 2 +- src/confd/yang/infix-containers.yang | 14 +++++++++----- ...03-27.yang => infix-containers@2024-10-14.yang} | 0 4 files changed, 21 insertions(+), 7 deletions(-) rename src/confd/yang/{infix-containers@2024-03-27.yang => infix-containers@2024-10-14.yang} (100%) diff --git a/doc/container.md b/doc/container.md index d7cd6437..d092068d 100644 --- a/doc/container.md +++ b/doc/container.md @@ -299,6 +299,7 @@ Currently two types of of container networks are supported: > For more information on VETH pairs, see the [Networking Guide][0]. + ### Container Bridge A container bridge is what most container setups use and users want. @@ -394,9 +395,15 @@ namespace of a container[^3]. This of course works with plain Ethernet interfaces as well, but here we will use one end of a VETH pair as an example. +The network `option` setting is available also for this case, but only +the `interface_name=foo0` option works. Which is still very useful. To +change the MAC address, you need to use the `custom-phys-adderss` in the +general network settings. + [^3]: Something which the container bridge network type does behind the scenes with one end of an automatically created VETH pair. + #### Routed Setup In this routed setup we reserve 192.168.0.0/24 for the network between @@ -429,9 +436,12 @@ Adding the interface to the container is the same as before, but since everything for host interfaces is set up in the interfaces context, we can take a bit of a shortcut. - admin@example:/config/container/ntpd/> set network ntpd + admin@example:/config/container/ntpd/> set network interface ntpd admin@example:/config/container/ntpd/> leave +> Use the `set network inteface ntpd option interface_name=foo0` to set +> the name of the interface inside the container to `foo0`. + The point of the routed case is that port forwarding from the container in this case is limited to a single interface, not *all interfaces* as is the default in the masquerading container bridge setup. diff --git a/src/confd/yang/containers.inc b/src/confd/yang/containers.inc index 7e63b0f2..5e6a45af 100644 --- a/src/confd/yang/containers.inc +++ b/src/confd/yang/containers.inc @@ -2,5 +2,5 @@ # REMEMBER TO UPDATE infix-interfaces ALSO IN confd.inc MODULES=( "infix-interfaces@2024-09-23.yang -e vlan-filtering -e containers" - "infix-containers@2024-03-27.yang" + "infix-containers@2024-10-14.yang" ) diff --git a/src/confd/yang/infix-containers.yang b/src/confd/yang/infix-containers.yang index c9dfc9d6..61c50baf 100644 --- a/src/confd/yang/infix-containers.yang +++ b/src/confd/yang/infix-containers.yang @@ -201,12 +201,16 @@ module infix-containers { } leaf-list option { - when "deref(../name)/../infix-if:container-network/infix-if:type = 'infix-if:bridge'"; - description "Options for masquerading container bridges. + description "Options for interface inside container, e.g., interface_name=foo0 - Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6) - mac=00:01:02:c0:ff:ee -- set fixed MAC address in container - interface_name=foo0 -- set interface name inside container"; + Options: ip=1.2.3.4 -- Set static IPv4 address* + ip6=2001:0:130f::9c0:876a:130b -- Set static IPv6 address* + mac=00:01:02:c0:ff:ee -- Set fixed MAC address + interface_name=foo0 -- Set interface name + + NOTE: Some (*) options only work with masquerading container bridges, + which automatically create VETH pairs with one end in the host + bridge and the other in the container."; type string; } } diff --git a/src/confd/yang/infix-containers@2024-03-27.yang b/src/confd/yang/infix-containers@2024-10-14.yang similarity index 100% rename from src/confd/yang/infix-containers@2024-03-27.yang rename to src/confd/yang/infix-containers@2024-10-14.yang From a14fada0ee3d94940913ca69724a19f8f4c49253 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 14 Oct 2024 17:17:07 +0200 Subject: [PATCH 2/4] confd: add support for container hostname format specifiers This patch makes it possible to use format specifiers to "uniqiefy" a container's hostname in the same way as with ietf-system hostname. The following specifiers are currently supported: - %h default hostname from /etc/os-release - %i value of ID from /etc/os-release - %m last three octets of base MAC, e.g., c0-ff-ee Signed-off-by: Joachim Wiberg --- doc/container.md | 11 +++++++++++ src/confd/src/ietf-system.c | 2 +- src/confd/src/infix-containers.c | 15 +++++++++++++-- src/confd/yang/infix-containers.yang | 18 ++++++++++++++++-- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/doc/container.md b/doc/container.md index d092068d..56e40d7d 100644 --- a/doc/container.md +++ b/doc/container.md @@ -609,6 +609,17 @@ container ID (hash) is used, but this can be easily changed: admin@example:/> container shell system root@sys101:/# +In fact, the container `hostname` setting supports the same format +specifiers as the host's `hostname` setting: + + - `%i`: OS ID, from `/etc/os-release`, from Menuconfig branding + - `%h`: Default hostname, from `/etc/os-release`, from branding + - `%m`: NIC specific part of base MAC, e.g., to `c0-ff-ee` + - `%%`: Literal % + +The most useful combination is probably `"container-name-%m"`, which in +this example give the container hostname `container-name-c0-ff-ee`. + [^1]: this does not apply to the admin-exec command `container run`. This command is intended to be used for testing and evaluating container images. Such containers are given a private network diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 39ef7dfd..c95b8b7b 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -1625,7 +1625,7 @@ static char *get_mac(struct confd *confd, char *mac, size_t len) * * XXX: PLEASE REFACTOR THIS INTO A PYTHON HELPER FOR FUTURE EXTENSIONS, OR BUGS! */ -static int hostnamefmt(struct confd *confd, char **fmt) +int hostnamefmt(struct confd *confd, char **fmt) { size_t hostlen, fmt_len; char *hostname; diff --git a/src/confd/src/infix-containers.c b/src/confd/src/infix-containers.c index 320070ef..ef576c8f 100644 --- a/src/confd/src/infix-containers.c +++ b/src/confd/src/infix-containers.c @@ -21,6 +21,9 @@ #define ACTIVE_QUEUE "/var/lib/containers/active" #define LOGGER "logger -t container -p local1.notice" +int hostnamefmt(struct confd *confd, char **fmt); + + static int add(const char *name, struct lyd_node *cif) { const char *image = lydx_get_cattr(cif, "image"); @@ -46,8 +49,16 @@ static int add(const char *name, struct lyd_node *cif) LYX_LIST_FOR_EACH(lyd_child(cif), node, "search") fprintf(fp, " --dns-search %s", lyd_get_value(node)); - if ((string = lydx_get_cattr(cif, "hostname"))) - fprintf(fp, " --hostname %s", string); + if ((string = lydx_get_cattr(cif, "hostname"))) { + char *fmt = (char *)string; + + if (hostnamefmt(&confd, &fmt)) { + ERRNO("%s: failed setting custom hostname", name); + } else { + fprintf(fp, " --hostname %s", fmt); + free(fmt); + } + } if (lydx_is_enabled(cif, "read-only")) fprintf(fp, " --read-only"); diff --git a/src/confd/yang/infix-containers.yang b/src/confd/yang/infix-containers.yang index 61c50baf..beb86601 100644 --- a/src/confd/yang/infix-containers.yang +++ b/src/confd/yang/infix-containers.yang @@ -22,6 +22,17 @@ module infix-containers { prefix infix-if; } + import infix-system { + prefix infix-sys; + } + + revision 2024-10-14 { + description "Two major changes: + - Allow changing name of host interfaces inside container + - Support hostname format specifiers, like ietf-system"; + reference "internal"; + } + revision 2024-03-27 { description "Add support for capabilities."; reference "internal"; @@ -160,8 +171,11 @@ module infix-containers { } leaf hostname { - description "Sets the container host name that is available inside the container."; - type inet:domain-name; + description "Sets the container host name, available inside the container. + + Format specifiers are for, default hostname, ID, and the + last three octets in base MAC, e.g., c0-ff-ee"; + type infix-sys:hostname; } leaf privileged { From 24b93074c53ba5c44845a4a0679f7aa0f5c24a46 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 14 Oct 2024 19:18:34 +0200 Subject: [PATCH 3/4] doc: update container documentation a bit, more images Signed-off-by: Joachim Wiberg --- doc/container.md | 49 +++++++++++++++----------------- doc/img/cni-bridge-firewall.svg | 4 +++ doc/img/cni-ntpd-bridged.svg | 4 +++ doc/img/cni-ntpd-routed.svg | 4 +++ doc/img/docker.webp | Bin 0 -> 37738 bytes 5 files changed, 35 insertions(+), 26 deletions(-) create mode 100644 doc/img/cni-bridge-firewall.svg create mode 100644 doc/img/cni-ntpd-bridged.svg create mode 100644 doc/img/cni-ntpd-routed.svg create mode 100644 doc/img/docker.webp diff --git a/doc/container.md b/doc/container.md index 56e40d7d..95f5ef49 100644 --- a/doc/container.md +++ b/doc/container.md @@ -1,5 +1,6 @@ Containers in Infix =================== +Docker whale * [Introduction](#introduction) * [Caution](#caution) @@ -78,16 +79,17 @@ In the CLI, containers can be run in one of two ways: 1. `container run IMAGE [COMMAND]`, and 2. enter `configure` context, then `edit container NAME` -The first is useful mostly for testing, or running single commands in an -image. It is a wrapper for `podman run -it --rm ...`, while the latter -is a wrapper and adaptation of `podman create ...`. +The former is useful mostly for testing, or running single commands in +an image. It is a wrapper for `podman run -it --rm ...`, while the +latter is a wrapper and adaptation of `podman create ...`. The second create a container with a semi-persistent writable layer that survives container restarts and host system restarts. However, if you change the container configuration or upgrade the image (see below), the container will be recreated and the writable layer is lost. This is why it is recommended to set up a named volume for directories, or use file -[Content Mounts][], in your container you want truly persistent content. +[Content Mounts](#content-mounts), in your container if you want truly +persistent content. In fact, in many cases the best way is to create a `read-only` container and use file mounts and volumes only for the critical parts. Podman @@ -303,11 +305,15 @@ Currently two types of of container networks are supported: ### Container Bridge A container bridge is what most container setups use and users want. + +![IP Masquerading Container Bridge](img/cni-bridge-firewall.svg) + The difference from a regular bridge is that the container runtime fully -manages them -- connecting containers automatically with VETH pairs and -setting up firewall rules between the host and other containers, as well -as managing port forwarding. This transparent background management is -what makes container use seem to be so simple. +manages them -- connecting containers with automatically created VETH +pairs (look at the bridge port names) and setting up firewall rules +between the host and other containers, as well as managing port +forwarding. This transparent background management is what makes +container use seem to be so simple. All interface configuration is done in configure context. @@ -409,12 +415,7 @@ general network settings. In this routed setup we reserve 192.168.0.0/24 for the network between the host and the `ntpd` container. - _____________ - | | - veth0 .1 | .2 eth0 | - \ 192.168.0.0/24 | / | - '--------------------' [ntpd] | - |_____________| +![Basic VETH pair connecting ntpd container.](img/cni-ntpd-routed.svg) Configuration is a straight-forward VETH pair setup where we name the container-end of pair `ntpd`. This is just a convenience for us when @@ -453,21 +454,15 @@ A perhaps more common case is to bridge the other end of the VETH pair with other physical ports. In this section we show how to add a new pair to give our container two interfaces: - _______________ - | | .1 br0 - veth0 .1 | .2 eth0 | / \ - \ 192.168.0.0/24 | / eth1 .2 | veth1b e1 - '------------------' \ | 192.168.1.0/24 / - | [ntpd] '------------------' - |_______________| +![Bridged setup with ntpd container.](img/cni-ntpd-bridged.svg) We start by adding the second VETH pair: admin@example:/config/> edit interface veth1a - admin@example:/config/interface/veth1a/> set veth peer veth1b + admin@example:/config/interface/veth1a/> set veth peer veth1 admin@example:/config/interface/veth1a/> set ipv4 address 192.168.1.2 prefix-length 24 -> The LAN bridge (br0) in this example has IP address 192.168.1.1. +> The LAN bridge (br1) in this example has IP address 192.168.1.1. When a container has multiple host interfaces it can often be useful to have a default route installed. This can be added from the host with a @@ -483,15 +478,16 @@ have a default route installed. This can be added from the host with a } } veth { - peer veth1b; + peer veth1; } admin@example:/config/interface/veth1a/> end - admin@example:/config/> set interface veth1b bridge-port bridge br0 + admin@example:/config/> set interface veth1 bridge-port bridge br1 Please note, container network routes require the base interface also have a static IP address set. Setting only the route, but no address, means the route is skipped. + ### Host Networking The third use-case is host networking, this is where a container share @@ -501,7 +497,7 @@ the host operating system. The host networking setup cannot be combined with any other network. -For an example, see below. +For an example, [see below](#application-container-nftables). Mounts and Volumes @@ -647,6 +643,7 @@ Notice how we `set network host`, so the container can see and act on all the host's interfaces, and that we also have to run the container in *privileged* mode. + ### Application Container: ntpd The default NTP server/client in Infix is Chrony, a fully working and diff --git a/doc/img/cni-bridge-firewall.svg b/doc/img/cni-bridge-firewall.svg new file mode 100644 index 00000000..04fb8861 --- /dev/null +++ b/doc/img/cni-bridge-firewall.svg @@ -0,0 +1,4 @@ + + + +
veth124
eth0
ip
10.0.10.0/24
.2
docker0
ip
.1
veth123
eth0
ip
.3
\ No newline at end of file diff --git a/doc/img/cni-ntpd-bridged.svg b/doc/img/cni-ntpd-bridged.svg new file mode 100644 index 00000000..28b33ffc --- /dev/null +++ b/doc/img/cni-ntpd-bridged.svg @@ -0,0 +1,4 @@ + + + +
veth0
eth0
ntpd container
ip
192.168.0.0/24
ip
.1
.2
eth1
veth1
ip
.2
bridge
ip
.1
192.168.1.0/24
e1
\ No newline at end of file diff --git a/doc/img/cni-ntpd-routed.svg b/doc/img/cni-ntpd-routed.svg new file mode 100644 index 00000000..033e08f4 --- /dev/null +++ b/doc/img/cni-ntpd-routed.svg @@ -0,0 +1,4 @@ + + + +
veth0
eth0
ntpd container
ip
192.168.0.0/24
ip
.1
.2
\ No newline at end of file diff --git a/doc/img/docker.webp b/doc/img/docker.webp new file mode 100644 index 0000000000000000000000000000000000000000..b29b95ecb0f5d4804d43f744fce0d0945e738ded GIT binary patch literal 37738 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 Date: Mon, 14 Oct 2024 19:41:01 +0200 Subject: [PATCH 4/4] doc: update changelog with latest fixes Signed-off-by: Joachim Wiberg --- doc/ChangeLog.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index 4dc2d098..52015513 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -13,6 +13,13 @@ addresses for interfaces! For details, see below issue #680. - Update CONTRIBUTING.md for scaling core team and helping external contributors understand the development process, issue #672 - OSPF: Add limitation to only allow one interface per area +- Add support for "dummy" interfaces, mostly useful for testing +- Add support for container hostname format specifiers, just like it + already works for the host's hostname setting +- Updated container documentation, improved images, detail how to set + interface name inside the container, and some syntax fixes +- Greatly reduced size of bundled curiOS httpd OCI container image, + reduced from 1.8 MiB to 281 KiB - The default builds now include the curiOS nftables container image, which can be used for advanced firewall setups. For an introduction see @@ -37,6 +44,8 @@ addresses for interfaces! For details, see below issue #680. this includes all operational data in ietf-routing:/routing/ribs. - Fix #697: password is not always set for new users, bug introduced in v24.06.0 when replacing Augeas with native user handling +- Fix #708: allow all container networks to set interface name inside + container, not just auto-generated veth-pair ends for `docker0` bridge - Fix BFD in OSPF, previously you could not enable BFD on a single interface without it was enabled on all interfaces