原版OpenFlow Switch Specification Version 1.3.0 (Wire Protocol 0x04) June 25, 2012 包含兩部分姚糊,前一部分是交換機規(guī)范蜒灰,共6個章節(jié),可以簡稱為“規(guī)范”塞弊;后一部分是將OpenFlow協(xié)議本身作為附件泪姨,可以認為是整體第7章枣宫,可以簡稱為“協(xié)議”文留。
本系列作為中文版拄氯,基本忠實原文語句和術(shù)語镊折,大部分關(guān)鍵詞都是中英文對照俄烁。將規(guī)范和協(xié)議再切分為2部分蟆豫,共4篇完整呈現(xiàn)芍锚。
OpenFlow 交換機規(guī)范 1.3.0 第一部分 1-5章
http://www.reibang.com/p/acfeae1771b3
OpenFlow 交換機規(guī)范 1.3.0 第二部分 6章
http://www.reibang.com/p/82e238eb8d14
OpenFlow協(xié)議第一部分
http://www.reibang.com/p/7eb86d164d26
OpenFlow協(xié)議第二部分
http://www.reibang.com/p/9cc08c698106
Appendix A The OpenFlow Protocol
附件A openflow 協(xié)議
Openflow 交換機規(guī)范的核心就是建立 Openflow 協(xié)議消息的結(jié)構(gòu)癌瘾。
下面描述的結(jié)構(gòu)饵溅,定義和枚舉都是源于文件 include/openflow/openflow.h妨退,此文件是 openflow 標準規(guī)范的一部分。所有結(jié)構(gòu)都是用填充和 8 字節(jié)來對齊(8-byte aligned),并且由斷言語句檢查碧注。所有OpenFlow消息都是以 big-endian 格式發(fā)送。
A.1 openflow 頭部
每個 openflow 消息都是以 head 開頭
/* 所有 OpenFlow 的頭部 /
struct ofp_header {
uint8_t version; / OFP_VERSION. 協(xié)議版本 /
uint8_t type; / 一個 OFPT_常數(shù) /
uint16_t length; / 包含頭部的長度 /
uint32_t xid; / 與包有關(guān)的事件 ID糖赔,回復配對請求時使用相同的 ID */
};
OFP_ASSERT(sizeof(struct ofp_header) == 8);
openflow 版本指正在使用的協(xié)議版本萍丐,早期階段的 openflow 草稿中,用最高位表示實驗版本放典,低位表明協(xié)議版本號∈疟洌現(xiàn)在介紹的協(xié)議 1.3.2,版本是 0x04奋构。
長度字段表明了消息的總長度壳影,因此并沒有用額外的幀標識去區(qū)分每個幀。
類型可以有以下值:
enum ofp_type {
/* 不可改變的消息 */
OFPT_HELLO = 0, /* 對稱消息 */
OFPT_ERROR= 1, /* 對稱消息 */
OFPT_ECHO_REQUEST= 2, /* 對稱消息 */
OFPT_ECHO_REPLY= 3, /* 對稱消息 */
OFPT_EXPERIMENTER= 4, /* 對稱消息 */
/* 交換機配置消息 */
OFPT_FEATURES_REQUEST = 5, /* 控制器 / 交換機消息 */
OFPT_FEATURES_REPLY= 6, /* 控制器 / 交換機消息 */
OFPT_GET_CONFIG_REQUEST = 7, /* 控制器 / 交換機消息 */
OFPT_GET_CONFIG_REPLY= 8, /* 控制器 / 交換機消息 */
OFPT_SET_CONFIG= 9, /* 控制器 / 交換機消息 */
/* 異步消息 */
OFPT_PACKET_IN = 10, /* 異步消息 */
OFPT_FLOW_REMOVED= 11, /* 異步消息 */
OFPT_PORT_STATUS = 12, /* 異步消息 */
/* 控制器命令消息 */
OFPT_PACKET_OUT= 13, 控制器 / 交換機消息 */
OFPT_FLOW_MOD = 14, 控制器 / 交換機消息 */
OFPT_GROUP_MOD= 15, 控制器 / 交換機消息 */
OFPT_PORT_MOD = 16, 控制器 / 交換機消息 */
OFPT_TABLE_MOD= 17, 控制器 / 交換機消息 */
/* 復合消息 */
OFPT_MULTIPART_REQUEST= 18, 控制器 / 交換機消息 */
OFPT_MULTIPART_REPLY= 19, 控制器 / 交換機消息 */
/* 屏障消息( 見 6.1.1 ) */
OFPT_BARRIER_REQUEST = 20, 控制器 / 交換機消息 */
OFPT_BARRIER_REPLY= 21, 控制器 / 交換機消息 */
/* 隊列配置消息. */
OFPT_QUEUE_GET_CONFIG_REQUEST = 22,/* 控制器 / 交換機消息 */
OFPT_QUEUE_GET_CONFIG_REPLY = 23, /* 控制器 / 交換機消息 */
/* 控制器角色改變請求消息 */
OFPT_ROLE_REQUEST = 24, 控制器 / 交換機消息 */
OFPT_ROLE_REPLY= 25, 控制器 / 交換機消息 */
/* 異步消息配置 */
OFPT_GET_ASYNC_REQUEST= 26, 控制器 / 交換機消息 */
OFPT_GET_ASYNC_REPLY = 27, 控制器 / 交換機消息 */
OFPT_SET_ASYNC= 28, 控制器 / 交換機消息 */
/* 測量器和速率限制器配置消息 */
OFPT_METER_MOD= 29, 控制器 / 交換機消息 */
};
A.1.1 填充
大多數(shù) openflow 消息都包含填充字段弥臼, 各種類型消息和各種共有的結(jié)構(gòu)中都有宴咧。 這些填充字段實際上它們的名字以 pad 開始,填充字段的目的就是使多字節(jié)實體和實際處理器邊界對齊径缅。
所有消息中共有結(jié)構(gòu)都是 64 比特對齊掺栅。其它類型則根據(jù)需要對齊,例如 32 位整數(shù)在32 位邊界中對齊纳猪。一個填充規(guī)則例外就是 OXM匹配字段氧卧,它從不進行填充 (A.3.2)。通常openflow 消息除非明確說明氏堤, 否則并不填充沙绝; 另一方面, 大多數(shù)共有的結(jié)構(gòu)都在結(jié)尾填充鼠锈。
填充字段應設(shè)置為零闪檬。 一個 openflow 實現(xiàn)必須能接受填充字段中設(shè)置的任何值, 而且必須忽略填充域中的內(nèi)容购笆。
A.2 公共結(jié)構(gòu)
本節(jié)介紹各種消息類型使用的結(jié)構(gòu)谬以。
A.2.1 端口結(jié)構(gòu)
Openflow 流水線通過端口收發(fā)數(shù)據(jù)包。交換機可以定義物理端口和邏輯端口由桌, openflow規(guī)范定義一些保留端口( 4.1 )为黎。
物理端口,交換機定義的邏輯端口行您, OFPP_LOCAL 保留端口結(jié)構(gòu)描述如下:
/* Description of a port */
struct ofp_port {
uint32_t port_no;
uint8_t pad[4];
uint8_t hw_addr[OFP_ETH_ALEN];
uint8_t pad2[2]; /* Align to 64 bits. */
char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */
uint32_t config; /* Bitmap of OFPPC_* flags. */
uint32_t state; /* Bitmap of OFPPS_* flags. */
/* Bitmaps of OFPPF_* that describe features. All bits zeroed if
* unsupported or unavailable. */
uint32_t curr; /* Current features. */
uint32_t advertised; /* Features being advertised by the port. */
uint32_t supported; /* Features supported by the port. */
uint32_t peer; /* Features advertised by peer. */
uint32_t curr_speed; /* Current port bitrate in kbps. */
uint32_t max_speed; /* Max port bitrate in kbps */
};
OFP_ASSERT(sizeof(struct ofp_port) == 64);
Port-no 唯一標識交換機內(nèi)的端口铭乾。 hw_addr 通常是端口 MAC地址; OFP_ETH_ALEN為 6.
名字字段是一個空終止字符串娃循,包含一個可讀接口名稱炕檩。 OFP_MAC_PORT_NAME_LEN值為 16.
配置字段描述端口的管理設(shè)置,有以下結(jié)構(gòu):
/* 物理端口的行為標志。 在 ofp_port 用這個標志描述當前端口配置笛质。用來設(shè)定端口行為泉沾。
*/
enum ofp_port_config {
OFPPC_PORT_DOWN= 1 << 0, /* 端口在管理下關(guān)閉 */
OFPPC_NO_RECV= 1 << 2, /* 丟棄端口接收的所有包 */
OFPPC_NO_FWD= 1 << 5, /* 丟棄所有轉(zhuǎn)發(fā)給該端口的包 */
OFPPC_NO_PACKET_IN= 1 << 6 /* 不向端口發(fā)送 packet-in 消息*/
};
這個OFPPC_PORT_DOWN位表明端口在管理下斷開,OpenFlow不應該使用妇押。 這 個OFPPC_NO_RECV位表明從哪個端口收到的包應該忽略跷究。 這個 OFPPC_NO_FWD位表明不應該發(fā)送包給這個端口。這個 OFPPFL_NO_PACKET_IN位表明這個端口的包發(fā)生漏表行為敲霍,不會觸發(fā)packet-in 消息給控制器俊马。
一般來說,端口配置位由控制器設(shè)置并且不被交換機改變肩杈。 這些位在交換機實現(xiàn)協(xié)議 ( 如:STP或者 BFD)時非常有用柴我。如果端口配置位被交換機通過其他管理接口改變了,交換機發(fā)送一個 OFPT_PORT_STATUS消息通知控制器發(fā)生了改變扩然。 (STP:生成樹協(xié)議 BFD:快速故障
檢測標準協(xié)議)
狀態(tài)字段描述了端口的內(nèi)部狀態(tài)艘儒,有以下結(jié)構(gòu):
/* 物理端口的當前狀態(tài),并不是由控制器配置的 */
enum ofp_port_state {
OFPPS_LINK_DOWN= 1 << 0, /* 目前沒有物理連接 */
OFPPS_BLOCKED= 1 << 1, /* 端口堵塞 */
OFPPS_LIVE= 1 << 2, /* 有效的快速故障備份組 */
};
端口狀態(tài)位代表物理連接或 openflower 以外的交換機協(xié)議夫偶。 OFPPS_LINK_DOWN位表明協(xié)議連接斷開彤悔。 OFPPS_BLOCKED位表明 openflowe 以外的交換,例如 802.1D 生成樹協(xié)議索守,防止OFPP_FLOOD端口的使用晕窑。
所有端口狀態(tài)位都是只讀的,不能被控制器改變卵佛。當端口標志改變時杨赤,交換機發(fā)送OFPT_PORT_STATUS消息通知控制器。
端口號使用以下規(guī)則:
/* 端口編號截汪。端口從 1 開始編號疾牲。 */
enum ofp_port_no {
OFPP_MAX= 0xffffff00, /* 物理端口和邏輯交換端口的最大號碼 */
/* 保留 OpenFlow 端口 ( 假裝輸出 "ports"). */
OFPP_IN_PORT= 0xfffffff8, /* 將包從輸入端口發(fā)出。為了將包發(fā)回給輸入端口衙解,這個保留端口必須要明確使用阳柔。 */
OFPP_TABLE= 0xfffffff9, /* 將包提交給第一個表。 NB: 這個目的端口只能在 packet-out消息中使用 */
OFPP_NORMAL= 0xfffffffa, /* 處理常規(guī)的 L2/L3 交換 */
OFPP_FLOOD= 0xfffffffb, /*VLAN 中所有物理端口, 除了輸入端口和阻塞的或者鏈路斷開的端口蚓峦。 */
OFPP_ALL= 0xfffffffc, /* 除了輸入端口外的所有物理端口 */
OFPP_CONTROLLER= 0xfffffffd, /* 發(fā)給控制器 */
OFPP_LOCAL= 0xfffffffe, /* 本地 openflow "port". */
OFPP_ANY= 0xffffffff /* 通配端口只能在流修改(刪除)舌剂、流統(tǒng)計請求中使用董济。篩選所
有流遏暴,無論是什么輸出端口(包括沒有輸出端口的流) */
};
Curr,advertised,supported,peer 字段表示鏈路模式( speed and duplexity ;10M 到
10G低匙,全雙工一汽、半雙工)避消,鏈路類型(銅 / 光纖),鏈路特征(自動協(xié)商和暫停)。 Curr 是當前連接方式岩喷、類型恕沫、特征; advertised 是廣播給對方的連接方式纱意、類型婶溯、特征; supported是支持的鏈路方式妇穴、類型、特征隶债。 Peer 是對方的連接方式腾它、類型、特征死讹。
端口特征由如下結(jié)構(gòu)表示:
/* 數(shù)據(jù)通道中有效端口的特征. */
enum ofp_port_features {
OFPPF_10MB_HD= 1 << 0, /* 支持 10M半雙工速率 */
OFPPF_10MB_FD= 1 << 1, /* 支持 10M全雙工速率 */
OFPPF_100MB_HD= 1 << 2, /* 支持 100M半雙工速率 */
OFPPF_100MB_FD= 1 << 3, /* 支持 100M全雙工速率 */
OFPPF_1GB_HD= 1 << 4, /* 支持 1 Gb半雙工速率 */
OFPPF_1GB_FD= 1 << 5, /* 支持 1 Gb全雙工速率 */
OFPPF_10GB_FD= 1 << 6, /* 支持 10Gb全雙工速率 */
OFPPF_40GB_FD= 1 << 7, /* 支持 40 Gb全雙工速率 */
OFPPF_100GB_FD= 1 << 8, /* 支持 100 Gb全雙工速率 */
OFPPF_1TB_FD= 1 << 9, /* 支持 1Tb 全雙工速率 */
OFPPF_OTHER= 1 << 10, /* 其他速率瞒滴,不在列表中 */
OFPPF_COPPER= 1 << 11, /* 銅線媒質(zhì). */
OFPPF_FIBER= 1 << 12, /* 光纖媒質(zhì) */
OFPPF_AUTONEG= 1 << 13, /* 自動協(xié)商 */
OFPPF_PAUSE= 1 << 14, /* 暫停 */
OFPPF_PAUSE_ASYM= 1 << 15 /* Asymmetric pause. */
};
多個標志可同時進行設(shè)置。如果沒有設(shè)置端口速度標志赞警,就會使用 max_speed 或者curr_speed妓忍。
curr_speed 表明鏈路當前傳輸速率, max_speed是最大傳輸速率愧旦, 以 kbps 為單位世剖。 將數(shù)字四舍五入適應通常的用法。例如笤虫,一個光學的 10Gb以太網(wǎng)端口應該設(shè)置字段為 10000000而不是 10312500旁瘫,一個 OC_192端口應該將字段設(shè)置為 100000000 而不是 9953280
Max_speed表明了鏈路的最大速率,而 curr_speed 表明了當前速率琼蚯。一個有三條鏈路的 LAG端口最大速率為 1Gb/s, 其中一個端口關(guān)閉酬凳, 一個端口自動協(xié)商速率為 1Gb/s, 一個端口自動協(xié)商速率 100Mb/s,最大速率為3Gb/s, 當前速率為 1.1Gb/s。
A.2.2 隊列結(jié)構(gòu)
一個 openflow 交換機通過簡單的排隊機制提供有限的 QoS服務(wù)遭庶。 一個(或多個) 隊列可以連接到端口宁仔,用來與流表項映射。流表項映射的某個隊列峦睡,就根據(jù)這個隊列的配置處理翎苫。
(注:將隊列綁定在某個端口,實現(xiàn)有限的流量控制操作)
隊列由一個 ofp_packet_queue 結(jié)構(gòu)來描述:
/* 隊列的完整描述 */
struct ofp_packet_queue {
uint32_t queue_id; /* 指定隊列的 ID */
uint32_t port; /* 隊列所屬的端口 */
uint16_t len; /* 隊列的字節(jié)長度 */
uint8_t pad[6];/* 64-bit 校正*/ (與上面的湊成 64 倍數(shù))
struct ofp_queue_prop_header properties[0]; /* 特性列表 */
};
OFP_ASSERT(sizeof(struct ofp_packet_queue) == 16);
一組屬性榨了,類型和配置來進一步描述每個隊列拉队。
enum ofp_queue_properties {
OFPQT_MIN_RATE= 1, /* 最低速率保證 */
OFPQT_MAX_RATE= 2, /* 最大速率 */
OFPQT_EXPERIMENTER= 0xffff /* 實驗定義屬性 */
};
每個隊列屬性描述以共同的頭部開始:
/* 隊列的一般描述。 */
struct ofp_queue_prop_header {
uint16_t property; /* OFPQT_.中的某一個 */
uint16_t len; /* 屬性的長度阻逮,包括頭部的長度 */
uint8_t pad[4]; /* 64-bit alignemnt. */
};
OFP_ASSERT(sizeof(struct ofp_queue_prop_header) == 8);
一個最小速率的隊列特性使用下列結(jié)構(gòu)和字段:
/* Min-Rate 隊列特征描述 */
struct ofp_queue_prop_min_rate {
struct ofp_queue_prop_header prop_header; /* prop: OFPQT_MIN, len: 16.*/
uint16_t rate; /* 以 0.1%為單位; 禁止大于 1000 */
uint8_t pad[6]; /* 64-bit 對齊 */
};
OFP_ASSERT(sizeof(struct ofp_queue_prop_min_rate) == 16);
如果沒有設(shè)定速率粱快,則速率設(shè)置為 OFPQ_MIN_RATE_UNCFG,即 0xfff。
一個最大速率隊列用的結(jié)構(gòu)和字段如下:
/* Max-Rate 隊列特征描述 */
struct ofp_queue_prop_max_rate {
struct ofp_queue_prop_header prop_header; /* prop: OFPQT_MAX,len: 16. */
uint16_t rate; /* 以 0.1%為單位; 禁止大于 1000 */
uint8_t pad[6]; /* 64-bit 對齊 */
};
OFP_ASSERT(sizeof(struct ofp_queue_prop_max_rate) == 16);
如果沒有設(shè)定速率事哭,則速率為 OFPQ_MAX_RATE_UNCFG漫雷,即 0fff。
一個實驗隊列屬性用的結(jié)構(gòu)和字段如下:
/* Experimenter 隊列特征描述 */
struct ofp_queue_prop_experimenter {
struct ofp_queue_prop_header prop_header; /* prop: OFPQT_EXPERIMENTER,len:
16. */
uint32_t experimenter; /* Experimenter ID 與 ofp_experimenter_header 結(jié)構(gòu)形式
相同*/
uint8_t pad[4]; /* 64-bit 對齊 */
uint8_t data[0]; /* 實驗者定義的數(shù)據(jù) */
};
OFP_ASSERT(sizeof(struct ofp_queue_prop_experimenter) == 16);
標準 Openflow 處理并沒有解釋其余的實驗隊列屬性鳍咱,而是由實驗者自己定義降盹。
A.2.3 流匹配結(jié)構(gòu)
一個 openflow 匹配表是由流匹配頭部和一序列 0 或者一些流匹配字段組成。
A.2.3.1 流匹配頭部
用 ofp_match 結(jié)構(gòu)描述匹配頭部:
/* 流的匹配字段 */
struct ofp_match {
uint16_t type; /* One of OFPMT_**/
uint16_t length; /* ofp_match 長度( 包括填充字段) */
/* Followed by:
* - Exactly (length - 4) (possibly 0) bytes containing OXMTLVs, then
* - Exactly ((length + 7)/8*8 - length) (between 0 and 7) bytes of
* all-zero bytes
*總之, 需要時就在 ofp_match 中進行填充, 使其為 8 的倍數(shù)谤辜,結(jié)構(gòu)長度對齊蓄坏。
*/
uint8_t oxm_fields[0]; /* 0 or more OXMmatch fields */
uint8_t pad[4]; /* Zero bytes - see above for sizing */
};
OFP_ASSERT(sizeof(struct ofp_match) == 8);
type 字段設(shè)置為 OFPMT_OXM,長度字段為包括所有匹配字段在內(nèi)的 ofp_match 結(jié)構(gòu)的實際長度丑念。 OpenFlow 有效載荷是一組 OXM流匹配字段涡戳。
/* 匹配類型表明正在使用的匹配結(jié)構(gòu) (構(gòu)成匹配的字段組)。所有匹配結(jié)構(gòu)中匹配類型在類型字段的開始脯倚。 "OpenFlow Extensible Match" 類型 與下面介紹的 OXMTLV 格式相符渔彰,并且必須所有交換機都支持。 Extensions that define other match types maybe published on the ONF wiki. 擴展項支持是可選的推正。
*/
enum ofp_match_type {
OFPMT_STANDARD= 0, /* 不贊成 */
OFPMT_OXM= 1, /* OpenFlow Extensible Match */
};
此 規(guī) 范 中 唯 一 有 效 的 匹 配 類 型 是 OFPMT_OXM,不 支 持 OpenFlow 1.1 匹 配 類 型OFPMT_STANDARD恍涂。如果使用另一種匹配類型,匹配字段和有效載荷可能變得會不一樣植榕,但是這超出了本規(guī)范的范圍再沧。
A.2.3.2 Flow Match Field Structures
流 匹 配 字 段 用 OpenFlow 可 擴 展 的 匹 配 (OXM)格 式 來 描 述, 即一種簡化的形式type-length-value (TLV)尊残。每個 OXMTLV長度從 5 到 259 ( 包括全部) 字節(jié)产园。 OXMTLVs 沒有相同的長度, 也沒有采取填充來對齊夜郁。 一個 OXMTLV 的前四個字節(jié)是頭部什燕,下面接的是 body部分。
一個 OXMTLV的頭部可看成一個網(wǎng)絡(luò)字節(jié)順序的 32-bit 字 ( 見圖 4)竞端。
OXMTLV的頭部定義如 Table 9
oxm_class 是一個 OXM匹配類屎即,包含相關(guān)的匹配類型,在 A.2.3.3 節(jié)有相關(guān)介紹事富。
oxm_field 是一個 class-specfic 值, 在匹配類里區(qū)分某一個匹配類型技俐。 oxm_class 和oxm_field 兩者(the most-signicant 23 bits of the header) 都是 oxm_type。oxm_type 通常表示一個協(xié)議的頭部字段统台,例如以太網(wǎng)類型雕擂,也可以適用于元數(shù)據(jù),例如數(shù)據(jù)包到達的那個交換機端口贱勃。
oxm_hasmask 定義如果 OXMTLV 包含位掩碼井赌,在 A.2.3.5 部分有詳細介紹谤逼。
oxm_length 是以字節(jié)為單位的正整數(shù),表示 OXMTLV負荷長度仇穗。 OXMTLV的長度流部,包括頭部,是精確地 4+oxm_length 個字節(jié)纹坐。
對于一個指定的 oxm_class, oxm_field, and oxm_hasmask 值, oxm_length 是一個常量枝冀。包括只允許軟件最低限度的解析 OXMTLV的未知類型。(類似的耘子,若指定 oxm_class,oxm_field, and oxm_length, 則 oxm_hasmask 是一個常量果漾。)
A.2.3.3 OXMclasses
匹配類型使用 OXM匹配類進行了結(jié)構(gòu)化, openflow 規(guī)范可以區(qū)分 OXM的兩種匹配類谷誓, ONF成員類和 ONF保留類绒障, 使用高位比特區(qū)分。 高位比特為 1 是 ONF保留類片林, 供 openflow 規(guī)范本身使用端盆。高位比特為 0 的是ONF成員類怀骤,必要時由 ONF分配费封,標識一個 ONF成員,并且可任意使用蒋伦。對 ONF成員類的支持是可選的弓摘。
OXM類定義如下:
/* OXMClass IDs.
* 高位比特區(qū)分保留類和成員類
* 0x0000 到 0x7FFF 的是成員類,由 ONF分配
* 0x8000 到 0xFFFE 的是保留類, 用于標準化痕届。
*/
enum ofp_oxm_class {
OFPXMC_NXM_0= 0x0000, /* 與 NXM后向兼容 */
OFPXMC_NXM_1= 0x0001, /* 與 NXM后向兼容 */
OFPXMC_OPENFLOW_BASIC = 0x8000, /* OpenFlow 基本類 */
OFPXMC_EXPERIMENTER= 0xFFFF, /* 實驗者類 */
};
OPPXMC_OPENFLOW_BASIC 類包含 openflow 匹配域的基本設(shè)置(見 A.2.3.7 )韧献。可選類OFPXMC_EXPERIMENTER 用于實驗者匹配(見 A.2.3.8 )研叫。其他 ONF保留類用于將來使用锤窑,如用于規(guī)范的 模塊化。 ONF成員類的前兩個OFPXMC_NXM_0和 OFPXMC_NXM_1用 于 與 Nicira Extensible Match(NXM)規(guī)范的后向兼容嚷炉。
A.2.3.4 Flow Match
一個 zero —length 的 openflow 匹配( 即沒有 OXMTLVs)可以匹配每個包渊啰。應被通配的匹配字段都從 openflow 匹配中忽略。
OXMTLV 對由 openflow 匹配進行匹配的包設(shè)置限制:
如果 oxm_hasmask為 0申屹,OXM TLV的 body 包含該字段的值绘证,稱為 oxm_value。OXM TLV匹配僅與相應字段等于 oxm_value 的包相匹配哗讥。
如果 oxm_hasmask為 1嚷那,oxm_entry 的 body 包含該字段的值 (oxm_value),緊接著是一個相同長度的位掩碼杆煞,叫為 oxm_mask魏宽。oxm_mask 里的每 1_bit 限制 OXMTLV 只能匹配字段與 oxm_value 相應位相等的包腐泻。 oxm_mask 的 0_bit 沒有這樣的限制。
當使用掩碼時湖员, oxm_mask中的 0_bit 與 oxm_value 中的 1_bit 一致時產(chǎn)生錯誤贫悄。交換機必須用OFPET_BAD_MATCH類型的消息和 OFPBMC_BAD_WILDCARDS 事件報告錯誤。
下表總結(jié)了相對應的 oxm_mask與 oxm_value 位之間在使用掩碼時的約束關(guān)系娘摔。忽略oxm_mask等同于提供一個全是 1-bit 的 oxm_mask窄坦。
當有多個 OXMTLV 時,要滿足所有的約束關(guān)系:包字段必須匹配 openflow 匹配中所有OXMTLV的部分凳寺。若沒有 OXMTLV的字段鸭津,則通配成 ANY, 忽略的 OXMTLV全部掩碼為零肠缨。
A.2.3.5 流匹配字段掩碼
當 oxm_hasmask為 1逆趋,OXMTLV包含一位掩碼并且長度有效地增加一倍, 所以 oxm_length總是 奇數(shù), 位掩碼在字段值之后晒奕,使用相同的方式編碼闻书。掩碼定義某個指定的位為 0,表明與其相應字段相同位的匹配是一種“ don’t care”匹配脑慧,而 1 意味著要精確匹配魄眉。
一個全 0比特 oxm_mask等同于 徹底忽略 OXM TLV,一個全1 比特oxm_mask等同于 指定oxm_hasmask為0,并且忽略 oxm_mask闷袒。
一些oxm_type不支持掩碼的通配符坑律,也就是說,當這些字段被指定時 oxm_hasmask必須為0囊骤。例如晃择,標識數(shù)據(jù)包接收的輸入端口(接受包的端口)字段可能未被掩碼。
一些oxm_type 不支持掩碼通配符也物,可能只支持特定 oxm_mask模式宫屠。例如,一些有 IPv4地址的字段可能被限制為 CIDR掩碼(子網(wǎng)掩碼)滑蚯。
個別字段的限定會在規(guī)范中詳細說明浪蹂。交換機可能接受規(guī)范不允許的 oxm_hasmask oxm_mask值,只要交換機能正確執(zhí)行對 oxm_hasmask 或oxm_mask值的支持膘魄,交換機必須拒絕嘗試創(chuàng)建包含它不支持的 oxm_hasmask或oxm_mask值的流表項(見 6.4 )乌逐。
A.2.3.6 流匹配字段基礎(chǔ)
給定oxm_type的OXMTLV的存在是受到其他 OXM TLV的存在或值的限制,一般來說创葡,只有當openflow 匹配明確地匹配了相應的協(xié)議浙踢,才能匹配協(xié)議的頭部字段。
例如:
只 有 在 另 一 個 表 項 中 oxm_type=OXM_OF_ETH_TYPE,oxm_hasmask=0,并且oxm_value=0x0800的前提下灿渴,才允許 OXM TLV 中xom_type=OXM_OF_IPV4_SRC洛波。也就是說胰舆,只有以太網(wǎng)的類型明確設(shè)置為 IPV4時,IPV4源地址的匹配才被允許蹬挤。
只有在一個表項中 oxm_type=OXM_OF_ETH_TYPE,oxm_hasmask=0, oxm_value=0x0800或0x6dd, 并且另一個表項中 oxm_type=OXM_OF_IP_PROTO,oxm_mask=0,oxm_value=6 的前提下缚窿,O才允許 OXM TLV中 xom_type=OXM_OF_TCP_SRC。也就是說焰扳,只有當以太網(wǎng)的類型為 IP,IP 協(xié)議為TCP時倦零,在 TCP源端口的匹配才允許。
只有在一個表項中 oxm_type=OXM_OF_ETH_TYPE,oxm_hasmask=0,oxm_value=0x8847或0x8848時吨悍,才允許 OXM TLV中oxm_type=OXM_OF_MPLS_LABEL扫茅。
只有在一個表項中 oxm_type=OXM_OF_VLAN_VID,oxm_value!=OFPVID=NONE 時, 才允許OXM TLV中oxm_type=OXM_OF_VLAN_PCP育瓜。
這些對個別字段的限制在規(guī)范中進行了說明 (見7.2.3.7 )葫隙。交換機實現(xiàn)時可放寬這些限制。例如躏仇,交換機可能在沒有任何先決條件的情況下接受恋脚。交換機必須拒絕建立試圖違反限
制的流表項(見 6.4 ),并且必須處理那些由于缺乏先決條件而不一致的匹配 (如焰手, 既匹配 TCP源端口又匹配 UDP目的端口)糟描。
由成員(成員類或作為實驗者字段)定義的新的匹配字段可為已有匹配字段提供了備用條件。例如册倒,通過替換 ETH_TYPE蚓挤,在可選鏈路技術(shù)(如 PPP)上重復使用用已有的 IP匹配字段(對于 PPP,那可能是一個假設(shè)的 PPP_PROTOCOL 字段)磺送。
有條件約束的 OXM TLV必須出現(xiàn)在那些作為條件的 OXM TLV后面驻子,那些在 openflow 匹配里的OXMTLV的順序不受約束。
任一指定的 oxm_type最多在 openflow 匹配中出現(xiàn)一次估灿,否則崇呵,交換機必須產(chǎn)生一個錯誤(見6.4 )。交換機實現(xiàn)時可放松這個規(guī)則馅袁, 允許在某些情況下多次出現(xiàn) oxm_type, 但是域慷, 這種匹配行為由具體實現(xiàn)來決定。
如果一個流表實現(xiàn)指定的 OXM TLV,這個流表必須接受包含其先決條件的有效匹配汗销,即使這個流表并不支持先決條件指定的匹配域的所有可能值犹褒。例如,一個流表匹配 IPv4源地址弛针,這個流表必須接受以太網(wǎng)類型精確匹配 IPV4叠骑,但是不需要支持以太網(wǎng)類型匹配其他任何值。
A.2.3.A.流匹配域
本規(guī)范為 oxm_class=OFPAMC_OPENFLOW_BASIC 的匹配字段定義了一個默認的集合削茁, 其值如下:
/* OXMFlow match field types for OpenFlow basic class. */
enum oxm_ofb_match_fields {
OFPXMT_OFB_IN_PORT= 0, /* Switch input port. */
OFPXMT_OFB_IN_PHY_PORT= 1, /* Switch physical input port. */
OFPXMT_OFB_METADATA = 2, /* Metadata passed between tables. */
OFPXMT_OFB_ETH_DST= 3, /* Ethernet destination address. */
OFPXMT_OFB_ETH_SRC= 4, /* Ethernet source address. */
OFPXMT_OFB_ETH_TYPE= 5, /* Ethernet frame type. */
OFPXMT_OFB_VLAN_VID= 6, /* VLAN id. */
OFPXMT_OFB_VLAN_PCP= 7, /* VLAN priority. */
OFPXMT_OFB_IP_DSCP= 8, /* IP DSCP(6 bits in ToS field). */
OFPXMT_OFB_IP_ECN= 9, /* IP ECN (2 bits in ToS field). */
OFPXMT_OFB_IP_PROTO= 10, /* IP protocol. */
OFPXMT_OFB_IPV4_SRC= 11, /* IPv4 source address. */
OFPXMT_OFB_IPV4_DST= 12, /* IPv4 destination address. */
OFPXMT_OFB_TCP_SRC= 13, /* TCP source port. */
OFPXMT_OFB_TCP_DST= 14, /* TCP destination port. */
OFPXMT_OFB_UDP_SRC= 15, /* UDPsource port. */
OFPXMT_OFB_UDP_DST= 16, /* UDPdestination port. */
OFPXMT_OFB_SCTP_SRC= 17, /* SCTP source port. */
OFPXMT_OFB_SCTP_DST= 18, /* SCTP destination port. */
OFPXMT_OFB_ICMPV4_TYPE= 19, /* ICMP type. */
OFPXMT_OFB_ICMPV4_CODE = 20, /* ICMP code. */
OFPXMT_OFB_ARP_OP= 21, /* ARPopcode. */
OFPXMT_OFB_ARP_SPA= 22, /* ARP source IPv4 address. */
OFPXMT_OFB_ARP_TPA= 23, /* ARP target IPv4 address. */
OFPXMT_OFB_ARP_SHA= 24, /* ARP source hardware address. */
OFPXMT_OFB_ARP_THA= 25, /* ARP target hardware address. */
OFPXMT_OFB_IPV6_SRC= 26, /* IPv6 source address. */
OFPXMT_OFB_IPV6_DST= 27, /* IPv6 destination address. */
OFPXMT_OFB_IPV6_FLABEL= 28, /* IPv6 Flow Label */
OFPXMT_OFB_ICMPV6_TYPE= 29, /* ICMPv6 type. */
OFPXMT_OFB_ICMPV6_CODE = 30, /* ICMPv6 code. */
OFPXMT_OFB_IPV6_ND_TARGET = 31, /* Target address for ND. */
OFPXMT_OFB_IPV6_ND_SLL= 32, /* Source link-layer for ND. */
OFPXMT_OFB_IPV6_ND_TLL= 33, /* Target link-layer for ND. */
OFPXMT_OFB_MPLS_LABEL = 34, /* MPLSlabel. */
OFPXMT_OFB_MPLS_TC= 35, /* MPLSTC. */
OFPXMT_OFP_MPLS_BOS = 36, /* MPLSBoS bit. */
OFPXMT_OFB_PBB_ISID= 37, /* PBB I-SID. */
OFPXMT_OFB_TUNNEL_ID= 38, /* Logical Port Metadata. */
OFPXMT_OFB_IPV6_EXTHDR= 39, /* IPv6 Extension Header pseudo-field */
};
交換機在它的流水線中必須支持表 11中列出的 required 匹配域宙枷。每個 required 匹配域在交換機中必須至少有一個流表支持:流表必須保證匹配那個字段掉房,匹配域的先決條件在表中必須已列出(見 A.2.3.6 )。required 域并不需要在所有流表中實現(xiàn)慰丛,也不需要在相同流表中實現(xiàn)卓囚。流表可以支持 no-requried 和實驗者匹配域。 控制器可以查詢交換機中每個流表支持哪些匹配域诅病。
每個匹配域有不同的大小哪亿,先決條件,和掩碼能力贤笆,如表 12所示锣夹。如果沒有明確說明,每個字段類型指的就是數(shù)據(jù)包頭域最外層事件苏潜。
輸入端口 OXM_OF_IN_PORT是一個有效的標準 openflow 端口银萍,可以是物理端口,邏輯端口恤左,OFPP_LOCAL保留端口或是 OFPP_CONTROLLER保留端口贴唇。物理端口 OXM_OF_IN_PHY_PORT在包輸入消息中用來標識邏輯端口下層的物理端口(見 A.4.1 )。
在多個表間查找時飞袋,元數(shù)據(jù)域 OXM_OF_METADATA 用來傳遞信息戳气。這個值可被隨意覆蓋。
隧道 ID 字段 OXM_OF_TUNNEL_ID攜帶與邏輯端口有關(guān)的可選元數(shù)據(jù)巧鸭。元數(shù)據(jù)的映射由邏輯端口實現(xiàn)定義瓶您。如果邏輯端口不支持這樣的數(shù)據(jù)或者數(shù)據(jù)包從物理端口接收,則值為 0纲仍。
例如呀袱,一個通過 GRE隧道接收的數(shù)據(jù)包包括一個( 32 位)密鑰,密鑰存儲在低 32 位郑叠,高 32位為 0夜赵。對 MPLS邏輯端口,低 20 位表示 MPLS標記乡革。對 VxLAN邏輯端口寇僧,低 24 位表示 VNI。
忽略 OFPXMT_OFB_LAN_VID字段表明流表項應該匹配數(shù)據(jù)包沸版, 無論數(shù)據(jù)包是否包含相應的標簽嘁傀。對于 VLAN標簽定義了下列特殊值,允許其匹配任何標簽的數(shù)據(jù)包视粮,與標簽的值無關(guān)细办,并且支持匹配沒有 VLAN標簽的數(shù)據(jù)包。為 OFPXMT_OFB_VLAN_VID定義的特殊值如下:
/* VLAN id 是 12-bits, 所以可以用總共 16 位來表示特殊情況
*
*/
enum ofp_vlan_id {
OFPVID_PRESENT= 0x1000, /* 表示 VLAN id 的 bit 位*/
OFPVID_NONE= 0x0000, /* 沒有設(shè)置 VLAN id */
};
當 OFPXMT_OFB_VLAN_VID字段為 通配 時(不是當前)或者 OFPXMT_OFB_VLAN_VID設(shè)置為OFPVID_NONE時必須拒絕 OFPXMT_OFB_VLAN_PCP 字段馒铃。表 13 總結(jié)了通配位的組合蟹腾,以及特殊的 VLAN標簽匹配的域值痕惋。
OXM_OF_IPV6_EXTHDR是一個偽字段,表明數(shù)據(jù)包頭部中不同的 IPV6 擴展頭部娃殖。 IPV6 擴展頭部比特組合在 OXM_OF_EXTHDR字段中值戳,這些比特位有下列值:
/* IPv6擴展報頭定義位為 pseudo-field */
enum ofp_ipv6exthdr_flags {
OFPIEH_NONEXT= 1 << 0, /* "No next header" encountered. */
OFPIEH_ESP= 1 << 1, /* Encrypted Sec Payload header present. */
OFPIEH_AUTH= 1 << 2, /* Authentication header present. */
OFPIEH_DEST= 1 << 3, /* 1 or 2 dest headers present. */
OFPIEH_FRAG= 1 << 4, /* Fragment header present. */
OFPIEH_ROUTER= 1 << 5, /* Router header present. */
OFPIEH_HOP= 1 << 6, /* Hop-by-hop header present. */
OFPIEH_UNREP= 1 << 7, /* Unexpected repeats encountered. */
OFPIEH_UNSEQ= 1 << 8, /* Unexpected sequencing encountered. */
};
如果IPv6逐跳選項擴展報頭作為數(shù)據(jù)包中第一個擴展報頭則 OFPIEH_HOP設(shè)為1。
如果目前是一個 IPv6路由擴展報頭則設(shè)置 OFPIEH_ROUTER為1炉爆。
如果目前是 IPv6分片擴展報頭則設(shè) OFIEH_FRAG為1堕虹。
如果目前是一個或多個 IPv6目的地選項擴展報頭則設(shè) OFPIEH_DEST為1。IPv6數(shù)據(jù)包中有一個或兩個很正常(見 RFC2460)芬首。
如果目前是 IPv6身份驗證擴展報頭則設(shè)置 OFPIEH_AUTH為1赴捞。
如果目前是 IPv6封裝安全凈荷擴展報頭則設(shè)置 OFPIEH_ESP為1。
如果目前 IPv6沒有下一個頭擴展報頭怎設(shè) OFIEH_NONNEXT 設(shè)為1郁稍。
如果IPv6擴展報頭不是 RFC的優(yōu)選項(不要求的)赦政,則設(shè) OFPIEH_UNSEQ為1。
如果多個 IPv6擴展報頭不期而遇耀怜, 則設(shè)OFPIEH_UNREP為1恢着。(若是兩個目的地的可選報頭,將不需要設(shè)置該位)财破。
A.2.3.8 實驗者流匹配字段
對 experimenter-specific 流匹配字段的支持是可選的掰派。 Experimenter-specific 可使用oxm_class=OFPXMC_EXPERIMENTER來定義流匹配字段。 OXM TLV body 前 4 個字節(jié)包含實驗
者身份左痢,結(jié)構(gòu)同 ofp_experimenter (見 A.5.4 )靡羡。Oxm_field 和 OXMTLV 其余部分都是
experimenter-defined 并且不需要填充或?qū)R。
/* Header for OXMexperimenter match fields. */
struct ofp_oxm_experimenter_header {
uint32_t oxm_header; /* oxm_class = OFPXMC_EXPERIMENTER*/
uint32_t experimenter; /* Experimenter ID which takes the same
form as in struct ofp_experimenter_header. */
};
OFP_ASSERT(sizeof(struct ofp_oxm_experimenter_header) == 8);
A.2.4 流指令結(jié)構(gòu)
當流匹配了流表項俊性,就執(zhí)行與這個流表項相關(guān)的流指令略步。定義的指令列表如下:
enum ofp_instruction_type {
OFPIT_GOTO_TABLE= 1, /* Setup the next table in the lookuppipeline */
OFPIT_WRITE_METADATA= 2, /* Setup the metadata field for use later inpipeline */
OFPIT_WRITE_ACTIONS= 3, /* Write the action(s) onto the datapath actionset */
OFPIT_APPLY_ACTIONS= 4, /* Applies the action(s) immediately */
OFPIT_CLEAR_ACTIONS= 5, /* Clears all actions from the datapathaction set */
OFPIT_METER= 6, /* Apply meter (rate limiter) */
OFPIT_EXPERIMENTER= 0xFFFF /* Experimenter instruction */
};
5.9 節(jié)中介紹的指令集,流表可能支持指令類型的子集磅废。指令定義包含指令類型纳像,長度
及相關(guān)數(shù)據(jù)荆烈。
/* 所有指令通用頭部拯勉。長度包括頭部和為了實現(xiàn) 64-bit 對齊的填充部分。
* NB: 指令長度必須為 8 的倍數(shù) */
struct ofp_instruction {
uint16_t type; /* Instruction type */
uint16_t len; /* Length of this struct in bytes. */
};
OFP_ASSERT(sizeof(struct ofp_instruction) == 4);
OFPIT_GOTO_TABLE指令用以下結(jié)構(gòu)和字段:
/* OFPIT_GOTO_TABLE的指令結(jié)構(gòu) */
struct ofp_instruction_goto_table {
uint16_t type; /* OFPIT_GOTO_TABLE*/
uint16_t len; /* Length of this struct in bytes. */
uint8_t table_id; /* Set next table in the lookup pipeline */
uint8_t pad[3]; /* Pad to 64 bits. */
};
OFP_ASSERT(sizeof(struct ofp_instruction_goto_table) == 8);
table_id 表示數(shù)據(jù)包處理流水線中的下一個表憔购。
OFPIT_WRITE_METADATA指令用以下結(jié)構(gòu)和字段:
/* OFPIT_WRITE_METADATA的指令結(jié)構(gòu) */
struct ofp_instruction_write_metadata {
uint16_t type; /* OFPIT_WRITE_METADATA*/
uint16_t len; /* Length of this struct in bytes. */
uint8_t pad[4]; /* Align to 64-bits */
uint64_t metadata; /* Metadata value to write */
uint64_t metadata_mask; /* Metadata write bitmask */
};
OFP_ASSERT(sizeof(struct ofp_instruction_write_metadata) == 24);
下一個表要查找元數(shù)據(jù)宫峦, 可以用 metadata 和 metadata_mask 寫入匹配字段的指定比特。
如果這個指令沒有規(guī)定玫鸟,則元數(shù)據(jù)發(fā)送時不需改變导绷。
OFPIT_WRITE_ACTIONS,OFPIT_APPLY_ACTIONS, 和 OFPIT_CLEAR_ACTIONS指令用以下
結(jié)構(gòu)和字段:
/*OFPIT_WRITE/APPLY/CLEAR_ACTIONS的結(jié)構(gòu)指令 */
struct ofp_instruction_actions {
uint16_t type; /* OFPIT_*_ACTIONS的一種 */
uint16_t len; /* 此結(jié)構(gòu)的比特長度 */
uint8_t pad[4]; /* 64 位對齊 */
struct ofp_action_header actions[0];
/* 0 個或多個與 OFPIT_WRITE_ACTIONS和 OFPIT_APPLY_ACTIONS相關(guān)的行動 */
};
OFP_ASSERT(sizeof(struct ofp_instruction_actions) == 8);
對于 Apply-Actions 指令屎飘,行動字段被當做一個列表妥曲,此行動應用于有序包贾费。對于
Write-Actions 指令,行動字段作為一個集合檐盟,此行動并入當前行動集褂萧。
對于 Clear-Actions 指令,此結(jié)構(gòu)不包含任何行動葵萎。
指令 OFPIT_METER使用以下的結(jié)構(gòu)和字段导犹。
/*OFPIT_METER的結(jié)構(gòu)指令 */
struct ofp_instruction_meter {
uint16_t type; /* OFPIT_METER的類型 */
uint16_t len; /* Length is 8. */
uint32_t meter_id; /* Meter 實例的 ID. */
};
OFP_ASSERT(sizeof(struct ofp_instruction_meter) == 8);
meter_id 顯示被應用在包上的測量。
指令 OFPIT_EXPERIMENTER使用以下的結(jié)構(gòu)和字段:
/*OFPIT_EXPERIMENTER的結(jié)構(gòu)指令 */
struct ofp_instruction_experimenter {
uint16_t type; /* OFPIT_EXPERIMENTER*/
uint16_t len; /* 結(jié)構(gòu)的比特長度 */
uint32_t experimenter;
/*Experimenter ID羡忘,其格式同 ofp_experimenter_header */
/* 實驗者自定義的其它數(shù)據(jù). */
};
OFP_ASSERT(sizeof(struct ofp_instruction_experimenter) == 8);
A.2.5 行動的結(jié)構(gòu)
許多行動是和流表項谎痢、組或數(shù)據(jù)相關(guān)的,目前定義的行動類型如下:
Enum ofp_action_type {
OFPAT_OUTPUT =0 /* 輸出到交換機端口 */
OFPAT_COPY_TTL_OUT=11 /* 申請復制 TTL outwards 去打包卷雕,從相鄰外層到最外層 */
OFPAT_COPY_TTL_IN=12/* 申請復制 TTL inwards 打包节猿,從最外層到相鄰外層 */
OFPAT_SET_MPLS_TTL= 15, /* MPLSTTL*/
OFPAT_DEC_MPLS_TTL= 16,/* 減少 MPLSTTL*/
OFPAT_PUSH_VLAN= 17, /* 壓入一個新的 VLAN標簽
OFPAT_POP_VLAN= 18, /* 彈出最外面的 VLAN 標簽*/
OFPAT_PUSH_MPLS= 19, /* 壓入一個新的 MPLS標簽*/
OFPAT_POP_MPLS= 20, /* 彈出最外面的 MPLS標簽 */
OFPAT_SET_QUEUE= 21, /* 設(shè)置輸出端口一個隊列的 ID*/
OFPAT_GROUP= 22, /* 申請組 */
OFPAT_SET_NW_TTL= 23, /* IP TTL. */
OFPAT_DEC_NW_TTL= 24, /* 減少 IP TTL. */
OFPAT_SET_FIELD= 25, /* 用 OXMTLV 格式設(shè)置一個頭部字段 */
OFPAT_PUSH_PBB= 26, /* 壓入一個新的 PBB 服務(wù)標簽 (I-TAG) */
OFPAT_POP_PBB= 27, /* 彈出外面的 PBB 服務(wù)標簽 (I-TAG) */
OFPAT_EXPERIMENTER= 0xffff
};
輸出漫雕、組沐批、建立隊列的行動在 5.12 節(jié)進行了描述,壓入 / 彈出的行動在表格 6 進行了介
紹蝎亚,表 12 用 OXM類型對 Set-Field 的行動進行了描述九孩,一個行動的定義包含了操作的類型、
長度和任何關(guān)聯(lián)的數(shù)據(jù)发框。
/* 行動的頭部是所有行動共有的躺彬,長度包括它的頭部和填充,使行動達到 64-bit梅惯。
NB:操作的長度 必須 是 8 的倍數(shù)宪拥, /
struct ofp_action_header {
uint16_t type; / OFPAT_ 之中的一個 /
uint16_t len; / 行動的長度, 包括它的頭部和填充约啊,使行動達到 64-bit */
uint8_t pad[4];
};
OFP_ASSERT(sizeof(struct ofp_action_header) == 8);
一個輸出行動是使用下面的結(jié)構(gòu)和字段:
/*OFPAT_OUTPUT是發(fā)送數(shù)據(jù)包到端口的行動結(jié)構(gòu)特碳。
當‘port ’是 OFPP_CONTROLLER時扣猫, 'max_len' 表示發(fā)送的最大字節(jié)數(shù)晋南。一個 0 的
'max_len' 表示沒有字節(jié)需要被發(fā)送碾盟。 一個 OFPCML_NO_BUFFER的 'max_len' 表示數(shù)據(jù)包沒有
緩沖并且整個數(shù)據(jù)包將會被發(fā)送到控制器括享。
struct ofp_action_output {
uint16_t type; /* OFPAT_OUTPUT.*/
uint16_t len; /* 長度是 16. */
uint32_t port; /* 輸出端口. */
uint16_t max_len; /* 發(fā)送給控制器的最大長度. */
uint8_t pad[6]; /* 填充到 64 bits. */
};
OFP_ASSERT(sizeof(struct ofp_action_output) == 16);
端口指的是數(shù)據(jù)包將發(fā)送的端口愉粤。 max_len 表示從 OFPP_CONTROLLER端口發(fā)送出去的數(shù)據(jù)包中數(shù)據(jù)的最大值杀迹。如果 max_len 是 0劣针,這個交換機必須發(fā)送 0 字節(jié)校镐。 OFPCML_NO_BUFFER中的 max_len 表示整個數(shù)據(jù)包將發(fā)送,并且它不能緩沖捺典。
enum ofp_controller_max_len {
OFPCML_MAX= 0xffe5, /* 用來請求一個指定長度的 max_len 最大值 */
OFPCML_NO_BUFFER= 0xffff /* 表明沒有緩沖鸟廓,整個數(shù)據(jù)包將會發(fā)送到控制器 */
};
Group 行動使用下面的結(jié)構(gòu)和字段:
/* Action structure for OFPAT_GROUP.*/
struct ofp_action_group {
uint16_t type; /* OFPAT_GROUP.*/
uint16_t len; /* 長度是 8. */
uint32_t group_id; /* 數(shù)組標識符 */
};
OFP_ASSERT(sizeof(struct ofp_action_group) == 8);
group_id 標識處理數(shù)據(jù)包的組,存儲段集的使用依賴于組的類型。
Set-Queue 的行動設(shè)置隊列 id引谜,用來映射一個流表項到已配置的端口隊列牍陌,不考慮 ToS和 VLANPCP,這個數(shù)據(jù)包不會由于 Set-Queue 行動而發(fā)生改變员咽。如果交換機內(nèi)部處理需要設(shè)置 ToS/PCP比特, 那么在發(fā)送數(shù)據(jù)包之前應該恢復其原來的值呐赡。
一個交換機可能只支持一個特定的 PCP/ToS隊列。在那種情況下骏融, 我們不能隨意映射一個流表到那個特定的隊列链嘀,因此 Set-Queue 行動不被支持。用戶仍然可以使用這些隊列档玻, 并通過設(shè)置有關(guān)字段 (ToS, VLAN PCP)等來映射流表項到隊列怀泊。
Set-Queue 行動使用下面的結(jié)構(gòu)和字段:
/* OFPAT_SET_QUEUEaction struct: 發(fā)送數(shù)據(jù)包到端口的給定隊列。 */
struct ofp_action_set_queue {
uint16_t type; /* OFPAT_SET_QUEUE.*/
uint16_t len; /* Len is 8. */
uint32_t queue_id; /* 數(shù)據(jù)包的隊列 id. */
};
OFP_ASSERT(sizeof(struct ofp_action_set_queue) == 8);
Set MPLSTTL 行動使用下面的結(jié)構(gòu)和字段:
/* OFPAT_SET_MPLS_TTL的行動結(jié)構(gòu)误趴。 */
struct ofp_action_mpls_ttl {
uint16_t type; /* OFPAT_SET_MPLS_TTL.*/
uint16_t len; /* 長度是 8. */
uint8_t mpls_ttl; /* MPLSTTL */
uint8_t pad[3];
};
OFP_ASSERT(sizeof(struct ofp_action_mpls_ttl) == 8);
mpls_ttl 字段由 MPLSTTL來設(shè)置霹琼。
Decrement MPLSTTL 行動無需協(xié)商而且只包含一個 ofp_action_header,行動使 MPLSTTL值減少凉当。
Set_IPv4 TTL 行動使用下列結(jié)構(gòu)和字段:
/* Action structure for OFPAT_SET_NW_TTL.*/
struct ofp_action_nw_ttl {
uint16_t type; /* OFPAT_SET_NW_TTL.*/
uint16_t len; /* Length is 8. */
uint8_t nw_ttl; /* IP TTL */
uint8_t pad[3];
};
OFP_ASSERT(sizeof(struct ofp_action_nw_ttl) == 8);
nw_ttl 字段是 IP 頭部的 TTL地址枣申。
Decrement IPv4 TTL 行動無需協(xié)商而且只包含一個 ofp_action_header,行動使 IP 頭部的 TTL 值減少看杭。
Copy TTL outwards 行動無需協(xié)商而且只包含一個 ofp_action_header忠藤,行動從緊鄰最外層的頭部復制 TTL 值到最外層頭部的 TTL。
Copy TTL inwards 行動無需協(xié)商而且只包含一個 ofp_action_header楼雹,行動從最外層的頭部復制 TTL值到緊鄰最外層頭部的 TTL模孩。
Push VLAN header 行動, Push MPLSheader 和 Push PBB header 行動使用下列結(jié)構(gòu)和字段:
/* Action structure for OFPAT_PUSH_VLAN/MPLS/PBB.*/
struct ofp_action_push {
uint16_t type; /* OFPAT_PUSH_VLAN/MPLS/PBB. */
uint16_t len; /* Length is 8. */
uint16_t ethertype; /* Ethertype */
uint8_t pad[2];
};
OFP_ASSERT(sizeof(struct ofp_action_push) == 8);
ethertype 表示 Ethertype 的新標簽贮缅。當壓入一個新的 VLAN標簽榨咐、新的 MPLS頭部或者PBB業(yè)務(wù)頭部時會使用.
Push PBBheader 行動邏輯上會壓入一個新的 PBB 業(yè)務(wù)實例頭部到數(shù)據(jù)包 (I-TAG TCI),并復制原始的數(shù)據(jù)包 ethertype 地址到標簽的客戶地址 (C-DA and C-SA)谴供。 I-TAG 的客戶地址就封裝在原始的 Ethertype 地址的位置上,因此這個操作可看作把骨干 MAC-in-MAC 頭部和 I-SID 字段加到數(shù)據(jù)包前面桂肌。這個 Push PBB header 行動不會把骨干 VANL頭部( B-TAG)加給數(shù)據(jù)包, 它可在壓入 PBB頭部操作之后再通過 Push VlAN header 的操作添加。這個操作之后饺蚊,常規(guī)的 set-field 行動可用來修改外部 Ethertype 地址( B-DA 和 B-SA)污呼。
Pop VLAN header 行動不需要參數(shù)裕坊,僅由通用 ofp_action_header 組成,這個行動會彈出數(shù)據(jù)包最外面的 VLAN標簽燕酷。
Pop PBBheader 行動不需要參數(shù)籍凝,僅由通用 ofp_action_header 組成。這個行動邏輯上會彈出數(shù)據(jù)包最外面的 PBB業(yè)務(wù)實例頭部苗缩,并且會復制數(shù)據(jù)包 Ethernet 地址里的客戶地址饵蒂。
這個操作表示從數(shù)據(jù)包前面移走骨干 MAC-in-MAC 頭部和 I-SID 字段。 Pop PBBheader 行動不會移走數(shù)據(jù)包的骨干 VLAN頭部(B-TAG), 它應在此操作之前通過 PopVLANheader 行動移走酱讶。
Pop MPLSheader 的行動使用以下結(jié)構(gòu)和字段:
/* 行動結(jié)構(gòu) for OFPAT_POP_MPLS.*/
struct ofp_action_pop_mpls {
uint16_t type; /* OFPAT_POP_MPLS.*/
uint16_t len; /* 長度是 8. */
uint16_t ethertype; /* ethertype*/
uint8_t pad[2];
};
OFP_ASSERT(sizeof(struct ofp_action_pop_mpls) == 8);
ethertype 表示 MPLS負荷的 Ethertype退盯。不管“bottom of stack (BoS)" 比特是否在 MPLS墊片上進行了設(shè)置, ethertype 用來作為即將形成的數(shù)據(jù)包的 Ethertype泻肯。 推薦流表項使用這個行動來匹配 MPLS標簽和 MPLSBoS字段來避免給 MPLS負荷錯誤的 ethertype渊迁。
當 BoS不等于 1 時,MPLS 規(guī)范不允許對 MPLS負荷設(shè)置任意的 ethertype灶挟×鹦啵控制器負責遵守這個要求,并且只能設(shè)置 0x8847 或 0x8848 作為那些 MPLS負荷的 ethertype稚铣。交換機可以 隨意的 執(zhí)行 MPLS需求: 此情況下漓骚,交換機應該拒絕任何與通配 BoS相匹配的流表項, 和在 Pop MPLSheader 行動中,利用錯誤的 ethertype 匹配 BoS為 0 的流表項榛泛。這兩種情況都應該返回一個 ofp_error_msg蝌蹂, 帶有 OFPET_BAD_ACTION類型和OFPBAC_MATCH_INCONSISTENT
代碼.
Set Field 行動使用以下結(jié)構(gòu)和行動:
/* Action structure for OFPAT_SET_FIELD.*/
struct ofp_action_set_field {
uint16_t type; /* OFPAT_SET_FIELD.*/
uint16_t len; /* 長度會被填補到 64 字節(jié). */
/* 接著:
* - 精確的 oxm_len bytes 包括一個單一 OXMTLV, then
* - Exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4) (between 0 and 7)
* bytes of all-zero bytes
*/
uint8_t field[4]; /* OXMTLV - Make compiler happy */
};
OFP_ASSERT(sizeof(struct ofp_action_set_field) == 8);
Field 包含使用單一 OXMTLV 結(jié)構(gòu)的頭部字段。 Set-Field 行動由 oxm_type曹锨、 OXM TLV類型孤个、修改相應的數(shù)據(jù)包頭部字段的值 oxm_value 以及 OXM的負荷定義的。 oxm_hasmask值必須是零而且不包括 oxm_mask沛简。流表項匹配必須包含設(shè)置的 OXM有關(guān)字段 ( 見 A.2.3.6),否則將會生成一個錯誤(見 6.4 )齐鲤。
set-field 行動的類型可以是任何有效的 OXM頭類型,A.2.3.7 節(jié)和表 12 描述了可能的OXM 類 型。 因 為 不 是 頭 部 字 段椒楣, 不 支 持 Set_Field 行 動 的 OXM 類 型OFPXMT_OFB_IN_PORT,OXM_OF_IN_PHY_PORT 和 OFPXMT_OFB_METADATA给郊。Set-Field 行動覆蓋指定的 OXM類型頭部字段, 并執(zhí)行所需頭部 CRC計算。 OXM字段是指頭部最外層, 除非字段類型明確指定其它字段, 因此一般 set-field 行動適用于 outermost-possible 頭( 例如“ Set VLAN ID“set-field 行動總是設(shè)置最外層 VLAN標簽的 ID)捧灰。
一個實驗者行動使用以下結(jié)構(gòu)和字段:
/* Action header for OFPAT_EXPERIMENTER.
* The rest of the body is experimenter-defined. */
struct ofp_action_experimenter_header {
uint16_t type; /* OFPAT_EXPERIMENTER. */
uint16_t len; /* 長度是 8 的倍數(shù). */
uint32_t experimenter; /* 實驗者 ID 與 ofp_experimenter_header 的結(jié)構(gòu)相同 */
};
OFP_ASSERT(sizeof(struct ofp_action_experimenter_header) == 8);
Experimneter 字段表示實驗者 ID淆九,需要使用與 ofp_experimenter 相同的形式。
A.3 Controller-to-Switch Messages
A.3.1 握手
控制器使用 OFPT_FEATURES_REQUEST 消息識別交換機和讀取它的基本功能。在會話建立( 見 6.3.1) 基礎(chǔ)上炭庙,控制器應該發(fā)送一個 OFPT_FEATURES_REQUEST 消息饲窿。這個消息只包含OpenFlow 頭部。交換機必須發(fā)送一個 OFPT_FEATURES_REPLY響應消息:
/* 交換機功能 */
struct ofp_switch_features {
struct ofp_header header;
uint64_t datapath_id; /* 數(shù)據(jù)通路唯一的 ID焕蹄。低 48-bits 是 MAC地址, 高 16 位是開發(fā)者定義逾雄。 */
uint32_t n_buffers; /* 一次緩沖最大的數(shù)據(jù)包數(shù)。 */
uint8_t n_tables; /* 數(shù)據(jù)通路支持的表數(shù)量腻脏。 */
uint8_t auxiliary_id; /* 標識輔助連接/
uint8_t pad[2]; /* 64 位對齊. */
/* 功能 */
uint32_t capabilities; /* 位圖的支持 "ofp_capabilities". */
uint32_t reserved;
};
OFP_ASSERT(sizeof(struct ofp_switch_features) == 32);
datapath_id 唯一標識數(shù)據(jù)通路鸦泳。 低 48 位用于交換機 MAC地址, 高 16 位表示由開發(fā)者使用。一個例子就是使用高 16 位作為 VLAN ID 在一個物理交換機里區(qū)分多個虛擬交換機實例永品。
這些字段應該被控制器視為一個不透明的位字符串做鹰。
n_buffers 字段表示交換機使用 packet-in 消息向控制器發(fā)送數(shù)據(jù)包時指定的最大緩沖數(shù)據(jù)包數(shù)量。
n_tables 字段描述交換機的表支持的數(shù)量, 每一種表都可以對支持的匹配字段, 行動和表項數(shù)量有不同的設(shè)置腐碱。 當控制器和交換機第一次通信, 控制器從特性回復中會發(fā)現(xiàn)有多少表交 換 機 支 持誊垢。 如 果 它 希 望 知 道 查 詢 的 表 大 小 、 類 型 和 順 序, 控 制 器 發(fā) 送 一 個OFPMP_TABLE_FEATURES 復合請求 (見7.3.5.5)症见。一個交換機必須按照數(shù)據(jù)包經(jīng)過表的次序返回表喂走。
auxiliary_id 字段表示交換機到控制器連接的類型, 主連接這個字段的設(shè)置為零, 輔助連接這個字段設(shè)置為非零值(見 6.3.5 )。
Capabilities 字段使用以下的組合標記:
/* Capabilities supported by the datapath. */
enum ofp_capabilities {
OFPC_FLOW_STATS= 1 << 0, /* 流量統(tǒng)計. */
OFPC_TABLE_STATS= 1 << 1, /* 表統(tǒng)計. */
OFPC_PORT_STATS= 1 << 2, /* 端口統(tǒng)計. */
OFPC_GROUP_STATS= 1 << 3, /* 組統(tǒng)計. */
OFPC_IP_REASM= 1 << 5, /* 可以重新組裝 IP 碎片. */
OFPC_QUEUE_STATS= 1 << 6, /* 隊列統(tǒng)計. */
OFPC_PORT_BLOCKED= 1 << 8 /* 交換機將阻塞循環(huán)端口. */
};
OFPC_PORT_BLOCKED位表示交換機協(xié)議谋作,這在 OpenFlow 以外, 如 802.1 D生成樹, 將檢測拓撲環(huán)路并阻塞端口防止數(shù)據(jù)包循環(huán)芋肠。如果沒有設(shè)置, 在大多數(shù)情況下, 控制器應該實現(xiàn)一個機制來防止數(shù)據(jù)包循環(huán)。
A.3.2 交換機配置
控制器分別使用 OFPT_SET_CONFIG和 OFPT_GET_CONFIG_REQUEST 消息可以設(shè)置和查詢交換機配置參數(shù)遵蚜。 交換機對配置的要求做出回應 OFPT_GET_CONFIG_REPLY消息; 它沒有對設(shè)置配置請求進行回復帖池。
OFPT_GET_CONFIG_REQUEST只有OpenFlow頭部。OFPT_SET_CONFIG和OFPT_GET_CONFIG_REPLY使用以下結(jié)構(gòu):
/* Switch configuration. */
struct ofp_switch_config {
struct ofp_header header;
uint16_t flags; /* OFPC_* flags 位圖. */
uint16_t miss_send_len; /* 數(shù)據(jù)通路應該發(fā)送給控制器的數(shù)據(jù)包最大字節(jié)數(shù)吭净。見ofp_controller_max_len 有效值 */
};
OFP_ASSERT(sizeof(struct ofp_switch_config) == 12);
配置標志包括以下:
enum ofp_config_flags {
/* Handling of IP fragments. */
OFPC_FRAG_NORMAL = 0, /* 分組沒有特殊處理. */
OFPC_FRAG_DROP= 1 << 0, /* 丟棄分組. */
OFPC_FRAG_REASM= 1 << 1, /* 重新組裝 ( 只有 OFPC_IP_REASM設(shè)置). */
OFPC_FRAG_MASK= 3,
};
OFPC_FRAG_標志表示 IP 分組是否應該正常處理睡汹、丟棄, 或重組。 “normal”處理分組意味著讓分組穿過 OpenFlow 表寂殉。如果任何字段 不存在 ( 如 TCP / UDP端口不合適 ), 這個數(shù)據(jù)包應不匹配任何表項里已設(shè)置的字段囚巴。
當不使用輸出行動對 OFPP_CONTROLLER邏輯端口時, miss_send_len 字段定義了 OpenFlow流水線發(fā)送到控制器的數(shù)據(jù)包字節(jié)數(shù), 例如友扰, 如果此消息被使能彤叉, 則發(fā)送攜帶無效 TTL 的數(shù)據(jù)包。如果這個字段等于 0, 交換機必須發(fā)送 ofp_packet_in 消息中零字節(jié)長的數(shù)據(jù)包村怪。如果該值設(shè)置為 OFPCML_NO_BUFFER秽浇,消息中必須包含完整的包, 而不會被緩沖。
A.3.3 Flow Table Configuration
流表編號從 0 和任意可取值直到 OFPTT_MAX甚负。OFPTT_ALL是一個保留值柬焕。
/ 表編號审残。表可以使用任何數(shù)值直至 OFPT_MAX./
enum ofp_table {
/ 最后一個可用的表數(shù). /
OFPTT_MAX= 0xfe,
/ 假表. /
OFPTT_ALL= 0xff / 通配符表用于表配置、流統(tǒng)計和刪除. /
};
控制器可以分別使用 OFP_TABLE_MOD和 OFPMP_TABLE請求對交換機配置和查詢表狀態(tài)击喂。
交換機使用 OFPT_MULTIPART_REPLY消息響應表的復合請求维苔。 OFP_TABLE_MOD使用以下結(jié)構(gòu)和
字段:
/ 流表的配置 / 修改行為 /
struct ofp_table_mod {
struct ofp_header header;
uint8_t table_id; / 表的 ID,OFPTT_ALL 表示所有表 /
uint8_t pad[3]; / 填補到 32 字節(jié) /
uint32_t config; / 位圖的 OFPTC_* flags /
};
OFP_ASSERT(sizeof(struct ofp_table_mod) == 16);
table_id 表示配置更改時應選擇的表碰辅。如果 table_id 是 OFPTT_ALL,則配置應用于交換
機中的所有表懂昂。
Config 字段是一個位圖, 早期版本的規(guī)范提供向后兼容性, 保留以供將來使用。 目前該定義的字段沒有標記没宾。該字段的值定義如下:
/ 配置表的標記凌彬,保留供將來使用. /
enum ofp_table_config {
OFPTC_DEPRECATED_MASK = 3, / 廢棄的比特 /
};
A.3.4 Modify State Messages
A.3.4.1 Modify Flow Entry Message
利用 OFPT_FLOW_MOD消息控制器完成一個流表修改:
/ 流建立和拆除 (controller -> datapath). /
struct ofp_flow_mod {
struct ofp_header header;
uint64_t cookie; / 不透明 controller-issued 標識符. /
uint64_t cookie_mask; / 限制 cookie 位的掩碼,當使用 OFPFC_MODIFY或 OFPFC_DELETE命令時必須匹配 cookie循衰。值為 0 表示沒有限制 /
/ 流行動 /
uint8_t table_id; / 放入流的表 ID铲敛。對 OFPFC_DELETE_* 命令,OFPTT_ALL 也可以用來刪除所有表里匹配的流。 /
uint8_t command; / OFPFC_之一. /
uint16_t idle_timeout; / 丟棄之前的空閑時間 (seconds). /
uint16_t hard_timeout; / 丟棄之前的最大時間 (seconds). /
uint16_t priority; / 流表項優(yōu)先級. /
uint32_t buffer_id; / 緩沖的包使用会钝》ソ或 OFP_NO_BUFFER。對 OFPFC_DELETE則無意義 /
uint32_t out_port; / 對于 OFPFC_DELETE命令,要求匹配的表項包含這個作為輸出端口迁酸。OFPP_ANY表示沒有限制 /
uint32_t out_group; / 對于 OFPFC_DELETE命令, 要求匹配的 表項 包括這個作為輸出組先鱼。值 OFPG_ANY表示沒有限制。/
uint16_t flags; / OFPFF_的標記位圖. /
uint8_t pad[2];
struct ofp_match match; / 字段相匹配奸鬓,變量的大小. /
/ 變量的大小和填充匹配總是被指令跟著 /
//struct ofp_instruction instructions[0]; / . /
};
OFP_ASSERT(sizeof(struct ofp_flow_mod) == 56);
cookie 字段是控制器選擇的一個不透明的數(shù)據(jù)值焙畔。這個值出現(xiàn)在流刪除消息和流統(tǒng)計,也可以用于過濾流統(tǒng)計, 流修改和刪除 ( 見 6.4)。數(shù)據(jù)包處理流水線不使用它, 因此不需要駐留在硬件里串远。 值-1(0xffffffffffffffff) 保留, 不得使用宏多。 當一個表項通過 OFPFC_ADD消息插入 流 表 中, 其 cookie 字 段 設(shè) 置 為 提 供 的 值。 當 一 個 流 表 項 修 改 (OFPFC_MODIFY或OFPFC_MODIFY_STRICT消息), 其 cookie 字段不變澡罚。
如果 cookie_mask 字段不為零, 當修改或刪除流表項時伸但,和 cookie 字段一起限制流匹配。OFPFC_ADD消息忽略這個字段留搔。 cookie_mask 字段的行動在 6.4 節(jié)說明更胖。
table_id 字段表示哪個表中的流表項應插入、修改或刪除催式。 Table 0 表示流水線上第一個表函喉。 OFPTT_ALL只對刪除請求有效。
Command字段必須是下列之一:
enum ofp_flow_mod_command {
OFPFC_ADD= 0, / 新流表. /
OFPFC_MODIFY= 1, / 修改所有匹配的流表. /
OFPFC_MODIFY_STRICT= 2, / 修改嚴格匹配通配符和優(yōu)先級的表項. /
OFPFC_DELETE= 3, / 刪除所有匹配的流動表 /
OFPFC_DELETE_STRICT= 4, / 刪除嚴格匹配通配符和優(yōu)先級的表項. /
}
OFPFC_MODIFY和 OFPFC_MODIFY_STRICT之間的區(qū)別在 6.4 節(jié)和解釋荣月,OFPFC_DELETE和
OFPFC_DELETE_STRICT之間的區(qū)別在 6.4 節(jié)進行闡述管呵。
Idle_timeout 和 hard_timeout 字段控制流表項過期的速度 ( 見 5.5)。當一個流表項插入表 中, 其 idle_timeout 和 hard_timeout 字 段 設(shè) 置 為 消 息 中 的 值哺窄。 當 一 個 流 表 項 修 改(OFPFC_MODIFY或 OFPFC_MODIFY_STRICT消息),idle_timeout 和 hard_timeout 字段被忽略捐下。
如果設(shè)置了 idle_timeout 而 hard_timeout 為零, 表項在 idle_timeout 秒后沒有收到信息后必須過期账锹。如果 idle_timeout 為零而設(shè)置了 hard_timeout,無論是否有數(shù)據(jù)包正碰撞表項坷襟,表項到 hard_timeout 秒必須過期奸柬。如果 idle_timeout 和 hard_timeout 都設(shè)置了,流表項將在沒有信息后 idle_timeout 秒婴程,或 hard_timeout 秒后超時, 以先到期者為準廓奕。如果idle_timeout 和 hard_timeout 都是零, 表項認為是永久的, 不會超時。 它可以被 OFPFC_DELETE類型的 flow_mod 消息移除档叔。
Priority 表示指定的流表中表的優(yōu)先級桌粉。較高的數(shù)據(jù)表示較高的優(yōu)先級。這一字段僅用于 OFPFC_ADD消息匹配和添加流表項時, 和當 OFPFC_MODIFY_STRICT或 OFPFC_DELETE_STRICT消息匹配流條目時衙四。
buffer_id 指向交換機緩沖的數(shù)據(jù)包并用 packet-in 消息發(fā)送給控制器铃肯。如果沒有緩沖數(shù)據(jù)包與 flow mod關(guān)聯(lián), 則必須設(shè)置為 OFP_NO_BUFFER。在流插入后传蹈, 包括一個有效 buffer_id的 flow mod移走緩沖區(qū)里對應數(shù)據(jù)包押逼,并從第一個流表開始,穿過整個 OpenFlow 流水線進行處理惦界。這實際上相當于發(fā)送了 flow mod的一個雙消息和 packet-out 轉(zhuǎn)發(fā)到 OFPP_TABLE邏輯端口 ( 見 A.3.7), 同時要求交換機必須在數(shù)據(jù)包輸出前完全處理 flow mod挑格。無論 flow mod指 向 哪 個 表, 或 是 flow mod 中 包 含 的 指 令 都 適 用 這 些 語 法。 OFPFC_DELETE和
OFPFC_DELETE_STRICT消息忽略這一字段表锻。
輸 出 端 口 和 組 利 用 out_port 和 out_group字段選擇性的過濾OFPFC_DELETE和OFPFC_DELETE_STRICT消息恕齐。如果 out_port 或 out_group 包含一個分別大于 OFPP_ANY或OFPG_ANY的值,就在匹配時引入了一個約束瞬逊。這個約束就是對端口或組來說显歧,流表項必須包含一個輸出行動。其它約束如 ofp_match 結(jié)構(gòu)和優(yōu)先仍會使用确镊;這純粹是一個額外的約束士骤。
注意若禁用輸出過濾,out_port 和 out_group 必須分別設(shè)置為 OFPP_ANY和 OFPG_ANY。這些字段由 OFPFC_ADD蕾域、OFPFC_MODIFY或 OFPFC_MODIFY_STRICT消息忽略拷肌。
Flags 字段可能包含的下列標記:
enum ofp_flow_mod_flags {
OFPFF_SEND_FLOW_REM= 1 << 0, / 發(fā)送刪除消息當流過期或被刪除. /
OFPFF_CHECK_OVERLAP= 1 << 1, / 首先要看的是重疊的表項. /
OFPFF_RESET_COUNTS= 1 << 2, / 重置流數(shù)據(jù)包和字節(jié)計數(shù). /
OFPFF_NO_PKT_COUNTS= 1 << 3, / 不要監(jiān)測的數(shù)據(jù)包計數(shù). /
OFPFF_NO_BYT_COUNTS= 1 << 4, / 不要監(jiān)測的字節(jié)計數(shù). /
};
OFPFF_SEND_FLOW_REM標志設(shè)置時, 當流表項過期或刪除時交換機必須發(fā)送一個流刪除消息。
OFPFF_CHECK_OVERLAP標志設(shè)置時, 交換機在向流表中插入前旨巷, 必須檢查沒有相同優(yōu)先級的表項沖突巨缘。如果有的話,flow mod 失敗并返回一個錯誤信息(見 6.4 )。
OFPFF_NO_PKT_COUNTS標 志 被 設(shè) 置 時, 交 換 機 不 需 要 監(jiān) 測 流 的 數(shù) 據(jù) 包 計 數(shù)采呐。
OFPFF_NO_BYT_COUNTS 標記被設(shè)置時, 交換機不需要監(jiān)測流的字節(jié)計數(shù)若锁。 設(shè)置這些標記可能減少一些OpenFlow 交換機的處理負荷, 盡管這些計數(shù)器在流表項刪除消息和流統(tǒng)計時可能不可用斧吐。交換機不需要注意這些標記又固,可跟蹤流計數(shù)并返回它不管相關(guān)標記的設(shè)置仲器。如果一個交換機不跟蹤流計數(shù), 相應的計數(shù)器不可用, 它必須設(shè)置為字段最大值。
當流表項插入到表中, 它的 flags 字段設(shè)置為消息中的值仰冠。當一個流表項匹配和修改(OFPFC_MODIFY或 OFPFC_MODIFY_STRICT消息), 則 flags 字段被忽略乏冀。
Instructions 字段包含了流表項添加或修改表項的指令集。 如果指令集是無效或不支持,交換機必須生成一個錯誤信息(見 6.4 )洋只。
A.3.4.2 修改組表項消息
控制器利用 OFPT_GROUP_MOD 消息對組表進行修改:
/ 組建立和拆除 (controller -> datapath). /
struct ofp_group_mod {
struct ofp_header header;
uint16_t command; / OFPGC_之一. /
uint8_t type; /OFPGT_*之一. /
uint8_t pad; / 填補到 64 位. /
uint32_t group_id; / 組標識 /
struct ofp_bucket buckets[0]; / 存儲段數(shù)組的 長度辆沦,從頭部的長度字段計算 /
};
OFP_ASSERT(sizeof(struct ofp_group_mod) == 16);
語義類型和組字段解釋 6.5 節(jié)。
Command字段必須是下列之一:
/ Group commands /
enum ofp_group_mod_command {
OFPGC_ADD= 0, / 新建群組. /
OFPGC_MODIFY= 1, / 修改所有匹配的組. /
OFPGC_DELETE= 2, / 刪除所有匹配的組木张。 /
};
Type 字段必須是下列之一:
/ 組類型众辨。值 [128端三,255] 保留給實驗者使用. /
enum ofp_group_type {
OFPGT_ALL= 0, / 所有的 ( 多播/ 廣播) 組. /
OFPGT_SELECT= 1, / 所選定組. /
OFPGT_INDIRECT= 2, / 間接組 /
OFPGT_FF= 3, / 快速故障轉(zhuǎn)移組. /
};
group_id 字段唯一地標識在交換機中的組舷礼。指定的組標識符定義如下:
/ 組編號。組可以使用任何不超過 OFPG_MAX的編號郊闯。 /
enum ofp_group {
/ 最后一個可用的組號. /
OFPG_MAX= 0xffffff00,
/ 假的組. /
OFPG_ALL= 0xfffffffc, / 表示所有組的組刪除命令. /
OFPG_ANY= 0xffffffff / 通配符組僅用于流統(tǒng)計請求妻献。選擇所有流 ( 包括沒有組的流)
/
};
Buckets 字段是一個存儲段的數(shù)組。對間接組团赁,數(shù)組必須包含一個存儲段 ( 見 5.6.1), 其它組類型在數(shù)組里可能有多個存儲段育拨。對快速故障轉(zhuǎn)移組, 存儲段次序就定義了其優(yōu)先級 ( 見5.6.1), 通 過 修 改 組 可 以 改 變 存 儲 段 的 排 序 ( 例 如 使 用 帶 OFPGC_MODIFY命 令 的OFPT_GROUP_MOD 消息)。
數(shù)組中的 存儲段 使用以下結(jié)構(gòu):
/ 用于組的存儲段 /
struct ofp_bucket {
uint16_t len; / 存儲段字節(jié)長度, 包括頭部和任何對齊 64 位的填充. /
uint16_t weight; / 存儲段的有關(guān)重量欢摄,為選擇的組定義. /
uint32_t watch_port;/ 狀態(tài)會影響存儲段是否活躍的端口熬丧。只需要快速轉(zhuǎn)移故障的組。 /
uint32_t watch_group; / 狀態(tài)會影響存儲段是否活躍的組怀挠。只需要快速轉(zhuǎn)移故障的組析蝴。 /
uint8_t pad[4];
struct ofp_action_header actions[0]; / 與存儲段關(guān)聯(lián)的 0 或多個行為,行動列表長度依據(jù)存儲段長度計算 */
};
OFP_ASSERT(sizeof(struct ofp_bucket) == 16);
Weight 字段只是為所選組定義的绿淋,它是否支持是可選的闷畸。 被組處理的存儲段共享信息由組中存儲段重量之和平均后的單個存儲段重量來定義。 當一個端口拆除, 信息量分布的改變沒有定義吞滞, 交換機的數(shù)據(jù)包分布精確度應與存儲段重量匹配佑菩,但沒有定義。
watch_port 和 watch_group 字段只有快速故障轉(zhuǎn)移組需要, 也可能選來實現(xiàn)用在其它組類型上裁赠。這些字段表示端口或組殿漠, 其活躍控制這個存儲段是否為轉(zhuǎn)發(fā)的候選者。對快速轉(zhuǎn)移故障組, 定義的第一個存儲段是最高優(yōu)先級,而且只有最高優(yōu)先級活躍存儲段被使用(見5.6.1)佩捞。
actions 字段是與存儲段相關(guān)的行動集绞幌。 當存儲段被數(shù)據(jù)包選中時, 其行動集就應用到數(shù)據(jù)包( 見 5.10)。
A.3.4.3 Port Modification Message
控制器使用 OFPT_PORT_MOD消息修改端口的行為:
/* 物理端口的修改行為 /
struct ofp_port_mod {
struct ofp_header header;
uint32_t port_no;
uint8_t pad[4];
uint8_t hw_addr[OFP_ETH_ALEN]; / 這是不可配置的硬件地址失尖。這是用來對請求進行正常檢查, 因此它必須返回相同 ofp_port 結(jié)構(gòu). /
uint8_t pad2[2]; / 填充到 64 字節(jié). /
uint32_t config; / OFPPC_位圖標記. /
uint32_t mask; / 位圖 OFPPC_標記的改變. /
uint32_t advertise; / 位圖的 OFPPF_*啊奄。所有位為零以防止任何行動發(fā)生. /
uint8_t pad3[4]; / 填充到 64 字節(jié). */
};
OFP_ASSERT(sizeof(struct ofp_port_mod) == 40);
Mask 字段用來在 config 字段中選擇比特去改變渐苏。 Advertise 字段沒有掩碼 ; 所有端口特性一起改變。
A.3.4.4 計量器修改消息
利用 OFPT_METER_MOD消息完成控制器的計量器修改:
/* 計量器配置. OFPT_METER_MOD. /
struct ofp_meter_mod {
struct ofp_header header;
uint16_t command; / OFPMC_之一. /
uint16_t flags; / OFPMF_位圖的標記. /
uint32_t meter_id; / 計量器實例. /
struct ofp_meter_band_header bands[0]; / 帶寬列表長度菇夸,從頭部長度字段計算. /
};
OFP_ASSERT(sizeof(struct ofp_meter_mod) == 16);
meter_id 字段在交換機里唯一地標識計量器琼富。計量器從 meter_id = 1 開始定義,直至交換機可以支持的最大數(shù)庄新。 OpenFlow 協(xié)議還定義了一些額外的不與流表相關(guān)的虛擬計量器:
/ 計量器編號鞠眉。 OFPM_MAX流表計可以使用任何數(shù)直至 OFPM_MAX/
enum ofp_meter {
/ 最后一個可用的計量器. /
OFPM_MAX= 0xffff0000,
/ 虛擬儀表. /
OFPM_SLOWPATH= 0xfffffffd, / 用于慢速數(shù)據(jù)通道的計量器. /
OFPM_CONTROLLER= 0xfffffffe, / 用于控制器連接的計量器。 /
OFPM_ALL= 0xffffffff, / 表示用于統(tǒng)計請求命令的所有計量器 /
};
OpenFlow 現(xiàn)有實現(xiàn)提供支持的虛擬計量器择诈, 在新實現(xiàn)中鼓勵使用常規(guī)流計量器或優(yōu)先級隊列械蹋。
OFPM_CONTROLLER: 虛擬計量器使用 CONTROLLER保留端口或其他處理, 控制所有數(shù)據(jù)包通過 Packet-in mes-sages 發(fā)送到控制器, ( 見 6.1.2)羞芍』└辏可用來限制發(fā)送到控制器的流量。
OFPM_SLOWPATH: 虛擬計量器控制所有數(shù)據(jù)包被緩慢數(shù)據(jù)通路的交換機處理荷科。許多交換機實現(xiàn)有一條快和慢數(shù)據(jù)通路唯咬, 例如硬件交換機可能有一條慢速軟數(shù)據(jù)通路, 或軟交換機可能有一條慢速的用戶空間數(shù)據(jù)通道。
Command字段的命令必須是下列之一:
/ Meter commands /
enum ofp_meter_mod_command {
OFPMC_ADD, / 新的計量器. /
OFPMC_MODIFY, / 修改指定的計量器. /
OFPMC_DELETE, / 刪除指定的計量器. */
};
Flags 字段可能包含以下標記的組合:
/* 計量器配置標記 */
enum ofp_meter_flags {
OFPMF_KBPS= 1 << 0, /* 速率值在 kb / s(kilo-bit 每秒. */
OFPMF_PKTPS= 1 << 1, /* 速率值用包 / 秒記. */
OFPMF_BURST= 1 << 2, /* 突發(fā)的尺寸. */
OFPMF_STATS= 1 << 3, /* 收集統(tǒng)計. */
};
Bands 字段是一個速率帶寬列表畏浆。 它可以包含任意數(shù)量的頻帶, 當可以理解的話胆胰, 每個頻帶類型是可以重復的。一次只能使用一個頻帶, 如果當前數(shù)據(jù)包速度超過多個頻帶速率, 頻帶則用最高的速率配置刻获。
所有的頻帶都使用相同的通用頭部來定義:
/* 所有計量器共同的頭部 */
struct ofp_meter_band_header {
uint16_t type; /* OFPMBT_*.之一 */
uint16_t len; /* 此頻帶的字節(jié)長度. */
uint32_t rate; /* 此頻帶的速率. */
uint32_t burst_size; /* 突發(fā)的的大小 */
};
OFP_ASSERT(sizeof(struct ofp_meter_band_header) == 12);
Rate 字段表示速率值蜀涨,在此頻帶基礎(chǔ)上可以傳送數(shù)據(jù)包 ( 見 5.7.1)。速率值單位是千比特/ 秒, 除非 flags 字段包括 OFPMF_PKTPS, 此時速率是包 / 秒蝎毡。
burst_size 字段只有在 flags 字段包含 OFPMF_BURST時使用厚柳。 對所有長度超過突發(fā)值的數(shù)據(jù)包和突發(fā)字節(jié), 它規(guī)定了計量器的粒度, 計量器的速率將嚴格限制顶掉。 突發(fā)值單位是千比特草娜,除非 flags 字段包括OFPMF_PKTPS, 在這種情況下, 突發(fā)值單位是包。
Type 字段必須是下列之一:
/* 計量器頻帶類型 */
enum ofp_meter_band_type {
OFPMBT_DROP= 1, /* 丟棄包. */
OFPMBT_DSCP_REMARK = 2, /* IP 頭部的 DSCP. */
OFPMBT_EXPERIMENTER= 0xFFFF /* 實驗者計量器頻帶. */
};
OpenFlow 交換機可能不支持所有頻帶類型, 并可能不允許在所有計量器上使用它所支持
的頻帶, 即一些計量器可能是專用的痒筒。
頻帶 OFPMBT_DROP定義了簡單的速率限制器宰闰,超過頻帶速率值的話數(shù)據(jù)包將丟棄,并使
用以下結(jié)構(gòu):
/* OFPMBT_DROPband - drop packets */
struct ofp_meter_band_drop {
uint16_t type; /* OFPMBT_DROP.*/
uint16_t len; /* 這個頻帶的字節(jié)長度. */
uint32_t rate; /* 開始丟棄包的速率 */
uint32_t burst_size; /* 突發(fā)大小 */
uint8_t pad[4];
};
OFP_ASSERT(sizeof(struct ofp_meter_band_drop) == 16);
頻帶 OFPMBT_DSCP_REMARK 定義了一個簡單的 DiffServ 策略簿透,對超過頻帶速率的數(shù)據(jù)包的 IP 頭部 DSCP字段移袍,檢測其丟棄的優(yōu)先級,并使用以下結(jié)構(gòu):
/* OFPMBT_DSCP_REMARK 頻帶- IP 頭部 DSCP*/
struct ofp_meter_band_dscp_remark {
uint16_t type; /* OFPMBT_DSCP_REMARK. */
uint16_t len; /* 頻帶的字節(jié)長度. */
uint32_t rate; /* 開始 檢測 數(shù)據(jù)包的速率. */
uint32_t burst_size; /* 突發(fā)大小 */
uint8_t prec_level; /* 添加的丟棄優(yōu)先級數(shù)老充。 */
uint8_t pad[3];
};
OFP_ASSERT(sizeof(struct ofp_meter_band_dscp_remark) == 16);
prec_level 字段表示如果超過頻帶速率超過某個數(shù)值葡盗, 數(shù)據(jù)包的丟棄優(yōu)先級應該增加。
/* OFPMBT_EXPERIMENTER 頻帶- 行動集中的寫行動 */
struct ofp_meter_band_experimenter {
uint16_t type; /* OFPMBT_*之一. */
uint16_t len; /* 這個頻帶的字節(jié)長度. */
uint32_t rate; /* 這個頻帶的速率 */
uint32_t burst_size; /* 突發(fā)大小. */
uint32_t experimenter; /* 實驗者 ID 與 ofp_experimenter_header 結(jié)構(gòu)相同 */
};
OFP_ASSERT(sizeof(struct ofp_meter_band_experimenter) == 16);