vpp插件DHCP client源码
1、使用dhcp_api.c中的函数添加dhcp client
源码vpp/src/pluggings/dhcp/dhcp_api.c
在VPP(Vector Packet Processing)中配置DHCP客户端涉及一系列步骤,以下是大致的代码流程:
-
包含必要的头文件: 在代码中包含必要的VPP头文件,这些头文件包含了配置DHCP客户端所需的结构和函数。
cCopy code#include <vlib/vlib.h> #include <vnet/ip/ip.h> #include <vnet/dhcp/dhcp_client_common.h>
-
创建配置结构体: 定义一个用于配置DHCP客户端的结构体
vl_api_dhcp_client_config_t
。struct codevl_api_dhcp_client_config_t dhcp_client_config = { .client_index = ..., .hostname = "...", // 设置其他配置参数 };
-
发送消息配置DHCP客户端: 使用VPP提供的API函数将配置信息发送到VPP中。
static void vl_api_dhcp_client_config_t_handler (vl_api_dhcp_client_config_t * mp);
-
处理配置消息: 有一个处理接收到的DHCP客户端配置消息的函数。在这个函数中,将会解析接收到的配置信息,并将其应用到DHCP客户端。
// 解析配置信息并应用到DHCP客户端 // config->client_index, config->hostname 等是消息中的配置参数 // 应用配置到DHCP客户端 static void vl_api_dhcp_client_config_t_handler(vl_api_dhcp_client_config_t * mp) { vlib_main_t *vm = vlib_get_main (); vl_api_dhcp_client_config_reply_t *rmp; u32 sw_if_index; ip_dscp_t dscp; int rv = 0; VALIDATE_SW_IF_INDEX (&(mp->client)); sw_if_index = ntohl (mp->client.sw_if_index); dscp = ip_dscp_decode (mp->client.dscp); rv = dhcp_client_config (mp->is_add, mp->client_index, vm, sw_if_index, mp->client.hostname, mp->client.id, (mp->client.want_dhcp_event ? dhcp_compl_event_callback : NULL), mp->client.set_broadcast_flag, dscp, mp->client.pid); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY); }
vl_api_dhcp_client_config_t
是用于配置DHCP客户端的数据结构,而_handlervl_api_dhcp_client_config_t_handler
则表示一个用于处理此配置结构的函数。这个函数负责接收配置信息、验证参数、将配置应用到系统中等操作。具体函数的实现可能会根据不同的代码库、框架或项目而有所不同,因此建议查阅相关的VPP文档、代码注释或源代码,以便获得关于vl_api_dhcp_client_config_t
和vl_api_dhcp_client_config_t_handler
的详细信息和实际用法。
2、DHCPv4 client命令行源码分析
源码vpp/src/pluggings/dhcp/client.c
(1)、初始化
初始dhcp_client_main
结构体,查找ip4-lookup
节点索引。
VLIB_INIT_FUNCTION (dhcp_client_init);
一般情况下,在VPP中,数据包经过一系列处理步骤,包括接收、解析、处理、转发等。
ip4-lookup
则是用于在路由过程中查找目的地IP地址的动作,用于确定应该将数据包发送到网络中的哪个接口或下一跳。
在本处当client发送DHCP Discover时,为了接受任何OFFER,无论是广播还是单播,都需要将 dhcp-client-detect
功能配置为输入功能,以便DHCP OFFER被发送到ip4-local
节点。如果没有 dhcp-client-detect
,广播的OFFER会到达255.255.255.255/32地址,单播会到达 0.0.0.0/0,这两个地址默认都会丢弃该报文,而后者可能会转发到其他地方。
dhcp-client-detect
通常用于特定的数据包处理流程中,用于识别DHCP客户端的数据包。一旦识别出DHCP客户端的数据包,通常会触发特定的处理流程,可能涉及为客户端分配IP地址或处理网络配置等。但它并不直接涉及到路由决策或数据包的转发。
(2)注册添加/删除client命令模块
VLIB_CLI_COMMAND (dhcp_client_set_command, static) = {
.path = "set dhcp client",
.short_help = "set dhcp client [del] intfc <interface> [hostname <name>]",
.function = dhcp_client_set_command_fn,
};
①、读取配置参数,添加或删除client
static clib_error_t * dhcp_client_set_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd);
int dhcp_client_add_del (dhcp_client_add_del_args_t * a);
添加client需要先在DHCP client pool索引if,查找是否存在相同的,不存在的话,再从DHCP client pool中分配一个client并添加设备信息。
②、发送信号事件(Signal Event)给指定的处理进程(Process)
always_inline void
vlib_process_signal_event (vlib_main_t * vm,
uword node_index, uword type_opaque, uword data);
vm
:VLIB 主要数据结构的指针,代表 VPP 的主要执行环境。event_type
:信号事件的类型,可以是自定义的事件类型。event_data
:携带的事件数据,根据实际需要传递。process_node_index
:目标处理进程的索引,指示应该将事件发送给哪个处理进程。
这个函数用于向 VPP 中的特定处理进程发送自定义的信号事件,从而触发或通知该进程执行特定的操作或任务。这种机制可以用于 VPP 中不同处理节点之间的通信、同步或协调任务。
本处注册的client 处理进程
VLIB_REGISTER_NODE (dhcp_client_process_node,static) = {
.function = dhcp_client_process,
.type = VLIB_NODE_TYPE_PROCESS,
.name = "dhcp-client-process",
.process_log2_n_stack_bytes = 16,
.n_errors = ARRAY_LEN(dhcp_client_process_stat_strings),
.error_strings = dhcp_client_process_stat_strings,
};
③client 处理进程函数
static uword
dhcp_client_process (vlib_main_t * vm,
vlib_node_runtime_t * rt, vlib_frame_t * f)
dhcp_client_process循环检测DHCP client pool活跃设备根据设备状态持续时间以及设备状态发送对应数据包,包括dhcp_discover_state、dhcp_request_state、dhcp_bound_state。
static int
dhcp_discover_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now);
static int
dhcp_request_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now);
static int
dhcp_bound_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now);//处于“BOUND”状态的客户端可以正常地进行网络通信,它已经成功地获取了所需的网络配置信息,可以和网络中的其他设备进行通信。这个状态一般会在 DHCP 客户端成功完成租约过程后出现。主要用于续订租约、解约。
client接收到服务端的网络配置后,进行的网络配置,其中可能涉及的一些函数或模块可能包括:
- vnet/ip/ip4.h 或 vnet/ip/ip6.h:用于 IPv4 或 IPv6 配置的相关函数。比如,
ip4_set_interface_address
或ip6_set_interface_address
可能被用来设置接口地址。 - vnet/ip/ip_neighbor.h:处理邻居(Neighbor)相关的函数,用于将 IP 地址与 MAC 地址关联。
- vnet/ip/ip_source_and_port_range_check.h:用于源 IP 和端口范围检查的函数。
- vnet/ip/ip6_neighbor.h:用于 IPv6 邻居关联的函数。
(3)注册查看client信息命令模块
VLIB_CLI_COMMAND (show_dhcp_client_command, static) = {
.path = "show dhcp client",
.short_help = "show dhcp client [intfc <intfc>][verbose]",
.function = show_dhcp_client_command_fn,
};
①、读取命令参数
static clib_error_t *
show_dhcp_client_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
②、根据命令参数显示client info
static u8 *format_dhcp_client (u8 * s, va_list * va)
verbose
参数显示DHCP client详细信息
(4)其它功能函数
/*
\* dhcp_client_for_us - server-to-client callback.
\* Called from proxy_node.c:dhcp_proxy_to_client_input().
\* This function first decides that the packet in question is
\* actually for the dhcp client code in case we're also acting as
\* a dhcp proxy. Ay caramba, what a folly!
*/
int
dhcp_client_for_us (u32 bi, vlib_buffer_t * b,
ip4_header_t * ip,
udp_header_t * udp, dhcp_header_t * dhcp);
在 VPP(Vector Packet Processing)中,dhcp_client_for_us
是用于检查一个 DHCP(Dynamic Host Configuration Protocol)数据包是否适用于本地接口的 DHCP 客户端。
这个函数通常用于检查接收到的 DHCP 数据包是否是发送给本地接口的。在网络中,DHCP 客户端通常会发送 DHCP 请求以获取 IP 地址等配置信息。dhcp_client_for_us
函数用于验证接收到的 DHCP 数据包是否与本地接口相关。
这个函数的作用通常是检查数据包中的目标 IP 地址或其他标识,以确定 DHCP 数据包是否针对本地接口。如果是,接口将处理该 DHCP 数据包,并相应地进行后续操作,比如为本地设备获取 IP 地址和其他网络配置。
在实际使用中,dhcp_client_for_us
可能作为 VPP 中的数据包处理函数的一部分,用于筛选和处理适用于本地接口的 DHCP 数据包。