libnm: allow configuring static route when address is empty

OpenShift MetalLB team requests to configure additional routes
whenever the nodes does not have a configured IP address or route for
the subnet in which MetalLB issues addresses.

Note in linux network stack, it does not matter what interface you add
the address on a node (for example, loopback), the kernel is always
processing arp-requests and sending arp-replies to any of them, this
behavior is considered correct and, moreover, it is widely used in the a
dynamic environment as Kubernetes.

https://issues.redhat.com/browse/RHEL-5098
https://gitlab.freedesktop.org/NetworkManager/NetworkManager-ci/-/merge_requests/1587
This commit is contained in:
Wen Liang 2024-01-21 17:53:52 -05:00
parent cf28660b6a
commit 0e7bda8ad8
3 changed files with 54 additions and 8 deletions

View file

@ -163,17 +163,17 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
g_assert(method);
if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) {
if (nm_setting_ip_config_get_num_addresses(s_ip) == 0
&& nm_setting_ip_config_get_num_routes(s_ip) == 0) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_MISSING_PROPERTY,
_("this property cannot be empty for '%s=%s'"),
NM_SETTING_IP_CONFIG_METHOD,
_("method '%s' requires at least an address or a route"),
method);
g_prefix_error(error,
"%s.%s: ",
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_ADDRESSES);
NM_SETTING_IP_CONFIG_METHOD);
return FALSE;
}
} else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)

View file

@ -228,17 +228,17 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
g_assert(method);
if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) {
if (nm_setting_ip_config_get_num_addresses(s_ip) == 0
&& nm_setting_ip_config_get_num_routes(s_ip) == 0) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_MISSING_PROPERTY,
_("this property cannot be empty for '%s=%s'"),
NM_SETTING_IP_CONFIG_METHOD,
_("method '%s' requires at least an address or a route"),
method);
g_prefix_error(error,
"%s.%s: ",
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_ADDRESSES);
NM_SETTING_IP_CONFIG_METHOD);
return FALSE;
}
} else if (NM_IN_STRSET(method,

View file

@ -5112,6 +5112,50 @@ check_done:;
/*****************************************************************************/
static void
test_setting_connection_empty_address_and_route(void)
{
NMSettingIPConfig *s_ip4;
NMIPRoute *route;
NMIPAddress *addr;
gs_unref_object NMConnection *con = NULL;
gs_free_error GError *error = NULL;
gboolean success;
/* IP4 setting */
con = nmtst_create_minimal_connection("wired", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
nm_connection_add_setting(con, NM_SETTING(s_ip4));
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
g_assert(s_ip4 != NULL);
g_assert(NM_IS_SETTING_IP4_CONFIG(s_ip4));
success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
nmtst_assert_no_success(success, error);
nm_clear_error(&error);
route = nm_ip_route_new(AF_INET, "192.168.12.0", 24, NULL, 0, NULL);
nm_setting_ip_config_add_route(s_ip4, route);
success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
nmtst_assert_success(success, error);
nm_clear_error(&error);
nm_setting_ip_config_clear_routes(s_ip4);
addr = nm_ip_address_new(AF_INET, "1.1.1.3", 24, NULL);
nm_setting_ip_config_add_address(s_ip4, addr);
success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
nmtst_assert_success(success, error);
nm_clear_error(&error);
nm_setting_ip_config_add_route(s_ip4, route);
success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
nmtst_assert_success(success, error);
nm_ip_address_unref(addr);
nm_ip_route_unref(route);
nm_clear_error(&error);
}
/*****************************************************************************/
static void
test_setting_connection_secondaries_verify(void)
{
@ -5420,6 +5464,8 @@ main(int argc, char **argv)
test_8021x);
g_test_add_data_func("/libnm/setting-8021x/pkcs12", "test-cert.p12, test", test_8021x);
g_test_add_func("/libnm/settings/test_setting_connection_empty_address_and_route",
test_setting_connection_empty_address_and_route);
g_test_add_func("/libnm/settings/test_setting_connection_secondaries_verify",
test_setting_connection_secondaries_verify);