openflow lab finished maybe

This commit is contained in:
2025-11-12 08:14:29 +08:00
parent 3835809adb
commit 11f2d26fce
7 changed files with 357 additions and 110 deletions

Binary file not shown.

40
openflow/GEMINI.md Normal file
View File

@ -0,0 +1,40 @@
# Project Overview
This project is an OpenFlow agent written in C. It implements a subset of the OpenFlow 1.3 protocol to allow a remote controller to manage a network switch. The agent is designed to run on an ARM-based device.
The core logic resides in `main_user_openflow.c`, which handles various OpenFlow message types such as `HELLO`, `FEATURES_REQUEST`, `GET_CONFIG_REQUEST`, and `PACKET_OUT`. The agent responds to these messages by sending back appropriate replies, allowing the controller to inspect and manage the switch's state.
The project is built using a `Makefile` and links against several local libraries, including `libofp` (for OpenFlow protocol handling) and `libnet` (for network packet manipulation).
# Building and Running
## Building
To build the project, you can use the provided `Makefile`. The `Makefile` uses the `arm-linux-gnueabihf-gcc` cross-compiler, so you'll need to have that installed and in your `PATH`.
```bash
# To build the project
make
```
This will create an executable file named `user_openflow` in the project's root directory.
## Running
The `user_openflow` executable can only be run on the target ARM device. Based on the comment at the end of `main_user_openflow.c`, the following command can be used to run the agent:
```bash
sudo ./user_openflow -c eth0 -i obx0,obx1,obx2,obx3
```
* `-c eth0`: Specifies the control interface.
* `-i obx0,obx1,obx2,obx3`: Specifies the data plane interfaces.
The agent will then listen for incoming connections from an OpenFlow controller.
# Development Conventions
* **Coding Style:** The code follows a C-style with a focus on clarity and modularity. Functions are well-documented with comments explaining their purpose, parameters, and return values.
* **Testing:** There is a Python script `openflow_flow-test.py`, which suggests that testing is done using Python scripts.
* **Dependencies:** The project relies on several pre-compiled libraries located in the `lib/` directory. Any new dependencies should be added there.
* **Architecture:** The main application logic is event-driven, with a central callback function that dispatches OpenFlow messages to their respective handlers. This makes it easy to extend the agent by adding new handlers for additional OpenFlow message types.

View File

@ -27,6 +27,7 @@
#include <main_libofp.h>
#include <ofp_v4.h>
#include <stdint.h>
#include <openboxS4.h>
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);
@ -315,8 +316,9 @@ handle_ofpmsg_aggregate(struct ofp_buffer *ofpbuf)
if (flow_stats_addr[i] != 0) {
((struct ofp_flow_stats *)flow_stats_addr[i])->duration_sec = htonl(tv.tv_sec - flow_stats_time[i].tv_sec);
((struct ofp_flow_stats *)flow_stats_addr[i])->duration_nsec = htonl(tv.tv_usec - flow_stats_time[i].tv_usec);
((struct ofp_flow_stats *)flow_stats_addr[i])->packet_count = ((uint64_t)0x100); // 涉及硬件地址拼尽全力无法找到姑且填充256
((struct ofp_flow_stats *)flow_stats_addr[i])->byte_count = ((uint64_t)0x40000); // 涉及硬件地址拼尽全力无法找到姑且填充262144=256*1024
// Read packet and byte counts from hardware registers
((struct ofp_flow_stats *)flow_stats_addr[i])->packet_count = fast_reg_rd(FAST_OFP_FLOW_STATS_PKTS + i * sizeof(uint64_t));
((struct ofp_flow_stats *)flow_stats_addr[i])->byte_count = fast_reg_rd(FAST_OFP_FLOW_STATS_BYTES + i * sizeof(uint64_t));
packet_count += ((struct ofp_flow_stats *)flow_stats_addr[i])->packet_count;
byte_count += ((struct ofp_flow_stats *)flow_stats_addr[i])->byte_count;

View File

@ -5,50 +5,57 @@
---
## 目录
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)
- [`main_user_openflow.c` 函数功能详解](#main_user_openflowc-函数功能详解)
- [目录](#目录)
- [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位无符号整数。
- `n`: 需要转换的64位无符号整数。
- **返回值**: 转换后的网络字节序64位整数。
- **逻辑**: 通过检查 `htonl(1)` 的结果来判断当前系统是否为大端序。如果是小端序则将高32位和低32位分别转换后交换位置。
### `ntohll`
```c
static inline uint64_t ntohll(uint64_t n)
```
- **功能**: 将64位无符号整数从网络字节序转换为主机字节序。
- **参数**:
- `n`: 需要转换的64位网络字节序整数。
- `n`: 需要转换的64位网络字节序整数。
- **返回值**: 转换后的主机字节序64位整数。
- **逻辑**: 与 `htonll` 类似,根据系统的大小端情况进行相应的转换。
@ -57,36 +64,40 @@ static inline uint64_t ntohll(uint64_t n)
## 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),用于匹配请求和响应。
- `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`
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`: 回复报文的总长度。
- `type`: 回复报文的类型。
- `xid`: 对应请求报文的事务ID。
- `len`: 回复报文的总长度。
- **返回值**: 指向新分配和初始化的报文缓冲区的指针 (`u8 *`)。
- **逻辑**:
1. 使用 `malloc` 分配指定长度 `len` 的内存。
2. 使用 `memset` 将分配的内存清零。
3. 调用 `build_opfmsg_header` 函数填充报文的头部信息。
4. 返回指向该缓冲区的指针。
1. 使用 `malloc` 分配指定长度 `len` 的内存。
2. 使用 `memset` 将分配的内存清零。
3. 调用 `build_opfmsg_header` 函数填充报文的头部信息。
4. 返回指向该缓冲区的指针。
---
@ -95,159 +106,175 @@ u8 *build_opfmsg_reply_ofpbuf(uint8_t type, uint32_t xid, uint16_t len)
这些函数遵循 `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` 表示消息已处理。
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` 结构体,包含交换机的功能信息,如:
1. 构建一个 `OFPT_FEATURES_REPLY` 类型的回复报文。
2. 填充 `ofp_switch_features` 结构体,包含交换机的功能信息,如:
- `datapath_id`: 交换机的唯一标识符。
- `n_buffers`: 交换机可以缓存的数据包数量。
- `n_tables`: 支持的流表数量此处硬编码为1
- `capabilities`: 支持的特性(如流统计、端口统计等)。
3. 发送该回复报文给控制器。
4. 返回 `HANDLE`
3. 发送该回复报文给控制器。
4. 返回 `HANDLE`
### `handle_ofpmsg_get_config_request`
- **对应消息**: `OFPT_GET_CONFIG_REQUEST`
- **功能**: 响应控制器查询交换机配置的请求。
- **逻辑**:
1. 构建一个 `OFPT_GET_CONFIG_REPLY` 类型的回复报文。
2. 填充 `ofp_switch_config` 结构体,包含交换机的配置信息,如:
1. 构建一个 `OFPT_GET_CONFIG_REPLY` 类型的回复报文。
2. 填充 `ofp_switch_config` 结构体,包含交换机的配置信息,如:
- `flags`: 配置标志。
- `miss_send_len`: 当发生 table-miss 时,发送到控制器的报文最大长度。
3. 发送该回复报文。
4. 返回 `HANDLE`
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`
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`
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`,累加每个流的包计数和字节计数,并统计流的数量。
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`
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`
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`
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`
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`
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`
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`
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`
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`: 消息的总长度。
- `ofpbuf`: 指向包含 OpenFlow 消息的缓冲区的指针。
- `len`: 消息的总长度。
- **返回值**:
- `HANDLE` (0x1): 如果消息被此回调中的某个函数处理了。
- `CONTINUE` (0x2): 如果消息类型不被支持或未被处理,交由后续处理。
- `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`
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. 程序将在此处循环等待和处理消息,直到被终止。
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. 程序将在此处循环等待和处理消息,直到被终止。

178
openflow/openflow.log Normal file
View File

@ -0,0 +1,178 @@
hnxs@NESystem-NetEXP:~/case/openflow$ sudo ./user_openflow -4 127.0.0.1 -c eth0 -i obx0,obx1,obx2,obx3
fastU->REG Version:20180827,OpenBox HW Version:2030200729,Base_addr:43c00000
port_name:eth0,port:0
port_name:obx0,port:0
port_name:obx1,port:1
port_name:obx2,port:2
port_name:obx3,port:3
fastU->librule version:20181015,Default Action:0x40000080
user_openflow)Connect to SDN Controller [ 127.0.0.1:6653 ] OK!
send openflow messages to openflow_msg_callback !!
header.version:6, type:0, len:16
header.version:6
ofpbuf_header->length=8
ofpbuf_reply,malloc:0xb3505478,type:1,len:8
NO CONNECTED!
send openflow messages to openflow_msg_callback !!
header.version:4, type:5, len:8
ofpbuf_header->length=32
ofpbuf_reply,malloc:0xb3505488,type:6,len:32
send openflow messages to openflow_msg_callback !!
header.version:4, type:18, len:16
ofpbuf_header->length=336
ofpbuf_reply,malloc:0xb35054b0,type:19,len:336
send openflow messages to openflow_msg_callback !!
header.version:4, type:7, len:8
ofpbuf_header->length=12
ofpbuf_reply,malloc:0xb3505478,type:8,len:12
send openflow messages to openflow_msg_callback !!
header.version:4, type:18, len:16
ofpbuf_header->length=1072
ofpbuf_reply,malloc:0xb3505478,type:19,len:1072
send openflow messages to openflow_msg_callback !!
header.version:4, type:18, len:16
Unsupported multipart request type: 12
send openflow messages to openflow_msg_callback !!
header.version:4, type:24, len:24
ofpbuf_header->length=24
ofpbuf_reply,malloc:0xb3505478,type:25,len:24
0_nms_of13)>> handle__opfmsg_role_request :main_user_openflow.c[515]
0_nms_of13)<< handle__opfmsg_role_request :main_user_openflow.c[519]
0_nms_of13)DELETE ALL RULE!
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx0 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx1 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx2 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx3 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx0 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx1 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx2 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx3 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
eth0 ADD!
obx0 ADD!
obx1 ADD!
obx2 ADD!
obx2(0x36f58) Start...
obx1(0x348d8) Start...
obx0(0x32410) Start...
obx3(0x39340) Start...
obx3 ADD!
fastU->PKT__IN-obx0 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! reason:NO MATCH[0]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:138
fastU->PKT_OUT-obx1 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! [ in:0x00000001 ]
fastU->PKT_OUT-obx2 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! [ in:0x00000001 ]
fastU->PKT_OUT-obx3 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! [ in:0x00000001 ]
fastU->PKT__IN-obx3 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! reason:NO MATCH[0]
FLOW_MOD->Output:0x0001,len:16,max_len:0xFFFF,action:30000000
Flow mod ADD(0) 30000000,Aging time:1762854049(5)
0_nms_of13)ADD HW NEW(0) RULE!
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:138
fastU->PKT_OUT-obx0 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! [ in:0x00000004 ]
fastU->PKT__IN-obx0 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! reason:NO MATCH[0]
FLOW_MOD->Output:0x0004,len:16,max_len:0xFFFF,action:30000003
Flow mod ADD(1) 30000003,Aging time:1762854050(5)
0_nms_of13)ADD HW NEW(1) RULE!
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:138
fastU->PKT_OUT-obx3 IPv4 [ 0x0800 ]/[ 1 ] Packet len:98 OK! [ in:0x00000001 ]
obx1 DELETE!
obx2 DELETE!
fastU->PKT__IN-obx3 ARP [ 0x0806 ]/[ 0 ] Packet len:60 OK! reason:NO MATCH[0]
FLOW_MOD->Output:0x0001,len:16,max_len:0xFFFF,action:30000000
Flow mod ADD(2) 30000000,Aging time:1762854054(5)
0_nms_of13)ADD HW NEW(2) RULE!
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:100
fastU->PKT_OUT-obx0 ARP [ 0x0806 ]/[ 0 ] Packet len:60 OK! [ in:0x00000004 ]
fastU->PKT__IN-obx0 ARP [ 0x0806 ]/[ 0 ] Packet len:60 OK! reason:NO MATCH[0]
FLOW_MOD->Output:0x0004,len:16,max_len:0xFFFF,action:30000003
Flow mod ADD(3) 30000003,Aging time:1762854054(5)
0_nms_of13)ADD HW NEW(3) RULE!
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:100
fastU->PKT_OUT-obx3 ARP [ 0x0806 ]/[ 0 ] Packet len:60 OK! [ in:0x00000001 ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx3 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx0 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx3 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx0 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
Aging Rule Delay 0,add 5s
Aging Rule Delay 1,add 5s
Aging Rule Delete 2 start(1762854049)--end(now:1762854055,aging:1762854054)
Aging Rule Delete 3 start(1762854049)--end(now:1762854055,aging:1762854054)
Aging Rule Delay 0,add 5s
Aging Rule Delete 1 start(1762854045)--end(now:1762854061,aging:1762854060)
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx3 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx0 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx3 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx0 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
Aging Rule Delete 0 start(1762854044)--end(now:1762854070,aging:1762854069)
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx3 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx0 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx3 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx0 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx3 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx0 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx3 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx0 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx3 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:115
fastU->PKT_OUT-obx0 LLDP [ 0x88CC ]/[ 0 ] Packet len:75 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx3 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]
send openflow messages to openflow_msg_callback !!
header.version:4, type:13, len:123
fastU->PKT_OUT-obx0 ETHX [ 0x8942 ]/[ 0 ] Packet len:83 OK! [ in:0xFFFFFFFD ]

BIN
openflow/openflow.pcap Normal file

Binary file not shown.

Binary file not shown.