mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 04:52:59 +01:00
Merge pull request #16724 from JKRhb/dhcp-ia-na-refactor
sys/net/dhcpv6: Refactor IA_NA implementation
This commit is contained in:
commit
170af29917
@ -204,6 +204,20 @@ void dhcpv6_client_conf_prefix(unsigned netif, const ipv6_addr_t *pfx,
|
||||
unsigned pfx_len, uint32_t valid,
|
||||
uint32_t pref);
|
||||
|
||||
/**
|
||||
* @brief Configures a address lease that is provided by the server.
|
||||
*
|
||||
* @param[in] netif Network interface the address was for.
|
||||
* @param[in] addr The assigned address.
|
||||
* @param[in] valid Valid lifetime of the address.
|
||||
* @param[in] pref Preferred lifetime of the address.
|
||||
*/
|
||||
static inline void dhcpv6_client_conf_addr(unsigned netif, const ipv6_addr_t *addr,
|
||||
uint32_t valid, uint32_t pref)
|
||||
{
|
||||
dhcpv6_client_conf_prefix(netif, addr, IPV6_ADDR_BIT_LEN, valid, pref);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the given network interface is configured
|
||||
* to use DHCPv6 IA_NA
|
||||
@ -214,33 +228,6 @@ void dhcpv6_client_conf_prefix(unsigned netif, const ipv6_addr_t *pfx,
|
||||
*/
|
||||
bool dhcpv6_client_check_ia_na(unsigned netif);
|
||||
|
||||
/**
|
||||
* @brief Configures a address lease that is provided by the server.
|
||||
*
|
||||
* @param[in] netif Network interface the address was for.
|
||||
* @param[in] addr The assigned address.
|
||||
*
|
||||
* @return sizeof(ipv6_addr_t) on success.
|
||||
* @return <0 on error.
|
||||
*/
|
||||
int dhcpv6_client_add_addr(unsigned netif, ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Deprecates an existing address from an address lease.
|
||||
*
|
||||
* @param[in] netif Network interface the address was for.
|
||||
* @param[in] addr The address to deprecate.
|
||||
*/
|
||||
void dhcpv6_client_deprecate_addr(unsigned netif, const ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Removes an existing address that originated from an address lease.
|
||||
*
|
||||
* @param[in] netif Network interface the address was for.
|
||||
* @param[in] addr The address to remove.
|
||||
*/
|
||||
void dhcpv6_client_remove_addr(unsigned netif, ipv6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Determines how long the prefix delegation lease is still valid.
|
||||
*
|
||||
@ -253,6 +240,21 @@ void dhcpv6_client_remove_addr(unsigned netif, ipv6_addr_t *addr);
|
||||
uint32_t dhcpv6_client_prefix_valid_until(unsigned netif,
|
||||
const ipv6_addr_t *pfx,
|
||||
unsigned pfx_len);
|
||||
|
||||
/**
|
||||
* @brief Determines how long the address lease is still valid.
|
||||
*
|
||||
* @param[in] netif Network interface the address was for.
|
||||
* @param[in] addr The assigned address.
|
||||
*
|
||||
* @return Remaining valid lifetime of the address lease in seconds.
|
||||
*/
|
||||
static inline uint32_t dhcpv6_client_addr_valid_until(unsigned netif,
|
||||
const ipv6_addr_t *addr)
|
||||
{
|
||||
return dhcpv6_client_prefix_valid_until(netif, addr, IPV6_ADDR_BIT_LEN);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -69,8 +69,6 @@ typedef struct {
|
||||
lease_t parent;
|
||||
ipv6_addr_t addr;
|
||||
uint8_t leased;
|
||||
uint32_t valid_until;
|
||||
uint32_t pref_until;
|
||||
} addr_lease_t;
|
||||
|
||||
/**
|
||||
@ -90,8 +88,7 @@ static uint8_t duid[DHCPV6_CLIENT_DUID_LEN];
|
||||
static addr_lease_t addr_leases[CONFIG_DHCPV6_CLIENT_ADDR_LEASE_MAX];
|
||||
static pfx_lease_t pfx_leases[CONFIG_DHCPV6_CLIENT_PFX_LEASE_MAX];
|
||||
static server_t server;
|
||||
static event_timeout_t solicit_renew_timeout, rebind_timeout,
|
||||
deprecate_remove_timeout;
|
||||
static event_timeout_t solicit_renew_timeout, rebind_timeout;
|
||||
static event_queue_t *event_queue;
|
||||
static sock_udp_t sock;
|
||||
static sock_udp_ep_t local = { .family = AF_INET6, .port = DHCPV6_CLIENT_PORT };
|
||||
@ -112,7 +109,6 @@ static void _solicit_servers(event_t *event);
|
||||
static void _request(event_t *event);
|
||||
static void _renew(event_t *event);
|
||||
static void _rebind(event_t *event);
|
||||
static void _deprecate_remove_addrs(event_t *event);
|
||||
|
||||
static void _set_event_timeout_ms(event_timeout_t *timeout, event_t *event,
|
||||
uint32_t delay_ms);
|
||||
@ -124,7 +120,6 @@ static event_t solicit_servers = { .handler = _solicit_servers };
|
||||
static event_t request = { .handler = _request };
|
||||
static event_t renew = { .handler = _renew };
|
||||
static event_t rebind = { .handler = _rebind };
|
||||
static event_t deprecate_remove_addrs = { .handler = _deprecate_remove_addrs };
|
||||
|
||||
#ifdef MODULE_AUTO_INIT_DHCPV6_CLIENT
|
||||
static char _thread_stack[DHCPV6_CLIENT_STACK_SIZE];
|
||||
@ -681,15 +676,10 @@ static void _update_addr_lease(const dhcpv6_opt_iaaddr_t *iaaddr, addr_lease_t *
|
||||
|
||||
lease->leased = 1U;
|
||||
memcpy(&lease->addr, &iaaddr->addr, sizeof(ipv6_addr_t));
|
||||
if (dhcpv6_client_add_addr(lease->parent.ia_id.info.netif,
|
||||
&lease->addr) == sizeof(ipv6_addr_t)) {
|
||||
DEBUG("IP ADDRESS successfully added!\n");
|
||||
lease->pref_until = pref;
|
||||
lease->valid_until = valid;
|
||||
|
||||
_set_event_timeout_sec(&deprecate_remove_timeout, &deprecate_remove_addrs,
|
||||
pref);
|
||||
}
|
||||
dhcpv6_client_conf_addr(
|
||||
lease->parent.ia_id.info.netif, &lease->addr,
|
||||
valid, pref
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1135,7 +1125,9 @@ static void _request_renew_rebind(uint8_t type)
|
||||
(i < CONFIG_DHCPV6_CLIENT_ADDR_LEASE_MAX);
|
||||
i++) {
|
||||
const addr_lease_t *lease = &addr_leases[i];
|
||||
uint32_t valid_until = lease->valid_until;
|
||||
uint32_t valid_until = dhcpv6_client_addr_valid_until(
|
||||
lease->parent.ia_id.info.netif, &lease->addr
|
||||
);
|
||||
if (valid_until > mrd) {
|
||||
mrd = valid_until;
|
||||
}
|
||||
@ -1218,33 +1210,6 @@ static void _rebind(event_t *event)
|
||||
_request_renew_rebind(DHCPV6_REBIND);
|
||||
}
|
||||
|
||||
static void _deprecate_remove_addrs(event_t *event)
|
||||
{
|
||||
if (!IS_USED(MODULE_DHCPV6_CLIENT_IA_NA)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)event;
|
||||
|
||||
for (unsigned i = 0; (i < CONFIG_DHCPV6_CLIENT_ADDR_LEASE_MAX); i++) {
|
||||
uint32_t now = _now_sec();
|
||||
addr_lease_t *lease = &addr_leases[i];
|
||||
if (now >= lease->valid_until) {
|
||||
DEBUG("DHCPv6 client: removing address\n");
|
||||
dhcpv6_client_remove_addr(lease->parent.ia_id.info.netif,
|
||||
&lease->addr);
|
||||
lease->leased = 0U;
|
||||
} else if (now >= lease->pref_until) {
|
||||
DEBUG("DHCPv6 client: deprecating address\n");
|
||||
dhcpv6_client_deprecate_addr(lease->parent.ia_id.info.netif,
|
||||
&lease->addr);
|
||||
_set_event_timeout_sec(&deprecate_remove_timeout,
|
||||
&deprecate_remove_addrs,
|
||||
lease->valid_until);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _set_event_timeout_ms(event_timeout_t *timeout, event_t *event,
|
||||
uint32_t delay_ms)
|
||||
{
|
||||
|
@ -96,36 +96,6 @@ bool dhcpv6_client_check_ia_na(unsigned iface)
|
||||
return netif->ipv6.aac_mode & GNRC_NETIF_AAC_DHCP;
|
||||
}
|
||||
|
||||
int dhcpv6_client_add_addr(unsigned iface, ipv6_addr_t *addr)
|
||||
{
|
||||
gnrc_netif_t *netif = gnrc_netif_get_by_pid(iface);
|
||||
|
||||
DEBUG("DHCPv6 client: ADD IP ADDRESS\n");
|
||||
|
||||
return gnrc_netif_ipv6_addr_add(netif, addr, 64, 0);
|
||||
}
|
||||
|
||||
void dhcpv6_client_deprecate_addr(unsigned iface, const ipv6_addr_t *addr)
|
||||
{
|
||||
gnrc_netif_t *netif = gnrc_netif_get_by_pid(iface);
|
||||
int i;
|
||||
|
||||
gnrc_netif_acquire(netif);
|
||||
i = gnrc_netif_ipv6_addr_idx(netif, addr);
|
||||
if (i >= 0) {
|
||||
netif->ipv6.addrs_flags[i] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK;
|
||||
netif->ipv6.addrs_flags[i] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_DEPRECATED;
|
||||
}
|
||||
gnrc_netif_release(netif);
|
||||
}
|
||||
|
||||
void dhcpv6_client_remove_addr(unsigned iface, ipv6_addr_t *addr)
|
||||
{
|
||||
gnrc_netif_t *netif = gnrc_netif_get_by_pid(iface);
|
||||
|
||||
gnrc_netif_ipv6_addr_remove(netif, addr);
|
||||
}
|
||||
|
||||
uint32_t dhcpv6_client_prefix_valid_until(unsigned netif,
|
||||
const ipv6_addr_t *pfx,
|
||||
unsigned pfx_len)
|
||||
|
@ -15,6 +15,7 @@ from ipaddress import (
|
||||
|
||||
|
||||
IA_NA_ADDRESS_POOL_PREFIX = "2001:db8:1::"
|
||||
IA_PD_PREFIX = "2001:db8:8000::"
|
||||
|
||||
|
||||
def testfunc(child):
|
||||
@ -23,17 +24,26 @@ def testfunc(child):
|
||||
child.expect(r"Iface\s+\d+")
|
||||
child.expect(r"inet6 addr:\s+fe80:[0-9a-f:]+\s+scope: link")
|
||||
|
||||
global_addr_1, global_addr_2 = extract_global_addresses(child)
|
||||
global_addr_1 = extract_global_address(child)
|
||||
global_addr_2 = extract_global_address(child)
|
||||
assert global_addr_1 != global_addr_2
|
||||
|
||||
global_pfx = extract_global_prefix(child)
|
||||
global_pfx_1 = extract_global_prefix(child)
|
||||
global_pfx_2 = extract_global_prefix(child)
|
||||
assert global_pfx_1 != global_pfx_2
|
||||
|
||||
test_global_addrs(global_addr_1, global_addr_2, global_pfx)
|
||||
assert check_ia_na_addr(global_addr_1, global_pfx_1) or \
|
||||
check_ia_pd_addr(global_addr_1, global_pfx_1)
|
||||
assert check_ia_na_addr(global_addr_2, global_pfx_2) or \
|
||||
check_ia_pd_addr(global_addr_2, global_pfx_2)
|
||||
|
||||
|
||||
def extract_global_prefix(child):
|
||||
child.expect(r"(?P<global_pfx>[0-9a-f:]+)/64\s+dev #\d\s+"
|
||||
r"expires \d+ sec\s+"
|
||||
r"deprecates \d+ sec")
|
||||
child.expect(
|
||||
r"(?P<global_pfx>[0-9a-f:]+)\/(64|128)\s+dev #\d\s+"
|
||||
r"expires \d+ sec\s+"
|
||||
r"deprecates \d+ sec"
|
||||
)
|
||||
global_pfx = child.match.group("global_pfx")
|
||||
|
||||
if global_pfx.endswith("::"):
|
||||
@ -50,36 +60,22 @@ def extract_global_address(child):
|
||||
return child.match.group("global_addr")
|
||||
|
||||
|
||||
def extract_global_addresses(child):
|
||||
"""Extract two global addresses and return them as a tuple."""
|
||||
return extract_global_address(child), extract_global_address(child)
|
||||
def check_prefix(addr, prefix):
|
||||
return addr.startswith(prefix)
|
||||
|
||||
|
||||
def check_ia_na_addr(ia_na_addr):
|
||||
def check_ia_na_addr(ia_na_addr, global_pfx):
|
||||
"""Check if the expected IA_NA address has been assigned"""
|
||||
return IPv6Address(ia_na_addr) in IPv6Network("{}/64".format(IA_NA_ADDRESS_POOL_PREFIX))
|
||||
result = IPv6Address(ia_na_addr) in IPv6Network(f"{IA_NA_ADDRESS_POOL_PREFIX}/64")
|
||||
result = result and check_prefix(ia_na_addr, global_pfx)
|
||||
return result
|
||||
|
||||
|
||||
def check_ia_pd_addr(ia_pd_addr, global_pfx):
|
||||
"""Check if the expected IA_PD address has been assigned"""
|
||||
return ia_pd_addr.startswith(global_pfx)
|
||||
|
||||
|
||||
def check_global_addrs(ia_na_addr, ia_pd_addr, global_pfx):
|
||||
"""Perform IA_NA check for the first and IA_PD for the second address"""
|
||||
return {
|
||||
"ia_na_check": check_ia_na_addr(ia_na_addr),
|
||||
"ia_pd_check": check_ia_pd_addr(ia_pd_addr, global_pfx),
|
||||
}
|
||||
|
||||
|
||||
def test_global_addrs(global_addr_1, global_addr_2, global_pfx):
|
||||
"""Assert that one global address is the IA_NA and the other one is the IA_PD address"""
|
||||
result_1 = check_global_addrs(global_addr_1, global_addr_2, global_pfx)
|
||||
result_2 = check_global_addrs(global_addr_2, global_addr_1, global_pfx)
|
||||
assert result_1 != result_2
|
||||
assert result_1["ia_na_check"] != result_2["ia_na_check"]
|
||||
assert result_1["ia_pd_check"] != result_2["ia_pd_check"]
|
||||
result = IPv6Address(ia_pd_addr) in IPv6Network(f"{IA_PD_PREFIX}/33")
|
||||
result = result and check_prefix(ia_pd_addr, global_pfx)
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
Reference in New Issue
Block a user