mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-05 01:47:58 +02:00
l3cfg: merge branch 'th/l3cfg-11'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/637
This commit is contained in:
commit
77ad359442
11 changed files with 892 additions and 609 deletions
|
|
@ -96,6 +96,22 @@ typedef struct {
|
|||
.ether_addr_octet = {__VA_ARGS__}, \
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_ether_addr_cmp(const NMEtherAddr *a, const NMEtherAddr *b)
|
||||
{
|
||||
NM_CMP_SELF(a, b);
|
||||
NM_CMP_DIRECT_MEMCMP(a, b, sizeof(NMEtherAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nm_ether_addr_equal(const NMEtherAddr *a, const NMEtherAddr *b)
|
||||
{
|
||||
return nm_ether_addr_cmp(a, b) == 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
guint8 addr_ptr[1];
|
||||
|
|
@ -248,126 +264,6 @@ gboolean nm_utils_ipaddr_is_normalized(int addr_family, const char *str_addr);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_CMP_RETURN(c) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const int _cc = (c); \
|
||||
if (_cc) \
|
||||
return _cc < 0 ? -1 : 1; \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_RETURN_DIRECT(c) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const int _cc = (c); \
|
||||
if (_cc) \
|
||||
return _cc; \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_SELF(a, b) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
\
|
||||
if (_a == _b) \
|
||||
return 0; \
|
||||
if (!_a) \
|
||||
return -1; \
|
||||
if (!_b) \
|
||||
return 1; \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_DIRECT(a, b) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
\
|
||||
if (_a != _b) \
|
||||
return (_a < _b) ? -1 : 1; \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_DIRECT_UNSAFE(a, b) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
if ((a) != (b)) \
|
||||
return ((a) < (b)) ? -1 : 1; \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
/* In the general case, direct pointer comparison is undefined behavior in C.
|
||||
* Avoid that by casting pointers to void* and then to uintptr_t. This comparison
|
||||
* is not really meaningful, except that it provides some kind of stable sort order
|
||||
* between pointers (that can otherwise not be compared). */
|
||||
#define NM_CMP_DIRECT_PTR(a, b) NM_CMP_DIRECT((uintptr_t)((void *) (a)), (uintptr_t)((void *) (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_MEMCMP(a, b, size) NM_CMP_RETURN(memcmp((a), (b), (size)))
|
||||
|
||||
#define NM_CMP_DIRECT_STRCMP(a, b) NM_CMP_RETURN_DIRECT(strcmp((a), (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_STRCMP0(a, b) NM_CMP_RETURN_DIRECT(nm_strcmp0((a), (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_IN6ADDR(a, b) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const struct in6_addr *const _a = (a); \
|
||||
const struct in6_addr *const _b = (b); \
|
||||
NM_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_FIELD(a, b, field) NM_CMP_DIRECT(((a)->field), ((b)->field))
|
||||
|
||||
#define NM_CMP_FIELD_UNSAFE(a, b, field) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
/* it's unsafe, because it evaluates the arguments more then once.
|
||||
* This is necessary for bitfields, for which typeof() doesn't work. */ \
|
||||
if (((a)->field) != ((b)->field)) \
|
||||
return ((a)->field < ((b)->field)) ? -1 : 1; \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_FIELD_BOOL(a, b, field) NM_CMP_DIRECT(!!((a)->field), !!((b)->field))
|
||||
|
||||
#define NM_CMP_FIELD_STR(a, b, field) NM_CMP_RETURN(strcmp(((a)->field), ((b)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_STR_INTERNED(a, b, field) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const char *_a = ((a)->field); \
|
||||
const char *_b = ((b)->field); \
|
||||
\
|
||||
if (_a != _b) { \
|
||||
NM_CMP_RETURN_DIRECT(nm_strcmp0(_a, _b)); \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define NM_CMP_FIELD_STR0(a, b, field) NM_CMP_RETURN_DIRECT(nm_strcmp0(((a)->field), ((b)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
|
||||
NM_CMP_RETURN(memcmp(&((a)->field), &((b)->field), NM_MIN(len, sizeof((a)->field))))
|
||||
|
||||
#define NM_CMP_FIELD_MEMCMP(a, b, field) \
|
||||
NM_CMP_RETURN(memcmp(&((a)->field), &((b)->field), sizeof((a)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_IN6ADDR(a, b, field) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const struct in6_addr *const _a = &((a)->field); \
|
||||
const struct in6_addr *const _b = &((b)->field); \
|
||||
NM_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_utils_memeqzero(gconstpointer data, gsize length);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -43,6 +44,23 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __CHECKER__
|
||||
#define _nm_bitwise __attribute__((__bitwise__))
|
||||
#define _nm_force __attribute__((__force__))
|
||||
#else
|
||||
#define _nm_bitwise
|
||||
#define _nm_force
|
||||
#endif
|
||||
|
||||
typedef uint16_t _nm_bitwise nm_le16_t;
|
||||
typedef uint16_t _nm_bitwise nm_be16_t;
|
||||
typedef uint32_t _nm_bitwise nm_le32_t;
|
||||
typedef uint32_t _nm_bitwise nm_be32_t;
|
||||
typedef uint64_t _nm_bitwise nm_le64_t;
|
||||
typedef uint64_t _nm_bitwise nm_be64_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef thread_local
|
||||
#define _nm_thread_local thread_local
|
||||
/*
|
||||
|
|
@ -749,6 +767,108 @@ nm_steal_fd(int *p_fd)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_CMP_RETURN(c) \
|
||||
do { \
|
||||
const int _cc = (c); \
|
||||
if (_cc) \
|
||||
return _cc < 0 ? -1 : 1; \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_RETURN_DIRECT(c) \
|
||||
do { \
|
||||
const int _cc = (c); \
|
||||
if (_cc) \
|
||||
return _cc; \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_SELF(a, b) \
|
||||
do { \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
\
|
||||
if (_a == _b) \
|
||||
return 0; \
|
||||
if (!_a) \
|
||||
return -1; \
|
||||
if (!_b) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_DIRECT(a, b) \
|
||||
do { \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
\
|
||||
if (_a != _b) \
|
||||
return (_a < _b) ? -1 : 1; \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_DIRECT_UNSAFE(a, b) \
|
||||
do { \
|
||||
if ((a) != (b)) \
|
||||
return ((a) < (b)) ? -1 : 1; \
|
||||
} while (0)
|
||||
|
||||
/* In the general case, direct pointer comparison is undefined behavior in C.
|
||||
* Avoid that by casting pointers to void* and then to uintptr_t. This comparison
|
||||
* is not really meaningful, except that it provides some kind of stable sort order
|
||||
* between pointers (that can otherwise not be compared). */
|
||||
#define NM_CMP_DIRECT_PTR(a, b) NM_CMP_DIRECT((uintptr_t)((void *) (a)), (uintptr_t)((void *) (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_MEMCMP(a, b, size) NM_CMP_RETURN(memcmp((a), (b), (size)))
|
||||
|
||||
#define NM_CMP_DIRECT_STRCMP(a, b) NM_CMP_RETURN_DIRECT(strcmp((a), (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_STRCMP0(a, b) NM_CMP_RETURN_DIRECT(nm_strcmp0((a), (b)))
|
||||
|
||||
#define NM_CMP_DIRECT_IN6ADDR(a, b) \
|
||||
do { \
|
||||
const struct in6_addr *const _a = (a); \
|
||||
const struct in6_addr *const _b = (b); \
|
||||
NM_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_FIELD(a, b, field) NM_CMP_DIRECT(((a)->field), ((b)->field))
|
||||
|
||||
#define NM_CMP_FIELD_UNSAFE(a, b, field) \
|
||||
do { \
|
||||
/* it's unsafe, because it evaluates the arguments more then once.
|
||||
* This is necessary for bitfields, for which typeof() doesn't work. */ \
|
||||
if (((a)->field) != ((b)->field)) \
|
||||
return ((a)->field < ((b)->field)) ? -1 : 1; \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_FIELD_BOOL(a, b, field) NM_CMP_DIRECT(!!((a)->field), !!((b)->field))
|
||||
|
||||
#define NM_CMP_FIELD_STR(a, b, field) NM_CMP_RETURN(strcmp(((a)->field), ((b)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_STR_INTERNED(a, b, field) \
|
||||
do { \
|
||||
const char *_a = ((a)->field); \
|
||||
const char *_b = ((b)->field); \
|
||||
\
|
||||
if (_a != _b) { \
|
||||
NM_CMP_RETURN_DIRECT(nm_strcmp0(_a, _b)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NM_CMP_FIELD_STR0(a, b, field) NM_CMP_RETURN_DIRECT(nm_strcmp0(((a)->field), ((b)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
|
||||
NM_CMP_RETURN(memcmp(&((a)->field), &((b)->field), NM_MIN(len, sizeof((a)->field))))
|
||||
|
||||
#define NM_CMP_FIELD_MEMCMP(a, b, field) \
|
||||
NM_CMP_RETURN(memcmp(&((a)->field), &((b)->field), sizeof((a)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_IN6ADDR(a, b, field) \
|
||||
do { \
|
||||
const struct in6_addr *const _a = &((a)->field); \
|
||||
const struct in6_addr *const _b = &((b)->field); \
|
||||
NM_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \
|
||||
} while (0)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_AF_UNSPEC 0 /* AF_UNSPEC */
|
||||
#define NM_AF_INET 2 /* AF_INET */
|
||||
#define NM_AF_INET6 10 /* AF_INET6 */
|
||||
|
|
|
|||
|
|
@ -2514,17 +2514,34 @@ void
|
|||
nm_l3_config_data_merge(NML3ConfigData * self,
|
||||
const NML3ConfigData *src,
|
||||
NML3ConfigMergeFlags merge_flags,
|
||||
const guint32 * default_route_table_x /* length 2, for IS_IPv4 */,
|
||||
const guint32 * default_route_metric_x /* length 2, for IS_IPv4 */,
|
||||
const guint32 * default_route_penalty_x /* length 2, for IS_IPv4 */,
|
||||
NML3ConfigMergeHookAddObj hook_add_addr,
|
||||
gpointer hook_user_data)
|
||||
{
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject *obj;
|
||||
int IS_IPv4;
|
||||
static const guint32 x_default_route_table_x[2] = {RT_TABLE_MAIN, RT_TABLE_MAIN};
|
||||
static const guint32 x_default_route_metric_x[2] = {NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
|
||||
NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4};
|
||||
static const guint32 x_default_route_penalty_x[2] = {0, 0};
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject * obj;
|
||||
int IS_IPv4;
|
||||
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(src, TRUE));
|
||||
|
||||
if (!default_route_table_x)
|
||||
default_route_table_x = x_default_route_table_x;
|
||||
if (!default_route_metric_x)
|
||||
default_route_metric_x = x_default_route_metric_x;
|
||||
if (!default_route_penalty_x)
|
||||
default_route_penalty_x = x_default_route_penalty_x;
|
||||
|
||||
nm_assert(default_route_table_x[0] != 0);
|
||||
nm_assert(default_route_table_x[1] != 0);
|
||||
nm_assert(default_route_metric_x[0] != 0); /* IPv6 route metric cannot be zero. */
|
||||
|
||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
|
||||
const NML3ConfigDatFlags has_dns_priority_flag =
|
||||
|
|
@ -2546,41 +2563,58 @@ nm_l3_config_data_merge(NML3ConfigData * self,
|
|||
if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES)) {
|
||||
nm_l3_config_data_iter_obj_for_each(&iter, src, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))
|
||||
{
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(NMP_OBJECT_CAST_IP_ROUTE(obj))) {
|
||||
const NMPlatformIPRoute *r_src = NMP_OBJECT_CAST_IP_ROUTE(obj);
|
||||
NMPlatformIPXRoute r;
|
||||
|
||||
#define _ensure_r() \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
if (r_src != &r.rx) { \
|
||||
r_src = &r.rx; \
|
||||
if (IS_IPv4) \
|
||||
r.r4 = *NMP_OBJECT_CAST_IP4_ROUTE(obj); \
|
||||
else \
|
||||
r.r6 = *NMP_OBJECT_CAST_IP6_ROUTE(obj); \
|
||||
r.rx.ifindex = self->ifindex; \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
if (r_src->table_any) {
|
||||
_ensure_r();
|
||||
r.rx.table_any = FALSE;
|
||||
r.rx.table_coerced = default_route_table_x[IS_IPv4];
|
||||
}
|
||||
|
||||
if (r_src->metric_any) {
|
||||
_ensure_r();
|
||||
r.rx.metric_any = FALSE;
|
||||
r.rx.metric_any = default_route_metric_x[IS_IPv4];
|
||||
}
|
||||
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) {
|
||||
if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES)
|
||||
&& !NM_FLAGS_HAS(src->flags,
|
||||
NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
|
||||
continue;
|
||||
|
||||
if (default_route_penalty_x && default_route_penalty_x[IS_IPv4] > 0) {
|
||||
NMPlatformIPXRoute r;
|
||||
|
||||
if (IS_IPv4)
|
||||
r.r4 = *NMP_OBJECT_CAST_IP4_ROUTE(obj);
|
||||
else
|
||||
r.r6 = *NMP_OBJECT_CAST_IP6_ROUTE(obj);
|
||||
r.rx.ifindex = self->ifindex;
|
||||
_ensure_r();
|
||||
r.rx.metric =
|
||||
nm_utils_ip_route_metric_penalize(r.rx.metric,
|
||||
default_route_penalty_x[IS_IPv4]);
|
||||
nm_l3_config_data_add_route_full(self,
|
||||
addr_family,
|
||||
NULL,
|
||||
&r.rx,
|
||||
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
nm_l3_config_data_add_route_full(self,
|
||||
addr_family,
|
||||
obj,
|
||||
NULL,
|
||||
r_src == &r.rx ? NULL : obj,
|
||||
r_src == &r.rx ? r_src : NULL,
|
||||
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#undef _ensure_r
|
||||
}
|
||||
|
||||
if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS))
|
||||
|
|
@ -2666,6 +2700,6 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex)
|
|||
ifindex = src->ifindex;
|
||||
|
||||
self = nm_l3_config_data_new(src->multi_idx, ifindex);
|
||||
nm_l3_config_data_merge(self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL, NULL, NULL);
|
||||
nm_l3_config_data_merge(self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL, NULL, NULL, NULL, NULL);
|
||||
return self;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,15 @@ typedef enum {
|
|||
/**
|
||||
* NML3ConfigMergeFlags:
|
||||
* @NM_L3_CONFIG_MERGE_FLAGS_NONE: no flags set
|
||||
* @NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD: if this merge flag is set,
|
||||
* the the NML3ConfigData doesn't get merged and it's information won't be
|
||||
* synced. The only purpose is to run ACD on its IPv4 addresses, but
|
||||
* regardless whether ACD succeeds/fails, the IP addresses won't be configured.
|
||||
* The point is to run ACD first (without configuring it), and only
|
||||
* commit the settings if requested. That can either happen by
|
||||
* nm_l3cfg_add_config() the same NML3Cfg again (with a different
|
||||
* tag), or by calling nm_l3cfg_add_config() again with this flag
|
||||
* cleared (and the same tag).
|
||||
* @NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES: don't merge routes
|
||||
* @NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES: don't merge default routes.
|
||||
* Note that if the respective NML3ConfigData has NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES
|
||||
|
|
@ -54,9 +63,10 @@ typedef enum {
|
|||
*/
|
||||
typedef enum _nm_packed {
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NONE = 0,
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES = (1LL << 0),
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES = (1LL << 1),
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NO_DNS = (1LL << 2),
|
||||
NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD = (1LL << 0),
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES = (1LL << 1),
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES = (1LL << 2),
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NO_DNS = (1LL << 3),
|
||||
} NML3ConfigMergeFlags;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -136,6 +146,8 @@ typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData *l3cd,
|
|||
void nm_l3_config_data_merge(NML3ConfigData * self,
|
||||
const NML3ConfigData *src,
|
||||
NML3ConfigMergeFlags merge_flags,
|
||||
const guint32 *default_route_table_x /* length 2, for IS_IPv4 */,
|
||||
const guint32 *default_route_metric_x /* length 2, for IS_IPv4 */,
|
||||
const guint32 *default_route_penalty_x /* length 2, for IS_IPv4 */,
|
||||
NML3ConfigMergeHookAddObj hook_add_addr,
|
||||
gpointer hook_user_data);
|
||||
|
|
|
|||
336
src/nm-l3cfg.c
336
src/nm-l3cfg.c
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <net/if.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-object.h"
|
||||
|
|
@ -111,6 +112,20 @@ struct _NML3CfgCommitTypeHandle {
|
|||
typedef struct {
|
||||
const NML3ConfigData *l3cd;
|
||||
NML3ConfigMergeFlags merge_flags;
|
||||
union {
|
||||
struct {
|
||||
guint32 default_route_table_6;
|
||||
guint32 default_route_table_4;
|
||||
};
|
||||
guint32 default_route_table_x[2];
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
guint32 default_route_metric_6;
|
||||
guint32 default_route_metric_4;
|
||||
};
|
||||
guint32 default_route_metric_x[2];
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
guint32 default_route_penalty_6;
|
||||
|
|
@ -163,7 +178,7 @@ typedef struct _NML3CfgPrivate {
|
|||
/* This is for rate-limiting the creation of nacd instance. */
|
||||
GSource *nacd_instance_ensure_retry;
|
||||
|
||||
GSource *acd_ready_on_idle_source;
|
||||
GSource *commit_on_idle_source;
|
||||
|
||||
guint64 pseudo_timestamp_counter;
|
||||
|
||||
|
|
@ -232,6 +247,8 @@ G_DEFINE_TYPE(NML3Cfg, nm_l3cfg, G_TYPE_OBJECT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle);
|
||||
|
||||
static void _property_emit_notify(NML3Cfg *self, NML3CfgPropertyEmitType emit_type);
|
||||
|
||||
static void _l3_acd_data_notify_acd_completed_all(NML3Cfg *self);
|
||||
|
|
@ -266,6 +283,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,
|
||||
|
|
@ -275,10 +293,9 @@ static NM_UTILS_ENUM2STR_DEFINE(
|
|||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
_l3_config_notify_type_and_payload_to_string(NML3ConfigNotifyType notify_type,
|
||||
const NML3ConfigNotifyPayload *payload,
|
||||
char * sbuf,
|
||||
gsize sbuf_size)
|
||||
_l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data,
|
||||
char * sbuf,
|
||||
gsize sbuf_size)
|
||||
{
|
||||
char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN];
|
||||
char *s = sbuf;
|
||||
|
|
@ -287,22 +304,31 @@ _l3_config_notify_type_and_payload_to_string(NML3ConfigNotifyType noti
|
|||
nm_assert(sbuf);
|
||||
nm_assert(sbuf_size > 0);
|
||||
|
||||
_l3_config_notify_type_to_string(notify_type, s, l);
|
||||
_l3_config_notify_type_to_string(notify_data->notify_type, s, l);
|
||||
nm_utils_strbuf_seek_end(&s, &l);
|
||||
|
||||
switch (notify_type) {
|
||||
switch (notify_data->notify_type) {
|
||||
case NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED:
|
||||
nm_utils_strbuf_append(&s,
|
||||
&l,
|
||||
", addr=%s, probe-result=%d",
|
||||
_nm_utils_inet4_ntop(payload->acd_completed.addr, sbuf_addr),
|
||||
(int) payload->acd_completed.probe_result);
|
||||
_nm_utils_inet4_ntop(notify_data->acd_completed.addr, sbuf_addr),
|
||||
(int) notify_data->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(notify_data->platform_change.obj)->obj_type_name,
|
||||
nm_platform_signal_change_type_to_string(notify_data->platform_change.change_type));
|
||||
nmp_object_to_string(notify_data->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,
|
||||
", obj-type-flags=0x%x",
|
||||
payload->platform_change_on_idle.obj_type_flags);
|
||||
notify_data->platform_change_on_idle.obj_type_flags);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -312,23 +338,26 @@ _l3_config_notify_type_and_payload_to_string(NML3ConfigNotifyType noti
|
|||
}
|
||||
|
||||
void
|
||||
_nm_l3cfg_emit_signal_notify(NML3Cfg * self,
|
||||
NML3ConfigNotifyType notify_type,
|
||||
const NML3ConfigNotifyPayload *payload)
|
||||
_nm_l3cfg_emit_signal_notify(NML3Cfg *self, const NML3ConfigNotifyData *notify_data)
|
||||
{
|
||||
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_ON_IDLE));
|
||||
nm_assert(notify_data);
|
||||
nm_assert(_NM_INT_NOT_NEGATIVE(notify_data->notify_type));
|
||||
nm_assert(notify_data->notify_type < _NM_L3_CONFIG_NOTIFY_TYPE_NUM);
|
||||
|
||||
_LOGT("emit signal (%s)",
|
||||
_l3_config_notify_type_and_payload_to_string(notify_type, payload, sbuf, sizeof(sbuf)));
|
||||
_LOGT("emit signal (%s)", _l3_config_notify_data_to_string(notify_data, sbuf, sizeof(sbuf)));
|
||||
|
||||
g_signal_emit(self, signals[SIGNAL_NOTIFY], 0, (int) notify_type, payload);
|
||||
g_signal_emit(self, signals[SIGNAL_NOTIFY], 0, notify_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_nm_l3cfg_emit_signal_notify_simple(NML3Cfg *self, NML3ConfigNotifyType notify_type)
|
||||
{
|
||||
NML3ConfigNotifyData notify_data;
|
||||
|
||||
notify_data.notify_type = notify_type;
|
||||
_nm_l3cfg_emit_signal_notify(self, ¬ify_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -581,13 +610,19 @@ _load_link(NML3Cfg *self, gboolean initial)
|
|||
gboolean nacd_link_now_up;
|
||||
AcdData * acd_data;
|
||||
|
||||
obj = nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE);
|
||||
if (initial) {
|
||||
obj = nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE);
|
||||
self->priv.plobj_next = nmp_object_ref(obj);
|
||||
} else {
|
||||
obj = self->priv.plobj_next;
|
||||
nm_assert(obj == nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE));
|
||||
}
|
||||
|
||||
if (initial && obj == self->priv.pllink)
|
||||
if (initial && obj == self->priv.plobj)
|
||||
return;
|
||||
|
||||
obj_old = g_steal_pointer(&self->priv.pllink);
|
||||
self->priv.pllink = nmp_object_ref(obj);
|
||||
obj_old = g_steal_pointer(&self->priv.plobj);
|
||||
self->priv.plobj = nmp_object_ref(obj);
|
||||
|
||||
if (obj && NM_FLAGS_HAS(NMP_OBJECT_CAST_LINK(obj)->n_ifi_flags, IFF_UP)
|
||||
&& (!obj_old || !NM_FLAGS_HAS(NMP_OBJECT_CAST_LINK(obj_old)->n_ifi_flags, IFF_UP)))
|
||||
|
|
@ -613,7 +648,7 @@ _load_link(NML3Cfg *self, gboolean initial)
|
|||
} else if (nacd_new_valid)
|
||||
nacd_changed = TRUE;
|
||||
ifname_old = nmp_object_link_get_ifname(obj_old);
|
||||
ifname = nmp_object_link_get_ifname(self->priv.pllink);
|
||||
ifname = nmp_object_link_get_ifname(self->priv.plobj);
|
||||
|
||||
if (initial) {
|
||||
_LOGT("link ifname changed: %s%s%s (initial)", NM_PRINT_FMT_QUOTE_STRING(ifname));
|
||||
|
|
@ -641,18 +676,16 @@ _load_link(NML3Cfg *self, gboolean initial)
|
|||
void
|
||||
_nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags)
|
||||
{
|
||||
NML3ConfigNotifyPayload payload;
|
||||
NML3ConfigNotifyData notify_data;
|
||||
|
||||
if (NM_FLAGS_ANY(obj_type_flags, nmp_object_type_to_flags(NMP_OBJECT_TYPE_LINK)))
|
||||
if (self->priv.plobj_next != self->priv.plobj)
|
||||
_load_link(self, FALSE);
|
||||
|
||||
payload = (NML3ConfigNotifyPayload){
|
||||
.platform_change_on_idle =
|
||||
{
|
||||
.obj_type_flags = obj_type_flags,
|
||||
},
|
||||
notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE;
|
||||
notify_data.platform_change_on_idle = (typeof(notify_data.platform_change_on_idle)){
|
||||
.obj_type_flags = obj_type_flags,
|
||||
};
|
||||
_nm_l3cfg_emit_signal_notify(self, NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, &payload);
|
||||
_nm_l3cfg_emit_signal_notify(self, ¬ify_data);
|
||||
|
||||
_l3_acd_data_notify_acd_completed_all(self);
|
||||
|
||||
|
|
@ -667,9 +700,23 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self,
|
|||
NMPlatformSignalChangeType change_type,
|
||||
const NMPObject * obj)
|
||||
{
|
||||
NML3ConfigNotifyData notify_data;
|
||||
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_LINK:
|
||||
{
|
||||
const NMPObject *plobj;
|
||||
|
||||
plobj = (change_type != NM_PLATFORM_SIGNAL_REMOVED) ? obj : NULL;
|
||||
nm_assert(plobj == nm_platform_link_get_obj(self->priv.platform, self->priv.ifindex, TRUE));
|
||||
nmp_object_ref_set(&self->priv.plobj_next, plobj);
|
||||
break;
|
||||
}
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
_l3_acd_ipv4_addresses_on_link_update(self,
|
||||
NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address,
|
||||
|
|
@ -682,6 +729,15 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE;
|
||||
notify_data.platform_change = (typeof(notify_data.platform_change)){
|
||||
.obj = obj,
|
||||
.change_type = change_type,
|
||||
};
|
||||
_nm_l3cfg_emit_signal_notify(self, ¬ify_data);
|
||||
|
||||
nm_assert(NMP_OBJECT_IS_VALID(obj));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -920,18 +976,6 @@ _acd_data_find_track(const AcdData * acd_data,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_l3_acd_platform_commit_acd_update(NML3Cfg *self)
|
||||
{
|
||||
/* The idea with NML3Cfg is that multiple users (NMDevice/NMVpnConnection) share one layer 3 configuration
|
||||
* and push their (portion of) IP configuration to it. That implies, that any user may issue nm_l3cfg_platform_commit()
|
||||
* at any time, in order to say that a new configuration is ready.
|
||||
*
|
||||
* This makes the mechanism also suitable for internally triggering a commit when ACD completes. */
|
||||
_LOGT("acd: acd update now");
|
||||
nm_l3cfg_platform_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_acd_has_valid_link(const NMPObject *obj,
|
||||
const guint8 ** out_addr_bin,
|
||||
|
|
@ -1035,9 +1079,9 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data)
|
|||
_LOGW("IPv4 address collision detection sees conflict on interface %i%s%s%s for "
|
||||
"address %s from host %s",
|
||||
self->priv.ifindex,
|
||||
NM_PRINT_FMT_QUOTED(self->priv.pllink,
|
||||
NM_PRINT_FMT_QUOTED(self->priv.plobj,
|
||||
" (",
|
||||
NMP_OBJECT_CAST_LINK(self->priv.pllink)->name,
|
||||
NMP_OBJECT_CAST_LINK(self->priv.plobj)->name,
|
||||
")",
|
||||
""),
|
||||
addr_str ?: _nm_utils_inet4_ntop(acd_data->addr, sbuf_addr),
|
||||
|
|
@ -1084,8 +1128,7 @@ _l3_acd_nacd_instance_ensure_retry_cb(gpointer user_data)
|
|||
nm_clear_g_source_inst(&self->priv.p->nacd_instance_ensure_retry);
|
||||
|
||||
_l3_changed_configs_set_dirty(self);
|
||||
_l3_acd_platform_commit_acd_update(self);
|
||||
|
||||
nm_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
|
@ -1106,12 +1149,8 @@ _l3_acd_nacd_instance_reset(NML3Cfg *self, NMTernary start_timer, gboolean acd_d
|
|||
|
||||
switch (start_timer) {
|
||||
case NM_TERNARY_FALSE:
|
||||
self->priv.p->nacd_instance_ensure_retry =
|
||||
nm_g_idle_source_new(G_PRIORITY_DEFAULT,
|
||||
_l3_acd_nacd_instance_ensure_retry_cb,
|
||||
self,
|
||||
NULL);
|
||||
g_source_attach(self->priv.p->nacd_instance_ensure_retry, NULL);
|
||||
_l3_changed_configs_set_dirty(self);
|
||||
nm_l3cfg_commit_on_idle_schedule(self);
|
||||
break;
|
||||
case NM_TERNARY_TRUE:
|
||||
self->priv.p->nacd_instance_ensure_retry =
|
||||
|
|
@ -1161,7 +1200,7 @@ again:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
valid = _acd_has_valid_link(self->priv.pllink, &addr_bin, &acd_not_supported);
|
||||
valid = _acd_has_valid_link(self->priv.plobj, &addr_bin, &acd_not_supported);
|
||||
if (!valid)
|
||||
goto failed_create_acd;
|
||||
|
||||
|
|
@ -1383,20 +1422,6 @@ _l3_acd_data_add_all(NML3Cfg *self, const L3ConfigData *const *infos, guint info
|
|||
_l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_INIT, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_l3_acd_ready_on_idle_cb(gpointer user_data)
|
||||
{
|
||||
NML3Cfg *self = user_data;
|
||||
|
||||
nm_clear_g_source_inst(&self->priv.p->acd_ready_on_idle_source);
|
||||
|
||||
_LOGT("acd: handle ACD changes on idle");
|
||||
|
||||
_l3_acd_platform_commit_acd_update(self);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_l3_acd_data_timeout_cb(gpointer user_data)
|
||||
{
|
||||
|
|
@ -1502,7 +1527,7 @@ _l3_acd_data_notify_acd_completed(NML3Cfg *self, AcdData *acd_data, gboolean for
|
|||
{
|
||||
gs_free NML3ConfigNotifyPayloadAcdFailedSource *sources_free = NULL;
|
||||
NML3ConfigNotifyPayloadAcdFailedSource * sources = NULL;
|
||||
NML3ConfigNotifyPayload payload;
|
||||
NML3ConfigNotifyData notify_data;
|
||||
AcdTrackData * acd_track;
|
||||
guint i, n;
|
||||
NMTernary acd_failed_notified_selector;
|
||||
|
|
@ -1547,17 +1572,14 @@ _l3_acd_data_notify_acd_completed(NML3Cfg *self, AcdData *acd_data, gboolean for
|
|||
}
|
||||
nm_assert(i == n);
|
||||
|
||||
payload = (NML3ConfigNotifyPayload){
|
||||
.acd_completed =
|
||||
{
|
||||
.addr = acd_data->addr,
|
||||
.probe_result = acd_data->probe_result,
|
||||
.sources_len = n,
|
||||
.sources = sources,
|
||||
},
|
||||
notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED;
|
||||
notify_data.acd_completed = (typeof(notify_data.acd_completed)){
|
||||
.addr = acd_data->addr,
|
||||
.probe_result = acd_data->probe_result,
|
||||
.sources_len = n,
|
||||
.sources = sources,
|
||||
};
|
||||
|
||||
_nm_l3cfg_emit_signal_notify(self, NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED, &payload);
|
||||
_nm_l3cfg_emit_signal_notify(self, ¬ify_data);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
nmp_object_unref(sources[i].obj);
|
||||
|
|
@ -2131,13 +2153,9 @@ handle_probe_done:
|
|||
/* probing just completed. Schedule handling the change. */
|
||||
_LOGT_acd(acd_data, "state: acd probe succeed");
|
||||
_l3_acd_data_notify_acd_completed_queue(self, acd_data);
|
||||
if (!self->priv.p->acd_ready_on_idle_source) {
|
||||
if (state_change_mode != ACD_STATE_CHANGE_MODE_POST_COMMIT)
|
||||
_l3_changed_configs_set_dirty(self);
|
||||
self->priv.p->acd_ready_on_idle_source =
|
||||
nm_g_idle_source_new(G_PRIORITY_DEFAULT, _l3_acd_ready_on_idle_cb, self, NULL);
|
||||
g_source_attach(self->priv.p->acd_ready_on_idle_source, NULL);
|
||||
}
|
||||
if (state_change_mode != ACD_STATE_CHANGE_MODE_POST_COMMIT)
|
||||
_l3_changed_configs_set_dirty(self);
|
||||
nm_l3cfg_commit_on_idle_schedule(self);
|
||||
}
|
||||
|
||||
if (!acd_data->nacd_probe) {
|
||||
|
|
@ -2213,6 +2231,33 @@ _l3_acd_data_process_changes(NML3Cfg *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_l3_commit_on_idle_cb(gpointer user_data)
|
||||
{
|
||||
NML3Cfg *self = user_data;
|
||||
|
||||
nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source);
|
||||
|
||||
_LOGT("platform commit on idle");
|
||||
_l3_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self)
|
||||
{
|
||||
nm_assert(NM_IS_L3CFG(self));
|
||||
|
||||
if (self->priv.p->commit_on_idle_source)
|
||||
return;
|
||||
|
||||
self->priv.p->commit_on_idle_source =
|
||||
nm_g_idle_source_new(G_PRIORITY_DEFAULT, _l3_commit_on_idle_cb, self, NULL);
|
||||
g_source_attach(self->priv.p->commit_on_idle_source, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _l3_config_datas_at(l3_config_datas, idx) \
|
||||
(&g_array_index((l3_config_datas), L3ConfigData, (idx)))
|
||||
|
||||
|
|
@ -2342,6 +2387,10 @@ nm_l3cfg_add_config(NML3Cfg * self,
|
|||
gboolean replace_same_tag,
|
||||
const NML3ConfigData *l3cd,
|
||||
int priority,
|
||||
guint32 default_route_table_4,
|
||||
guint32 default_route_table_6,
|
||||
guint32 default_route_metric_4,
|
||||
guint32 default_route_metric_6,
|
||||
guint32 default_route_penalty_4,
|
||||
guint32 default_route_penalty_6,
|
||||
guint32 acd_timeout_msec,
|
||||
|
|
@ -2356,6 +2405,13 @@ nm_l3cfg_add_config(NML3Cfg * self,
|
|||
nm_assert(l3cd);
|
||||
nm_assert(nm_l3_config_data_get_ifindex(l3cd) == self->priv.ifindex);
|
||||
|
||||
nm_assert(default_route_metric_6 != 0u); /* IPv6 default route metric cannot be zero. */
|
||||
|
||||
if (default_route_table_4 == 0u)
|
||||
default_route_table_4 = RT_TABLE_MAIN;
|
||||
if (default_route_table_6 == 0u)
|
||||
default_route_table_6 = RT_TABLE_MAIN;
|
||||
|
||||
if (!self->priv.p->l3_config_datas) {
|
||||
self->priv.p->l3_config_datas = g_array_new(FALSE, FALSE, sizeof(L3ConfigData));
|
||||
g_object_ref(self);
|
||||
|
|
@ -2396,6 +2452,10 @@ nm_l3cfg_add_config(NML3Cfg * self,
|
|||
.tag = tag,
|
||||
.l3cd = nm_l3_config_data_ref_and_seal(l3cd),
|
||||
.merge_flags = merge_flags,
|
||||
.default_route_table_4 = default_route_table_4,
|
||||
.default_route_table_6 = default_route_table_6,
|
||||
.default_route_metric_4 = default_route_metric_4,
|
||||
.default_route_metric_6 = default_route_metric_6,
|
||||
.default_route_penalty_4 = default_route_penalty_4,
|
||||
.default_route_penalty_6 = default_route_penalty_6,
|
||||
.acd_timeout_msec = acd_timeout_msec,
|
||||
|
|
@ -2417,6 +2477,22 @@ nm_l3cfg_add_config(NML3Cfg * self,
|
|||
l3_config_data->merge_flags = merge_flags;
|
||||
changed = TRUE;
|
||||
}
|
||||
if (l3_config_data->default_route_table_4 != default_route_table_4) {
|
||||
l3_config_data->default_route_table_4 = default_route_table_4;
|
||||
changed = TRUE;
|
||||
}
|
||||
if (l3_config_data->default_route_table_6 != default_route_table_6) {
|
||||
l3_config_data->default_route_table_6 = default_route_table_6;
|
||||
changed = TRUE;
|
||||
}
|
||||
if (l3_config_data->default_route_metric_4 != default_route_metric_4) {
|
||||
l3_config_data->default_route_metric_4 = default_route_metric_4;
|
||||
changed = TRUE;
|
||||
}
|
||||
if (l3_config_data->default_route_metric_6 != default_route_metric_6) {
|
||||
l3_config_data->default_route_metric_6 = default_route_metric_6;
|
||||
changed = TRUE;
|
||||
}
|
||||
if (l3_config_data->default_route_penalty_4 != default_route_penalty_4) {
|
||||
l3_config_data->default_route_penalty_4 = default_route_penalty_4;
|
||||
changed = TRUE;
|
||||
|
|
@ -2569,11 +2645,18 @@ _l3cfg_update_combined_config(NML3Cfg * self,
|
|||
self->priv.ifindex);
|
||||
|
||||
for (i = 0; i < l3_config_datas_len; i++) {
|
||||
hook_data.tag = l3_config_datas_sorted[i]->tag;
|
||||
const L3ConfigData *l3cd_data = l3_config_datas_sorted[i];
|
||||
|
||||
if (NM_FLAGS_HAS(l3cd_data->merge_flags, NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD))
|
||||
continue;
|
||||
|
||||
hook_data.tag = l3cd_data->tag;
|
||||
nm_l3_config_data_merge(l3cd,
|
||||
l3_config_datas_sorted[i]->l3cd,
|
||||
l3_config_datas_sorted[i]->merge_flags,
|
||||
l3_config_datas_sorted[i]->default_route_penalty_x,
|
||||
l3cd_data->l3cd,
|
||||
l3cd_data->merge_flags,
|
||||
l3cd_data->default_route_table_x,
|
||||
l3cd_data->default_route_metric_x,
|
||||
l3cd_data->default_route_penalty_x,
|
||||
_l3_hook_add_addr_cb,
|
||||
&hook_data);
|
||||
}
|
||||
|
|
@ -2666,11 +2749,10 @@ _routes_temporary_not_available_timeout(gpointer user_data)
|
|||
|
||||
if (any_expired) {
|
||||
/* a route expired. We emit a signal, but we don't schedule it again. That will
|
||||
* only happen if the user calls nm_l3cfg_platform_commit() again. */
|
||||
_nm_l3cfg_emit_signal_notify(
|
||||
* only happen if the user calls nm_l3cfg_commit() again. */
|
||||
_nm_l3cfg_emit_signal_notify_simple(
|
||||
self,
|
||||
NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED,
|
||||
NULL);
|
||||
NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
|
@ -2792,10 +2874,7 @@ out_prune:
|
|||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_platform_commit(NML3Cfg * self,
|
||||
int addr_family,
|
||||
NML3CfgCommitType commit_type,
|
||||
gboolean * out_final_failure_for_temporary_not_available)
|
||||
_l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type)
|
||||
{
|
||||
const gboolean IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
|
||||
|
|
@ -2920,19 +2999,19 @@ _platform_commit(NML3Cfg * self,
|
|||
routes_temporary_not_available_arr))
|
||||
final_failure_for_temporary_not_available = TRUE;
|
||||
|
||||
if (final_failure_for_temporary_not_available)
|
||||
NM_SET_OUT(out_final_failure_for_temporary_not_available, TRUE);
|
||||
/* FIXME(l3cfg) */
|
||||
(void) final_failure_for_temporary_not_available;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_l3cfg_platform_commit(NML3Cfg *self, NML3CfgCommitType commit_type)
|
||||
static void
|
||||
_l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle)
|
||||
{
|
||||
gboolean commit_type_detected = FALSE;
|
||||
gboolean success = TRUE;
|
||||
char sbuf_ct[30];
|
||||
|
||||
g_return_val_if_fail(NM_IS_L3CFG(self), FALSE);
|
||||
g_return_if_fail(NM_IS_L3CFG(self));
|
||||
nm_assert(NM_IN_SET(commit_type,
|
||||
NM_L3_CFG_COMMIT_TYPE_NONE,
|
||||
NM_L3_CFG_COMMIT_TYPE_AUTO,
|
||||
|
|
@ -2964,30 +3043,33 @@ nm_l3cfg_platform_commit(NML3Cfg *self, NML3CfgCommitType commit_type)
|
|||
break;
|
||||
}
|
||||
|
||||
_LOGT("platform-commit %s%s",
|
||||
_LOGT("platform-commit %s%s%s",
|
||||
_l3_cfg_commit_type_to_string(commit_type, sbuf_ct, sizeof(sbuf_ct)),
|
||||
commit_type_detected ? " (auto)" : "");
|
||||
commit_type_detected ? " (auto)" : "",
|
||||
is_idle ? " (idle handler)" : "");
|
||||
|
||||
if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE)
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
nm_clear_g_source_inst(&self->priv.p->acd_ready_on_idle_source);
|
||||
nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source);
|
||||
|
||||
if (commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY)
|
||||
_l3cfg_externally_removed_objs_drop(self);
|
||||
|
||||
/* FIXME(l3cfg): handle items currently not configurable in kernel. */
|
||||
|
||||
if (!_platform_commit(self, AF_INET, commit_type, NULL))
|
||||
success = FALSE;
|
||||
if (!_platform_commit(self, AF_INET6, commit_type, NULL))
|
||||
success = FALSE;
|
||||
_l3_commit_one(self, AF_INET, commit_type);
|
||||
_l3_commit_one(self, AF_INET6, commit_type);
|
||||
|
||||
_l3_acd_data_process_changes(self);
|
||||
|
||||
_nm_l3cfg_emit_signal_notify(self, NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, NULL);
|
||||
_nm_l3cfg_emit_signal_notify_simple(self, NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT);
|
||||
}
|
||||
|
||||
return success;
|
||||
void
|
||||
nm_l3cfg_commit(NML3Cfg *self, NML3CfgCommitType commit_type)
|
||||
{
|
||||
_l3_commit(self, commit_type, FALSE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -3015,7 +3097,7 @@ nm_l3cfg_commit_type_get(NML3Cfg *self)
|
|||
* NML3Cfg needs to know whether it is in charge of an interface (and how "much").
|
||||
* By default, it is not in charge, but various users can register themself with
|
||||
* a certain @commit_type. The "higher" commit type is the used one when calling
|
||||
* nm_l3cfg_platform_commit() with %NM_L3_CFG_COMMIT_TYPE_AUTO.
|
||||
* nm_l3cfg_commit() with %NM_L3_CFG_COMMIT_TYPE_AUTO.
|
||||
*
|
||||
* Returns: a handle tracking the registration, or %NULL of @commit_type
|
||||
* is %NM_L3_CFG_COMMIT_TYPE_NONE.
|
||||
|
|
@ -3231,7 +3313,7 @@ finalize(GObject *object)
|
|||
|
||||
nm_assert(c_list_is_empty(&self->priv.p->commit_type_lst_head));
|
||||
|
||||
nm_clear_g_source_inst(&self->priv.p->acd_ready_on_idle_source);
|
||||
nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source);
|
||||
|
||||
nm_assert(nm_g_array_len(self->priv.p->property_emit_list) == 0u);
|
||||
|
||||
|
|
@ -3257,7 +3339,8 @@ finalize(GObject *object)
|
|||
nm_clear_l3cd(&self->priv.p->combined_l3cd_merged);
|
||||
nm_clear_l3cd(&self->priv.p->combined_l3cd_commited);
|
||||
|
||||
nm_clear_pointer(&self->priv.pllink, nmp_object_unref);
|
||||
nm_clear_pointer(&self->priv.plobj, nmp_object_unref);
|
||||
nm_clear_pointer(&self->priv.plobj_next, nmp_object_unref);
|
||||
|
||||
nm_clear_pointer(&self->priv.p->acd_ipv4_addresses_on_link, g_hash_table_unref);
|
||||
|
||||
|
|
@ -3300,9 +3383,8 @@ nm_l3cfg_class_init(NML3CfgClass *klass)
|
|||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_INT /* NML3ConfigNotifyType */,
|
||||
G_TYPE_POINTER /* (const NML3ConfigNotifyPayload *) */);
|
||||
1,
|
||||
G_TYPE_POINTER /* (const NML3ConfigNotifyData *) */);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -42,6 +48,7 @@ typedef struct {
|
|||
} NML3ConfigNotifyPayloadAcdFailedSource;
|
||||
|
||||
typedef struct {
|
||||
NML3ConfigNotifyType notify_type;
|
||||
union {
|
||||
struct {
|
||||
in_addr_t addr;
|
||||
|
|
@ -50,11 +57,16 @@ 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;
|
||||
};
|
||||
} NML3ConfigNotifyPayload;
|
||||
} NML3ConfigNotifyData;
|
||||
|
||||
struct _NML3CfgPrivate;
|
||||
|
||||
|
|
@ -64,7 +76,8 @@ struct _NML3Cfg {
|
|||
struct _NML3CfgPrivate *p;
|
||||
NMNetns * netns;
|
||||
NMPlatform * platform;
|
||||
const NMPObject * pllink;
|
||||
const NMPObject * plobj;
|
||||
const NMPObject * plobj_next;
|
||||
int ifindex;
|
||||
bool changed_configs : 1;
|
||||
} priv;
|
||||
|
|
@ -86,6 +99,18 @@ void _nm_l3cfg_notify_platform_change(NML3Cfg * self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMDedupMultiIndex;
|
||||
|
||||
struct _NMDedupMultiIndex *nm_netns_get_multi_idx(NMNetns *self);
|
||||
|
||||
static inline struct _NMDedupMultiIndex *
|
||||
nm_l3cfg_get_multi_idx(const NML3Cfg *self)
|
||||
{
|
||||
return nm_netns_get_multi_idx(self->priv.netns);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_l3cfg_get_ifindex(const NML3Cfg *self)
|
||||
{
|
||||
|
|
@ -94,34 +119,36 @@ nm_l3cfg_get_ifindex(const NML3Cfg *self)
|
|||
return self->priv.ifindex;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nm_l3cfg_get_ifname(const NML3Cfg *self)
|
||||
{
|
||||
nm_assert(NM_IS_L3CFG(self));
|
||||
|
||||
return nmp_object_link_get_ifname(self->priv.pllink);
|
||||
}
|
||||
|
||||
static inline const NMPObject *
|
||||
nm_l3cfg_get_plobj(const NML3Cfg *self)
|
||||
nm_l3cfg_get_plobj(const NML3Cfg *self, gboolean get_next)
|
||||
{
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
nm_assert(NM_IS_L3CFG(self));
|
||||
|
||||
return self->priv.pllink;
|
||||
if (get_next) {
|
||||
/* This is the instance that we just got reported in the last signal from
|
||||
* the platform cache. It's probably exactly the same as if you would look
|
||||
* into the platform cache.
|
||||
*
|
||||
* On the other hand, we pick up changes only on an idle handler. So the last
|
||||
* decisions were not made based on this, but instead of "plobj". */
|
||||
return self->priv.plobj_next;
|
||||
}
|
||||
return self->priv.plobj;
|
||||
}
|
||||
|
||||
static inline const NMPlatformLink *
|
||||
nm_l3cfg_get_pllink(const NML3Cfg *self)
|
||||
nm_l3cfg_get_pllink(const NML3Cfg *self, gboolean get_next)
|
||||
{
|
||||
if (!self)
|
||||
return NULL;
|
||||
return NMP_OBJECT_CAST_LINK(nm_l3cfg_get_plobj(self, get_next));
|
||||
}
|
||||
|
||||
nm_assert(NM_IS_L3CFG(self));
|
||||
|
||||
return NMP_OBJECT_CAST_LINK(self->priv.pllink);
|
||||
static inline const char *
|
||||
nm_l3cfg_get_ifname(const NML3Cfg *self, gboolean get_next)
|
||||
{
|
||||
return nmp_object_link_get_ifname(nm_l3cfg_get_plobj(self, get_next));
|
||||
}
|
||||
|
||||
static inline NMNetns *
|
||||
|
|
@ -144,9 +171,7 @@ gboolean nm_l3cfg_get_acd_is_pending(NML3Cfg *self);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void _nm_l3cfg_emit_signal_notify(NML3Cfg * self,
|
||||
NML3ConfigNotifyType notify_type,
|
||||
const NML3ConfigNotifyPayload *pay_load);
|
||||
void _nm_l3cfg_emit_signal_notify(NML3Cfg *self, const NML3ConfigNotifyData *notify_data);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -174,6 +199,10 @@ gboolean nm_l3cfg_add_config(NML3Cfg * self,
|
|||
gboolean replace_same_tag,
|
||||
const NML3ConfigData *l3cd,
|
||||
int priority,
|
||||
guint32 default_route_table_4,
|
||||
guint32 default_route_table_6,
|
||||
guint32 default_route_metric_4,
|
||||
guint32 default_route_metric_6,
|
||||
guint32 default_route_penalty_4,
|
||||
guint32 default_route_penalty_6,
|
||||
guint32 acd_timeout_msec,
|
||||
|
|
@ -215,7 +244,9 @@ typedef enum _nm_packed {
|
|||
|
||||
} NML3CfgCommitType;
|
||||
|
||||
gboolean nm_l3cfg_platform_commit(NML3Cfg *self, NML3CfgCommitType commit_type);
|
||||
void nm_l3cfg_commit(NML3Cfg *self, NML3CfgCommitType commit_type);
|
||||
|
||||
void nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -4704,7 +4704,10 @@ _nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj)
|
|||
NLA_PUT(msg, RTA_SRC, addr_len, &obj->ip6_route.src);
|
||||
}
|
||||
|
||||
NLA_PUT_U32(msg, RTA_PRIORITY, obj->ip_route.metric);
|
||||
NLA_PUT_U32(msg,
|
||||
RTA_PRIORITY,
|
||||
is_v4 ? nm_platform_ip4_route_get_effective_metric(&obj->ip4_route)
|
||||
: nm_platform_ip6_route_get_effective_metric(&obj->ip6_route));
|
||||
|
||||
if (table > 0xFF)
|
||||
NLA_PUT_U32(msg, RTA_TABLE, table);
|
||||
|
|
|
|||
|
|
@ -3437,7 +3437,8 @@ nm_platform_lookup_predicate_routes_main(const NMPObject *obj, gpointer user_dat
|
|||
{
|
||||
nm_assert(
|
||||
NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
return nm_platform_route_table_is_main(obj->ip_route.table_coerced);
|
||||
return nm_platform_route_table_is_main(
|
||||
nm_platform_ip_route_get_effective_table(&obj->ip_route));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -3446,7 +3447,7 @@ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel(const NMPObject *obj
|
|||
{
|
||||
nm_assert(
|
||||
NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
return nm_platform_route_table_is_main(obj->ip_route.table_coerced)
|
||||
return nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&obj->ip_route))
|
||||
&& obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
|
||||
}
|
||||
|
||||
|
|
@ -4395,11 +4396,12 @@ nm_platform_ip_route_get_prune_list(NMPlatform * self,
|
|||
const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) {
|
||||
if (nm_platform_route_table_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced, TRUE)
|
||||
if (nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj))
|
||||
== RT_TABLE_LOCAL)
|
||||
continue;
|
||||
} else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) {
|
||||
if (!nm_platform_route_table_is_main(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced))
|
||||
if (!nm_platform_route_table_is_main(
|
||||
nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj))))
|
||||
continue;
|
||||
} else
|
||||
nm_assert(route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
|
|
@ -4488,7 +4490,9 @@ nm_platform_ip_route_sync(NMPlatform *self,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!IS_IPv4 && NMP_OBJECT_CAST_IP6_ROUTE(conf_o)->metric == 0) {
|
||||
if (!IS_IPv4
|
||||
&& nm_platform_ip6_route_get_effective_metric(NMP_OBJECT_CAST_IP6_ROUTE(conf_o))
|
||||
== 0) {
|
||||
/* User space cannot add routes with metric 0. However, kernel can, and we might track such
|
||||
* routes in @route as they are present external. Skip them silently. */
|
||||
continue;
|
||||
|
|
@ -4582,29 +4586,33 @@ sync_route_add:
|
|||
if (vt->is_ip4) {
|
||||
const NMPlatformIP4Route *rt = NMP_OBJECT_CAST_IP4_ROUTE(conf_o);
|
||||
|
||||
nmp_object_stackinit(&oo,
|
||||
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
&((NMPlatformIP4Route){
|
||||
.ifindex = rt->ifindex,
|
||||
.network = rt->gateway,
|
||||
.plen = 32,
|
||||
.metric = rt->metric,
|
||||
.rt_source = rt->rt_source,
|
||||
.table_coerced = rt->table_coerced,
|
||||
}));
|
||||
nmp_object_stackinit(
|
||||
&oo,
|
||||
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
&((NMPlatformIP4Route){
|
||||
.ifindex = rt->ifindex,
|
||||
.network = rt->gateway,
|
||||
.plen = 32,
|
||||
.metric = nm_platform_ip4_route_get_effective_metric(rt),
|
||||
.rt_source = rt->rt_source,
|
||||
.table_coerced = nm_platform_ip_route_get_effective_table(
|
||||
NM_PLATFORM_IP_ROUTE_CAST(rt)),
|
||||
}));
|
||||
} else {
|
||||
const NMPlatformIP6Route *rt = NMP_OBJECT_CAST_IP6_ROUTE(conf_o);
|
||||
|
||||
nmp_object_stackinit(&oo,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
&((NMPlatformIP6Route){
|
||||
.ifindex = rt->ifindex,
|
||||
.network = rt->gateway,
|
||||
.plen = 128,
|
||||
.metric = rt->metric,
|
||||
.rt_source = rt->rt_source,
|
||||
.table_coerced = rt->table_coerced,
|
||||
}));
|
||||
nmp_object_stackinit(
|
||||
&oo,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
&((NMPlatformIP6Route){
|
||||
.ifindex = rt->ifindex,
|
||||
.network = rt->gateway,
|
||||
.plen = 128,
|
||||
.metric = nm_platform_ip6_route_get_effective_metric(rt),
|
||||
.rt_source = rt->rt_source,
|
||||
.table_coerced = nm_platform_ip_route_get_effective_table(
|
||||
NM_PLATFORM_IP_ROUTE_CAST(rt)),
|
||||
}));
|
||||
}
|
||||
|
||||
_LOG3D("route-sync: failure to add IPv%c route: %s: %s; try adding direct "
|
||||
|
|
@ -4760,21 +4768,25 @@ nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route)
|
|||
NMPlatformIP4Route *r4;
|
||||
NMPlatformIP6Route *r6;
|
||||
|
||||
route->table_coerced =
|
||||
nm_platform_route_table_coerce(nm_platform_ip_route_get_effective_table(route));
|
||||
route->table_any = FALSE;
|
||||
|
||||
route->rt_source = nmp_utils_ip_config_source_round_trip_rtprot(route->rt_source);
|
||||
|
||||
switch (addr_family) {
|
||||
case AF_INET:
|
||||
r4 = (NMPlatformIP4Route *) route;
|
||||
r4->table_coerced = nm_platform_route_table_coerce(
|
||||
nm_platform_route_table_uncoerce(r4->table_coerced, TRUE));
|
||||
r4->network = nm_utils_ip4_address_clear_host_address(r4->network, r4->plen);
|
||||
r4->rt_source = nmp_utils_ip_config_source_round_trip_rtprot(r4->rt_source);
|
||||
r4->scope_inv = _ip_route_scope_inv_get_normalized(r4);
|
||||
route->metric = nm_platform_ip4_route_get_effective_metric(r4);
|
||||
route->metric_any = FALSE;
|
||||
r4->network = nm_utils_ip4_address_clear_host_address(r4->network, r4->plen);
|
||||
r4->scope_inv = _ip_route_scope_inv_get_normalized(r4);
|
||||
break;
|
||||
case AF_INET6:
|
||||
r6 = (NMPlatformIP6Route *) route;
|
||||
r6->table_coerced = nm_platform_route_table_coerce(
|
||||
nm_platform_route_table_uncoerce(r6->table_coerced, TRUE));
|
||||
route->metric = nm_platform_ip6_route_get_effective_metric(r6);
|
||||
route->metric_any = FALSE;
|
||||
nm_utils_ip6_address_clear_host_address(&r6->network, &r6->network, r6->plen);
|
||||
r6->rt_source = nmp_utils_ip_config_source_round_trip_rtprot(r6->rt_source),
|
||||
nm_utils_ip6_address_clear_host_address(&r6->src, &r6->src, r6->src_plen);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -6453,6 +6465,7 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
|
|||
char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
|
||||
char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN];
|
||||
char str_type[30];
|
||||
char str_metric[30];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null(route, &buf, &len))
|
||||
return buf;
|
||||
|
|
@ -6470,30 +6483,33 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
|
|||
"%s/%d"
|
||||
" via %s"
|
||||
"%s"
|
||||
" metric %" G_GUINT32_FORMAT " mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */
|
||||
"%s" /* rtm_flags */
|
||||
"%s%s" /* scope */
|
||||
"%s%s" /* pref-src */
|
||||
"%s" /* tos */
|
||||
"%s" /* window */
|
||||
"%s" /* cwnd */
|
||||
"%s" /* initcwnd */
|
||||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
" metric %s"
|
||||
" mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */
|
||||
"%s" /* rtm_flags */
|
||||
"%s%s" /* scope */
|
||||
"%s%s" /* pref-src */
|
||||
"%s" /* tos */
|
||||
"%s" /* window */
|
||||
"%s" /* cwnd */
|
||||
"%s" /* initcwnd */
|
||||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"",
|
||||
nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced),
|
||||
str_type,
|
||||
sizeof(str_type)),
|
||||
route->table_coerced
|
||||
? nm_sprintf_buf(str_table,
|
||||
"table %u ",
|
||||
nm_platform_route_table_uncoerce(route->table_coerced, FALSE))
|
||||
: "",
|
||||
route->table_any
|
||||
? "table ?? "
|
||||
: (route->table_coerced
|
||||
? nm_sprintf_buf(str_table,
|
||||
"table %u ",
|
||||
nm_platform_route_table_uncoerce(route->table_coerced, FALSE))
|
||||
: ""),
|
||||
s_network,
|
||||
route->plen,
|
||||
s_gateway,
|
||||
str_dev,
|
||||
route->metric,
|
||||
route->metric_any ? "??" : nm_sprintf_buf(str_metric, "%u", route->metric),
|
||||
route->mss,
|
||||
nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)),
|
||||
_rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags),
|
||||
|
|
@ -6568,6 +6584,7 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
|
|||
char str_initrwnd[32];
|
||||
char str_mtu[32];
|
||||
char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN];
|
||||
char str_metric[30];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null(route, &buf, &len))
|
||||
return buf;
|
||||
|
|
@ -6582,81 +6599,84 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
|
|||
|
||||
_to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev));
|
||||
|
||||
g_snprintf(buf,
|
||||
len,
|
||||
"type %s " /* type */
|
||||
"%s" /* table */
|
||||
"%s/%d"
|
||||
" via %s"
|
||||
"%s"
|
||||
" metric %" G_GUINT32_FORMAT " mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */
|
||||
"%s" /* source */
|
||||
"%s" /* rtm_flags */
|
||||
"%s%s" /* pref-src */
|
||||
"%s" /* window */
|
||||
"%s" /* cwnd */
|
||||
"%s" /* initcwnd */
|
||||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"%s" /* pref */
|
||||
"",
|
||||
nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced),
|
||||
str_type,
|
||||
sizeof(str_type)),
|
||||
route->table_coerced
|
||||
g_snprintf(
|
||||
buf,
|
||||
len,
|
||||
"type %s " /* type */
|
||||
"%s" /* table */
|
||||
"%s/%d"
|
||||
" via %s"
|
||||
"%s"
|
||||
" metric %s"
|
||||
" mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */
|
||||
"%s" /* source */
|
||||
"%s" /* rtm_flags */
|
||||
"%s%s" /* pref-src */
|
||||
"%s" /* window */
|
||||
"%s" /* cwnd */
|
||||
"%s" /* initcwnd */
|
||||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"%s" /* pref */
|
||||
"",
|
||||
nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced),
|
||||
str_type,
|
||||
sizeof(str_type)),
|
||||
route->table_any
|
||||
? "table ?? "
|
||||
: (route->table_coerced
|
||||
? nm_sprintf_buf(str_table,
|
||||
"table %u ",
|
||||
nm_platform_route_table_uncoerce(route->table_coerced, FALSE))
|
||||
: "",
|
||||
s_network,
|
||||
route->plen,
|
||||
s_gateway,
|
||||
str_dev,
|
||||
route->metric,
|
||||
route->mss,
|
||||
nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)),
|
||||
route->src_plen || !IN6_IS_ADDR_UNSPECIFIED(&route->src)
|
||||
? nm_sprintf_buf(s_src_all,
|
||||
" src %s/%u",
|
||||
_nm_utils_inet6_ntop(&route->src, s_src),
|
||||
(unsigned) route->src_plen)
|
||||
: "",
|
||||
_rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags),
|
||||
s_pref_src[0] ? " pref-src " : "",
|
||||
s_pref_src[0] ? s_pref_src : "",
|
||||
route->window || route->lock_window
|
||||
? nm_sprintf_buf(str_window,
|
||||
" window %s%" G_GUINT32_FORMAT,
|
||||
route->lock_window ? "lock " : "",
|
||||
route->window)
|
||||
: "",
|
||||
route->cwnd || route->lock_cwnd ? nm_sprintf_buf(str_cwnd,
|
||||
" cwnd %s%" G_GUINT32_FORMAT,
|
||||
route->lock_cwnd ? "lock " : "",
|
||||
route->cwnd)
|
||||
: "",
|
||||
route->initcwnd || route->lock_initcwnd
|
||||
? nm_sprintf_buf(str_initcwnd,
|
||||
" initcwnd %s%" G_GUINT32_FORMAT,
|
||||
route->lock_initcwnd ? "lock " : "",
|
||||
route->initcwnd)
|
||||
: "",
|
||||
route->initrwnd || route->lock_initrwnd
|
||||
? nm_sprintf_buf(str_initrwnd,
|
||||
" initrwnd %s%" G_GUINT32_FORMAT,
|
||||
route->lock_initrwnd ? "lock " : "",
|
||||
route->initrwnd)
|
||||
: "",
|
||||
route->mtu || route->lock_mtu ? nm_sprintf_buf(str_mtu,
|
||||
" mtu %s%" G_GUINT32_FORMAT,
|
||||
route->lock_mtu ? "lock " : "",
|
||||
route->mtu)
|
||||
: "",
|
||||
route->rt_pref ? nm_sprintf_buf(
|
||||
str_pref,
|
||||
" pref %s",
|
||||
nm_icmpv6_router_pref_to_string(route->rt_pref, str_pref2, sizeof(str_pref2)))
|
||||
: "");
|
||||
: ""),
|
||||
s_network,
|
||||
route->plen,
|
||||
s_gateway,
|
||||
str_dev,
|
||||
route->metric_any ? "??" : nm_sprintf_buf(str_metric, "%u", route->metric),
|
||||
route->mss,
|
||||
nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)),
|
||||
route->src_plen || !IN6_IS_ADDR_UNSPECIFIED(&route->src)
|
||||
? nm_sprintf_buf(s_src_all,
|
||||
" src %s/%u",
|
||||
_nm_utils_inet6_ntop(&route->src, s_src),
|
||||
(unsigned) route->src_plen)
|
||||
: "",
|
||||
_rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags),
|
||||
s_pref_src[0] ? " pref-src " : "",
|
||||
s_pref_src[0] ? s_pref_src : "",
|
||||
route->window || route->lock_window ? nm_sprintf_buf(str_window,
|
||||
" window %s%" G_GUINT32_FORMAT,
|
||||
route->lock_window ? "lock " : "",
|
||||
route->window)
|
||||
: "",
|
||||
route->cwnd || route->lock_cwnd ? nm_sprintf_buf(str_cwnd,
|
||||
" cwnd %s%" G_GUINT32_FORMAT,
|
||||
route->lock_cwnd ? "lock " : "",
|
||||
route->cwnd)
|
||||
: "",
|
||||
route->initcwnd || route->lock_initcwnd
|
||||
? nm_sprintf_buf(str_initcwnd,
|
||||
" initcwnd %s%" G_GUINT32_FORMAT,
|
||||
route->lock_initcwnd ? "lock " : "",
|
||||
route->initcwnd)
|
||||
: "",
|
||||
route->initrwnd || route->lock_initrwnd
|
||||
? nm_sprintf_buf(str_initrwnd,
|
||||
" initrwnd %s%" G_GUINT32_FORMAT,
|
||||
route->lock_initrwnd ? "lock " : "",
|
||||
route->initrwnd)
|
||||
: "",
|
||||
route->mtu || route->lock_mtu ? nm_sprintf_buf(str_mtu,
|
||||
" mtu %s%" G_GUINT32_FORMAT,
|
||||
route->lock_mtu ? "lock " : "",
|
||||
route->mtu)
|
||||
: "",
|
||||
route->rt_pref ? nm_sprintf_buf(
|
||||
str_pref,
|
||||
" pref %s",
|
||||
nm_icmpv6_router_pref_to_string(route->rt_pref, str_pref2, sizeof(str_pref2)))
|
||||
: "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
@ -7891,67 +7911,75 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
|
|||
{
|
||||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
nm_hash_update_vals(h,
|
||||
nm_platform_route_table_uncoerce(obj->table_coerced, TRUE),
|
||||
nm_utils_ip4_address_clear_host_address(obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->tos);
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)),
|
||||
nm_utils_ip4_address_clear_host_address(obj->network, obj->plen),
|
||||
obj->plen,
|
||||
nm_platform_ip4_route_get_effective_metric(obj),
|
||||
obj->tos,
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any));
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
nm_hash_update_vals(h,
|
||||
obj->type_coerced,
|
||||
nm_platform_route_table_uncoerce(obj->table_coerced, TRUE),
|
||||
nm_utils_ip4_address_clear_host_address(obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->tos,
|
||||
/* on top of WEAK_ID: */
|
||||
obj->ifindex,
|
||||
nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source),
|
||||
_ip_route_scope_inv_get_normalized(obj),
|
||||
obj->gateway,
|
||||
obj->mss,
|
||||
obj->pref_src,
|
||||
obj->window,
|
||||
obj->cwnd,
|
||||
obj->initcwnd,
|
||||
obj->initrwnd,
|
||||
obj->mtu,
|
||||
obj->r_rtm_flags & RTNH_F_ONLINK,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
obj->lock_initrwnd,
|
||||
obj->lock_mtu));
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
obj->type_coerced,
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)),
|
||||
nm_utils_ip4_address_clear_host_address(obj->network, obj->plen),
|
||||
obj->plen,
|
||||
nm_platform_ip4_route_get_effective_metric(obj),
|
||||
obj->tos,
|
||||
/* on top of WEAK_ID: */
|
||||
obj->ifindex,
|
||||
nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source),
|
||||
_ip_route_scope_inv_get_normalized(obj),
|
||||
obj->gateway,
|
||||
obj->mss,
|
||||
obj->pref_src,
|
||||
obj->window,
|
||||
obj->cwnd,
|
||||
obj->initcwnd,
|
||||
obj->initrwnd,
|
||||
obj->mtu,
|
||||
obj->r_rtm_flags & RTNH_F_ONLINK,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->metric_any,
|
||||
obj->table_any,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
obj->lock_initrwnd,
|
||||
obj->lock_mtu));
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
nm_hash_update_vals(h,
|
||||
obj->type_coerced,
|
||||
nm_platform_route_table_uncoerce(obj->table_coerced, TRUE),
|
||||
obj->ifindex,
|
||||
nm_utils_ip4_address_clear_host_address(obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->gateway,
|
||||
nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source),
|
||||
_ip_route_scope_inv_get_normalized(obj),
|
||||
obj->tos,
|
||||
obj->mss,
|
||||
obj->pref_src,
|
||||
obj->window,
|
||||
obj->cwnd,
|
||||
obj->initcwnd,
|
||||
obj->initrwnd,
|
||||
obj->mtu,
|
||||
obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK),
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
obj->lock_initrwnd,
|
||||
obj->lock_mtu));
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
obj->type_coerced,
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)),
|
||||
obj->ifindex,
|
||||
nm_utils_ip4_address_clear_host_address(obj->network, obj->plen),
|
||||
obj->plen,
|
||||
nm_platform_ip4_route_get_effective_metric(obj),
|
||||
obj->gateway,
|
||||
nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source),
|
||||
_ip_route_scope_inv_get_normalized(obj),
|
||||
obj->tos,
|
||||
obj->mss,
|
||||
obj->pref_src,
|
||||
obj->window,
|
||||
obj->cwnd,
|
||||
obj->initcwnd,
|
||||
obj->initrwnd,
|
||||
obj->mtu,
|
||||
obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK),
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->metric_any,
|
||||
obj->table_any,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
obj->lock_initrwnd,
|
||||
obj->lock_mtu));
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
nm_hash_update_vals(h,
|
||||
|
|
@ -7960,7 +7988,7 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
|
|||
obj->ifindex,
|
||||
obj->network,
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
nm_platform_ip4_route_get_effective_metric(obj),
|
||||
obj->gateway,
|
||||
obj->rt_source,
|
||||
obj->scope_inv,
|
||||
|
|
@ -7974,6 +8002,8 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
|
|||
obj->mtu,
|
||||
obj->r_rtm_flags,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->metric_any,
|
||||
obj->table_any,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
|
|
@ -7992,11 +8022,14 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a,
|
|||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
NM_CMP_DIRECT(nm_platform_route_table_uncoerce(a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce(b->table_coerced, TRUE));
|
||||
NM_CMP_FIELD_UNSAFE(a, b, table_any);
|
||||
NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)),
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b)));
|
||||
NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen));
|
||||
NM_CMP_FIELD(a, b, plen);
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, metric_any);
|
||||
if (!a->metric_any)
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD(a, b, tos);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
|
||||
NM_CMP_FIELD(a, b, ifindex);
|
||||
|
|
@ -8024,9 +8057,10 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a,
|
|||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
NM_CMP_FIELD(a, b, type_coerced);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, table_any);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
NM_CMP_DIRECT(nm_platform_route_table_uncoerce(a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce(b->table_coerced, TRUE));
|
||||
NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)),
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b)));
|
||||
} else
|
||||
NM_CMP_FIELD(a, b, table_coerced);
|
||||
NM_CMP_FIELD(a, b, ifindex);
|
||||
|
|
@ -8035,7 +8069,9 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a,
|
|||
else
|
||||
NM_CMP_FIELD(a, b, network);
|
||||
NM_CMP_FIELD(a, b, plen);
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, metric_any);
|
||||
if (!a->metric_any)
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD(a, b, gateway);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source),
|
||||
|
|
@ -8078,54 +8114,61 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
|
||||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
nm_hash_update_vals(h,
|
||||
nm_platform_route_table_uncoerce(obj->table_coerced, TRUE),
|
||||
*nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
*nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen);
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)),
|
||||
*nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
nm_platform_ip6_route_get_effective_metric(obj),
|
||||
*nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any));
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
nm_hash_update_vals(h,
|
||||
obj->type_coerced,
|
||||
nm_platform_route_table_uncoerce(obj->table_coerced, TRUE),
|
||||
*nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
*nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
/* on top of WEAK_ID: */
|
||||
obj->ifindex,
|
||||
obj->gateway);
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
obj->type_coerced,
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)),
|
||||
*nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
nm_platform_ip6_route_get_effective_metric(obj),
|
||||
*nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any),
|
||||
/* on top of WEAK_ID: */
|
||||
obj->ifindex,
|
||||
obj->gateway);
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
nm_hash_update_vals(h,
|
||||
obj->type_coerced,
|
||||
nm_platform_route_table_uncoerce(obj->table_coerced, TRUE),
|
||||
obj->ifindex,
|
||||
*nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->gateway,
|
||||
obj->pref_src,
|
||||
*nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source),
|
||||
obj->mss,
|
||||
obj->r_rtm_flags & RTM_F_CLONED,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
obj->lock_initrwnd,
|
||||
obj->lock_mtu),
|
||||
obj->window,
|
||||
obj->cwnd,
|
||||
obj->initcwnd,
|
||||
obj->initrwnd,
|
||||
obj->mtu,
|
||||
_route_pref_normalize(obj->rt_pref));
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
obj->type_coerced,
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)),
|
||||
obj->ifindex,
|
||||
*nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
nm_platform_ip6_route_get_effective_metric(obj),
|
||||
obj->gateway,
|
||||
obj->pref_src,
|
||||
*nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source),
|
||||
obj->mss,
|
||||
obj->r_rtm_flags & RTM_F_CLONED,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->metric_any,
|
||||
obj->table_any,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
obj->lock_initrwnd,
|
||||
obj->lock_mtu),
|
||||
obj->window,
|
||||
obj->cwnd,
|
||||
obj->initcwnd,
|
||||
obj->initrwnd,
|
||||
obj->mtu,
|
||||
_route_pref_normalize(obj->rt_pref));
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
nm_hash_update_vals(h,
|
||||
|
|
@ -8133,8 +8176,7 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
obj->table_coerced,
|
||||
obj->ifindex,
|
||||
obj->network,
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
nm_platform_ip6_route_get_effective_metric(obj),
|
||||
obj->gateway,
|
||||
obj->pref_src,
|
||||
obj->src,
|
||||
|
|
@ -8143,6 +8185,8 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
obj->mss,
|
||||
obj->r_rtm_flags,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->metric_any,
|
||||
obj->table_any,
|
||||
obj->lock_window,
|
||||
obj->lock_cwnd,
|
||||
obj->lock_initcwnd,
|
||||
|
|
@ -8167,11 +8211,14 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
|
|||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
NM_CMP_DIRECT(nm_platform_route_table_uncoerce(a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce(b->table_coerced, TRUE));
|
||||
NM_CMP_FIELD_UNSAFE(a, b, table_any);
|
||||
NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)),
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b)));
|
||||
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen));
|
||||
NM_CMP_FIELD(a, b, plen);
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, metric_any);
|
||||
if (!a->metric_any)
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen));
|
||||
NM_CMP_FIELD(a, b, src_plen);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
|
||||
|
|
@ -8183,9 +8230,10 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
|
|||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
NM_CMP_FIELD(a, b, type_coerced);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, table_any);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
NM_CMP_DIRECT(nm_platform_route_table_uncoerce(a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce(b->table_coerced, TRUE));
|
||||
NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)),
|
||||
nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b)));
|
||||
} else
|
||||
NM_CMP_FIELD(a, b, table_coerced);
|
||||
NM_CMP_FIELD(a, b, ifindex);
|
||||
|
|
@ -8194,7 +8242,9 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
|
|||
else
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, network);
|
||||
NM_CMP_FIELD(a, b, plen);
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, metric_any);
|
||||
if (!a->metric_any)
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, gateway);
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, pref_src);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
|
|
|
|||
|
|
@ -148,10 +148,17 @@ typedef enum {
|
|||
} NMPlatformRoutingRuleCmpType;
|
||||
|
||||
typedef struct {
|
||||
guint8 data[20 /* NM_UTILS_HWADDR_LEN_MAX */];
|
||||
union {
|
||||
guint8 data[20 /* NM_UTILS_HWADDR_LEN_MAX */];
|
||||
NMEtherAddr ether_addr;
|
||||
};
|
||||
guint8 len;
|
||||
} NMPLinkAddress;
|
||||
|
||||
/* assert that NMEtherAddr does not affect the alignment of NMPLinkAddress struct. */
|
||||
G_STATIC_ASSERT(_nm_alignof(NMEtherAddr) == 1);
|
||||
G_STATIC_ASSERT(_nm_alignof(NMPLinkAddress) == 1);
|
||||
|
||||
gconstpointer nmp_link_address_get(const NMPLinkAddress *addr, size_t *length);
|
||||
GBytes * nmp_link_address_get_as_bytes(const NMPLinkAddress *addr);
|
||||
|
||||
|
|
@ -390,22 +397,22 @@ typedef union {
|
|||
* Note that contrary to IPv6, you can add routes with metric 0 and it is even
|
||||
* the default.
|
||||
*/
|
||||
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 0
|
||||
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 ((guint32) 0u)
|
||||
|
||||
/* Default value for adding an IPv6 route. This is also what iproute2 does.
|
||||
* Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024).
|
||||
*
|
||||
* Note that kernel doesn't allow adding IPv6 routes with metric zero via netlink.
|
||||
* It however can itself add routes with metric zero. */
|
||||
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 1024
|
||||
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 ((guint32) 1024u)
|
||||
|
||||
/* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user
|
||||
* configures addresses. */
|
||||
#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE 0
|
||||
#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE ((guint32) 0u)
|
||||
|
||||
#define __NMPlatformIPRoute_COMMON \
|
||||
__NMPlatformObjWithIfindex_COMMON; \
|
||||
\
|
||||
#define __NMPlatformIPRoute_COMMON \
|
||||
__NMPlatformObjWithIfindex_COMMON; \
|
||||
\
|
||||
/* The NMIPConfigSource. For routes that we receive from cache this corresponds
|
||||
* to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values).
|
||||
* When adding a route, the source will be coerced to the protocol using
|
||||
|
|
@ -417,11 +424,11 @@ typedef union {
|
|||
*
|
||||
* When deleting an IPv4/IPv6 route, the rtm_protocol field must match (even
|
||||
* if it is not part of the primary key for IPv6) -- unless rtm_protocol is set
|
||||
* to zero, in which case the first matching route (with proto ignored) is deleted. */ \
|
||||
NMIPConfigSource rt_source; \
|
||||
\
|
||||
guint8 plen; \
|
||||
\
|
||||
* to zero, in which case the first matching route (with proto ignored) is deleted. */ \
|
||||
NMIPConfigSource rt_source; \
|
||||
\
|
||||
guint8 plen; \
|
||||
\
|
||||
/* RTA_METRICS:
|
||||
*
|
||||
* For IPv4 routes, these properties are part of their
|
||||
|
|
@ -432,15 +439,24 @@ typedef union {
|
|||
*
|
||||
* When deleting a route, kernel seems to ignore the RTA_METRICS properties.
|
||||
* That is a problem/bug for IPv4 because you cannot explicitly select which
|
||||
* route to delete. Kernel just picks the first. See rh#1475642. */ \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \
|
||||
bool lock_window : 1; \
|
||||
bool lock_cwnd : 1; \
|
||||
bool lock_initcwnd : 1; \
|
||||
bool lock_initrwnd : 1; \
|
||||
bool lock_mtu : 1; \
|
||||
\
|
||||
* route to delete. Kernel just picks the first. See rh#1475642. */ \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \
|
||||
bool lock_window : 1; \
|
||||
bool lock_cwnd : 1; \
|
||||
bool lock_initcwnd : 1; \
|
||||
bool lock_initrwnd : 1; \
|
||||
bool lock_mtu : 1; \
|
||||
\
|
||||
/* if TRUE, the "metric" field gets ignored and can be overridden with settings from
|
||||
* the device. This is to track routes that should be configured (e.g. from a DHCP
|
||||
* lease), but where the actual metric is determined by NMDevice. */ \
|
||||
bool metric_any : 1; \
|
||||
\
|
||||
/* like "metric_any", the table is determined by other layers of the code.
|
||||
* This field overrides "table_coerced" field. */ \
|
||||
bool table_any : 1; \
|
||||
\
|
||||
/* rtnh_flags
|
||||
*
|
||||
* Routes with rtm_flags RTM_F_CLONED are hidden by platform and
|
||||
|
|
@ -450,44 +466,44 @@ typedef union {
|
|||
* NOTE: currently we ignore all flags except RTM_F_CLONED
|
||||
* and RTNH_F_ONLINK.
|
||||
* We also may not properly consider the flags as part of the ID
|
||||
* in route-cmp. */ \
|
||||
unsigned r_rtm_flags; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \
|
||||
guint32 mss; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \
|
||||
guint32 window; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \
|
||||
guint32 cwnd; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \
|
||||
guint32 initcwnd; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \
|
||||
guint32 initrwnd; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \
|
||||
guint32 mtu; \
|
||||
\
|
||||
/* RTA_PRIORITY (iproute2: metric) */ \
|
||||
guint32 metric; \
|
||||
\
|
||||
* in route-cmp. */ \
|
||||
unsigned r_rtm_flags; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \
|
||||
guint32 mss; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \
|
||||
guint32 window; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \
|
||||
guint32 cwnd; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \
|
||||
guint32 initcwnd; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \
|
||||
guint32 initrwnd; \
|
||||
\
|
||||
/* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \
|
||||
guint32 mtu; \
|
||||
\
|
||||
/* RTA_PRIORITY (iproute2: metric) */ \
|
||||
guint32 metric; \
|
||||
\
|
||||
/* rtm_table, RTA_TABLE.
|
||||
*
|
||||
* This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and
|
||||
* zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main
|
||||
* table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \
|
||||
guint32 table_coerced; \
|
||||
\
|
||||
* table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \
|
||||
guint32 table_coerced; \
|
||||
\
|
||||
/* rtm_type.
|
||||
*
|
||||
* This is not the original type, if type_coerced is 0 then
|
||||
* it means RTN_UNSPEC otherwise the type value is preserved.
|
||||
* */ \
|
||||
guint8 type_coerced; \
|
||||
\
|
||||
* */ \
|
||||
guint8 type_coerced; \
|
||||
\
|
||||
/*end*/
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -1311,7 +1327,7 @@ nm_platform_route_table_coerce(guint32 table)
|
|||
|
||||
/**
|
||||
* nm_platform_route_table_uncoerce:
|
||||
* @table: the route table, in its coerced value
|
||||
* @table_coerced: the route table, in its coerced value
|
||||
* @normalize: whether to normalize RT_TABLE_UNSPEC to
|
||||
* RT_TABLE_MAIN. For kernel, routes with a table id
|
||||
* RT_TABLE_UNSPEC do not exist and are treated like
|
||||
|
|
@ -2053,6 +2069,34 @@ nm_platform_ip_address_get_peer_address(int addr_family, const NMPlatformIPAddre
|
|||
|
||||
void nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route);
|
||||
|
||||
static inline guint32
|
||||
nm_platform_ip4_route_get_effective_metric(const NMPlatformIP4Route *r)
|
||||
{
|
||||
nm_assert(r);
|
||||
nm_assert(!r->metric_any || r->metric == 0);
|
||||
|
||||
return r->metric_any ? NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 : r->metric;
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
nm_platform_ip6_route_get_effective_metric(const NMPlatformIP6Route *r)
|
||||
{
|
||||
nm_assert(r);
|
||||
nm_assert(!r->metric_any || r->metric == 0);
|
||||
|
||||
return r->metric_any ? NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 : r->metric;
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
nm_platform_ip_route_get_effective_table(const NMPlatformIPRoute *r)
|
||||
{
|
||||
nm_assert(r);
|
||||
nm_assert(!r->table_any || r->table_coerced == 0);
|
||||
|
||||
return r->table_any ? 254u /* RT_TABLE_MAIN */
|
||||
: nm_platform_route_table_uncoerce(r->table_coerced, TRUE);
|
||||
}
|
||||
|
||||
static inline gconstpointer
|
||||
nm_platform_ip_route_get_gateway(int addr_family, const NMPlatformIPRoute *route)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -116,43 +116,45 @@ _test_l3cfg_data_set_notify_type(TestL3cfgData *tdata, TestL3cfgNotifyType notif
|
|||
}
|
||||
|
||||
static void
|
||||
_test_l3cfg_signal_notify(NML3Cfg * l3cfg,
|
||||
int notify_type_i,
|
||||
const NML3ConfigNotifyPayload *payload,
|
||||
TestL3cfgData * tdata)
|
||||
_test_l3cfg_signal_notify(NML3Cfg * l3cfg,
|
||||
const NML3ConfigNotifyData *notify_data,
|
||||
TestL3cfgData * tdata)
|
||||
{
|
||||
NML3ConfigNotifyType l3_notify_type = notify_type_i;
|
||||
|
||||
g_assert(NM_IS_L3CFG(l3cfg));
|
||||
g_assert(tdata);
|
||||
g_assert((!!payload)
|
||||
== NM_IN_SET(l3_notify_type,
|
||||
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE,
|
||||
NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED));
|
||||
g_assert(notify_data);
|
||||
g_assert(_NM_INT_NOT_NEGATIVE(notify_data->notify_type));
|
||||
g_assert(notify_data->notify_type < _NM_L3_CONFIG_NOTIFY_TYPE_NUM);
|
||||
|
||||
if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)
|
||||
g_assert(payload->platform_change_on_idle.obj_type_flags != 0u);
|
||||
if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)
|
||||
g_assert(notify_data->platform_change_on_idle.obj_type_flags != 0u);
|
||||
else if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE) {
|
||||
g_assert(NMP_OBJECT_IS_VALID(notify_data->platform_change.obj));
|
||||
g_assert(notify_data->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(notify_data->notify_type,
|
||||
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE,
|
||||
NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE))
|
||||
return;
|
||||
g_assert_not_reached();
|
||||
return;
|
||||
case TEST_L3CFG_NOTIFY_TYPE_COMMIT_1:
|
||||
g_assert_cmpint(tdata->post_commit_event_count, ==, 0);
|
||||
switch (l3_notify_type) {
|
||||
switch (notify_data->notify_type) {
|
||||
case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT:
|
||||
tdata->post_commit_event_count++;
|
||||
return;
|
||||
case NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED:
|
||||
switch (tdata->f->test_idx) {
|
||||
case 2:
|
||||
nmtst_assert_ip4_address(payload->acd_completed.addr, "192.167.133.45");
|
||||
g_assert(payload->acd_completed.probe_result);
|
||||
nmtst_assert_ip4_address(notify_data->acd_completed.addr, "192.167.133.45");
|
||||
g_assert(notify_data->acd_completed.probe_result);
|
||||
g_assert(tdata->general_event_count == 0);
|
||||
tdata->general_event_count++;
|
||||
return;
|
||||
|
|
@ -160,19 +162,23 @@ _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(notify_data->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) {
|
||||
if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED) {
|
||||
g_assert(tdata->notify_data.wait_for_acd_ready_1.cb_count == 0);
|
||||
tdata->notify_data.wait_for_acd_ready_1.cb_count++;
|
||||
return;
|
||||
}
|
||||
if (l3_notify_type == NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT) {
|
||||
if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT) {
|
||||
g_assert(tdata->notify_data.wait_for_acd_ready_1.cb_count == 1);
|
||||
tdata->notify_data.wait_for_acd_ready_1.cb_count++;
|
||||
nmtstp_platform_ip_addresses_assert(tdata->f->platform,
|
||||
|
|
@ -276,6 +282,10 @@ test_l3cfg(gconstpointer test_data)
|
|||
'a',
|
||||
0,
|
||||
0,
|
||||
NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4,
|
||||
NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
|
||||
0,
|
||||
0,
|
||||
acd_timeout_msec,
|
||||
NM_L3_CONFIG_MERGE_FLAGS_NONE);
|
||||
}
|
||||
|
|
@ -287,7 +297,7 @@ test_l3cfg(gconstpointer test_data)
|
|||
LOGD_PLATFORM);
|
||||
|
||||
_test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_COMMIT_1);
|
||||
nm_l3cfg_platform_commit(l3cfg0, NM_L3_CFG_COMMIT_TYPE_REAPPLY);
|
||||
nm_l3cfg_commit(l3cfg0, NM_L3_CFG_COMMIT_TYPE_REAPPLY);
|
||||
g_assert_cmpint(tdata->post_commit_event_count, ==, 1);
|
||||
_test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue