通过这几天对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协议的扩展的更多相关文章

  1. 深入理解OAuth2.0协议

    1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...

  2. 帮你深入理解OAuth2.0协议

    1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...

  3. OpenID Connect:OAuth 2.0协议之上的简单身份层

    OpenID Connect是什么?OpenID Connect(目前版本是1.0)是OAuth 2.0协议(可参考本人此篇:OAuth 2.0 / RCF6749 协议解读)之上的简单身份层,用 A ...

  4. (转)帮你深入理解OAuth2.0协议

    1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...

  5. 问题:OAuth2.0;结果:帮你深入理解OAuth2.0协议

    1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题. 豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒 ...

  6. 对OAuth2.0协议的理解和测试demo

    1. 什么是OAuth OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容. OAuth ...

  7. 硕盟 TYPE C转HDMI+VGA+USB3.0+PD3.0四口扩展坞

    硕盟SM-T54是一款USB-C 四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显示器.电视机或其他显示设备.产品可以接入硬盘. ...

  8. USB2.0协议笔记

    1.概述     USB(Universal Serial Bus)具有传输速率快,可热插拔等显著特点,应用已经十分广泛,目前的相当多的设备已经支持最新的USB3.0协议.理论上USB1.1的传输速度 ...

  9. Swift - 2 (?和!、结构体、类、协议、扩展、闭包)

    1> 可选类型(?)和强制解包(!) 在swift中,可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型.其实所谓的 nil 就是 Optional.None , 非 ...

随机推荐

  1. My.Ioc 代码示例——谈一谈如何实现装饰器模式,兼谈如何扩展 My.Ioc

    装饰器模式体现了一种“组合优于继承”的思想.当我们要动态为对象增加新功能时,装饰器模式往往是我们的好帮手. 很多后期出现的 Ioc 容器都为装饰器模式提供了支持,比如说 Autofac.在 My.Io ...

  2. ASP.NET C#使用JavaScriptSerializer实现序列化与反序列化得到JSON

    在JavaScriptSerializer中,我们可以看到下面可以使用的方法或者构造函数,它们都是实例方法: Member Description JavaScriptSerializer() 构造函 ...

  3. Wpf Binding.Path设置

    Binding.Path 获取或设置绑定源属性的路径. 每个绑定通常都具有四个组件:绑定目标对象.目标属性.绑定源,以及要使用的绑定源值的路径.有关这些数据绑定概念的更多信息,请参见数据绑定概述. 使 ...

  4. 顶部图片放大回弹效果Scrollview ---- 各应用中常见的自定义View 解析

    原理并不难.  代码量也不大.  非常简洁 .  先来个效果图 再上一波代码. public class SpecialScrollView extends ScrollView implements ...

  5. UIImageView添加边框和阴影

    - (void)viewDidLoad { [super viewDidLoad]; //添加显示 UIImage *image = [UIImage imageNamed:@"0_wang ...

  6. weka打开提示内存不足的解决方法

    今天在linux中打开Weka时,打开基因数据文件的时候出现如 Not enough memory . Please load a smaller dataset or use a larger he ...

  7. 你好,C++(32) 类是对现实世界的抽象和描述 6.2.1 类的声明和定义

    6.2  类:当C++爱上面向对象 类这个概念是面向对象思想在C++中的具体体现:它既是封装的结果,同时也是继承和多态的载体.因此,要想学习C++中的面向对象程序设计,也就必须从“类”开始. 6.2. ...

  8. archlinux的安装与简单配置(长期更新)

    安装部分较为较为简略,详细内容请查看arch的wiki 分区 cfdisk 格式化 mkfs.ext4 /dev/sdaX ... 挂载分区 mount /dev/sdaX /mnt ... 修改软件 ...

  9. PHP Predefined Interfaces 预定义接口

    SPL提供了6个迭代器接口: Traversable 遍历接口(检测一个类是否可以使用 foreach 进行遍历的接口) Iterator 迭代器接口(可在内部迭代自己的外部迭代器或类的接口) Ite ...

  10. jQuery中的综合动画

    所谓综合动画,就是在链式表达式依次执行相关animate函数,其中的参数是以键值对的方式存在的. 如下示例,就展示了一个基本的综合动画. <!DOCTYPE html PUBLIC " ...