对openflow 1.0协议的扩展
通过这几天对openvswitch代码的分析,以及项目的须要,须要对openflow 1.0进行一定的扩展,发现网上没有这方面的教程,尽管在搞懂ovs代码架构,floodlight controller中利用的事件驱动模型之后,会认为并非难事,可是对于刚入门SDN的同学来说,须要一番折腾,这里简单记录一下,希望帮助到其它人。
环境配置:2host + 1 OVS + floodlight
软件版本号: openvswitch 1.9.0 , floodlight0.85
在尝试对ovs中的openflow协议进行扩展之前至少应该理清的是,ovs怎样与SDN controller进行通信,收发of msg的过程,处理of action的流程,特别是怎样解析来自controller的消息;此外由于Floodlight利用的是netty框架,所以还要理解netty事件驱动的原理。接下来添加一个简单的openflow message以及相应的action ,然后看ovs能否成功接收来自controller的消息。
1.在 include/openflow/openflow-1.0.h中扩展of协议,添加我们的消息类型。(里面的字段依据自己的业务逻辑须要而设置)
struct ofp10_action_fp_update {
ovs_be16 type;
ovs_be16 len;
ovs_be32 vector;
};
OFP_ASSERT(sizeof(struct ofp10_action_fp_update) == 8);
struct ofp_fp_update{
ovs_be32 buffer_id; /* ID assigned by datapath or UINT32_MAX. */
ovs_be16 in_port; /* Packet's input port (OFPP_NONE if none). */
ovs_be16 other; /* other fields reserved. */
struct ofp_action_header actions[0]; /* The action length is inferred
from the length field in the
header. */
};
OFP_ASSERT(sizeof(struct ofp_fp_update) == 8);
2.在 lib/ofp-msg.h 更新ofpraw这个结构体(非常重要,由于当ovs收到来自controller的消息之后就会利用ofpraw里面格式化的定义来验证消息的有效性,从而进行兴许处理)和ofptype枚举体。须要注意的是对ofpraw的更改一定要遵循固定的格式,凝视中讲的非常清楚。
enum ofpraw {
/* Immutable standard messages.
*
* The OpenFlow standard promises to preserve these messages and their numbers
* in future versions, so we mark them as <all>, which covers every OpenFlow
* version numbered 0x01...0xff, rather than as OF1.0+, which covers only
* OpenFlow versions that we otherwise implement.
* Without <all> here, then we would fail to decode "hello" messages that
* announce a version higher than we understand, even though there still could
* be a version in common with the peer that we do understand. The <all>
* keyword is less useful for the other messages, because our OpenFlow channels
* accept only OpenFlow messages with a previously negotiated version.
*/
....................................................
/* OFPT 1.0 (13): struct ofp_packet_out, uint8_t[]. */
OFPRAW_OFPT10_PACKET_OUT,
/* OFPT 1.1+ (13): struct ofp11_packet_out, uint8_t[]. */
OFPRAW_OFPT11_PACKET_OUT,
/* OFPT 1.0 (20): struct ofp_fp_update, struct ofp_action_header[]. */
OFPRAW_OFPT10_FP_UPDATE,
};
enum ofptype {
/* Immutable messages. */
OFPTYPE_HELLO, /* OFPRAW_OFPT_HELLO. */
OFPTYPE_ERROR, /* OFPRAW_OFPT_ERROR. */
......................................
/* Controller command messages. */
OFPTYPE_PACKET_OUT, /* OFPRAW_OFPT10_PACKET_OUT.
* OFPRAW_OFPT11_PACKET_OUT. */
OFPTYPE_FLOW_MOD, /* OFPRAW_OFPT10_FLOW_MOD.
* OFPRAW_OFPT11_FLOW_MOD.
* OFPRAW_NXT_FLOW_MOD. */
OFPTYPE_PORT_MOD, /* OFPRAW_OFPT10_PORT_MOD.
* OFPRAW_OFPT11_PORT_MOD. */
OFPTYPE_FP_UPDATE, /* OFPRAW_OFPT10_FP_UPDATE. */
};
3. 在lib/ofp-util.h 中加入对应的数据结构代表对应的通用类型结构,由于ovs用户空间在解码对应的消息的时候须要针对详细的类型运行对应的动作,所以也要更新 ofp-actions.h
// ofp-util.h
struct ofputil_fp_update {
struct ofpact *ofpacts; /* Actions. */
size_t ofpacts_len; /* Size of ofpacts in bytes. */
};
// 对这个消息编解码辅助函数
enum ofperr ofputil_decode_fp_update(struct ofputil_fp_update *,
const struct ofp_header *,
struct ofpbuf *ofpacts);
struct ofpbuf *ofputil_encode_fp_update(const struct ofputil_fp_update *,
enum ofputil_protocol protocol);
// ofp-actions.h
struct ofpact_fp_update {
struct ofpact ofpact;
uint32_t vector; /* 自己定义*/
};
4. 在 ofproto/ofproto.c (3790)- handle_openflow_() 函数中加入处理该消息的分支,
static enum ofperr
3793 handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
3794 {
3795 const struct ofp_header *oh = msg->data;
3796 enum ofptype type;
3797 enum ofperr error;
3798
3799 error = ofptype_decode(&type, oh);
3800 if (error) {
3801 return error;
3802 }
3803
3804 switch (type) {
3805 /* OpenFlow requests. */
3806 case OFPTYPE_ECHO_REQUEST:
3807 return handle_echo_request(ofconn, oh);
3808
3809 case OFPTYPE_FEATURES_REQUEST:
3810 return handle_features_request(ofconn, oh);
3811
3812 case OFPTYPE_GET_CONFIG_REQUEST:
3813 return handle_get_config_request(ofconn, oh);
3814
3815 case OFPTYPE_SET_CONFIG:
3816 return handle_set_config(ofconn, oh);
3817
3818 case OFPTYPE_PACKET_OUT:
3819 return handle_packet_out(ofconn, oh);
3820 case OFPTYPE_FP_UPDATE:
3821 return handle_fp_update(ofconn, oh);
...............................................
}
处理函数自己依据须要来实现,这里只打印日志信息。
static enum ofperr
handle_fp_update(struct ofconn *ofconn, const struct ofp_header *oh)
{
//TODO
VLOG_INFO("=====I GOT FP FROM CONTROLLER ========");
return 0;
}
以上就是ovs上须要考虑的地方,细节处要注意。接下来是Floodlight上面通过构造一个该消息,而后当接收到packet in 后就将其发送到这个SW上。
5. 在org.openflow.protocol 包中添加我们的消息类,以及对应的方法。
public class OFFPUpdate extends OFMessage implements OFActionFactoryAware{
public static int MINIMUM_LENGTH = 16;
public static int BUFFER_ID_NONE = 0xffffffff;
protected OFActionFactory actionFactory;
protected int bufferId;
protected short inPort = 0x0000; // not used yet
protected short other;
protected List<OFAction> actions;
public OFFPUpdate(){
super();
this.type = OFType.FP_UPDATE;
this.length = U16.t(MINIMUM_LENGTH);
}
....................................
}
6.然后再OFType中标示这个新增的消息类。
public enum OFType {
HELLO (0, OFHello.class, new Instantiable<OFMessage>() {
@Override
public OFMessage instantiate() {
return new OFHello();
}}),
...........................................................
FP_UPDATE (20, OFFPUpdate.class, new Instantiable<OFMessage>() {
@Override
public OFMessage instantiate() {
return new OFFPUpdate();
}});
}
7. 在org.openflow.protocol.action中新增相应的action类,由于每次从SDN controller发送控制类消息时都会设置它的action list。
public class OFActionFPUpdate extends OFAction implements Cloneable {
public static int MINIMUM_LENGTH = 8;
protected int vector;
public OFActionFPUpdate() {
super.setType(OFActionType.FP_UPDATE);
super.setLength((short) MINIMUM_LENGTH);
}
public OFActionFPUpdate(int vector) {
super();
super.setType(OFActionType.FP_UPDATE);
super.setLength((short) MINIMUM_LENGTH);
this.vector = vector;
}
...................................
}
8. 最后写一个简单的module 来測试。这里的思路是当收到某个SW发来的packetin消息时,我们就给这个交换机下发一个FPUpdate的消息。主要代码:
OFFPUpdate fu =
(OFFPUpdate) floodlightProvider.getOFMessageFactory()
.getMessage(OFType.FP_UPDATE);
OFActionFPUpdate action = new OFActionFPUpdate();
action.setVector(0xffffffff); // just for testing
List<OFAction> actions = new ArrayList<OFAction>();
actions.add(action);
fu.setBufferId(OFFPUpdate.BUFFER_ID_NONE)
.setInPort((short)0)
.setActions(actions)
.setLengthU(OFFPUpdate.MINIMUM_LENGTH+OFActionFPUpdate.MINIMUM_LENGTH);
try {
sw.write(fu, cntx);
} catch (IOException e) {
logger.error("Failure writing fp update", e);
}
通过简单的測试,整个流程是正确的。
转载请注明出处:点击打开链接
对openflow 1.0协议的扩展的更多相关文章
- 深入理解OAuth2.0协议
1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...
- 帮你深入理解OAuth2.0协议
1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...
- OpenID Connect:OAuth 2.0协议之上的简单身份层
OpenID Connect是什么?OpenID Connect(目前版本是1.0)是OAuth 2.0协议(可参考本人此篇:OAuth 2.0 / RCF6749 协议解读)之上的简单身份层,用 A ...
- (转)帮你深入理解OAuth2.0协议
1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...
- 问题:OAuth2.0;结果:帮你深入理解OAuth2.0协议
1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题. 豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒 ...
- 对OAuth2.0协议的理解和测试demo
1. 什么是OAuth OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容. OAuth ...
- 硕盟 TYPE C转HDMI+VGA+USB3.0+PD3.0四口扩展坞
硕盟SM-T54是一款USB-C 四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显示器.电视机或其他显示设备.产品可以接入硬盘. ...
- USB2.0协议笔记
1.概述 USB(Universal Serial Bus)具有传输速率快,可热插拔等显著特点,应用已经十分广泛,目前的相当多的设备已经支持最新的USB3.0协议.理论上USB1.1的传输速度 ...
- Swift - 2 (?和!、结构体、类、协议、扩展、闭包)
1> 可选类型(?)和强制解包(!) 在swift中,可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型.其实所谓的 nil 就是 Optional.None , 非 ...
随机推荐
- left ,right ,cross ,full/left outer join/区别 详解
--创建测试表wwif OBJECT_ID('qq') is not null drop table qqcreate table qq([序号] varchar(5),[内容1] varchar(1 ...
- 关于Jquery.Data()和HTML标签的data-*属性
人们总喜欢往HTML标签上添加自定义属性来存储和操作数据.但这样做的问题是,你不知道将来会不会有其它脚本把你的自定义属性给重置掉,此外,你这样做也会导致html语法上不符合Html规范,以及一些其它副 ...
- 从服务器将Oracle数据库导出到本地Oracle数据库的方法
1.将服务器上的Oracle数据库导入到本地 在CMD模式下执行以下命令: exp username1/password@服务器端数据库 file=本地硬盘:/文件名.dmp 例如: exp ...
- 一些iOS笔试题目
1.什么是arc?(arc是为了解决什么问题诞生的?) 首先解释ARC: automatic reference counting自动引用计数. ARC几个要点: 在对象被创建时 retain cou ...
- Shell 脚本编程笔记(一) Hello Shell
最近不断在接触Linux操作系统,对它一个终端走天下的特性感到十分新奇和伟大.同时也被各种命令折磨的死去活来...公司的一个老同事给我讲,在公司的极品geek宅都是只用一个黑黑的框完成一切的.结果我一 ...
- python密码处理(可用于生产模式)
import os from hashlib import sha256 from hmac import HMAC def encrypt_password(password, salt=None) ...
- Extjs之combobox联动
Ext.Loader.setConfig({ enabled : true }); Ext.Loader.setPath('Ext.ux', '../extjs/ux'); Ext.require([ ...
- Python学习笔记 :01概述
Python基础 首先推荐学习Python基础的教程和书籍 视频教程推荐南京大学张莉老师在cousera上的教程用Python玩转数据 入门教程<Python基础教程> 数据挖掘教程< ...
- Scut:运行测试服务器
在大致过了一遍Scut的底层结构(其实只是对各个组件有了一个初步印象而已),现在开始尝试搭建“口袋天界”的Scut服务端. 1. 设置外部启动项 项目属性 -- 调试 -- 启动外部程序 -- 项目根 ...
- 调用系统API还是很高效的,不必担心性能
代码如下: void MainWindow::on_pushButton_2_clicked() { QTime total; total.start(); ; ; i<=*; i++) { Q ...