OpenDayLight (ODL) 是一款开源SDN控制器框架,在linux平台上运行。北向接口为RESTAPI,南向接口可下发多种协议至路由器设备。因工作中需要测试pcep path protection功能,于是对ODL的南向协议模块bgpcep这个项目进行了相关的扩展。
1. 支持path protection lsp的创建、update和remove
需求:
(1)支持使用initiatelsp报文来创建workinglsp、protectionlsp;
(2)支持使用updatelsp报文来update更新workinglsp、protectionlsp;
(3)支持使用initiatelsp报文来remove删除workinglsp、protectionlsp;
(4)支持对于包含pathprotection 的report报文的处理;
设计:
(1) 使用针对lspa对象的处理流程来输入associationgroup的参数;
(2) 然后利用serialize串行化流程来把这些associationgroup参数组成initiatelsp报文;
(3) 处理pcc返回的report报文,使得lspname和plsp-id的关系能够input到pce中的lspdb中,以便支持随后的update或removelsp操作;
实现:
通过lspa对象的处理流程映射为associationgroup的处理。
开发步骤:
(1) 为新的TLV设计从RESTCONF接口传入的数据类型,并绑定在lspa对象下。
Association group TLV format:
Path protection TLV as optional TLV of association group TLV:
首先,根据TLV需求在lspa对象的yang模型下定义新的子结点。其中obj-class子结点可配是由于目前路由器版本采用旧版的tlv(class = 100),而官方的class已更新成40。这样做方便为以后路由器代码变动而做下发报文的改变。Lspa的数据类型定义在pcep-types.yang这个文件中。
container lspa {
//ppag related
leaf r-flag {
type boolean;
default false;
}
leaf association-type {
type uint8;
default 1;
}
leaf association-id {
type uint8;
mandatory true;
}
leaf association-source {
type inet:ipv4-address;
mandatory true;
}
leaf s-flag {
type boolean;
}
leaf p-flag {
type boolean;
}
leaf obj-class {
type uint8;
default 40;
}
leaf pt-flag {
type uint8 {
range 0..63;
}
}
}
新定义的对象在path protection tlv中的对应关系为:
编辑好yang文件后,在pcep/api路径下执行mvnclean install,对应的新的java API就生成了。新的API里面包含新增对象的get,set以及build等方法。(Yang和javaAPI的映射关系详细参见ODLyangtools说明)
(2) 改变现有lspa的串行方法。
在PCEPLspaObjectParser.java文件中删除原有对象的引用,利用get()方法导入Input的新类型对象,调用串行函数将对象按照所需tlv格式写入buffer中。
上述改完以后发现,ODL不能处理盒子回的report报文而关闭了pcepsession。这是个很严重的问题。跟踪log以后定位出原因是在解析report报文的时候ODL还是把扩展的ppag报文当成lspa报文来处理,且ppag的report报文比ODL所期望的lspareport报文要短,产生了Exception(异常)。于是,不仅要修改串行函数,解析函数也做了一个调整,很简单就是把解析完tlv的前3行之后的代码给注释掉了。
篡改后的函数如下:
public class PCEPLspaObjectParser extends AbstractObjectWithTlvsParser<TlvsBuilder> {
public static int CLASS = 100;
public static final int TYPE = 1;
/*
* lengths of fields in bytes
*/
private static final int FLAGS_SIZE = 8;
private static final int A_FLAGS_SIZE = 32; //association flags size
/*
* offsets of flags inside flags field in bits
*/
private static final int L_FLAG_OFFSET = 7;
private static final int S_FLAG_OFFSET = 30; //association flag s
private static final int P_FLAG_OFFSET = 31; //association flag p
private static final int R_FLAG_OFFS