use*_*794 14 linux udp network-programming
操作系统:Linux 2.6.24(x86)
我的应用程序在多个客户端连接到UDP端口4500的服务器上运行.
间歇性地,应用程序无法将UDP流量发送到UDP端口4500上的客户端
这是因为sendmsg系统调用失败,错误代码3(ESRCH)
sendmsg的手册页没有谈论错误ESRCH
即使在终止应用程序并重新启动它之后,问题也无法解决.
其他端口上的UDP流量工作正常
重新启动服务器是唯一的解决方案.
使用内核2.6.11,我没有看到这样的问题.
有关如何调试此问题的任何想法?
要调试这个问题,鉴于可用的信息,我认为最好的起点是看看是否有一种方法sendmsg可以返回ESRCH. 首先,我们需要获取您遇到问题的特定内核版本的源代码,我在这里找到了它
经过一番挖掘,我们可以看到以下链可能会执行:
net/ipv4/udp.c:646:
err = ip_route_output_flow(&rt, &fl, sk, 1);
net/ipv4/route.c:2421:
err = __xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);
net/xfrm/xfrm_policy.c:1380:
pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN,
fl, family,
XFRM_POLICY_OUT);
net/xfrm/xfrm_policy.c:890:
err = xfrm_policy_match(pol, fl, type, family, dir);
Run Code Online (Sandbox Code Playgroud)
最后,我们最终在net/xfrm/xfrm_policy.c:854:xrfm_policy_match
/*
* Find policy to apply to this flow.
*
* Returns 0 if policy found, else an -errno.
*/
static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
u8 type, u16 family, int dir)
{
struct xfrm_selector *sel = &pol->selector;
int match, ret = -ESRCH;
if (pol->family != family ||
pol->type != type)
return ret;
match = xfrm_selector_match(sel, fl, family);
if (match)
ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
因此,xfrm_policy_match如果您检查其中的代码,xfrm_lookup_bytype您会发现一个循环,该循环一直持续到迭代器耗尽或返回值xrfm_policy_match不是,看起来错误来自于此ESRCH。
这告诉我们您的 sendmsg 调用失败,因为您的端口没有 xfrm 策略。当您声明它有效时,就会出现错误并持续存在,这表明您系统上的 xfrm 策略正在被调整或损坏。
通过查看 xfrm 手册页,我们可以看到有一些用于研究策略的工具。通过阅读手册页,我的下一步将是ip xfrm state list在问题未发生时和问题发生后运行,并比较输出。不幸的是,我没有运行 2.6.24 内核的系统来进行更深入的研究。
请注意,我没有任何技巧可以得出这个结论,它是通过检查代码、grep 和查找来确定的。这可能需要花费大量的时间和精力,尤其是当您不熟悉代码库时。为了解决这个问题而不是调试它,我会在深入研究之前尝试不同的内核版本。
看起来ESRCH错误来自一个名为 的网络子系统xfrm,有一组用于调查的工具可以在其手册页上xfrm找到
该错误很可能是由于您尝试发送到的地址/端口缺少策略所致。这可能是由于系统运行时的配置更改或导致 xfrm 策略损坏的错误造成的。