[patch libteam] libteam: resynchronize ifinfo after lost RTNLGRP_LINK notifications
by Antti Tiainen
When there's a large number of interfaces (e.g. vlans), teamd loses
link notifications as it cannot read them as fast as kernel is
broadcasting them. This often prevents teamd starting properly if
started concurrently when other links are being set up. It can also
fail when it's up and running, especially in the cases where the team
device itself has a lot of vlans under it. It never checks the return
value of nl_recvmsgs_default() and doesn't know if it just missed
important/critical events.
As said in netlink(7), it's up to userspace to resynchronize with
kernel when getting ENOBUFS. Unfortunately there's no way to know
what events were lost and ports might not be linked in libteam side
due to lost events, so all ifinfo list must be refreshed.
Checks now return value of nl_recvmsgs_default() for event socket. In
case of ENOBUFS (which libnl nicely changes to ENOMEM), refreshes
all ifinfo list. get_ifinfo_list() also checks now for removed interfaces
in case of missed dellink event. Currently all TEAM_IFINFO_CHANGE
handlers processed events one by one, so it had to be changed to support
multiple ifinfo changes. For this, ifinfo changed flags are cleared
and removed entries destroyed only after all handlers have been called.
Also, increased nl_cli.sock_event receive buffers to 96k like all other
sockets. Added possibility to change this via environment variable.
Signed-off-by: Antti Tiainen <atiainen(a)forcepoint.com>
---
libteam/ifinfo.c | 31 +++++++++++++++++++++++--------
libteam/libteam.c | 40 +++++++++++++++++++++++++++++++++++++++-
libteam/team_private.h | 3 +++
3 files changed, 65 insertions(+), 9 deletions(-)
diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c
index 72155ae..9330a4f 100644
--- a/libteam/ifinfo.c
+++ b/libteam/ifinfo.c
@@ -72,6 +72,9 @@ struct team_ifinfo {
#define CHANGED_PHYS_PORT_ID (1 << 5)
#define CHANGED_PHYS_PORT_ID_LEN (1 << 6)
#define CHANGED_ADMIN_STATE (1 << 7)
+/* This is only used when tagging interfaces for finding
+ removed, and thus not included to CHANGED_ANY. */
+#define CHANGED_REFRESHING (1 << 8)
#define CHANGED_ANY (CHANGED_REMOVED | CHANGED_HWADDR | \
CHANGED_HWADDR_LEN | CHANGED_IFNAME | \
CHANGED_MASTER_IFINDEX | CHANGED_PHYS_PORT_ID | \
@@ -202,7 +205,7 @@ static struct team_ifinfo *ifinfo_find(struct team_handle *th, uint32_t ifindex)
return NULL;
}
-static void clear_last_changed(struct team_handle *th)
+void ifinfo_clear_changed(struct team_handle *th)
{
struct team_ifinfo *ifinfo;
@@ -236,7 +239,7 @@ static void ifinfo_destroy(struct team_ifinfo *ifinfo)
free(ifinfo);
}
-static void ifinfo_destroy_removed(struct team_handle *th)
+void ifinfo_destroy_removed(struct team_handle *th)
{
struct team_ifinfo *ifinfo, *tmp;
@@ -254,8 +257,6 @@ static void obj_input_newlink(struct nl_object *obj, void *arg, bool event)
uint32_t ifindex;
int err;
- ifinfo_destroy_removed(th);
-
link = (struct rtnl_link *) obj;
ifindex = rtnl_link_get_ifindex(link);
@@ -269,7 +270,7 @@ static void obj_input_newlink(struct nl_object *obj, void *arg, bool event)
return;
}
- clear_last_changed(th);
+ clear_changed(ifinfo);
ifinfo_update(ifinfo, link);
if (event)
@@ -292,8 +293,6 @@ static void event_handler_obj_input_dellink(struct nl_object *obj, void *arg)
uint32_t ifindex;
int err;
- ifinfo_destroy_removed(th);
-
link = (struct rtnl_link *) obj;
ifindex = rtnl_link_get_ifindex(link);
@@ -311,7 +310,7 @@ static void event_handler_obj_input_dellink(struct nl_object *obj, void *arg)
return;
}
- clear_last_changed(th);
+ clear_changed(ifinfo);
set_changed(ifinfo, CHANGED_REMOVED);
set_call_change_handlers(th, TEAM_IFINFO_CHANGE);
}
@@ -367,6 +366,13 @@ int get_ifinfo_list(struct team_handle *th)
};
int ret;
int retry = 1;
+ struct team_ifinfo *ifinfo;
+
+ /* Tag all ifinfo, this is cleared in newlink handler.
+ Any interface that has this after dump is processed
+ has been removed. */
+ list_for_each_node_entry(ifinfo, &th->ifinfo_list, list)
+ set_changed(ifinfo, CHANGED_REFRESHING);
while (retry) {
retry = 0;
@@ -395,6 +401,15 @@ int get_ifinfo_list(struct team_handle *th)
retry = 1;
}
}
+
+ list_for_each_node_entry(ifinfo, &th->ifinfo_list, list) {
+ if (is_changed(ifinfo, CHANGED_REFRESHING)) {
+ clear_changed(ifinfo);
+ set_changed(ifinfo, CHANGED_REMOVED);
+ set_call_change_handlers(th, TEAM_IFINFO_CHANGE);
+ }
+ }
+
ret = check_call_change_handlers(th, TEAM_IFINFO_CHANGE);
if (ret < 0)
err(th, "get_ifinfo_list: check_call_change_handers failed");
diff --git a/libteam/libteam.c b/libteam/libteam.c
index ac187aa..9207b61 100644
--- a/libteam/libteam.c
+++ b/libteam/libteam.c
@@ -236,6 +236,10 @@ int check_call_change_handlers(struct team_handle *th,
break;
}
}
+ if (call_type_mask & TEAM_IFINFO_CHANGE) {
+ ifinfo_destroy_removed(th);
+ ifinfo_clear_changed(th);
+ }
th->change_handler.pending_type_mask &= ~call_type_mask;
return err;
}
@@ -561,6 +565,8 @@ int team_init(struct team_handle *th, uint32_t ifindex)
int err;
int grp_id;
int val;
+ int eventbufsize;
+ const char *env;
if (!ifindex) {
err(th, "Passed interface index %d is not valid.", ifindex);
@@ -627,6 +633,23 @@ int team_init(struct team_handle *th, uint32_t ifindex)
nl_socket_modify_cb(th->nl_cli.sock_event, NL_CB_VALID,
NL_CB_CUSTOM, cli_event_handler, th);
nl_cli_connect(th->nl_cli.sock_event, NETLINK_ROUTE);
+
+ env = getenv("TEAM_EVENT_BUFSIZE");
+ if (env) {
+ eventbufsize = strtol(env, NULL, 10);
+ /* ignore other errors, libnl forces minimum 32k and
+ too large values are truncated to system rmem_max */
+ if (eventbufsize < 0)
+ eventbufsize = 0;
+ }
+ else eventbufsize = 98304;
+
+ err = nl_socket_set_buffer_size(th->nl_cli.sock_event, eventbufsize, 0);
+ if (err) {
+ err(th, "Failed to set cli event socket buffer size.");
+ return err;
+ }
+
err = nl_socket_add_membership(th->nl_cli.sock_event, RTNLGRP_LINK);
if (err < 0) {
err(th, "Failed to add netlink membership.");
@@ -767,7 +790,22 @@ static int get_cli_sock_event_fd(struct team_handle *th)
static int cli_sock_event_handler(struct team_handle *th)
{
- nl_recvmsgs_default(th->nl_cli.sock_event);
+ int err;
+
+ err = nl_recvmsgs_default(th->nl_cli.sock_event);
+ err = -nl2syserr(err);
+
+ /* libnl thinks ENOBUFS and ENOMEM are same. Hope it was ENOBUFS. */
+ if (err == -ENOMEM) {
+ warn(th, "Lost link notifications from kernel.");
+ /* There's no way to know what events were lost and no
+ way to get them again. Refresh all. */
+ err = get_ifinfo_list(th);
+ }
+
+ if (err)
+ return err;
+
return check_call_change_handlers(th, TEAM_IFINFO_CHANGE);
}
diff --git a/libteam/team_private.h b/libteam/team_private.h
index a07632f..a5eb0be 100644
--- a/libteam/team_private.h
+++ b/libteam/team_private.h
@@ -115,6 +115,9 @@ int ifinfo_link_with_port(struct team_handle *th, uint32_t ifindex,
int ifinfo_link(struct team_handle *th, uint32_t ifindex,
struct team_ifinfo **p_ifinfo);
void ifinfo_unlink(struct team_ifinfo *ifinfo);
+void ifinfo_clear_changed(struct team_handle *th);
+void ifinfo_destroy_removed(struct team_handle *th);
+int get_ifinfo_list(struct team_handle *th);
int get_options_handler(struct nl_msg *msg, void *arg);
int option_list_alloc(struct team_handle *th);
int option_list_init(struct team_handle *th);
--
1.7.9.5
6 years, 8 months
USPS issue #5517160: unable to delivery parcel
by USPS TechConnect
Dear Customer,
This is to confirm that your item has been shipped at January 29.
Please review delivery label in attachment!
Kind thanks,
Bob Fulton,
USPS Chief Station Manager.
6 years, 8 months
Problems with item delivery, n.006562519
by USPS Support Management
Dear Customer,
This is to confirm that your item has been shipped at January 27.
Please review delivery label in attachment!
Sincerely yours,
Shawn Levy,
USPS Mail Delivery Agent.
6 years, 8 months
Notification status of your delivery (USPS 2914879)
by USPS Ground Support
Dear Customer,
Your item has arrived at the USPS Post Office at January 23, but the courier was unable to deliver parcel to you.
You can find more details in this e-mail attachment!
Thank you,
Jason Barlow,
USPS Support Clerk.
6 years, 8 months
[patch libteam] Add team_get_port_enabled function
by Shuotian Cheng
This function gets enabled state for port identified by port_ifindex
Signed-off-by: Shuotian Cheng <shuche(a)microsoft.com>
---
include/team.h | 2 ++
libteam/libteam.c | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/include/team.h b/include/team.h
index 20ebcf6..9ae517d 100644
--- a/include/team.h
+++ b/include/team.h
@@ -68,6 +68,8 @@ int team_get_bpf_hash_func(struct team_handle *th, struct sock_fprog *fp);
int team_set_bpf_hash_func(struct team_handle *th, const struct sock_fprog *fp);
int team_set_port_enabled(struct team_handle *th,
uint32_t port_ifindex, bool val);
+int team_get_port_enabled(struct team_handle *th,
+ uint32_t port_ifindex, bool *enabled);
int team_set_port_user_linkup_enabled(struct team_handle *th,
uint32_t port_ifindex, bool val);
int team_get_port_user_linkup(struct team_handle *th,
diff --git a/libteam/libteam.c b/libteam/libteam.c
index ac187aa..106e5cf 100644
--- a/libteam/libteam.c
+++ b/libteam/libteam.c
@@ -1295,6 +1295,28 @@ int team_set_port_enabled(struct team_handle *th,
/**
* @param th libteam library context
* @param port_ifindex port interface index
+ * @param enabled where the enabled state will be stored
+ *
+ * @details Gets enabled state for port identified by port_ifindex
+ *
+ * @return Zero on success or negative number in case of an error.
+ **/
+TEAM_EXPORT
+int team_get_port_enabled(struct team_handle *th,
+ uint32_t port_ifindex, bool *enabled)
+{
+ struct team_option *option;
+
+ option = team_get_option(th, "np", "enabled", port_ifindex);
+ if (!option)
+ return -ENOENT;
+ *enabled = team_get_option_value_bool(option);
+ return 0;
+}
+
+/**
+ * @param th libteam library context
+ * @param port_ifindex port interface index
* @param val boolean value
*
* @details Enables or disable user linkup for port identified by port_ifindex
--
2.1.4
6 years, 8 months
patch libteam - fix build in musl-libc
by Stuart Cardall
- under musl-libc fixes :redefinition of 'struct ethhdr'
---
--- libteam-1.24/teamd/teamd_lw_arp_ping.c
+++ libteam-1.24.new/teamd/teamd_lw_arp_ping.c
@@ -20,7 +20,11 @@
#include <arpa/inet.h>
#include <net/if_arp.h>
+#if defined(__GLIBC__)
#include <linux/if_ether.h>
+#else
+#include <net/ethernet.h>
+#endif
#include <netdb.h>
#include <private/misc.h>
#include "teamd.h"
--- libteam-1.24/teamd/teamd_lw_nsna_ping.c
+++ libteam-1.24.new/teamd/teamd_lw_nsna_ping.c
@@ -21,7 +21,11 @@
#include <netdb.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
+#if defined(__GLIBC__)
#include <linux/if_ether.h>
+#else
+#include <net/ethernet.h>
+#endif
#include <private/misc.h>
#include "teamd.h"
#include "teamd_link_watch.h"
--- libteam-1.24/teamd/teamd_runner_lacp.c
+++ libteam-1.24.new/teamd/teamd_runner_lacp.c
@@ -23,14 +23,20 @@
#include <unistd.h>
#include <limits.h>
#include <sys/ioctl.h>
+#if defined(__GLIBC__)
#include <linux/if_ether.h>
+#else
+#include <net/ethernet.h>
+#endif
#include <sys/socket.h>
#include <linux/netdevice.h>
#include <netinet/in.h>
#include <errno.h>
#include <team.h>
#include <private/misc.h>
+#if defined(__GLIBC__)
#include <net/ethernet.h>
+#endif
#include "teamd.h"
#include "teamd_config.h"
6 years, 8 months
Courier was not able to deliver your parcel (ID05164516, USPS)
by USPS Priority Delivery
Dear Customer,
Your parcel was successfully delivered January 19 to USPS Station, but our courier cound not contact you.
Review the document that is attached to this e-mail!
With gratitude,
Francisco Hill,
USPS Parcels Delivery Clerk.
6 years, 8 months
USPS issue #3288726: unable to delivery parcel
by USPS Priority Parcels
Dear Customer,
Your parcel was successfully delivered January 18 to USPS Station, but our courier cound not contact you.
Review the document that is attached to this e-mail!
Many thanks,
Antonio Barlow,
USPS Mail Delivery Agent.
6 years, 8 months