From 3835809adb1ce19ede2c64cb90f3f2a04f8cfc03 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Tue, 11 Nov 2025 17:33:16 +0800 Subject: [PATCH] bug fixed --- openflow.pcap | Bin 0 -> 19432 bytes openflow/main_user_openflow.c | 14 +- openflow/main_user_openflow_analysis.md | 253 ++++++++++++++++++++++++ openflow/user_openflow | Bin 291676 -> 291676 bytes 4 files changed, 260 insertions(+), 7 deletions(-) create mode 100644 openflow.pcap create mode 100644 openflow/main_user_openflow_analysis.md diff --git a/openflow.pcap b/openflow.pcap new file mode 100644 index 0000000000000000000000000000000000000000..48638631520c74ba59d33a98ef32c18d578fa392 GIT binary patch literal 19432 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 Kmzq`J$o~VU+Da$@ literal 0 HcmV?d00001 diff --git a/openflow/main_user_openflow.c b/openflow/main_user_openflow.c index 2441613..3158bbb 100644 --- a/openflow/main_user_openflow.c +++ b/openflow/main_user_openflow.c @@ -26,11 +26,11 @@ #include #include #include - -void nms_exec_action(u32 inport,u32 outport,struct eth_header *eth,int len,int hit_idx); -void pkt_print(u8 *data, u16 len); #include +extern void nms_exec_action(u32 inport,u32 outport,struct eth_header *eth,int len,int hit_idx); +extern void pkt_print(u8 *data, u16 len); + extern uintptr_t *flow_stats_addr; @@ -221,10 +221,10 @@ handle_ofpmsg_desc(struct ofp_buffer *ofpbuf) (struct ofp_buffer *)build_opfmsg_reply_ofpbuf(OFPT_MULTIPART_REPLY,ofpbuf->header.xid,reply_len); struct ofp_multipart *ofpmp_reply = (struct ofp_multipart *)ofpbuf_reply->data; - static const char *default_mfr_desc = "Wanglixuan"; - static const char *default_hw_desc = "Lixuan_OpenBox"; - static const char *default_sw_desc = "Lixuan_Driver"; - static const char *default_serial_desc = "Lixuan OpenBox Series"; + static const char *default_mfr_desc = "Chengjingyu_Networks"; + static const char *default_hw_desc = "Jingyu_OpenBox"; + static const char *default_sw_desc = "Jingyu_Driver"; + static const char *default_serial_desc = "Jingyu OpenBox Series"; static const char *default_dp_desc = "None"; ofpmp_reply->type = htons(OFPMP_DESC); diff --git a/openflow/main_user_openflow_analysis.md b/openflow/main_user_openflow_analysis.md new file mode 100644 index 0000000..62607d6 --- /dev/null +++ b/openflow/main_user_openflow_analysis.md @@ -0,0 +1,253 @@ +# `main_user_openflow.c` 函数功能详解 + +本文档详细介绍了 `main_user_openflow.c` 文件中每个函数的功能、参数和实现逻辑。该文件主要负责处理和响应来自控制器的各种 OpenFlow 1.3 (OFP13) 消息。 + +--- + +## 目录 +1. [辅助函数](#1-辅助函数) + - [`htonll`](#htonll) + - [`ntohll`](#ntohll) +2. [报文构建函数](#2-报文构建函数) + - [`build_opfmsg_header`](#build_opfmsg_header) + - [`build_opfmsg_reply_ofpbuf`](#build_opfmsg_reply_ofpbuf) +3. [OpenFlow 消息处理函数](#3-openflow-消息处理函数) + - [`handle_opfmsg_hello`](#handle_opfmsg_hello) + - [`handle_opfmsg_features_request`](#handle_opfmsg_features_request) + - [`handle_ofpmsg_get_config_request`](#handle_ofpmsg_get_config_request) + - [`handle_ofpmsg_desc`](#handle_ofpmsg_desc) + - [`handle_ofpmsg_flow_stats`](#handle_ofpmsg_flow_stats) + - [`handle_ofpmsg_aggregate`](#handle_ofpmsg_aggregate) + - [`handle_ofpmsg_table`](#handle_ofpmsg_table) + - [`handle_ofpmsg_port_stats`](#handle_ofpmsg_port_stats) + - [`handle_ofpmsg_group_features`](#handle_ofpmsg_group_features) + - [`handle_ofpmsg_port_desc`](#handle_ofpmsg_port_desc) + - [`handle_ofpmsg_packet_out`](#handle_ofpmsg_packet_out) + - [`handle__opfmsg_role_request`](#handle__opfmsg_role_request) +4. [核心回调与主函数](#4-核心回调与主函数) + - [`handle_openflow_callback`](#handle_openflow_callback) + - [`main`](#main) + +--- + +## 1. 辅助函数 + +### `htonll` +```c +static inline uint64_t htonll(uint64_t n) +``` +- **功能**: 将64位无符号整数从主机字节序(Host Byte Order)转换网络字节序(Network Byte Order)。 +- **参数**: + - `n`: 需要转换的64位无符号整数。 +- **返回值**: 转换后的网络字节序64位整数。 +- **逻辑**: 通过检查 `htonl(1)` 的结果来判断当前系统是否为大端序。如果是小端序,则将高32位和低32位分别转换后交换位置。 + +### `ntohll` +```c +static inline uint64_t ntohll(uint64_t n) +``` +- **功能**: 将64位无符号整数从网络字节序转换为主机字节序。 +- **参数**: + - `n`: 需要转换的64位网络字节序整数。 +- **返回值**: 转换后的主机字节序64位整数。 +- **逻辑**: 与 `htonll` 类似,根据系统的大小端情况进行相应的转换。 + +--- + +## 2. 报文构建函数 + +### `build_opfmsg_header` +```c +void build_opfmsg_header(struct ofp_header *ofpbuf_header, uint16_t len, uint8_t type, uint32_t xid) +``` +- **功能**: 构建一个标准的 OpenFlow 报文头。 +- **参数**: + - `ofpbuf_header`: 指向 `ofp_header` 结构体的指针,用于填充报文头信息。 + - `len`: 整个 OpenFlow 报文的总长度。 + - `type`: OpenFlow 报文的类型 (例如 `OFPT_HELLO`, `OFPT_FEATURES_REPLY` 等)。 + - `xid`: 事务ID (Transaction ID),用于匹配请求和响应。 +- **逻辑**: + 1. 设置版本号为 `OFP13_VERSION` (0x04)。 + 2. 使用 `htons` 将长度 `len` 转换网络字节序后填充。 + 3. 设置报文类型 `type`。 + 4. 设置事务ID `xid`。 + +### `build_opfmsg_reply_ofpbuf` +```c +u8 *build_opfmsg_reply_ofpbuf(uint8_t type, uint32_t xid, uint16_t len) +``` +- **功能**: 分配内存并构建一个用于回复的 OpenFlow 报文缓冲区。 +- **参数**: + - `type`: 回复报文的类型。 + - `xid`: 对应请求报文的事务ID。 + - `len`: 回复报文的总长度。 +- **返回值**: 指向新分配和初始化的报文缓冲区的指针 (`u8 *`)。 +- **逻辑**: + 1. 使用 `malloc` 分配指定长度 `len` 的内存。 + 2. 使用 `memset` 将分配的内存清零。 + 3. 调用 `build_opfmsg_header` 函数填充报文的头部信息。 + 4. 返回指向该缓冲区的指针。 + +--- + +## 3. OpenFlow 消息处理函数 + +这些函数遵循 `handle_openflow_callback` 的规范,返回 `HANDLE` (0x1) 表示消息已处理,返回 `CONTINUE` (0x2) 表示未处理。 + +### `handle_opfmsg_hello` +- **对应消息**: `OFPT_HELLO` +- **功能**: 处理与控制器建立连接时的 `HELLO` 消息。 +- **逻辑**: + 1. 检查接收到的 `HELLO` 消息中的 OpenFlow 版本号。 + 2. 如果版本号是 `0x04` (OpenFlow 1.3),则打印 "RECV HELLO!"。 + 3. 如果版本号不匹配,则构建一个 `OFPT_ERROR` 消息并发送给控制器,表明版本不兼容。 + 4. 返回 `HANDLE` 表示消息已处理。 + +### `handle_opfmsg_features_request` +- **对应消息**: `OFPT_FEATURES_REQUEST` +- **功能**: 响应控制器查询交换机功能的请求。 +- **逻辑**: + 1. 构建一个 `OFPT_FEATURES_REPLY` 类型的回复报文。 + 2. 填充 `ofp_switch_features` 结构体,包含交换机的功能信息,如: + - `datapath_id`: 交换机的唯一标识符。 + - `n_buffers`: 交换机可以缓存的数据包数量。 + - `n_tables`: 支持的流表数量(此处硬编码为1)。 + - `capabilities`: 支持的特性(如流统计、端口统计等)。 + 3. 发送该回复报文给控制器。 + 4. 返回 `HANDLE`。 + +### `handle_ofpmsg_get_config_request` +- **对应消息**: `OFPT_GET_CONFIG_REQUEST` +- **功能**: 响应控制器查询交换机配置的请求。 +- **逻辑**: + 1. 构建一个 `OFPT_GET_CONFIG_REPLY` 类型的回复报文。 + 2. 填充 `ofp_switch_config` 结构体,包含交换机的配置信息,如: + - `flags`: 配置标志。 + - `miss_send_len`: 当发生 table-miss 时,发送到控制器的报文最大长度。 + 3. 发送该回复报文。 + 4. 返回 `HANDLE`。 + +### `handle_ofpmsg_desc` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_DESC`) +- **功能**: 响应控制器查询交换机描述信息的请求。 +- **逻辑**: + 1. 构建一个 `OFPT_MULTIPART_REPLY` 类型的回复报文。 + 2. 设置 multipart 类型为 `OFPMP_DESC`。 + 3. 填充 `ofp_desc_stats` 结构体,包含制造商、硬件、软件、序列号等描述信息(此处使用硬编码的字符串)。 + 4. 发送该回复报文。 + 5. 返回 `HANDLE`。 + +### `handle_ofpmsg_flow_stats` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_FLOW`) +- **功能**: 响应控制器查询流表统计信息的请求。 +- **逻辑**: + 1. 遍历全局流表统计地址数组 `flow_stats_addr`,计算所有有效流表项的总长度。 + 2. 构建一个足够大的 `OFPT_MULTIPART_REPLY` 回复报文。 + 3. 设置 multipart 类型为 `OFPMP_FLOW`。 + 4. 再次遍历 `flow_stats_addr`,将每个有效的流表统计信息 (`ofp_flow_stats`) 拷贝到回复报文中。 + 5. 发送该回复报文。 + 6. 返回 `HANDLE`。 + +### `handle_ofpmsg_aggregate` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_AGGREGATE`) +- **功能**: 响应控制器查询聚合统计信息(总流数、总包数、总字节数)的请求。 +- **逻辑**: + 1. 构建一个 `OFPT_MULTIPART_REPLY` 回复报文,类型为 `OFPMP_AGGREGATE`。 + 2. 初始化 `flow_count`, `packet_count`, `byte_count` 为 0。 + 3. 遍历 `flow_stats_addr`,累加每个流的包计数和字节计数,并统计流的数量。 + - **注意**: 此处代码会更新每个流的 `duration_sec` 和 `duration_nsec`,并为 `packet_count` 和 `byte_count` 填充了硬编码的示例值。 + 4. 将聚合统计结果填充到 `ofp_aggregate_stats_reply` 结构体中。 + 5. 发送该回复报文。 + 6. 返回 `HANDLE`。 + +### `handle_ofpmsg_table` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_TABLE`) +- **功能**: 响应控制器查询流表自身统计信息的请求。 +- **逻辑**: + 1. 构建一个 `OFPT_MULTIPART_REPLY` 回复报文,类型为 `OFPMP_TABLE`。 + 2. 填充 `ofp_table_stats` 结构体,包含活动流表项数量、查询次数、匹配次数等信息(此处硬编码为1个流表,活动数量为1)。 + 3. 发送该回复报文。 + 4. 返回 `HANDLE`。 + +### `handle_ofpmsg_port_stats` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_PORT_STATS`) +- **功能**: 响应控制器查询端口统计信息的请求。 +- **逻辑**: + 1. 根据全局端口信息结构体 `nmps` 中的端口数量 `cnt`,构建一个 `OFPT_MULTIPART_REPLY` 回复报文。 + 2. 设置 multipart 类型为 `OFPMP_PORT_STATS`。 + 3. 遍历所有端口,将每个端口的统计信息 `nmps.ports[i].stats` 拷贝到回复报文中,并计算和填充端口的活动时间。 + 4. 发送该回复报文。 + 5. 返回 `HANDLE`。 + +### `handle_ofpmsg_group_features` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_GROUP_FEATURES`) +- **功能**: 响应控制器查询交换机组表(Group Table)特性的请求。 +- **逻辑**: + 1. 构建一个 `OFPT_MULTIPART_REPLY` 回复报文。 + 2. 填充 `ofp_group_features` 结构体,设置其类型为 `OFPMP_GROUP_FEATURES`。 + 3. 发送该回复报文。 + 4. 返回 `HANDLE`。 + +### `handle_ofpmsg_port_desc` +- **对应消息**: `OFPT_MULTIPART_REQUEST` (子类型 `OFPMP_PORT_DESC`) +- **功能**: 响应控制器查询端口描述信息的请求。 +- **逻辑**: + 1. 根据全局端口信息结构体 `nmps` 中的端口数量 `cnt`,构建一个 `OFPT_MULTIPART_REPLY` 回复报文。 + 2. 设置 multipart 类型为 `OFPMP_PORT_DESC`。 + 3. 遍历所有端口,将每个端口的状态描述信息 `nmps.ports[i].state` 拷贝到回复报文中。 + 4. 发送该回复报文。 + 5. 返回 `HANDLE`。 + +### `handle_ofpmsg_packet_out` +- **对应消息**: `OFPT_PACKET_OUT` +- **功能**: 处理控制器下发的 `Packet Out` 消息,该消息指示交换机将特定数据包通过指定端口发送出去。 +- **逻辑**: + 1. 解析 `ofp_packet_out` 消息,提取出 `in_port`(入端口)、`actions_len`(动作列表长度)以及附带的数据包(`eth`)。 + 2. 检查 `actions_len`: + - 如果为 0,表示没有指定动作,默认执行泛洪(`OFPP_FLOOD`)。 + - 如果不为 0,则遍历动作列表。 + 3. 对于 `OFPAT_OUTPUT` 类型的动作,提取 `port`(出端口),并调用 `nms_exec_action` 函数将数据包从指定端口发送出去。 + 4. 返回 `HANDLE`。 + +### `handle__opfmsg_role_request` +- **对应消息**: `OFPT_ROLE_REQUEST` +- **功能**: 处理控制器设置或查询交换机角色的请求(如 Master, Slave)。 +- **逻辑**: + 1. 构建一个 `OFPT_ROLE_REPLY` 类型的回复报文。 + 2. 将请求中的角色信息 (`ofp_role`) 直接拷贝到回复报文中。 + 3. 发送该回复报文。 + 4. 返回 `HANDLE`。 + +--- + +## 4. 核心回调与主函数 + +### `handle_openflow_callback` +```c +int handle_openflow_callback(struct ofp_buffer *ofpbuf, int len) +``` +- **功能**: 这是注册给 OpenFlow 库的核心回调函数,作为所有进入的 OpenFlow 消息的分发中枢。 +- **参数**: + - `ofpbuf`: 指向包含 OpenFlow 消息的缓冲区的指针。 + - `len`: 消息的总长度。 +- **返回值**: + - `HANDLE` (0x1): 如果消息被此回调中的某个函数处理了。 + - `CONTINUE` (0x2): 如果消息类型不被支持或未被处理,交由后续处理。 +- **逻辑**: + 1. 从报文头中提取消息类型 `oftype`。 + 2. 使用 `switch` 语句根据 `oftype` 将消息分发给对应的 `handle_...` 函数。 + 3. 对于 `OFPT_MULTIPART_REQUEST` 类型的消息,会进一步检查其子类型(`multipart->type`),并分发给相应的处理函数(如 `handle_ofpmsg_desc`, `handle_ofpmsg_flow_stats` 等)。 + 4. 如果 `switch` 语句中没有匹配的类型,则打印未处理信息并返回 `CONTINUE`。 + +### `main` +```c +int main(int argc, char* argv[]) +``` +- **功能**: 程序的主入口点。 +- **逻辑**: + 1. 调用 `ofp_init(argc, argv)` 初始化 OpenFlow 环境。 + 2. 定义一个 `mask` 变量,用于指定程序希望监听和处理哪些类型的 OpenFlow 消息。 + 3. 通过位或运算 (`|`) 将多个消息类型的掩码(如 `MASK_HELLO`, `MASK_FEATURES_REQUEST` 等)组合起来,赋值给 `mask`。 + 4. 调用 `openflow_hook_init(mask, handle_openflow_callback)`,将 `mask` 和核心回调函数 `handle_openflow_callback` 注册到 OpenFlow 库。这样,只有 `mask` 中指定类型的消息到达时,`handle_openflow_callback` 才会被调用。 + 5. 调用 `pause()`,使程序进入挂起状态,等待网络事件(即等待 OpenFlow 消息的到来)。 + 6. 程序将在此处循环等待和处理消息,直到被终止。 diff --git a/openflow/user_openflow b/openflow/user_openflow index 3207c7251747a791b5bcc7265eb4dd40851fe7f3..b6654539459e176d1527ee71b9bb09b16cfe485a 100755 GIT binary patch delta 13411 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