Skip to main content

OpenFlow link capacity

Openflow 1.0中,對於每個Port的定義如下

/* 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. */
};

從這個定義之中,可以注意到有ㄧ個欄位叫做curr,他是一個bitmaps的表達式,由ofp_port_features所組成

/* Features of physical ports available in a datapath. */
enum ofp_port_features {
OFPPF_10MB_HD = 1 << 0, /* 10 Mb half-duplex rate support. */
OFPPF_10MB_FD = 1 << 1, /* 10 Mb full-duplex rate support. */
OFPPF_100MB_HD = 1 << 2, /* 100 Mb half-duplex rate support. */
OFPPF_100MB_FD = 1 << 3, /* 100 Mb full-duplex rate support. */
OFPPF_1GB_HD = 1 << 4, /* 1 Gb half-duplex rate support. */
OFPPF_1GB_FD = 1 << 5, /* 1 Gb full-duplex rate support. */
OFPPF_10GB_FD = 1 << 6, /* 10 Gb full-duplex rate support. */
OFPPF_COPPER = 1 << 7, /* Copper medium. */
OFPPF_FIBER = 1 << 8, /* Fiber medium. */
OFPPF_AUTONEG = 1 << 9, /* Auto-negotiation. */
OFPPF_PAUSE = 1 << 10, /* Pause. */
OFPPF_PAUSE_ASYM = 1 << 11 /* Asymmetric pause. */
};

這樣看起來我們可以透過features request的方式來取得switch上每一個port的capacity,因此做了下列實驗

環境建置

  • Controller: Floodlight
  • Network environment: mininet or OVS on PC

Expr 1

{
"00:00:00:00:00:00:00:01": {
"actions": 4095,
"buffers": 256,
"capabilities": 199,
"datapathId": "00:00:00:00:00:00:00:01",
"length": 176,
"ports": [
{
"advertisedFeatures": 0,
"config": 0,
"currentFeatures": 192,
"hardwareAddress": "32:38:53:8a:27:42",
"name": "s1-eth1",
"peerFeatures": 0,
"portNumber": 1,
"state": 0,
"supportedFeatures": 0
},
{
"advertisedFeatures": 0,
"config": 0,
"currentFeatures": 192,
"hardwareAddress": "8a:5d:09:2f:cf:06",
"name": "s1-eth2",
"peerFeatures": 0,
"portNumber": 2,
"state": 0,
"supportedFeatures": 0
},
{
"advertisedFeatures": 0,
"config": 0,
"currentFeatures": 0,
"hardwareAddress": "7e:00:4e:66:4d:45",
"name": "s1",
"peerFeatures": 0,
"portNumber": 65534,
"state": 0,
"supportedFeatures": 0
}
],
"tables": -2,
"type": "FEATURES_REPLY",
"version": 1,
"xid": 7
}
}
  • 從回傳的訊息中可以看到,除了lo以外的currentFeatures都是192,192就是2^7+2^6,所以對應到ofp_port_features就是OFPPF_10GB_FD以及OFPPF_COPPER

Expr 2

{
"00:00:00:00:00:00:00:01": {
"actions": 4095,
"buffers": 256,
"capabilities": 199,
"datapathId": "00:00:00:00:00:00:00:01",
"length": 176,
"ports": [
{
"advertisedFeatures": 0,
"config": 0,
"currentFeatures": 192,
"hardwareAddress": "32:38:53:8a:27:42",
"name": "s1-eth1",
"peerFeatures": 0,
"portNumber": 1,
"state": 0,
"supportedFeatures": 0
},
{
"advertisedFeatures": 0,
"config": 0,
"currentFeatures": 192,
"hardwareAddress": "8a:5d:09:2f:cf:06",
"name": "s1-eth2",
"peerFeatures": 0,
"portNumber": 2,
"state": 0,
"supportedFeatures": 0
},
{
"advertisedFeatures": 0,
"config": 0,
"currentFeatures": 0,
"hardwareAddress": "7e:00:4e:66:4d:45",
"name": "s1",
"peerFeatures": 0,
"portNumber": 65534,
"state": 0,
"supportedFeatures": 0
}
],
"tables": -2,
"type": "FEATURES_REPLY",
"version": 1,
"xid": 7
}
}
  • 可以看到完全沒有變化,不管有沒有設定tc link,這個currentFeatures的值依然是固定在10G,因此就很好奇會不會是這個featureRequest本身並沒有實作出來,因此換一個網路環境再試試看

Expr 3

{
"00:00:a0:36:9f:00:ed:04": {
"actions": 4095,
"buffers": 256,
"capabilities": 199,
"datapathId": "00:00:a0:36:9f:00:ed:04",
"length": 272,
"ports": [
{
"advertisedFeatures": 1711,
"config": 0,
"currentFeatures": 672,
"hardwareAddress": "a0:36:9f:00:ed:06",
"name": "eth3",
"peerFeatures": 0,
"portNumber": 3,
"state": 0,
"supportedFeatures": 1711
},
{
"advertisedFeatures": 1711,
"config": 0,
"currentFeatures": 640,
"hardwareAddress": "a0:36:9f:00:ed:05",
"name": "eth2",
"peerFeatures": 0,
"portNumber": 2,
"state": 1,
"supportedFeatures": 1711
},
{
"advertisedFeatures": 1711,
"config": 0,
"currentFeatures": 640,
"hardwareAddress": "a0:36:9f:00:ed:07",
"name": "eth4",
"peerFeatures": 0,
"portNumber": 4,
"state": 1,
"supportedFeatures": 1711
},
{
"advertisedFeatures": 0,
"config": 1,
"currentFeatures": 0,
"hardwareAddress": "a0:36:9f:00:ed:04",
"name": "br0",
"peerFeatures": 0,
"portNumber": 65534,
"state": 1,
"supportedFeatures": 0
},
{
"advertisedFeatures": 1711,
"config": 0,
"currentFeatures": 640,
"hardwareAddress": "a0:36:9f:00:ed:04",
"name": "eth1",
"peerFeatures": 0,
"portNumber": 1,
"state": 1,
"supportedFeatures": 1711
}
],
"tables": -1,
"type": "FEATURES_REPLY",
"version": 1,
"xid": 4
}
}

  • 採用真正的網卡後,就會發現currentFeatures的值是有變化的,這代表OVS的確有實作這個功能,於是我就開始好奇,為什麼Mininet中得到的數值都是10G,tc link到底是什麼

Mininet

  • 在仔細研究mininet的source code後,大致瞭解了整個運作流程

  • mininet要在兩個switch間創造一條link的時候,是透過下列手段達成的

    • ip link add name s1-eth1 type veth peer name s2-eth1 這種系統指令創造一個特殊的裝置veth,這兩個裝置的封包會彼此互通,因此就達成了link的功用

    • 此時透過ethtool s1-eth1可以觀察到其中 Speed: 10000Mb/s這樣的設定,他的速度就是設定成10G

    • OVS中會使用 struct ethtool_cmd這種結構來獲取port的相關資訊,這時候他會根據speed這個欄位來設定currentFeautres的數值

    • 因此mininet創造出來的link預設都是10G,所以OVS那邊都會抓到10G的資訊

  • traffic control的部分則是透過系統的tc指令來做到速度限制的功能,所以不會動到每個port的設定