diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index 2fc1b58eb3..faae72670d 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -588,6 +588,14 @@ static const IPReservationTypeDesc ip_reservation_types[_NM_NETNS_IP_RESERVATION .addr_plen = 24, .allow_reuse = TRUE, }, + [NM_NETNS_IP_RESERVATION_TYPE_CLAT] = + { + .name = "clat", + .start_addr = 0xc0000005, /* 192.0.0.{5-7,0-4}/32 */ + .range_plen = 29, + .addr_plen = 32, + .allow_reuse = FALSE, + }, }; NMNetnsIPReservation * diff --git a/src/core/nm-netns.h b/src/core/nm-netns.h index 5ddb852ad5..e32d5680aa 100644 --- a/src/core/nm-netns.h +++ b/src/core/nm-netns.h @@ -43,6 +43,7 @@ NML3Cfg *nm_netns_l3cfg_acquire(NMNetns *netns, int ifindex); typedef enum { NM_NETNS_IP_RESERVATION_TYPE_SHARED4, + NM_NETNS_IP_RESERVATION_TYPE_CLAT, _NM_NETNS_IP_RESERVATION_TYPE_NUM, } NMNetnsIPReservationType; diff --git a/src/core/tests/test-netns.c b/src/core/tests/test-netns.c index 26ecbcb8b8..7bcd380927 100644 --- a/src/core/tests/test-netns.c +++ b/src/core/tests/test-netns.c @@ -53,6 +53,44 @@ test_ip_reservation_shared4(void) } } +static void +test_ip_reservation_clat(void) +{ + gs_unref_object NMPlatform *platform = NULL; + gs_unref_object NMNetns *netns = NULL; + NMNetnsIPReservation *res[8]; + NMNetnsIPReservation *res1; + char buf[NM_INET_ADDRSTRLEN]; + guint i; + + platform = g_object_ref(NM_PLATFORM_GET); + netns = nm_netns_new(platform); + + /* Allocate addresses 192.0.0.{5,6,7,0,1,2,3,4} */ + for (i = 0; i < 8; i++) { + res[i] = nm_netns_ip_reservation_get(netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT); + g_snprintf(buf, sizeof(buf), "192.0.0.%u", (i + 5) % 8); + nmtst_assert_ip4_address(res[i]->addr, buf); + g_assert_cmpint(res[i]->_ref_count, ==, 1); + } + + /* Release an address and get it back */ + nm_netns_ip_reservation_release(res[2]); + res[2] = nm_netns_ip_reservation_get(netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT); + nmtst_assert_ip4_address(res[2]->addr, "192.0.0.7"); + + /* No reuse */ + NMTST_EXPECT_NM_ERROR("netns[*]: clat: ran out of IP addresses"); + res1 = nm_netns_ip_reservation_get(netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT); + g_test_assert_expected_messages(); + g_assert_null(res1); + + /* Release all */ + for (i = 0; i < 8; i++) { + nm_netns_ip_reservation_release(res[i]); + } +} + /*****************************************************************************/ NMTST_DEFINE(); @@ -64,6 +102,7 @@ main(int argc, char **argv) nm_linux_platform_setup(); g_test_add_func("/netns/ip_reservation/shared4", test_ip_reservation_shared4); + g_test_add_func("/netns/ip_reservation/clat", test_ip_reservation_clat); return g_test_run(); }