aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Tiainen <atiainen@forcepoint.com>2018-05-03 20:13:35 +0300
committerJiri Pirko <jiri@mellanox.com>2018-05-10 20:41:39 +0200
commit05a7a9598fc9e616a1acf19096aeb93f7288bb35 (patch)
tree2539c119c701dd5376df5b9de8cf10ff36c682a0
parent87662455fc6eae38de70fd7b6f758c22ec7a443a (diff)
downloadlibteam-05a7a9598fc9e616a1acf19096aeb93f7288bb35.tar.gz
libteam: don't crash when trying to print unregistered device name
team_port_str() will crash when trying to print port name that was just unregistered, if dellink event is handled before port removal event. This is regression from Commit 046fb6ba0aec ("libteam: resynchronize ifinfo after lost RTNLGRP_LINK notifications"), which made it free all removed interfaces after ifinfo handlers are called. Put the ifinfo_destroy_removed() back to dellink/newlink handlers as it was before that commit. Clean up the ifinfo list after change handlers only if it refreshed the entire ifinfo list after lost events. There's still a rare possibility that dellink event is missed due to full socket receive buffer, which would cause ifinfo refresh and clearing removed interfaces. For this, add NULL check to team_port_str() so it doesn't try to print port device name in this situation. Signed-off-by: Antti Tiainen <atiainen@forcepoint.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
-rw-r--r--include/team.h1
-rw-r--r--libteam/ifinfo.c7
-rw-r--r--libteam/libteam.c2
-rw-r--r--libteam/stringify.c3
4 files changed, 10 insertions, 3 deletions
diff --git a/include/team.h b/include/team.h
index 9ae517d..b31c8d8 100644
--- a/include/team.h
+++ b/include/team.h
@@ -223,6 +223,7 @@ enum {
TEAM_PORT_CHANGE = 0x1,
TEAM_OPTION_CHANGE = 0x2,
TEAM_IFINFO_CHANGE = 0x4,
+ TEAM_IFINFO_REFRESH = 0x8,
TEAM_ANY_CHANGE = TEAM_PORT_CHANGE |
TEAM_OPTION_CHANGE |
TEAM_IFINFO_CHANGE,
diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c
index 5c32a9c..46d56a2 100644
--- a/libteam/ifinfo.c
+++ b/libteam/ifinfo.c
@@ -258,6 +258,8 @@ 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);
@@ -294,6 +296,8 @@ 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);
@@ -412,7 +416,8 @@ int get_ifinfo_list(struct team_handle *th)
}
}
- ret = check_call_change_handlers(th, TEAM_IFINFO_CHANGE);
+ ret = check_call_change_handlers(th, TEAM_IFINFO_CHANGE |
+ TEAM_IFINFO_REFRESH);
if (ret < 0)
err(th, "get_ifinfo_list: check_call_change_handers failed");
return ret;
diff --git a/libteam/libteam.c b/libteam/libteam.c
index 77a06dd..ce0467e 100644
--- a/libteam/libteam.c
+++ b/libteam/libteam.c
@@ -236,7 +236,7 @@ int check_call_change_handlers(struct team_handle *th,
break;
}
}
- if (call_type_mask & TEAM_IFINFO_CHANGE) {
+ if (call_type_mask & TEAM_IFINFO_REFRESH) {
ifinfo_destroy_removed(th);
ifinfo_clear_changed(th);
}
diff --git a/libteam/stringify.c b/libteam/stringify.c
index 38f4788..f1faf90 100644
--- a/libteam/stringify.c
+++ b/libteam/stringify.c
@@ -344,7 +344,8 @@ static bool __team_port_str(struct team_port *port,
team_is_port_removed(port) ? "-" :
team_is_port_changed(port) ? "*" : " ",
ifindex,
- team_get_ifinfo_ifname(ifinfo),
+ ifinfo ? team_get_ifinfo_ifname(ifinfo) :
+ "(removed)",
team_is_port_link_up(port) ? "up": "down",
team_get_port_speed(port),
team_get_port_duplex(port) ? "FD" : "HD");