l3cfg: add NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE notification

Our NML3Cfg instance is the IP configuration manage of one ifindex.
Often users have an NML3Cfg instance at hand, but they still need to
react to platform signals. Instead of requiring those users to register
their own signal (which also gets notifications about uninteresting
interfaces), re-emit the signal from NML3Cfg.

We already had NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE which
does something similar, but collects multiple changes and emits them
on an idle handler.
This commit is contained in:
Thomas Haller 2020-09-23 18:55:08 +02:00
parent 432d7f2151
commit 11c80ccf19
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 58 additions and 8 deletions

View file

@ -281,6 +281,7 @@ static NM_UTILS_ENUM2STR_DEFINE(
_l3_config_notify_type_to_string,
NML3ConfigNotifyType,
NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED, "acd-complete"),
NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, "platform-change"),
NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, "platform-change-on-idle"),
NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, "post-commit"),
NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED,
@ -313,6 +314,15 @@ _l3_config_notify_type_and_payload_to_string(NML3ConfigNotifyType noti
_nm_utils_inet4_ntop(payload->acd_completed.addr, sbuf_addr),
(int) payload->acd_completed.probe_result);
break;
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE:
nm_utils_strbuf_append(
&s,
&l,
", obj-type=%s, change=%s, obj=",
NMP_OBJECT_GET_CLASS(payload->platform_change.obj)->obj_type_name,
nm_platform_signal_change_type_to_string(payload->platform_change.change_type));
nmp_object_to_string(payload->platform_change.obj, NMP_OBJECT_TO_STRING_PUBLIC, s, l);
break;
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
nm_utils_strbuf_append(&s,
&l,
@ -331,13 +341,14 @@ _nm_l3cfg_emit_signal_notify(NML3Cfg * self,
NML3ConfigNotifyType notify_type,
const NML3ConfigNotifyPayload *payload)
{
char sbuf[100];
char sbuf[sizeof(_nm_utils_to_string_buffer)];
nm_assert(_NM_INT_NOT_NEGATIVE(notify_type));
nm_assert(notify_type < _NM_L3_CONFIG_NOTIFY_TYPE_NUM);
nm_assert((!!payload)
== NM_IN_SET(notify_type,
NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE));
_LOGT("emit signal (%s)",
@ -682,9 +693,14 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self,
NMPlatformSignalChangeType change_type,
const NMPObject * obj)
{
NML3ConfigNotifyPayload payload;
NMPObjectType obj_type;
nm_assert(NMP_OBJECT_IS_VALID(obj));
switch (NMP_OBJECT_GET_TYPE(obj)) {
obj_type = NMP_OBJECT_GET_TYPE(obj);
switch (obj_type) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
_l3_acd_ipv4_addresses_on_link_update(self,
NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address,
@ -697,6 +713,17 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self,
default:
break;
}
payload = (NML3ConfigNotifyPayload){
.platform_change =
{
.obj = obj,
.change_type = change_type,
},
};
_nm_l3cfg_emit_signal_notify(self, NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, &payload);
nm_assert(NMP_OBJECT_IS_VALID(obj));
}
/*****************************************************************************/

View file

@ -26,6 +26,12 @@ typedef enum {
/* emitted at the end of nm_l3cfg_platform_commit(). */
NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT,
/* NML3Cfg hooks to the NMPlatform signals for link, addresses and routes.
* It re-emits the platform signal.
* Contrary to NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, this even
* is re-emitted synchronously. */
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE,
/* NML3Cfg hooks to the NMPlatform signals for link, addresses and routes.
* It re-emits the signal on an idle handler. The purpose is for something
* like NMDevice which is already subscribed to these signals, it can get the
@ -50,6 +56,11 @@ typedef struct {
const NML3ConfigNotifyPayloadAcdFailedSource *sources;
} acd_completed;
struct {
const NMPObject * obj;
NMPlatformSignalChangeType change_type;
} platform_change;
struct {
guint32 obj_type_flags;
} platform_change_on_idle;

View file

@ -95,7 +95,7 @@ nm_netns_get_multi_idx(NMNetns *self)
typedef struct {
int ifindex;
guint32 signal_pending_flag;
guint32 signal_pending_obj_type_flags;
NML3Cfg *l3cfg;
CList signal_pending_lst;
} L3CfgData;
@ -192,8 +192,9 @@ _platform_signal_on_idle_cb(gpointer user_data)
while ((l3cfg_data = c_list_first_entry(&work_list, L3CfgData, signal_pending_lst))) {
nm_assert(NM_IS_L3CFG(l3cfg_data->l3cfg));
c_list_unlink(&l3cfg_data->signal_pending_lst);
_nm_l3cfg_notify_platform_change_on_idle(l3cfg_data->l3cfg,
nm_steal_int(&l3cfg_data->signal_pending_flag));
_nm_l3cfg_notify_platform_change_on_idle(
l3cfg_data->l3cfg,
nm_steal_int(&l3cfg_data->signal_pending_obj_type_flags));
}
return G_SOURCE_REMOVE;
@ -217,7 +218,7 @@ _platform_signal_cb(NMPlatform * platform,
if (!l3cfg_data)
return;
l3cfg_data->signal_pending_flag |= nmp_object_type_to_flags(obj_type);
l3cfg_data->signal_pending_obj_type_flags |= nmp_object_type_to_flags(obj_type);
if (c_list_is_empty(&l3cfg_data->signal_pending_lst)) {
c_list_link_tail(&priv->l3cfg_signal_pending_lst_head, &l3cfg_data->signal_pending_lst);

View file

@ -127,18 +127,25 @@ _test_l3cfg_signal_notify(NML3Cfg * l3cfg,
g_assert(tdata);
g_assert((!!payload)
== NM_IN_SET(l3_notify_type,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE,
NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED));
if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)
g_assert(payload->platform_change_on_idle.obj_type_flags != 0u);
else if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE) {
g_assert(NMP_OBJECT_IS_VALID(payload->platform_change.obj));
g_assert(payload->platform_change.change_type != 0);
}
switch (tdata->notify_type) {
case TEST_L3CFG_NOTIFY_TYPE_NONE:
g_assert_not_reached();
break;
case TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL:
if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)
if (NM_IN_SET(l3_notify_type,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE))
return;
g_assert_not_reached();
return;
@ -160,12 +167,16 @@ _test_l3cfg_signal_notify(NML3Cfg * l3cfg,
g_assert_not_reached();
return;
}
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE:
return;
default:
g_assert_not_reached();
return;
}
case TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1:
if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)
if (NM_IN_SET(l3_notify_type,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE,
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE))
return;
if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED) {
g_assert(tdata->notify_data.wait_for_acd_ready_1.cb_count == 0);