mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-03 11:18:09 +02:00
platform: merge branch 'th/platform-route-pt1-bgo785449'
- extend platform's route-compare() functions with a mode argument. Most important is the new mode NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, which corresponds kernels ID of how routes compare. - when deleting routes, set all known parameters in the netlink message. Previously we would omit paramters, but that causes kernel to delete the first matching route. - cleanup fields of routes https://bugzilla.gnome.org/show_bug.cgi?id=785449
This commit is contained in:
commit
6da6323080
21 changed files with 954 additions and 700 deletions
|
|
@ -1188,7 +1188,7 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
|
|||
static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
|
|
|
|||
|
|
@ -24,6 +24,93 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#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_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_MEMCMP(a, b, size) \
|
||||
NM_CMP_RETURN (memcmp ((a), (b), (size)))
|
||||
|
||||
#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 (g_strcmp0 (_a, _b)); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
#define NM_CMP_FIELD_STR0(a, b, field) \
|
||||
NM_CMP_RETURN (g_strcmp0 (((a)->field), ((b)->field)))
|
||||
|
||||
#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
|
||||
NM_CMP_RETURN (memcmp (&((a)->field), &((b)->field), \
|
||||
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
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern const void *const _NM_PTRARRAY_EMPTY[1];
|
||||
|
||||
#define NM_PTRARRAY_EMPTY(type) ((type const*) _NM_PTRARRAY_EMPTY)
|
||||
|
|
|
|||
|
|
@ -316,28 +316,28 @@ nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_
|
|||
return dst;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
|
||||
int
|
||||
nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
|
||||
{
|
||||
int nbytes;
|
||||
guint8 t, m;
|
||||
guint8 va, vb, m;
|
||||
|
||||
if (plen >= 128)
|
||||
return memcmp (addr_a, addr_b, sizeof (struct in6_addr)) == 0;
|
||||
NM_CMP_DIRECT_MEMCMP (addr_a, addr_b, sizeof (struct in6_addr));
|
||||
else {
|
||||
nbytes = plen / 8;
|
||||
if (nbytes)
|
||||
NM_CMP_DIRECT_MEMCMP (addr_a, addr_b, nbytes);
|
||||
|
||||
nbytes = plen / 8;
|
||||
if (nbytes) {
|
||||
if (memcmp (addr_a, addr_b, nbytes) != 0)
|
||||
return FALSE;
|
||||
plen = plen % 8;
|
||||
if (plen != 0) {
|
||||
m = ~((1 << (8 - plen)) - 1);
|
||||
va = ((((const guint8 *) addr_a))[nbytes]) & m;
|
||||
vb = ((((const guint8 *) addr_b))[nbytes]) & m;
|
||||
NM_CMP_DIRECT (va, vb);
|
||||
}
|
||||
}
|
||||
|
||||
plen = plen % 8;
|
||||
if (plen == 0)
|
||||
return TRUE;
|
||||
|
||||
m = ~((1 << (8 - plen)) - 1);
|
||||
t = ((((const guint8 *) addr_a))[nbytes]) ^ ((((const guint8 *) addr_b))[nbytes]);
|
||||
return (t & m) == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -111,18 +111,51 @@ extern const NMIPAddr nm_ip_addr_zero;
|
|||
|
||||
guint nm_utils_in6_addr_hash (const struct in6_addr *addr);
|
||||
|
||||
static inline guint
|
||||
NM_HASH_COMBINE_IN6_ADDR (guint h, const struct in6_addr *addr)
|
||||
{
|
||||
return NM_HASH_COMBINE (h, addr ? nm_utils_in6_addr_hash (addr) : 0);
|
||||
}
|
||||
|
||||
gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
|
||||
|
||||
gconstpointer nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen);
|
||||
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
|
||||
const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
|
||||
gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
|
||||
int nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
|
||||
|
||||
static inline gboolean
|
||||
nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
|
||||
{
|
||||
return nm_utils_ip6_address_same_prefix_cmp (addr_a, addr_b, plen) == 0;
|
||||
}
|
||||
|
||||
#define NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(a, b, plen) \
|
||||
NM_CMP_RETURN (nm_utils_ip6_address_same_prefix_cmp ((a), (b), (plen)))
|
||||
|
||||
#define NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a, b, plen) \
|
||||
G_STMT_START { \
|
||||
const guint8 _plen = (plen); \
|
||||
const in_addr_t _aa = (a); \
|
||||
const in_addr_t _ab = (b); \
|
||||
\
|
||||
NM_CMP_DIRECT (htonl (nm_utils_ip4_address_clear_host_address (_aa, _plen)), \
|
||||
htonl (nm_utils_ip4_address_clear_host_address (_ab, _plen))); \
|
||||
} G_STMT_END
|
||||
|
||||
static inline guint
|
||||
NM_HASH_COMBINE_IN6ADDR (guint h, const struct in6_addr *addr)
|
||||
{
|
||||
if (!addr)
|
||||
g_return_val_if_reached (h);
|
||||
return NM_HASH_COMBINE (h, nm_utils_in6_addr_hash (addr));
|
||||
}
|
||||
|
||||
static inline guint
|
||||
NM_HASH_COMBINE_IN6ADDR_PREFIX (guint h, const struct in6_addr *addr, guint8 plen)
|
||||
{
|
||||
struct in6_addr a;
|
||||
|
||||
if (!addr)
|
||||
g_return_val_if_reached (h);
|
||||
nm_utils_ip6_address_clear_host_address (&a, addr, plen);
|
||||
/* we don't hash plen itself. The caller may want to do that.*/
|
||||
return NM_HASH_COMBINE (h, nm_utils_in6_addr_hash (&a));
|
||||
}
|
||||
|
||||
double nm_utils_exp10 (gint16 e);
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ _vt_routes_has_entry (const VTableIP *vtable, const GPtrArray *routes, const Ent
|
|||
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (routes->pdata[i]);
|
||||
|
||||
route.rx.rt_source = r->rt_source;
|
||||
if (nm_platform_ip4_route_cmp (r, &route.r4) == 0)
|
||||
if (nm_platform_ip4_route_cmp_full (r, &route.r4) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -220,7 +220,7 @@ _vt_routes_has_entry (const VTableIP *vtable, const GPtrArray *routes, const Ent
|
|||
const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (routes->pdata[i]);
|
||||
|
||||
route.rx.rt_source = r->rt_source;
|
||||
if (nm_platform_ip6_route_cmp (r, &route.r6) == 0)
|
||||
if (nm_platform_ip6_route_cmp_full (r, &route.r6) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +304,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
rt.plen = 0;
|
||||
rt.metric = entry->effective_metric;
|
||||
|
||||
success = nm_platform_ip4_route_add (priv->platform, &rt);
|
||||
success = nm_platform_ip4_route_add (priv->platform, NMP_NLM_FLAG_REPLACE, &rt);
|
||||
} else {
|
||||
NMPlatformIP6Route rt = entry->route.r6;
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
rt.plen = 0;
|
||||
rt.metric = entry->effective_metric;
|
||||
|
||||
success = nm_platform_ip6_route_add (priv->platform, &rt);
|
||||
success = nm_platform_ip6_route_add (priv->platform, NMP_NLM_FLAG_REPLACE, &rt);
|
||||
}
|
||||
if (!success) {
|
||||
_LOGW (vtable->vt->addr_family, "failed to add default route %s with effective metric %u",
|
||||
|
|
|
|||
|
|
@ -76,16 +76,14 @@ gboolean
|
|||
nm_ip_config_obj_id_equal_ip4_route (const NMPlatformIP4Route *r_a,
|
||||
const NMPlatformIP4Route *r_b)
|
||||
{
|
||||
return r_a->network == r_b->network
|
||||
&& r_a->plen == r_b->plen;
|
||||
return nm_platform_ip4_route_cmp (r_a, r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST) == 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_ip_config_obj_id_equal_ip6_route (const NMPlatformIP6Route *r_a,
|
||||
const NMPlatformIP6Route *r_b)
|
||||
{
|
||||
return r_a->plen == r_b->plen
|
||||
&& IN6_ARE_ADDR_EQUAL (&r_a->network, &r_b->network);
|
||||
return nm_platform_ip6_route_cmp (r_a, r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST) == 0;
|
||||
}
|
||||
|
||||
static guint
|
||||
|
|
@ -104,17 +102,15 @@ _idx_obj_id_hash (const NMDedupMultiIdxType *idx_type,
|
|||
break;
|
||||
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
||||
h = 851146661;
|
||||
h = NM_HASH_COMBINE_IN6_ADDR (h, &o->ip6_address.address);
|
||||
h = NM_HASH_COMBINE_IN6ADDR (h, &o->ip6_address.address);
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
h = 40303327;
|
||||
h = NM_HASH_COMBINE (h, o->ip4_route.network);
|
||||
h = NM_HASH_COMBINE (h, o->ip_route.plen);
|
||||
h = NM_HASH_COMBINE (h, nm_platform_ip4_route_hash (NMP_OBJECT_CAST_IP4_ROUTE (o), NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST));
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
h = 577629323;
|
||||
h = NM_HASH_COMBINE_IN6_ADDR (h, &o->ip6_route.network);
|
||||
h = NM_HASH_COMBINE (h, o->ip_route.plen);
|
||||
h = NM_HASH_COMBINE (h, nm_platform_ip6_route_hash (NMP_OBJECT_CAST_IP6_ROUTE (o), NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST));
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (0);
|
||||
|
|
@ -1512,7 +1508,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
|
|||
if (!has)
|
||||
break;
|
||||
|
||||
if (nm_platform_ip4_route_cmp (r_src, r_dst) != 0) {
|
||||
if (nm_platform_ip4_route_cmp_full (r_src, r_dst) != 0) {
|
||||
are_equal = FALSE;
|
||||
if ( !nm_ip_config_obj_id_equal_ip4_route (r_src, r_dst)
|
||||
|| r_src->gateway != r_dst->gateway
|
||||
|
|
|
|||
|
|
@ -569,7 +569,6 @@ merge_route_attributes (NMIPRoute *s_route, NMPlatformIP6Route *r)
|
|||
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \
|
||||
r->field = g_variant_get_ ## type (variant);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, tos, BYTE, byte);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, initcwnd, UINT32, uint32);
|
||||
|
|
@ -1291,7 +1290,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
|
|||
if (!has)
|
||||
break;
|
||||
|
||||
if (nm_platform_ip6_route_cmp (r_src, r_dst) != 0) {
|
||||
if (nm_platform_ip6_route_cmp_full (r_src, r_dst) != 0) {
|
||||
are_equal = FALSE;
|
||||
if ( !nm_ip_config_obj_id_equal_ip6_route (r_src, r_dst)
|
||||
|| r_src->metric != r_dst->metric
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ _route_equals_ignoring_ifindex (const VTableIP *vtable, const NMPlatformIPXRoute
|
|||
r2_backup.rx.metric = (guint32) r2_metric;
|
||||
r2 = &r2_backup;
|
||||
}
|
||||
return vtable->vt->route_cmp (r1, r2, FALSE) == 0;
|
||||
return vtable->vt->route_cmp (r1, r2, NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) == 0;
|
||||
}
|
||||
|
||||
static NMPlatformIPXRoute *
|
||||
|
|
@ -896,15 +896,16 @@ next:
|
|||
gateway_routes = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
g_array_append_val (gateway_routes, i_ipx_routes);
|
||||
} else
|
||||
vtable->vt->route_add (priv->platform, 0, cur_ipx_route, *p_effective_metric);
|
||||
vtable->vt->route_add (priv->platform, NMP_NLM_FLAG_REPLACE,
|
||||
cur_ipx_route, 0, *p_effective_metric);
|
||||
}
|
||||
|
||||
if (gateway_routes) {
|
||||
for (i = 0; i < gateway_routes->len; i++) {
|
||||
i_ipx_routes = g_array_index (gateway_routes, guint, i);
|
||||
vtable->vt->route_add (priv->platform, 0,
|
||||
vtable->vt->route_add (priv->platform, NMP_NLM_FLAG_REPLACE,
|
||||
ipx_routes->index->entries[i_ipx_routes],
|
||||
effective_metrics[i_ipx_routes]);
|
||||
0, effective_metrics[i_ipx_routes]);
|
||||
}
|
||||
g_array_unref (gateway_routes);
|
||||
}
|
||||
|
|
@ -953,7 +954,8 @@ next:
|
|||
|| route_dest_cmp_result != 0
|
||||
|| !_route_equals_ignoring_ifindex (vtable, cur_plat_route, cur_ipx_route, *p_effective_metric)) {
|
||||
|
||||
if (!vtable->vt->route_add (priv->platform, ifindex, cur_ipx_route, *p_effective_metric)) {
|
||||
if (!vtable->vt->route_add (priv->platform, NMP_NLM_FLAG_REPLACE,
|
||||
cur_ipx_route, ifindex, *p_effective_metric)) {
|
||||
if (cur_ipx_route->rx.rt_source < NM_IP_CONFIG_SOURCE_USER) {
|
||||
_LOGD (vtable->vt->addr_family,
|
||||
"ignore error adding IPv%c route to kernel: %s",
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gate
|
|||
static inline int
|
||||
_nmtst_platform_ip4_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return nm_platform_ip4_route_cmp ((const NMPlatformIP4Route *) a, (const NMPlatformIP4Route *) b);
|
||||
return nm_platform_ip4_route_cmp_full ((const NMPlatformIP4Route *) a, (const NMPlatformIP4Route *) b);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -215,7 +215,7 @@ nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP
|
|||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (nm_platform_ip4_route_cmp (&a[i], &b[i]) != 0) {
|
||||
if (nm_platform_ip4_route_cmp_full (&a[i], &b[i]) != 0) {
|
||||
char buf[sizeof (_nm_utils_to_string_buffer)];
|
||||
|
||||
g_error ("Error comparing IPv4 route[%lu]: %s vs %s", (unsigned long) i,
|
||||
|
|
@ -248,7 +248,7 @@ nmtst_platform_ip4_routes_equal_aptr (const NMPObject *const*a, const NMPlatform
|
|||
static inline int
|
||||
_nmtst_platform_ip6_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return nm_platform_ip6_route_cmp ((const NMPlatformIP6Route *) a, (const NMPlatformIP6Route *) b);
|
||||
return nm_platform_ip6_route_cmp_full ((const NMPlatformIP6Route *) a, (const NMPlatformIP6Route *) b);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -268,7 +268,7 @@ nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP
|
|||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (nm_platform_ip6_route_cmp (&a[i], &b[i]) != 0) {
|
||||
if (nm_platform_ip6_route_cmp_full (&a[i], &b[i]) != 0) {
|
||||
char buf[sizeof (_nm_utils_to_string_buffer)];
|
||||
|
||||
g_error ("Error comparing IPv6 route[%lu]: %s vs %s", (unsigned long) i,
|
||||
|
|
|
|||
|
|
@ -1192,7 +1192,10 @@ ip_route_delete (NMPlatform *platform, const NMPObject *obj)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ipx_route_add (NMPlatform *platform, int addr_family, const NMPlatformObject *route)
|
||||
ip_route_add (NMPlatform *platform,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
const NMPlatformIPRoute *route)
|
||||
{
|
||||
NMDedupMultiIter iter;
|
||||
nm_auto_nmpobj NMPObject *obj = NULL;
|
||||
|
|
@ -1208,10 +1211,13 @@ ipx_route_add (NMPlatform *platform, int addr_family, const NMPlatformObject *ro
|
|||
|
||||
g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
/* currently, only replace is implemented. */
|
||||
g_assert (flags == NMP_NLM_FLAG_REPLACE);
|
||||
|
||||
obj = nmp_object_new (addr_family == AF_INET
|
||||
? NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
: NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
route);
|
||||
(const NMPlatformObject *) route);
|
||||
rt = &obj->ip_route;
|
||||
rt->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt->rt_source);
|
||||
|
||||
|
|
@ -1274,18 +1280,6 @@ ipx_route_add (NMPlatform *platform, int addr_family, const NMPlatformObject *ro
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
|
||||
{
|
||||
return ipx_route_add (platform, AF_INET, (const NMPlatformObject *) route);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
|
||||
{
|
||||
return ipx_route_add (platform, AF_INET6, (const NMPlatformObject *) route);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -1396,7 +1390,6 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
|
|||
platform_class->ip4_address_delete = ip4_address_delete;
|
||||
platform_class->ip6_address_delete = ip6_address_delete;
|
||||
|
||||
platform_class->ip4_route_add = ip4_route_add;
|
||||
platform_class->ip6_route_add = ip6_route_add;
|
||||
platform_class->ip_route_add = ip_route_add;
|
||||
platform_class->ip_route_delete = ip_route_delete;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2018,9 +2018,13 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
memcpy (&obj->ip6_route.pref_src, nla_data (tb[RTA_PREFSRC]), addr_len);
|
||||
}
|
||||
|
||||
if (!is_v4 && tb[RTA_SRC]) {
|
||||
_check_addr_or_errout (tb, RTA_SRC, addr_len);
|
||||
memcpy (&obj->ip6_route.src, nla_data (tb[RTA_SRC]), addr_len);
|
||||
if (is_v4)
|
||||
obj->ip4_route.tos = rtm->rtm_tos;
|
||||
else {
|
||||
if (tb[RTA_SRC]) {
|
||||
_check_addr_or_errout (tb, RTA_SRC, addr_len);
|
||||
memcpy (&obj->ip6_route.src, nla_data (tb[RTA_SRC]), addr_len);
|
||||
}
|
||||
obj->ip6_route.src_plen = rtm->rtm_src_len;
|
||||
}
|
||||
|
||||
|
|
@ -2030,12 +2034,11 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
obj->ip_route.initcwnd = initcwnd;
|
||||
obj->ip_route.initrwnd = initrwnd;
|
||||
obj->ip_route.mtu = mtu;
|
||||
obj->ip_route.tos = rtm->rtm_tos;
|
||||
obj->ip_route.lock_window = NM_FLAGS_HAS (lock, 1 << RTAX_WINDOW);
|
||||
obj->ip_route.lock_cwnd = NM_FLAGS_HAS (lock, 1 << RTAX_CWND);
|
||||
obj->ip_route.lock_window = NM_FLAGS_HAS (lock, 1 << RTAX_WINDOW);
|
||||
obj->ip_route.lock_cwnd = NM_FLAGS_HAS (lock, 1 << RTAX_CWND);
|
||||
obj->ip_route.lock_initcwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITCWND);
|
||||
obj->ip_route.lock_initrwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITRWND);
|
||||
obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU);
|
||||
obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU);
|
||||
|
||||
if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) {
|
||||
/* we must not straight way reject cloned routes, because we might have cached
|
||||
|
|
@ -2414,38 +2417,42 @@ nla_put_failure:
|
|||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
static guint32
|
||||
ip_route_get_lock_flag (const NMPlatformIPRoute *route)
|
||||
{
|
||||
return (((guint32) route->lock_window) << RTAX_WINDOW)
|
||||
| (((guint32) route->lock_cwnd) << RTAX_CWND)
|
||||
| (((guint32) route->lock_initcwnd) << RTAX_INITCWND)
|
||||
| (((guint32) route->lock_initrwnd) << RTAX_INITRWND)
|
||||
| (((guint32) route->lock_mtu) << RTAX_MTU);
|
||||
}
|
||||
|
||||
/* Copied and modified from libnl3's build_route_msg() and rtnl_route_build_msg(). */
|
||||
static struct nl_msg *
|
||||
_nl_msg_new_route (int nlmsg_type,
|
||||
int nlmsg_flags,
|
||||
const NMPObject *obj,
|
||||
NMIPConfigSource source,
|
||||
unsigned char scope,
|
||||
gconstpointer gateway,
|
||||
guint32 mss,
|
||||
gconstpointer pref_src,
|
||||
gconstpointer src,
|
||||
guint8 src_plen,
|
||||
guint32 window,
|
||||
guint32 cwnd,
|
||||
guint32 initcwnd,
|
||||
guint32 initrwnd,
|
||||
guint32 mtu,
|
||||
guint32 lock)
|
||||
NMPNlmFlags nlmsgflags,
|
||||
const NMPObject *obj)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
gboolean is_v4 = klass->addr_family == AF_INET;
|
||||
const guint32 lock = ip_route_get_lock_flag (NMP_OBJECT_CAST_IP_ROUTE (obj));
|
||||
struct rtmsg rtmsg = {
|
||||
.rtm_family = klass->addr_family,
|
||||
.rtm_tos = obj->ip_route.tos,
|
||||
.rtm_tos = is_v4
|
||||
? obj->ip4_route.tos
|
||||
: 0,
|
||||
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
|
||||
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
|
||||
.rtm_scope = scope,
|
||||
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source),
|
||||
.rtm_scope = is_v4
|
||||
? nm_platform_route_scope_inv (obj->ip4_route.scope_inv)
|
||||
: RT_SCOPE_NOWHERE,
|
||||
.rtm_type = RTN_UNICAST,
|
||||
.rtm_flags = 0,
|
||||
.rtm_dst_len = obj->ip_route.plen,
|
||||
.rtm_src_len = src ? src_plen : 0,
|
||||
.rtm_src_len = is_v4
|
||||
? 0
|
||||
: NMP_OBJECT_CAST_IP6_ROUTE (obj)->src_plen,
|
||||
};
|
||||
|
||||
gsize addr_len;
|
||||
|
|
@ -2453,7 +2460,8 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
|
||||
|
||||
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
||||
nm_assert (((NMPNlmFlags) ((int) nlmsgflags)) == nlmsgflags);
|
||||
msg = nlmsg_alloc_simple (nlmsg_type, (int) nlmsgflags);
|
||||
if (!msg)
|
||||
g_return_val_if_reached (NULL);
|
||||
|
||||
|
|
@ -2469,33 +2477,46 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
? (gconstpointer) &obj->ip4_route.network
|
||||
: (gconstpointer) &obj->ip6_route.network);
|
||||
|
||||
if (src)
|
||||
NLA_PUT (msg, RTA_SRC, addr_len, src);
|
||||
if (!is_v4) {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (obj)->src))
|
||||
NLA_PUT (msg, RTA_SRC, addr_len, &obj->ip6_route.src);
|
||||
}
|
||||
|
||||
NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric);
|
||||
|
||||
if (pref_src)
|
||||
NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
|
||||
if (is_v4) {
|
||||
if (NMP_OBJECT_CAST_IP4_ROUTE (obj)->pref_src)
|
||||
NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src);
|
||||
} else {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (obj)->pref_src))
|
||||
NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip6_route.pref_src);
|
||||
}
|
||||
|
||||
if (mss || window || cwnd || initcwnd || initrwnd || mtu || lock) {
|
||||
if ( obj->ip_route.mss
|
||||
|| obj->ip_route.window
|
||||
|| obj->ip_route.cwnd
|
||||
|| obj->ip_route.initcwnd
|
||||
|| obj->ip_route.initrwnd
|
||||
|| obj->ip_route.mtu
|
||||
|| lock) {
|
||||
struct nlattr *metrics;
|
||||
|
||||
metrics = nla_nest_start (msg, RTA_METRICS);
|
||||
if (!metrics)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (mss)
|
||||
NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
|
||||
if (window)
|
||||
NLA_PUT_U32 (msg, RTAX_WINDOW, window);
|
||||
if (cwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_CWND, cwnd);
|
||||
if (initcwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_INITCWND, initcwnd);
|
||||
if (initrwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_INITRWND, initrwnd);
|
||||
if (mtu)
|
||||
NLA_PUT_U32 (msg, RTAX_MTU, mtu);
|
||||
if (obj->ip_route.mss)
|
||||
NLA_PUT_U32 (msg, RTAX_ADVMSS, obj->ip_route.mss);
|
||||
if (obj->ip_route.window)
|
||||
NLA_PUT_U32 (msg, RTAX_WINDOW, obj->ip_route.window);
|
||||
if (obj->ip_route.cwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_CWND, obj->ip_route.cwnd);
|
||||
if (obj->ip_route.initcwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_INITCWND, obj->ip_route.initcwnd);
|
||||
if (obj->ip_route.initrwnd)
|
||||
NLA_PUT_U32 (msg, RTAX_INITRWND, obj->ip_route.initrwnd);
|
||||
if (obj->ip_route.mtu)
|
||||
NLA_PUT_U32 (msg, RTAX_MTU, obj->ip_route.mtu);
|
||||
if (lock)
|
||||
NLA_PUT_U32 (msg, RTAX_LOCK, lock);
|
||||
|
||||
|
|
@ -2503,9 +2524,12 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
}
|
||||
|
||||
/* We currently don't have need for multi-hop routes... */
|
||||
if ( gateway
|
||||
&& memcmp (gateway, &nm_ip_addr_zero, addr_len) != 0)
|
||||
NLA_PUT (msg, RTA_GATEWAY, addr_len, gateway);
|
||||
if (is_v4) {
|
||||
NLA_PUT (msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway);
|
||||
} else {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&obj->ip6_route.gateway))
|
||||
NLA_PUT (msg, RTA_GATEWAY, addr_len, &obj->ip6_route.gateway);
|
||||
}
|
||||
NLA_PUT_U32 (msg, RTA_OIF, obj->ip_route.ifindex);
|
||||
|
||||
return msg;
|
||||
|
|
@ -5675,73 +5699,40 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, gui
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint32
|
||||
ip_route_get_lock_flag (NMPlatformIPRoute *route)
|
||||
{
|
||||
return (((guint32) route->lock_window) << RTAX_WINDOW)
|
||||
| (((guint32) route->lock_cwnd) << RTAX_CWND)
|
||||
| (((guint32) route->lock_initcwnd) << RTAX_INITCWND)
|
||||
| (((guint32) route->lock_initrwnd) << RTAX_INITRWND)
|
||||
| (((guint32) route->lock_mtu) << RTAX_MTU);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
|
||||
ip_route_add (NMPlatform *platform,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
const NMPlatformIPRoute *route)
|
||||
{
|
||||
NMPObject obj;
|
||||
NMPlatformIP4Route *r;
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route);
|
||||
r = NMP_OBJECT_CAST_IP4_ROUTE (&obj);
|
||||
r->network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
|
||||
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
|
||||
NLM_F_CREATE | NLM_F_REPLACE,
|
||||
&obj,
|
||||
route->rt_source,
|
||||
route->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
|
||||
&route->gateway,
|
||||
route->mss,
|
||||
route->pref_src ? &route->pref_src : NULL,
|
||||
NULL,
|
||||
0,
|
||||
route->window,
|
||||
route->cwnd,
|
||||
route->initcwnd,
|
||||
route->initrwnd,
|
||||
route->mtu,
|
||||
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
|
||||
return do_add_addrroute (platform, &obj, nlmsg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
|
||||
{
|
||||
NMPObject obj;
|
||||
NMPlatformIP6Route *r;
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
NMPlatformIP4Route *r4;
|
||||
NMPlatformIP6Route *r6;
|
||||
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route);
|
||||
r = NMP_OBJECT_CAST_IP6_ROUTE (&obj);
|
||||
nm_utils_ip6_address_clear_host_address (&r->network, &r->network, r->plen);
|
||||
switch (addr_family) {
|
||||
case AF_INET:
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route);
|
||||
r4 = NMP_OBJECT_CAST_IP4_ROUTE (&obj);
|
||||
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 = nm_platform_route_scope_inv (!r4->gateway
|
||||
? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
|
||||
break;
|
||||
case AF_INET6:
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route);
|
||||
r6 = NMP_OBJECT_CAST_IP6_ROUTE (&obj);
|
||||
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:
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
|
||||
NLM_F_CREATE | NLM_F_REPLACE,
|
||||
&obj,
|
||||
route->rt_source,
|
||||
IN6_IS_ADDR_UNSPECIFIED (&route->gateway) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
|
||||
&route->gateway,
|
||||
route->mss,
|
||||
!IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL,
|
||||
!IN6_IS_ADDR_UNSPECIFIED (&route->src) ? &route->src : NULL,
|
||||
route->src_plen,
|
||||
route->window,
|
||||
route->cwnd,
|
||||
route->initcwnd,
|
||||
route->initrwnd,
|
||||
route->mtu,
|
||||
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE, flags, &obj);
|
||||
if (!nlmsg)
|
||||
g_return_val_if_reached (FALSE);
|
||||
return do_add_addrroute (platform, &obj, nlmsg);
|
||||
}
|
||||
|
||||
|
|
@ -5789,24 +5780,9 @@ ip_route_delete (NMPlatform *platform,
|
|||
}
|
||||
}
|
||||
|
||||
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
|
||||
0,
|
||||
obj,
|
||||
NM_IP_CONFIG_SOURCE_UNKNOWN,
|
||||
RT_SCOPE_NOWHERE,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
nlmsg = _nl_msg_new_route (RTM_DELROUTE, 0, obj);
|
||||
if (!nlmsg)
|
||||
return FALSE;
|
||||
g_return_val_if_reached (FALSE);
|
||||
return do_delete_object (platform, obj, nlmsg);
|
||||
}
|
||||
|
||||
|
|
@ -6537,8 +6513,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
|||
platform_class->ip4_address_delete = ip4_address_delete;
|
||||
platform_class->ip6_address_delete = ip6_address_delete;
|
||||
|
||||
platform_class->ip4_route_add = ip4_route_add;
|
||||
platform_class->ip6_route_add = ip6_route_add;
|
||||
platform_class->ip_route_add = ip_route_add;
|
||||
platform_class->ip_route_delete = ip_route_delete;
|
||||
|
||||
platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -73,6 +73,72 @@ struct udev_device;
|
|||
/* Redefine this in host's endianness */
|
||||
#define NM_GRE_KEY 0x2000
|
||||
|
||||
typedef enum {
|
||||
/* use our own platform enum for the nlmsg-flags. Otherwise, we'd have
|
||||
* to include <linux/netlink.h> */
|
||||
NMP_NLM_FLAG_F_REPLACE = 0x100, /* NLM_F_REPLACE, Override existing */
|
||||
NMP_NLM_FLAG_F_EXCL = 0x200, /* NLM_F_EXCL, Do not touch, if it exists */
|
||||
NMP_NLM_FLAG_F_CREATE = 0x400, /* NLM_F_CREATE, Create, if it does not exist */
|
||||
NMP_NLM_FLAG_F_APPEND = 0x800, /* NLM_F_APPEND, Add to end of list */
|
||||
|
||||
/* the following aliases correspond to iproute2's `ip route CMD` for
|
||||
* RTM_NEWROUTE, with CMD being one of add, change, replace, prepend,
|
||||
* append and test. */
|
||||
NMP_NLM_FLAG_ADD = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_EXCL,
|
||||
NMP_NLM_FLAG_CHANGE = NMP_NLM_FLAG_F_REPLACE,
|
||||
NMP_NLM_FLAG_REPLACE = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_REPLACE,
|
||||
NMP_NLM_FLAG_PREPEND = NMP_NLM_FLAG_F_CREATE,
|
||||
NMP_NLM_FLAG_APPEND = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_APPEND,
|
||||
NMP_NLM_FLAG_TEST = NMP_NLM_FLAG_F_EXCL,
|
||||
} NMPNlmFlags;
|
||||
|
||||
typedef enum {
|
||||
/* compare fields which kernel considers as similar routes.
|
||||
* It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID
|
||||
* and means that `ip route add` would fail to add two routes
|
||||
* that have the same NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID.
|
||||
* On the other hand, `ip route append` would allow that, as
|
||||
* long as NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID differs. */
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID,
|
||||
|
||||
/* compare two routes as kernel would allow to add them with
|
||||
* `ip route append`. In other words, kernel does not allow you to
|
||||
* add two routes (at the same time) which compare equal according
|
||||
* to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID.
|
||||
*
|
||||
* For the ID we can only recognize route fields that we actually implement.
|
||||
* However, kernel supports more routing options, some of them also part of
|
||||
* the ID. NetworkManager is oblivious to these options and will wrongly think
|
||||
* that two routes are idential, while they are not. That can lead to an
|
||||
* inconsistent platform cache. Not much what we can do about that, except
|
||||
* implementing all options that kernel supports *sigh*. See rh#1337860.
|
||||
*/
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID,
|
||||
|
||||
/* FIXME: this type is what NMPCache currently uses for object identity.
|
||||
* Eventually, we want to use NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID,
|
||||
* which is the same what kernel does. */
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE,
|
||||
|
||||
/* NMIP4Config and NMIP6Config also track a list of routes. They have their
|
||||
* own notion of what equality means. Basically, they consider network/plen
|
||||
* for IPv4 and IPv6. */
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST,
|
||||
|
||||
/* compare all fields as they make sense for kernel. For example,
|
||||
* a route destination 192.168.1.5/24 is not accepted by kernel and
|
||||
* we treat it identical to 192.168.1.0/24. Semantically these
|
||||
* routes are identical, but NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL will
|
||||
* report them as different. */
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY,
|
||||
|
||||
/* compare all fields. This should have the same effect as memcmp(),
|
||||
* except allowing for undefined data in holes between field alignment.
|
||||
*/
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL,
|
||||
|
||||
} NMPlatformIPRouteCmpType;
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
|
||||
/* dummy value, to enforce that the enum type is signed and has a size
|
||||
|
|
@ -287,7 +353,15 @@ typedef union {
|
|||
/* 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
|
||||
* nmp_utils_ip_config_source_coerce_to_rtprot(). */ \
|
||||
* nmp_utils_ip_config_source_coerce_to_rtprot().
|
||||
*
|
||||
* rtm_protocol is part of the primary key of an IPv4 route (meaning, you can add
|
||||
* two IPv4 routes that only differ in their rtm_protocol. For IPv6, that is not
|
||||
* the case.
|
||||
*
|
||||
* 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; \
|
||||
|
|
@ -297,21 +371,51 @@ typedef union {
|
|||
* of platform users. This flag is internal to track those hidden
|
||||
* routes. Such a route is not alive, according to nmp_object_is_alive(). */ \
|
||||
bool rt_cloned:1; \
|
||||
\
|
||||
\
|
||||
/* RTA_METRICS:
|
||||
*
|
||||
* For IPv4 routes, these properties are part of their
|
||||
* ID (meaning: you can add otherwise idential IPv4 routes that
|
||||
* only differ by the metric property).
|
||||
* On the other hand, for IPv6 you cannot add two IPv6 routes that only differ
|
||||
* by an RTA_METRICS property.
|
||||
*
|
||||
* When deleting a route, kernel seems to ignore the RTA_METRICS propeties.
|
||||
* 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; \
|
||||
\
|
||||
guint32 metric; \
|
||||
/* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \
|
||||
guint32 mss; \
|
||||
guint32 tos; \
|
||||
\
|
||||
/* 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; \
|
||||
\
|
||||
/*end*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
__NMPlatformIPRoute_COMMON;
|
||||
|
|
@ -327,22 +431,60 @@ typedef struct {
|
|||
struct _NMPlatformIP4Route {
|
||||
__NMPlatformIPRoute_COMMON;
|
||||
in_addr_t network;
|
||||
|
||||
/* RTA_GATEWAY. The gateway is part of the primary key for a route */
|
||||
in_addr_t gateway;
|
||||
|
||||
/* The bitwise inverse of the route scope. It is inverted so that the
|
||||
* default value (RT_SCOPE_NOWHERE) is nul. */
|
||||
guint8 scope_inv;
|
||||
|
||||
/* RTA_PREFSRC/rtnl_route_get_pref_src(). A value of zero means that
|
||||
* no pref-src is set. */
|
||||
/* RTA_PREFSRC (called "src" by iproute2).
|
||||
*
|
||||
* pref_src is part of the ID of an IPv4 route. When deleting a route,
|
||||
* pref_src must match, unless set to 0.0.0.0 to match any. */
|
||||
in_addr_t pref_src;
|
||||
|
||||
/* rtm_tos (iproute2: tos)
|
||||
*
|
||||
* For IPv4, tos is part of the weak-id (like metric).
|
||||
*
|
||||
* For IPv6, tos is ignored by kernel. */
|
||||
guint8 tos;
|
||||
|
||||
/* The bitwise inverse of the route scope rtm_scope. It is inverted so that the
|
||||
* default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv()
|
||||
* to convert back and forth between the inverese representation and the
|
||||
* real value.
|
||||
*
|
||||
* rtm_scope is part of the primary key for IPv4 routes. When deleting a route,
|
||||
* the scope must match, unless it is left at RT_SCOPE_NOWHERE, in which case the first
|
||||
* matching route is deleted.
|
||||
*
|
||||
* For IPv6 routes, the scope is ignored and kernel always assumes global scope.
|
||||
* Hence, this field is only in NMPlatformIP4Route. */
|
||||
guint8 scope_inv;
|
||||
};
|
||||
|
||||
struct _NMPlatformIP6Route {
|
||||
__NMPlatformIPRoute_COMMON;
|
||||
struct in6_addr network;
|
||||
|
||||
/* RTA_GATEWAY. The gateway is part of the primary key for a route */
|
||||
struct in6_addr gateway;
|
||||
|
||||
/* RTA_PREFSRC (called "src" by iproute2).
|
||||
*
|
||||
* pref_src is not part of the ID for an IPv6 route. You cannot add two
|
||||
* routes that only differ by pref_src.
|
||||
*
|
||||
* When deleting a route, pref_src is ignored by kernel. */
|
||||
struct in6_addr pref_src;
|
||||
|
||||
/* RTA_SRC and rtm_src_len (called "from" by iproute2).
|
||||
*
|
||||
* Kernel clears the host part of src/src_plen.
|
||||
*
|
||||
* src/src_plen is part of the ID of a route just like network/plen. That is,
|
||||
* Not only `ip route append`, but also `ip route add` allows to add routes that only
|
||||
* differ in their src/src_plen.
|
||||
*/
|
||||
struct in6_addr src;
|
||||
guint8 src_plen;
|
||||
};
|
||||
|
|
@ -364,9 +506,13 @@ typedef struct {
|
|||
NMPObjectType obj_type;
|
||||
int addr_family;
|
||||
gsize sizeof_route;
|
||||
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, gboolean consider_host_part);
|
||||
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type);
|
||||
const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
|
||||
gboolean (*route_add) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric);
|
||||
gboolean (*route_add) (NMPlatform *self,
|
||||
NMPNlmFlags flags,
|
||||
const NMPlatformIPXRoute *route,
|
||||
int ifindex,
|
||||
gint64 metric);
|
||||
guint32 (*metric_normalize) (guint32 metric);
|
||||
} NMPlatformVTableRoute;
|
||||
|
||||
|
|
@ -640,8 +786,10 @@ typedef struct {
|
|||
gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
|
||||
gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
|
||||
|
||||
gboolean (*ip4_route_add) (NMPlatform *, const NMPlatformIP4Route *route);
|
||||
gboolean (*ip6_route_add) (NMPlatform *, const NMPlatformIP6Route *route);
|
||||
gboolean (*ip_route_add) (NMPlatform *,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
const NMPlatformIPRoute *route);
|
||||
gboolean (*ip_route_delete) (NMPlatform *, const NMPObject *obj);
|
||||
|
||||
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
|
||||
|
|
@ -954,8 +1102,10 @@ gboolean nm_platform_address_flush (NMPlatform *self, int ifindex);
|
|||
|
||||
const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
|
||||
const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
|
||||
gboolean nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route);
|
||||
gboolean nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route);
|
||||
|
||||
gboolean nm_platform_ip4_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route);
|
||||
gboolean nm_platform_ip6_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route);
|
||||
|
||||
gboolean nm_platform_ip_route_delete (NMPlatform *self, const NMPObject *route);
|
||||
|
||||
const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
|
||||
|
|
@ -991,26 +1141,27 @@ int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVla
|
|||
int nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b);
|
||||
int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b);
|
||||
int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b);
|
||||
int nm_platform_ip4_route_cmp_full (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gboolean consider_host_part);
|
||||
int nm_platform_ip6_route_cmp_full (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gboolean consider_host_part);
|
||||
|
||||
int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteCmpType cmp_type);
|
||||
int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteCmpType cmp_type);
|
||||
|
||||
static inline int
|
||||
nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
|
||||
nm_platform_ip4_route_cmp_full (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
|
||||
{
|
||||
return nm_platform_ip4_route_cmp_full (a, b, TRUE);
|
||||
return nm_platform_ip4_route_cmp (a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL);
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
|
||||
nm_platform_ip6_route_cmp_full (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
|
||||
{
|
||||
return nm_platform_ip6_route_cmp_full (a, b, TRUE);
|
||||
return nm_platform_ip6_route_cmp (a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL);
|
||||
}
|
||||
|
||||
guint nm_platform_link_hash (const NMPlatformLink *obj);
|
||||
guint nm_platform_ip4_address_hash (const NMPlatformIP4Address *obj);
|
||||
guint nm_platform_ip6_address_hash (const NMPlatformIP6Address *obj);
|
||||
guint nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj);
|
||||
guint nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj);
|
||||
guint nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type);
|
||||
guint nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpType cmp_type);
|
||||
guint nm_platform_lnk_gre_hash (const NMPlatformLnkGre *obj);
|
||||
guint nm_platform_lnk_infiniband_hash (const NMPlatformLnkInfiniband *obj);
|
||||
guint nm_platform_lnk_ip6tnl_hash (const NMPlatformLnkIp6Tnl *obj);
|
||||
|
|
@ -1021,6 +1172,18 @@ guint nm_platform_lnk_sit_hash (const NMPlatformLnkSit *obj);
|
|||
guint nm_platform_lnk_vlan_hash (const NMPlatformLnkVlan *obj);
|
||||
guint nm_platform_lnk_vxlan_hash (const NMPlatformLnkVxlan *obj);
|
||||
|
||||
static inline guint
|
||||
nm_platform_ip4_route_hash_full (const NMPlatformIP4Route *obj)
|
||||
{
|
||||
return nm_platform_ip4_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL);
|
||||
}
|
||||
|
||||
static inline guint
|
||||
nm_platform_ip6_route_hash_full (const NMPlatformIP6Route *obj)
|
||||
{
|
||||
return nm_platform_ip6_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL);
|
||||
}
|
||||
|
||||
gboolean nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self);
|
||||
gboolean nm_platform_check_support_user_ipv6ll (NMPlatform *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -225,21 +225,16 @@ _idx_obj_part (const DedupMultiIdxType *idx_type,
|
|||
if (obj_b) {
|
||||
return obj_type == NMP_OBJECT_GET_TYPE (obj_b)
|
||||
&& obj_b->object.ifindex > 0
|
||||
&& obj_a->ip_route.plen == obj_b->ip_route.plen
|
||||
&& obj_a->ip_route.metric == obj_b->ip_route.metric
|
||||
&& (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
? obj_a->ip4_route.network == obj_b->ip4_route.network
|
||||
: IN6_ARE_ADDR_EQUAL (&obj_a->ip6_route.network, &obj_b->ip6_route.network));
|
||||
? (nm_platform_ip4_route_cmp (&obj_a->ip4_route, &obj_b->ip4_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) == 0)
|
||||
: (nm_platform_ip6_route_cmp (&obj_a->ip6_route, &obj_b->ip6_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) == 0));
|
||||
}
|
||||
if (request_hash) {
|
||||
h = (guint) idx_type->cache_id_type;
|
||||
h = NM_HASH_COMBINE (h, obj_a->ip_route.plen);
|
||||
h = NM_HASH_COMBINE (h, obj_a->ip_route.metric);
|
||||
h = NM_HASH_COMBINE (h, obj_type);
|
||||
if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE)
|
||||
h = NM_HASH_COMBINE (h, obj_a->ip4_route.network);
|
||||
h = NM_HASH_COMBINE (h, nm_platform_ip4_route_hash (&obj_a->ip4_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID));
|
||||
else
|
||||
h = NM_HASH_COMBINE (h, nm_utils_in6_addr_hash (&obj_a->ip6_route.network));
|
||||
h = NM_HASH_COMBINE (h, nm_platform_ip6_route_hash (&obj_a->ip6_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID));
|
||||
return _HASH_NON_ZERO (h);
|
||||
}
|
||||
return 1;
|
||||
|
|
@ -559,10 +554,9 @@ nmp_object_stackinit_id (NMPObject *obj, const NMPObject *src)
|
|||
nm_assert (obj);
|
||||
|
||||
klass = NMP_OBJECT_GET_CLASS (src);
|
||||
if (!klass->cmd_obj_stackinit_id)
|
||||
_nmp_object_stackinit_from_class (obj, klass);
|
||||
else
|
||||
klass->cmd_obj_stackinit_id (obj, src);
|
||||
_nmp_object_stackinit_from_class (obj, klass);
|
||||
if (klass->cmd_plobj_id_copy)
|
||||
klass->cmd_plobj_id_copy (&obj->object, &src->object);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -574,12 +568,6 @@ nmp_object_stackinit_id_link (NMPObject *obj, int ifindex)
|
|||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_stackinit_id_link (NMPObject *obj, const NMPObject *src)
|
||||
{
|
||||
nmp_object_stackinit_id_link (obj, src->link.ifindex);
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address)
|
||||
{
|
||||
|
|
@ -591,12 +579,6 @@ nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 addres
|
|||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_stackinit_id_ip4_address (NMPObject *obj, const NMPObject *src)
|
||||
{
|
||||
nmp_object_stackinit_id_ip4_address (obj, src->ip_address.ifindex, src->ip4_address.address, src->ip_address.plen, src->ip4_address.peer_address);
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address)
|
||||
{
|
||||
|
|
@ -607,12 +589,6 @@ nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct i
|
|||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_stackinit_id_ip6_address (NMPObject *obj, const NMPObject *src)
|
||||
{
|
||||
nmp_object_stackinit_id_ip6_address (obj, src->ip_address.ifindex, &src->ip6_address.address);
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric)
|
||||
{
|
||||
|
|
@ -624,12 +600,6 @@ nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network,
|
|||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_stackinit_id_ip4_route (NMPObject *obj, const NMPObject *src)
|
||||
{
|
||||
nmp_object_stackinit_id_ip4_route (obj, src->ip_route.ifindex, src->ip4_route.network, src->ip_route.plen, src->ip_route.metric);
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric)
|
||||
{
|
||||
|
|
@ -642,12 +612,6 @@ nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6
|
|||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_stackinit_id_ip6_route (NMPObject *obj, const NMPObject *src)
|
||||
{
|
||||
nmp_object_stackinit_id_ip6_route (obj, src->ip_route.ifindex, &src->ip6_route.network, src->ip_route.plen, src->ip_route.metric);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
|
|
@ -1024,12 +988,14 @@ _vt_cmd_plobj_id_copy (ip4_route, NMPlatformIP4Route, {
|
|||
dst->plen = src->plen;
|
||||
dst->metric = src->metric;
|
||||
dst->network = src->network;
|
||||
nm_assert (nm_platform_ip4_route_cmp (dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE) == 0);
|
||||
});
|
||||
_vt_cmd_plobj_id_copy (ip6_route, NMPlatformIP6Route, {
|
||||
dst->ifindex = src->ifindex;
|
||||
dst->plen = src->plen;
|
||||
dst->metric = src->metric;
|
||||
dst->network = src->network;
|
||||
nm_assert (nm_platform_ip6_route_cmp (dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE) == 0);
|
||||
});
|
||||
|
||||
/* Uses internally nmp_object_copy(), hence it also violates the const
|
||||
|
|
@ -1091,20 +1057,9 @@ _vt_cmd_plobj_id_equal (ip6_address, NMPlatformIP6Address,
|
|||
/* for IPv6 addresses, the prefix length is not part of the primary identifier. */
|
||||
&& IN6_ARE_ADDR_EQUAL (&obj1->address, &obj2->address));
|
||||
_vt_cmd_plobj_id_equal (ip4_route, NMPlatformIP4Route,
|
||||
obj1->ifindex == obj2->ifindex
|
||||
&& obj1->plen == obj2->plen
|
||||
&& obj1->metric == obj2->metric
|
||||
&& nm_utils_ip4_address_clear_host_address (obj1->network, obj1->plen) == nm_utils_ip4_address_clear_host_address (obj2->network, obj2->plen));
|
||||
nm_platform_ip4_route_cmp (obj1, obj2, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE) == 0);
|
||||
_vt_cmd_plobj_id_equal (ip6_route, NMPlatformIP6Route,
|
||||
obj1->ifindex == obj2->ifindex
|
||||
&& obj1->plen == obj2->plen
|
||||
&& obj1->metric == obj2->metric
|
||||
&& ({
|
||||
struct in6_addr n1, n2;
|
||||
|
||||
IN6_ARE_ADDR_EQUAL(nm_utils_ip6_address_clear_host_address (&n1, &obj1->network, obj1->plen),
|
||||
nm_utils_ip6_address_clear_host_address (&n2, &obj2->network, obj2->plen));
|
||||
}));
|
||||
nm_platform_ip6_route_cmp (obj1, obj2, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE) == 0);
|
||||
|
||||
guint
|
||||
nmp_object_id_hash (const NMPObject *obj)
|
||||
|
|
@ -1153,22 +1108,10 @@ _vt_cmd_plobj_id_hash (ip6_address, NMPlatformIP6Address, {
|
|||
hash = NM_HASH_COMBINE (hash, nm_utils_in6_addr_hash (&obj->address));
|
||||
})
|
||||
_vt_cmd_plobj_id_hash (ip4_route, NMPlatformIP4Route, {
|
||||
hash = (guint) 2569857221u;
|
||||
hash = hash + ((guint) obj->ifindex);
|
||||
hash = NM_HASH_COMBINE (hash, obj->plen);
|
||||
hash = NM_HASH_COMBINE (hash, obj->metric);
|
||||
hash = NM_HASH_COMBINE (hash, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen));
|
||||
hash = nm_platform_ip4_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE);
|
||||
})
|
||||
_vt_cmd_plobj_id_hash (ip6_route, NMPlatformIP6Route, {
|
||||
hash = (guint) 3999787007u;
|
||||
hash = hash + ((guint) obj->ifindex);
|
||||
hash = NM_HASH_COMBINE (hash, obj->plen);
|
||||
hash = NM_HASH_COMBINE (hash, obj->metric);
|
||||
hash = NM_HASH_COMBINE (hash,
|
||||
({
|
||||
struct in6_addr n1;
|
||||
nm_utils_in6_addr_hash (nm_utils_ip6_address_clear_host_address (&n1, &obj->network, obj->plen));
|
||||
}));
|
||||
hash = nm_platform_ip6_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID_CACHE);
|
||||
})
|
||||
|
||||
gboolean
|
||||
|
|
@ -2355,7 +2298,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.cmd_obj_hash = _vt_cmd_obj_hash_link,
|
||||
.cmd_obj_cmp = _vt_cmd_obj_cmp_link,
|
||||
.cmd_obj_copy = _vt_cmd_obj_copy_link,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_link,
|
||||
.cmd_obj_dispose = _vt_cmd_obj_dispose_link,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_link,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_link,
|
||||
|
|
@ -2379,7 +2321,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
|
||||
.supported_cache_ids = _supported_cache_ids_ipx_address,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_address,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_address,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip4_address,
|
||||
|
|
@ -2400,7 +2341,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
|
||||
.supported_cache_ids = _supported_cache_ids_ipx_address,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_address,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip6_address,
|
||||
|
|
@ -2421,15 +2361,14 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
|
||||
.supported_cache_ids = _supported_cache_ids_ipx_route,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_route,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip4_route,
|
||||
.cmd_plobj_id_hash = _vt_cmd_plobj_id_hash_ip4_route,
|
||||
.cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip4_route,
|
||||
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip4_route_to_string,
|
||||
.cmd_plobj_hash = (guint (*) (const NMPlatformObject *obj)) nm_platform_ip4_route_hash,
|
||||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_route_cmp,
|
||||
.cmd_plobj_hash = (guint (*) (const NMPlatformObject *obj)) nm_platform_ip4_route_hash_full,
|
||||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_route_cmp_full,
|
||||
},
|
||||
[NMP_OBJECT_TYPE_IP6_ROUTE - 1] = {
|
||||
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
|
||||
|
|
@ -2442,15 +2381,14 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
|
||||
.supported_cache_ids = _supported_cache_ids_ipx_route,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_route,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip6_route,
|
||||
.cmd_plobj_id_hash = _vt_cmd_plobj_id_hash_ip6_route,
|
||||
.cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_route,
|
||||
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip6_route_to_string,
|
||||
.cmd_plobj_hash = (guint (*) (const NMPlatformObject *obj)) nm_platform_ip6_route_hash,
|
||||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_route_cmp,
|
||||
.cmd_plobj_hash = (guint (*) (const NMPlatformObject *obj)) nm_platform_ip6_route_hash_full,
|
||||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_route_cmp_full,
|
||||
},
|
||||
[NMP_OBJECT_TYPE_LNK_GRE - 1] = {
|
||||
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ typedef struct {
|
|||
guint (*cmd_obj_hash) (const NMPObject *obj);
|
||||
int (*cmd_obj_cmp) (const NMPObject *obj1, const NMPObject *obj2);
|
||||
void (*cmd_obj_copy) (NMPObject *dst, const NMPObject *src);
|
||||
void (*cmd_obj_stackinit_id) (NMPObject *obj, const NMPObject *src);
|
||||
void (*cmd_obj_dispose) (NMPObject *obj);
|
||||
gboolean (*cmd_obj_is_alive) (const NMPObject *obj);
|
||||
gboolean (*cmd_obj_is_visible) (const NMPObject *obj);
|
||||
|
|
|
|||
|
|
@ -903,7 +903,7 @@ void nmtstp_ip4_route_add (NMPlatform *platform,
|
|||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
g_assert (nm_platform_ip4_route_add (platform, &route));
|
||||
g_assert (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_REPLACE, &route));
|
||||
}
|
||||
|
||||
void nmtstp_ip6_route_add (NMPlatform *platform,
|
||||
|
|
@ -927,7 +927,7 @@ void nmtstp_ip6_route_add (NMPlatform *platform,
|
|||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
g_assert (nm_platform_ip6_route_add (platform, &route));
|
||||
g_assert (nm_platform_ip6_route_add (platform, NMP_NLM_FLAG_REPLACE, &route));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP
|
|||
{
|
||||
const NMPObjectType obj_type = obj_type_i;
|
||||
const NMPlatformSignalChangeType change_type = change_type_i;
|
||||
NMPObject o_id;
|
||||
nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
|
||||
|
||||
g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_IP4_ROUTE);
|
||||
g_assert (received);
|
||||
|
|
@ -76,6 +78,11 @@ ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP
|
|||
g_assert (data && data->name);
|
||||
g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED);
|
||||
|
||||
/* run code for initializing the ID only */
|
||||
nmp_object_stackinit_id (&o_id, NMP_OBJECT_UP_CAST (received));
|
||||
nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), TRUE);
|
||||
nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), FALSE);
|
||||
|
||||
if (data->ifindex && data->ifindex != received->ifindex)
|
||||
return;
|
||||
if (data->change_type != change_type)
|
||||
|
|
@ -93,6 +100,8 @@ ip6_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP
|
|||
{
|
||||
const NMPObjectType obj_type = obj_type_i;
|
||||
const NMPlatformSignalChangeType change_type = change_type_i;
|
||||
NMPObject o_id;
|
||||
nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
|
||||
|
||||
g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_IP6_ROUTE);
|
||||
g_assert (received);
|
||||
|
|
@ -100,6 +109,11 @@ ip6_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP
|
|||
g_assert (data && data->name);
|
||||
g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED);
|
||||
|
||||
/* run code for initializing the ID only */
|
||||
nmp_object_stackinit_id (&o_id, NMP_OBJECT_UP_CAST (received));
|
||||
nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), TRUE);
|
||||
nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), FALSE);
|
||||
|
||||
if (data->ifindex && data->ifindex != received->ifindex)
|
||||
return;
|
||||
if (data->change_type != change_type)
|
||||
|
|
@ -418,7 +432,7 @@ test_ip4_route_options (void)
|
|||
route.mtu = 1350;
|
||||
route.lock_cwnd = TRUE;
|
||||
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &route));
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route));
|
||||
|
||||
/* Test route listing */
|
||||
routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex);
|
||||
|
|
@ -518,7 +532,7 @@ test_ip6_route_options (gconstpointer test_data)
|
|||
_wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6);
|
||||
|
||||
for (i = 0; i < rts_n; i++)
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &rts_add[i]));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]));
|
||||
|
||||
routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX);
|
||||
switch (TEST_IDX) {
|
||||
|
|
|
|||
|
|
@ -467,23 +467,25 @@ parse_route_options (NMIPRoute *route, int family, const char *line, GError **er
|
|||
}
|
||||
|
||||
/* tos */
|
||||
regex = g_regex_new ("(?:\\s|^)tos\\s+(\\S+)(?:$|\\s)", 0, 0, NULL);
|
||||
g_regex_match (regex, line, 0, &match_info);
|
||||
if (g_match_info_matches (match_info)) {
|
||||
gs_free char *str = g_match_info_fetch (match_info, 1);
|
||||
gint64 num = _nm_utils_ascii_str_to_int64 (str, 0, 0, G_MAXUINT8, -1);
|
||||
if (family == AF_INET) {
|
||||
regex = g_regex_new ("(?:\\s|^)tos\\s+(\\S+)(?:$|\\s)", 0, 0, NULL);
|
||||
g_regex_match (regex, line, 0, &match_info);
|
||||
if (g_match_info_matches (match_info)) {
|
||||
gs_free char *str = g_match_info_fetch (match_info, 1);
|
||||
gint64 num = _nm_utils_ascii_str_to_int64 (str, 16, 0, G_MAXUINT8, -1);
|
||||
|
||||
if (num == -1) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid route %s '%s'", "tos", str);
|
||||
goto out;
|
||||
if (num == -1) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid route %s '%s'", "tos", str);
|
||||
goto out;
|
||||
}
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_TOS,
|
||||
g_variant_new_byte ((guchar) num));
|
||||
}
|
||||
nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_TOS,
|
||||
g_variant_new_byte ((guchar) num));
|
||||
g_clear_pointer (®ex, g_regex_unref);
|
||||
g_clear_pointer (&match_info, g_match_info_free);
|
||||
}
|
||||
g_clear_pointer (®ex, g_regex_unref);
|
||||
g_clear_pointer (&match_info, g_match_info_free);
|
||||
|
||||
/* from */
|
||||
if (family == AF_INET6) {
|
||||
|
|
|
|||
|
|
@ -1893,7 +1893,7 @@ get_route_attributes_string (NMIPRoute *route, int family)
|
|||
} else if (strstr (names[i], "lock-")) {
|
||||
/* handled above */
|
||||
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TOS)) {
|
||||
g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_byte (attr));
|
||||
g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr));
|
||||
} else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC)
|
||||
|| nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_FROM)) {
|
||||
char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) ? "src" : "from";
|
||||
|
|
|
|||
|
|
@ -4108,7 +4108,6 @@ test_write_wired_static (void)
|
|||
|
||||
route6 = nm_ip_route_new (AF_INET6, "::", 128, "2222:aaaa::9999", 1, &error);
|
||||
g_assert_no_error (error);
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_TOS, g_variant_new_byte (0xb8));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32 (100));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (1280));
|
||||
nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, g_variant_new_boolean (TRUE));
|
||||
|
|
|
|||
|
|
@ -822,7 +822,7 @@ _assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NM
|
|||
c.r6 = route->r6;
|
||||
c.rx.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (c.rx.rt_source);
|
||||
}
|
||||
if (!r || vtable->route_cmp (r, &c, TRUE) != 0) {
|
||||
if (!r || vtable->route_cmp (r, &c, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) != 0) {
|
||||
g_error ("Invalid route. Expect %s, has %s",
|
||||
vtable->route_to_string (&c, NULL, 0),
|
||||
vtable->route_to_string (r, buf, sizeof (buf)));
|
||||
|
|
@ -857,7 +857,7 @@ test_ip4_full_sync (test_fixture *fixture, gconstpointer user_data)
|
|||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02);
|
||||
_assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03);
|
||||
|
||||
vtable->route_add (NM_PLATFORM_GET, 0, (const NMPlatformIPXRoute *) &r03, -1);
|
||||
vtable->route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, (const NMPlatformIPXRoute *) &r03, 0, -1);
|
||||
|
||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
|
||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue