mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 00:10:15 +01:00
ndisc: merge branch 'th/ndisc-timeout-fixes'
https://bugzilla.redhat.com/show_bug.cgi?id=1874743 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/733
This commit is contained in:
commit
5217d0046e
12 changed files with 1202 additions and 829 deletions
|
|
@ -1364,6 +1364,59 @@ nm_g_source_attach(GSource *source, GMainContext *context)
|
|||
return source;
|
||||
}
|
||||
|
||||
static inline GSource *
|
||||
nm_g_idle_add_source(GSourceFunc func, gpointer user_data)
|
||||
{
|
||||
/* G convenience function to attach a new timeout source to the default GMainContext.
|
||||
* In that sense it's very similar to g_idle_add() except that it returns a
|
||||
* reference to the new source. */
|
||||
return nm_g_source_attach(nm_g_idle_source_new(G_PRIORITY_DEFAULT, func, user_data, NULL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static inline GSource *
|
||||
nm_g_timeout_add_source(guint timeout_msec, GSourceFunc func, gpointer user_data)
|
||||
{
|
||||
/* G convenience function to attach a new timeout source to the default GMainContext.
|
||||
* In that sense it's very similar to g_timeout_add() except that it returns a
|
||||
* reference to the new source. */
|
||||
return nm_g_source_attach(
|
||||
nm_g_timeout_source_new(timeout_msec, G_PRIORITY_DEFAULT, func, user_data, NULL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static inline GSource *
|
||||
nm_g_timeout_add_source_seconds(guint timeout_sec, GSourceFunc func, gpointer user_data)
|
||||
{
|
||||
/* G convenience function to attach a new timeout source to the default GMainContext.
|
||||
* In that sense it's very similar to g_timeout_add_seconds() except that it returns a
|
||||
* reference to the new source. */
|
||||
return nm_g_source_attach(
|
||||
nm_g_timeout_source_new_seconds(timeout_sec, G_PRIORITY_DEFAULT, func, user_data, NULL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static inline GSource *
|
||||
nm_g_timeout_add_source_approx(guint timeout_msec,
|
||||
guint timeout_sec_threshold,
|
||||
GSourceFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
/* If timeout_msec is larger or equal than a threshold, then we use g_timeout_source_new_seconds()
|
||||
* instead. */
|
||||
if (timeout_msec / 1000u >= timeout_sec_threshold)
|
||||
source = nm_g_timeout_source_new_seconds(timeout_msec / 1000u,
|
||||
G_PRIORITY_DEFAULT,
|
||||
func,
|
||||
user_data,
|
||||
NULL);
|
||||
else
|
||||
source = nm_g_timeout_source_new(timeout_msec, G_PRIORITY_DEFAULT, func, user_data, NULL);
|
||||
return nm_g_source_attach(source, NULL);
|
||||
}
|
||||
|
||||
NM_AUTO_DEFINE_FCN0(GMainContext *, _nm_auto_unref_gmaincontext, g_main_context_unref);
|
||||
#define nm_auto_unref_gmaincontext nm_auto(_nm_auto_unref_gmaincontext)
|
||||
|
||||
|
|
|
|||
|
|
@ -1194,6 +1194,14 @@ nmtst_main_loop_run(GMainLoop *loop, guint timeout_msec)
|
|||
return loopx != NULL;
|
||||
}
|
||||
|
||||
#define nmtst_main_loop_run_assert(loop, timeout_msec) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
if (!nmtst_main_loop_run((loop), (timeout_msec))) \
|
||||
g_assert_not_reached(); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
static inline void
|
||||
_nmtst_main_loop_quit_on_notify(GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5148,26 +5148,26 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink)
|
|||
static void
|
||||
ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
gint32 now;
|
||||
GArray * addresses, *dns_servers, *dns_domains;
|
||||
guint len, i;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
gs_unref_array GArray *addresses = NULL;
|
||||
gs_unref_array GArray *dns_servers = NULL;
|
||||
gs_unref_array GArray * dns_domains = NULL;
|
||||
guint len;
|
||||
guint i;
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
|
||||
if (nm_ndisc_get_node_type(ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
|
||||
return;
|
||||
|
||||
now = nm_utils_get_monotonic_timestamp_sec();
|
||||
|
||||
head_entry = nm_ip6_config_lookup_addresses(priv->ip_config_6);
|
||||
addresses =
|
||||
g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscAddress), head_entry ? head_entry->len : 0);
|
||||
nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) {
|
||||
const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter.current->obj);
|
||||
NMNDiscAddress * ndisc_addr;
|
||||
guint32 lifetime, preferred;
|
||||
gint32 base;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address))
|
||||
continue;
|
||||
|
|
@ -5178,31 +5178,21 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
|
|||
if (addr->plen != 64)
|
||||
continue;
|
||||
|
||||
/* resolve the timestamps relative to a new base.
|
||||
*
|
||||
* Note that for convenience, platform @addr might have timestamp and/or
|
||||
* lifetime unset. We don't allow that flexibility for ndisc and require
|
||||
* well defined timestamps. */
|
||||
if (addr->timestamp) {
|
||||
nm_assert(addr->timestamp < G_MAXINT32);
|
||||
base = addr->timestamp;
|
||||
} else
|
||||
base = now;
|
||||
|
||||
lifetime = nm_utils_lifetime_get(addr->timestamp,
|
||||
addr->lifetime,
|
||||
addr->preferred,
|
||||
base,
|
||||
NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
|
||||
&preferred);
|
||||
if (!lifetime)
|
||||
continue;
|
||||
|
||||
g_array_set_size(addresses, addresses->len + 1);
|
||||
ndisc_addr = &g_array_index(addresses, NMNDiscAddress, addresses->len - 1);
|
||||
ndisc_addr->address = addr->address;
|
||||
ndisc_addr->timestamp = base;
|
||||
ndisc_addr->lifetime = lifetime;
|
||||
ndisc_addr->preferred = preferred;
|
||||
ndisc_addr = &g_array_index(addresses, NMNDiscAddress, addresses->len - 1);
|
||||
ndisc_addr->address = addr->address;
|
||||
ndisc_addr->expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime);
|
||||
ndisc_addr->expiry_preferred_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred);
|
||||
}
|
||||
|
||||
len = nm_ip6_config_get_num_nameservers(priv->ip_config_6);
|
||||
|
|
@ -5212,10 +5202,10 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
|
|||
const struct in6_addr *nameserver = nm_ip6_config_get_nameserver(priv->ip_config_6, i);
|
||||
NMNDiscDNSServer * ndisc_nameserver;
|
||||
|
||||
ndisc_nameserver = &g_array_index(dns_servers, NMNDiscDNSServer, i);
|
||||
ndisc_nameserver->address = *nameserver;
|
||||
ndisc_nameserver->timestamp = now;
|
||||
ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME;
|
||||
ndisc_nameserver = &g_array_index(dns_servers, NMNDiscDNSServer, i);
|
||||
ndisc_nameserver->address = *nameserver;
|
||||
ndisc_nameserver->expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME);
|
||||
}
|
||||
|
||||
len = nm_ip6_config_get_num_searches(priv->ip_config_6);
|
||||
|
|
@ -5225,16 +5215,13 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
|
|||
const char * search = nm_ip6_config_get_search(priv->ip_config_6, i);
|
||||
NMNDiscDNSDomain *ndisc_search;
|
||||
|
||||
ndisc_search = &g_array_index(dns_domains, NMNDiscDNSDomain, i);
|
||||
ndisc_search->domain = (char *) search;
|
||||
ndisc_search->timestamp = now;
|
||||
ndisc_search->lifetime = NM_NDISC_ROUTER_LIFETIME;
|
||||
ndisc_search = &g_array_index(dns_domains, NMNDiscDNSDomain, i);
|
||||
ndisc_search->domain = (char *) search;
|
||||
ndisc_search->expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME);
|
||||
}
|
||||
|
||||
nm_ndisc_set_config(ndisc, addresses, dns_servers, dns_domains);
|
||||
g_array_unref(addresses);
|
||||
g_array_unref(dns_servers);
|
||||
g_array_unref(dns_domains);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -30,11 +30,10 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
struct in6_addr network;
|
||||
int plen;
|
||||
struct in6_addr gateway;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
gint64 expiry_msec;
|
||||
gint64 expiry_preferred_msec;
|
||||
int plen;
|
||||
NMIcmpv6RouterPref preference;
|
||||
} FakePrefix;
|
||||
|
||||
|
|
@ -128,8 +127,7 @@ void
|
|||
nm_fake_ndisc_add_gateway(NMFakeNDisc * self,
|
||||
guint ra_id,
|
||||
const char * addr,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
gint64 expiry_msec,
|
||||
NMIcmpv6RouterPref preference)
|
||||
{
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self);
|
||||
|
|
@ -137,12 +135,12 @@ nm_fake_ndisc_add_gateway(NMFakeNDisc * self,
|
|||
NMNDiscGateway * gw;
|
||||
|
||||
g_assert(ra);
|
||||
g_array_set_size(ra->gateways, ra->gateways->len + 1);
|
||||
gw = &g_array_index(ra->gateways, NMNDiscGateway, ra->gateways->len - 1);
|
||||
g_assert(inet_pton(AF_INET6, addr, &gw->address) == 1);
|
||||
gw->timestamp = timestamp;
|
||||
gw->lifetime = lifetime;
|
||||
gw->preference = preference;
|
||||
|
||||
gw = nm_g_array_append_new(ra->gateways, NMNDiscGateway);
|
||||
if (inet_pton(AF_INET6, addr, &gw->address) != 1)
|
||||
g_assert_not_reached();
|
||||
gw->expiry_msec = expiry_msec;
|
||||
gw->preference = preference;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -151,9 +149,8 @@ nm_fake_ndisc_add_prefix(NMFakeNDisc * self,
|
|||
const char * network,
|
||||
guint plen,
|
||||
const char * gateway,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
gint64 expiry_msec,
|
||||
gint64 expiry_preferred_msec,
|
||||
NMIcmpv6RouterPref preference)
|
||||
{
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self);
|
||||
|
|
@ -161,54 +158,52 @@ nm_fake_ndisc_add_prefix(NMFakeNDisc * self,
|
|||
FakePrefix * prefix;
|
||||
|
||||
g_assert(ra);
|
||||
g_array_set_size(ra->prefixes, ra->prefixes->len + 1);
|
||||
prefix = &g_array_index(ra->prefixes, FakePrefix, ra->prefixes->len - 1);
|
||||
memset(prefix, 0, sizeof(*prefix));
|
||||
g_assert(inet_pton(AF_INET6, network, &prefix->network) == 1);
|
||||
g_assert(inet_pton(AF_INET6, gateway, &prefix->gateway) == 1);
|
||||
prefix->plen = plen;
|
||||
prefix->timestamp = timestamp;
|
||||
prefix->lifetime = lifetime;
|
||||
prefix->preferred = preferred;
|
||||
prefix->preference = preference;
|
||||
|
||||
prefix = nm_g_array_append_new(ra->prefixes, FakePrefix);
|
||||
*prefix = (FakePrefix){
|
||||
.plen = plen,
|
||||
.expiry_msec = expiry_msec,
|
||||
.expiry_preferred_msec = expiry_preferred_msec,
|
||||
.preference = preference,
|
||||
};
|
||||
if (inet_pton(AF_INET6, network, &prefix->network) != 1)
|
||||
g_assert_not_reached();
|
||||
if (inet_pton(AF_INET6, gateway, &prefix->gateway) != 1)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void
|
||||
nm_fake_ndisc_add_dns_server(NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char * address,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime)
|
||||
gint64 expiry_msec)
|
||||
{
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self);
|
||||
FakeRa * ra = find_ra(priv->ras, ra_id);
|
||||
NMNDiscDNSServer * dns;
|
||||
|
||||
g_assert(ra);
|
||||
g_array_set_size(ra->dns_servers, ra->dns_servers->len + 1);
|
||||
dns = &g_array_index(ra->dns_servers, NMNDiscDNSServer, ra->dns_servers->len - 1);
|
||||
g_assert(inet_pton(AF_INET6, address, &dns->address) == 1);
|
||||
dns->timestamp = timestamp;
|
||||
dns->lifetime = lifetime;
|
||||
|
||||
dns = nm_g_array_append_new(ra->dns_servers, NMNDiscDNSServer);
|
||||
|
||||
dns->expiry_msec = expiry_msec;
|
||||
if (inet_pton(AF_INET6, address, &dns->address) != 1)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void
|
||||
nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char * domain,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime)
|
||||
nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self, guint ra_id, const char *domain, gint64 expiry_msec)
|
||||
{
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self);
|
||||
FakeRa * ra = find_ra(priv->ras, ra_id);
|
||||
NMNDiscDNSDomain * dns;
|
||||
|
||||
g_assert(ra);
|
||||
g_array_set_size(ra->dns_domains, ra->dns_domains->len + 1);
|
||||
dns = &g_array_index(ra->dns_domains, NMNDiscDNSDomain, ra->dns_domains->len - 1);
|
||||
dns->domain = g_strdup(domain);
|
||||
dns->timestamp = timestamp;
|
||||
dns->lifetime = lifetime;
|
||||
|
||||
dns = nm_g_array_append_new(ra->dns_domains, NMNDiscDNSDomain);
|
||||
|
||||
dns->domain = g_strdup(domain);
|
||||
dns->expiry_msec = expiry_msec;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -222,6 +217,7 @@ nm_fake_ndisc_done(NMFakeNDisc *self)
|
|||
static gboolean
|
||||
send_rs(NMNDisc *ndisc, GError **error)
|
||||
{
|
||||
_LOGT("send_rs()");
|
||||
g_signal_emit(ndisc, signals[RS_SENT], 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -229,13 +225,13 @@ send_rs(NMNDisc *ndisc, GError **error)
|
|||
static gboolean
|
||||
receive_ra(gpointer user_data)
|
||||
{
|
||||
NMFakeNDisc * self = user_data;
|
||||
NMFakeNDiscPrivate * priv = NM_FAKE_NDISC_GET_PRIVATE(self);
|
||||
NMNDisc * ndisc = NM_NDISC(self);
|
||||
NMNDiscDataInternal *rdata = ndisc->rdata;
|
||||
FakeRa * ra = priv->ras->data;
|
||||
NMNDiscConfigMap changed = 0;
|
||||
gint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
NMFakeNDisc * self = user_data;
|
||||
NMFakeNDiscPrivate * priv = NM_FAKE_NDISC_GET_PRIVATE(self);
|
||||
NMNDisc * ndisc = NM_NDISC(self);
|
||||
NMNDiscDataInternal *rdata = ndisc->rdata;
|
||||
FakeRa * ra = priv->ras->data;
|
||||
NMNDiscConfigMap changed = 0;
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
guint i;
|
||||
NMNDiscDHCPLevel dhcp_level;
|
||||
|
||||
|
|
@ -250,53 +246,51 @@ receive_ra(gpointer user_data)
|
|||
}
|
||||
|
||||
for (i = 0; i < ra->gateways->len; i++) {
|
||||
NMNDiscGateway *item = &g_array_index(ra->gateways, NMNDiscGateway, i);
|
||||
const NMNDiscGateway *item = &g_array_index(ra->gateways, NMNDiscGateway, i);
|
||||
|
||||
if (nm_ndisc_add_gateway(ndisc, item))
|
||||
if (nm_ndisc_add_gateway(ndisc, item, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_GATEWAYS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->prefixes->len; i++) {
|
||||
FakePrefix * item = &g_array_index(ra->prefixes, FakePrefix, i);
|
||||
NMNDiscRoute route = {
|
||||
.network = item->network,
|
||||
.plen = item->plen,
|
||||
.gateway = item->gateway,
|
||||
.timestamp = item->timestamp,
|
||||
.lifetime = item->lifetime,
|
||||
.preference = item->preference,
|
||||
FakePrefix * item = &g_array_index(ra->prefixes, FakePrefix, i);
|
||||
const NMNDiscRoute route = {
|
||||
.network = item->network,
|
||||
.plen = item->plen,
|
||||
.gateway = item->gateway,
|
||||
.expiry_msec = item->expiry_msec,
|
||||
.preference = item->preference,
|
||||
};
|
||||
|
||||
g_assert(route.plen > 0 && route.plen <= 128);
|
||||
|
||||
if (nm_ndisc_add_route(ndisc, &route))
|
||||
if (nm_ndisc_add_route(ndisc, &route, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
|
||||
if (item->plen == 64) {
|
||||
NMNDiscAddress address = {
|
||||
.address = item->network,
|
||||
.timestamp = item->timestamp,
|
||||
.lifetime = item->lifetime,
|
||||
.preferred = item->preferred,
|
||||
.dad_counter = 0,
|
||||
const NMNDiscAddress address = {
|
||||
.address = item->network,
|
||||
.expiry_msec = item->expiry_msec,
|
||||
.expiry_preferred_msec = item->expiry_preferred_msec,
|
||||
.dad_counter = 0,
|
||||
};
|
||||
|
||||
if (nm_ndisc_complete_and_add_address(ndisc, &address, now))
|
||||
if (nm_ndisc_complete_and_add_address(ndisc, &address, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->dns_servers->len; i++) {
|
||||
NMNDiscDNSServer *item = &g_array_index(ra->dns_servers, NMNDiscDNSServer, i);
|
||||
const NMNDiscDNSServer *item = &g_array_index(ra->dns_servers, NMNDiscDNSServer, i);
|
||||
|
||||
if (nm_ndisc_add_dns_server(ndisc, item))
|
||||
if (nm_ndisc_add_dns_server(ndisc, item, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_DNS_SERVERS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->dns_domains->len; i++) {
|
||||
NMNDiscDNSDomain *item = &g_array_index(ra->dns_domains, NMNDiscDNSDomain, i);
|
||||
const NMNDiscDNSDomain *item = &g_array_index(ra->dns_domains, NMNDiscDNSDomain, i);
|
||||
|
||||
if (nm_ndisc_add_dns_domain(ndisc, item))
|
||||
if (nm_ndisc_add_dns_domain(ndisc, item, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_DNS_DOMAINS;
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +307,7 @@ receive_ra(gpointer user_data)
|
|||
priv->ras = g_slist_remove(priv->ras, priv->ras->data);
|
||||
fake_ra_free(ra);
|
||||
|
||||
nm_ndisc_ra_received(NM_NDISC(self), now, changed);
|
||||
nm_ndisc_ra_received(NM_NDISC(self), now_msec, changed);
|
||||
|
||||
/* Schedule next RA */
|
||||
if (priv->ras) {
|
||||
|
|
@ -378,7 +372,7 @@ nm_fake_ndisc_new(int ifindex, const char *ifname)
|
|||
NM_NDISC_ROUTER_SOLICITATIONS,
|
||||
NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,
|
||||
NM_NDISC_ROUTER_SOLICITATION_INTERVAL,
|
||||
NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT,
|
||||
NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL,
|
||||
NM_NDISC_RA_TIMEOUT,
|
||||
30u,
|
||||
NULL);
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ guint nm_fake_ndisc_add_ra(NMFakeNDisc * self,
|
|||
void nm_fake_ndisc_add_gateway(NMFakeNDisc * self,
|
||||
guint ra_id,
|
||||
const char * addr,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
gint64 expiry_msec,
|
||||
NMIcmpv6RouterPref preference);
|
||||
|
||||
void nm_fake_ndisc_add_prefix(NMFakeNDisc * self,
|
||||
|
|
@ -44,22 +43,19 @@ void nm_fake_ndisc_add_prefix(NMFakeNDisc * self,
|
|||
const char * network,
|
||||
guint plen,
|
||||
const char * gateway,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
gint64 expiry_msec,
|
||||
gint64 expiry_preferred_msec,
|
||||
NMIcmpv6RouterPref preference);
|
||||
|
||||
void nm_fake_ndisc_add_dns_server(NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char * address,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime);
|
||||
gint64 expiry_msec);
|
||||
|
||||
void nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char * domain,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime);
|
||||
gint64 expiry_msec);
|
||||
|
||||
void nm_fake_ndisc_emit_new_ras(NMFakeNDisc *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -85,14 +85,26 @@ send_rs(NMNDisc *ndisc, GError **error)
|
|||
static NMIcmpv6RouterPref
|
||||
_route_preference_coerce(enum ndp_route_preference pref)
|
||||
{
|
||||
#define _ASSERT_ENUM(v1, v2) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
G_STATIC_ASSERT((NMIcmpv6RouterPref)(v1) == (v2)); \
|
||||
G_STATIC_ASSERT((enum ndp_route_preference)(v2) == (v1)); \
|
||||
G_STATIC_ASSERT((gint64)(v1) == (v2)); \
|
||||
G_STATIC_ASSERT((gint64)(v2) == (v1)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
switch (pref) {
|
||||
case NDP_ROUTE_PREF_LOW:
|
||||
return NM_ICMPV6_ROUTER_PREF_LOW;
|
||||
case NDP_ROUTE_PREF_MEDIUM:
|
||||
return NM_ICMPV6_ROUTER_PREF_MEDIUM;
|
||||
case NDP_ROUTE_PREF_HIGH:
|
||||
return NM_ICMPV6_ROUTER_PREF_HIGH;
|
||||
_ASSERT_ENUM(NDP_ROUTE_PREF_LOW, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
_ASSERT_ENUM(NDP_ROUTE_PREF_MEDIUM, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
_ASSERT_ENUM(NDP_ROUTE_PREF_HIGH, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
return (NMIcmpv6RouterPref) pref;
|
||||
}
|
||||
|
||||
/* unexpected value must be treated as MEDIUM (RFC 4191). */
|
||||
return NM_ICMPV6_ROUTER_PREF_MEDIUM;
|
||||
}
|
||||
|
|
@ -105,7 +117,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
NMNDiscConfigMap changed = 0;
|
||||
struct ndp_msgra * msgra = ndp_msgra(msg);
|
||||
struct in6_addr gateway_addr;
|
||||
gint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
int offset;
|
||||
int hop_limit;
|
||||
guint32 val;
|
||||
|
|
@ -121,7 +133,9 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
* single time when the configuration is finished and updates can
|
||||
* come at any time.
|
||||
*/
|
||||
_LOGD("received router advertisement at %d", (int) now);
|
||||
_LOGD("received router advertisement at timestamp %" G_GINT64_FORMAT ".%03d seconds",
|
||||
now_msec / 1000,
|
||||
(int) (now_msec % 1000));
|
||||
|
||||
gateway_addr = *ndp_msg_addrto(msg);
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&gateway_addr))
|
||||
|
|
@ -163,13 +177,18 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
*/
|
||||
{
|
||||
const NMNDiscGateway gateway = {
|
||||
.address = gateway_addr,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msgra_router_lifetime(msgra),
|
||||
.preference = _route_preference_coerce(ndp_msgra_route_preference(msgra)),
|
||||
.address = gateway_addr,
|
||||
.expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msgra_router_lifetime(msgra)),
|
||||
.preference = _route_preference_coerce(ndp_msgra_route_preference(msgra)),
|
||||
};
|
||||
|
||||
if (nm_ndisc_add_gateway(ndisc, &gateway))
|
||||
/* https://tools.ietf.org/html/rfc2461#section-4.2
|
||||
* > A Lifetime of 0 indicates that the router is not a
|
||||
* > default router and SHOULD NOT appear on the default
|
||||
* > router list.
|
||||
* We handle that by tracking a gateway that expires right now. */
|
||||
|
||||
if (nm_ndisc_add_gateway(ndisc, &gateway, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_GATEWAYS;
|
||||
}
|
||||
|
||||
|
|
@ -192,64 +211,71 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
|
||||
if (ndp_msg_opt_prefix_flag_on_link(msg, offset)) {
|
||||
const NMNDiscRoute route = {
|
||||
.network = r_network,
|
||||
.plen = r_plen,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_prefix_valid_time(msg, offset),
|
||||
.network = r_network,
|
||||
.plen = r_plen,
|
||||
.expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(now_msec,
|
||||
ndp_msg_opt_prefix_valid_time(msg, offset)),
|
||||
};
|
||||
|
||||
if (nm_ndisc_add_route(ndisc, &route))
|
||||
if (nm_ndisc_add_route(ndisc, &route, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
}
|
||||
|
||||
/* Address */
|
||||
if (r_plen == 64 && ndp_msg_opt_prefix_flag_auto_addr_conf(msg, offset)) {
|
||||
NMNDiscAddress address = {
|
||||
.address = r_network,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_prefix_valid_time(msg, offset),
|
||||
.preferred = ndp_msg_opt_prefix_preferred_time(msg, offset),
|
||||
const guint32 valid_time = ndp_msg_opt_prefix_valid_time(msg, offset);
|
||||
const guint32 preferred_time =
|
||||
NM_MIN(ndp_msg_opt_prefix_preferred_time(msg, offset), valid_time);
|
||||
const NMNDiscAddress address = {
|
||||
.address = r_network,
|
||||
.expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, valid_time),
|
||||
.expiry_preferred_msec = _nm_ndisc_lifetime_to_expiry(now_msec, preferred_time),
|
||||
};
|
||||
|
||||
if (address.preferred <= address.lifetime) {
|
||||
if (nm_ndisc_complete_and_add_address(ndisc, &address, now))
|
||||
changed |= NM_NDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
if (nm_ndisc_complete_and_add_address(ndisc, &address, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
}
|
||||
ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_ROUTE) {
|
||||
NMNDiscRoute route = {
|
||||
.gateway = gateway_addr,
|
||||
.plen = ndp_msg_opt_route_prefix_len(msg, offset),
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_route_lifetime(msg, offset),
|
||||
.preference = _route_preference_coerce(ndp_msg_opt_route_preference(msg, offset)),
|
||||
};
|
||||
guint8 plen = ndp_msg_opt_route_prefix_len(msg, offset);
|
||||
struct in6_addr network;
|
||||
|
||||
if (route.plen == 0 || route.plen > 128)
|
||||
if (plen == 0 || plen > 128)
|
||||
continue;
|
||||
|
||||
/* Routers through this particular gateway */
|
||||
nm_utils_ip6_address_clear_host_address(&route.network,
|
||||
nm_utils_ip6_address_clear_host_address(&network,
|
||||
ndp_msg_opt_route_prefix(msg, offset),
|
||||
route.plen);
|
||||
if (nm_ndisc_add_route(ndisc, &route))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
plen);
|
||||
|
||||
{
|
||||
const NMNDiscRoute route = {
|
||||
.network = network,
|
||||
.gateway = gateway_addr,
|
||||
.plen = plen,
|
||||
.expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_route_lifetime(msg, offset)),
|
||||
.preference = _route_preference_coerce(ndp_msg_opt_route_preference(msg, offset)),
|
||||
};
|
||||
|
||||
/* Routers through this particular gateway */
|
||||
if (nm_ndisc_add_route(ndisc, &route, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
}
|
||||
}
|
||||
|
||||
/* DNS information */
|
||||
ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_RDNSS) {
|
||||
struct in6_addr *addr;
|
||||
int addr_index;
|
||||
|
||||
ndp_msg_opt_rdnss_for_each_addr (addr, addr_index, msg, offset) {
|
||||
NMNDiscDNSServer dns_server = {
|
||||
.address = *addr,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_rdnss_lifetime(msg, offset),
|
||||
const NMNDiscDNSServer dns_server = {
|
||||
.address = *addr,
|
||||
.expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_rdnss_lifetime(msg, offset)),
|
||||
};
|
||||
|
||||
if (nm_ndisc_add_dns_server(ndisc, &dns_server))
|
||||
if (nm_ndisc_add_dns_server(ndisc, &dns_server, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_DNS_SERVERS;
|
||||
}
|
||||
}
|
||||
|
|
@ -258,13 +284,13 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
int domain_index;
|
||||
|
||||
ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) {
|
||||
NMNDiscDNSDomain dns_domain = {
|
||||
.domain = domain,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_dnssl_lifetime(msg, offset),
|
||||
const NMNDiscDNSDomain dns_domain = {
|
||||
.domain = domain,
|
||||
.expiry_msec =
|
||||
_nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_dnssl_lifetime(msg, offset)),
|
||||
};
|
||||
|
||||
if (nm_ndisc_add_dns_domain(ndisc, &dns_domain))
|
||||
if (nm_ndisc_add_dns_domain(ndisc, &dns_domain, now_msec))
|
||||
changed |= NM_NDISC_CONFIG_DNS_DOMAINS;
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +330,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
nm_ndisc_ra_received(ndisc, now, changed);
|
||||
nm_ndisc_ra_received(ndisc, now_msec, changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -362,7 +388,6 @@ send_ra(NMNDisc *ndisc, GError **error)
|
|||
{
|
||||
NMLndpNDiscPrivate * priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc);
|
||||
NMNDiscDataInternal * rdata = ndisc->rdata;
|
||||
gint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
int errsv;
|
||||
struct in6_addr * addr;
|
||||
struct ndp_msg * msg;
|
||||
|
|
@ -392,18 +417,9 @@ send_ra(NMNDisc *ndisc, GError **error)
|
|||
/* The device let us know about all addresses that the device got
|
||||
* whose prefixes are suitable for delegating. Let's announce them. */
|
||||
for (i = 0; i < rdata->addresses->len; i++) {
|
||||
const NMNDiscAddress *address = &g_array_index(rdata->addresses, NMNDiscAddress, i);
|
||||
guint32 age = NM_CLAMP((gint64) now - (gint64) address->timestamp, 0, G_MAXUINT32 - 1);
|
||||
guint32 lifetime = address->lifetime;
|
||||
guint32 preferred = address->preferred;
|
||||
const NMNDiscAddress * address = &g_array_index(rdata->addresses, NMNDiscAddress, i);
|
||||
struct nd_opt_prefix_info *prefix;
|
||||
|
||||
/* Clamp the life times if they're not forever. */
|
||||
if (lifetime != NM_NDISC_INFINITY)
|
||||
lifetime = lifetime > age ? lifetime - age : 0;
|
||||
if (preferred != NM_NDISC_INFINITY)
|
||||
preferred = preferred > age ? preferred - age : 0;
|
||||
|
||||
prefix = _ndp_msg_add_option(msg, sizeof(*prefix));
|
||||
if (!prefix) {
|
||||
/* Maybe we could sent separate RAs, but why bother... */
|
||||
|
|
@ -416,8 +432,14 @@ send_ra(NMNDisc *ndisc, GError **error)
|
|||
prefix->nd_opt_pi_prefix_len = 64;
|
||||
prefix->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
|
||||
prefix->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
|
||||
prefix->nd_opt_pi_valid_time = htonl(lifetime);
|
||||
prefix->nd_opt_pi_preferred_time = htonl(preferred);
|
||||
prefix->nd_opt_pi_valid_time =
|
||||
htonl(_nm_ndisc_lifetime_from_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP,
|
||||
address->expiry_msec,
|
||||
TRUE));
|
||||
prefix->nd_opt_pi_preferred_time =
|
||||
htonl(_nm_ndisc_lifetime_from_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP,
|
||||
address->expiry_preferred_msec,
|
||||
TRUE));
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[0] = address->address.s6_addr32[0];
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[1] = address->address.s6_addr32[1];
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[2] = 0;
|
||||
|
|
@ -691,13 +713,12 @@ nm_lndp_ndisc_get_sysctl(NMPlatform *platform,
|
|||
NM_SET_OUT(out_router_solicitations, router_solicitations);
|
||||
}
|
||||
if (out_router_solicitation_interval || out_default_ra_timeout) {
|
||||
router_solicitation_interval =
|
||||
ipv6_sysctl_get(platform,
|
||||
ifname,
|
||||
"router_solicitation_interval",
|
||||
1,
|
||||
G_MAXINT32,
|
||||
NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT);
|
||||
router_solicitation_interval = ipv6_sysctl_get(platform,
|
||||
ifname,
|
||||
"router_solicitation_interval",
|
||||
1,
|
||||
G_MAXINT32,
|
||||
NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL);
|
||||
NM_SET_OUT(out_router_solicitation_interval, router_solicitation_interval);
|
||||
}
|
||||
if (out_default_ra_timeout) {
|
||||
|
|
|
|||
|
|
@ -21,14 +21,15 @@ struct _NMNDiscDataInternal {
|
|||
|
||||
typedef struct _NMNDiscDataInternal NMNDiscDataInternal;
|
||||
|
||||
void nm_ndisc_ra_received(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed);
|
||||
void nm_ndisc_ra_received(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed);
|
||||
void nm_ndisc_rs_received(NMNDisc *ndisc);
|
||||
|
||||
gboolean nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new);
|
||||
gboolean nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s);
|
||||
gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new);
|
||||
gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new);
|
||||
gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new);
|
||||
gboolean nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new_item, gint64 now_msec);
|
||||
gboolean
|
||||
nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item, gint64 now_msec);
|
||||
gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec);
|
||||
gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec);
|
||||
gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_item, gint64 now_msec);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -48,48 +48,91 @@ typedef enum {
|
|||
NM_NDISC_DHCP_LEVEL_MANAGED
|
||||
} NMNDiscDHCPLevel;
|
||||
|
||||
/* we rely on the fact that NM_NDISC_INFINITY is the largest possible
|
||||
* time duration (G_MAXUINT32) and that the range of finite values
|
||||
* goes from 0 to G_MAXUINT32-1. */
|
||||
#define NM_NDISC_INFINITY G_MAXUINT32
|
||||
#define NM_NDISC_INFINITY_U32 ((uint32_t) -1)
|
||||
|
||||
struct _NMNDiscGateway {
|
||||
/* It's important that this is G_MAXINT64, so that we can meaningfully do
|
||||
* MIN(e1, e2) to find the minimum expiry time (and properly handle if any
|
||||
* of them is infinity).
|
||||
*
|
||||
* While usually you assign this to "expiry_msec", you might say the
|
||||
* unit of it is milliseconds. But of course, infinity has not really a unit. */
|
||||
#define NM_NDISC_EXPIRY_INFINITY G_MAXINT64
|
||||
|
||||
/* in common cases, the expiry_msec tracks the timestamp in nm_utils_get_monotonic_timestamp_mses()
|
||||
* timestamp when the item expires.
|
||||
*
|
||||
* When we configure an NMNDiscAddress to be announced via the router advertisement,
|
||||
* then that address does not have a fixed expiry point in time, instead, the expiry
|
||||
* really contains the lifetime from the moment when we send the router advertisement.
|
||||
* In that case, the expiry_msec is more a "lifetime" that starts counting at timestamp
|
||||
* zero.
|
||||
*
|
||||
* The unit is milliseconds (but of course, the timestamp is zero, so it doesn't really matter). */
|
||||
#define NM_NDISC_EXPIRY_BASE_TIMESTAMP ((gint64) 0)
|
||||
|
||||
static inline gint64
|
||||
_nm_ndisc_lifetime_to_expiry(gint64 now_msec, guint32 lifetime)
|
||||
{
|
||||
if (lifetime == NM_NDISC_INFINITY_U32)
|
||||
return NM_NDISC_EXPIRY_INFINITY;
|
||||
return now_msec + (((gint64) lifetime) * 1000);
|
||||
}
|
||||
|
||||
static inline gint64
|
||||
_nm_ndisc_lifetime_from_expiry(gint64 now_msec, gint64 expiry_msec, gboolean ceil)
|
||||
{
|
||||
gint64 diff;
|
||||
|
||||
if (expiry_msec == NM_NDISC_EXPIRY_INFINITY)
|
||||
return NM_NDISC_INFINITY_U32;
|
||||
|
||||
/* we don't expect nor handle integer overflow. The time stamp and expiry
|
||||
* should be reasonably small so that it cannot happen. */
|
||||
|
||||
diff = expiry_msec - now_msec;
|
||||
|
||||
if (diff <= 0)
|
||||
return 0;
|
||||
|
||||
if (ceil) {
|
||||
/* we ceil() towards the next full second (instead of floor()). */
|
||||
diff += 999;
|
||||
}
|
||||
|
||||
return NM_MIN(diff / 1000, (gint64)(G_MAXUINT32 - 1));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMNDiscGateway {
|
||||
struct in6_addr address;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
gint64 expiry_msec;
|
||||
NMIcmpv6RouterPref preference;
|
||||
};
|
||||
typedef struct _NMNDiscGateway NMNDiscGateway;
|
||||
} NMNDiscGateway;
|
||||
|
||||
struct _NMNDiscAddress {
|
||||
typedef struct _NMNDiscAddress {
|
||||
struct in6_addr address;
|
||||
gint64 expiry_msec;
|
||||
gint64 expiry_preferred_msec;
|
||||
guint8 dad_counter;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
};
|
||||
typedef struct _NMNDiscAddress NMNDiscAddress;
|
||||
} NMNDiscAddress;
|
||||
|
||||
struct _NMNDiscRoute {
|
||||
typedef struct _NMNDiscRoute {
|
||||
struct in6_addr network;
|
||||
guint8 plen;
|
||||
struct in6_addr gateway;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
gint64 expiry_msec;
|
||||
NMIcmpv6RouterPref preference;
|
||||
};
|
||||
typedef struct _NMNDiscRoute NMNDiscRoute;
|
||||
guint8 plen;
|
||||
} NMNDiscRoute;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
gint64 expiry_msec;
|
||||
} NMNDiscDNSServer;
|
||||
|
||||
typedef struct {
|
||||
char * domain;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
char * domain;
|
||||
gint64 expiry_msec;
|
||||
} NMNDiscDNSDomain;
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -112,15 +155,17 @@ typedef enum {
|
|||
NM_NDISC_NODE_TYPE_ROUTER,
|
||||
} NMNDiscNodeType;
|
||||
|
||||
#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16
|
||||
#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861 MAX_RTR_SOLICITATIONS */
|
||||
#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4 /* RFC4861 RTR_SOLICITATION_INTERVAL */
|
||||
#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861 MAX_INITIAL_RTR_ADVERTISEMENTS */
|
||||
#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861 MIN_DELAY_BETWEEN_RAS */
|
||||
#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861 MAX_INITIAL_RTR_ADVERT_INTERVAL */
|
||||
#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861 MAX_RA_DELAY_TIME */
|
||||
#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861 MaxRtrAdvInterval default */
|
||||
#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */
|
||||
#define NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL 4 /* seconds */
|
||||
#define NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY 1 /* seconds */
|
||||
|
||||
#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16
|
||||
#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861, MAX_RTR_SOLICITATIONS */
|
||||
#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861, MAX_INITIAL_RTR_ADVERTISEMENTS */
|
||||
#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861, MIN_DELAY_BETWEEN_RAS */
|
||||
#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861, MAX_INITIAL_RTR_ADVERT_INTERVAL */
|
||||
#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861, MAX_RA_DELAY_TIME */
|
||||
#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861, MaxRtrAdvInterval default */
|
||||
#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */
|
||||
|
||||
struct _NMNDiscPrivate;
|
||||
struct _NMNDiscDataInternal;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "nm-test-utils-core.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMFakeNDisc *
|
||||
ndisc_new(void)
|
||||
{
|
||||
|
|
@ -26,19 +28,20 @@ ndisc_new(void)
|
|||
iid.id_u8[7] = 1;
|
||||
nm_ndisc_set_iid(ndisc, iid);
|
||||
g_assert(ndisc);
|
||||
|
||||
return NM_FAKE_NDISC(ndisc);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
match_gateway(const NMNDiscData *rdata,
|
||||
guint idx,
|
||||
const char * addr,
|
||||
guint32 ts,
|
||||
guint32 lt,
|
||||
gint64 expiry_msec,
|
||||
NMIcmpv6RouterPref pref)
|
||||
{
|
||||
const NMNDiscGateway *gw;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_assert(rdata);
|
||||
g_assert_cmpint(idx, <, rdata->gateways_n);
|
||||
|
|
@ -46,63 +49,57 @@ match_gateway(const NMNDiscData *rdata,
|
|||
|
||||
gw = &rdata->gateways[idx];
|
||||
|
||||
g_assert_cmpstr(inet_ntop(AF_INET6, &gw->address, buf, sizeof(buf)), ==, addr);
|
||||
g_assert_cmpint(gw->timestamp, ==, ts);
|
||||
g_assert_cmpint(gw->lifetime, ==, lt);
|
||||
nmtst_assert_ip6_address(&gw->address, addr);
|
||||
g_assert_cmpint(gw->expiry_msec, ==, expiry_msec);
|
||||
g_assert_cmpint(gw->preference, ==, pref);
|
||||
}
|
||||
|
||||
#define match_address(rdata, idx, addr, ts, lt, pref) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMNDiscData * _rdata = (rdata); \
|
||||
guint _idx = (idx); \
|
||||
const NMNDiscAddress *_a; \
|
||||
guint _ts = (ts); \
|
||||
\
|
||||
g_assert(_rdata); \
|
||||
g_assert_cmpint(_idx, <, _rdata->addresses_n); \
|
||||
g_assert(_rdata->addresses); \
|
||||
\
|
||||
_a = &_rdata->addresses[_idx]; \
|
||||
\
|
||||
nmtst_assert_ip6_address(&_a->address, (addr)); \
|
||||
g_assert_cmpint(_a->timestamp, <=, _ts + 1); \
|
||||
g_assert_cmpint((int) _a->timestamp, >=, (int) _ts - 1); \
|
||||
g_assert_cmpint(_a->timestamp + _a->lifetime, ==, _ts + (lt)); \
|
||||
g_assert_cmpint(_a->timestamp + _a->preferred, ==, _ts + (pref)); \
|
||||
} \
|
||||
#define match_address(rdata, idx, addr, _expiry_msec, _expiry_preferred_msec) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMNDiscData * _rdata = (rdata); \
|
||||
guint _idx = (idx); \
|
||||
const NMNDiscAddress *_a; \
|
||||
\
|
||||
g_assert(_rdata); \
|
||||
g_assert_cmpint(_idx, <, _rdata->addresses_n); \
|
||||
g_assert(_rdata->addresses); \
|
||||
\
|
||||
_a = &_rdata->addresses[_idx]; \
|
||||
\
|
||||
nmtst_assert_ip6_address(&_a->address, (addr)); \
|
||||
g_assert_cmpint(_a->expiry_msec, ==, (_expiry_msec)); \
|
||||
g_assert_cmpint(_a->expiry_preferred_msec, ==, (_expiry_preferred_msec)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define match_route(rdata, idx, nw, pl, gw, ts, lt, pref) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMNDiscData * _rdata = (rdata); \
|
||||
guint _idx = (idx); \
|
||||
const NMNDiscRoute *_r; \
|
||||
int _plen = (pl); \
|
||||
\
|
||||
g_assert(_rdata); \
|
||||
g_assert_cmpint(_idx, <, _rdata->routes_n); \
|
||||
g_assert(_rdata->routes); \
|
||||
g_assert(_plen > 0 && _plen <= 128); \
|
||||
\
|
||||
_r = &_rdata->routes[idx]; \
|
||||
\
|
||||
nmtst_assert_ip6_address(&_r->network, (nw)); \
|
||||
g_assert_cmpint((int) _r->plen, ==, _plen); \
|
||||
nmtst_assert_ip6_address(&_r->gateway, (gw)); \
|
||||
g_assert_cmpint(_r->timestamp, ==, (ts)); \
|
||||
g_assert_cmpint(_r->lifetime, ==, (lt)); \
|
||||
g_assert_cmpint(_r->preference, ==, (pref)); \
|
||||
} \
|
||||
#define match_route(rdata, idx, nw, pl, gw, _expiry_msec, pref) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMNDiscData * _rdata = (rdata); \
|
||||
guint _idx = (idx); \
|
||||
const NMNDiscRoute *_r; \
|
||||
int _plen = (pl); \
|
||||
\
|
||||
g_assert(_rdata); \
|
||||
g_assert_cmpint(_idx, <, _rdata->routes_n); \
|
||||
g_assert(_rdata->routes); \
|
||||
g_assert(_plen > 0 && _plen <= 128); \
|
||||
\
|
||||
_r = &_rdata->routes[idx]; \
|
||||
\
|
||||
nmtst_assert_ip6_address(&_r->network, (nw)); \
|
||||
g_assert_cmpint((int) _r->plen, ==, _plen); \
|
||||
nmtst_assert_ip6_address(&_r->gateway, (gw)); \
|
||||
g_assert_cmpint(_r->expiry_msec, ==, (_expiry_msec)); \
|
||||
g_assert_cmpint(_r->preference, ==, (pref)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
static void
|
||||
match_dns_server(const NMNDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt)
|
||||
match_dns_server(const NMNDiscData *rdata, guint idx, const char *addr, gint64 expiry_msec)
|
||||
{
|
||||
const NMNDiscDNSServer *dns;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_assert(rdata);
|
||||
g_assert_cmpint(idx, <, rdata->dns_servers_n);
|
||||
|
|
@ -110,13 +107,12 @@ match_dns_server(const NMNDiscData *rdata, guint idx, const char *addr, guint32
|
|||
|
||||
dns = &rdata->dns_servers[idx];
|
||||
|
||||
g_assert_cmpstr(inet_ntop(AF_INET6, &dns->address, buf, sizeof(buf)), ==, addr);
|
||||
g_assert_cmpint(dns->timestamp, ==, ts);
|
||||
g_assert_cmpint(dns->lifetime, ==, lt);
|
||||
nmtst_assert_ip6_address(&dns->address, addr);
|
||||
g_assert_cmpint(dns->expiry_msec, ==, expiry_msec);
|
||||
}
|
||||
|
||||
static void
|
||||
match_dns_domain(const NMNDiscData *rdata, guint idx, const char *domain, guint32 ts, guint32 lt)
|
||||
match_dns_domain(const NMNDiscData *rdata, guint idx, const char *domain, gint64 expiry_msec)
|
||||
{
|
||||
const NMNDiscDNSDomain *dns;
|
||||
|
||||
|
|
@ -127,67 +123,96 @@ match_dns_domain(const NMNDiscData *rdata, guint idx, const char *domain, guint3
|
|||
dns = &rdata->dns_domains[idx];
|
||||
|
||||
g_assert_cmpstr(dns->domain, ==, domain);
|
||||
g_assert_cmpint(dns->timestamp, ==, ts);
|
||||
g_assert_cmpint(dns->lifetime, ==, lt);
|
||||
g_assert_cmpint(dns->expiry_msec, ==, expiry_msec);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainLoop *loop;
|
||||
gint64 timestamp_msec_1;
|
||||
guint counter;
|
||||
guint rs_counter;
|
||||
guint32 timestamp1;
|
||||
guint32 first_solicit;
|
||||
gint64 first_solicit_msec;
|
||||
guint32 timeout_id;
|
||||
} TestData;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
|
||||
g_assert_cmpint(changed,
|
||||
==,
|
||||
NM_NDISC_CONFIG_DHCP_LEVEL | NM_NDISC_CONFIG_GATEWAYS
|
||||
| NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES
|
||||
| NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS
|
||||
| NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU);
|
||||
g_assert_cmpint(rdata->dhcp_level, ==, NM_NDISC_DHCP_LEVEL_OTHERCONF);
|
||||
match_gateway(rdata, 0, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 10);
|
||||
match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp1, 10);
|
||||
match_dns_domain(rdata, 0, "foobar.com", data->timestamp1, 10);
|
||||
switch (data->counter++) {
|
||||
case 0:
|
||||
g_assert_cmpint(changed,
|
||||
==,
|
||||
NM_NDISC_CONFIG_DHCP_LEVEL | NM_NDISC_CONFIG_GATEWAYS
|
||||
| NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES
|
||||
| NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS
|
||||
| NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU);
|
||||
g_assert_cmpint(rdata->dhcp_level, ==, NM_NDISC_DHCP_LEVEL_OTHERCONF);
|
||||
match_gateway(rdata,
|
||||
0,
|
||||
"fe80::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_address(rdata,
|
||||
0,
|
||||
"2001:db8:a:a::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
data->timestamp_msec_1 + 10000);
|
||||
match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 10);
|
||||
match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp_msec_1 + 10000);
|
||||
match_dns_domain(rdata, 0, "foobar.com", data->timestamp_msec_1 + 3500);
|
||||
|
||||
g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc)));
|
||||
data->counter++;
|
||||
g_main_loop_quit(data->loop);
|
||||
g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc)));
|
||||
break;
|
||||
case 1:
|
||||
g_main_loop_quit(data->loop);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_simple(void)
|
||||
{
|
||||
NMFakeNDisc *ndisc = ndisc_new();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now};
|
||||
guint id;
|
||||
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE);
|
||||
gs_unref_object NMFakeNDisc *ndisc = ndisc_new();
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
TestData data = {
|
||||
.loop = loop,
|
||||
.timestamp_msec_1 = now_msec,
|
||||
};
|
||||
guint id;
|
||||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_OTHERCONF, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 10);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now, 10);
|
||||
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:a::",
|
||||
64,
|
||||
"fe80::1",
|
||||
now_msec + 10000,
|
||||
now_msec + 10000,
|
||||
10);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec + 10000);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now_msec + 3500);
|
||||
|
||||
g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_simple_changed), &data);
|
||||
|
||||
nm_ndisc_start(NM_NDISC(ndisc));
|
||||
g_main_loop_run(data.loop);
|
||||
g_assert_cmpint(data.counter, ==, 1);
|
||||
|
||||
g_object_unref(ndisc);
|
||||
g_main_loop_unref(data.loop);
|
||||
nmtst_main_loop_run_assert(data.loop, 15000);
|
||||
g_assert_cmpint(data.counter, ==, 2);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_everything_rs_sent(NMNDisc *ndisc, TestData *data)
|
||||
{
|
||||
|
|
@ -208,11 +233,19 @@ test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_
|
|||
| NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES
|
||||
| NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS
|
||||
| NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU);
|
||||
match_gateway(rdata, 0, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 10);
|
||||
match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp1, 10);
|
||||
match_dns_domain(rdata, 0, "foobar.com", data->timestamp1, 10);
|
||||
match_gateway(rdata,
|
||||
0,
|
||||
"fe80::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_address(rdata,
|
||||
0,
|
||||
"2001:db8:a:a::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
data->timestamp_msec_1 + 10000);
|
||||
match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 10);
|
||||
match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp_msec_1 + 10000);
|
||||
match_dns_domain(rdata, 0, "foobar.com", data->timestamp_msec_1 + 10000);
|
||||
} else if (data->counter == 1) {
|
||||
g_assert_cmpint(changed,
|
||||
==,
|
||||
|
|
@ -221,16 +254,28 @@ test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_
|
|||
| NM_NDISC_CONFIG_DNS_DOMAINS);
|
||||
|
||||
g_assert_cmpint(rdata->gateways_n, ==, 1);
|
||||
match_gateway(rdata, 0, "fe80::2", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_gateway(rdata,
|
||||
0,
|
||||
"fe80::2",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
g_assert_cmpint(rdata->addresses_n, ==, 2);
|
||||
match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 0);
|
||||
match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1, 10, 10);
|
||||
match_address(rdata,
|
||||
0,
|
||||
"2001:db8:a:a::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
data->timestamp_msec_1);
|
||||
match_address(rdata,
|
||||
1,
|
||||
"2001:db8:a:b::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
data->timestamp_msec_1 + 10000);
|
||||
g_assert_cmpint(rdata->routes_n, ==, 1);
|
||||
match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1, 10, 10);
|
||||
match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 10000, 10);
|
||||
g_assert_cmpint(rdata->dns_servers_n, ==, 1);
|
||||
match_dns_server(rdata, 0, "2001:db8:c:c::2", data->timestamp1, 10);
|
||||
match_dns_server(rdata, 0, "2001:db8:c:c::2", data->timestamp_msec_1 + 10000);
|
||||
g_assert_cmpint(rdata->dns_domains_n, ==, 1);
|
||||
match_dns_domain(rdata, 0, "foobar2.com", data->timestamp1, 10);
|
||||
match_dns_domain(rdata, 0, "foobar2.com", data->timestamp_msec_1 + 10000);
|
||||
|
||||
g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc)));
|
||||
g_main_loop_quit(data->loop);
|
||||
|
|
@ -243,42 +288,57 @@ test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_
|
|||
static void
|
||||
test_everything(void)
|
||||
{
|
||||
NMFakeNDisc *ndisc = ndisc_new();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now};
|
||||
guint id;
|
||||
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE);
|
||||
gs_unref_object NMFakeNDisc *ndisc = ndisc_new();
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
TestData data = {
|
||||
.loop = loop,
|
||||
.timestamp_msec_1 = now_msec,
|
||||
};
|
||||
guint id;
|
||||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 10);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now, 10);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:a::",
|
||||
64,
|
||||
"fe80::1",
|
||||
now_msec + 10000,
|
||||
now_msec + 10000,
|
||||
10);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec + 10000);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now_msec + 10000);
|
||||
|
||||
/* expire everything from the first RA in the second */
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 0, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 0, 0, 0);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 0);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now, 0);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now_msec, now_msec, 0);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now_msec);
|
||||
|
||||
/* and add some new stuff */
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::2", now, 10);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar2.com", now, 10);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:b::",
|
||||
64,
|
||||
"fe80::2",
|
||||
now_msec + 10000,
|
||||
now_msec + 10000,
|
||||
10);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::2", now_msec + 10000);
|
||||
nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar2.com", now_msec + 10000);
|
||||
|
||||
g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_everything_changed), &data);
|
||||
g_signal_connect(ndisc, NM_FAKE_NDISC_RS_SENT, G_CALLBACK(test_everything_rs_sent), &data);
|
||||
|
||||
nm_ndisc_start(NM_NDISC(ndisc));
|
||||
g_main_loop_run(data.loop);
|
||||
nmtst_main_loop_run_assert(data.loop, 15000);
|
||||
g_assert_cmpint(data.counter, ==, 2);
|
||||
g_assert_cmpint(data.rs_counter, ==, 1);
|
||||
|
||||
g_object_unref(ndisc);
|
||||
g_main_loop_unref(data.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -296,14 +356,30 @@ test_preference_order_cb(NMNDisc * ndisc,
|
|||
| NM_NDISC_CONFIG_ROUTES);
|
||||
|
||||
g_assert_cmpint(rdata->gateways_n, ==, 2);
|
||||
match_gateway(rdata, 0, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
match_gateway(rdata, 1, "fe80::2", data->timestamp1 + 1, 10, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
match_gateway(rdata,
|
||||
0,
|
||||
"fe80::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
match_gateway(rdata,
|
||||
1,
|
||||
"fe80::2",
|
||||
data->timestamp_msec_1 + 11000,
|
||||
NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
g_assert_cmpint(rdata->addresses_n, ==, 2);
|
||||
match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
match_address(rdata,
|
||||
0,
|
||||
"2001:db8:a:a::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
data->timestamp_msec_1 + 10000);
|
||||
match_address(rdata,
|
||||
1,
|
||||
"2001:db8:a:b::1",
|
||||
data->timestamp_msec_1 + 11000,
|
||||
data->timestamp_msec_1 + 10000);
|
||||
g_assert_cmpint(rdata->routes_n, ==, 2);
|
||||
match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 5);
|
||||
match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 11000, 10);
|
||||
match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 5);
|
||||
|
||||
g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc)));
|
||||
g_main_loop_quit(data->loop);
|
||||
|
|
@ -315,31 +391,46 @@ test_preference_order_cb(NMNDisc * ndisc,
|
|||
static void
|
||||
test_preference_order(void)
|
||||
{
|
||||
NMFakeNDisc *ndisc = ndisc_new();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now};
|
||||
guint id;
|
||||
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE);
|
||||
gs_unref_object NMFakeNDisc *ndisc = ndisc_new();
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
TestData data = {
|
||||
.loop = loop,
|
||||
.timestamp_msec_1 = now_msec,
|
||||
};
|
||||
guint id;
|
||||
|
||||
/* Test insertion order of gateways */
|
||||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 5);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:a::",
|
||||
64,
|
||||
"fe80::1",
|
||||
now_msec + 10000,
|
||||
now_msec + 10000,
|
||||
5);
|
||||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", ++now, 10, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now_msec + 11000, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:b::",
|
||||
64,
|
||||
"fe80::2",
|
||||
now_msec + 11000,
|
||||
now_msec + 10000,
|
||||
10);
|
||||
|
||||
g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_preference_order_cb), &data);
|
||||
|
||||
nm_ndisc_start(NM_NDISC(ndisc));
|
||||
g_main_loop_run(data.loop);
|
||||
nmtst_main_loop_run_assert(data.loop, 15000);
|
||||
g_assert_cmpint(data.counter, ==, 2);
|
||||
|
||||
g_object_unref(ndisc);
|
||||
g_main_loop_unref(data.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -356,14 +447,30 @@ test_preference_changed_cb(NMNDisc * ndisc,
|
|||
NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES
|
||||
| NM_NDISC_CONFIG_ROUTES);
|
||||
g_assert_cmpint(rdata->gateways_n, ==, 2);
|
||||
match_gateway(rdata, 0, "fe80::2", data->timestamp1 + 1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_gateway(rdata, 1, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
match_gateway(rdata,
|
||||
0,
|
||||
"fe80::2",
|
||||
data->timestamp_msec_1 + 11000,
|
||||
NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_gateway(rdata,
|
||||
1,
|
||||
"fe80::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
g_assert_cmpint(rdata->addresses_n, ==, 2);
|
||||
match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
match_address(rdata,
|
||||
0,
|
||||
"2001:db8:a:a::1",
|
||||
data->timestamp_msec_1 + 10000,
|
||||
data->timestamp_msec_1 + 10000);
|
||||
match_address(rdata,
|
||||
1,
|
||||
"2001:db8:a:b::1",
|
||||
data->timestamp_msec_1 + 11000,
|
||||
data->timestamp_msec_1 + 11000);
|
||||
g_assert_cmpint(rdata->routes_n, ==, 2);
|
||||
match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 5);
|
||||
match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 11000, 10);
|
||||
match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 5);
|
||||
} else if (data->counter == 2) {
|
||||
g_assert_cmpint(changed,
|
||||
==,
|
||||
|
|
@ -371,14 +478,30 @@ test_preference_changed_cb(NMNDisc * ndisc,
|
|||
| NM_NDISC_CONFIG_ROUTES);
|
||||
|
||||
g_assert_cmpint(rdata->gateways_n, ==, 2);
|
||||
match_gateway(rdata, 0, "fe80::1", data->timestamp1 + 2, 10, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
match_gateway(rdata, 1, "fe80::2", data->timestamp1 + 1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
match_gateway(rdata,
|
||||
0,
|
||||
"fe80::1",
|
||||
data->timestamp_msec_1 + 12000,
|
||||
NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
match_gateway(rdata,
|
||||
1,
|
||||
"fe80::2",
|
||||
data->timestamp_msec_1 + 11000,
|
||||
NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
g_assert_cmpint(rdata->addresses_n, ==, 2);
|
||||
match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1 + 3, 9, 9);
|
||||
match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
match_address(rdata,
|
||||
0,
|
||||
"2001:db8:a:a::1",
|
||||
data->timestamp_msec_1 + 12000,
|
||||
data->timestamp_msec_1 + 12000);
|
||||
match_address(rdata,
|
||||
1,
|
||||
"2001:db8:a:b::1",
|
||||
data->timestamp_msec_1 + 11000,
|
||||
data->timestamp_msec_1 + 11000);
|
||||
g_assert_cmpint(rdata->routes_n, ==, 2);
|
||||
match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1 + 2, 10, 15);
|
||||
match_route(rdata, 1, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 12000, 15);
|
||||
match_route(rdata, 1, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 11000, 10);
|
||||
|
||||
g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc)));
|
||||
g_main_loop_quit(data->loop);
|
||||
|
|
@ -390,10 +513,14 @@ test_preference_changed_cb(NMNDisc * ndisc,
|
|||
static void
|
||||
test_preference_changed(void)
|
||||
{
|
||||
NMFakeNDisc *ndisc = ndisc_new();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now};
|
||||
guint id;
|
||||
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE);
|
||||
gs_unref_object NMFakeNDisc *ndisc = ndisc_new();
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
TestData data = {
|
||||
.loop = loop,
|
||||
.timestamp_msec_1 = now_msec,
|
||||
};
|
||||
guint id;
|
||||
|
||||
/* Test that when a low-preference and medium gateway send advertisements,
|
||||
* that if the low-preference gateway switches to high-preference, we do
|
||||
|
|
@ -402,18 +529,39 @@ test_preference_changed(void)
|
|||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 5);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:a::",
|
||||
64,
|
||||
"fe80::1",
|
||||
now_msec + 10000,
|
||||
now_msec + 10000,
|
||||
5);
|
||||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", ++now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now_msec + 11000, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:b::",
|
||||
64,
|
||||
"fe80::2",
|
||||
now_msec + 11000,
|
||||
now_msec + 11000,
|
||||
10);
|
||||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", ++now, 10, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 15);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 12000, NM_ICMPV6_ROUTER_PREF_HIGH);
|
||||
nm_fake_ndisc_add_prefix(ndisc,
|
||||
id,
|
||||
"2001:db8:a:a::",
|
||||
64,
|
||||
"fe80::1",
|
||||
now_msec + 12000,
|
||||
now_msec + 12000,
|
||||
15);
|
||||
|
||||
g_signal_connect(ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
|
|
@ -421,68 +569,38 @@ test_preference_changed(void)
|
|||
&data);
|
||||
|
||||
nm_ndisc_start(NM_NDISC(ndisc));
|
||||
g_main_loop_run(data.loop);
|
||||
nmtst_main_loop_run_assert(data.loop, 15000);
|
||||
g_assert_cmpint(data.counter, ==, 3);
|
||||
|
||||
g_object_unref(ndisc);
|
||||
g_main_loop_unref(data.loop);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_dns_solicit_loop_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
TestData * data)
|
||||
_test_dns_solicit_loop_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
TestData * data)
|
||||
{
|
||||
data->counter++;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
success_timeout(TestData *data)
|
||||
{
|
||||
data->timeout_id = 0;
|
||||
g_main_loop_quit(data->loop);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dns_solicit_loop_rs_sent(NMFakeNDisc *ndisc, TestData *data)
|
||||
_test_dns_solicit_loop_rs_sent(NMFakeNDisc *ndisc, TestData *data)
|
||||
{
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
guint id;
|
||||
|
||||
if (data->rs_counter > 0 && data->rs_counter < 6) {
|
||||
if (data->rs_counter == 1) {
|
||||
data->first_solicit = now;
|
||||
/* Kill the test after 10 seconds if it hasn't failed yet */
|
||||
data->timeout_id = g_timeout_add_seconds(10, (GSourceFunc) success_timeout, data);
|
||||
}
|
||||
|
||||
/* On all but the first solicitation, which should be triggered by the
|
||||
* DNS servers reaching 1/2 lifetime, emit a new RA without the DNS
|
||||
* servers again.
|
||||
*/
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 0, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
|
||||
|
||||
nm_fake_ndisc_emit_new_ras(ndisc);
|
||||
} else if (data->rs_counter >= 6) {
|
||||
/* Fail if we've sent too many solicitations in the past 4 seconds */
|
||||
g_assert_cmpint(now - data->first_solicit, >, 4);
|
||||
g_source_remove(data->timeout_id);
|
||||
g_main_loop_quit(data->loop);
|
||||
}
|
||||
data->rs_counter++;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dns_solicit_loop(void)
|
||||
{
|
||||
NMFakeNDisc *ndisc = ndisc_new();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_sec();
|
||||
TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now, 0};
|
||||
guint id;
|
||||
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE);
|
||||
gs_unref_object NMFakeNDisc *ndisc = ndisc_new();
|
||||
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
|
||||
TestData data = {
|
||||
.loop = loop,
|
||||
.timestamp_msec_1 = now_msec,
|
||||
};
|
||||
guint id;
|
||||
|
||||
/* Ensure that no solicitation loop happens when DNS servers or domains
|
||||
* stop being sent in advertisements. This can happen if two routers
|
||||
|
|
@ -493,26 +611,27 @@ test_dns_solicit_loop(void)
|
|||
|
||||
id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert(id);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 6);
|
||||
nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_LOW);
|
||||
nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec + 6000);
|
||||
|
||||
g_signal_connect(ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK(test_dns_solicit_loop_changed),
|
||||
G_CALLBACK(_test_dns_solicit_loop_changed),
|
||||
&data);
|
||||
g_signal_connect(ndisc,
|
||||
NM_FAKE_NDISC_RS_SENT,
|
||||
G_CALLBACK(test_dns_solicit_loop_rs_sent),
|
||||
G_CALLBACK(_test_dns_solicit_loop_rs_sent),
|
||||
&data);
|
||||
|
||||
nm_ndisc_start(NM_NDISC(ndisc));
|
||||
g_main_loop_run(data.loop);
|
||||
if (nmtst_main_loop_run(data.loop, 10000))
|
||||
g_error("we expect to run the loop until timeout. What is wrong?");
|
||||
g_assert_cmpint(data.counter, ==, 3);
|
||||
|
||||
g_object_unref(ndisc);
|
||||
g_main_loop_unref(data.loop);
|
||||
g_assert_cmpint(data.rs_counter, ==, 1);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ char * nm_utils_format_con_diff_for_audit(GHashTable *diff);
|
|||
/* this enum is compatible with ICMPV6_ROUTER_PREF_* (from <linux/icmpv6.h>,
|
||||
* the values for netlink attribute RTA_PREF) and "enum ndp_route_preference"
|
||||
* from <ndp.h>. */
|
||||
typedef enum {
|
||||
typedef enum _nm_packed {
|
||||
NM_ICMPV6_ROUTER_PREF_MEDIUM = 0x0, /* ICMPV6_ROUTER_PREF_MEDIUM */
|
||||
NM_ICMPV6_ROUTER_PREF_LOW = 0x3, /* ICMPV6_ROUTER_PREF_LOW */
|
||||
NM_ICMPV6_ROUTER_PREF_HIGH = 0x1, /* ICMPV6_ROUTER_PREF_HIGH */
|
||||
|
|
|
|||
|
|
@ -1497,6 +1497,7 @@ nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
|
|||
NMIP6ConfigPrivate *priv;
|
||||
guint i;
|
||||
gboolean changed = FALSE;
|
||||
gint32 base_time_sec;
|
||||
|
||||
g_return_if_fail(NM_IS_IP6_CONFIG(self));
|
||||
|
||||
|
|
@ -1504,6 +1505,16 @@ nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
|
|||
|
||||
g_return_if_fail(priv->ifindex > 0);
|
||||
|
||||
/* the base-timestamp doesn't matter it's only an anchor for the
|
||||
* expiry. However, try to re-use the same base-time for a while
|
||||
* by rounding it to 10000 seconds.
|
||||
*
|
||||
* That is because we deduplicate and NMPlatformIP6Address instances
|
||||
* so using the same timestamps is preferable. */
|
||||
base_time_sec = nm_utils_get_monotonic_timestamp_sec();
|
||||
base_time_sec = (base_time_sec / 10000) * 10000;
|
||||
base_time_sec = NM_MAX(1, base_time_sec);
|
||||
|
||||
nm_dedup_multi_index_dirty_set_idx(priv->multi_idx, &priv->idx_ip6_addresses);
|
||||
|
||||
for (i = 0; i < addresses_n; i++) {
|
||||
|
|
@ -1516,9 +1527,13 @@ nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
|
|||
a->ifindex = priv->ifindex;
|
||||
a->address = ndisc_addr->address;
|
||||
a->plen = plen;
|
||||
a->timestamp = ndisc_addr->timestamp;
|
||||
a->lifetime = ndisc_addr->lifetime;
|
||||
a->preferred = MIN(ndisc_addr->lifetime, ndisc_addr->preferred);
|
||||
a->timestamp = base_time_sec,
|
||||
a->lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) base_time_sec) * 1000,
|
||||
ndisc_addr->expiry_msec,
|
||||
TRUE),
|
||||
a->preferred = _nm_ndisc_lifetime_from_expiry(((gint64) base_time_sec) * 1000,
|
||||
ndisc_addr->expiry_preferred_msec,
|
||||
TRUE),
|
||||
a->addr_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
a->n_ifa_flags = ifa_flags;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue