diff options
| author | Michael Biebl <biebl@debian.org> | 2015-11-24 00:06:32 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2015-11-24 00:06:32 +0100 |
| commit | a6ece1a2aa19a6268335c87d4fdef20123dd04a5 (patch) | |
| tree | 87f1961faacdfafb1c4fee5f2feb6bcb5c06813b /src/platform | |
| parent | 81836c2d44802b4cca833d7775dd627e0797a7e2 (diff) | |
Imported Upstream version 1.0.8 upstream/1.0.8
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/Makefile.in | 1 | ||||
| -rw-r--r-- | src/platform/nm-linux-platform.c | 199 | ||||
| -rw-r--r-- | src/platform/nm-platform-utils.c | 29 | ||||
| -rw-r--r-- | src/platform/nm-platform.c | 6 | ||||
| -rw-r--r-- | src/platform/nmp-object.c | 6 | ||||
| -rw-r--r-- | src/platform/tests/Makefile.am | 1 | ||||
| -rw-r--r-- | src/platform/tests/Makefile.in | 8 | ||||
| -rw-r--r-- | src/platform/tests/test-link.c | 47 |
8 files changed, 214 insertions, 83 deletions
diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index 0616c88b..e8b73294 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -313,6 +313,7 @@ LOG_DRIVER = @LOG_DRIVER@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index cd0a4e07..2dd0b512 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -169,6 +169,9 @@ _nl_get_vtable (void) vtable.f_nl_has_capability = &_nl_f_nl_has_capability; trace ("libnl: rtnl_link_get_link_netnsid() %s", vtable.f_rtnl_link_get_link_netnsid ? "supported" : "not supported"); + + g_return_val_if_fail (vtable.handle, &vtable); + g_return_val_if_fail (vtable.handle_route, &vtable); } return &vtable; @@ -463,7 +466,7 @@ _nl_sock_request_link (NMPlatform *platform, struct nl_sock *sk, int ifindex, co g_return_val_if_fail (ifindex > 0 || name, -NLE_INVAL); - _LOGT ("sock: request-link %d%s%s%s", ifindex, name ? ", \"" : "", name ? name : "", name ? "\"" : ""); + _LOGt ("sock: request-link %d%s%s%s", ifindex, name ? ", \"" : "", name ? name : "", name ? "\"" : ""); if ((err = rtnl_link_build_get_request (ifindex, name, &msg)) < 0) return err; @@ -488,7 +491,7 @@ _nl_sock_request_all (NMPlatform *platform, struct nl_sock *sk, NMPObjectType ob klass = nmp_class_from_type (obj_type); - _LOGT ("sock: request-all-%s", klass->obj_type_name); + _LOGt ("sock: request-all-%s", klass->obj_type_name); /* reimplement * nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP); @@ -898,7 +901,7 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, gboolean *c obj = _lookup_link_cached (platform, rtnl_link_get_ifindex (rtnllink), completed_from_cache, link_cached); if (obj && obj->link.kind) { rtnl_type = obj->link.kind; - _LOGT ("link_extract_type(): complete kind from cache: ifindex=%d, kind=%s", rtnl_link_get_ifindex (rtnllink), rtnl_type); + _LOGt ("link_extract_type(): complete kind from cache: ifindex=%d, kind=%s", rtnl_link_get_ifindex (rtnllink), rtnl_type); } } if (out_kind) @@ -944,18 +947,18 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, gboolean *c gs_free char *anycast_mask = NULL; gs_free char *devtype = NULL; - if (arptype == 256) { - /* Some s390 CTC-type devices report 256 for the encapsulation type - * for some reason, but we need to call them Ethernet. - */ - if (!g_strcmp0 (driver, "ctcm")) - return NM_LINK_TYPE_ETHERNET; - } - /* Fallback OVS detection for kernel <= 3.16 */ if (nmp_utils_ethtool_get_driver_info (ifname, &driver, NULL, NULL)) { if (!g_strcmp0 (driver, "openvswitch")) return NM_LINK_TYPE_OPENVSWITCH; + + if (arptype == 256) { + /* Some s390 CTC-type devices report 256 for the encapsulation type + * for some reason, but we need to call them Ethernet. + */ + if (!g_strcmp0 (driver, "ctcm")) + return NM_LINK_TYPE_ETHERNET; + } } sysfs_path = g_strdup_printf ("/sys/class/net/%s", ifname); @@ -1009,8 +1012,8 @@ _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_ob nm_assert (memcmp (obj, ((char [sizeof (NMPObjectLink)]) { 0 }), sizeof (NMPObjectLink)) == 0); - if (_LOGT_ENABLED () && !NM_IN_SET (rtnl_link_get_family (nlo), AF_UNSPEC, AF_BRIDGE)) - _LOGT ("netlink object for ifindex %d has unusual family %d", rtnl_link_get_ifindex (nlo), rtnl_link_get_family (nlo)); + if (_LOGt_ENABLED () && !NM_IN_SET (rtnl_link_get_family (nlo), AF_UNSPEC, AF_BRIDGE)) + _LOGt ("netlink object for ifindex %d has unusual family %d", rtnl_link_get_ifindex (nlo), rtnl_link_get_family (nlo)); obj->ifindex = rtnl_link_get_ifindex (nlo); @@ -1132,6 +1135,7 @@ _rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr, gint32 *out guint32 last_update_time = rtnl_addr_get_last_update_time ((struct rtnl_addr *) rtnladdr); struct timespec tp; gint64 now_nl, now_nm, result; + int err; /* timestamp is unset. Default to 1. */ if (!last_update_time) { @@ -1142,7 +1146,8 @@ _rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr, gint32 *out /* do all the calculations in milliseconds scale */ - clock_gettime (CLOCK_MONOTONIC, &tp); + err = clock_gettime (CLOCK_MONOTONIC, &tp); + g_assert (err == 0); now_nm = nm_utils_get_monotonic_timestamp_ms (); now_nl = (((gint64) tp.tv_sec) * ((gint64) 1000)) + (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000)); @@ -1466,7 +1471,7 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cach klass = NMP_OBJECT_GET_CLASS (obj); - _LOGT ("emit signal %s %s: %s (%ld)", + _LOGt ("emit signal %s %s: %s (%ld)", klass->signal_type, nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op), nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0), @@ -1523,8 +1528,8 @@ delayed_action_to_string (DelayedActionType action_type) } } -#define _LOGT_delayed_action(action_type, arg, operation) \ - _LOGT ("delayed-action: %s %s (%d) [%p / %d]", ""operation, delayed_action_to_string (action_type), (int) action_type, arg, GPOINTER_TO_INT (arg)) +#define _LOGt_delayed_action(action_type, arg, operation) \ + _LOGt ("delayed-action: %s %s (%d) [%p / %d]", ""operation, delayed_action_to_string (action_type), (int) action_type, arg, GPOINTER_TO_INT (arg)) static void delayed_action_handle_MASTER_CONNECTED (NMPlatform *platform, int master_ifindex) @@ -1579,7 +1584,7 @@ delayed_action_handle_one (NMPlatform *platform) priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_MASTER_CONNECTED; nm_assert (_nm_utils_ptrarray_find_first (priv->delayed_action.list_master_connected->pdata, priv->delayed_action.list_master_connected->len, user_data) < 0); - _LOGT_delayed_action (DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle"); + _LOGt_delayed_action (DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle"); delayed_action_handle_MASTER_CONNECTED (platform, GPOINTER_TO_INT (user_data)); return TRUE; } @@ -1588,7 +1593,7 @@ delayed_action_handle_one (NMPlatform *platform) /* Next we prefer read-netlink, because the buffer size is limited and we want to process events * from netlink early. */ if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_READ_NETLINK)) { - _LOGT_delayed_action (DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle"); + _LOGt_delayed_action (DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle"); priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_READ_NETLINK; delayed_action_handle_READ_NETLINK (platform); return TRUE; @@ -1601,10 +1606,10 @@ delayed_action_handle_one (NMPlatform *platform) priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL; - if (_LOGT_ENABLED ()) { + if (_LOGt_ENABLED ()) { for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) { if (NM_FLAGS_HAS (flags, iflags)) - _LOGT_delayed_action (iflags, NULL, "handle"); + _LOGt_delayed_action (iflags, NULL, "handle"); } } @@ -1617,11 +1622,11 @@ delayed_action_handle_one (NMPlatform *platform) user_data = priv->delayed_action.list_refresh_link->pdata[0]; g_ptr_array_remove_index_fast (priv->delayed_action.list_refresh_link, 0); - if (priv->delayed_action.list_master_connected->len == 0) + if (priv->delayed_action.list_refresh_link->len == 0) priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; nm_assert (_nm_utils_ptrarray_find_first (priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data) < 0); - _LOGT_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle"); + _LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle"); delayed_action_handle_REFRESH_LINK (platform, GPOINTER_TO_INT (user_data)); @@ -1653,6 +1658,33 @@ delayed_action_handle_idle (gpointer user_data) } static void +delayed_action_clear_REFRESH_LINK (NMPlatform *platform, int ifindex) +{ + NMLinuxPlatformPrivate *priv; + gssize idx; + gpointer user_data; + + if (ifindex <= 0) + return; + + priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) + return; + + user_data = GINT_TO_POINTER (ifindex); + + idx = _nm_utils_ptrarray_find_first (priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data); + if (idx < 0) + return; + + _LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "clear"); + + g_ptr_array_remove_index_fast (priv->delayed_action.list_refresh_link, idx); + if (priv->delayed_action.list_refresh_link->len == 0) + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; +} + +static void delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gpointer user_data) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); @@ -1673,10 +1705,10 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp priv->delayed_action.flags |= action_type; - if (_LOGT_ENABLED ()) { + if (_LOGt_ENABLED ()) { for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) { if (NM_FLAGS_HAS (action_type, iflags)) - _LOGT_delayed_action (iflags, user_data, "schedule"); + _LOGt_delayed_action (iflags, user_data, "schedule"); } } @@ -1694,7 +1726,7 @@ cache_prune_candidates_record_all (NMPlatform *platform, NMPObjectType obj_type) priv->prune_candidates = nmp_cache_lookup_all_to_hash (priv->cache, nmp_cache_id_init_object_type (NMP_CACHE_ID_STATIC, obj_type, FALSE), priv->prune_candidates); - _LOGT ("cache-prune: record %s (now %u candidates)", nmp_class_from_type (obj_type)->obj_type_name, + _LOGt ("cache-prune: record %s (now %u candidates)", nmp_class_from_type (obj_type)->obj_type_name, priv->prune_candidates ? g_hash_table_size (priv->prune_candidates) : 0); } @@ -1711,8 +1743,8 @@ cache_prune_candidates_record_one (NMPlatform *platform, NMPObject *obj) if (!priv->prune_candidates) priv->prune_candidates = g_hash_table_new_full (NULL, NULL, (GDestroyNotify) nmp_object_unref, NULL); - if (_LOGT_ENABLED () && !g_hash_table_contains (priv->prune_candidates, obj)) - _LOGT ("cache-prune: record-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + if (_LOGt_ENABLED () && !g_hash_table_contains (priv->prune_candidates, obj)) + _LOGt ("cache-prune: record-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); g_hash_table_add (priv->prune_candidates, nmp_object_ref (obj)); } @@ -1726,8 +1758,8 @@ cache_prune_candidates_drop (NMPlatform *platform, const NMPObject *obj) priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); if (priv->prune_candidates) { - if (_LOGT_ENABLED () && g_hash_table_contains (priv->prune_candidates, obj)) - _LOGT ("cache-prune: drop-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + if (_LOGt_ENABLED () && g_hash_table_contains (priv->prune_candidates, obj)) + _LOGt ("cache-prune: drop-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); g_hash_table_remove (priv->prune_candidates, obj); } } @@ -1752,7 +1784,7 @@ cache_prune_candidates_prune (NMPlatform *platform) while (g_hash_table_iter_next (&iter, (gpointer *)&obj, NULL)) { auto_nmp_obj NMPObject *obj_cache = NULL; - _LOGT ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + _LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); cache_op = nmp_cache_remove (priv->cache, obj, TRUE, &obj_cache, &was_visible, cache_pre_hook, platform); do_emit_signal (platform, obj_cache, cache_op, was_visible, NM_PLATFORM_REASON_INTERNAL); } @@ -1786,7 +1818,7 @@ cache_delayed_deletion_prune (NMPlatform *platform) if (prune_list) { for (i = 0; i < prune_list->len; i++) { obj = prune_list->pdata[i]; - _LOGT ("delayed-deletion: delete %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + _LOGt ("delayed-deletion: delete %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); cache_remove_netlink (platform, obj, NULL, NULL, NM_PLATFORM_REASON_EXTERNAL); } g_ptr_array_unref (prune_list); @@ -1813,7 +1845,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP nm_assert (klass == (new ? NMP_OBJECT_GET_CLASS (new) : NMP_OBJECT_GET_CLASS (old))); - _LOGT ("update-cache-%s: %s: %s%s%s", + _LOGt ("update-cache-%s: %s: %s%s%s", klass->obj_type_name, (ops_type == NMP_CACHE_OPS_UPDATED ? "UPDATE" @@ -1869,6 +1901,37 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP } } { + int ifindex = -1; + + /* removal of a link could be caused by moving the link to another netns. + * In this case, we potentially have to update other links that have this link as parent. + * Currently, kernel misses to sent us a notification in this case (rh #1262908). */ + + if ( ops_type == NMP_CACHE_OPS_REMOVED + && old /* <-- nonsensical, make coverity happy */ + && old->_link.netlink.is_in_netlink) + ifindex = old->link.ifindex; + else if ( ops_type == NMP_CACHE_OPS_UPDATED + && old && new /* <-- nonsensical, make coverity happy */ + && old->_link.netlink.is_in_netlink + && !new->_link.netlink.is_in_netlink) + ifindex = new->link.ifindex; + + if (ifindex > 0) { + const NMPlatformLink *const *links; + + links = cache_lookup_all_objects (NMPlatformLink, platform, NMP_OBJECT_TYPE_LINK, FALSE); + if (links) { + for (; *links; links++) { + const NMPlatformLink *l = (*links); + + if (l->parent == ifindex) + delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (l->ifindex)); + } + } + } + } + { /* if a link goes down, we must refresh routes */ if ( ops_type == NMP_CACHE_OPS_UPDATED && old && new /* <-- nonsensical, make coverity happy */ @@ -1974,7 +2037,7 @@ _new_sequence_number (NMPlatform *platform, guint32 seq) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - _LOGT ("_new_sequence_number(): new sequence number %u", seq); + _LOGt ("_new_sequence_number(): new sequence number %u", seq); priv->nlh_seq_expect = seq; } @@ -1985,7 +2048,7 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name, gboolean h NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); guint32 seq; - _LOGT ("do_request_link (%d,%s)", ifindex, name ? name : ""); + _LOGt ("do_request_link (%d,%s)", ifindex, name ? name : ""); if (ifindex > 0) { NMPObject *obj; @@ -1993,7 +2056,7 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name, gboolean h cache_prune_candidates_record_one (platform, (NMPObject *) nmp_cache_lookup_link (priv->cache, ifindex)); obj = nmp_object_new_link (ifindex); - _LOGT ("delayed-deletion: protect object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + _LOGt ("delayed-deletion: protect object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); g_hash_table_insert (priv->delayed_deletion, obj, NULL); } @@ -2038,9 +2101,11 @@ do_request_all (NMPlatform *platform, DelayedActionType action_type, gboolean ha /* clear any delayed action that request a refresh of this object type. */ priv->delayed_action.flags &= ~iflags; + _LOGt_delayed_action (iflags, NULL, "handle (do-request-all)"); if (obj_type == NMP_OBJECT_TYPE_LINK) { priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0); + _LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, NULL, "clear (do-request-all)"); } event_handler_read_netlink_all (platform, FALSE); @@ -2081,7 +2146,7 @@ kernel_add_object (NMPlatform *platform, NMPObjectType obj_type, const struct nl g_return_val_if_reached (-NLE_INVAL); } - _LOGT ("kernel-add-%s: returned %s (%d)", + _LOGt ("kernel-add-%s: returned %s (%d)", nmp_class_from_type (obj_type)->obj_type_name, nl_geterror (nle), -nle); switch (nle) { @@ -2125,20 +2190,20 @@ kernel_delete_object (NMPlatform *platform, NMPObjectType object_type, const str case -NLE_SUCCESS: return NLE_SUCCESS; case -NLE_OBJ_NOTFOUND: - _LOGT ("kernel-delete-%s: failed with \"%s\" (%d), meaning the object was already removed", + _LOGt ("kernel-delete-%s: failed with \"%s\" (%d), meaning the object was already removed", nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle); return -NLE_SUCCESS; case -NLE_FAILURE: if (object_type == NMP_OBJECT_TYPE_IP6_ADDRESS) { /* On RHEL7 kernel, deleting a non existing address fails with ENXIO (which libnl maps to NLE_FAILURE) */ - _LOGT ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed", + _LOGt ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed", nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle); return NLE_SUCCESS; } break; case -NLE_NOADDR: if (object_type == NMP_OBJECT_TYPE_IP4_ADDRESS || object_type == NMP_OBJECT_TYPE_IP6_ADDRESS) { - _LOGT ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed", + _LOGt ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed", nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle); return -NLE_SUCCESS; } @@ -2146,7 +2211,7 @@ kernel_delete_object (NMPlatform *platform, NMPObjectType object_type, const str default: break; } - _LOGT ("kernel-delete-%s: failed with %s (%d)", + _LOGt ("kernel-delete-%s: failed with %s (%d)", nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle); return nle; } @@ -2183,7 +2248,7 @@ kernel_change_link (NMPlatform *platform, struct rtnl_link *nlo, gboolean *compl obj_cache = nmp_cache_lookup_link (priv->cache, ifindex); if (!obj_cache || !obj_cache->_link.netlink.is_in_netlink) { - _LOGT ("kernel-change-link: failure changing link %d: cannot complete link", ifindex); + _LOGt ("kernel-change-link: failure changing link %d: cannot complete link", ifindex); *complete_from_cache = FALSE; return -NLE_INVAL; } @@ -2204,7 +2269,7 @@ kernel_change_link (NMPlatform *platform, struct rtnl_link *nlo, gboolean *compl nle = rtnl_link_build_add_request (nlo, nlflags, &msg); if (nle < 0) { - _LOGT ("kernel-change-link: failure changing link %d: cannot construct message (%s, %d)", + _LOGt ("kernel-change-link: failure changing link %d: cannot construct message (%s, %d)", ifindex, nl_geterror (nle), -nle); return nle; } @@ -2234,18 +2299,18 @@ errout: */ switch (nle) { case -NLE_SUCCESS: - _LOGT ("kernel-change-link: success changing link %d", ifindex); + _LOGt ("kernel-change-link: success changing link %d", ifindex); break; case -NLE_EXIST: - _LOGT ("kernel-change-link: success changing link %d: %s (%d)", + _LOGt ("kernel-change-link: success changing link %d: %s (%d)", ifindex, nl_geterror (nle), -nle); break; case -NLE_OBJ_NOTFOUND: - _LOGT ("kernel-change-link: failure changing link %d: firmware not found (%s, %d)", + _LOGt ("kernel-change-link: failure changing link %d: firmware not found (%s, %d)", ifindex, nl_geterror (nle), -nle); break; default: - _LOGT ("kernel-change-link: failure changing link %d: netlink error (%s, %d)", + _LOGt ("kernel-change-link: failure changing link %d: netlink error (%s, %d)", ifindex, nl_geterror (nle), -nle); break; } @@ -2277,13 +2342,13 @@ event_seq_check (struct nl_msg *msg, gpointer user_data) priv->nlh_seq_last = hdr->nlmsg_seq; if (priv->nlh_seq_expect == 0) - _LOGT ("event_seq_check(): seq %u received (not waited)", hdr->nlmsg_seq); + _LOGt ("event_seq_check(): seq %u received (not waited)", hdr->nlmsg_seq); else if (hdr->nlmsg_seq == priv->nlh_seq_expect) { - _LOGT ("event_seq_check(): seq %u received", hdr->nlmsg_seq); + _LOGt ("event_seq_check(): seq %u received", hdr->nlmsg_seq); priv->nlh_seq_expect = 0; } else - _LOGT ("event_seq_check(): seq %u received (wait for %u)", hdr->nlmsg_seq, priv->nlh_seq_last); + _LOGt ("event_seq_check(): seq %u received (wait for %u)", hdr->nlmsg_seq, priv->nlh_seq_last); return NL_OK; } @@ -2291,7 +2356,7 @@ event_seq_check (struct nl_msg *msg, gpointer user_data) static int event_err (struct sockaddr_nl *nla, struct nlmsgerr *nlerr, gpointer platform) { - _LOGT ("event_err(): error from kernel: %s (%d) for request %d", + _LOGt ("event_err(): error from kernel: %s (%d) for request %d", strerror (nlerr ? -nlerr->error : 0), nlerr ? -nlerr->error : 0, NM_LINUX_PLATFORM_GET_PRIVATE (platform)->nlh_seq_last); @@ -2333,13 +2398,13 @@ event_notification (struct nl_msg *msg, gpointer user_data) /* The event notifies about a deleted object. We don't need to initialize all the * fields of the nmp-object. Shortcut nmp_object_from_nl(). */ obj = nmp_object_from_nl (platform, nlo, TRUE, TRUE); - _LOGD ("event-notification: %s, seq %u: %s", + _LOGT ("event-notification: %s, seq %u: %s", _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); break; default: obj = nmp_object_from_nl (platform, nlo, FALSE, TRUE); - _LOGD ("event-notification: %s, seq %u: %s", + _LOGT ("event-notification: %s, seq %u: %s", _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); break; @@ -2351,12 +2416,14 @@ event_notification (struct nl_msg *msg, gpointer user_data) switch (msghdr->nlmsg_type) { case RTM_NEWLINK: - if ( NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK - && g_hash_table_lookup (priv->delayed_deletion, obj) != NULL) { - /* the object is scheduled for delayed deletion. Replace that object - * by clearing the value from priv->delayed_deletion. */ - _LOGT ("delayed-deletion: clear delayed deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); - g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), NULL); + if (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK) { + if (g_hash_table_lookup (priv->delayed_deletion, obj) != NULL) { + /* the object is scheduled for delayed deletion. Replace that object + * by clearing the value from priv->delayed_deletion. */ + _LOGt ("delayed-deletion: clear delayed deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), NULL); + } + delayed_action_clear_REFRESH_LINK (platform, obj->link.ifindex); } /* fall-through */ case RTM_NEWADDR: @@ -2369,7 +2436,7 @@ event_notification (struct nl_msg *msg, gpointer user_data) && g_hash_table_contains (priv->delayed_deletion, obj)) { /* We sometimes receive spurious RTM_DELLINK events. In this case, we want to delay * the deletion of the object until later. */ - _LOGT ("delayed-deletion: delay deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + _LOGt ("delayed-deletion: delay deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), nmp_object_ref (obj)); break; } @@ -2681,7 +2748,7 @@ do_add_link (NMPlatform *platform, const char *name, const struct rtnl_link *nlo * link so that it is in the cache. A better solution would be to do everything * via one netlink socket. */ if (!nmp_cache_lookup_link_full (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, 0, obj_needle.link.name, FALSE, NM_LINK_TYPE_NONE, NULL, NULL)) { - _LOGT ("do-add-link: reload: the added link is not yet ready. Request %s", obj_needle.link.name); + _LOGt ("do-add-link: reload: the added link is not yet ready. Request %s", obj_needle.link.name); do_request_link (platform, 0, obj_needle.link.name, TRUE); } @@ -2733,7 +2800,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, const struct nl /* FIXME: instead of re-requesting the added object, add it via nlh_event * so that the events are in sync. */ if (!nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, obj_id)) { - _LOGT ("do-add-%s: reload: the added object is not yet ready. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + _LOGt ("do-add-%s: reload: the added object is not yet ready. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0)); do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id), TRUE); } @@ -2771,12 +2838,12 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, const struct nl obj = nmp_cache_lookup_link_full (priv->cache, obj_id->link.ifindex, obj_id->link.ifindex <= 0 && obj_id->link.name[0] ? obj_id->link.name : NULL, FALSE, NM_LINK_TYPE_NONE, NULL, NULL); if (obj && obj->_link.netlink.is_in_netlink) { - _LOGT ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + _LOGt ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0)); do_request_link (platform, obj_id->link.ifindex, obj_id->link.name, TRUE); } } else { if (nmp_cache_lookup_obj (priv->cache, obj_id)) { - _LOGT ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + _LOGt ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0)); do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id), TRUE); } } @@ -4621,7 +4688,7 @@ event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks) if (!wait_for_acks || priv->nlh_seq_expect == 0) { if (wait_for_seq) - _LOGT ("read-netlink-all: ACK for sequence number %u received", priv->nlh_seq_expect); + _LOGt ("read-netlink-all: ACK for sequence number %u received", priv->nlh_seq_expect); return any; } @@ -4629,7 +4696,7 @@ event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks) if (wait_for_seq != priv->nlh_seq_expect) { /* We are waiting for a new sequence number (or we will wait for the first time). * Reset/start counting the overall wait time. */ - _LOGT ("read-netlink-all: wait for ACK for sequence number %u...", priv->nlh_seq_expect); + _LOGt ("read-netlink-all: wait for ACK for sequence number %u...", priv->nlh_seq_expect); wait_for_seq = priv->nlh_seq_expect; timestamp = now; timeout = TIMEOUT; diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index b7f0947e..e9b8d4be 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -139,21 +139,31 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname, guint8 *buf, size_t *length) { - gs_free struct ethtool_perm_addr *epaddr = NULL; + struct { + struct ethtool_perm_addr e; + guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1]; + } edata; + guint zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 }; if (!ifname) return FALSE; - epaddr = g_malloc0 (sizeof (*epaddr) + NM_UTILS_HWADDR_LEN_MAX); - epaddr->cmd = ETHTOOL_GPERMADDR; - epaddr->size = NM_UTILS_HWADDR_LEN_MAX; + memset (&edata, 0, sizeof (edata)); + edata.e.cmd = ETHTOOL_GPERMADDR; + edata.e.size = NM_UTILS_HWADDR_LEN_MAX; - if (!ethtool_get (ifname, epaddr)) + if (!ethtool_get (ifname, &edata.e)) return FALSE; - g_assert (epaddr->size <= NM_UTILS_HWADDR_LEN_MAX); - memcpy (buf, epaddr->data, epaddr->size); - *length = epaddr->size; + g_assert (edata.e.size <= NM_UTILS_HWADDR_LEN_MAX); + + /* Some drivers might return a permanent address of all zeros. + * Reject that (rh#1264024) */ + if (memcmp (edata.e.data, zeros, edata.e.size) == 0) + return FALSE; + + memcpy (buf, edata.e.data, edata.e.size); + *length = edata.e.size; return TRUE; } @@ -269,6 +279,9 @@ nmp_utils_ethtool_set_wake_on_lan (const char *ifname, { struct ethtool_wolinfo wol_info = { }; + if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) + return TRUE; + nm_log_dbg (LOGD_PLATFORM, "setting Wake-on-LAN options 0x%x, password '%s'", (unsigned int) wol, wol_password); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index fcb5b061..9948ac8b 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -427,7 +427,7 @@ nm_platform_link_get_all (NMPlatform *self) for (i = 0; i < links->len; i++) { item = &g_array_index (links, NMPlatformLink, i); - _LOGT ("link-get: %3d: %s", i, nm_platform_link_to_string (item)); + _LOGt ("link-get: %3d: %s", i, nm_platform_link_to_string (item)); nm_assert (item->ifindex > 0 && !g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))); @@ -483,7 +483,7 @@ nm_platform_link_get_all (NMPlatform *self) if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))) continue; - _LOGT ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item)); + _LOGt ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item)); g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_array_index (result, NMPlatformLink, j++) = *item; @@ -496,7 +496,7 @@ nm_platform_link_get_all (NMPlatform *self) * This can happen for veth pairs where each peer is parent of the other end. */ item = &g_array_index (links, NMPlatformLink, first_idx); - _LOGT ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item)); + _LOGt ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item)); g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_array_index (result, NMPlatformLink, j++) = *item; diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 7fe2d7d3..eb6bfc3a 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -178,7 +178,7 @@ nmp_object_ref (NMPObject *obj) g_return_val_if_fail (obj->_ref_count != NMP_REF_COUNT_STACKINIT, NULL); obj->_ref_count++; - _LOGT (obj, "ref: %d", obj->_ref_count); + _LOGt (obj, "ref: %d", obj->_ref_count); return obj; } @@ -189,7 +189,7 @@ nmp_object_unref (NMPObject *obj) if (obj) { g_return_if_fail (obj->_ref_count > 0); g_return_if_fail (obj->_ref_count != NMP_REF_COUNT_STACKINIT); - _LOGT (obj, "%s: %d", + _LOGt (obj, "%s: %d", obj->_ref_count <= 1 ? "destroy" : "unref", obj->_ref_count - 1); if (--obj->_ref_count <= 0) { @@ -221,7 +221,7 @@ _nmp_object_new_from_class (const NMPClass *klass) obj = g_slice_alloc0 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object)); obj->_class = klass; obj->_ref_count = 1; - _LOGT (obj, "new"); + _LOGt (obj, "new"); return obj; } diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am index 54844ec1..35aa098a 100644 --- a/src/platform/tests/Makefile.am +++ b/src/platform/tests/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = \ -I${top_srcdir} \ -I${top_srcdir}/include \ + -I${top_builddir}/include \ -I${top_srcdir}/src \ -I${top_builddir}/src \ -I${top_srcdir}/libnm-core \ diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in index a9333539..f45f3a9c 100644 --- a/src/platform/tests/Makefile.in +++ b/src/platform/tests/Makefile.in @@ -616,6 +616,7 @@ LOG_DRIVER = @LOG_DRIVER@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ @@ -757,9 +758,10 @@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include \ - -I${top_srcdir}/src -I${top_builddir}/src \ - -I${top_srcdir}/libnm-core -I${top_builddir}/libnm-core \ - -I${srcdir}/.. -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -I${top_builddir}/include -I${top_srcdir}/src \ + -I${top_builddir}/src -I${top_srcdir}/libnm-core \ + -I${top_builddir}/libnm-core -I${srcdir}/.. \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \ $(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(am__append_1) diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index ce371b75..f9645d85 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -118,6 +118,41 @@ software_add (NMLinkType link_type, const char *name) } static void +test_link_changed_signal_cb (NMPlatform *platform, + NMPObjectType obj_type, + int ifindex, + const NMPlatformIP4Route *route, + NMPlatformSignalChangeType change_type, + NMPlatformReason reason, + gboolean *p_test_link_changed_signal_arg) +{ + /* test invocation of platform signals with multiple listeners + * connected to the signal. Platform signals have enum-typed + * arguments and there seem to be an issue with invoking such + * signals on s390x and ppc64 archs. + * https://bugzilla.redhat.com/show_bug.cgi?id=1260577 + * + * As the test shows, the failure is not reproducible for + * platform signals. + */ + g_assert (NM_IS_PLATFORM (platform)); + g_assert (platform == NM_PLATFORM_GET); + + g_assert (ifindex > 0); + g_assert (route); + + g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_LINK); + + g_assert_cmpint ((gint64) change_type, !=, (gint64) 0); + g_assert_cmpint (change_type, !=, NM_PLATFORM_SIGNAL_NONE); + + g_assert_cmpint ((gint64) reason, !=, (gint64) 0); + g_assert_cmpint (reason, !=, NM_PLATFORM_REASON_NONE); + + *p_test_link_changed_signal_arg = TRUE; +} + +static void test_slave (int master, int type, SignalData *master_changed) { int ifindex; @@ -125,6 +160,8 @@ test_slave (int master, int type, SignalData *master_changed) SignalData *link_changed, *link_removed; char *value; NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, master); + gboolean test_link_changed_signal_arg1; + gboolean test_link_changed_signal_arg2; g_assert (NM_IN_SET (link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE)); @@ -158,11 +195,21 @@ test_slave (int master, int type, SignalData *master_changed) else g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); + test_link_changed_signal_arg1 = FALSE; + test_link_changed_signal_arg2 = FALSE; + g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg1); + g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg2); + /* Set master up */ g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, master, NULL)); g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, master)); accept_signals (master_changed, 1, 2); + g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg1); + g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg2); + g_assert (test_link_changed_signal_arg1); + g_assert (test_link_changed_signal_arg2); + /* Master with a disconnected slave is disconnected * * For some reason, bonding and teaming slaves are automatically set up. We |