flowgrammable/ofpmsg-js

语言: JavaScript

git: https://github.com/flowgrammable/ofpmsg-js

OpenFlow消息javascript库
OpenFlow message javascript library
README.md (中文)

OpenFlow消息库js

这是一个用于操作OpenFlow消息的库。它提供基本的 用于从套接字,文件或用户程序构造消息的工具。该 library为类型长度值(TLV)消息建立一组基本模式 基于论文消除网络协议的层组成 抽象和系统语言中的漏洞 设计。这个库对任何人都很有用 想要快速构建基于OpenFlow的工具:测试人员,解码器,数据包 发电机,控制器或开关代理。

样品使用

// import the library
var ofp = require('ofpmsg-js');

// import some symbols into easier local names
var view   = ofp.view;
var ofp1_2 = ofp["1.2"];

// Construct a version specific message and serialize
var error = ofp1_2.Error({ type: 1, code: 2, data: 'This is wrong' });
var v = new view.View(new Buffer(1024));
error.toView(v);

// Reset the view so we can deserialize ... useful for testing :)
v.reset();

// Deserialize the view to any version of OpenFlow
var msg = ofp.msg.fromView(view);

// Reset the view so we can deserialize ... useful for testing :)
v.reset();

// Deserialize the view to version 1.2 of OpenFlow
var msg1_2 = ofp["1.2"].fromView(view);

开发设置

  • 先决条件: 安装Node或IO.js. 全局安装Grunt - sudo npm install -g grunt-cli
  • 依赖关系: 安装本地依赖项 - npm install
  • 测试: 执行单元测试 - 咕噜声

支持的类型

  • 视图 - 序列化/反序列化的内存抽象
  • 标题 - openflow标题类型
  • 消息 - 通用OpenFlow消息类型
  • 数据 - 任意未解释数据的包装器
  • 有效负载 - 特定于版本的OpenFlow有效负载类型
  • ethernet.MAC - 以太网MAC地址类型
  • ipv4.Address - IPv4地址类型

支持的功能

  • header.bytes() - 返回标头的字节大小
  • util.makePayload(Class,type,Base) - 构建OpenFlow有效负载类型
  • util.makeIndex(Type) - 从header.type到payload Type构建一个对象映射
  • util.fromView(Type,view) - 构造一个Type,调用fromView并返回obj
  • util.Variant(Index) - 在给定type-Type映射的情况下构建变量转换器

产生异常

  • 可得到
  • 未定义

视图

这种类型是一个包装内存对象的简单抽象。在javascript这个 是Buffer类型。视图对于管理结构约束和关键是至关重要的 确保我们在消息期间始终在安全的内存区域内运行 基于二进制的序列化或反序列化。

视图包含Buffer对象并跟踪缓冲区中的三个位置: 头部,尾部和偏移。头部和尾部是不可变的并且指向 底层Buffer的边界,而offset用作游标 通过Buffer跟踪序列化/反序列化进度。读或写 对视图的操作将使偏移量增加读取的字节数 或写的。所有读/写操作都假定最重要的字节优先 内存中的(MSBF)层。

施工

视图可以从Buffer对象构造。缓冲区可能来自a 套接字,文件或内存位置。没有可选的构造参数。 另外,可以从另一视图构造视图。解码时一定 协议类型通常需要人为约束协议 反序列化器视图的输入数据。这可以通过以下两种方式实现: 提前或约束。两个操作都返回受限制的新视图 现有Buffer对象的子集。 Advance将推进头指针 指定的字节数,而约束将减少尾指针 是来自头部的指示字节数。

// Construct a new view from a new Buffer
var view = new View(new Buffer(1024));

// Produce a new view without the 8 byte header
var newView = view.advance(8);

// Produce a new view constrained by the indicated payload length
var newView = view.constrain(100);

操作

视图是用于使用缓冲区进行序列化/反序列化的接口。 提供的操作允许:无符号的序列化和反序列化 整数和字节数组数据类型。此外,还有一些操作 用于确定可用于额外的字节数 序列化/ deseriation。最后,有一个有用的操作重置 供测试用。它允许序列化到视图,重置偏移量 指针,然后从同一视图反序列化。

// Reset the offset pointer to be equal to the head
view.reset();

// Determine if enough bytes remain from `tail - offset` 
if(view.available() < 8) { ...

// Determine how many bytes used from `offset - head`
view.consumed()

// Deserialize a 1 byte unsigned integer
var version = view.readUInt8();

// Deserialize a 2 byte, MSBF, unsigned integer
var length  = view.readUInt16();

// Deserialize a 4 byte, MSBF, unsigned integer
var xid     = view.readUInt32();

// Deserialize a byte array from using all remaining buffer space
var data    = view.read();

// Deserialize a 32 element byte array
var name    = view.read(32);

// Serialize a 1 byte unsigned integer
view.writeUInt8(type);

// Serialize a 2 byte unsigned integer
view.writeUInt16(length);

// Serialize a 4 byte unsigned integer
view.writeUInt32(xid);

// Serialize a byte array
view.write(buffer);

OpenFlow标头不会在协议版本之间发生变化。标题 包括版本(uint8),类型(uint8),长度(uint16)和事务ID (UINT32)。所有多字节无符号整数都在最高有效字节中 (MSBF)订单。标头长度表示OpenFlow中的字节数 message with包含标头和消息有效负载。一个有效的标题 必须具有至少8个字节的长度字段。

施工

有两种构造标题的方法:来自程序员的术语,或者 通过反序列化视图。

// Construct a default state header and deserialize
var hdr = Header();
hdr.fromView(view);

// Construct a header given named terms
var hdr = Header({
  version: 1,
  type: 1,
  length: 8,
  xid: 1
});

// Construct a header from a view
var hdr = fromView(view);

操作

标头操作支持:序列化,反序列化,有效性检查, 和字符串表示。

// Determine if the header is valid (length >= bytes of the header)
if(hdr.isValid()) { ...

// Determine how many bytes the header consumes in a view
if(view.available() < hdr.bytes()) { ...

// Deserialize a view into a header
hdr.fromView(view);

// Serilaize a header into a view
hdr.toView(view);

// Print a string representaiton of the header
console.log(hdr.toString());

功能

头模块只导出一个函数,该函数返回字节数 标题所需的序列化/反序列化。这是一个常数 表达式作为标题是固定的字段块。

// Determine if the view has enough space for a Header
if(view.available() < bytes()) { ...

信息

这是任何OpenFlow消息的通用封装。它包括一个标题 一个有效负载属性,无论verison如何,标头都是常量 OpenFlow,但有效负载因版本而异。

施工

提供的构造接口非常灵活。用户可以提供 有效载荷和标题将自动构建。或者用户可以提供 建筑中的标题和有效负载。可以在一个视图中构建视图 限制和不受限制的时尚。您可以从视图构建到任何视图 库支持的版本,或表明应该构造 仅限于特定协议

// Construct a message with the supplied payload, determine the header
var msg = Message({
  payload: ofp1_0.Hello()
});

// Construct a message with the supplied header and payload
var msg = Message({
  header:  hdr.Header(...),
  payload: ofp1_0.Hello()
});

// construct a default message and then deserialize from a view
var msg = Message();
msg.fromView(view);

// Construct a default message, deserialize from a view, but restrict payload
// type construction to OpenFlow 1.0
var msg = Message();
msg.fromView(view, 1);

// Construct a message from a view
var msg = fromView(view);

// Construct a message from a view, but restrict construction to OpenFlow 1.0
var msg = fromView(view, 1);

操作

提供的操作仅限于支持序列化/反序列化。

// Determine the current size in bytes of a message
if(view.available() < msg.bytes()) {
  throw 'Not enough bytes in view';
}
// Serialize the message to the view
msg.toView(view);

数据

Data类型是希望携带的消息有效负载的简单基类 未解释的数据。 OpenFlow有效负载类型中的典型模式是允许的 任意字节数组后缀任何有效负载类型。这种机制允许a 在几乎任何消息类型中传递非标准数据的标准方法。一些 OpenFlow消息类型将继承此类型。存储未解释的数据 作为字节数组使用缓冲区类型。

施工

可以明确地构造数据以发送和接收未解释的字节 阵列。大多数使用Data类型的有效内容类型都将继承自Data和 在toView / fromView的末尾调用super toView / fromView 实现。

// Construct an empty data set
var data = new Data();

// Construct a data set from a utf8 encoding of a string
var data = new Data('asdfasdfasdf');

// Construct a data set from a Buffer
var data = new Data(new Buffer(100));

操作

此类型仅暴露了一些操作:确定字节大小, serizliation和反序列化。

// Determine if enough bytes are available to serialize the data set
if(view.available() < data.bytes()) { ...

// Deserialize a data set from a view
data.fromView(view);

// Serialize a data set to a view
data.toView(view);

功能

makePayload(Class,type,Base)

所有OpenFlow有效内容类型必须关联其OpenFlow标头类型值 与他们的对象定义。一些OpenFlow有效载荷允许未解释 数据后缀有效载荷值,允许标准的传递方式 任何消息序列中的非标准数据。数据类型提供了此功能 通用的未解释的数据行为。这是一个用于分配的辅助函数 标题类型值,有时继承自Base对象原型,for 所有OpenFlow有效负载类型定义。

// Import the Data type
var dt = require('./data');
var util = require('./util');

// Construct a new payload type
function Hello(data) {
  ...
  // Call the base class constructor
  dt.Data.call(this, data);
}
// Establish its header type value of '0' and inherit from Data
util.makePayload(Hello, 0, dt.Data);

function Error(type, code, data) {
  this.type = ...;
  this.code = ...;
  // Call the base class constructor
  dt.Data.call(this, data);
}
// Establish its header type value of '1' and inherit from Data
util.makePayload(Hello, 1, dt.Data);

Error.prototype.fromView = function(view) {
  // Perform error field deserialization
  ...
  // Call the base class deserializer
  dt.Data.prototype.fromView.call(this, view);
};

fromView(类型,视图)

这是一个简单的辅助函数,它构造了一个Type的默认对象, 立即调用该对象上的fromView反序列化操作,并且 然后返回对象。这种模式对于减少非常有用 代码冗长。

var msg = util.fromView(Message, view);
var hdr = util.fromView(Header, view);
var hello = util.fromView(Hello, view);

makeIndex(类型)

这是每个OpenFlow版本化有效负载模块使用的构建器函数 将有效负载类型值的映射导出到有效负载类型。这张地图是必要的 通过任何版本的OpenFlow进行通用消息构造的输入。为了 要使地图生效,每个Type(Hello,Error等)必须导出Type值。如 只要使用makePayload帮助程序和类型值构建有效内容类型 提供,这个属性将持有。

// constructs a map of the payload types
var map = util.makeIndex([
  Hello,
  Error,
  ...
]);

// Resultant object
// {
//   "0": Hello,
//   "1": Error,
//   ...
// }

变体(图)

这是一个辅助函数,它为构造构建一个函数对象 变种类型。函数的输入是从类型字符串到Type的Map。 返回的值是一个带有类型值和视图的函数 在运行时构造和反序列化相应的Type。

// Construct a variant over a map of payload types
var variant = util.Variant({
  "0": Hello,
  "1": Error,
  ...
});
// Deserialize a header
var hdr = util.fromView(Header, view);
// Execute the variant deserializer based on input form the header
var payload = variant(hdr.type, view);

本文使用googletrans自动翻译,仅供参考, 原文来自github.com

en_README.md

OpenFlow Message Library js

This is a library for manipulating OpenFlow messages. It provides basic
facilities for message construction from sockets, files, or user programs. The
library establishes a basic set of patterns for Type Length Value (TLV) message
layer composition based on the paper Eliminating Network Protocol
Vulnerabilities throught Abstraction and System Language
Design
. This library is useful for anyone
wanting to quickly build OpenFlow based tools: testers, decoders, packet
generators, controllers, or switch-agents.

Sample Usage

// import the library
var ofp = require('ofpmsg-js');

// import some symbols into easier local names
var view   = ofp.view;
var ofp1_2 = ofp["1.2"];

// Construct a version specific message and serialize
var error = ofp1_2.Error({ type: 1, code: 2, data: 'This is wrong' });
var v = new view.View(new Buffer(1024));
error.toView(v);

// Reset the view so we can deserialize ... useful for testing :)
v.reset();

// Deserialize the view to any version of OpenFlow
var msg = ofp.msg.fromView(view);

// Reset the view so we can deserialize ... useful for testing :)
v.reset();

// Deserialize the view to version 1.2 of OpenFlow
var msg1_2 = ofp["1.2"].fromView(view);

Development Setup

  • Prerequisites:
    • Install Node or IO.js
    • Install Grunt globally - sudo npm install -g grunt-cli
  • Dependencies:
    • Install local dependencies - npm install
  • Tests:
    • Execute unit tests - grunt

Types Supported

  • View - memory abstraction for serialization/deserialization
  • Header - openflow header type
  • Message - generic OpenFlow message type
  • Data - wrapper for arbitrary uninterpreted data
  • Payloads - version specific OpenFlow payload types
  • ethernet.MAC - ethernet MAC address type
  • ipv4.Address - IPv4 address type

Functions Supported

  • header.bytes() - return the size in bytes of a header
  • util.makePayload(Class, type, Base) - builds OpenFlow payload types
  • util.makeIndex(Type) - builds an object map from header.type to payload Type
  • util.fromView(Type, view) - constructs a Type, calls fromView and returns obj
  • util.Variant(Index) - builds a variant transformer given a type-Type map

Exceptions Generated

  • Available
  • Undefined

View

This type is a simple abstraction that wraps a memory object. In javascript this
is the Buffer type. A view is critical for managing structural constraints and
ensuring we are always operating within safe regions of memory during message
binary based serialization or deserialization.

A view contains a Buffer object and tracks three locations within the buffer:
head, tail, and offset. The head and tail are immutable and point to the
boundaries of the underlying Buffer, while the offset is used as a cursor to
track serialization/deserialization progress through the Buffer. Read or write
operations against the view will advance the offset by the amount of bytes read
or written. All read/write operations assume a Most Significant Byte First
(MSBF) layer within memory.

Construction

A view can constructed from a Buffer object. The buffer may come from a
socket, file, or memory location. There are no optional construction arguments.
Additionally, a view may be constructed from another view. When decoding certain
types of protocols it is often necessary to artificially constrain the protocol
deserializers view of the input data. This can be achieved in two ways through:
advance, or constrain. Both operations return a new view over a restricted
subset of the existing Buffer object. Advance will advance the head pointer by
the indicated number of bytes, while constrain will reduce the tail pointer to
be the indicated number of bytes from the head.

// Construct a new view from a new Buffer
var view = new View(new Buffer(1024));

// Produce a new view without the 8 byte header
var newView = view.advance(8);

// Produce a new view constrained by the indicated payload length
var newView = view.constrain(100);

Operations

The view is the interface used for serialization/deserialization with a buffer.
The operations provided allow for: serialization and deserialization of unsigned
integer and byte array data types. Additionally, there are a few operations
provided for determining how many bytes are available for additional
serialization/deseriation. Finally, there is an operation reset that is useful
for testing. It allows for serializations to a view, reseting the offset
pointer, and then deserializing from the same view.

// Reset the offset pointer to be equal to the head
view.reset();

// Determine if enough bytes remain from `tail - offset` 
if(view.available() < 8) { ...

// Determine how many bytes used from `offset - head`
view.consumed()

// Deserialize a 1 byte unsigned integer
var version = view.readUInt8();

// Deserialize a 2 byte, MSBF, unsigned integer
var length  = view.readUInt16();

// Deserialize a 4 byte, MSBF, unsigned integer
var xid     = view.readUInt32();

// Deserialize a byte array from using all remaining buffer space
var data    = view.read();

// Deserialize a 32 element byte array
var name    = view.read(32);

// Serialize a 1 byte unsigned integer
view.writeUInt8(type);

// Serialize a 2 byte unsigned integer
view.writeUInt16(length);

// Serialize a 4 byte unsigned integer
view.writeUInt32(xid);

// Serialize a byte array
view.write(buffer);

Header

The OpenFlow header does not change across versions of the protocol. A header
includes a version (uint8), type (uint8), length (uint16), and transaction id
(uint32). All multi-byte unsigned integers are in Most Significant Byte First
(MSBF) order. A header's length indicates the number of bytes in an OpenFlow
message with is inclusive of the header and the message payload. A valid header
must have a length field with at least 8 bytes.

Construction

There are two ways of constructing a header: from terms by a programmer, or
through deserialization of a view.

// Construct a default state header and deserialize
var hdr = Header();
hdr.fromView(view);

// Construct a header given named terms
var hdr = Header({
  version: 1,
  type: 1,
  length: 8,
  xid: 1
});

// Construct a header from a view
var hdr = fromView(view);

Operations

Header operations support: serilaization, deserialization, validity checking,
and string representation.

// Determine if the header is valid (length >= bytes of the header)
if(hdr.isValid()) { ...

// Determine how many bytes the header consumes in a view
if(view.available() < hdr.bytes()) { ...

// Deserialize a view into a header
hdr.fromView(view);

// Serilaize a header into a view
hdr.toView(view);

// Print a string representaiton of the header
console.log(hdr.toString());

Functions

The header module only exports one function, which returns the number of bytes
required by a header for serialization/deserialization. This is a constant
expression as the header is a fixed block of fields.

// Determine if the view has enough space for a Header
if(view.available() < bytes()) { ...

Message

This is a generic encapsulation for any OpenFlow message. It includes a header
an payload property, where the header is constant regardless of verison of
OpenFlow but the payload varies according to version.

Construction

The constrution interfaces supplied are fairly flexible. A user can just supply
payloads and headers will be automatically constructed. Or the user can supply
headers and payloads in construction. Construction from views is possible in a
restricted and unrestricted fashion. You can construct from a view to any
version supported by the library, or indicate that construction should be
limited to a particular protocol

// Construct a message with the supplied payload, determine the header
var msg = Message({
  payload: ofp1_0.Hello()
});

// Construct a message with the supplied header and payload
var msg = Message({
  header:  hdr.Header(...),
  payload: ofp1_0.Hello()
});

// construct a default message and then deserialize from a view
var msg = Message();
msg.fromView(view);

// Construct a default message, deserialize from a view, but restrict payload
// type construction to OpenFlow 1.0
var msg = Message();
msg.fromView(view, 1);

// Construct a message from a view
var msg = fromView(view);

// Construct a message from a view, but restrict construction to OpenFlow 1.0
var msg = fromView(view, 1);

Operations

The operations provided are limited to supporting serialization/deserialization.

// Determine the current size in bytes of a message
if(view.available() < msg.bytes()) {
  throw 'Not enough bytes in view';
}
// Serialize the message to the view
msg.toView(view);

Data

The Data type is a simple base class for message payloads that wish to carry
uninterpreted data. A typical pattern in OpenFlow payload types is to allow for
arbitrary byte arrays to postfix any payload type. This mechanisms allows for a
standard way of passing non-standard data in almost any message type. Several
OpenFlow message types will inherit from this type. Uninterpreted data is stored
as a byte array usign the Buffer type.

Construction

Data can be constructed explicitly for sending and recieving uninterpreted byte
arrays. Most payload types that use the Data type will inherit from Data and
call the super toView/fromView at the end of their toView/fromView
implementations.

// Construct an empty data set
var data = new Data();

// Construct a data set from a utf8 encoding of a string
var data = new Data('asdfasdfasdf');

// Construct a data set from a Buffer
var data = new Data(new Buffer(100));

Operations

This type only exposed a few operations for: determining byte size,
serizliation, and deserialization.

// Determine if enough bytes are available to serialize the data set
if(view.available() < data.bytes()) { ...

// Deserialize a data set from a view
data.fromView(view);

// Serialize a data set to a view
data.toView(view);

Functions

makePayload(Class, type, Base)

All OpenFlow payload types must have their OpenFlow header type value associated
with their object definition. Some OpenFlow payloads allow for uninterpreted
data to postfix the payload values, which allows for a standard way of passing
non-standard data in any message sequence. The Data type provides for this
generic uninterpreted data behavior. This is a helper function for assigning the
header type value, and sometimes inheriting from a Base object prototype, for
all OpenFlow payload type definitions.

// Import the Data type
var dt = require('./data');
var util = require('./util');

// Construct a new payload type
function Hello(data) {
  ...
  // Call the base class constructor
  dt.Data.call(this, data);
}
// Establish its header type value of '0' and inherit from Data
util.makePayload(Hello, 0, dt.Data);

function Error(type, code, data) {
  this.type = ...;
  this.code = ...;
  // Call the base class constructor
  dt.Data.call(this, data);
}
// Establish its header type value of '1' and inherit from Data
util.makePayload(Hello, 1, dt.Data);

Error.prototype.fromView = function(view) {
  // Perform error field deserialization
  ...
  // Call the base class deserializer
  dt.Data.prototype.fromView.call(this, view);
};

fromView(Type, view)

This is a simple helper function that constructs a default object of Type,
immediately calls the fromView deserialization operation on that object, and
then returns the object. This pattern can be quite useful for cutting down on
code verbosity.

var msg = util.fromView(Message, view);
var hdr = util.fromView(Header, view);
var hello = util.fromView(Hello, view);

makeIndex(Type)

This is a builder function used by every OpenFlow versioned payload module to
export a map of payload type values to payload Types. This map is a necessary
input for generic message construction over any version of OpenFlow. In order
for the map to work, each Type (Hello, Error, etc.) must export a Type value. As
long as a payload type is built using the makePayload helper and a type value
is supplied, this property will hold.

// constructs a map of the payload types
var map = util.makeIndex([
  Hello,
  Error,
  ...
]);

// Resultant object
// {
//   "0": Hello,
//   "1": Error,
//   ...
// }

Variant(Map)

This is a helper function that builds a function object for the construction of
variant types. The input to the function is a Map from a type string to a Type.
The returned value is a function that takes a type value and view and will
construct and deserialize the appropriate Type at runtime.

// Construct a variant over a map of payload types
var variant = util.Variant({
  "0": Hello,
  "1": Error,
  ...
});
// Deserialize a header
var hdr = util.fromView(Header, view);
// Execute the variant deserializer based on input form the header
var payload = variant(hdr.type, view);