summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-05-06 13:04:13 +0200
committerThomas Haller <thaller@redhat.com>2015-05-06 13:50:15 +0200
commitdef2937885bc8ffde79ffc125602e4747bc9045f (patch)
tree7a02c4124daa17230583378a6f04d92ccb41c81e
parent31ddde76009b308545330209ba2ac501c850c70f (diff)
downloadNetworkManager-th/platform_refact_caching-bgo747981-2.tar.gz
-rw-r--r--src/platform/nm-linux-platform.c134
1 files changed, 48 insertions, 86 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index a95137c322..2aeac45747 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -367,7 +367,6 @@ typedef struct {
typedef struct {
struct nl_sock *nlh;
- struct nl_sock *nlh_event;
NMPCache *cache;
GIOChannel *event_channel;
guint event_id;
@@ -432,63 +431,36 @@ kernel_get_object (NMPlatform *platform, struct nl_sock *sock, const NMPObject *
struct nl_object *nlo_needle;
NMPObject *obj;
int nle;
- struct nl_cache *cache;
+ const NMPClass *klass = NMP_OBJECT_GET_CLASS (needle);
- switch (NMP_OBJECT_GET_TYPE (needle)) {
- case OBJECT_TYPE_LINK:
- nle = rtnl_link_get_kernel (sock, needle->link.ifindex,
- needle->link.name[0] ? needle->link.name : NULL,
- (struct rtnl_link **) &nlo);
- switch (nle) {
- case -NLE_SUCCESS:
- _support_user_ipv6ll_detect ((struct rtnl_link *) nlo);
- obj = nmp_object_from_nl (platform, nlo, FALSE);
- _LOGD ("kernel-get-link: succeeds for ifindex=%d, name=%s: %s",
- needle->link.ifindex, needle->link.name,
- nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- return obj;
- case -NLE_NODEV:
- _LOGD ("kernel-get-link: succeeds for ifindex=%d, name=%s: NO DEVICE",
- needle->link.ifindex, needle->link.name);
+ switch (klass->obj_type) {
+ case OBJECT_TYPE_LINK: {
+ struct nl_msg *msg;
+
+ if ((nle = rtnl_link_build_get_request (needle->link.ifindex, needle->link.name[0] ? needle->link.name : NULL, &msg)))
return NULL;
- default:
- _LOGD ("kernel-get-link: fails for ifindex=%d, name=%s: %s (%d)",
- needle->link.ifindex, needle->link.name,
- nl_geterror (nle), nle);
+
+ nle = nl_send_auto(sock, msg);
+ nlmsg_free(msg);
+ if (nle < 0)
return NULL;
- }
+
+ break;
+ }
case OBJECT_TYPE_IP4_ADDRESS:
case OBJECT_TYPE_IP6_ADDRESS:
+ nl_rtgen_request (sock, RTM_GETADDR, klass->addr_family, NLM_F_DUMP);
+ break;
case OBJECT_TYPE_IP4_ROUTE:
- case OBJECT_TYPE_IP6_ROUTE:
- /* FIXME: every time we refresh *one* object, we request an
- * entire dump. */
- nle = nl_cache_alloc_and_fill (nl_cache_ops_lookup (NMP_OBJECT_GET_CLASS (needle)->nl_type),
- sock, &cache);
- if (nle) {
- _LOGE ("kernel-get-%s: fails for %s: %s (%d)",
- NMP_OBJECT_GET_CLASS (needle)->obj_type_name,
- nmp_object_to_string (needle, NMP_OBJECT_TO_STRING_ID, NULL, 0),
- nl_geterror (nle), nle);
- return NULL;
- }
+ case OBJECT_TYPE_IP6_ROUTE: {
+ struct rtmsg rhdr = {
+ .rtm_family = klass->addr_family,
+ .rtm_flags = RTM_F_CLONED,
+ };
- nlo_needle = nmp_object_to_nl (platform, needle, TRUE);
- nlo = nl_cache_search (cache, nlo_needle);
- nl_object_put (nlo_needle);
- nl_cache_free (cache);
-
- if (!nlo) {
- _LOGD ("kernel-get-%s: had no results for %s",
- NMP_OBJECT_GET_CLASS (needle)->obj_type_name,
- nmp_object_to_string (needle, NMP_OBJECT_TO_STRING_ID, NULL, 0));
- return NULL;
- }
- obj = nmp_object_from_nl (platform, nlo, FALSE);
- _LOGD ("kernel-get-%s: succeeds: %s",
- NMP_OBJECT_GET_CLASS (needle)->obj_type_name,
- nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- return obj;
+ nl_send_simple (sock, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr));
+ break;
+ }
default:
g_return_val_if_reached (NULL);
}
@@ -2080,12 +2052,16 @@ event_notification (struct nl_msg *msg, gpointer user_data)
auto_nl_object struct nl_object *nlo = NULL;
auto_nmp_obj NMPObject *obj = NULL;
int event;
+ struct nlmsghdr *msghdr;
- event = nlmsg_hdr (msg)->nlmsg_type;
+ msghdr = nlmsg_hdr (msg);
+ event = msghdr->nlmsg_type;
if (_support_kernel_extended_ifa_flags_still_undecided () && event == RTM_NEWADDR)
_support_kernel_extended_ifa_flags_detect (msg);
+ _LOGD (">>> RECEIVED message %d: seq:%d", event, msghdr->nlmsg_seq);
+
nl_msg_parse (msg, ref_object, &nlo);
if (!nlo)
return NL_OK;
@@ -2097,8 +2073,10 @@ event_notification (struct nl_msg *msg, gpointer user_data)
_support_user_ipv6ll_detect ((struct rtnl_link *) nlo);
_LOGD ("event-notification: type %d: %s", event, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- if (obj)
- do_refresh_object (platform, obj, NM_PLATFORM_REASON_EXTERNAL, TRUE, NULL);
+ if (NM_IN_SET (event, RTM_DELLINK, RTM_DELADDR, RTM_DELROUTE))
+ cache_remove_netlink (platform, obj, NULL, NULL, NM_PLATFORM_REASON_EXTERNAL);
+ else
+ cache_update_netlink (platform, obj, NULL, NULL, NM_PLATFORM_REASON_EXTERNAL);
return NL_OK;
}
@@ -4133,7 +4111,7 @@ event_handler (GIOChannel *channel,
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
int nle;
- nle = nl_recvmsgs_default (priv->nlh_event);
+ nle = nl_recvmsgs_default (priv->nlh);
if (nle < 0)
switch (nle) {
case -NLE_DUMP_INTR:
@@ -4146,17 +4124,17 @@ event_handler (GIOChannel *channel,
warning ("Too many netlink events. Need to resynchronize platform cache");
/* Drain the event queue, we've lost events and are out of sync anyway and we'd
* like to free up some space. We'll read in the status synchronously. */
- nl_socket_modify_cb (priv->nlh_event, NL_CB_VALID, NL_CB_DEFAULT, NULL, NULL);
+ nl_socket_modify_cb (priv->nlh, NL_CB_VALID, NL_CB_DEFAULT, NULL, NULL);
do {
errno = 0;
- nle = nl_recvmsgs_default (priv->nlh_event);
+ nle = nl_recvmsgs_default (priv->nlh);
/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
if (nle == 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
nle = -NLE_AGAIN;
} while (nle != -NLE_AGAIN);
- nl_socket_modify_cb (priv->nlh_event, NL_CB_VALID, NL_CB_CUSTOM, event_notification, user_data);
+ nl_socket_modify_cb (priv->nlh, NL_CB_VALID, NL_CB_CUSTOM, event_notification, user_data);
delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_ALL, NULL);
delayed_action_handle_all (platform);
break;
@@ -4168,7 +4146,7 @@ event_handler (GIOChannel *channel,
}
static struct nl_sock *
-setup_socket (gboolean event, gpointer user_data)
+setup_socket (NMPlatform *platform)
{
struct nl_sock *sock;
int nle;
@@ -4177,14 +4155,12 @@ setup_socket (gboolean event, gpointer user_data)
g_return_val_if_fail (sock, NULL);
/* Only ever accept messages from kernel */
- nle = nl_socket_modify_cb (sock, NL_CB_MSG_IN, NL_CB_CUSTOM, verify_source, user_data);
+ nle = nl_socket_modify_cb (sock, NL_CB_MSG_IN, NL_CB_CUSTOM, verify_source, platform);
g_assert (!nle);
/* Dispatch event messages (event socket only) */
- if (event) {
- nl_socket_modify_cb (sock, NL_CB_VALID, NL_CB_CUSTOM, event_notification, user_data);
- nl_socket_disable_seq_check (sock);
- }
+ nl_socket_modify_cb (sock, NL_CB_VALID, NL_CB_CUSTOM, event_notification, platform);
+ nl_socket_disable_seq_check (sock);
nle = nl_connect (sock, NETLINK_ROUTE);
g_assert (!nle);
@@ -4192,10 +4168,8 @@ setup_socket (gboolean event, gpointer user_data)
g_assert (!nle);
/* No blocking for event socket, so that we can drain it safely. */
- if (event) {
- nle = nl_socket_set_nonblocking (sock);
- g_assert (!nle);
- }
+ nle = nl_socket_set_nonblocking (sock);
+ g_assert (!nle);
return sock;
}
@@ -4332,29 +4306,24 @@ constructed (GObject *_object)
GUdevEnumerator *enumerator;
GList *devices, *iter;
- /* Initialize netlink socket for requests */
- priv->nlh = setup_socket (FALSE, platform);
- g_assert (priv->nlh);
- debug ("Netlink socket for requests established: %d", nl_socket_get_local_port (priv->nlh));
-
/* Initialize netlink socket for events */
- priv->nlh_event = setup_socket (TRUE, platform);
- g_assert (priv->nlh_event);
+ priv->nlh = setup_socket (platform);
+ g_assert (priv->nlh);
/* The default buffer size wasn't enough for the testsuites. It might just
* as well happen with NetworkManager itself. For now let's hope 128KB is
* good enough.
*/
- nle = nl_socket_set_buffer_size (priv->nlh_event, 131072, 0);
+ nle = nl_socket_set_buffer_size (priv->nlh, 131072, 0);
g_assert (!nle);
- nle = nl_socket_add_memberships (priv->nlh_event,
+ nle = nl_socket_add_memberships (priv->nlh,
RTNLGRP_LINK,
RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR,
RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV6_ROUTE,
0);
g_assert (!nle);
- debug ("Netlink socket for events established: %d", nl_socket_get_local_port (priv->nlh_event));
+ _LOGD ("Netlink socket established: %d", nl_socket_get_local_port (priv->nlh));
- priv->event_channel = g_io_channel_unix_new (nl_socket_get_fd (priv->nlh_event));
+ priv->event_channel = g_io_channel_unix_new (nl_socket_get_fd (priv->nlh));
g_io_channel_set_encoding (priv->event_channel, NULL, NULL);
g_io_channel_set_close_on_unref (priv->event_channel, TRUE);
@@ -4374,12 +4343,6 @@ constructed (GObject *_object)
priv->udev_client = g_udev_client_new (udev_subsys);
g_signal_connect (priv->udev_client, "uevent", G_CALLBACK (handle_udev_event), platform);
- /* request all IPv6 addresses (hopeing that there is at least one), to check for
- * the IFA_FLAGS attribute. */
- nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP);
- if (nle < 0)
- nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle));
-
priv->wifi_data = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) wifi_utils_deinit);
/* And read initial device list */
@@ -4429,7 +4392,6 @@ nm_linux_platform_finalize (GObject *object)
g_source_remove (priv->event_id);
g_io_channel_unref (priv->event_channel);
nl_socket_free (priv->nlh);
- nl_socket_free (priv->nlh_event);
g_object_unref (priv->udev_client);
g_hash_table_unref (priv->wifi_data);