Note: OpenFlow規范中並沒有規定握手之后必須發送Set config消息,這取決於控制器。因此Set config消息一定是在握手后進行,但不一定是在控制器收到Features Reply之后。
1. Hello
控制器與交互及互相發送 Hello 消息。Hello消息中只包含有OpenFlow Header,其中的 type 字段為 OFPT_HELLO,version 字段為發送方所支持的最高版本 OpenFlow 。這時候會出現兩種情況:
- 雙方都支持 OpenFlow ,則選取 Hello 消息中最低版本的協議作為通信協議
- 如果其中有一方不支持 OpenFlow 協議版本,則發送 Error 消息后斷開連接
如果雙方 OpenFlow 版本可以兼容,則 OpenFlow 連接建立成功。
Q1:Hello 消息是使用什么協議傳輸?TCP?UDP?
Q2:所有的網絡協議在升級的時候都必須向前兼容更低版本的協議?why?
2. Features Request
OpenFlow 連接建立之后,就像你剛到手一部新手機,你最想知道的就是手機的配置如何一樣,控制器最需要獲得交換機的特性信息,交換機的特性信息包括交換機的 ID(DPID),交換機緩沖區數量,交換機端口及端口屬性等等。
控制器向交換機發送 Features Request 消息查詢交換機特性,Features Request 消息只包含 OpenFlow Header,其中 type 字段為 OFPT_FEATURES_REQUEST。
3. Features Reply
交換機在收到控制器發出的 Features Request 消息后返回 Features Request 消息,Features 消息包括 OpenFlow Header 和 Features Reply Message。后者結構如下:
struct ofp_switch_features{
struct ofp_header header;
uint64_t datapath_id; /*唯一標識 id 號*/
uint32_t n_buffers; /*交緩沖區可以緩存的最大數據包個數*/
uint8_t n_tables; /*流表數量*/
uint8_t pad[3]; /*align to 64 bits*/
uint32_t capabilities; /*支持的特殊功能,具體見 ofp_capabilities*/
uint32_t actions; /*支持的動作,具體見 ofp_actions_type*/
struct ofp_phy_port ports[0]; /*物理端口描述列表,具體見 ofp_phy_port*/
};
Q3:uint8_t pad[3] 這一字段的作用是什么?為了保證整個結構體長度是 64bits 的整數倍?
ofp_capabilities 結構如下:
ofp_actions_type 結構如下:
ofp_phy_port 結構如下:
struct ofp_phy_port{
uint16_t port_no; /*物理端口的編號*/
uint8_t hw_addr[OFP_EHT_ALEN]; /*MAC地址*/
char name[OFP_MAX_PORT_NAME_LEN]; /*端口的名稱*/
uint32_t config; /*端口配置,見 ofp_port_config*/
uint32_t state; /*端口狀態,見ofp_port_state*/
uint32_t curr; /*物理屬性*/
uint32_t advertised; /*物理屬性*/
uint32_t supported; /*物理屬性*/
uint32_t peer; /*物理屬性*/
};
ofp_port_config 和 ofp_port_state 結構如下:
4. Set config
知道了交換機的特性之后就要配置交換機了。OpenFlow 交換機只有兩個屬性需要控制器配置:
- 第一個屬性為 flags,用來指示交換機如何才處理 IP 分片數據包。
- 第二個屬性為 miss_send_len,用來指示當一個交換機無法處理的數據包到達時,將數據包發給控制器的最大字節數。
5. Packet-in
有兩種情況會觸發交換機向控制器發送 Packet-in 消息:
- 當交換機收到一個數據包后,查找流表。如果流表中有匹配條目,則交換機按照流表所指示的 action 列表處理數據包。如果沒有,則交換機將數據包封裝在 Packet-in 消息中發送給控制器處理,注意這時候數據包仍然會被放進緩沖區等待處理而不是被丟棄。
- 數據包在流表中有匹配的條目,但是其中所指示的 action 列表中包含轉發給控制器的動作(Output = CONTROLLER),注意這時候數據包不會被放進緩沖區。
Packet-in消息格式如下:
struct ofp_packet_in {
struct ofp_header header;
uint32_t buffer_id; /*Packet-in消息所攜帶的數據包在交換機緩存區中的ID*/
uint16_t total_len; /*data字段的長度*/
uint16_t in_port; /*數據包進入交換機時的端口號*/
uint8_t reason; /*發送Packet-in消息的原因,具體見 ofp_packet_in_reason*/
uint8_t pad;
uint8_t data[0]; /*攜帶的數據包*/
};
ofp_packet_in_reason 結構如下:
enum ofp_packet_in_reason {
OFPR_NO_MACTH /*沒有匹配的條目*/
OFPR_ACTION /*action列表中包含轉發給控制器的動作*/
};
6. Flow-Mod / Packet-out
當控制器收到 Packet-in 消息時有兩種響應的方式:
Flow-Mod
控制器收到 Packet‐in 消息后,可以發送 Flow‐Mod 消息向交換機寫一個流表項。並
且將 Flow‐Mod 消息中的 buffer_id 字段設置為 Packet‐in 消息中的 buffer_id 值。從而
控制器向交換機寫入了一條與數據包相關的流表項,並且指定該數據包按照此流表項的 action 列表處理。
Flow-Mod 消息共有五種類型:
- ADD,用來添加一條新的流表項
- DELETE,用來刪除所有符合一定條件的流表項
- DELETE-STRICT,用來刪除某一條指定的流表項
- MODIFY,用來修改所有符合一定條件的流表項
- MODIFY-STRICT,用來修改某一條指定的流表項
以上五種類型對應的數值分別為0-4
Flow-Mod 消息格式:
struct ofp_flow_mod {
struct ofp_header header;
struct ofp_match match; /*流表的匹配域*/
uint64_t cookie; /*流表項標識符*/
uint16_t command; /*可以是ADD,DELETE,DELETE-STRICT,MODIFY,MODIFY-STRICT*/
uint16_t idle_timeout; /*空閑超時時間*/
uint16_t hard_timeout; /*最大生存時間*/
uint16_t priority; /*優先級,優先級高的流表項優先匹配*/
uint32_t buffer_id; /*緩存區ID ,用於指定緩存區中的一個數據包按這個消息的action列表處理*/
uint16_t out_port; /*如果這條消息是用於刪除流表則需要提供額外的匹配參數*/
uint16_t flags; /*標志位,可以用來指示流表刪除后是否發送flow‐removed消息,添加流表時是否檢查流表重復項,添加的流表項是否為應急流表項。*/
struct ofp_action_header actions[0]; /*action列表*/
};
Packet-Out
並不是所有的數據包都需要向交換機中添加一條流表項來匹配處理,網絡中有些數據包出現的數量很少(如ARP、 IGMP等),沒必要通過流表項來指定這一類數據包的處理方法。此時可以使用 Packet-Out 消息,高速交換機某一個數據包如何處理。
Q3:為什么沒必要通過流表項來指定出現的數量很少的數據包的處理方法?
struct ofp_packet_out {
struct ofp_header header;
uint32_t buffer_id; /*交換機緩存區id,如果為-1則指定的為packet-out消息攜帶的data字段*/
uint16_t in_port; /*如果buffer_id為‐1,並且action列表中指定了Output=TABLE的動作,in_port將作為data段
數據包的額外匹配信息進行流表查詢*/
uint16_t actions_len; /*action列表的長度,可以用來區分actions和data段*/
struct ofp_action_header actions[0]; /*動作列表*/
uint8_t data[0]; /*數據緩存區,可以存儲一個以太網幀,可選*/
}
Flow-Mod 是指定一類數據包的處理方法,而 Packet-Out 則是指定某一個數據包的處理方法。不僅如此,Packet-Out 消息還可以讓交換機產生一個數據包並按照 action 列表處理。
總結
基於 OpenFlow 的 SDN 工作流程,如下圖: