From 9e5a35b78fac0da1e4fce653820ccba015c23f44 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 26 Sep 2026 12:54:15 +0200 Subject: [PATCH 1/3] confd: infer classful prefix length for IPv4 addresses An IPv4 address set without a prefix length is accepted in the candidate but fails on commit: Error: Mandatory choice "subnet" data do not exist. Fill in the prefix length from the address class: /8 for class A, /16 for class B, /24 for class C. Class D and E get no default. Signed-off-by: Joachim Wiberg --- src/confd/src/interfaces.c | 4 ++++ src/confd/src/interfaces.h | 1 + src/confd/src/ip.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/confd/src/interfaces.c b/src/confd/src/interfaces.c index be1bc222b..822600426 100644 --- a/src/confd/src/interfaces.c +++ b/src/confd/src/interfaces.c @@ -190,6 +190,10 @@ static int ifchange_cand(sr_session_ctx_t *session, uint32_t sub_id, const char if (err) break; + err = ifchange_cand_infer_ipv4_prefix(session, new); + if (err) + break; + err = cni_ifchange_cand_infer_type(session, new->xpath); if (err) break; diff --git a/src/confd/src/interfaces.h b/src/confd/src/interfaces.h index a7bb77c07..3ff5063e2 100644 --- a/src/confd/src/interfaces.h +++ b/src/confd/src/interfaces.h @@ -108,6 +108,7 @@ int interfaces_get_all_l3(const struct lyd_node *tree, char ***ifaces); int interfaces_validate_keys(sr_session_ctx_t *session, struct lyd_node *config); /* ip.c */ +int ifchange_cand_infer_ipv4_prefix(sr_session_ctx_t *session, const sr_val_t *val); int netdag_gen_ipv6_autoconf(struct dagger *net, struct lyd_node *cif, struct lyd_node *dif, FILE *ip); int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif, diff --git a/src/confd/src/ip.c b/src/confd/src/ip.c index 463b3b1e1..c451e50f2 100644 --- a/src/confd/src/ip.c +++ b/src/confd/src/ip.c @@ -12,6 +12,44 @@ #include "interfaces.h" +/* Classful default for IPv4 addresses set without a prefix length */ +int ifchange_cand_infer_ipv4_prefix(sr_session_ctx_t *session, const sr_val_t *val) +{ + sr_val_t inferred = { .type = SR_UINT8_T }; + sr_error_t err = SR_ERR_OK; + struct in_addr ina; + uint32_t addr; + char *xpath; + size_t cnt; + + if (!strstr(val->xpath, ":ipv4/address[") || fnmatch("*]/ip", val->xpath, 0)) + return SR_ERR_OK; + if (inet_pton(AF_INET, val->data.string_val, &ina) != 1) + return SR_ERR_OK; + + addr = ntohl(ina.s_addr); + if (IN_CLASSA(addr)) + inferred.data.uint8_val = 8; + else if (IN_CLASSB(addr)) + inferred.data.uint8_val = 16; + else if (IN_CLASSC(addr)) + inferred.data.uint8_val = 24; + else + return SR_ERR_OK; /* class D/E, no default */ + + xpath = strdup(val->xpath); + if (!xpath) + return SR_ERR_SYS; + *strrchr(xpath, '/') = 0; + + err = srx_nitems(session, &cnt, "%s/prefix-length", xpath); + if (!err && !cnt) + err = srx_set_item(session, &inferred, 0, "%s/prefix-length", xpath); + + free(xpath); + return err; +} + int netdag_gen_ipv6_autoconf(struct dagger *net, struct lyd_node *cif, struct lyd_node *dif, FILE *ip) { From 1e94de385d2f46a3b51abfcfa6f378b03db035da Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 26 Sep 2026 12:54:16 +0200 Subject: [PATCH 2/3] cli: accept IP addresses in CIDR notation Bump klish-plugin-sysrepo, which splits ADDR/LEN list keys into the address and its prefix-length: set interface eth0 ipv4 address 192.168.1.1/24 This also works for IPv6, and with edit and delete. Signed-off-by: Joachim Wiberg --- package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash | 2 +- package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash index 087f9c342..40dbfa3b9 100644 --- a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash @@ -1,3 +1,3 @@ # Locally calculated sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE -sha256 0c07cb330a9f3855eefe9f9fa0d9f91d921cbf369571e943ab9ac264cd281db0 klish-plugin-sysrepo-3b4e69780e64f0b8f42dc3784defe72285911ad4-git4.tar.gz +sha256 c5ae2e3770a5e5a7bb81f73ac39a4f84688b5cf1fbcaf4a27b35e64329886d5f klish-plugin-sysrepo-a112518ec2fb32ae56dc10d624119ba17ae46d73-git4.tar.gz diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk index ec4ece5a0..d479fa4fd 100644 --- a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk @@ -4,7 +4,7 @@ # ################################################################################ -KLISH_PLUGIN_SYSREPO_VERSION = 3b4e69780e64f0b8f42dc3784defe72285911ad4 +KLISH_PLUGIN_SYSREPO_VERSION = a112518ec2fb32ae56dc10d624119ba17ae46d73 KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git KLISH_PLUGIN_SYSREPO_SITE_METHOD = git KLISH_PLUGIN_SYSREPO_LICENSE = BSD-3 From 70c0cd6c17dac83e0e1c6c14dabd9bc4d6ddeb30 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 26 Sep 2026 12:54:17 +0200 Subject: [PATCH 3/3] doc: CIDR notation and classful IPv4 prefix length in the CLI Signed-off-by: Joachim Wiberg --- doc/ChangeLog.md | 3 +++ doc/ip.md | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index 9f50875a1..7911e476e 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -29,6 +29,9 @@ All notable changes to the project are documented in this file. - The CLI accepts an unambiguous prefix of a command name, e.g. `sh int` for `show interface` +- The CLI accepts IP addresses in CIDR notation, e.g. `set ipv4 address + 192.168.1.1/24`. An IPv4 address set without a prefix length gets the + classful default: /8, /16, or /24 - Add a `log` RPC to `infix-syslog`, and a matching admin-exec `log` command in the CLI, for injecting messages in the system log over NETCONF/RESTCONF, issue #1639. Severity, app-name, msgid, and RFC 5424 diff --git a/doc/ip.md b/doc/ip.md index e53f334fd..69ca80aa3 100644 --- a/doc/ip.md +++ b/doc/ip.md @@ -300,6 +300,22 @@ lo ethernet UP 00:00:00:00:00:00 admin@example:/> +The address and prefix length can also be given in CIDR notation, e.g., +`set address 10.0.1.1/24`. This works for IPv6 addresses as well, and +with the `edit` and `delete` commands. + +An IPv4 address set without a prefix length gets the default length of +its address class: + +| **Class** | **First octet** | **Prefix length** | +|-----------|-----------------|-------------------| +| A | 0-127 | 8 | +| B | 128-191 | 16 | +| C | 192-223 | 24 | + +Multicast and reserved addresses (class D and E) have no default and +need an explicit prefix length. + ### Static IPv6 address ![Setting static IPv6](img/ip-address-example-ipv6-static.svg)