platform: merge branch 'th/platform-recvmsg-enobufs'

This commit is contained in:
Thomas Haller 2016-01-25 15:49:31 +01:00
commit 583c759dd7
10 changed files with 64 additions and 42 deletions

View file

@ -457,7 +457,7 @@ create_and_realize (NMDevice *device,
g_assert (iface);
plerr = nm_platform_link_bond_add (NM_PLATFORM_GET, iface, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create bond interface '%s' for '%s': %s",
iface,

View file

@ -405,7 +405,7 @@ create_and_realize (NMDevice *device,
hwaddr ? mac_address : NULL,
hwaddr ? ETH_ALEN : 0,
out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create bridge interface '%s' for '%s': %s",
iface,

View file

@ -272,7 +272,7 @@ create_and_realize (NMDevice *device,
}
plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, parent_ifindex, p_key, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
nm_device_get_iface (device),

View file

@ -661,7 +661,7 @@ create_and_realize (NMDevice *device,
}
plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create GRE interface '%s' for '%s': %s",
iface,
@ -687,7 +687,7 @@ create_and_realize (NMDevice *device,
lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel);
plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create SIT interface '%s' for '%s': %s",
iface,
@ -713,7 +713,7 @@ create_and_realize (NMDevice *device,
lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel);
plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create IPIP interface '%s' for '%s': %s",
iface,
@ -742,7 +742,7 @@ create_and_realize (NMDevice *device,
lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6;
plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create IPIP interface '%s' for '%s': %s",
iface,

View file

@ -238,7 +238,7 @@ create_and_realize (NMDevice *device,
lnk.tap = nm_setting_macvlan_get_tap (s_macvlan);
plerr = nm_platform_link_macvlan_add (NM_PLATFORM_GET, iface, parent_ifindex, &lnk, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create %s interface '%s' for '%s': %s",
lnk.tap ? "macvtap" : "macvlan",

View file

@ -222,7 +222,7 @@ create_and_realize (NMDevice *device,
nm_setting_tun_get_vnet_hdr (s_tun),
nm_setting_tun_get_multi_queue (s_tun),
out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create TUN/TAP interface '%s' for '%s': %s",
iface,

View file

@ -237,7 +237,7 @@ create_and_realize (NMDevice *device,
vlan_id,
nm_setting_vlan_get_flags (s_vlan),
out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create VLAN interface '%s' for '%s': %s",
iface,

View file

@ -224,7 +224,7 @@ create_and_realize (NMDevice *device,
props.l3miss = nm_setting_vxlan_get_l3_miss (s_vxlan);
plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, iface, &props, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create VXLAN interface '%s' for '%s': %s",
iface,

View file

@ -673,7 +673,7 @@ create_and_realize (NMDevice *device,
NMPlatformError plerr;
plerr = nm_platform_link_team_add (NM_PLATFORM_GET, iface, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create team master interface '%s' for '%s': %s",
iface,

View file

@ -58,6 +58,9 @@
#define VLAN_FLAG_MVRP 0x8
/* nm-internal error codes for libnl. Make sure they don't overlap. */
#define _NLE_NM_NOBUFS 500
/*********************************************************************************************/
#define IFQDISCSIZ 32
@ -2804,13 +2807,23 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
static void
delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
WaitForNlResponseResult result)
WaitForNlResponseResult fallback_result)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
while (priv->delayed_action.list_wait_for_nl_response->len > 0)
delayed_action_wait_for_nl_response_complete (platform, priv->delayed_action.list_wait_for_nl_response->len - 1, result);
while (priv->delayed_action.list_wait_for_nl_response->len > 0) {
const DelayedActionWaitForNlResponseData *data;
guint idx = priv->delayed_action.list_wait_for_nl_response->len - 1;
WaitForNlResponseResult r;
data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, idx);
/* prefer the result that we already have. */
r = data->seq_result ? : fallback_result;
delayed_action_wait_for_nl_response_complete (platform, idx, r);
}
}
nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0);
@ -3461,7 +3474,7 @@ event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResu
}
static void
event_valid_msg (NMPlatform *platform, struct nl_msg *msg)
event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_events)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_auto_nmpobj NMPObject *obj = NULL;
@ -3477,6 +3490,9 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg)
if (_support_kernel_extended_ifa_flags_still_undecided () && msghdr->nlmsg_type == RTM_NEWADDR)
_support_kernel_extended_ifa_flags_detect (msg);
if (!handle_events)
return;
if (NM_IN_SET (msghdr->nlmsg_type, RTM_DELLINK, RTM_DELADDR, RTM_DELROUTE)) {
/* The event notifies about a deleted object. We don't need to initialize all
* fields of the object. */
@ -5517,24 +5533,30 @@ continue_reading:
errno = 0;
n = nl_recv (sk, &nla, &buf, &creds);
/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
if (n == 0 && errno == EAGAIN) {
/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
* workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
n = -NLE_AGAIN;
switch (n) {
case 0:
/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
if (errno == EAGAIN) {
/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
* workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
n = -NLE_AGAIN;
}
break;
case -NLE_NOMEM:
if (errno == ENOBUFS) {
/* we are very much interested in a overrun of the receive buffer.
* nl_recv() maps all kinds of errors to NLE_NOMEM, so check also
* for errno explicitly. And if so, hack our own return code to signal
* the overrun. */
n = -_NLE_NM_NOBUFS;
}
break;
}
if (n <= 0)
return n;
if (!handle_events) {
/* we read until failure or there is nothing to read (EAGAIN). */
g_clear_pointer (&buf, free);
g_clear_pointer (&creds, free);
goto continue_reading;
}
hdr = (struct nlmsghdr *) buf;
while (nlmsg_ok (hdr, n)) {
gboolean abort_parsing = FALSE;
@ -5627,7 +5649,9 @@ continue_reading:
/* Valid message (not checking for MULTIPART bit to
* get along with broken kernels. NL_SKIP has no
* effect on this. */
event_valid_msg (platform, msg);
event_valid_msg (platform, msg, handle_events);
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
}
@ -5651,6 +5675,12 @@ continue_reading:
goto continue_reading;
}
stop:
if (!handle_events) {
/* when we don't handle events, we want to drain all messages from the socket
* without handling the messages (but still check for sequence numbers).
* Repeat reading. */
goto continue_reading;
}
err = 0;
out:
nlmsg_free (msg);
@ -5696,12 +5726,10 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
case -NLE_DUMP_INTR:
_LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
break;
case -NLE_NOMEM:
case -_NLE_NM_NOBUFS:
_LOGI ("netlink: read: 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. */
delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
event_handler_recvmsgs (platform, FALSE);
delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
delayed_action_schedule (platform,
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
@ -5926,14 +5954,8 @@ constructed (GObject *_object)
nle = nl_socket_set_nonblocking (priv->nlh);
g_assert (!nle);
/* 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.
*
* FIXME: it's unclear that this is still actually needed. The testsuite
* certainly doesn't fail for me. Maybe it can be removed.
*/
nle = nl_socket_set_buffer_size (priv->nlh, 131072, 0);
/* use 8 MB for receive socket kernel queue. */
nle = nl_socket_set_buffer_size (priv->nlh, 8*1024*1024, 0);
g_assert (!nle);
nle = nl_socket_add_memberships (priv->nlh,