diff options
-rw-r--r-- | src/platform/nm-platform.c | 55 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 3 |
2 files changed, 48 insertions, 10 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 33aa8db69e..5ac788f73f 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -5064,12 +5064,15 @@ nm_platform_qdisc_sync (NMPlatform *self, known_qdiscs_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal); - if (known_qdiscs) { for (i = 0; i < known_qdiscs->len; i++) { const NMPObject *q = g_ptr_array_index (known_qdiscs, i); - g_hash_table_insert (known_qdiscs_idx, (gpointer) q, (gpointer) q); + if (!g_hash_table_insert (known_qdiscs_idx, (gpointer) q, (gpointer) q)) { + _LOGW ("duplicate qdisc %s", nm_platform_qdisc_to_string (&q->qdisc, NULL, 0)); + return FALSE; + } + } } @@ -5078,13 +5081,34 @@ nm_platform_qdisc_sync (NMPlatform *self, NMP_OBJECT_TYPE_QDISC, ifindex), NULL, NULL); - if (plat_qdiscs) { for (i = 0; i < plat_qdiscs->len; i++) { - const NMPObject *q = g_ptr_array_index (plat_qdiscs, i); + const NMPObject *p = g_ptr_array_index (plat_qdiscs, i); + const NMPObject *k; - if (!g_hash_table_lookup (known_qdiscs_idx, q)) - success &= nm_platform_object_delete (self, q); + /* look up known qdisc with same parent */ + k = g_hash_table_lookup (known_qdiscs_idx, p); + + if (k) { + const NMPlatformQdisc *qdisc_k = NMP_OBJECT_CAST_QDISC (k); + const NMPlatformQdisc *qdisc_p = NMP_OBJECT_CAST_QDISC (p); + + /* check other fields */ + if ( nm_platform_qdisc_cmp_full (qdisc_k, qdisc_p, FALSE) != 0 + || ( qdisc_k->handle != qdisc_p->handle + && qdisc_k != 0)) { + k = NULL; + } + } + + if (k) { + g_hash_table_remove (known_qdiscs_idx, k); + } else { + /* can't delete qdisc with zero handle */ + if (TC_H_MAJ (p->qdisc.handle) != 0) { + success &= nm_platform_object_delete (self, p); + } + } } } @@ -5092,8 +5116,10 @@ nm_platform_qdisc_sync (NMPlatform *self, for (i = 0; i < known_qdiscs->len; i++) { const NMPObject *q = g_ptr_array_index (known_qdiscs, i); - success &= (nm_platform_qdisc_add (self, NMP_NLM_FLAG_ADD, - NMP_OBJECT_CAST_QDISC (q)) >= 0); + if (g_hash_table_contains (known_qdiscs_idx, q)) { + success &= (nm_platform_qdisc_add (self, NMP_NLM_FLAG_ADD, + NMP_OBJECT_CAST_QDISC (q)) >= 0); + } } } @@ -6518,14 +6544,17 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h) } int -nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) +nm_platform_qdisc_cmp_full (const NMPlatformQdisc *a, + const NMPlatformQdisc *b, + gboolean compare_handle) { NM_CMP_SELF (a, b); NM_CMP_FIELD (a, b, ifindex); NM_CMP_FIELD (a, b, parent); NM_CMP_FIELD_STR_INTERNED (a, b, kind); NM_CMP_FIELD (a, b, addr_family); - NM_CMP_FIELD (a, b, handle); + if (compare_handle) + NM_CMP_FIELD (a, b, handle); NM_CMP_FIELD (a, b, info); if (nm_streq0 (a->kind, "fq_codel")) { @@ -6542,6 +6571,12 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) return 0; } +int +nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) +{ + return nm_platform_qdisc_cmp_full (a, b, TRUE); +} + const char * nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsize len) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 4bfbfea432..fb82262979 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1909,6 +1909,9 @@ nm_platform_routing_rule_cmp_full (const NMPlatformRoutingRule *a, const NMPlatf } int nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b); +int nm_platform_qdisc_cmp_full (const NMPlatformQdisc *a, + const NMPlatformQdisc *b, + gboolean compare_handle); int nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b); void nm_platform_link_hash_update (const NMPlatformLink *obj, NMHashState *h); |