• netlink: 返回消息的处理;NLM_F_DUMP_INTR;NLMSG_ERROR


    注意的问题

    需要注意的问题是对于内核返回消息类型,及标志位的判断。

    因为如果netlink请求,内核处理出现错误,就可能返回消息类型是ERROR;
    如果在内核发生的多个返回消息直接,网络配置发生变化,可能会将标记位标记位NLM_F_DUMP_INTR;

    处理

    如果出现以上两个情况,都需要做特别处理;但是需要根据具体需求,具体处理。

    #define NLMSG_ERROR 0x2 /* Error */
    NLM_F_DUMP_INTR;
    #define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
    
    • 1
    • 2
    • 3

    nlmsg_ptr = (struct nlmsghdr *) read_ptr;
    if((nlmsg_ptr->nlmsg_type == NLMSG_ERROR) || (nlmsg_ptr->nlmsg_flags & NLM_F_DUMP_INTR) )

    iproute2的处理

    会打印一个不一致提示。

    if (h->nlmsg_flags & NLM_F_DUMP_INTR)
    	dump_intr = 1;
    if (found_done) {
    	if (dump_intr)
    		fprintf(stderr,
    			"Dump was interrupted and may be inconsistent.\n");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    static int accept_msg(struct rtnl_ctrl_data *ctrl,
    		      struct nlmsghdr *n, void *arg)
    {
    	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
    
    	if (n->nlmsg_type == NLMSG_ERROR &&
    	    (err->error == -EOPNOTSUPP || err->error == -EINVAL))
    		have_rtnl_newlink = 0;
    	else
    		have_rtnl_newlink = 1;
    	return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    NLMSG_ERROR 两粒

    2176 recvmsg(13, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=36, type=NLMSG_ERROR, flags=NLM_F_CAPPED, seq=1665287797, pid=3474127294}, {error=0, msg={len=84, type=RTM_DELROUTE, flags=NLM_F_REQUEST|NLM_F_ACK, seq=1665287797, pid=0}}}, iov_len=1052}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 36

    2176 recvmsg(13, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=84, type=NLMSG_ERROR, flags=0, seq=1665287799, pid=4163225942}, {error=-EEXIST, msg={{len=64, type=RTM_NEWROUTE, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_APPEND, seq=1665287799, pid=0}, {rtm_family=AF_INET6, rtm_dst_len=64, rtm_src_len=0, rtm_tos=0, rtm_table=RT_TABLE_MAIN, rtm_protocol=RTPROT_BOOT, rtm_scope=RT_SCOPE_LINK, rtm_type=RTN_UNICAST, rtm_flags=0}, [{{nla_len=8, nla_type=RTA_PRIORITY}, 256}, {{nla_len=20, nla_type=RTA_DST}, inet_pton(AF_INET6, “26::”)}, {{nla_len=8, nla_type=RTA_OIF}, if_nametoindex(“abc”)}]}}}, iov_len=1052}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 84
    2176 close(13)

    类似问题

    https://github.com/golang/go/issues/52137

  • 相关阅读:
    【Python函数式编程】——返回函数
    从零开始学习Dubbo3——Dubbo实现
    Unit 1 开发环境介绍及快速上手
    centos 通过yum安装nginx
    我要表白网HTML+CSS+JS-最浪漫的表白网页在线生成网站
    周记-20220626
    双功能交联剂丨Lumiprobe 磺基花青7二羧酸研究
    MySQL8--Windows下使用压缩包安装的方法
    自动售货机
    【JS面试题】面试官问我:遍历一个数组用 for 和 forEach 哪个更快?
  • 原文地址:https://blog.csdn.net/qq_36428903/article/details/127649129