对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 , 非 ...
随机推荐
- [JS] 如何清空file input框 [整理]
测试环境:OS --> winXPBrowsers --> IE6+, FF 3.0.11, FF 3.5, Opera 9.64, Opera 10 beta 2, Safari 4, ...
- (转)dedecms [field:array runphp='yes']标签使用技巧
field支持用array获取任意字段的值:(支持标记:文章内容模板的 {dede:field name=’array’ /}.arclist.arclistsg.loop.sql 标签) 我们平时常 ...
- Design Pattern —— Singleton
Design Pattern —— Singleton 强力推荐枚举和类级内部类方式实现单例模式 单例模式是开发中非常常用的一种模式,简单的说,我们希望一个类永远都只有一个对象. 主要有两个用途: ...
- jquery动画总结
基本动画 show() //直接显示元素,没有动画 show(speed, [callback]) //有动画,有回调函数 hide() //直接隐藏元素,没有动画 hide(speed, [call ...
- seajs常用API整理
本文来自于https://github.com/seajs/seajs/issues/266
- C# 中使用 OpenSSL 的公钥/私钥进行加密和解密
在C#中进行RSA解密,需要用RSACryptoServiceProvider,但是不支持OpenSSL格式的公钥或者私钥. X509 公钥 -----BEGIN PUBLIC KEY----- MI ...
- Linux命令——创建删除文件
创建文件夹 mkdir filename 进入目录文件 cd filename 返回上一级目录 cd ..返回多级目录 cd ../../.. (../表示一级) 创建文件 touch filen ...
- JQuery Dialog(JS模态窗口,可拖拽的DIV) 效果实现代码
效果图 调用示意图 交互示意图 如上图所示,这基本是JQueryDialog的完整逻辑流程了. 1.用户点击模态窗口的“提交”按钮时,调用JQueryDialog.Ok()函数,这个函数对应了用户 ...
- Python中函数参数传递问题
先上两个例子: http://python.jobbole.com/85231/ a = 1 def fun(a): a = 2 fun(a) print a # 结果为1 fun(a)中的a,可以看 ...
- Kafka 集群消息监控系统:Kafka Eagle
Kafka Eagle 1.概述 在开发工作当中,消费 Kafka 集群中的消息时,数据的变动是我们所关心的,当业务并不复杂的前提下,我们可以使用 Kafka 提供的命令工具,配合 Zookeeper ...