core,nmcli: merge branch 'th/limit-routes-addresses'

See-also: https://github.com/firewalld/firewalld/issues/1232

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1799
This commit is contained in:
Thomas Haller
2023-11-30 15:51:58 +01:00
5 changed files with 143 additions and 45 deletions

4
NEWS
View File

@@ -15,6 +15,10 @@ Overview of changes since NetworkManager-1.44
* Honor udev property ID_NET_MANAGED_BY to only manage an interface
when set to "org.freedesktop.NetworkManager".
* Drop build support with Python2. Python3 is now required.
* nmcli: limit number of printed addresses/routes in `nmcli` overview to 10.
* Limit number of exported IP addresses/routes on D-Bus to 100 to reduce
performance cost. Also, D-Bus updates for addresses/routes are now rate
limited to 3 per second.
=============================================
NetworkManager-1.44

View File

@@ -1558,7 +1558,8 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
char addr_str[NM_INET_ADDRSTRLEN];
NMDedupMultiIter iter;
const NMPObject *obj;
guint i;
const gsize MAX_ADDRESSES = 100;
gsize i;
nm_assert_addr_family(addr_family);
@@ -1580,6 +1581,11 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
nm_platform_dedup_multi_iter_next_obj(&iter, &obj, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))) {
const NMPlatformIPXAddress *address = NMP_OBJECT_CAST_IPX_ADDRESS(obj);
if (i > MAX_ADDRESSES) {
/* Limited. The rest is hidden. */
break;
}
if (out_address_data) {
GVariantBuilder addr_builder;
gconstpointer p;
@@ -1669,6 +1675,8 @@ nm_utils_ip_routes_to_dbus(int addr_family,
GVariantBuilder builder_data;
GVariantBuilder builder_legacy;
char addr_str[NM_INET_ADDRSTRLEN];
const gsize MAX_ROUTES = 100;
gsize i;
nm_assert_addr_family(addr_family);
@@ -1681,6 +1689,7 @@ nm_utils_ip_routes_to_dbus(int addr_family,
g_variant_builder_init(&builder_legacy, G_VARIANT_TYPE("a(ayuayu)"));
}
i = 0;
nm_dedup_multi_iter_init(&iter, head_entry);
while (nm_platform_dedup_multi_iter_next_obj(&iter, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))) {
const NMPlatformIPXRoute *r = NMP_OBJECT_CAST_IPX_ROUTE(obj);
@@ -1699,6 +1708,13 @@ nm_utils_ip_routes_to_dbus(int addr_family,
if (r->rx.type_coerced != nm_platform_route_type_coerce(RTN_UNICAST))
continue;
if (i >= MAX_ROUTES) {
/* Limited. The rest is hidden. */
break;
}
i++;
if (out_route_data) {
GVariantBuilder route_builder;
gconstpointer gateway;

View File

@@ -16,6 +16,10 @@
/*****************************************************************************/
#define NOTIFY_PLATFORM_RATELIMIT_MSEC 333
/*****************************************************************************/
GType nm_ip4_config_get_type(void);
GType nm_ip6_config_get_type(void);
@@ -67,6 +71,73 @@ _value_set_variant_as(GValue *value, const char *const *strv, guint len)
/*****************************************************************************/
static void
_notify_platform_handle(NMIPConfig *self, gint64 now_msec)
{
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
guint32 obj_type_flags;
nm_clear_g_source_inst(&priv->notify_platform_timeout_source);
priv->notify_platform_rlimited_until_msec = now_msec + NOTIFY_PLATFORM_RATELIMIT_MSEC;
obj_type_flags = nm_steal_int(&priv->notify_platform_obj_type_flags);
nm_assert(obj_type_flags != 0u);
_handle_platform_change(self, obj_type_flags, FALSE);
}
static gboolean
_notify_platform_cb(gpointer user_data)
{
_notify_platform_handle(user_data, nm_utils_get_monotonic_timestamp_msec());
return G_SOURCE_CONTINUE;
}
static void
_notify_platform(NMIPConfig *self, guint32 obj_type_flags)
{
const int addr_family = nm_ip_config_get_addr_family(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
gint64 now_msec;
obj_type_flags &= (nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))
| nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)));
if (obj_type_flags == 0u)
return;
priv->notify_platform_obj_type_flags |= obj_type_flags;
if (priv->notify_platform_timeout_source) {
/* We are currently rate limited. Don't bother to check whether
* (now_msec < priv->notify_platform_rlimited_until_msec), just always
* delegate to the timeout handler. It is scheduled with a lower idle
* priority, so we want that additional backoff. */
return;
}
now_msec = nm_utils_get_monotonic_timestamp_msec();
if (now_msec < priv->notify_platform_rlimited_until_msec) {
priv->notify_platform_timeout_source = nm_g_source_attach(
/* Schedule with a low G_PRIORITY_LOW. */
nm_g_timeout_source_new(priv->notify_platform_rlimited_until_msec - now_msec,
G_PRIORITY_LOW - 10,
_notify_platform_cb,
self,
NULL),
NULL);
return;
}
_notify_platform_handle(self, now_msec);
}
/*****************************************************************************/
static void
_l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMIPConfig *self)
{
@@ -76,7 +147,7 @@ _l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMIPCo
_handle_l3cd_changed(self, notify_data->l3cd_changed.l3cd_new);
break;
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
_handle_platform_change(self, notify_data->platform_change_on_idle.obj_type_flags, FALSE);
_notify_platform(self, notify_data->platform_change_on_idle.obj_type_flags);
break;
default:
break;
@@ -207,6 +278,8 @@ finalize(GObject *object)
NMIPConfig *self = NM_IP_CONFIG(object);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
nm_clear_g_source_inst(&priv->notify_platform_timeout_source);
nm_clear_g_signal_handler(priv->l3cfg, &priv->l3cfg_notify_id);
g_object_unref(priv->l3cfg);

View File

@@ -32,7 +32,10 @@ struct _NMIPConfigPrivate {
struct {
const NMPObject *best_default_route;
} v_gateway;
gulong l3cfg_notify_id;
GSource *notify_platform_timeout_source;
gint64 notify_platform_rlimited_until_msec;
gulong l3cfg_notify_id;
guint32 notify_platform_obj_type_flags;
};
struct _NMIPConfig {

View File

@@ -1411,36 +1411,57 @@ device_overview(NmCli *nmc, NMDevice *device)
static void
ac_overview(NmCli *nmc, NMActiveConnection *ac)
{
GString *outbuf = g_string_sized_new(80);
NMIPConfig *ip;
nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT_A(NM_UTILS_GET_NEXT_REALLOC_SIZE_488, FALSE);
const guint MAX_ADDRESSES = 10;
const guint MAX_ROUTES = 10;
int IS_IPv4;
if (nm_active_connection_get_controller(ac)) {
g_string_append_printf(outbuf,
"%s %s, ",
_("master"),
nm_device_get_iface(nm_active_connection_get_controller(ac)));
nm_str_buf_append_printf(&str,
"%s %s, ",
_("master"),
nm_device_get_iface(nm_active_connection_get_controller(ac)));
}
if (nm_active_connection_get_vpn(ac))
g_string_append_printf(outbuf, "%s, ", _("VPN"));
nm_str_buf_append_printf(&str, "%s, ", _("VPN"));
if (nm_active_connection_get_default(ac))
g_string_append_printf(outbuf, "%s, ", _("ip4 default"));
nm_str_buf_append_printf(&str, "%s, ", _("ip4 default"));
if (nm_active_connection_get_default6(ac))
g_string_append_printf(outbuf, "%s, ", _("ip6 default"));
if (outbuf->len >= 2) {
g_string_truncate(outbuf, outbuf->len - 2);
nmc_print("\t%s\n", outbuf->str);
nm_str_buf_append_printf(&str, "%s, ", _("ip6 default"));
if (str.len >= 2) {
nm_str_buf_set_size(&str, str.len - 2u, TRUE, FALSE);
nmc_print("\t%s\n", nm_str_buf_get_str(&str));
}
ip = nm_active_connection_get_ip4_config(ac);
if (ip) {
nm_str_buf_reset(&str);
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
NMIPConfig *ip;
const GPtrArray *p;
int i;
guint i;
ip = IS_IPv4 ? nm_active_connection_get_ip4_config(ac)
: nm_active_connection_get_ip6_config(ac);
if (!ip)
continue;
p = nm_ip_config_get_addresses(ip);
for (i = 0; i < p->len; i++) {
NMIPAddress *a = p->pdata[i];
nmc_print("\tinet4 %s/%d\n", nm_ip_address_get_address(a), nm_ip_address_get_prefix(a));
nmc_print("\tinet%c %s/%d\n",
IS_IPv4 ? '4' : '6',
nm_ip_address_get_address(a),
nm_ip_address_get_prefix(a));
if (i >= MAX_ADDRESSES - 1u && p->len - i > 2u) {
/* Print always at least MAX_ADDRESSES fully.
* If there are MAX_ADDRESSES+1 addresses, print them all fully.
* If there are more addresses, print MAX_ADDRESSES fully, and a
* "more" line. */
nmc_print("\tinet%c ... more\n", IS_IPv4 ? '4' : '6');
break;
}
}
p = nm_ip_config_get_routes(ip);
@@ -1450,33 +1471,14 @@ ac_overview(NmCli *nmc, NMActiveConnection *ac)
nm_str_buf_reset(&str);
_nm_ip_route_to_string(a, &str);
nmc_print("\troute4 %s\n", nm_str_buf_get_str(&str));
nmc_print("\troute%c %s\n", IS_IPv4 ? '4' : '6', nm_str_buf_get_str(&str));
if (i >= MAX_ROUTES - 1u && p->len - i > 2u) {
nmc_print("\troute%c ... more\n", IS_IPv4 ? '4' : '6');
break;
}
}
}
ip = nm_active_connection_get_ip6_config(ac);
if (ip) {
const GPtrArray *p;
int i;
p = nm_ip_config_get_addresses(ip);
for (i = 0; i < p->len; i++) {
NMIPAddress *a = p->pdata[i];
nmc_print("\tinet6 %s/%d\n", nm_ip_address_get_address(a), nm_ip_address_get_prefix(a));
}
p = nm_ip_config_get_routes(ip);
for (i = 0; i < p->len; i++) {
NMIPRoute *a = p->pdata[i];
nm_str_buf_reset(&str);
_nm_ip_route_to_string(a, &str);
nmc_print("\troute6 %s\n", nm_str_buf_get_str(&str));
}
}
g_string_free(outbuf, TRUE);
}
void