Commit 057b6397 authored by Thomas Haller's avatar Thomas Haller
Browse files

core: move setting NDisc addresses/routes to NMIP6Config

Add an utility function for resetting addresses/routes of NMIP6Config
from NMNDisc data. For one, this de-duplicates code in device and
nm-iface-helper.

Also, we no longer first reset (delete) all addresses and add them anew.
Instead, we first mark all entries as dirty for deletion, merge (append)
the new entires, and delete the remaining dirty entires. This saves a
extra work, in the expected case where NMIP6Config already contains
several of the new entries.
parent 1b3a0208
......@@ -7420,49 +7420,18 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
}
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
/* Rebuild address list from neighbor discovery cache. */
nm_ip6_config_reset_addresses (priv->ac_ip6_config);
/* ndisc->addresses contains at most max_addresses entries.
* This is different from what the kernel does, which
* also counts static and temporary addresses when checking
* max_addresses.
**/
for (i = 0; i < rdata->addresses_n; i++) {
const NMNDiscAddress *discovered_address = &rdata->addresses[i];
NMPlatformIP6Address address;
memset (&address, 0, sizeof (address));
address.address = discovered_address->address;
address.plen = system_support ? 64 : 128;
address.timestamp = discovered_address->timestamp;
address.lifetime = discovered_address->lifetime;
address.preferred = discovered_address->preferred;
if (address.preferred > address.lifetime)
address.preferred = address.lifetime;
address.addr_source = NM_IP_CONFIG_SOURCE_NDISC;
address.n_ifa_flags = ifa_flags;
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
}
nm_ip6_config_reset_addresses_ndisc (priv->ac_ip6_config,
rdata->addresses,
rdata->addresses_n,
system_support ? 64 : 128,
ifa_flags);
}
if (changed & NM_NDISC_CONFIG_ROUTES) {
/* Rebuild route list from neighbor discovery cache. */
nm_ip6_config_reset_routes (priv->ac_ip6_config);
for (i = 0; i < rdata->routes_n; i++) {
const NMNDiscRoute *discovered_route = &rdata->routes[i];
const NMPlatformIP6Route route = {
.network = discovered_route->network,
.plen = discovered_route->plen,
.gateway = discovered_route->gateway,
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
.metric = nm_device_get_ip6_route_metric (self),
};
nm_ip6_config_add_route (priv->ac_ip6_config, &route);
}
nm_ip6_config_reset_routes_ndisc (priv->ac_ip6_config,
rdata->routes,
rdata->routes_n,
nm_device_get_ip6_route_metric (self));
}
if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
......
......@@ -69,22 +69,24 @@ typedef struct {
NMNDiscPreference preference;
} NMNDiscGateway;
typedef struct {
struct _NMNDiscAddress {
struct in6_addr address;
guint8 dad_counter;
guint32 timestamp;
guint32 lifetime;
guint32 preferred;
} NMNDiscAddress;
};
typedef struct _NMNDiscAddress NMNDiscAddress;
typedef struct {
struct _NMNDiscRoute {
struct in6_addr network;
guint8 plen;
struct in6_addr gateway;
guint32 timestamp;
guint32 lifetime;
NMNDiscPreference preference;
} NMNDiscRoute;
};
typedef struct _NMNDiscRoute NMNDiscRoute;
typedef struct {
struct in6_addr address;
......
......@@ -156,7 +156,6 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
NMIP6Config *existing;
int system_support;
guint32 ifa_flags = 0x00;
int i;
/*
* Check, whether kernel is recent enough, to help user space handling RA.
......@@ -194,49 +193,18 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
}
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
/* Rebuild address list from neighbor discovery cache. */
nm_ip6_config_reset_addresses (ndisc_config);
/* ndisc->addresses contains at most max_addresses entries.
* This is different from what the kernel does, which
* also counts static and temporary addresses when checking
* max_addresses.
**/
for (i = 0; i < rdata->addresses_n; i++) {
const NMNDiscAddress *discovered_address = &rdata->addresses[i];
NMPlatformIP6Address address;
memset (&address, 0, sizeof (address));
address.address = discovered_address->address;
address.plen = system_support ? 64 : 128;
address.timestamp = discovered_address->timestamp;
address.lifetime = discovered_address->lifetime;
address.preferred = discovered_address->preferred;
if (address.preferred > address.lifetime)
address.preferred = address.lifetime;
address.addr_source = NM_IP_CONFIG_SOURCE_NDISC;
address.n_ifa_flags = ifa_flags;
nm_ip6_config_add_address (ndisc_config, &address);
}
nm_ip6_config_reset_addresses_ndisc (ndisc_config,
rdata->addresses,
rdata->addresses_n,
system_support ? 64 : 128,
ifa_flags);
}
if (changed & NM_NDISC_CONFIG_ROUTES) {
/* Rebuild route list from neighbor discovery cache. */
nm_ip6_config_reset_routes (ndisc_config);
for (i = 0; i < rdata->routes_n; i++) {
const NMNDiscRoute *discovered_route = &rdata->routes[i];
const NMPlatformIP6Route route = {
.network = discovered_route->network,
.plen = discovered_route->plen,
.gateway = discovered_route->gateway,
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
.metric = global_opt.priority_v6,
};
nm_ip6_config_add_route (ndisc_config, &route);
}
nm_ip6_config_reset_routes_ndisc (ndisc_config,
rdata->routes,
rdata->routes_n,
global_opt.priority_v6);
}
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
......
......@@ -35,6 +35,7 @@
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-ip4-config.h"
#include "ndisc/nm-ndisc.h"
#include "introspection/org.freedesktop.NetworkManager.IP6Config.h"
......@@ -1189,6 +1190,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst);
src_priv = NM_IP6_CONFIG_GET_PRIVATE (src);
g_return_val_if_fail (src_priv->ifindex > 0, FALSE);
g_object_freeze_notify (G_OBJECT (dst));
/* ifindex */
......@@ -1520,6 +1523,58 @@ nm_ip6_config_get_route_metric (const NMIP6Config *self)
/*****************************************************************************/
void
nm_ip6_config_reset_addresses_ndisc (NMIP6Config *self,
const NMNDiscAddress *addresses,
guint addresses_n,
guint8 plen,
guint32 ifa_flags)
{
NMIP6ConfigPrivate *priv;
guint i;
gboolean changed = FALSE;
g_return_if_fail (NM_IS_IP6_CONFIG (self));
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
g_return_if_fail (priv->ifindex > 0);
nm_dedup_multi_index_dirty_set_idx (priv->multi_idx, &priv->idx_ip6_addresses);
for (i = 0; i < addresses_n; i++) {
const NMNDiscAddress *ndisc_addr = &addresses[i];
NMPObject obj;
NMPlatformIP6Address *a;
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
a = NMP_OBJECT_CAST_IP6_ADDRESS (&obj);
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->addr_source = NM_IP_CONFIG_SOURCE_NDISC;
a->n_ifa_flags = ifa_flags;
if (_nm_ip_config_add_obj (priv->multi_idx,
&priv->idx_ip6_addresses_,
priv->ifindex,
&obj,
NULL,
FALSE,
TRUE))
changed = TRUE;
}
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_addresses, FALSE) > 0)
changed = TRUE;
if (changed)
_notify_addresses (self);
}
void
nm_ip6_config_reset_addresses (NMIP6Config *self)
{
......@@ -1698,6 +1753,55 @@ nm_ip6_config_has_any_dad_pending (const NMIP6Config *self,
/*****************************************************************************/
void
nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
const NMNDiscRoute *routes,
guint routes_n,
guint32 metric)
{
NMIP6ConfigPrivate *priv;
guint i;
gboolean changed = FALSE;
g_return_if_fail (NM_IS_IP6_CONFIG (self));
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
g_return_if_fail (priv->ifindex > 0);
nm_dedup_multi_index_dirty_set_idx (priv->multi_idx, &priv->idx_ip6_routes);
for (i = 0; i < routes_n; i++) {
const NMNDiscRoute *ndisc_route = &routes[i];
NMPObject obj;
NMPlatformIP6Route *r;
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
r = NMP_OBJECT_CAST_IP6_ROUTE (&obj);
r->ifindex = priv->ifindex;
r->network = ndisc_route->network;
r->plen = ndisc_route->plen;
r->gateway = ndisc_route->gateway;
r->rt_source = NM_IP_CONFIG_SOURCE_NDISC;
r->metric = metric;
if (_nm_ip_config_add_obj (priv->multi_idx,
&priv->idx_ip6_routes_,
priv->ifindex,
&obj,
NULL,
FALSE,
TRUE))
changed = TRUE;
}
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
changed = TRUE;
if (changed)
_notify_routes (self);
}
void
nm_ip6_config_reset_routes (NMIP6Config *self)
{
......
......@@ -191,6 +191,18 @@ gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b);
void nm_ip6_config_set_privacy (NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy);
struct _NMNDiscAddress;
void nm_ip6_config_reset_addresses_ndisc (NMIP6Config *self,
const struct _NMNDiscAddress *addresses,
guint addresses_n,
guint8 plen,
guint32 ifa_flags);
struct _NMNDiscRoute;
void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
const struct _NMNDiscRoute *routes,
guint routes_n,
guint32 metric);
/*****************************************************************************/
/* Testing-only functions */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment