-
Notifications
You must be signed in to change notification settings - Fork 531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
teamsyncd::Additional checks put inplace to make sure the netlink message is valid #1144
Conversation
…id before addLag is called. Have seen cases where the interface name is NULL and the ifindex is an incorrect one.
Hi judyjoseph, Could you please share the teamsyncd related logs when the issue is seen (OR when you introduced the issue manually).
By any chance are the logs similar to the one's reported in #763 ? Rgds, |
teamsyncd/teamsync.cpp
Outdated
{ | ||
SWSS_LOG_ERROR("Unable to allocate netlink socket"); | ||
} else { | ||
nl_connect(m_nl_sock, NETLINK_ROUTE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check error code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure will add an explicit check.
teamsyncd/teamsync.cpp
Outdated
m_nl_sock = nl_socket_alloc(); | ||
if (!m_nl_sock) | ||
{ | ||
SWSS_LOG_ERROR("Unable to allocate netlink socket"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to crash it. Otherwise your check will not work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had thought before about introducing a throw statement and crashing if the socket_alloc() fails. But didn't do so as I have seen these failure messages of "Unable to initialize team socket" with the team_alloc()/team_init() in other scenario's like back to back config reload command issued multiple times. So didn't want teamsyncd to fail when we try to spawn the process because if this additional check we are introducing.
But I think on a second thought -- I agree with you, it is good to throw error and crash as this is not a good scenario. Shall update, thanks.
teamsyncd/teamsync.cpp
Outdated
} | ||
|
||
/* Refill cache and check for ifindex */ | ||
nl_cache_refill(m_nl_sock ,m_link_cache); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could return not zero as error indication
Also. Would it be to much to refill all cache for every ifindex to name operation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will do a bit of profiling and see how much time it takes will all the max number of Port channels created. We need to do a refill before checking -- as I found cache incosistency issues in case when we do config reload command back to back.
Also I see similar implementations in
RouteSync::onRouteMsg() --> calling RouteSync::getIfName()
NeighSync::onMsg() --> LinkCache::getInstance().ifindexToName()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did more profiling for the refill cache, and found it was done in the same second ( it took around 1ms for refill API to complete execution ) - which looked ok.
teamsyncd/teamsync.cpp
Outdated
if (rtnl_link_i2name(m_link_cache, ifindex, ifName, TeamPortSync::MAX_IFNAME) == NULL) | ||
{ | ||
/* Returns ifindex as string / */ | ||
return to_string(ifindex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same as before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea was to give back the ifindex itself as the interface name and hence the caller function match will fail and ignore the NETLINK update, instead of proceeding with the TeamSync::addLag() API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the API format so that now it checks the interface name in the API checkIfindexToName() and returns true/false depending on the interface name is present in kernel cache or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as comments
|
Hi Madhukar, |
Hi Pavel,
thanks, |
…link message is valid
The reason for the error "TeamPortSync: Failed to initialize team handler" during CONFIG-RELOAD is having the old port-channel netdevices in the kernel. I'll be submitting this PR later with more details; you may use the above fix in the meanwhile. |
@judyjoseph - can you please let me know if the suggested solution works for you? |
@@ -102,13 +161,38 @@ void TeamSync::onMsg(int nlmsg_type, struct nl_object *obj) | |||
if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_DELLINK)) | |||
return; | |||
|
|||
string lagName = rtnl_link_get_name(link); | |||
/* Introduce check if the interface name is NULL */ | |||
char *ifName = rtnl_link_get_name(link); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand why you change the previous lagName to ifName here. seems ifName is not used anymore afterwards
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason behind this fix was the observation of a crash in teamsyncd segmentation fault with invalid ifindex and mtu value
#7 swss::TeamSync::addLag (this=0x3e8, lagName=..., ifindex=-374612960, admin_state=, oper_state=, mtu=3920352592)
So the plan here was to check if the ifName is null … to make sure we don't proceed.
* We are here because this is a NEW link create netlink message from kernel. | ||
* Fetch and compare the interface name using ifindex from kernel cache. | ||
*/ | ||
if(!checkIfindexToName(ifindex, lagName)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
under what conditions do we see ifindex does not match lagName? if we ignore such messages, what is the consequence here? Are we losing some validate netlink messages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my testing I have seen messages with the older if indices coming to teamsyncd on doing a config reload. So the idea was to make sure we proceed to add Lag only the ifindices --> interface name and the "Name" which came in netlink message is same. This check should not resulting in losing valid messages.
@madhukar-kamarapu , teammgrd will recreate those port channel devices. is there a race condition between teamsync and teammgrd? maybe we should put some explicit dependency between teamsync and teammgrd? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could not get the exact reproduction scenario, but induced these errors manually and found the teamsyncd staying up.
I think it's impossible to verify anything until we can reproduce the issue.
Have you check this change b931751 ?Hi Pavel,
I am not able to reproduce this segmentation fault in teamsyncd with multiple back to back config reloads. This issue occurred earlier after a config reload.
I have tried the patch b931751 -- but the error message "TeamPortSync: Failed to initialize team handler" comes again randomly on back to back config reloads and now it happens thrice.thanks,
JudyThe reason for the error "TeamPortSync: Failed to initialize team handler" during CONFIG-RELOAD is having the old port-channel netdevices in the kernel.
Fix: Delete the old port-channel netdevices from the kernel before teamsyncd is started. You may add the logic in TeamSync::TeamSync().
Quick fix to validate: Delete all the port-channel netdevices using the command "ip link del dev PortChannelXXX" before teamd docker starts.
I'll be submitting this PR later with more details; you may use the above fix in the meanwhile.
This fix should also solve your teamsyncd crash.
Note: In sonic-buildimage/dockers/docker-teamd/start.sh, start teamsyncd 1st followed with teammgrd. This helps in addressing few issues.@judyjoseph - can you please let me know if the suggested solution works for you?
@madhukar-kamarapu, Thank you for your comments. From what I understand from code and from testing scenario's - the issues I see of invalid netlink messages is when we do commands like config reload/ load minigraph where we stop start the services. I agree with you that one approach could be to delete all the port-channels in the constructor, but then for this fix to work, we will have to change process startup order to start teamsyncd first and then teammgrd which could have other impacts ( to be analyzed )
The fix I am working on now is to do a good clean of the interfaces when the teamd docker goes down, like clean up the portchannel interfaces in teammgrd signal handler. Additionally I am looking into checking if we don't wait enough on doing a docker stop. Are we spawning the teamd docker again too quickly ? I find this as the root-cause of invalid netlink messages coming in teamSync::onMsg() -- your thoughts.
@judyjoseph - if teammgrd is launched before teamsyncd, I've observed NLE_DUMP_INTR error on the netlink socket opened by teamsyncd. Reason - during config-reload OR cold-reboot, all the netdevices (front-panel-ports, port-channel, VLAN, VTEP, etc) are being created in the kernel. Due to this, the DUMP_REQUEST sent by teamsyncd fails. Note: This is purely a timing issue though. Upon receiving NLE_DUMP_INTR, we are supposed to retry the DUMP_REQUEST (already done on teamd - https://lists.fedoraproject.org/archives/list/libteam@lists.fedorahosted.org/thread/SMLV7U2FCYL7UUAYVDBGQMHHSI3YWEK7/). As long as we delete the stale (old) port-channel netdevices in the kernel during config-reload, I don't see any problem by starting teamsyncd 1st followed with teammgrd. We can add dependency though - program an entry TeamsyncdInitDone in APP_DB (similar to PortInitDone in PORT_TABLE of APP_DB). |
@judyjoseph - Adding logic to clean-up the port-channel interfaces in teammgrd signal handlers seems fine. One another thought - how about terminating all the teamd processes; it should take care of removing the port-channel netdevices in the kernel. Spawning teamd docker quickly is fine - all we need to ensure that proper clean-up is done before we bring up the teamd docker. |
When the teamd docker receives a stop signal, only the processes started by supervisord gets the SIGTERM, so this fix is to propogate the signal to teamd processes via the signal handler in teamsyncd process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please update the questionnaire:
- What I did
- Why I did it
- How I verified it
Thanks for taking a look. I too find difficult to update this PR .. hence I had opened a new one #1159. Can you take a look ? The details are updated already there. |
Yes I have verified that the teamd processes exits cleanly and the Port channel interfaces are removed on config reload/ docker restart - I would need to try a docker upgrade though |
I did some study on this and found that the teamd processes were not getting the SIGTERM signal from supervisord on issuing the "docker stop". Can you take a look at the PR #1159. This change gets things cleaned and has least impact. |
Thanks. Please update the docker upgrade results in the new PR #1159. |
@judyjoseph - I guess you're going to abandon the current PR (#1144). Please confirm. |
Depends on sonic-net#1453 - What I did Added support to query and clear headroom pool watermark counters Added unit test for the headroom pool watermark counters - How I did it Modified watermarkstat script to query/clear headroom pool watermark counters Added show and clear commands - How to verify it Send traffic such that it treks into the headroom pool and check for the headroom pool usage using the show command below Set polling interval to 30s and issue clear commands mentioned below and verify that counters are cleared - New command output (if the output of a command-line utility has changed) Show commands admin@sonic:~$ show headroom-pool watermark Headroom pool maximum occupancy: Pool Bytes --------------------- ------- ingress_lossless_pool 12480 admin@sonic:~$ show headroom-pool persistent-watermark Headroom pool maximum occupancy: Pool Bytes --------------------- ------- ingress_lossless_pool 12480 Clear commands admin@sonic:~$ sudo sonic-clear headroom-pool watermark admin@sonic:~$ sudo sonic-clear headroom-pool persistent-watermark Signed-off-by: Neetha John <nejo@microsoft.com>
What I did
Added additional checks in the netlink message handling of teamsyncd to make sure the message is for a valid interface with ifindex and name. This is using the netlink cache infrastructure to check if the interface name retrieved from cache with the ifindex is matching with the interfaceName in the netlink NEW LINK create message. If the interface name is not same, we drop the message.
Why I did it
Have seen random cases where teamsyncd fails and the stack trace was showing interface name as NULL and the ifindex an incorrect one.
How I verified it
Could not get the exact reproduction scenario, but induced these errors manually and found the teamsyncd staying up.
Details if related