VSOMEIP代码阅读整理(1) - 网卡状态监听

news2024/11/15 21:23:39

一. 概述

在routing进程所使用的配置文件中,存在如下配置项目:
{
    "unicast" : "192.168.56.101",
    ...
    "service-discovery" :
    {
        "enable" : "true",
        "multicast" : "224.244.224.245",
        ...
    }
}
    
其中有 "unicast" : "192.168.56.101"和	"multicast" : "224.244.224.245" 两个通信地址,这两个地址一个是用于vsomeip用于对外通信的单播地址,另一个配置的是service-discovery功能依赖的组播的地址。

作为routingmanager的进程需要监听这个单播地址和组播地址所在的网卡的状态,这部分功能主要在netlink_connector中实现,routing_manager_imp依赖netlink_connector来监听网卡状态,并且在网卡状态ready的情况下才会启动routing。

netlink_connector中使用到了linux平台的netlink协议用于监听内核上网卡相关事件。

二. netlink protocol

netlink是linux平台上第一种IPC机制,主要用于用户态进程与内核进程通信,此外还可以用于用户态进程之间通信(这个使用unix domain socket)也可以做到。

netlink和传统的和内核通信的机制(ioctl,sysfs属性)等不同,netlink是支持全双工的通信的,也就是可以异步通信的,而其他几种传统的内核通信的机制只支持半双工同步通信的方式。在这种情况下,内核甚至支持主动发起通信,而不是由应用发起通信。

此外,netlink支持组播的方式,以组播的方式将消息发给多个进程(根据groupid)。

img

netlink的通信方式使用的是socket API,创建NETLINK socket的时候,需要指定NETLINK socket的协议类型类型()
sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);   // NETLINK_ROUTE是协议类型
目前的linxu系统中支持32中协议类型,个人认为这个协议类型就是事件组(网卡/路由/安全/审计/SCSI设备...等等)。
#define NETLINK_ROUTE        0    /* 用于设置和查询路由表等网络核心模块*/
#define NETLINK_UNUSED        1    /* Unused number                */
#define NETLINK_USERSOCK    2    /* Reserved for user mode socket protocols,保留用于用户态进程间通信     */
#define NETLINK_FIREWALL    3    /* Unused number, formerly ip_queue        */
#define NETLINK_SOCK_DIAG    4    /* socket monitoring                */
#define NETLINK_NFLOG        5    /* netfilter/iptables ULOG */
...
...
NETLINK socket需要做bind操作绑定NETLINK的地址,NETLINK地址结构如下:
struct sockaddr_nl {
    __kernel_sa_family_t    nl_family;    /* 协议族 AF_NETLINK    */
    unsigned short    nl_pad;        /* 固定填写0 zero        */
    __u32        nl_pid;        /* 端口ID,内核填0,应用进程填PID port ID    */
    __u32        nl_groups;    /* 广播组 multicast groups mask */
};
除了nl_pad固定为0以外,其他参数需要填写
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;    // 协议族
// RTMGRP_LINK: 网卡UP/DOWN
// RTMGRP_IPV4_IFADDR: ip地址变化
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;    // 广播组(事件组中的具体事件)
  设置好NETLINK地址后,将其绑定到socket上面
bind(sock, (struct sockaddr *)&addr, sizeof(addr);
接着,就可以使用该socket和内核进行netlink通信了,通过标准recv接口从内核接收消息
while (running && (len = recv(sock, buffer, 4096, 0)) > 0) {
	nlh = (struct nlmsghdr *)buffer;
	while (NLMSG_OK(nlh, len) && (nlh->nlmsg_type != NLMSG_DONE)) {
		// 解析不同类型的NetLink消息
		...
		// 下一条消息
		nlh = NLMSG_NEXT(nlh, len);
	}
}
close(sock);

三. netlink_connector

​ netlink_connector类依赖了NETLINK通信机制和内核进行通信,用于监控网卡的状态,根据传入的单播地址和组播地址监控。

​ 首先netlink_connector类中也创建了用于NETLINK通信的socket

class netlink_connector : public std::enable_shared_from_this<netlink_connector> {
	...
private:
	...
	boost::asio::basic_raw_socket<nl_protocol> socket_;  // nl_protocol结构体中默认famliy为PF_NETLINK, type为SOCK_RAW
	...
}

void netlink_connector::start() {
	...
	socket_.open(nl_protocol(NETLINK_ROUTE), ec);   // 协议类型为NETLINK_ROUTE,用于设置和查询路由表等网络核心模块
	...
	socket_.bind(nl_endpoint<nl_protocol>(
                RTMGRP_LINK |        // - 当网卡变动时会触发这个多播组
                RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |  // 当ipv4/ipv6地址变动时会触发这个多播组
                RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE |    // 当ipv4/ipv6路由变动时会触发这个多播组
                RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_MROUTE), ec);   // 当多播路由发生更新时会触发这个多播组
	

​ 然后,使用创建的socket接收内核的消息并且解析,根据不同的事件回调上层routing_manager_impl

socket_.async_receive(
    boost::asio::buffer(&recv_buffer_[0], recv_buffer_size),
    std::bind(
        &netlink_connector::receive_cbk,
        shared_from_this(),
        std::placeholders::_1,
        std::placeholders::_2
    )
);

void netlink_connector::receive_cbk(boost::system::error_code const &_error,
                 std::size_t _bytes) {
    while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) {
            char ifname[IF_NAMESIZE];
            switch (nlh->nlmsg_type) { // 根据多播组内的消息类型分别处理
                case RTM_NEWADDR: {    // IP地址变化
                	// 解析出消息中的IP地址,如果该IP是VSOMEIP配置的单播地址,则往下
                	// 根据IP地址找到网卡,获取其状态(UP/DOWN)
                	// 通知上层handler处理(handler第一个参数标志是单播还是组播地址的网卡)
                }
                break;
                case RTM_NEWLINK: {    // 网卡变化
                	// 获取网卡IP,如果该IP是VSOMEIP配置的单播地址,则往下
                	// 获取网卡状态
                	// 通知上层handler处理
                }
                break;
                case RTM_NEWROUTE: {   // 路由添加
                	check_sd_multicast_route_match(...) {
                		// 读取路由项的目标地址(RTA_DST),判断地址是否为SD的组播地址
                        // 读取路由项的输出网络设备索引,判断设备索引是否为单播地址通信使用的网络设备的索引
                        // 读取路由项的网关地址
                        // 1. 如果单播地址通信使用的网络设备被加到SD的组播中,返回true
                        // 2. 如果单播地址通信使用的网络设备被添加到组播,但是组播地址长度为0,返回true(使用默认路由作为SD的地址)
                        // 3. 不满足上面两种情况,返回false
                	}
                	// check_sd_multicast_route_match返回true,则通知上层组播准备好了
               	}
               	break;
                case RTM_DELROUTE: {   // 路由删除
                	check_sd_multicast_route_match(...) {
                		...
                	}
                	// check_sd_multicast_route_match返回true,则通知上层组播未准备好
                }
                break;
                ...
            }
}

​ 对于netlink_connector,其监听网卡以及组播路由的变化事件。routing_manager_impl则是这些事件的消费者

void routing_manager_impl::start() {
	...
	netlink_connector_->register_net_if_changes_handler(
            std::bind(&routing_manager_impl::on_net_interface_or_route_state_changed,
            this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    ...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2185194.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线程和进程的关系和区别

目录 进程 概念 特点 生命周期 进程的通信 应用场景 线程 概念 特点 类型 状态 调度 应用场景 线程和进程的关系与区别 关系 区别 总结 僵尸进程 产生原因 解决方法 进程 概念 第一&#xff0c;进程是一个实体。每一个进程都有它自己的地址空间&#xff…

数字通信中不同信道类型对通信系统性能影响matlab仿真分析,对比AWGN,BEC,BSC以及多径信道

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

C0013.Clion中利用C++调用opencv打开摄像头

下载opencv https://opencv.org/get-started/ 直接官网下载opencv-4.9.0-windows.exe 安装opencv opencv配置环境变量 如上安装配置完成。

SpringBoot框架下的健康信息管理解决方案

第1章 绪论 1.1背景及意义 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们生活水平的不断提高&#xff0c;日常生活中人们对医院管理方面的要求也在不断提高&#xff0c;由于老龄化人数更是不断增加&#xff0c;使得师生健康信息管理系统的开发成为必需而且紧…

第三批安全可靠评测名单公布,几家欢喜几家忧

9月30号&#xff0c;赶在国庆长假之前&#xff0c;中国信息安全评测中心发布了《安全可靠评测结果公告(2024年第2号)》&#xff0c;测试结果自发布之日起有效期三年。 本期测试分为集中式数据库、分布式数据库和中央处理器三个大类&#xff0c;结果共有14家公司的16个产品入围&…

AI绘画实现数字人2D形象生成及3D数字人视频生成

概述 随着人工智能技术的不断进步&#xff0c;AI绘画已经成为数字艺术创作领域的重要工具。本章将详细介绍如何利用AI绘画技术生成数字人的2D形象&#xff0c;并进一步将其转化为3D数字人视频。通过一系列实践步骤和Python代码示例&#xff0c;您将能够掌握从平台使用到系统部…

计算机毕业设计之:音乐媒体播放及周边产品运营平台(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

看Threejs好玩示例,学习创新与技术(Noise)

给图像加一点噪声效果&#xff0c;可以起到朦胧背景的效果&#xff0c;比如下面这幅画。 除了普通的图片外&#xff0c;我们可以把这个效果应用到地图或其他方面&#xff0c;比如超过范围不允许用户了解更详细的内容。当然&#xff0c;也可以采用雾Fog效果&#xff0c;但后处理…

鸿蒙ArkUI实战开发-主打自研语言及框架

ArkUI 是 HarmonyOS 的声明式 UI 开发框架&#xff0c;而 ArkUI-X 是基于 ArkUI 框架扩展而来的跨平台开发框架。ArkUI-X 支持 HarmonyOS、OpenHarmony、Android 和 iOS 平台&#xff0c;允许开发者使用一套代码构建支持多平台的应用程序。 一、ArkUI-X 的实战开发步骤 在实战开…

(c++)在堆区创建一个数组并且访问与释放

在堆区创建一个数组&#xff0c;然后利用一个指针指向这个数组的首地址&#xff0c;通过这个指针来访问这个数组。 代码展示了三种赋值的方式&#xff1a; 1.直接利用数组访问赋值 2.利用循环结构&#xff08;和1原理一样&#xff09; 3.循环结构键盘输入赋值 然后输出这个…

Ray_Tracing_In_One_Weekend上

目标&#xff1a; 使用vscodeIDE编写代码&#xff0c;这是我的配置 学习这个教程&#xff0c;完成一个简易的光线追踪器开发 1输出PPM图像 在不使用 opengl &#xff08;渲染图像&#xff09;/ std_image.h&#xff08;加载图像&#xff09;等库的情况下&#xff0c;怎样通…

某信服, 一点底线都没有, 一点Face都不要

某些软件厂商, 仗着自己有点背景, 做出来的东西真的是流氓 !!! 铁子们, 这玩意儿怎么卸载呢?

CertiK《Hack3d:2024年第三季度安全报告》(附报告全文链接)

CertiK《Hack3d&#xff1a;2024年第三季度Web3.0安全报告》现已发布&#xff0c;本次报告深入分析了2024年7月至9月的链上安全状况&#xff0c;本季度总损失金额为7.53亿美元&#xff0c;网络钓鱼和私钥泄露是本季度造成资产损失的主要原因。 ​ 关键数据 2024年第三季度&a…

数电基础(脉冲波形的变化和发生+multisim)

1.脉冲波形的变化和发生 1.1单稳态电路 1.1.1逻辑门组成的单稳态电路 基本概念 &#xff08;1&#xff09;单稳态电路&#xff08;monostable multivibrator又称one-shot&#xff09;常用于脉冲的变换&#xff0c;延时和定时 电路的输出有稳态和暂稳态两个不同的工作状态 …

java常用框架结构

1. Spring框架 特色&#xff1a;Spring框架就像是一个万能工具箱&#xff0c;提供了丰富的功能来满足开发者的各种需求。它支持面向切面编程&#xff08;AOP&#xff09;、依赖注入&#xff08;DI&#xff09;等特性&#xff0c;使得代码更加模块化和可维护。Spring还提供了对数…

【web安全】——XXE漏洞

1.XML基础 1.1.XML简介 XML被称为可扩展标记语言&#xff0c;与HTML类似&#xff0c;但是HTML中的标签都是预定义(预先定义好每个标签的作用)的&#xff0c;而XML语言中的标签都是自定义(可以自己定义标签的名称、属性、值、作用)的;HTML中的标签可以是单标签&#xff0c;而X…

洛谷 P11045 [蓝桥杯 2024 省 Java B] 最优分组

[Problem Discription] \color{blue}{\texttt{[Problem Discription]}} [Problem Discription] [Analysis] \color{blue}{\texttt{[Analysis]}} [Analysis] 首先得注意这么一点&#xff1a; k k k 必须得是 n n n 的因数&#xff08;这里的 n , k n,k n,k 对应于题目的 N ,…

【若依】postman调试出现认证失败,无法访问系统资源

如果前后端都已经连接通了&#xff0c;但是调试出现错误代码&#xff0c;可能是因为没有授权的问题&#xff0c;需要获得授权。 授权内容在cookie中 把cookie中的token内容粘贴到postman里面 这个时候再在postman里测试接口&#xff0c;发现可以拿到数据了

【C++】“list”的介绍和常用接口的模拟实现

【C】“list”的介绍和常用接口的模拟实现 一. list的介绍1. list常见的重要接口2. list的迭代器失效 二. list常用接口的模拟实现&#xff08;含注释&#xff09;三. list与vector的对比 一. list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xf…

操作符详解与表达式求值

目录 操作符分类 1.算数操作符 2.移位操作符&#xff08;只适用于整数范围&#xff09; &#xff08;1&#xff09;引入 &#xff08;2&#xff09;左移操作符<< &#xff08;2&#xff09;右移操作符>> 3.位操作符 4.赋值操作符 复合赋值符 5.单目操作符 5…