SDN-OpenFlow1.0協議分析

目錄

openflow1.0代碼

openflow交換機

Openflow1.0對數據包匹配特徵的描述方法

wildcards字段

Openflow1.0對數據包處理方法的描述方法

OpenFlow交換機流表

Openflow消息

OpenFlow消息格式

建立Openflow連接

獲取交換機特性(Features)信息

Features Reply Message結構

物理端口描述

 配置交換機Openflow屬性

 交換機接收數據包(Packet-in)

Packet-in消息格式

控制器配置流表(Flow-Mod消息)

 用Flow-Mod消息響應Packet-in消息

交換機轉發數據包(Packet-Out)

Packet-Out消息格式

 Packet-Out消息的應用場景


openflow1.0代碼

文中所有數據結構請查看openflow1.0源代碼

提取碼:g3nq

在include->openflow->openflow.h中

openflow交換機

openflow交換機中的轉發表稱爲流表(Flow Table) 流表包含數據包匹配特徵和數據包處理方法。

數據包匹配特徵:

  1. 一層:交換機入端口(Ingress Port)
  2. 二層:源MAC地址(Ether source)、目的MAC地址(Ether dst)、以太網類型(Ether Type)、VLAN標籤(VLAN id)、VLAN優先級(VLAN priority)
  3. 三層:源IP(IP src)、目的IP(IP dst)、IP協議字段(IP proto)、IP服務類型(IPToS bits)
  4. 四層:TCP/UDP源端口號(TCP/UDP src port)、TCP/UDP目的端口號(TCP/UDP dst port)
匹配字段
Ingress Port Ether Source Ether st Ether type VLAN id VLAN priority IP src IP dst IP proto IP ToS bits TCP/UDP src port TCP/UDP dst port

 

Openflow1.0對數據包匹配特徵的描述方法

/* Fields to match against flows */
struct ofp_match {
    uint32_t wildcards;        /* Wildcard fields. */
    uint16_t in_port;          /* Input switch port. */
    uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */
    uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */
    uint16_t dl_vlan;          /* Input VLAN id. */
    uint8_t dl_vlan_pcp;       /* Input VLAN priority. */
    uint8_t pad1[1];           /* Align to 64-bits */
    uint16_t dl_type;          /* Ethernet frame type. */
    uint8_t nw_tos;            /* IP ToS (actually DSCP field, 6 bits). */
    uint8_t nw_proto;          /* IP protocol or lower 8 bits of
                                * ARP opcode. */
    uint8_t pad2[2];           /* Align to 64-bits */
    uint32_t nw_src;           /* IP source address. */
    uint32_t nw_dst;           /* IP destination address. */
    uint16_t tp_src;           /* TCP/UDP source port. */
    uint16_t tp_dst;           /* TCP/UDP destination port. */
};
/ *與流量匹配的字段* /
struct ofp_match {
    uint32_t wildcards;            / *通配符字段。 * /
    uint16_t in_port;              / *輸入開關端口。 * /
    uint8_t dl_src [OFP_ETH_ALEN]; / *以太網源地址。 * /
    uint8_t dl_dst [OFP_ETH_ALEN]; / *以太網目標地址。 * /
    uint16_t dl_vlan;              / *輸入VLAN ID。 * /
    uint8_t dl_vlan_pcp;           / *輸入VLAN優先級。 * /
    uint8_t pad1 [1];              / *對齊64位* /
    uint16_t dl_type;              / *以太網幀類型。 * /
    uint8_t nw_tos;               / * IP ToS(實際上是DSCP字段,6位)。 * /
    uint8_t nw_proto;             / * IP協議或以下的低8位
                                 * ARP操作碼。 * /
    uint8_t pad2 [2];             / *對齊64位* /
    uint32_t nw_src;             / * IP源地址。 * /
    uint32_t nw_dst;             / * IP目標地址。 * /
    uint16_t tp_src;             / * TCP / UDP源端口。 * /
    uint16_t tp_dst;             / * TCP / UDP目標端口。 * /
};

 相對於前面所說,多了三個字段,分別是wildcards、pad1[1]、pad2[2],作用如翻譯所寫。

wildcards字段

/* Flow wildcards. */
enum ofp_flow_wildcards {
    OFPFW_IN_PORT  = 1 << 0,  /* Switch input port. */
    OFPFW_DL_VLAN  = 1 << 1,  /* VLAN id. */
    OFPFW_DL_SRC   = 1 << 2,  /* Ethernet source address. */
    OFPFW_DL_DST   = 1 << 3,  /* Ethernet destination address. */
    OFPFW_DL_TYPE  = 1 << 4,  /* Ethernet frame type. */
    OFPFW_NW_PROTO = 1 << 5,  /* IP protocol. */
    OFPFW_TP_SRC   = 1 << 6,  /* TCP/UDP source port. */
    OFPFW_TP_DST   = 1 << 7,  /* TCP/UDP destination port. */

    /* IP source address wildcard bit count.  0 is exact match, 1 ignores the
     * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
     * the entire field.  This is the *opposite* of the usual convention where
     * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded. */
    OFPFW_NW_SRC_SHIFT = 8,
    OFPFW_NW_SRC_BITS = 6,
    OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT,
    OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT,

    /* IP destination address wildcard bit count.  Same format as source. */
    OFPFW_NW_DST_SHIFT = 14,
    OFPFW_NW_DST_BITS = 6,
    OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT,
    OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT,

    OFPFW_DL_VLAN_PCP = 1 << 20,  /* VLAN priority. */
    OFPFW_NW_TOS = 1 << 21,  /* IP ToS (DSCP field, 6 bits). */

    /* Wildcard all fields. */
    OFPFW_ALL = ((1 << 22) - 1)
};
/ *流通配符。 * /
enum of_p_flow_wildcards{
    OFPFW_IN_PORT = 1 << 0,/ *開關輸入端口。 * /
    OFPFW_DL_VLAN = 1 << 1,/ * VLAN ID。 * /
    OFPFW_DL_SRC = 1 << 2,/ *以太網源地址。 * /
    OFPFW_DL_DST = 1 << 3,/ *以太網目標地址。 * /
    OFPFW_DL_TYPE = 1 << 4,/ *以太網幀類型。 * /
    OFPFW_NW_PROTO = 1 << 5,/ * IP協議。 * /
    OFPFW_TP_SRC = 1 << 6,/ * TCP / UDP源端口。 * /
    OFPFW_TP_DST = 1 << 7,/ * TCP / UDP目標端口。 * /

    / * IP源地址通配符位數。 0是完全匹配,1則忽略
     * LSB,2忽略2個最低有效位,...,32和更高的通配符
     *整個領域。這與通常的約定相反
     *例如/ 24表示通配符爲8位(不是24位)。 * /
    OFPFW_NW_SRC_SHIFT = 8
    OFPFW_NW_SRC_BITS = 6
    OFPFW_NW_SRC_MASK =(((1 << OFPFW_NW_SRC_BITS)-1)<< OFPFW_NW_SRC_SHIFT,
    OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT,

    / * IP目標地址通配符位數。與源格式相同。 * /
    OFPFW_NW_DST_SHIFT = 14
    OFPFW_NW_DST_BITS = 6
    OFPFW_NW_DST_MASK =(((1 << OFPFW_NW_DST_BITS)-1)<< OFPFW_NW_DST_SHIFT,
    OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT,

    OFPFW_DL_VLAN_PCP = 1 << 20,/ * VLAN優先級。 * /
    OFPFW_NW_TOS = 1 << 21,/ * IP ToS(DSCP字段,6位)。 * /

    / *通配所有字段。 * /
    OFPFW_ALL =((1 << 22)-1)
};

 

wildcards字段
22-31 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
保留 IP服務類型 VLAN優先級 目的IP 源IP 目的端口 源端口 IP協議字段 以太網類型 目的MAC 源MAC VLAN標籤 入端口

除源IP和目的IP以外,掩碼位爲0表示對應匹配項需要精確匹配,掩碼爲爲1表示忽略匹配項。
源IP和目的IP字段的掩碼錶示32bit lP地址可以忽略匹配的長度。
如果源IP的掩碼爲8(wildcard的8-13bit爲001000),表示源IP字段的高24bit需要精確匹配,源IP字段的低8bit可以忽略。

Openflow1.0對數據包處理方法的描述方法

Openflow1.0提供兩種數據包的處理方法:

  1. 轉發(Forward)
  2. 修改包頭(Modify field)
  • SET_VLAN_VID 修改VLAN標籤
  • SET_VLAN_PCP 修改VLAN優先級
  • STRIP_VLAN 彈出VLAN標籤
  • SET_DL_SRC 修改源MAC地址
  • SET_DL_DST 修改目的MAC地址
  • SET_NW_SRC 修改源IP地址
  • SET_NW_DST 修改目的IP地址
  • SET_NW_TOS 修改IP服務類型字段
  • SET_TP_SRC 修改源端口號
  • SET_TP_DST 修改目的端口號

以上每一種操作稱爲一個動作(Action),流表中的數據包處理方法是一個動 作列表(Action List),動作列表由以上各種動作組合合成。

Action的頭

/* Action header that is common to all actions.  The length includes the
 * header and any padding used to make the action 64-bit aligned.
 * NB: The length of an action *must* always be a multiple of eight. */
struct ofp_action_header {
    uint16_t type;                  /* One of OFPAT_*. */
    uint16_t len;                   /* Length of action, including this
                                       header.  This is the length of action,
                                       including any padding to make it
                                       64-bit aligned. */
    uint8_t pad[4];
};
/ *所有動作共有的頭。 長度包括
  *頭和用於使操作64位對齊的任何填充。
  *注意:動作的長度*必須*始終是8的倍數。 * /
struct ofp_action_header {
     uint16_t type; / * OFPAT_ *之一。 * /
     uint16_t len; / *動作時長,包括此
                      頭。 這是行動的時長,
                      包括任何填充物
                      64位對齊。 * /
     uint8_t pad [4];
};

其中,type字段爲以下之一

enum ofp_action_type {
    OFPAT_OUTPUT,           /* Output to switch port. */
    OFPAT_SET_VLAN_VID,     /* Set the 802.1q VLAN id. */
    OFPAT_SET_VLAN_PCP,     /* Set the 802.1q priority. */
    OFPAT_STRIP_VLAN,       /* Strip the 802.1q header. */
    OFPAT_SET_DL_SRC,       /* Ethernet source address. */
    OFPAT_SET_DL_DST,       /* Ethernet destination address. */
    OFPAT_SET_NW_SRC,       /* IP source address. */
    OFPAT_SET_NW_DST,       /* IP destination address. */
    OFPAT_SET_NW_TOS,       /* IP ToS (DSCP field, 6 bits). */
    OFPAT_SET_TP_SRC,       /* TCP/UDP source port. */
    OFPAT_SET_TP_DST,       /* TCP/UDP destination port. */
    OFPAT_ENQUEUE,          /* Output to queue.  */
    OFPAT_VENDOR = 0xffff
};
enum of_p_action_type{
     OFPAT_OUTPUT,      / *輸出到交換機端口。 * /
     OFPAT_SET_VLAN_VID,/ *設置802.1q VLAN ID。 * /
     OFPAT_SET_VLAN_PCP,/ *設置802.1q優先級。 * /
     OFPAT_STRIP_VLAN,  / *剝離802.1q標頭。 * /
     OFPAT_SET_DL_SRC,  / *以太網源地址。 * /
     OFPAT_SET_DL_DST,  / *以太網目標地址。 * /
     OFPAT_SET_NW_SRC,  / * IP源地址。 * /
     OFPAT_SET_NW_DST,  / * IP目標地址。 * /
     OFPAT_SET_NW_TOS,  / * IP ToS(DSCP字段,6位)。 * /
     OFPAT_SET_TP_SRC,  / * TCP / UDP源端口。 * /
     OFPAT_SET_TP_DST,  / * TCP / UDP目標端口。 * /
     OFPAT_ENQUEUE,     / *輸出到隊列。 * /
     OFPAT_VENDOR = 0xffff
};

其中OFPAT_OUTPUT和OFPAT_ENQUEUE爲轉發操作,其他類型爲修改包頭操作

OUTPUT類型

/* Action structure for OFPAT_OUTPUT, which sends packets out 'port'.
 * When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max
 * number of bytes to send.  A 'max_len' of zero means no bytes of the
 * packet should be sent.*/
struct ofp_action_output {
    uint16_t type;                  /* OFPAT_OUTPUT. */
    uint16_t len;                   /* Length is 8. */
    uint16_t port;                  /* Output port. */
    uint16_t max_len;               /* Max length to send to controller. */
};
/ * OFPAT_OUTPUT的操作結構,該結構將數據包從“端口”發送出去。
  *當“端口”爲OFPP_CONTROLLER時,“ max_len”表示最大
  *要發送的字節數。 “ max_len”爲零表示沒有字節
  *數據包應該發送。* /
struct ofp_action_output {
     uint16_t type;     / * OFPAT_OUTPUT。 * /
     uint16_t len;     / *長度爲8。* /
     uint16_t port;     / *輸出端口。 * /
     uint16_t max_len; / *要發送到控制器的最大長度。 * /
};

output類型Action的結構包含一個port參數和一個max_len參數Port參數指定了數據包的輸出端口,輸出端口可以是交換機的一個實際物理端口,也可以是一下虛擬端口

  • ALL:將數據包從除入端口以外其他所有端口發出
  • CONTROLLER:將數據包發送給控制器
  • LOCAL:將數據包發送給交換機本地端口>TABLE:將數據包按照流表匹配條目處理
  • IN_PORT:將數據包從入端口發出
  • NORMAL:按照普通二層交換機流程處理數據包
  • FLOOD:將數據包從最小生成樹使能端口轉發(不包括入端口)當port爲CONTROLLER時,max_len指定了發給CONTROLLER的數據包最大長度。當port爲其他參數時,max_len無意義。

 ENQUEUE類型

/* OFPAT_ENQUEUE action struct: send packets to given queue on port. */
struct ofp_action_enqueue {
    uint16_t type;            /* OFPAT_ENQUEUE. */
    uint16_t len;             /* Len is 16. */
    uint16_t port;            /* Port that queue belongs. Should
                                 refer to a valid physical port
                                 (i.e. < OFPP_MAX) or OFPP_IN_PORT. */
    uint8_t pad[6];           /* Pad for 64-bit alignment. */
    uint32_t queue_id;        /* Where to enqueue the packets. */
};
/ * OFPAT_ENQUEUE操作結構:將數據包發送到端口上的給定隊列。 * /
struct ofp_action_enqueue {
     uint16_t type; / * OFPAT_ENQUEUE。 * /
     uint16_t len; / * Len是16。* /
     uint16_t port; / *隊列所屬的端口。 應該
                       引用有效的物理端口
                     (即<OFPP_MAX)或OFPP_IN_PORT。 * /
     uint8_t pad [6]; / * pad用於64位對齊。 * /
     uint32_t queue_id; / *將數據包放入隊列的位置。 * /
};

VLAN_VID類型——修改VLAN的ID

/* Action structure for OFPAT_SET_VLAN_VID. */
struct ofp_action_vlan_vid {
    uint16_t type;                  /* OFPAT_SET_VLAN_VID. */
    uint16_t len;                   /* Length is 8. */
    uint16_t vlan_vid;              /* VLAN id. */
    uint8_t pad[2];
};
/ * OFPAT_SET_VLAN_VID的操作結構。 * /
struct ofp_action_vlan_vid {
     uint16_t type;      / * OFPAT_SET_VLAN_VID。 * /
     uint16_t len;       / *長度爲8。* /
     uint16_t vlan_vid; / * VLAN ID。 * /
     uint8_t  pad [2];
};

VLAN_PCP類型——修改VLAN優先級

/* Action structure for OFPAT_SET_VLAN_PCP. */
struct ofp_action_vlan_pcp {
    uint16_t type;                  /* OFPAT_SET_VLAN_PCP. */
    uint16_t len;                   /* Length is 8. */
    uint8_t vlan_pcp;               /* VLAN priority. */
    uint8_t pad[3];
};
/ * OFPAT_SET_VLAN_PCP的操作結構。 * /
struct ofp_action_vlan_pcp {
     uint16_t類型;     / * OFPAT_SET_VLAN_PCP。 * /
     uint16_t len;     / *長度爲8。* /
     uint8_t vlan_pcp; / * VLAN優先級。 * /
     uint8_t pad [3];
};

 DL_ADDR類型——修改MAC地址

/* Action structure for OFPAT_SET_DL_SRC/DST. */
struct ofp_action_dl_addr {
    uint16_t type;                  /* OFPAT_SET_DL_SRC/DST. */
    uint16_t len;                   /* Length is 16. */
    uint8_t dl_addr[OFP_ETH_ALEN];  /* Ethernet address. */
    uint8_t pad[6];
};
/ * OFPAT_SET_DL_SRC / DST的操作結構。 * /
struct ofp_action_dl_addr {
     uint16_t type; / * OFPAT_SET_DL_SRC / DST。 * /
     uint16_t len; / *長度爲16。* /
     uint8_t  dl_addr [OFP_ETH_ALEN]; / *以太網地址。 * /
     uint8_t  pad [6];
};

NW_ADDR類型——修改IP地址

/* Action structure for OFPAT_SET_NW_SRC/DST. */
struct ofp_action_nw_addr {
    uint16_t type;                  /* OFPAT_SET_TW_SRC/DST. */
    uint16_t len;                   /* Length is 8. */
    uint32_t nw_addr;               /* IP address. */
};
/ * OFPAT_SET_NW_SRC / DST的操作結構。 * /
struct ofp_action_nw_addr {
     uint16_t類型; / * OFPAT_SET_TW_SRC / DST。 * /
     uint16_t len; / *長度爲8。* /
     uint32_t nw_addr; /* IP地址。 * /
};

NW_TOS類型——修改IP服務類型

/* Action structure for OFPAT_SET_NW_TOS. */
struct ofp_action_nw_tos {
    uint16_t type;                  /* OFPAT_SET_TW_SRC/DST. */
    uint16_t len;                   /* Length is 8. */
    uint8_t nw_tos;                 /* IP ToS (DSCP field, 6 bits). */
    uint8_t pad[3];
};
/ * OFPAT_SET_NW_TOS的操作結構。 * /
struct ofp_action_nw_tos {
     uint16_t類型; / * OFPAT_SET_TW_SRC / DST。 * /
     uint16_t len; / *長度爲8。* /
     uint8_t nw_tos; / * IP ToS(DSCP字段,6位)。 * /
     uint8_t pad [3];
};

TP_PORT類型——修改傳輸層端口號

/* Action structure for OFPAT_SET_TP_SRC/DST. */
struct ofp_action_tp_port {
    uint16_t type;                  /* OFPAT_SET_TP_SRC/DST. */
    uint16_t len;                   /* Length is 8. */
    uint16_t tp_port;               /* TCP/UDP port. */
    uint8_t pad[2];
};
/ * OFPAT_SET_TP_SRC / DST的操作結構。 * /
struct ofp_action_tp_port {
     uint16_t類型; / * OFPAT_SET_TP_SRC / DST。 * /
     uint16_t len; / *長度爲8。* /
     uint16_t tp_port; / * TCP / UDP端口。 * /
     uint8_t pad [2];
};

OpenFlow交換機流表

Openflow消息

Openflow消息總共分爲三大類:
1、Controller-to-Switch(控制器至交換機消息),此類消息由控制器主動發出

  • Features用來獲取交換機特性
  • Configuration 用來配置Openflow交換機
  • Modify-State用來修改交換機狀態(修改流表)
  • Read-Stats用來讀取交換機狀態
  • Send-Packet用來發送數據包
  • Barrier阻塞消息

2、Asynchronous(異步消息),此類消息由交換機主動發出

  • Packet-in 用來告知控制器交換機接收到數據包
  • Flow-Removed用來告知控制器交換機流表被刪除>Port-Status用來告知控制器交換機端口狀態更新
  • Error用來告知控制器交換機發生錯誤

3、Symmetric(對稱消息),此類消息可以由控制器或交換機主動發起

  • Hello用來建立Openflow連接
  • Echo用來確認交換機與控制器之間的連接狀態
  • Vendor廠商自定義消息

OpenFlow消息格式

OpenFlow協議數據包由OpenFlow Header和OpenFlow Message兩部分組成

OpenFlow的頭

/* Header on all OpenFlow packets. */
struct ofp_header {
    uint8_t version;    /* OFP_VERSION. */
    uint8_t type;       /* One of the OFPT_ constants. */
    uint16_t length;    /* Length including this ofp_header. */
    uint32_t xid;       /* Transaction id associated with this packet.
                           Replies use the same id as was in the request
                           to facilitate pairing. */
};
/ *所有OpenFlow數據包的頭。 * /
struct ofp_header {
     uint8_t  version; / * OFP_VERSION。 * /
     uint8_t  type;     / * OFPT_常量之一。 * /
     uint16_t length;  / *長度,包括此ofp_header。 * /
     uint32_t xid;      / *與該數據包關聯的交易ID。
                           回覆使用與請求中相同的ID
                           方便配對。 * /
};

OpenFlow消息

enum ofp_type {
    /* Immutable messages. */
    OFPT_HELLO,               /* Symmetric message */
    OFPT_ERROR,               /* Symmetric message */
    OFPT_ECHO_REQUEST,        /* Symmetric message */
    OFPT_ECHO_REPLY,          /* Symmetric message */
    OFPT_VENDOR,              /* Symmetric message */

    /* Switch configuration messages. */
    OFPT_FEATURES_REQUEST,    /* Controller/switch message */
    OFPT_FEATURES_REPLY,      /* Controller/switch message */
    OFPT_GET_CONFIG_REQUEST,  /* Controller/switch message */
    OFPT_GET_CONFIG_REPLY,    /* Controller/switch message */
    OFPT_SET_CONFIG,          /* Controller/switch message */

    /* Asynchronous messages. */
    OFPT_PACKET_IN,           /* Async message */
    OFPT_FLOW_REMOVED,        /* Async message */
    OFPT_PORT_STATUS,         /* Async message */

    /* Controller command messages. */
    OFPT_PACKET_OUT,          /* Controller/switch message */
    OFPT_FLOW_MOD,            /* Controller/switch message */
    OFPT_PORT_MOD,            /* Controller/switch message */

    /* Statistics messages. */
    OFPT_STATS_REQUEST,       /* Controller/switch message */
    OFPT_STATS_REPLY,         /* Controller/switch message */

    /* Barrier messages. */
    OFPT_BARRIER_REQUEST,     /* Controller/switch message */
    OFPT_BARRIER_REPLY,       /* Controller/switch message */

    /* Queue Configuration messages. */
    OFPT_QUEUE_GET_CONFIG_REQUEST,  /* Controller/switch message */
    OFPT_QUEUE_GET_CONFIG_REPLY     /* Controller/switch message */

};
enum ofp_type{
    / *不可變的消息。 * /
    OFPT_HELLO,       / *對稱消息* /
    OFPT_ERROR,       / *對稱消息* /
    OFPT_ECHO_REQUEST,/ *對稱消息* /
    OFPT_ECHO_REPLY,  / *對稱消息* /
    OFPT_VENDOR,     / *對稱消息* /

    / *交換機配置消息。 * /
    OFPT_FEATURES_REQUEST,  / *控制器/交換機消息* /
    OFPT_FEATURES_REPLY,    / *控制器/交換機消息* /
    OFPT_GET_CONFIG_REQUEST,/ *控制器/交換機消息* /
    OFPT_GET_CONFIG_REPLY,  / *控制器/交換機消息* /
    OFPT_SET_CONFIG,        / *控制器/交換機消息* /

    / *異步消息。 * /
    OFPT_PACKET_IN,   / *異步消息* /
    OFPT_FLOW_REMOVED,/ *異步消息* /
    OFPT_PORT_STATUS, / *異步消息* /

    / *控制器命令消息。 * /
    OFPT_PACKET_OUT,/ *控制器/交換機消息* /
    OFPT_FLOW_MOD,  / *控制器/交換機消息* /
    OFPT_PORT_MOD,  / *控制器/交換機消息* /

    / *統計消息。 * /
    OFPT_STATS_REQUEST,/ *控制器/交換機消息* /
    OFPT_STATS_REPLY,  / *控制器/交換機消息* /

    / *障礙消息。 * /
    OFPT_BARRIER_REQUEST,/ *控制器/交換機消息* /
    OFPT_BARRIER_REPLY,  / *控制器/交換機消息* /

    / *隊列配置消息。 * /
    OFPT_QUEUE_GET_CONFIG_REQUEST,/ *控制器/交換機消息* /
    OFPT_QUEUE_GET_CONFIG_REPLY    / *控制器/交換機消息* /

};

建立Openflow連接


控制器與交換機互相發送Hello消息Hello消息中只包含Openflow Header Openflow Header中的version字段爲發送方所支持的最高版本Openflow協議
雙方選取Hello消息中最低版本的協議作爲通信協議如果有一方不支持Openflow協議版本,應發送Error消息後斷開連接
如果雙方Openflow版本可以兼容,則Openflow連接建立成功。

獲取交換機特性(Features)信息


Openflow連接建立後,控制器最需要獲得交換機的特性信息,交換機的特性信息包括交
換機的ID(DPID),交換機緩衝區數量,交換機端口及端口屬性等等。
控制器向交換機發送Features Request消息查詢交換機特性,Features Request消息只包含Openflow Header。
交換機在收到Features Request消息後返回Features Reply消息,Features Reply消息包括Openflow Header 和Features Reply Message

Features Reply Message結構

/* Switch features. */
struct ofp_switch_features {
    struct ofp_header header;
    uint64_t datapath_id;   /* Datapath unique ID.  The lower 48-bits are for
                               a MAC address, while the upper 16-bits are
                               implementer-defined. */
    uint32_t n_buffers;     /* Max packets buffered at once. */
    uint8_t n_tables;       /* Number of tables supported by datapath. */
    uint8_t pad[3];         /* Align to 64-bits. */

    /* Features. */
    uint32_t capabilities;  /* Bitmap of support "ofp_capabilities". */
    uint32_t actions;       /* Bitmap of supported "ofp_action_type"s. */

    /* Port info.*/
    struct ofp_phy_port ports[0];  /* Port definitions.  The number of ports
                                      is inferred from the length field in
                                      the header. */
};
/ *切換功能。 * /
struct ofp_switch_features {
     struct ofp_header header;
     uint64_t datapath_id; / *數據路徑唯一ID。 低48位用於
                               MAC地址,而高16位是
                               實施者定義的。 * /
     uint32_t n_buffers; / *一次緩衝的最大數據包數。 * /
     uint8_t n_tables;   / *數據路徑支持的表數。 * /
     uint8_t pad[3];    / *對齊64位。 * /

     /* 特徵。 * /
     uint32_t capabilities;      / *支持“ ofp_capabilities”的位圖。 * /
     uint32_t actions;     / *支持的“ ofp_action_type”的位圖。 * /

     / *端口信息* /
     struct ofp_phy_port ports[0]; / *端口定義。 端口數
                                       從中的長度字段推斷
                                       標頭。 * /
};

物理端口描述

/* Description of a physical port */
struct ofp_phy_port {
    uint16_t port_no;
    uint8_t hw_addr[OFP_ETH_ALEN];
    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. */
};
/ *物理端口的說明* /
struct ofp_phy_port {
     uint16_t port_no;
     uint8_t hw_addr [OFP_ETH_ALEN];
     char name[OFP_MAX_PORT_NAME_LEN]; / *空終止* /

     uint32_t config; / * OFPPC_ *標誌的位圖。 * /
     uint32_t state; / * OFPPS_ *標誌的位圖。 * /

     / * OFPPF_ *位圖,用於描述功能。 如果所有位清零
      *不支持或不可用。 * /
     uint32_t curr; / *當前功能。 * /
     uint32_t advertised; / *端口正在通告的功能。 * /
     uint32_t supported; / *端口支持的功能。 * /
     uint32_t peer; / *由對等方通告的功能。 * /
};
/* Flags to indicate behavior of the physical port.  These flags are
 * used in ofp_phy_port to describe the current configuration.  They are
 * used in the ofp_port_mod message to configure the port's behavior.
 */
enum ofp_port_config {
    OFPPC_PORT_DOWN    = 1 << 0,  /* Port is administratively down. */

    OFPPC_NO_STP       = 1 << 1,  /* Disable 802.1D spanning tree on port. */
    OFPPC_NO_RECV      = 1 << 2,  /* Drop all packets except 802.1D spanning
                                     tree packets. */
    OFPPC_NO_RECV_STP  = 1 << 3,  /* Drop received 802.1D STP packets. */
    OFPPC_NO_FLOOD     = 1 << 4,  /* Do not include this port when flooding. */
    OFPPC_NO_FWD       = 1 << 5,  /* Drop packets forwarded to port. */
    OFPPC_NO_PACKET_IN = 1 << 6   /* Do not send packet-in msgs for port. */
};
/ *指示物理端口行爲的標誌。 這些標誌是
  *在ofp_phy_port中用於描述當前配置。 他們是
  *在ofp_port_mod消息中使用,用於配置端口的行爲。
  * /
enum of_p_port_config{
     OFPPC_PORT_DOWN = 1 << 0, / *端口在管理上已關閉。 * /

     OFPPC_NO_STP = 1 << 1,    / *禁用端口上的802.1D生成樹。 * /
     OFPPC_NO_RECV = 1 << 2,    / *丟棄除802.1D跨越之外的所有數據包
                                      樹包。 * /
     OFPPC_NO_RECV_STP = 1 << 3,/ *丟棄收到的802.1D STP數據包。 * /
     OFPPC_NO_FLOOD = 1 << 4,   / *泛洪時不包括此端口。 * /
     OFPPC_NO_FWD = 1 << 5,     / *丟棄轉發到端口的數據包。 * /
     OFPPC_NO_PACKET_IN = 1 << 6 / *不要爲端口發送入站消息。 * /
};

 配置交換機Openflow屬性

/* Switch configuration. */
struct ofp_switch_config {
    struct ofp_header header;
    uint16_t flags;             /* OFPC_* flags. */
    uint16_t miss_send_len;     /* Max bytes of new flow that datapath should
                                   send to the controller. */
};
/ *交換機配置。 * /
struct ofp_switch_config {
     struct ofp_header header;
     uint16_t flags;         / * OFPC_ *標誌。 * /
     uint16_t miss_send_len; / *數據路徑應包含的新流的最大字節數
                                    發送給控制器。 * /
};

Openflow交換機只有兩個屬性需要控制器配置第一個屬性爲flags,用來指示交換機如何處理IP分片數據包;第二個屬性爲miss _send_len,用來指示當一個交換機無法處理的數據包到達時,將數據包發給控制器的最大字節數。 

enum ofp_config_flags {
    /* Handling of IP fragments. */
    OFPC_FRAG_NORMAL   = 0,  /* No special handling for fragments. */
    OFPC_FRAG_DROP     = 1,  /* Drop fragments. */
    OFPC_FRAG_REASM    = 2,  /* Reassemble (only if OFPC_IP_REASM set). */
    OFPC_FRAG_MASK     = 3
};
enum of_p_config_flags{
     / *處理IP片段。 * /
     OFPC_FRAG_NORMAL = 0,/ *對片段沒有特殊處理。 * /
     OFPC_FRAG_DROP = 1,  / *丟棄片段。 * /
     OFPC_FRAG_REASM = 2, / *重新組裝(僅在設置了OFPC_IP_REASM的情況下)。 * /
     OFPC_FRAG_MASK = 3
};

 交換機接收數據包(Packet-in)

Packet-in消息觸發情況1:
當交換機收到一個數據包後,會查找流表,找出與數據包包頭相匹配的條目。
如果流表中有匹配條目,則交換機按照流表所指示的action列表處理數據包。
如果流表中沒有匹配條目,則交換機會將數據包封裝在Packet-in消息中發送給控制器處理。此時數據包會被緩存在交換機中等待處理。

Packet-in消息觸發情況2:

交換機流表所指示的action列表中包含轉發給控制器的動作(Output=CONTROLLER)。
此時數據包不會被緩存在交換機中。

Packet-in消息格式

/* Packet received on port (datapath -> controller). */
struct ofp_packet_in {
    struct ofp_header header;
    uint32_t buffer_id;     /* ID assigned by datapath. */
    uint16_t total_len;     /* Full length of frame. */
    uint16_t in_port;       /* Port on which frame was received. */
    uint8_t reason;         /* Reason packet is being sent (one of OFPR_*) */
    uint8_t pad;
    uint8_t data[0];        /* Ethernet frame, halfway through 32-bit word,
                               so the IP header is 32-bit aligned.  The
                               amount of data is inferred from the length
                               field in the header.  Because of padding,
                               offsetof(struct ofp_packet_in, data) ==
                               sizeof(struct ofp_packet_in) - 2. */
};
/ *在端口(數據路徑->控制器)上接收到的數據包。 * /
struct ofp_packet_in {
     struct ofp_header header;
     uint32_t buffer_id; / *由數據路徑分配的ID。 * /
     uint16_t total_len; / *整個幀的長度。 * /
     uint16_t in_port;   / *接收幀的端口。 * /
     uint8_t  reason;  / *原因包被髮送(OFPR_ *之一)* /
     uint8_t  pad;
     uint8_t  data[0]; / *以太網幀,位於32位字的中間,
                          因此IP標頭是32位對齊的 的
                          從長度推斷數據量
                          標頭中的字段。 由於填充,
                          offsetof(struct ofp_packet_in,data)==
                          sizeof(struct ofp_packet_in)-2. * /
};

reason字段,由這個字段可以看出前面所寫Packet_in事件觸發的兩種情況。

/* Why is this packet being sent to the controller? */
enum ofp_packet_in_reason {
    OFPR_NO_MATCH,          /* No matching flow. */
    OFPR_ACTION             /* Action explicitly output to controller. */
};
/ *爲什麼將此數據包發送到控制器? * /
enum of_p_packet_in_reason{
     OFPR_NO_MATCH,/ *沒有匹配的流程。 * /
     OFPR_ACTION   / *操作明確輸出到控制器。 * /
};

控制器配置流表(Flow-Mod消息)


Flow-Mod消息用來添加、刪除、修改Openflow交換機的流表信息
Flow-Mod消息共有五種類型:

  • ADD                      類型的flow-mod消息用來添加一條新的流表項
  • DELETE                類型的flow-mod消息用來刪除所有符合一定條件的流表項
  • DELETE-STRICT 類型的flow-mod消息用來刪除某一條指定的流表項
  • MODIFY                類型的flow-mod消息用來修改所有符合一定條件的流表項
  • MODIFY-STRICT 類型的flow-mod消息用來修改某一條指定的流表項
/* Flow setup and teardown (controller -> datapath). */
struct ofp_flow_mod {
    struct ofp_header header;
    struct ofp_match match;      /* Fields to match */
    uint64_t cookie;             /* Opaque controller-issued identifier. */

    /* Flow actions. */
    uint16_t command;             /* One of OFPFC_*. */
    uint16_t idle_timeout;        /* Idle time before discarding (seconds). */
    uint16_t hard_timeout;        /* Max time before discarding (seconds). */
    uint16_t priority;            /* Priority level of flow entry. */
    uint32_t buffer_id;           /* Buffered packet to apply to (or -1).
                                     Not meaningful for OFPFC_DELETE*. */
    uint16_t out_port;            /* For OFPFC_DELETE* commands, require
                                     matching entries to include this as an
                                     output port.  A value of OFPP_NONE
                                     indicates no restriction. */
    uint16_t flags;               /* One of OFPFF_*. */
    struct ofp_action_header actions[0]; /* The action length is inferred
                                            from the length field in the
                                            header. */
};

 

/ *流設置和拆除(控制器->數據路徑)。 * /
struct ofp_flow_mod {
    struct ofp_header header;
    struct ofp_match match; / *要匹配的字段* /
    uint64_t cookie;        / *不透明的控制器發出的標識符。 * /

    / *流動作。 * /
    uint16_t command;      / * OFPFC_ *之一。 * /
    uint16_t idle_timeout; / *丟棄前的空閒時間(秒)。 * /
    uint16_t hard_timeout; / *丟棄前的最長時間(秒)。 * /
    uint16_t priority;    / *流條目的優先級。 * /
    uint32_t buffer_id;    / *要應用於的緩衝數據包(或-1)。
                              對於OFPFC_DELETE *沒有意義。 * /
    uint16_t out_port;     / *對於OFPFC_DELETE *命令,要求
                               匹配條目以將此作爲
                               輸出端口。值爲OFPP_NONE
                               表示沒有限制。 * /
    uint16_t flags;       / * OFPFF_ *之一。 * /
    struct ofp_action_header actions [0]; / *
                                            從標頭中的長度字段推斷動作長度
                                             * /
};

 用Flow-Mod消息響應Packet-in消息

當交換機收到一個數據包並且交換機中沒有與該數據包匹配的流表項時,交換機將此數據包封裝到Packet-in消息中發送給控制器,並且交換機會將該數據包緩存。
控制器收到Packet-in消息後,可以發送Flow-Mod消息向交換機寫一個流表項。並且將Flow-Mod消息中的buffer_id字段設置爲Packet-in消息中的buffer_id值。從而控制器向交換機寫入了一條與數據包相關的流表項,並且指定該數據包按照此流表項的aciton列表處理。

交換機轉發數據包(Packet-Out)

並不是所有的數據包都需要向交換機中添加一條流表項來匹配處理,網絡中還存在多種數據包,它出現的數量很少(如ARP、IGMP等),以至於沒有必要通過流表項來指定這一類數據包的處理方法。
此時,控制器可以使用PacketOut消息,告訴交換機某一個數據包如何處理。

Packet-Out消息格式

/* Send packet (controller -> datapath). */
struct ofp_packet_out {
    struct ofp_header header;
    uint32_t buffer_id;           /* ID assigned by datapath (-1 if none). */
    uint16_t in_port;             /* Packet's input port (OFPP_NONE if none). */
    uint16_t actions_len;         /* Size of action array in bytes. */
    struct ofp_action_header actions[0]; /* Actions. */
    /* uint8_t data[0]; */        /* Packet data.  The length is inferred
                                     from the length field in the header.
                                     (Only meaningful if buffer_id == -1.) */
};
/ *發送數據包(控制器->數據路徑)。 * /
struct ofp_packet_out {
     struct ofp_header header;
     uint32_t buffer_id;     / *由數據路徑分配的ID(如果沒有則爲-1)。 * /
     uint16_t in_port;       / *數據包的輸入端口(如果沒有,則爲OFPP_NONE)。 * /
     uint16_t actions_len;   / *操作數組的大小,以字節爲單位。 * /
     struct ofp_action_header actions [0]; / *動作。 * /
     / * uint8_t數據[0]; * / / *數據包數據。 該長度是根據標題中的length字段推斷出來的。
                               (僅在buffer_id == -1時有意義。)* /
};

 Packet-Out消息的應用場景

1、指定某一個數據包的處理方法
2、讓交換機產生一個數據包並按照action列表處理典型應用:鏈路發現
控制器向一個交換機發送Packet-Out消息,buffer_id=-1,data段爲某種特殊數據包,actions爲從交換機的某個端口轉發
如果發出這個數據包的端口另一端也連接一個Openflow交換機,對端的交換機會產生一個Packet-ln消息將這個特殊的數據包上交給控制器,從而控制器探測到一條鏈路的存在

更多SDN相關內容,請查看:SDN-自學筆記

有問題請下方評論,轉載請註明出處,並附有原文鏈接,謝謝!如有侵權,請及時聯繫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章