openbox lab initialized

This commit is contained in:
2025-11-06 00:01:42 +08:00
parent 0fe20bb24c
commit edb0725375
2508 changed files with 670396 additions and 66 deletions

View File

@@ -0,0 +1,518 @@
/***************************************************************************
* 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>
struct eth_header;
void nms_exec_action(u32 inport,u32 outport,struct eth_header *eth,int len,int hit_idx);
extern void pkt_print(u8 *pkt, uint16_t len);
static struct ofp_buffer *build_opfmsg_reply_ofpbuf(uint8_t type,uint32_t xid,uint16_t len);
#ifndef htobe64
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define htobe64(x) __builtin_bswap64((u64)(x))
#define be64toh(x) __builtin_bswap64((u64)(x))
#else
#define htobe64(x) (x)
#define be64toh(x) (x)
#endif
#endif
static inline uint64_t host_to_be64(uint64_t value)
{
return htobe64(value);
}
static struct ofp_buffer *build_multipart_reply(struct ofp_buffer *request,
uint16_t mp_type,
size_t body_len,
struct ofp_multipart **mp_out)
{
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) + body_len;
struct ofp_buffer *reply = build_opfmsg_reply_ofpbuf(
OFPT_MULTIPART_REPLY, request->header.xid, reply_len);
if (!reply) {
return NULL;
}
struct ofp_multipart *mp = (struct ofp_multipart *)reply->data;
memset(mp, 0, sizeof(*mp));
mp->type = htons(mp_type);
if (mp_out) {
*mp_out = mp;
}
return reply;
}
static enum opfmsg_hook_ret handle_opfmsg_get_config_request(struct ofp_buffer *ofpbuf);
static enum opfmsg_hook_ret handle_opfmsg_multipart_request(struct ofp_buffer *ofpbuf);
static enum opfmsg_hook_ret handle_opfmsg_packet_out(struct ofp_buffer *ofpbuf);
static enum opfmsg_hook_ret handle_opfmsg_flow_mod(struct ofp_buffer *ofpbuf);
static enum opfmsg_hook_ret handle_opfmsg_role_request(struct ofp_buffer *ofpbuf);
/**
* @brief
*
* 构建openflow报文头
*
*/
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
*
* 构建回应报文
*
* @return
*/
static struct ofp_buffer *build_opfmsg_reply_ofpbuf(uint8_t type,uint32_t xid,uint16_t len)
{
struct ofp_buffer *reply = (struct ofp_buffer *)malloc(len);
if (!reply) {
return NULL;
}
memset(reply,0,len);
build_opfmsg_header(&reply->header,len,type,xid);
printf("ofpbuf_reply,malloc:%p,type:%d,len:%d\n",reply,type,len);
return reply;
}
static enum opfmsg_hook_ret
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 =
build_opfmsg_reply_ofpbuf(OFPT_ERROR,ofpbuf->header.xid,reply_len);
if (!ofpbuf_reply) {
return CONTINUE;
}
//打印error消息
pkt_print((u8 *)ofpbuf,htons(ofpbuf->header.length));
//发送error消息
send_openflow_message(ofpbuf_reply,reply_len);
}
//返回已处理状态码
return HANDLE;
}
static enum opfmsg_hook_ret
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 = build_opfmsg_reply_ofpbuf(OFPT_FEATURES_REPLY,
ofpbuf->header.xid,feature_reply_len);
if (!ofpbuf_reply) {
return CONTINUE;
}
//获取交换机的功能信息 指针变量 feature_reply_msg
struct ofp_switch_features *feature_reply_msg =(struct ofp_switch_features *)ofpbuf_reply->data;
//TODO
/* 构建feature回应报文把交换机的功能信息发送给控制器指针变量feature_reply_msg赋值 */
memset(feature_reply_msg,0,sizeof(*feature_reply_msg));
feature_reply_msg->datapath_id = host_to_be64(0x0100000000000001ULL);
feature_reply_msg->n_buffers = htonl(256);
feature_reply_msg->n_tables = 4;
feature_reply_msg->capabilities = htonl(0);
//调用系统发送接口,发送回应报文
send_openflow_message(ofpbuf_reply,feature_reply_len);
//返回已处理状态码
return HANDLE;
}
static enum opfmsg_hook_ret handle_opfmsg_get_config_request(struct ofp_buffer *ofpbuf)
{
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_switch_config);
struct ofp_buffer *reply = build_opfmsg_reply_ofpbuf(
OFPT_GET_CONFIG_REPLY, ofpbuf->header.xid, reply_len);
if (!reply) {
return CONTINUE;
}
struct ofp_switch_config *cfg = (struct ofp_switch_config *)reply->data;
memset(cfg, 0, sizeof(*cfg));
cfg->flags = htons(0);
cfg->miss_send_len = htons(0xffff);
send_openflow_message(reply, reply_len);
return HANDLE;
}
static void handle_multipart_desc(struct ofp_buffer *ofpbuf)
{
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_DESC,
sizeof(struct ofp_desc_stats), &mp_reply);
if (!reply || !mp_reply) {
return;
}
struct ofp_desc_stats *desc = mp_reply->ofpmp_desc;
memset(desc, 0, sizeof(*desc));
snprintf(desc->mfr_desc, sizeof(desc->mfr_desc), "FAST Reference Switch");
snprintf(desc->hw_desc, sizeof(desc->hw_desc), "FAST Virtual datapath");
snprintf(desc->sw_desc, sizeof(desc->sw_desc), "OF1.3 Example Stack");
snprintf(desc->serial_num, sizeof(desc->serial_num), "FAST-0001");
snprintf(desc->dp_desc, sizeof(desc->dp_desc), "FAST educational datapath");
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) + sizeof(struct ofp_desc_stats);
send_openflow_message(reply, reply_len);
}
static void handle_multipart_flow(struct ofp_buffer *ofpbuf)
{
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_FLOW, 0, &mp_reply);
if (!reply) {
return;
}
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart);
send_openflow_message(reply, reply_len);
}
static void handle_multipart_aggregate(struct ofp_buffer *ofpbuf)
{
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_AGGREGATE,
sizeof(struct ofp_aggregate_stats_reply), &mp_reply);
if (!reply || !mp_reply) {
return;
}
struct ofp_aggregate_stats_reply *body = mp_reply->ofpmp_aggregate_reply;
memset(body, 0, sizeof(*body));
body->packet_count = host_to_be64(0);
body->byte_count = host_to_be64(0);
body->flow_count = htonl(0);
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) +
sizeof(struct ofp_aggregate_stats_reply);
send_openflow_message(reply, reply_len);
}
static void handle_multipart_table(struct ofp_buffer *ofpbuf)
{
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_TABLE,
sizeof(struct ofp_table_stats), &mp_reply);
if (!reply || !mp_reply) {
return;
}
struct ofp_table_stats *table = mp_reply->table_stats;
memset(table, 0, sizeof(*table));
table->table_id = 0;
table->active_count = htonl(0);
table->lookup_count = host_to_be64(0);
table->matched_count = host_to_be64(0);
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) + sizeof(struct ofp_table_stats);
send_openflow_message(reply, reply_len);
}
static void handle_multipart_port_stats(struct ofp_buffer *ofpbuf)
{
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_PORT_STATS,
sizeof(struct ofp_port_stats), &mp_reply);
if (!reply || !mp_reply) {
return;
}
struct ofp_port_stats *stats = mp_reply->ofpmp_port_stats;
memset(stats, 0, sizeof(*stats));
stats->port_no = htonl(1);
stats->rx_packets = host_to_be64(0);
stats->tx_packets = host_to_be64(0);
stats->rx_bytes = host_to_be64(0);
stats->tx_bytes = host_to_be64(0);
stats->rx_dropped = host_to_be64(0);
stats->tx_dropped = host_to_be64(0);
stats->rx_errors = host_to_be64(0);
stats->tx_errors = host_to_be64(0);
stats->rx_frame_err = host_to_be64(0);
stats->rx_over_err = host_to_be64(0);
stats->rx_crc_err = host_to_be64(0);
stats->collisions = host_to_be64(0);
stats->duration_sec = htonl(0);
stats->duration_nsec = htonl(0);
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) + sizeof(struct ofp_port_stats);
send_openflow_message(reply, reply_len);
}
static void handle_multipart_group_features(struct ofp_buffer *ofpbuf)
{
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_GROUP_FEATURES,
sizeof(struct ofp_group_features), &mp_reply);
if (!reply || !mp_reply) {
return;
}
struct ofp_group_features *features = (struct ofp_group_features *)mp_reply->body;
memset(features, 0, sizeof(*features));
features->types = htonl(0);
features->capabilities = htonl(0);
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) +
sizeof(struct ofp_group_features);
send_openflow_message(reply, reply_len);
}
static void fill_port(struct ofp_port *port, uint32_t port_no, const char *name)
{
memset(port, 0, sizeof(*port));
port->port_no = htonl(port_no);
snprintf(port->name, sizeof(port->name), "%s", name);
port->curr_speed = htonl(1000000);
port->max_speed = htonl(1000000);
}
static void handle_multipart_port_desc(struct ofp_buffer *ofpbuf)
{
size_t ports_count = 2;
size_t body_len = ports_count * sizeof(struct ofp_port);
struct ofp_multipart *mp_reply = NULL;
struct ofp_buffer *reply = build_multipart_reply(ofpbuf, OFPMP_PORT_DESC, body_len, &mp_reply);
if (!reply || !mp_reply) {
return;
}
struct ofp_port *ports = mp_reply->ofpmp_port_desc;
fill_port(&ports[0], 1, "fast-eth1");
fill_port(&ports[1], 2, "fast-eth2");
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_multipart) + body_len;
send_openflow_message(reply, reply_len);
}
static enum opfmsg_hook_ret handle_opfmsg_multipart_request(struct ofp_buffer *ofpbuf)
{
if (ntohs(ofpbuf->header.length) < sizeof(struct ofp_header) + sizeof(struct ofp_multipart)) {
printf("multipart request too short\n");
return HANDLE;
}
struct ofp_multipart *mp = (struct ofp_multipart *)ofpbuf->data;
uint16_t type = ntohs(mp->type);
printf("multipart request type=%u\n", type);
switch (type) {
case OFPMP_DESC:
handle_multipart_desc(ofpbuf);
break;
case OFPMP_FLOW:
handle_multipart_flow(ofpbuf);
break;
case OFPMP_AGGREGATE:
handle_multipart_aggregate(ofpbuf);
break;
case OFPMP_TABLE:
handle_multipart_table(ofpbuf);
break;
case OFPMP_PORT_STATS:
handle_multipart_port_stats(ofpbuf);
break;
case OFPMP_GROUP_FEATURES:
handle_multipart_group_features(ofpbuf);
break;
case OFPMP_PORT_DESC:
handle_multipart_port_desc(ofpbuf);
break;
default:
printf("unsupported multipart type %u\n", type);
break;
}
return HANDLE;
}
static enum opfmsg_hook_ret handle_opfmsg_packet_out(struct ofp_buffer *ofpbuf)
{
struct ofp_packet_out *pkt_out = (struct ofp_packet_out *)&ofpbuf->header;
uint16_t actions_len = ntohs(pkt_out->actions_len);
uint16_t total_len = ntohs(ofpbuf->header.length);
if (total_len < sizeof(struct ofp_packet_out)) {
printf("packet_out length %u shorter than header\n", total_len);
return HANDLE;
}
if (actions_len > total_len - sizeof(struct ofp_packet_out)) {
printf("packet_out invalid actions_len=%u total_len=%u\n", actions_len, total_len);
return HANDLE;
}
uint32_t in_port = ntohl(pkt_out->in_port);
uint8_t *payload = (uint8_t *)pkt_out->actions + actions_len;
int payload_len = total_len - (payload - (uint8_t *)&ofpbuf->header);
if (payload_len <= 0) {
printf("packet_out without payload\n");
return HANDLE;
}
uint32_t out_port = 0;
if (actions_len >= sizeof(struct ofp_action_output)) {
struct ofp_action_output *action = (struct ofp_action_output *)pkt_out->actions;
out_port = ntohl(action->port);
}
printf("packet_out in_port=%u out_port=%u len=%d\n", in_port, out_port, payload_len);
nms_exec_action(in_port, out_port, (struct eth_header *)payload, payload_len, -1);
return HANDLE;
}
static enum opfmsg_hook_ret handle_opfmsg_flow_mod(struct ofp_buffer *ofpbuf)
{
uint16_t total_len = ntohs(ofpbuf->header.length);
if (total_len < sizeof(struct ofp_header) + sizeof(struct fast_rule)) {
printf("flow_mod payload too small: %u\n", total_len);
return HANDLE;
}
struct fast_rule *rule = (struct fast_rule *)ofpbuf->data;
print_user_rule(rule);
int idx = fast_add_rule(rule);
printf("fast_add_rule result index=%d\n", idx);
return HANDLE;
}
static enum opfmsg_hook_ret handle_opfmsg_role_request(struct ofp_buffer *ofpbuf)
{
size_t reply_len = sizeof(struct ofp_header) + sizeof(struct ofp_role);
struct ofp_buffer *reply = build_opfmsg_reply_ofpbuf(
OFPT_ROLE_REPLY, ofpbuf->header.xid, reply_len);
if (!reply) {
return CONTINUE;
}
struct ofp_role *req = (struct ofp_role *)ofpbuf->data;
struct ofp_role *rsp = (struct ofp_role *)reply->data;
memcpy(rsp, req, sizeof(*rsp));
send_openflow_message(reply, reply_len);
return HANDLE;
}
/**
*
* callback 的返回值必须有且只能存在两种返回值:
*
* 已处理: HANDLE = 0x1,
* 不处理CONTINUE = 0x2
*
*/
static int 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_opfmsg_get_config_request(ofpbuf);
case OFPT_MULTIPART_REQUEST:
return handle_opfmsg_multipart_request(ofpbuf);
case OFPT_PACKET_OUT:
return handle_opfmsg_packet_out(ofpbuf);
case OFPT_FLOW_MOD:
return handle_opfmsg_flow_mod(ofpbuf);
case OFPT_ROLE_REQUEST:
return handle_opfmsg_role_request(ofpbuf);
default:
printf(" --do not handle the message!\n");
}
//返回不处理状态码
return CONTINUE;
}
/** 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);
//获取 OFPT_HELLO(0) 和 OFPT_FEATURES_REQUEST (5)消息
mask = (1U << OFPT_HELLO) |
(1U << OFPT_FEATURES_REQUEST) |
(1U << OFPT_GET_CONFIG_REQUEST) |
(1U << OFPT_MULTIPART_REQUEST) |
(1U << OFPT_PACKET_OUT) |
(1U << OFPT_FLOW_MOD) |
(1U << OFPT_ROLE_REQUEST);
openflow_hook_init(mask,handle_openflow_callback);
pause();
return 0;
}