device/ndisc: add nm_ndisc_stop() method

It is bad style to rely on the last unref of an object for stopping
the operation. With a ref-counted object you should never rely on
anybody else still having (or not having) a reference. Hence, you
should not rely on stopping the ND during the last unref.

Add an explicit nm_ndisc_stop() function.
This commit is contained in:
Thomas Haller 2020-09-15 15:36:19 +02:00
parent e8eaaa78d1
commit 6ce482c526
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 94 additions and 21 deletions

View file

@ -337,6 +337,14 @@ start (NMNDisc *ndisc)
priv->receive_ra_id = g_timeout_add_seconds (ra->when, receive_ra, ndisc);
}
static void
stop (NMNDisc *ndisc)
{
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (ndisc);
nm_clear_g_source (&priv->receive_ra_id);
}
void
nm_fake_ndisc_emit_new_ras (NMFakeNDisc *self)
{
@ -388,7 +396,8 @@ nm_fake_ndisc_class_init (NMFakeNDiscClass *klass)
object_class->dispose = dispose;
ndisc_class->start = start;
ndisc_class->start = start;
ndisc_class->stop = stop;
ndisc_class->send_rs = send_rs;
signals[RS_SENT] =

View file

@ -535,6 +535,36 @@ start (NMNDisc *ndisc)
}
}
static void
_cleanup (NMNDisc *ndisc)
{
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE (ndisc);
nm_clear_g_source_inst (&priv->event_source);
if (priv->ndp) {
switch (nm_ndisc_get_node_type (ndisc)) {
case NM_NDISC_NODE_TYPE_HOST:
ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc);
break;
case NM_NDISC_NODE_TYPE_ROUTER:
ndp_msgrcv_handler_unregister (priv->ndp, receive_rs, NDP_MSG_RS, nm_ndisc_get_ifindex (ndisc), ndisc);
break;
default:
nm_assert_not_reached ();
break;
}
ndp_close (priv->ndp);
priv->ndp = NULL;
}
}
static void
stop (NMNDisc *ndisc)
{
_cleanup (ndisc);
}
/*****************************************************************************/
static int
@ -659,24 +689,8 @@ static void
dispose (GObject *object)
{
NMNDisc *ndisc = NM_NDISC (object);
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE (ndisc);
nm_clear_g_source_inst (&priv->event_source);
if (priv->ndp) {
switch (nm_ndisc_get_node_type (ndisc)) {
case NM_NDISC_NODE_TYPE_HOST:
ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc);
break;
case NM_NDISC_NODE_TYPE_ROUTER:
ndp_msgrcv_handler_unregister (priv->ndp, receive_rs, NDP_MSG_RS, nm_ndisc_get_ifindex (ndisc), ndisc);
break;
default:
g_assert_not_reached ();
}
ndp_close (priv->ndp);
priv->ndp = NULL;
}
_cleanup (ndisc);
G_OBJECT_CLASS (nm_lndp_ndisc_parent_class)->dispose (object);
}
@ -688,7 +702,8 @@ nm_lndp_ndisc_class_init (NMLndpNDiscClass *klass)
NMNDiscClass *ndisc_class = NM_NDISC_CLASS (klass);
object_class->dispose = dispose;
ndisc_class->start = start;
ndisc_class->send_rs = send_rs;
ndisc_class->send_ra = send_ra;
ndisc_class->start = start;
ndisc_class->stop = stop;
ndisc_class->send_rs = send_rs;
ndisc_class->send_ra = send_ra;
}

View file

@ -960,6 +960,53 @@ nm_ndisc_start (NMNDisc *ndisc)
announce_router_initial (ndisc);
}
void
nm_ndisc_stop (NMNDisc *ndisc)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
NMNDiscDataInternal *rdata;
NMNDiscPrivate *priv;
g_return_if_fail (NM_IS_NDISC (ndisc));
priv = NM_NDISC_GET_PRIVATE (ndisc);
nm_assert (NM_NDISC_GET_CLASS (ndisc)->stop);
_LOGD ("stopping neighbor discovery for ifindex %d",
priv->ifindex);
if (!nm_ndisc_netns_push (ndisc, &netns))
return;
NM_NDISC_GET_CLASS (ndisc)->stop (ndisc);
rdata = &priv->rdata;
g_array_set_size (rdata->gateways, 0);
g_array_set_size (rdata->addresses, 0);
g_array_set_size (rdata->routes, 0);
g_array_set_size (rdata->dns_servers, 0);
g_array_set_size (rdata->dns_domains, 0);
priv->rdata.public.hop_limit = 64;
/* Start at very low number so that last_rs - router_solicitation_interval
* is much lower than nm_utils_get_monotonic_timestamp_sec() at startup.
*/
priv->last_rs = G_MININT32;
nm_clear_g_source_inst (&priv->ra_timeout_source);
nm_clear_g_source (&priv->send_rs_id);
nm_clear_g_source (&priv->send_ra_id);
nm_clear_g_free (&priv->last_error);
nm_clear_g_source (&priv->timeout_id);
priv->solicitations_left = 0;
priv->announcements_left = 0;
priv->last_rs = G_MININT32;
priv->last_ra = G_MININT32;
}
NMNDiscConfigMap
nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal)
{

View file

@ -163,6 +163,7 @@ typedef struct {
GObjectClass parent;
void (*start) (NMNDisc *ndisc);
void (*stop) (NMNDisc *ndisc);
gboolean (*send_rs) (NMNDisc *ndisc, GError **error);
gboolean (*send_ra) (NMNDisc *ndisc, GError **error);
} NMNDiscClass;
@ -177,6 +178,7 @@ NMNDiscNodeType nm_ndisc_get_node_type (NMNDisc *self);
gboolean nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid);
void nm_ndisc_start (NMNDisc *ndisc);
void nm_ndisc_stop (NMNDisc *ndisc);
NMNDiscConfigMap nm_ndisc_dad_failed (NMNDisc *ndisc,
const struct in6_addr *address,
gboolean emit_changed_signal);