openbox lab report initialized

This commit is contained in:
2025-11-21 01:38:25 +08:00
parent fec271fcaa
commit 404cac344f
20 changed files with 18008 additions and 2 deletions

View File

@ -0,0 +1,627 @@
/***************************************************************************
* main_opfmsg.c
*
* 2017/02/28 15:52:34 星期二
* Copyright 2017 XuDongLai
* <XuDongLai0923@163.com>
****************************************************************************/
/*
* main_opfmsg.c
*
* Copyright (C) 2017 - XuDongLai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <fast.h>
#include <main_libofp.h>
#include <ofp_v4.h>
extern uint64_t *flow_stats_addr;
extern struct timeval flow_stats_time[];
extern struct nms_ports_info nmps;
extern struct timeval start_tv;
/**
* @brief
*
* @param n
*
* @return
*/
/*64位主机序转网络序*/
static inline uint64_t
htonll(uint64_t n)
{
return htonl(1) == 1 ? n : (((uint64_t)htonl(n)) << 32) | htonl(n >> 32);
}
/*64位网络序转主机序*/
/**
* @brief
*
* @param n
*
* @return
*/
static inline uint64_t
ntohll(uint64_t n)
{
return htonl(1) == 1 ? n : (((uint64_t)ntohl(n)) << 32) | ntohl(n >> 32);
}
/**
* @brief 构建OpenFlow报文头
*
* 该函数用于填充OpenFlow报文头包括版本、长度、类型和事务ID。
*
* @param ofpbuf_header OpenFlow报文头结构体指针
* @param len 报文长度
* @param type 报文类型
* @param xid 事务ID
*/
void build_opfmsg_header(struct ofp_header *ofpbuf_header,uint16_t len,uint8_t type,uint32_t xid)
{
ofpbuf_header->version = OFP13_VERSION;
ofpbuf_header->length = htons(len);
ofpbuf_header->type = type;
ofpbuf_header->xid = xid;
printf("ofpbuf_header->length=%d\n",ntohs(ofpbuf_header->length));
}
/**
* @brief 构建OpenFlow回应报文
*
* 该函数用于构建并返回一个OpenFlow回应报文报文类型和长度由参数指定。
*
* @param type 报文类型
* @param xid 事务ID
* @param len 报文长度
*
* @return 返回构建的报文缓冲区指针
*/
u8 *build_opfmsg_reply_ofpbuf(uint8_t type,uint32_t xid,uint16_t len)
{
struct ofp_header *reply = (struct ofp_header *)malloc(len);
memset((u8 *)reply,0,len);
build_opfmsg_header(reply,len,type,xid);
printf("ofpbuf_reply,malloc:%p,type:%d,len:%d\n",reply,type,len);
return (u8 *)reply;
}
/**
* @brief 处理OpenFlow Hello消息
*
* 该函数用于处理接收到的OpenFlow Hello消息。如果协议版本不是1.3,则发送错误消息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_opfmsg_hello(struct ofp_buffer *ofpbuf)
{
printf("header.version:%d\n",ofpbuf->header.version);
if(ofpbuf->header.version == 0x04)
{
printf("RECV HELLO!\n\n\n");
}else //不是openflow1.3协议则发送error消息
{
int reply_len = sizeof(struct ofp_header);
//填充openflow协议头协议类型为OFPT_ERROR
struct ofp_buffer *ofpbuf_reply =
(struct ofp_buffer *)build_reply_ofpbuf(OFPT_ERROR,ofpbuf->header.xid,reply_len);
//打印error消息
pkt_print((u8 *)ofpbuf,htons(ofpbuf->header.length));
//发送error消息
send_openflow_message(ofpbuf_reply,reply_len);
}
//返回已处理状态码
return HANDLE;
}
/**
* @brief 处理OpenFlow Features Request消息
*
* 该函数用于处理接收到的OpenFlow Features Request消息并返回交换机的功能信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_opfmsg_features_request(struct ofp_buffer *ofpbuf)
{
int feature_reply_len = sizeof(struct ofp_switch_features)+sizeof(struct ofp_header);
//填充openflow协议头协议类型为 OFPT_FEATURES_REPLY
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_opfmsg_reply_ofpbuf(OFPT_FEATURES_REPLY,
ofpbuf->header.xid,feature_reply_len);
//获取交换机的功能信息 指针变量 feature_reply_msg
struct ofp_switch_features *feature_reply_msg =(struct ofp_switch_features *)ofpbuf_reply->data;
//TODO
/* 构建feature回应报文把交换机的功能信息发送给控制器指针变量feature_reply_msg赋值 */
feature_reply_msg->datapath_id = 0x6655443322110000;
feature_reply_msg->n_buffers = 0x100;
feature_reply_msg->n_tables = 0x02;
feature_reply_msg->auxiliary_id = 0;
feature_reply_msg->capabilities = htonl(0x0000004f);
feature_reply_msg->reserved = htonl(0x00000000);
// feature_reply_msg->datapath_id = htonll(0x1234 << 48);
// feature_reply_msg->n_buffers = 0x100; // 256
// feature_reply_msg->n_tables = 1;
// feature_reply_msg->auxiliary_id = 0;
// feature_reply_msg->capabilities = htonl(0x0007);
// feature_reply_msg->reserved = htonl(0x0000);
//调用系统发送接口,发送回应报文
send_openflow_message(ofpbuf_reply,feature_reply_len);
//返回已处理状态码
return HANDLE;
}
/**
* @brief 处理OpenFlow Get Config Request消息
*
* 该函数用于处理接收到的OpenFlow Get Config Request消息并返回交换机的配置信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_get_config_request(struct ofp_buffer *ofpbuf)
{
int reply_len = sizeof(struct ofp_switch_config)+sizeof(struct ofp_header);
//填充openflow协议头协议类型为 OFPT_GET_CONFIG_REPLY
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_GET_CONFIG_REPLY,
ofpbuf->header.xid,reply_len);
struct ofp_switch_config *switch_config_reply =(struct ofp_switch_config *)ofpbuf_reply->data;
switch_config_reply->flags = htons(0x0000);
switch_config_reply->miss_send_len = htons(0xffe5); //65509,基于协议
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Description Request消息
*
* 该函数用于处理接收到的OpenFlow Description Request消息并返回交换机的描述信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_desc(struct ofp_buffer *ofpbuf)
{
int reply_len = sizeof(struct ofp_header)+sizeof(struct ofp_multipart)+sizeof(struct ofp_desc_stats);
struct ofp_buffer *ofpbuf_reply =
(struct ofp_buffer *)build_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 = "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);
ofpmp_reply->flags = htonl(OFPMP_REPLY_MORE_NO);
snprintf(ofpmp_reply->ofpmp_desc[0].mfr_desc, sizeof ofpmp_reply->ofpmp_desc[0].mfr_desc, "%s", default_mfr_desc);
snprintf(ofpmp_reply->ofpmp_desc[0].hw_desc, sizeof ofpmp_reply->ofpmp_desc[0].hw_desc, "%s", default_hw_desc);
snprintf(ofpmp_reply->ofpmp_desc[0].sw_desc, sizeof ofpmp_reply->ofpmp_desc[0].sw_desc, "%s", default_sw_desc);
snprintf(ofpmp_reply->ofpmp_desc[0].serial_num, sizeof ofpmp_reply->ofpmp_desc[0].serial_num, "%s", default_serial_desc);
snprintf(ofpmp_reply->ofpmp_desc[0].dp_desc, sizeof ofpmp_reply->ofpmp_desc[0].dp_desc, "%s", default_dp_desc);
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Flow Stats Request消息
*
* 该函数用于处理接收到的OpenFlow Flow Stats Request消息并返回流统计信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_flow_stats(struct ofp_buffer *ofpbuf)
{
int i = 0, reply_len = 0, flow_stats_offset;
struct ofp_flow_stats *current_flow_stats = NULL;
struct ofp_buffer *reply_buffer = NULL;
struct ofp_multipart *multipart_reply = NULL;
// 计算长度
for (; i < FAST_RULE_CNT; i++) {
if (flow_stats_addr[i] != NULL) {
reply_len += ntohs(((struct ofp_flow_stats *)flow_stats_addr[i])->length);
}
}
reply_len += sizeof(struct ofp_header) + sizeof(struct ofp_multipart);
// 构造响应包
reply_buffer = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_MULTIPART_REPLY, ofpbuf->header.xid, reply_len);
multipart_reply = (struct ofp_multipart *)reply_buffer->data;
multipart_reply->type = htons(OFPMP_FLOW); // 标识信息
multipart_reply->flags = htonl(OFPMP_REPLY_MORE_NO); //这条不用回
// 填充包体
flow_stats_offset = sizeof(struct ofp_multipart);
current_flow_stats = (struct ofp_flow_stats *)&reply_buffer->data[flow_stats_offset];
for (i = 0; i < FAST_RULE_CNT; i++) {
if (flow_stats_addr[i] != NULL) {
memcpy(current_flow_stats, flow_stats_addr[i], ntohs(((struct ofp_flow_stats *)flow_stats_addr[i])->length));
flow_stats_offset += ntohs(current_flow_stats->length);
current_flow_stats = (struct ofp_flow_stats *)&reply_buffer->data[flow_stats_offset];
}
}
send_openflow_message(reply_buffer, reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Aggregate Stats Request消息
*
* 该函数用于处理接收到的OpenFlow Aggregate Stats Request消息并返回聚合统计信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_aggregate(struct ofp_buffer *ofpbuf)
{
int reply_len = sizeof(struct ofp_header)+ sizeof(struct ofp_multipart)+sizeof(struct ofp_aggregate_stats_reply);
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_MULTIPART_REPLY,
ofpbuf->header.xid,reply_len);
struct ofp_multipart *ofpmp_reply = (struct ofp_multipart *)ofpbuf_reply->data;
int i = 0,flow_count = 0;
u64 byte_count = 0,packet_count = 0;
struct timeval tv;
ofpmp_reply->type = htons(OFPMP_AGGREGATE);
ofpmp_reply->flags = htonl(OFPMP_REPLY_MORE_NO);
gettimeofday(&tv, NULL);
for (; i < FAST_RULE_CNT; i++) {
if (flow_stats_addr[i] != NULL) {
((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
// 从硬件寄存器读取数据包计数和字节计数
((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;
flow_count++;
}
}
ofpmp_reply->ofpmp_aggregate_reply[0].packet_count = packet_count;
ofpmp_reply->ofpmp_aggregate_reply[0].byte_count = byte_count;
ofpmp_reply->ofpmp_aggregate_reply[0].flow_count = flow_count;
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Table Stats Request消息
*
* 该函数用于处理接收到的OpenFlow Table Stats Request消息并返回表统计信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_table(struct ofp_buffer *ofpbuf)
{
int i = 0;
int reply_len = sizeof(struct ofp_header)+sizeof(struct ofp_multipart)+
sizeof(struct ofp_table_stats)*1;
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_MULTIPART_REPLY,
ofpbuf->header.xid,reply_len);
struct ofp_multipart *ofpmp_reply = (struct ofp_multipart *)ofpbuf_reply->data;
ofpmp_reply->type = htons(OFPMP_TABLE);
ofpmp_reply->flags = htonl(OFPMP_REPLY_MORE_NO);
for(i=0;i<1;i++)
{
ofpmp_reply->table_stats[i].matched_count = htonll(0);
ofpmp_reply->table_stats[i].table_id = i;
ofpmp_reply->table_stats[i].lookup_count = htonll(0);
ofpmp_reply->table_stats[i].active_count = htonl(1);
}
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Port Stats Request消息
*
* 该函数用于处理接收到的OpenFlow Port Stats Request消息并返回端口统计信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_port_stats(struct ofp_buffer *ofpbuf)
{
int i = 0;
int reply_len = sizeof(struct ofp_header)+sizeof(struct ofp_multipart)+
sizeof(struct ofp_port_stats)*nmps.cnt;
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_MULTIPART_REPLY,
ofpbuf->header.xid,reply_len);
struct ofp_multipart *ofpmp_reply = (struct ofp_multipart *)ofpbuf_reply->data;
struct timeval tv;
ofpmp_reply->type = htons(OFPMP_PORT_STATS);
ofpmp_reply->flags = htonl(OFPMP_REPLY_MORE_NO);
for(i=0;i<nmps.cnt;i++){
gettimeofday(&tv,NULL);
ofpmp_reply->ofpmp_port_stats[i] = nmps.ports[i].stats;
ofpmp_reply->ofpmp_port_stats[i].duration_sec = htonl(start_tv.tv_sec - tv.tv_sec);
ofpmp_reply->ofpmp_port_stats[i].duration_nsec = htonl(tv.tv_usec);
}
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Group Features Request消息
*
* 该函数用于处理接收到的OpenFlow Group Features Request消息并返回组功能信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_group_features(struct ofp_buffer *ofpbuf)
{
int i = 0;
int reply_len = sizeof(struct ofp_header)+sizeof(struct ofp_group_features)+8;
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_MULTIPART_REPLY,
ofpbuf->header.xid,reply_len);
struct ofp_group_features *group = (struct ofp_group_features *)ofpbuf_reply->data;
group->types = htons(OFPMP_GROUP_FEATURES);
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Port Description Request消息
*
* 该函数用于处理接收到的OpenFlow Port Description Request消息并返回端口描述信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_port_desc(struct ofp_buffer *ofpbuf)
{
int i = 0;
int reply_len = sizeof(struct ofp_header)+sizeof(struct ofp_multipart)+
sizeof(struct ofp_port)*nmps.cnt;
struct ofp_buffer *ofpbuf_reply = (struct ofp_buffer *)build_reply_ofpbuf(OFPT_MULTIPART_REPLY,
ofpbuf->header.xid,reply_len);
struct ofp_multipart *ofpmp_reply = (struct ofp_multipart *)ofpbuf_reply->data;
ofpmp_reply->type = htons(OFPMP_PORT_DESC);
ofpmp_reply->flags = htonl(OFPMP_REPLY_MORE_NO);
for(i=0;i<nmps.cnt;i++)
{
ofpmp_reply->ofpmp_port_desc[i] = nmps.ports[i].state;
}
send_openflow_message(ofpbuf_reply,reply_len);
return HANDLE;
}
/**
* @brief 处理OpenFlow Packet Out消息
*
* 该函数用于处理接收到的OpenFlow Packet Out消息并根据消息中的动作执行相应的操作。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle_ofpmsg_packet_out(struct ofp_buffer *ofpbuf)
{
struct ofp_packet_out *out = (struct ofp_packet_out *)ofpbuf;
struct ofp_action_output *action = (struct ofp_action_output *)&out->actions[0];
int action_len = ntohs(out->actions_len);
struct eth_header *eth = (struct eth_header *)&ofpbuf->data[sizeof(struct ofp_packet_out) - sizeof(struct ofp_header) + action_len];
int i = 0,send_len = ntohs(ofpbuf->header.length) - sizeof(struct ofp_packet_out) - action_len;
if(action_len == 0)
{
nms_exec_action(ntohl(out->in_port),OFPP_FLOOD,eth,send_len,-1);
}
else
{
while(action_len > 0)
{
if(action->type == OFPAT_OUTPUT)
{
nms_exec_action(ntohl(out->in_port),ntohl(action->port),eth,send_len,-1);
}
action_len -= sizeof(struct ofp_action_output);
action++;
}
}
return HANDLE;
}
/**
* @brief 处理OpenFlow Role Request消息
*
* 该函数用于处理接收到的OpenFlow Role Request消息并返回角色信息。
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
*
* @return 返回处理状态码
*/
static enum ofperr
handle__opfmsg_role_request(struct ofp_buffer *ofpbuf)
{
int reply_len = sizeof(struct ofp_header)+sizeof(struct ofp_role);
struct ofp_buffer *ofpbuf_reply =
(struct ofp_buffer *)build_reply_ofpbuf(OFPT_ROLE_REPLY,ofpbuf->header.xid,reply_len);
SHOW_FUN(0);
memcpy(ofpbuf_reply->data,ofpbuf->data,sizeof(struct ofp_role));
ofpbuf_reply->header.type = OFPT_ROLE_REPLY;
send_openflow_message(ofpbuf_reply,reply_len);
SHOW_FUN(1);
return HANDLE;
}
/**
* @brief OpenFlow消息回调处理函数
*
* 该函数根据接收到的OpenFlow消息类型调用相应的处理函数。
* callback 的返回值必须有且只能存在两种返回值:
* 已处理: HANDLE = 0x1,
* 不处理CONTINUE = 0x2
*
* @param ofpbuf 接收到的OpenFlow消息缓冲区
* @param len 消息长度
*
* @return 返回处理状态码
*/
enum ofperr handle_openflow_callback(struct ofp_buffer *ofpbuf, int len)
{
int oftype = ofpbuf->header.type;
printf("header.version:%d, type:%d, len:%d\n", ofpbuf->header.version, ofpbuf->header.type, htons(ofpbuf->header.length));
switch (oftype) {
case OFPT_HELLO:
return handle_opfmsg_hello(ofpbuf);
case OFPT_FEATURES_REQUEST:
return handle_opfmsg_features_request(ofpbuf);
case OFPT_GET_CONFIG_REQUEST:
return handle_ofpmsg_get_config_request(ofpbuf);
case OFPT_MULTIPART_REQUEST:
// 根据 multipart 请求的具体类型进一步处理
{
struct ofp_multipart *multipart = (struct ofp_multipart *)ofpbuf->data;
switch (ntohs(multipart->type)) {
case OFPMP_DESC:
return handle_ofpmsg_desc(ofpbuf);
case OFPMP_FLOW:
return handle_ofpmsg_flow_stats(ofpbuf);
case OFPMP_AGGREGATE:
return handle_ofpmsg_aggregate(ofpbuf);
case OFPMP_TABLE:
return handle_ofpmsg_table(ofpbuf);
case OFPMP_PORT_STATS:
return handle_ofpmsg_port_stats(ofpbuf);
case OFPMP_GROUP_FEATURES:
return handle_ofpmsg_group_features(ofpbuf);
case OFPMP_PORT_DESC:
return handle_ofpmsg_port_desc(ofpbuf);
default:
printf("Unsupported multipart request type: %d\n", ntohs(multipart->type));
break;
}
}
break;
case OFPT_PACKET_OUT:
return handle_ofpmsg_packet_out(ofpbuf);
case OFPT_ROLE_REQUEST:
return handle__opfmsg_role_request(ofpbuf);
default:
printf(" --do not handle the message!\n");
}
// 返回不处理状态码
return CONTINUE;
}
#define MASK_HELLO (1 << OFPT_HELLO) // 1 << 0
#define MASK_FEATURES_REQUEST (1 << OFPT_FEATURES_REQUEST) // 1 << 5
#define MASK_GET_CONFIG_REQUEST (1 << OFPT_GET_CONFIG_REQUEST) // 1 << 7
#define MASK_PACKET_OUT (1 << OFPT_PACKET_OUT) // 1 << 13
#define MASK_MULTIPART_REQUEST (1 << OFPT_MULTIPART_REQUEST) // 1 << 18
#define MASK_ROLE_REQUEST (1 << OFPT_ROLE_REQUEST) // 1 << 24
/** mask 为获取openflow消息的bimap掩码,openflow消息枚举见 "enum ofp_type"
*
* 如:获取 OFPT_HELLO(0) 和 OFPT_FEATURES_REQUEST(5)消息,
* mask值设为 mask = 0b'100001 = 0x21
*
*/
int main(int argc,char* argv[])
{
int mask = 0;
ofp_init(argc,argv);
// 使用宏为 mask 赋值,监听以下消息类型:
// OFPT_HELLO, OFPT_FEATURES_REQUEST, OFPT_GET_CONFIG_REQUEST,
// OFPT_PACKET_OUT, OFPT_MULTIPART_REQUEST, OFPT_ROLE_REQUEST
mask = MASK_HELLO | MASK_FEATURES_REQUEST | MASK_GET_CONFIG_REQUEST |
MASK_PACKET_OUT | MASK_MULTIPART_REQUEST | MASK_ROLE_REQUEST;
openflow_hook_init(mask,handle_openflow_callback);
pause();
return 0;
}
// sudo xofp -4 127.0.0.1 -c eth0 -i obx0,obx1,obx2,obx3