mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-31 04:53:01 +02:00
confd: rename dhcp-client option name -> id
For consistency with the new dhcp-server model, which has an option value 'name', options are now referred to as id's or identifiers. This means bumping the confd syntax version 1.3 -> 1.4 and adding a migration script for existing dhcp-client configuration files. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
CONFD_VERSION = 1.3
|
||||
CONFD_VERSION = 1.4
|
||||
CONFD_SITE_METHOD = local
|
||||
CONFD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/confd
|
||||
CONFD_LICENSE = BSD-3-Clause
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
AC_PREREQ(2.61)
|
||||
# confd version is same as system YANG model version, step on breaking changes
|
||||
AC_INIT([confd], [1.3], [https://github.com/kernelkit/infix/issues])
|
||||
AC_INIT([confd], [1.4], [https://github.com/kernelkit/infix/issues])
|
||||
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
|
||||
AM_SILENT_RULES(yes)
|
||||
|
||||
@@ -17,6 +17,7 @@ AC_CONFIG_FILES([
|
||||
share/migrate/1.1/Makefile
|
||||
share/migrate/1.2/Makefile
|
||||
share/migrate/1.3/Makefile
|
||||
share/migrate/1.4/Makefile
|
||||
src/Makefile
|
||||
yang/Makefile
|
||||
])
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# Rename DHCP client option attribute 'name' -> 'id' to make DHCP server.
|
||||
|
||||
file=$1
|
||||
temp=${file}.tmp
|
||||
|
||||
jq '(
|
||||
.["infix-dhcp-client:dhcp-client"]?."client-if"[]?.option[]? |=
|
||||
if has("name") then
|
||||
{ "id": .name } + . | del(.name)
|
||||
else
|
||||
.
|
||||
end
|
||||
)' "$file" > "$temp" &&
|
||||
mv "$temp" "$file"
|
||||
@@ -0,0 +1,2 @@
|
||||
migratedir = $(pkgdatadir)/migrate/1.4
|
||||
dist_migrate_DATA = 10-dhcp-client-option-name.sh
|
||||
@@ -1,2 +1,2 @@
|
||||
SUBDIRS = 1.0 1.1 1.2 1.3
|
||||
SUBDIRS = 1.0 1.1 1.2 1.3 1.4
|
||||
migratedir = $(pkgdatadir)/migrate
|
||||
|
||||
@@ -102,12 +102,12 @@ static char *os_name_version(char *str, size_t len)
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *compose_option(const char *ifname, const char *name, const char *value,
|
||||
static char *compose_option(const char *ifname, const char *id, const char *value,
|
||||
char *option, size_t len)
|
||||
{
|
||||
if (value) {
|
||||
if (isdigit(name[0])) {
|
||||
unsigned long opt = strtoul(name, NULL, 0);
|
||||
if (isdigit(id[0])) {
|
||||
unsigned long opt = strtoul(id, NULL, 0);
|
||||
|
||||
switch (opt) {
|
||||
case 81:
|
||||
@@ -116,25 +116,25 @@ static char *compose_option(const char *ifname, const char *name, const char *va
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(option, len, "-x %s:%s ", name, value);
|
||||
snprintf(option, len, "-x %s:%s ", id, value);
|
||||
} else {
|
||||
if (!strcmp(name, "fqdn"))
|
||||
if (!strcmp(id, "fqdn"))
|
||||
fqdn(value, option, len);
|
||||
else if (!strcmp(name, "hostname"))
|
||||
snprintf(option, len, "-x %s:%s ", name, value);
|
||||
else if (!strcmp(id, "hostname"))
|
||||
snprintf(option, len, "-x %s:%s ", id, value);
|
||||
else
|
||||
snprintf(option, len, "-x %s:'\"%s\"' ", name, value);
|
||||
snprintf(option, len, "-x %s:'\"%s\"' ", id, value);
|
||||
}
|
||||
} else {
|
||||
struct { char *name; char *(*cb)(const char *, char *, size_t); } opt[] = {
|
||||
struct { char *id; char *(*cb)(const char *, char *, size_t); } opt[] = {
|
||||
{ "hostname", hostname },
|
||||
{ "address", ip_cache },
|
||||
{ "fqdn", NULL },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
for (size_t i = 0; opt[i].name; i++) {
|
||||
if (strcmp(name, opt[i].name))
|
||||
for (size_t i = 0; opt[i].id; i++) {
|
||||
if (strcmp(id, opt[i].id))
|
||||
continue;
|
||||
|
||||
if (!opt[i].cb || !opt[i].cb(ifname, option, len))
|
||||
@@ -143,17 +143,17 @@ static char *compose_option(const char *ifname, const char *name, const char *va
|
||||
return option;
|
||||
}
|
||||
|
||||
snprintf(option, len, "-O %s ", name);
|
||||
snprintf(option, len, "-O %s ", id);
|
||||
}
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
static char *compose_options(const char *ifname, char **options, const char *name, const char *value)
|
||||
static char *compose_options(const char *ifname, char **options, const char *id, const char *value)
|
||||
{
|
||||
char opt[300];
|
||||
|
||||
compose_option(ifname, name, value, opt, sizeof(opt));
|
||||
compose_option(ifname, id, value, opt, sizeof(opt));
|
||||
if (*options) {
|
||||
char *opts;
|
||||
|
||||
@@ -177,10 +177,10 @@ static char *dhcp_options(const char *ifname, struct lyd_node *cfg)
|
||||
char *options = NULL;
|
||||
|
||||
LYX_LIST_FOR_EACH(lyd_child(cfg), option, "option") {
|
||||
const char *value = lydx_get_cattr(option, "value");
|
||||
const char *name = lydx_get_cattr(option, "name");
|
||||
const char *id = lydx_get_cattr(option, "id");
|
||||
const char *val = lydx_get_cattr(option, "value");
|
||||
|
||||
options = compose_options(ifname, &options, name, value);
|
||||
options = compose_options(ifname, &options, id, val);
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
@@ -339,7 +339,7 @@ static void infer_options(sr_session_ctx_t *session, const char *xpath)
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NELEMS(opt); i++)
|
||||
srx_set_item(session, NULL, 0, "%s/option[name='%s']", xpath, opt[i]);
|
||||
srx_set_item(session, NULL, 0, "%s/option[id='%s']", xpath, opt[i]);
|
||||
}
|
||||
|
||||
static int cand(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
|
||||
|
||||
@@ -30,7 +30,7 @@ MODULES=(
|
||||
"infix-routing@2024-11-27.yang"
|
||||
"ieee802-dot1ab-lldp@2022-03-15.yang"
|
||||
"infix-lldp@2025-01-08.yang"
|
||||
"infix-dhcp-client@2024-09-20.yang"
|
||||
"infix-dhcp-client@2025-01-20.yang"
|
||||
"infix-dhcp-server@2024-08-18.yang"
|
||||
"infix-meta@2024-10-18.yang"
|
||||
"infix-system@2024-11-27.yang"
|
||||
|
||||
@@ -10,6 +10,10 @@ module infix-dhcp-client {
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "This module implements an IPv4 DHCP client";
|
||||
|
||||
revision 2025-01-20 {
|
||||
description "Rename option 'name' -> 'id' and rename internal type.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2024-09-20 {
|
||||
description "Routes are installed in Frr (staticd), clarify preference
|
||||
vs metric and adjust default preference 100 -> 5.";
|
||||
@@ -133,13 +137,13 @@ module infix-dhcp-client {
|
||||
description "ARP for lease to check for IP address collisions (slow).";
|
||||
}
|
||||
list option {
|
||||
key "name";
|
||||
key "id";
|
||||
description
|
||||
"List of DHCP options to request (and accept). The default is an
|
||||
empty list, meaning all supported options. To restrict the
|
||||
client to only get IP address and default route, set this to:
|
||||
'subnet router'";
|
||||
leaf name {
|
||||
leaf id {
|
||||
type dhcp-client-options;
|
||||
description "DHCP option to request from, or inform server of.";
|
||||
}
|
||||
@@ -149,7 +153,7 @@ module infix-dhcp-client {
|
||||
Example: option:hostname, value:xyzzy
|
||||
option:clientid, value:01:02:03:04:05:06:07:08:09:0a
|
||||
option:0x51, value:xyzzy.example.com";
|
||||
must "../name != 'hostname' or re-match(., '[a-zA-Z0-9\\-_]{1,64}')";
|
||||
must "../id != 'hostname' or re-match(., '[a-zA-Z0-9\\-_]{1,64}')";
|
||||
}
|
||||
}
|
||||
leaf route-preference {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Route preference: DHCP vs Static
|
||||
Route preference: DHCP vs Static
|
||||
|
||||
This test configures a device with both a DHCP-acquired route on a
|
||||
dedicated interface and a static route to the same destination on
|
||||
@@ -70,13 +70,13 @@ def config_target1(target, data1, data2, link):
|
||||
"if-name": data1,
|
||||
"enabled": True,
|
||||
"option": [
|
||||
{"name": "broadcast"},
|
||||
{"name": "dns"},
|
||||
{"name": "domain"},
|
||||
{"name": "hostname"},
|
||||
{"name": "ntpsrv"},
|
||||
{"name": "router"},
|
||||
{"name": "subnet"}
|
||||
{"id": "broadcast"},
|
||||
{"id": "dns"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "ntpsrv"},
|
||||
{"id": "router"},
|
||||
{"id": "subnet"}
|
||||
],
|
||||
"route-preference": 5
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
DHCP Basic
|
||||
"""DHCP Basic
|
||||
|
||||
This is a very basic DHCP test that requests an IPv4 lease
|
||||
from a DHCP server and checks that the lease is set on the
|
||||
interface.
|
||||
|
||||
"""
|
||||
|
||||
import infamy, infamy.dhcp
|
||||
@@ -13,6 +13,7 @@ from infamy.util import until
|
||||
|
||||
with infamy.Test() as test:
|
||||
ADDRESS = '10.0.0.42'
|
||||
|
||||
with test.step("Initialize"):
|
||||
env = infamy.Env()
|
||||
client = env.attach("client", "mgmt")
|
||||
@@ -31,7 +32,7 @@ with infamy.Test() as test:
|
||||
}
|
||||
client.put_config_dict("infix-dhcp-client", config)
|
||||
|
||||
with test.step("Verify client get DHCP lease for 10.0.0.42 on client:data"):
|
||||
with test.step("Verify client lease for 10.0.0.42"):
|
||||
until(lambda: iface.address_exist(client, port, ADDRESS))
|
||||
|
||||
test.succeed()
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
DHCP router
|
||||
"""DHCP router
|
||||
|
||||
Verify that the DHCP client receives default gateway (DHCP option 3, router)
|
||||
and that route exists in operational datastore.
|
||||
Verify that the DHCP client receives default gateway (DHCP option 3,
|
||||
router) and that route exists in operational datastore.
|
||||
"""
|
||||
|
||||
import infamy, infamy.dhcp
|
||||
@@ -11,7 +10,8 @@ import infamy.route as route
|
||||
from infamy.util import until
|
||||
|
||||
with infamy.Test() as test:
|
||||
ROUTER = '192.168.0.254'
|
||||
ROUTER = '192.168.0.254'
|
||||
|
||||
with test.step("Initialize"):
|
||||
env = infamy.Env()
|
||||
client = env.attach("client", "mgmt")
|
||||
@@ -26,14 +26,14 @@ with infamy.Test() as test:
|
||||
"client-if": [{
|
||||
"if-name": f"{port}",
|
||||
"option": [
|
||||
{ "name": "router" }
|
||||
{"id": "router"}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
client.put_config_dict("infix-dhcp-client", config)
|
||||
|
||||
with test.step("Verify client to set up default route via 192.168.0.254"):
|
||||
with test.step("Verify client has default route via 192.168.0.254"):
|
||||
until(lambda: route.ipv4_route_exist(client, "0.0.0.0/0", ROUTER))
|
||||
|
||||
test.succeed()
|
||||
|
||||
@@ -64,8 +64,8 @@ with infamy.Test() as test:
|
||||
"client-if": [{
|
||||
"if-name": f"{port}",
|
||||
"option": [
|
||||
{"name": "router"},
|
||||
{"name": "staticroutes"}
|
||||
{"id": "router"},
|
||||
{"id": "staticroutes"}
|
||||
]
|
||||
}]
|
||||
}
|
||||
@@ -75,17 +75,17 @@ with infamy.Test() as test:
|
||||
netns.addip("192.168.0.1")
|
||||
print(f"Start DHCP server {ROUTER} with option 3 and 121")
|
||||
with infamy.dhcp.Server(netns, prefix=PREFIX, router=ROUTER):
|
||||
with test.step("Verify 'client' has a route 10.0.0.0/24 via 192.168.0.254 (option 121)"):
|
||||
with test.step("Verify client has route 10.0.0.0/24 via 192.168.0.254 (option 121)"):
|
||||
print("Verify client use classless routes, option 121")
|
||||
until(lambda: route.ipv4_route_exist(client, PREFIX, ROUTER))
|
||||
|
||||
with test.step("Verify 'client' has default route via 192.168.0.254 (not use option 3)"):
|
||||
with test.step("Verify client has default route via 192.168.0.254 (not use option 3)"):
|
||||
print("Verify client did *not* use option 3")
|
||||
if route.ipv4_route_exist(client, "0.0.0.0/0", ROUTER):
|
||||
test.fail()
|
||||
|
||||
with test.step("Verify 'client' still has canary route to 20.0.0.0/24 via 192.168.0.2"):
|
||||
with test.step("Verify client still has canary route to 20.0.0.0/24 via 192.168.0.2"):
|
||||
until(lambda: route.ipv4_route_exist(client, CANARY,
|
||||
CANHOP, pref=250))
|
||||
CANHOP, pref=250))
|
||||
|
||||
test.succeed()
|
||||
|
||||
Reference in New Issue
Block a user