OpenvSwitch/OpenFlow 架構解析與實踐案例


目錄

前言

該篇文章是在《通俗說 Openvswitch》的基礎上再結合我再網上收集的資料進行學習、整理與歸納,感謝劉大(公眾號:劉超的通俗雲計算)以及創作者的分享。

軟件定義網絡(SDN)

軟件定義有啥好處呢?
想象你有一個大的數據中心,里面有很多的網絡設備,光交換機就有很多,你希望在交換機上配置一些網絡的策略,例如某個口應該屬於某個 VLAN。
怎么配置呢?登到這台交換機上去,敲幾行命令就搞定了。
如果要配置 100 台交換機呢?頭大了吧,難不成登陸 100 台?
想不想有一個集中的地方,能看到整個網絡的拓撲圖,統一配置一下,然后一回車,配置的策略就通過管理網絡平面下發到 100 台交換機上。這樣整個網絡的拓撲結構就不是硬的了,也即不是通過插線,拔線,登陸盒子配置的,而是變成了軟的,也即通過軟件統一控制,這個統一控制的地方我們稱為 SDN Controller(控制器),這樣的網絡拓撲結構,我們稱為軟件定義的網絡

虛擬交換機(vSwitch)

虛擬交換機(vSwitch)就是利用虛擬平台,通過軟件的方式實現(Software Defined Network,SDN,軟件定義網絡)的交換機部件。跟傳統的物理交換機相比,虛擬交換機具備眾多優點:一是配置靈活,一台普通的服務器可以配置出數十台甚至上百台虛擬交換機,且端口數目也可以靈活選擇。例如,一台 VMware ESXi 服務器可以仿真出 248 台虛擬交換機,且每台交換機預設虛擬端口即可達 56 個;二是成本低廉,通過虛擬交換同樣可以獲得昂貴的普通交換機才能達到的性能,例如,微軟的 Hyper-V,虛擬機與虛擬交換機之間的聯機速度輕易可達 10Gbps。

為什么說雲計算時代的 SDN 非常重要

因為虛擬機的創建,刪除,遷移比物理機靈活的多,所以很難像物理的交換機一樣,用網線將交換機和物理服務器連接起來,就不怎么變了。虛擬機就不一樣了,所以需要虛擬交換機,也即通過軟件模擬一個交換機,用軟件模擬一根網線,一頭插在虛擬機上,一頭插在虛擬交換機上,一會兒創建五個虛擬機,要插到一個交換機上,一會兒其中兩個虛擬機遷移到了另外的物理機上,則他們兩個的網口要從上一台交換機上拔下來,插到新的虛擬交換機上,這樣做沒有問題,因為都是軟件實現的,很靈活。

OpenFlow 簡介

OpenFlow is a open standard managed by Open Networking Foundation. It specifies a protocol by which a remote controller can modify the behavior of networking devices through a well-defined “forwarding instruction set”.

OpenFlow,一種網上通信協議,屬於數據鏈路層,能夠控制網上交換器或路由器的數據轉發平面(Forwarding Plane),借此改變網上數據包所經過的網上路徑。簡而言之,OpenFlow 就是 SDN Controller 遠程控制網絡設備的協議,經由網上交換器,決定網上數據包要由何種路徑通過網絡交換機。雖然 OpenFlow 的功能不如各大網絡廠商的自家協議強大,但正因如此,OpenFlow 成為了一個兼容非常高的功能子集,以至於讓各網絡廠商能夠達成了部分的共識。

OpenFlow 允許從遠程控制網上交換器的數據包轉送表,透過新增、修改、移除數據包控制規則與行動,來改變數據包轉送的路徑。比起用訪問控制表(ACLs)和路由協議,允許更加復雜且靈活的流量管理。同時,OpenFlow 允許不同網絡供應商用一個簡單,開源的協議去遠程管理交換機(通常提供專有的接口和描述語言)。OpenFlow 協議用來描述控制器和交換機之間交互所用信息的標准,以及控制器和交換機的接口標准。

在這里插入圖片描述

Open vSwitch

Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware’s vNetwork distributed vswitch or Cisco’s Nexus 1000V.
官方網站

Open vSwitch(下文簡稱 OvS)就是一個開源的虛擬交換機實現。廣泛應用在雲計算行業,為網絡管理員提供虛擬雲主機之間和之內的流量可見性與可控性。Open vSwitch 旨在用虛擬化方案解決網絡問題,與控制器軟件一起實現分布式的虛擬交換技術。這意味着,交換機和控制器軟件能夠在多個服務器之間創建集群網絡配置,從而不需要在每一台雲主機和物理主機上單獨配置網絡。這個交換機還支持 VLAN 中繼,通過 NetFlow、sFlow 和 RSPAN 實現可見性,通過 OpenFlow 協議進行管理。它還有其他一些特性:嚴格流量控制,它由 OpenFlow 交換協議實現;遠程管理功能,它能通過網絡策略實現更多控制。
在這里插入圖片描述

簡而言之,Open vSwitch 即開放的軟件虛擬交換機,能夠達到產品級的質量,也就是說可以部署一些生產環境使用。它不光支持基本的二層交換,還支持標准的管理機接口和協議(e.g. NetFlow,sFlow,SPAN,RSAPN,CLI,LACP,802.1ag),同時也支持 OpenFlow,可以很好的與 SDN 體系融合

Open vSwitch 的特性清單

  • 支持通過 NetFlow、sFlow、IPFIX、SPAN、RSPAN 和 GRE-tunneled 鏡像使虛擬機內部通訊可以被監控;
  • 支持 LACP(IEEE 802.1AX-2008,多端口綁定)協議;
  • 支持標准的 802.1Q VLAN 模型以及 Trunk 模式;
  • 支持 BFD 和 802.1ag 鏈路狀態監測;
  • 支持 STP(IEEE 802.1D-1998);
  • 支持細粒度的 Qos;
  • 支持 HFSC 系統級別的流量控制隊列;
  • 支持每虛擬機網卡的流量的流量控制策略;
  • 支持基於源 MAC 負載均衡模式、主備模式、L4 哈希模式的多端口綁定;
  • 支持 OpenFlow 協議(包括許多虛擬化的增強特性);
  • 支持IPV6
  • 支持多種隧道協議(GRE, VXLAN, IPsec, GRE and VXLAN over IPsec)
  • 支持通過 C 或者 Python 接口遠程配置;
  • 支持內核態和用戶態的轉發引擎設置;
  • 支持多列表轉發的發送緩存引擎;
  • 支持轉發層抽象以容易的定向到新的軟件或者硬件平台;

Open vSwitch 的架構

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

ovsdb(ovsdb-server)

輕量級的數據庫,用於存儲整個 OvS 的配置信息,包括接口,交換內容,VLAN,虛擬交換機的創建,網卡的添加等信息與操作記錄,都由 ovsdb 保存到一個 conf.db 文件(JSON 格式)里面,通過 db.sock 提供服務。

ovs-vswitchd(vswitchd)

OvS 的核心部件,實現交換功能,與 Linux 內核兼容模塊一起實現基於流的交換(Flow-based Switching)。它和上層 Controller 通信遵從 OpenFlow 協議,它與 ovsdb-server 通信遵從 OVSDB 協議,它和內核模塊通過 netlink 進行通信,它支持多個獨立的 Datapath(網橋),它通過更改 Flow Table 實現了 Binding(綁定)和 VLAN 等功能。是真正的虛擬交換機生命周期管理進程。它通過 db.sock 文件從 ovsdb-server 進程讀取 conf.db 的配置信息(e.g. 用戶所創建的虛擬交換機、所添加的網卡等等操作記錄)。

Datapatch(openvswitch.ko)

在 OvS 中,給一個交換機,或者說一個橋,用了一個專業的名詞,叫做 DataPath!是一個 Linux Kernel 模塊,監聽網卡接口設備,獲取網絡包並交給 vSwitch 處理,支持數據在內核的交換。當 openvswtich.ko 被加載到了內核,會在網卡上注冊一個鈎子函數,每當有網絡包到達網卡時,這個函數就會被調用,將網絡包開始層層拆包(MAC 層,IP 層,TCP 層等),然后查看有沒有已經定義好的策略來處理網絡包(e.g. 修改 MAC,修改 IP,修改 TCP 端口,從哪個網卡發出去等等),如果找到了策略,則將網絡包從網卡發出。這個處理過程全在內核完成,所以非常快,稱之為 Fast Path。
在這里插入圖片描述

NOTE:然而內核態並沒有被分配太多內存,所以內核態能夠保存的策略很少,往往有新的策略到來,老的策略就被丟棄。如果在內核態找不到策略,則需要到用戶態去查詢,網絡包會通過 netlink(一種內核態與用戶態交互的機制)發送給 vswitchd,vswitchd 有一個監聽線程,當發現有從內核態發過來的包,就進入自己的處理流程。在用戶態相對較慢,故稱值為 Slow Path。用戶態的 vswtichd 不需要吝嗇內存,它包含了所有策略,這些策略都是 Controller(控制器)通過 OpenFlow 協議下發的。vswtichd 會根據網絡包的信息層層匹配,直到找到一款策略進行處理。如果實在找不到,則一般會采用默認策略,比如丟棄這個包。當最終匹配到了一個策略之后,則會根據 “局部性原理” 再通過 netlink 協議,將這條策略下發到內核態,為了下一個相同類型的網絡包能夠直接從內核匹配到,以此加快執行效率。當這條策略下發給內核時,如果內核的內存空間不足,則會開始淘汰部分老策略。由於近因效應,接下來的網絡包應該大概率能夠匹配這條策略的。例如:傳輸一個文件,同類型的網絡包會源源不斷的到來。
在這里插入圖片描述

OvS 的工具集

  • ovs-vsctl:用於獲取、更改 ovs-vswitchd 的配置信息。
  • ovs-ofctl:用於查詢、控制 OvS 作為 OpenFlow 交換機工作時的流表內容。
  • ovs-pki:用於創建、管理 OvS 與 Controller 之間的 SSL 通信框架。
  • ovs-dpctl:用於配置 Switch 內核模塊,可以控制轉發規則。
  • ovs-appctl:用於向 ovs-vswitchd 守護進程發送命令消息,一般用不上。
    在這里插入圖片描述

ovs-vsctl 常用指令

# 查看 OvS Log 級別
ovs-appctl vlog/list
# 設置 Log 級別
ovs-appctl vlog/set {module name}:{console, syslog, file}:{off, emer, err, warn, info, dbg}
# 以 stp 設置 file 為 dbg level 為例
ovs-appctl vlog/set stp:file:dbg

# 查看 OvS 版本
ovs-ofctl -V

# 查詢指令歷史記錄
ovsdb-tool show-log [-mmm]

# 修改 ofport (openflow port number) 為 100
ovs-vsctl add-port <bridge> <interface> -- set Interface <interface> ofport_request=100
# 設置 interface 為 internal
ovs-vsctl set Interface <interface> type=internal

# 開啟指定 Bridge 的 STP
ovs-vsctl set bridge <bridge> stp_enable=true
# 關閉指定 Bridge 的 STP
ovs-vsctl set bridge <bridge> stp_enable=false
# 查詢指定 Bridge 的 STP 的配置信息
ovs-vsctl get bridge <bridge> stp_enable
# 設置指定 Bridge 的 STP Priority
ovs−vsctl set bridge <bridge> other_config:stp-priority=0x7800
# 設置指定 Bridge 的 STP Cost
ovs−vsctl set port <bridge> other_config:stp-path-cost=10

Open vSwitch 的工作原理

要理解 OvS 的工作原理,首先要了解網橋的工作原理。網橋也叫做橋接器,工作在數據鏈路層,將兩個 LAN 連接,根據 MAC 地址來轉發數據幀,可以看成一個 “低層的路由器”。網橋處理數據幀遵循以下幾條規則:

  • 在一個接口上接收到的幀不會再往那個接口上發送此幀。
  • 每個接收到的幀都要學習其 Source MAC 地址。
  • 如果數據幀是多播或者廣播包(通過 2 層 MAC 地址確定)則要向接收端口以外的所有端口轉發,如果上層協議感興趣,則還會遞交上層處理。
  • 如果數據幀的地址不能在 CAM(MAC-Port Mapping)表中找到,則向接收端口以外的所有端口轉發。
  • 如果 CAM 表中能找到,則轉發給相應端口,如果發送和接收都是同一個端口,則不發送。
  • 網橋是以混雜模式工作的,所有 MAC 地址的數據幀都能夠通過。

Open vSwitch 的內核模塊(openvswitch.ko)實現了多個 “數據路徑(Datapath)”(類似於網橋),每個 Datapath 都可以有多個 vPorts(類似於網橋上的端口)。每個 Datapath 也通過關聯流表(Flow Table)來定義數據流向,通常的操作都是將數據流轉發到指定的 vPort 上。當網絡包到達一個 vPort,內核模塊所做的處理是提取其流的關鍵信息並在流表中查找這些關鍵信息,當有一個匹配的流時,就對該網絡包執行相應的操作;如果沒有匹配,則將網絡包送到用戶空間的處理隊列中,用戶空間可能會定義一個流用於以后碰到相同類型的網絡包可以在內核中執行操作,這就是所謂的 Slow Path 和 Fast Path。

Open vSwitch 實現的流量控制很大部分上是通過 OpenFlow 交換協議實現的。OpenFlow 使 Controller 能夠通過網絡訪問一個交換機或路由器的 Datapath。網管人員可以在任意一台計算機(Controller)上遠程控制數據管理,這樣他們就能夠進行精細的路由和交換控制,並實現復雜的網絡策略。有了 Open vSwitch 中的這些遠程管理功能,雲計算的集成商和供應商就能夠向客戶提供在一台計算機上持續管理各自虛擬網絡、應用和策略的功能。

OpenvSwitch 的典型工作流程

在這里插入圖片描述

  1. Instance 產生一個數據包並發送至虛擬網絡接口 vNIC(Instance eth0)。
  2. 這個數據包傳遞到物理機的 vNIC 接口(vnet)。
  3. 數據包從 vnet 出來,到達 Bridge br100 上。
  4. 數據包經過 Bridge 的處理,從物理節點上的 NIC(eth0)發出。
  5. 數據包從 eth0 出去后,按照宿主機的路由以及默認網關操作。此時該數據包已經不再受你控制了。

NOTE:L2 Switch 連接到宿主機的 eth0 通常是一個 Trunk 口,因為虛擬機對應的 vnet 往往會設置 VLAN TAG 來隔離虛擬機的廣播域。所以 eth0 就相當於一個 Trunk 口,而 vnets 就相當於 Access 口。

Open vSwitch 的安裝部署

OS:CentOS7

Step1. 關閉 SELinux,否則 ovsdb-server Manager 無法正常工作。

[root@localhost ~]# setenforce 0

[root@localhost ~]# cat /etc/selinux/config | grep -v ^#
SELINUX=disabled
SELINUXTYPE=targeted

Step 2. yum install

yum install openvswitch openvswitch-test

Step 3. 啟動服務

systemctl enable openvswitch
systemctl start openvswitch
systemctl status openvswitch

查看當前的 OvS 版本:

[root@localhost ~]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    ovs_version: "2.0.0"

查看 OvS 服務進程清單:

ovsdb-server /etc/openvswitch/conf.db 
    -vconsole:emer -vsyslog:err 
    -vfile:info 
    --remote=punix:/var/run/openvswitch/db.sock 
    --private-key=db:Open_vSwitch,SSL,private_key 
    --certificate=db:Open_vSwitch,SSL,certificate 
    --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --no-chdir 
    --log-file=/var/log/openvswitch/ovsdb-server.log 
    --pidfile=/var/run/openvswitch/ovsdb-server.pid
    --detach 
    --monitor

ovs-vswitchd unix:/var/run/openvswitch/db.sock 
    -vconsole:emer 
    -vsyslog:err 
    -vfile:info 
    --mlockall 
    --no-chdir 
    --log-file=/var/log/openvswitch/ovs-vswitchd.log 
    --pidfile=/var/run/openvswitch/ovs-vswitchd.pid 
    --detach 
    --monitor

查看加載的內核模塊:

[root@localhost ~]# lsmod | grep openvswitch
openvswitch            70743  0
vxlan                  37584  1 openvswitch
gre                    13808  1 openvswitch
libcrc32c              12644  2 xfs,openvswitch

從架構圖可知,ovsdb-server 與 ovs-vswitchd 可以通過 UNIX Domain Socket(/var/run/openvswitch/db.sock)進行互相通信。

Open vSwitch 的 DB(ovs-db)

ovs-db 在操作系統上的載體是 JSON 文件 /etc/openvswitch/conf.db,通過執行指令 ovsdb-client dump 可以查看其內容,e.g.

[root@localhost ~]# ovsdb-client dump
Bridge table
_uuid controller datapath_id datapath_type external_ids fail_mode flood_vlans flow_tables ipfix mirrors name netflow other_config ports protocols sflow status stp_enable
----- ---------- ----------- ------------- ------------ --------- ----------- ----------- ----- ------- ---- ------- ------------ ----- --------- ----- ------ ----------

Controller table
_uuid connection_mode controller_burst_limit controller_rate_limit enable_async_messages external_ids inactivity_probe is_connected local_gateway local_ip local_netmask max_backoff other_config role status target
----- --------------- ---------------------- --------------------- --------------------- ------------ ---------------- ------------ ------------- -------- ------------- ----------- ------------ ---- ------ ------

Flow_Sample_Collector_Set table
_uuid bridge external_ids id ipfix
----- ------ ------------ -- -----

Flow_Table table
_uuid flow_limit groups name overflow_policy
----- ---------- ------ ---- ---------------

IPFIX table
_uuid cache_active_timeout cache_max_flows external_ids obs_domain_id obs_point_id sampling targets
----- -------------------- --------------- ------------ ------------- ------------ -------- -------

Interface table
_uuid admin_state bfd bfd_status cfm_fault cfm_fault_status cfm_health cfm_mpid cfm_remote_mpids cfm_remote_opstate duplex external_ids ifindex ingress_policing_burst ingress_policing_rate lacp_current link_resets link_speed link_state mac mac_in_use mtu name ofport ofport_request options other_config statistics status type
----- ----------- --- ---------- --------- ---------------- ---------- -------- ---------------- ------------------ ------ ------------ ------- ---------------------- --------------------- ------------ ----------- ---------- ---------- --- ---------- --- ---- ------ -------------- ------- ------------ ---------- ------ ----

Manager table
_uuid connection_mode external_ids inactivity_probe is_connected max_backoff other_config status target
----- --------------- ------------ ---------------- ------------ ----------- ------------ ------ ------

Mirror table
_uuid external_ids name output_port output_vlan select_all select_dst_port select_src_port select_vlan statistics
----- ------------ ---- ----------- ----------- ---------- --------------- --------------- ----------- ----------

NetFlow table
_uuid active_timeout add_id_to_interface engine_id engine_type external_ids targets
----- -------------- ------------------- --------- ----------- ------------ -------

Open_vSwitch table
_uuid                                bridges cur_cfg db_version external_ids                                       manager_options next_cfg other_config ovs_version ssl statistics system_type system_version
------------------------------------ ------- ------- ---------- -------------------------------------------------- --------------- -------- ------------ ----------- --- ---------- ----------- --------------
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f []      0       "7.3.0"    {system-id="257b9b47-87e7-4404-9af8-37f98b04f2bd"} []              0        {}           "2.0.0"     []  {}         unknown     unknown       

Port table
_uuid bond_downdelay bond_fake_iface bond_mode bond_updelay external_ids fake_bridge interfaces lacp mac name other_config qos statistics status tag trunks vlan_mode
----- -------------- --------------- --------- ------------ ------------ ----------- ---------- ---- --- ---- ------------ --- ---------- ------ --- ------ ---------

QoS table
_uuid external_ids other_config queues type
----- ------------ ------------ ------ ----

Queue table
_uuid dscp external_ids other_config
----- ---- ------------ ------------

SSL table
_uuid bootstrap_ca_cert ca_cert certificate external_ids private_key
----- ----------------- ------- ----------- ------------ -----------

sFlow table
_uuid agent external_ids header polling sampling targets
----- ----- ------------ ------ ------- -------- -------

使用圖形化工具可以更加友好的查看:
在這里插入圖片描述
數據庫表之間的關系如下圖所示:
在這里插入圖片描述

其中 Open_vSwitch 表是 OvS DB 的 root(根)。
在這里插入圖片描述
在這里插入圖片描述
它的表結構如下圖,記錄 ovs-vswitchd 的配置信息,e.g.

  • Bridge 設備的配置
  • OvS 本身的配置
    • other_config:stats-update-interval:將統計信息寫入數據庫的間隔時間
    • other_config:flow-restore-wait: 針對 hot-upgrade,如果為 True 則不處理任何包。一般使用的過程為:先停掉 ovs-vswitchd,然后將這個值設為 True,再啟動 ovs-vswitchd。這個時候不處理任何包,然后使用 ovs-ofctl 將 flow table restore 到一個正確的狀態,最后設置這個值為 False,開始處理包。
    • other_config:flow-limit:指定 Flow Table 中 flow entry(入口)的數量
    • other_config:n-handler-threads:用於處理新 Flow 的線程數
    • other_config:n-revalidator-threads:用於驗證 Flow 的線程數
    • other_config:enable-statistics:是否統計以下項目
      • statistics:cpu:統計 CPU 數量,線程
      • statistics:load_average:system load
      • statistics:memory:總 RAM,Swap
      • statistics:process_NAME:統計 memory size, cpu time 等(with NAME replaced by a process name)
      • statistics:file_systems:mount point, size, used
    • client request id:cur_cfg 和 next_cfg,當一個 Client 修改完數據庫時,next_cfg 加 1,然后等待 OvS 應用這些修改,當應用完畢,則 cur_cfg 加 1,此時 cur_cfg 等於 next_cfg。顯然,該配置是為了保證高並發請求的一致性而存在的。
    • 對 ovsdb-server 的配置,指向 Manager 表,ovs-vswitchd 作為 ovsdb-server 的 Client 之一,Manager 配置了 DB Connection 的字段。
    • 對 SSL DB Connection 的配置:指向 SSL 表,主要配置 SSL 安全通信所需要的 private key、certificate 等文件的路徑。

Open vSwitch 的操作對象

數據庫結構是一款軟件的資源模型設計的映射,下文主要根據 OvS 的資源模型來依次認識每種資源對象的特性與作用。

Manager

Manager 對象都是為了配置 ovsdb-server 的 Connection,讓 Clients(e.g. ovs-vswitchd、ovs-vsctl、host) 可以遠程對 ovsdb-server 執行 DB Operation。

從上述架構圖可知,ovsdb-server 是 ovs-db 提供管理的 RPC 接口。加載了 Open_vSwitch 表中的 manager_options 字段值來作為監聽端口。

Manager 的表結構
在這里插入圖片描述
其中最重要的字段是 target,記錄了 ovsdb-server 的監聽參數信息:

  • Active(主動)database connection methods:

    • ssl:ip[:port]:監聽在指定 Remote IP 的 Port 上,協議為 SSL
    • tcp:ip[:port]:監聽在指定 Remote IP 的 Port 上,協議為 TCP
    • unix:FILE:Unix domain socket named FILE
  • Passive(被動)database connection methods:

    • pssl:[port][:ip]:監聽在本機 IP 的指定 Port 上,協議為 SSL
    • ptcp:[port][:ip]:監聽在本機 IP 的指定 Port 上,協議為 TCP

通過下述指令設置:

ovs-vsctl set-manager TARGET...      # set the list of managers to TARGET...

# Active Listener
ovs-vsctl set-manager tcp:1.2.3.4:6640
# Passive Listener 
ovs-vsctl set-manager ptcp:6640

NOTE:基於 TCP 的 DB Connection,使得 ovs-vsctl 在遠程機器上也可以控制 ovsdb-server。

配置 Manager OvS DB Connection

[root@localhost ~]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    ovs_version: "2.0.0"

[root@localhost ~]# ovs-vsctl set-manager ptcp:8881

[root@localhost ~]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "ptcp:8881"
    ovs_version: "2.0.0"

[root@localhost ~]# ovsdb-client dump
...
Manager table
_uuid                                connection_mode external_ids inactivity_probe is_connected max_backoff other_config status                                                               target
------------------------------------ --------------- ------------ ---------------- ------------ ----------- ------------ -------------------------------------------------------------------- -----------
84f0a33c-a798-40fc-a285-ed4d83121d3e []              {}           []               false        []          {}           {bound_port="8881", sec_since_connect="0", sec_since_disconnect="0"} "ptcp:8881"

檢查 Port 是否正常開啟:

[root@localhost ~]# netstat -lpntu | grep 8881
tcp        0      0 0.0.0.0:8881            0.0.0.0:*               LISTEN      3024/ovsdb-server

從遠程計算機上執行連接:

[root@localhost ~]# ovs-vsctl --db=tcp:192.168.1.109:8881 show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "ptcp:8881"
    ovs_version: "2.0.0"

NOTE:注意防火牆的干擾因素。

SSL

如果將 Open vSwitch 配置為通過網絡連接到 OpenFlow 控制器(ovs-vswitchd 與 ovs-controller 之間),那么建議你使用 OpenSSL 來構建安全的網絡通訊,雙向的 SSL 互相可確保 OpenFlow 連接的完整性和與安全。

想建立 SSL 連接,首先要獲取相關的 CA 證書,並將這些證書記錄到 SSL 表中。啟動 ovsdb-server 時,通過選項 --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert 來指定應用這些參數。

SSL 表結構
在這里插入圖片描述
SSL 表屬性

  • private_key:私鑰
  • ca_cert:CA 根證書
  • bootstrap_ca_cert(Boolean):如果為 True,則每次啟動 ovsdb-server,都會向 Controller 獲取最新的 CA 證書。否則,就繼續使用舊的 CA 證書。
  • certificate:CA 簽發的證書

其中主機(客戶端)的 Public key 包含在 CA 簽發的證書(certificate)內,然后再由 CA 中心的 private key 進行簽名,CA 中心來擔保這個 certificate 是合法的。為了驗證 CA 簽名,還需要 CA 的 public key,並放到 ca_cert 指向的 CA 證書里面。而 CA 本身的 public key 也需要被簽名更高級的 CA 或者 CA(根 CA)自己擔保。

SSL 驗證流程

  1. 客戶端持有 CA 根證書(ca_cert)並與 CA 的私鑰進行驗證(CA 根證書由 CA 通過自己的私鑰進行自簽發),驗證成功則說明該 CA 是 root CA,可以自己擔保自己。
  2. 客戶端持有 CA 簽發的證書(certificate,內含客戶端公鑰)並與 CA 根證書進行驗證(由 CA 簽發的證書可以使用 CA 私鑰解開),如果驗證成功則返回客戶端的公鑰。
  3. 客戶端持有自己的私鑰並與 CA 解開的客戶端公鑰進行驗證,驗證成功,則說明該客戶端是受到 CA 擔保的。
  4. 客戶端與服務器建立 SSL 連接。
    在這里插入圖片描述
    簡而言之,客戶端需要保證持有自己的私鑰、CA 簽發的證書、CA 根證書才可以完成 SSL 驗證。更多 CA 自簽發的內容,請瀏覽《自建 CA 中心並簽發 CA 證書》
# 查詢 SSL 連接
ovs-vsctl get-ssl
# 設置 SSL 證書
ovs-vsctl set-ssl sc-privkey.pem sc-cert.pem cacert.pem
# 刪除 SSL 連接
ovs-vsctl del-ssl

配置 SSL Connection

自簽發 CA 根證書

  • Step 1. 生成 CA 根證書的 RSA 私鑰
mkdir ~/OVS_CA
cd ~/OVS_CA

openssl genrsa -out caprivate.key 1024
  • Step 2. 生成 CA 根證書的簽名請求(CSR)
openssl req -key caprivate.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=fanguiju@163.com" -out cacertificate.req
  • Step 3. 自簽發CA 根證書(內含了 CA 的公鑰)
openssl x509 -req -in cacertificate.req -signkey caprivate.key -out cacertificate.pem

PS:自簽發即自己擔保自己,用自己的私鑰對自己的 CSR 進行簽發,所以也稱為根證書。

簽發客戶端證書

  • Step 1. 生成客戶端私鑰
mkdir ~/ClientCerts
cd ~/ClientCerts

openssl genrsa -out cliu8private.key 1024
  • Step 2. 生成客戶端簽名請求
openssl req -key cliu8private.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=cliu8@163.com" -out cliu8certificate.req
  • Step 3. CA 中心簽發客戶端證書(CA 中心擔保該客戶端)
cp ~/OVS_CA/caprivate.key ~/OVS_CA/cacertificate.pem ~/ClientCerts

openssl x509 -req -in cliu8certificate.req -CA cacertificate.pem -CAkey caprivate.key -out cliu8certificate.pem -CAcreateserial

配置 SSL Connection

ovs-vsctl del-manager
ovs-vsctl set-manager pssl:8881
ovs-vsctl set-ssl /root/ClientCerts/cliu8private.key /root/ClientCerts/cliu8certificate.pem /root/OVS_CA/cacertificate.pem

NOTE:set-ssl 一定要指定絕對路徑,否則無法正確載入證書文件。

查看修改

[root@localhost newcerts]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "pssl:8881"
    ovs_version: "2.0.0"

[root@localhost ~]# ovsdb-client dump
...
SSL table
_uuid                                bootstrap_ca_cert ca_cert                          certificate                              external_ids private_key
------------------------------------ ----------------- -------------------------------- ---------------------------------------- ------------ ------------------------------------
f8d8f0f5-f87b-430b-9d48-123a74a6804f false             "/root/OVS_CA/cacertificate.pem" "/root/ClientCerts/cliu8certificate.pem" {}           "/root/ClientCerts/cliu8private.key"

驗證

  • 此時如果不輸入 PKI 配置則無法通過 SSL 認證
[root@localhost ~]# ovs-vsctl --db=ssl:192.168.1.109:8881 show
2019-02-23T06:46:26Z|00001|stream_ssl|ERR|Private key must be configured to use SSL
2019-02-23T06:46:26Z|00002|stream_ssl|ERR|Certificate must be configured to use SSL
2019-02-23T06:46:26Z|00003|stream_ssl|ERR|CA certificate must be configured to use SSL
2019-02-23T06:46:26Z|00004|reconnect|WARN|ssl:192.168.1.109:8881: connection attempt failed (Protocol not available)
ovs-vsctl: ssl:192.168.1.109:8881: database connection failed (Protocol not available)
  • 將 cliu8private.key、cliu8certificate.pem、cacertificate.pem 的副本復制到客戶端
scp cliu8private.key cliu8certificate.pem cacertificate.pem root@192.168.1.110:~/certs
  • 在客戶端請求建立 SSL 連接
[root@localhost certs]#  ovs-vsctl --db=ssl:192.168.1.109:8881 --private-key=cliu8private.key --certificate=cliu8certificate.pem --ca-cert=cacertificate.pem show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "pssl:8881"
    ovs_version: "2.0.0"

NOTE:

PKI configuration (required to use SSL):
  -p, --private-key=FILE  file with private key
  -c, --certificate=FILE  file with certificate for private key
  -C, --ca-cert=FILE      file with peer CA certificate

Bridge

Bridge 即網橋,但在 Linux 的語義中 Bridge 與 vSwitch 具有相同的含義,可見 Bridge 正式 Open vSwitch 最為核心的對象與概念。關於 Bridge 的概念不再多談,更詳細的內容可以瀏覽《Networking 基本術語/概念》一文。下面主要記錄了 OvS 關於 Bridge 的常見操作。

Bridge 常用操作指令

Bridge commands:
  add-br BRIDGE               create a new bridge named BRIDGE
  add-br BRIDGE PARENT VLAN   create new fake BRIDGE in PARENT on VLAN
  del-br BRIDGE               delete BRIDGE and all of its ports
  list-br                     print the names of all the bridges
  br-exists BRIDGE            exit 2 if BRIDGE does not exist
  br-to-vlan BRIDGE           print the VLAN which BRIDGE is on
  br-to-parent BRIDGE         print the parent of BRIDGE
  br-set-external-id BRIDGE KEY VALUE  set KEY on BRIDGE to VALUE
  br-set-external-id BRIDGE KEY  unset KEY on BRIDGE
  br-get-external-id BRIDGE KEY  print value of KEY on BRIDGE
  br-get-external-id BRIDGE  list key-value pairs on BRIDGE

# Bridge 管理操作
ovs-vsctl show
ovs-vsctl add-br <bridge>
ovs-vsctl del-br <bridge>
ovs-vsctl --if-exists del-br <bridge>
ovs-vsctl add-port <bridge> <port>|<interface>
ovs-vsctl del-port <bridge> <port>|<interface>
ovs-vsctl list <bridge>|<port>|<interface>
ovs-vsctl list bridge <bridge>
# 創建 Bridge 的同時為 Bridge 添加 Port/Interface
ovs−vsctl add−br <bridge> -- add−port <bridge> <port>|<interface>

在這里插入圖片描述

  • 創建虛擬交換機:
[root@localhost ~]# ovs-vsctl add-br ubuntu_br
[root@localhost ~]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "ptcp:8881"
    Bridge ubuntu_br
        Port ubuntu_br
            Interface ubuntu_br
                type: internal
    ovs_version: "2.0.0"
  • 創建虛擬 “網線”(VETH pair):
[root@localhost ~]# ip link add first_br type veth peer name first_if
[root@localhost ~]# ip link add second_br type veth peer name second_if
[root@localhost ~]# ip link add third_br type veth peer name third_if
  • 查看新建的設備:
[root@localhost ~]# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:a2:2e:a4 brd ff:ff:ff:ff:ff:ff
3: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether f6:66:5f:f9:ba:17 brd ff:ff:ff:ff:ff:ff
4: ubuntu_br: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000
    link/ether 46:ca:9f:ed:0b:46 brd ff:ff:ff:ff:ff:ff
5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT qlen 1000
    link/ether 52:54:00:69:fc:47 brd ff:ff:ff:ff:ff:ff
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000
    link/ether 52:54:00:69:fc:47 brd ff:ff:ff:ff:ff:ff
7: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000
    link/ether fe:54:00:b8:9a:cf brd ff:ff:ff:ff:ff:ff
8: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000
    link/ether fe:54:00:43:07:06 brd ff:ff:ff:ff:ff:ff
9: vnet2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000
    link/ether fe:54:00:ce:e6:40 brd ff:ff:ff:ff:ff:ff
10: first_if@first_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 46:df:83:a6:66:bc brd ff:ff:ff:ff:ff:ff
11: first_br@file_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 72:90:6d:0d:4b:e0 brd ff:ff:ff:ff:ff:ff
12: second_if@second_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 6a:68:8f:38:86:a2 brd ff:ff:ff:ff:ff:ff
13: second_br@second_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 86:8d:e3:32:03:b4 brd ff:ff:ff:ff:ff:ff
14: third_if@third_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 5e:72:4c:9b:4d:18 brd ff:ff:ff:ff:ff:ff
15: third_br@third_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether a2:cf:5f:72:da:23 brd ff:ff:ff:ff:ff:ff
  • 將虛擬 “網線” 的一端接入虛擬交換機:
[root@localhost ~]# ovs-vsctl add-port ubuntu_br first_br
[root@localhost ~]# ovs-vsctl add-port ubuntu_br second_br
[root@localhost ~]# ovs-vsctl add-port ubuntu_br third_br

[root@localhost ~]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "ptcp:8881"
    Bridge ubuntu_br
        Port ubuntu_br
            Interface ubuntu_br
                type: internal
        Port first_br
            Interface first_br
        Port second_br
            Interface second_br
        Port third_br
            Interface third_br
    ovs_version: "2.0.0"

NOTE:Bridge ubuntu_br 的同名 Port,一般就是 Bridge 的管理端口了,類比物理交換機的管理端口,一般會為其配置 IP 地址。

Controller

OvS 是一個 OpenFlow Switch 實現,可以通過 OpenFlow Controller(OpenFlow 協議)對所有分布式的 Bridge 進行統一管理。所謂 “管理”,實際上是對 Bridge 的 Flow Table 的管理。SDN Controller 的核心是控制策略的下發,並以此來決策數據的流向

Controller 有兩種類型

  • Primary Controller:真正控制 Bridge 的 Flow Table,Bridge 會保持與 Controller 的連接,如果連接失敗或斷開,取決於 Bridge 的 Fail Mode 來進行處理。一個 Bridge 可以連接到多個 Controller,但是 Controller 之間的協作需要 Controller 自己來完成。
  • Service Controller:僅僅用於 Support,偶爾操作,Maintain 使用,如果 Connection 與 Bridge 斷開連接,Bridge 的 Fail Mode 也不會起作用。

OvS 為 Bridge 提供了下列兩種 Fail Mode

  • Secure:斷開連接后 Bridge 會試圖重連 Controller 直至成功,並不會自己維護 Flow Table。
  • Standalone:若 Bridge 嘗試三次依舊連接不上 Controller,則會自己建立並維護獨立的 Flow Table。
# 查詢 Bridge 的 Fail Mode
ovs-vsctl get-fail-mode ovs-br
# 設置 Bridge 的 Fail Mode
ovs-vsctl set-fail-mode ovs-br standalone
ovs-vsctl set-fail-mode ovs-br secure
# 移除 Bridge 的 Fail Mode
ovs-vsctl del-fail-mode ovs-br

# 查看 Bridge 和 Controller 的連接模式
ovs-vsctl get controller ovs-br connection-mode
# 設置 Out-of-band 連接模式
ovs-vsctl set controller ovs-br connection-mode=out-of-band
# 設置 In-band (default) 連接模式
ovs-vsctl set controller ovs-br connection-mode=in-band
# 移除 hidden flow
ovs-vsctl set bridge br0 other-config:disable-in-band=true

Controller 表結構
在這里插入圖片描述

Controller 常用指令

# 設置 Controller
ovs-vsctl set-controller <bridge> tcp:<controller_ip>:6633
# 設置 Multi Controller
ovs-vsctl set-controller <bridge> tcp:<controller_ip1>:6633 tcp:<controller_ip2>:6633
# 獲取 Bridge 的 Controller
ovs-vsctl get-controller <bridge>
# 移除 Controller
ovs-vsctl del-controller <bridge>

安裝 Floodlight

OpenFlow Controller 的種類繁多,常見有如 OpenDaylight 等等,詳細清單可瀏覽《OpenFlow Controllers in GENI》。本篇以 Floodlight 為例,感受 Controller 對 Bridge 的流量控制功能。

官方網站:http://www.projectfloodlight.org/getting-started/
官方部署手冊:https://floodlight.atlassian.net/wiki/spaces/floodlightcontroller/pages/1343544/Installation+Guide
在這里插入圖片描述

Installing Floodlight

git clone git://github.com/floodlight/floodlight.git
cd floodlight/
git submodule init
git submodule update
ant

sudo mkdir /var/lib/floodlight
sudo mkdir /var/log/floodlight
sudo chmod 777 /var/lib/floodlight

NOTE: 這里使用的是 Tag 1.2 版本

Running Floodlight in the Terminal

nohup java -jar ~/floodlight/target/floodlight.jar > /var/log/floodlight/floodlight.log 2>&1 &

檢查 Controller 的監聽端口

[root@localhost ~]# cat /var/log/floodlight/floodlight.log | grep "Listening for switch connections"
09:28:16.102 INFO [n.f.c.i.OFSwitchManager:main] Listening for switch connections on /0.0.0.0:6653

[root@localhost ~]# netstat -lpntu | grep 6653
tcp6       0      0 :::6653                 :::*                    LISTEN      20159/java

NOTE:Floodlight 會通過監聽 /0.0.0.0:6653 Socket 來獲取 Bridge 的連接。

將 Bridge 連接到 Controller

[root@localhost floodlight-1.2]# ovs-vsctl set-controller ubuntu_br tcp:192.168.1.109:6653
[root@localhost floodlight-1.2]# ovs-vsctl show
2028eafc-e1db-4ea8-b0fc-30a21fdaca0f
    Manager "ptcp:8881"
    Bridge ubuntu_br
        Controller "tcp:192.168.1.109:6633"
        Port ubuntu_br
            Interface ubuntu_br
                type: internal
        Port third_br
            Interface third_br
        Port first_br
            Interface first_br
        Port second_br
            Interface second_br
    ovs_version: "2.0.0"

NOTE:Bridge 連接到 Controller 之后,Controller 就可以收集、下發、管理 Bridge 的相關信息了(e.g. Flow Table)。

訪問 Web GUI

http://192.168.1.109:8080/ui/index.html

將 KVM 虛擬機接入 OvS Bridge

將三台 KVM 虛擬機接入到 Bridge

[root@localhost ~]# virsh domiflist VM1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
macvtap1   direct     ubuntu_br  rtl8139     52:54:00:b8:9a:cf

[root@localhost ~]# virsh domiflist VM2
Interface  Type       Source     Model       MAC
-------------------------------------------------------
macvtap0   direct     ubuntu_br  rtl8139     52:54:00:43:07:06

[root@localhost ~]# virsh domiflist VM3
Interface  Type       Source     Model       MAC
-------------------------------------------------------
macvtap2   direct     ubuntu_br  rtl8139     52:54:00:ce:e6:40

NOTE:VM1、2、3 都連接到同一個 Bridge 上,只要三者具有網段的 IP 地址就可以通信了。

查看 Floodlight Dashboard
在這里插入圖片描述
等待一段時間 Floodlight 就會將會主機上的 Bridges、Bridge 上的 Hosts、Host 的 IP/MAC 地址等信息收集上來。

Floodlight Controller 常用指令

Floodlight Dashboard 基本上只作為展示,所以大部分操作依舊需要通過指令行來完成。

  • 請求該 Controller 上所有 Switch 的 DPID
curl http://localhost:8080/wm/core/controller/switches/json
  • 查看流表項
curl http://localhost:8080/wm/staticflowentrypusher/list/all/json
  • 查看指定 Switch 的流表項
curl http://192.168.1.109:8080/wm/core/switch/00:00:46:ca:9f:ed:0b:46/flow/json
  • 添加靜態流表項
curl -d '{"switch": "00:00:00:00:00:00:00:01", "name":"flow-mod-1", "cookie":"0", "priority":"32768", "ingress-port":"1", "active":"true", "actions":"output=2"}' http://localhost:8080/wm/staticflowentrypusher/json
  • 只允許 10.0.0.101 和 10.0.0.103 相互 Ping 的靜態流表
# VM1
curl -d '{"switch": "00:00:46:ca:9f:ed:0b:46", "name":"static-flow2", "cookie":"0", "priority":"32768", "src-mac":"52:54:00:b8:9a:cf","active":"true", "actions":"output=10"}'  http://localhost:8080/wm/staticflowentrypusher/json

# VM3
curl -d '{"switch": "00:00:46:ca:9f:ed:0b:46", "name":"static-flow1", "cookie":"0", "priority":"32768", "src-mac":"52:54:00:ce:e6:40","active":"true", "actions":"output=12"}'  http://localhost:8080/wm/staticflowentrypusher/json
  • 刪除指定流表
curl -X DELETE -d '{"name":"flow-mod-1"}' http://localhost:8080/wm/staticflowentrypusher/json
  • 刪除指定 Switch 所有流表
curl http://localhost:8080/wm/staticflowentrypusher /clear/<dpid>/json

Mirror

Mirror 的功能就是配置一個 Bridge 將某些具有特定條件的包發給指定的 Mirrored Ports。

包的條件有以下幾種:

  • select_all
  • select_dst_port
  • select_src_port
  • select_vlan

指定的目的 Ports 有以下兩種:

  • output_port (SPAN Switched Port ANalyzer)
  • output_vlan (RSPAN Remote Switched Port ANalyzer)

SPAN

Source (SPAN) port - A port that is monitored with use of the SPAN feature.
Destination (SPAN) port - A port that monitors source ports, usually where a network analyzer is connected.

在這里插入圖片描述

ovs-vsctl add-br ovs-br
ovs-vsctl add-port ovs-br eth0
ovs-vsctl add-port ovs-br eth1
# 設置 SPAN Mirrors,將 ovs-br 上 add-port {eth0,eth1} Mirror 至 tap0
ovs-vsctl add-port ovs-br tap0 \
     -- --id=@p get port tap0 \
     -- --id=@m create mirror name=m0 select-all=true output-port=@p \
     -- set bridge ovs-br mirrors=@m
# 刪除 SPAN Mirrors
ovs-vsctl clear bridge ovs-br mirrors

RSPAN

  • 被監控的流量不是發送到一個指定的端口,而是 Flood 給指定的 VLAN
  • 監聽的端口不一定要在本地 Switch 上,可以在指定的 VLAN 的任意 Switch 上
  • S1 is a source switch
  • S2 and S3 are intermediate switches
  • S4 and S5 are destination switches.
  • learning is disabled to enable flooding
    在這里插入圖片描述

Interface

Open vSwitch 支持的網卡類型

  • netdev:通用網卡設備(e.g. eth0、veth)

    • 接收:一個 netdev 在 L2 收到報文后會直接通過 OvS 接收函數處理,不會再走傳統內核 TCP/IP 協議棧。
    • 發送:OvS 中的一條流指定從該 netdev 發出的時候就通過該網卡設備發送。
  • internal:虛擬網卡設備

    • 接收:當從系統發出的報文路由查找通過該設備發送的時候,就進入 OvS 接收處理函數。
    • 發送:OvS 中的一條流制定從該 internal 設備發出的時候,該報文被重新注入內核協議棧。
  • gre device:隧道設備(不管用戶態創建多少個 GRE Tunnel,在內核態有且只有一個 GRE 設備)

    • 接收:當系統收到 GRE 報文后,傳遞給 L4 層解析 gre header,然后傳遞給 OvS 接收處理函數。
    • 發送:OvS 中的一條流制定從該 GRE 設備發送,報文會根據流表規則加上 GRE 頭以及外層包裹 IP,查找路由發送。

Port

Port 與 VLAN

Port 的一個重要的特性就是 VLAN Configuration,具有兩種類型:

  • Trunk Port
  • Access Port

Trunk Port:

  • 這個 Port 不配置 Tag,配置 trunks。
  • 如果 trunks 為空,則所有的 VLAN 都 trunk,缺省 VLAN ID 為 0,全部允許通過。
  • 如果 trunks 不為空,則僅有符合條件(ID)的 VLAN 能通過。

簡而言之,就是物理交換機的 Trunk 口,符合 Trunks 列表的 VLAN ID 可通過。

Access Port:

  • 這個 Port 配置 Tag,從這個 Port 進來的包都被打上 Tag(ID)。
  • 如果從其他的 Trunk Port 中進來的本身就帶有 VLAN ID 的包,若 VLAN ID 等於這個 Port 的 Tag,則會從這個 Port 發出。
  • 從其他的 Access Port 進來的包,如果 Tag 相同,也會被 Forward 到這個 Port。
  • 從 Access Port 發出的包會被摘除 Tag,不帶 VLAN ID。
  • 如果一個本身帶 VLAN ID 的包到達 Access Port,即便 VLAN ID 等於 Tag,也會被拋棄,Access Port 只接受 Untag 包。

簡而言之,由 Access Port 接收到的包會被打上 Tag,Access Port 只接收 Untag 包,否則丟棄。具有相同 VLAN ID 的包會給轉發到對應的 Access Port 然后解除 Tag 再發出。

Port 與 VLAN 的常用操作指令

# 添加 Port 並設置 VLAN tag,ID 為 3
ovs-vsctl add-port <bridge> <vlan_access_interface> tag=3 -- set interface <vlan_access_interface> type=internal
# 為已存在的 Port 設置 VLAN tag,ID 為 9
ovs-vsctl set port <port> tag=9
# 移除 VLAN tag
ovs-vsctl del-port <bridge> <vlan_access_interface>
# 查詢 VLAN
ifconfig <vlan_access_interface>
# 設置 Vlan Trunk
ovs-vsctl add-port <bridge> <vlan_trunk_interface> trunk=3,4,5,6
# 添加設置 VLAN 的 Flow,ID 為 100
ovs-ofctl add-flow <bridge> in_port=1,dl_vlan=0xffff,actions=mod_vlan_vid:100,output:3
ovs-ofctl add-flow <bridge> in_port=1,dl_vlan=0xffff,actions=push_vlan:0x8100,set_field:100-\>vlan_vid,output:3
# 添加摘除 VLAN tag 的 Flow
ovs-ofctl add-flow <bridge> in_port=3,dl_vlan=100,actions=strip_vlan,output:1
# ovs-ofctl add-flow pop-vlan
ovs-ofctl add-flow ovs-br in_port=3,dl_vlan=0xffff,actions=pop_vlan,output:1

Port 與 Bond

Port 和 Interface 的關系是一對多的關系,因為 OvS 支持 Bond 功能。所謂 Bond 就是將多個 Interface “捆綁” 在一起形成一個虛擬的連接,從而實現高可用性以及高吞吐量的效果。

常見的 bond_mode 有以下幾種:

  • active-backup:故障轉移,一個連接 Active,其他連接 Backup。
  • balance-slb:負載均衡,根據源 MAC 和 output VLAN 進行負載均衡。
  • balance-tcp:負載均衡,必須在支持 LACP 協議的情況下才可以,可根據 L2, L3, L4 進行負載均衡。
  • stable(LACP):Attempts to always assign a given flow to the same slave consistently.

PS:LACP (Link Aggregation Control Protocol,鏈路聚合控制協議)。
在這里插入圖片描述
OvS 的 bond 模型:
在這里插入圖片描述

Port 與 QoS

OvS 中的 Qos 往往是和 Flow Policy 一起使用的。總所周知 QoS 有兩個方向,一個是入方向(Ingress),一個是出方向(Egress)。

在這里插入圖片描述

網絡流程 QoS 的實現原理與方式

在 Linux 上最常用的網絡 QoS 就是 TC 工具,其主要是通過 隊列 的方式來實現的。

1.Classless Queuing Disciplines:默認為 pfifo_fast,是一種不把網絡包分類的技術。pfifo_fast 根據網絡包中的 TOS 對應的數字,在 TOS 的 priomap 中查看對應的 Band,不同的 Band 對應的不同的隊列。

在這里插入圖片描述
在這里插入圖片描述
2. SFQ, Stochastic Fair Queuing:有很多的 FIFO 的隊列,TCP Session 或者 UDP stream 會被分配到某個隊列。包會 RoundRobin 的從各個隊列中取出發送。這樣一個 Session 就不會占據所有的流量。但不是每一個 Session 都具有一個隊列,而是通過 Hash 算法,將大量的 Session 分配到有限的隊列中。這樣兩個或若干個 Session 會共享一個隊列,也有可能互相影響。因此 Hash 函數會經常改變,從而 Session 不會總是相互影響。

在這里插入圖片描述
3. TBF, Token Bucket Filter:所有的網絡包排成隊列進行發送,但不是到了隊頭就能發送,而是需要拿到 Token 的包才能發送。Token 根據設定的速率(Rate)生成,所以即便隊列很長,也會按照 Rate 進行發送。當沒有包在隊列中時,Token 還是以既定的速度生成,但是並非無限累積,而是到 Buckets 放滿為止,籃子(buckets)的大小常用 burst/buffer/maxburst 參數來設定。Buckets 會避免下面這種情況:當長時間沒有包發送的時候,積累了大量的 Token,突然來了大量的包,每個都能得到 Token,造成瞬間流量大增。

在這里插入圖片描述
4. Classful Queuing Disciplines:其中典型的為 HTB, Hierarchical Token Bucket

  • Shaping:僅僅發生在葉子節點,依賴於其他的 Queue。
  • Borrowing:當網絡資源空閑的時候,借點過來為我所用。
  • Rate:設定的速率。
  • Ceil:最大的速率,與 Rate 之間的差值表示最多能向別人借多少。

在這里插入圖片描述

使用 TC 創建一個 HTB(Hierarchical Token Bucket)樹

在這里插入圖片描述

# 創建一個 HTB 的 qdisc 在 eth0 上,句柄為 1:,default 12 表示默認發送給 1:12。
tc qdisc add dev eth0 root handle 1: htb default 12

# 創建一個 root class,然后再創建幾個 sub class。
# 同一個 root class 下的 sub class 可以相互借流量,如果直接不在 qdisc下面創建一個 root class,而是直接創建三個 class,他們之間是不能相互借流量的。
tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps

# 創建葉子 qdisc,分別為 fifo 和 sfq。
tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5
tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5
tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10

# 設定規則:從 IP 1.2.3.4 來的並且發送給 port 80 的包,從 1:10 走;其他從 1.2.3.4 發送來的包從 1:11 走;其他的走默認。
# 實現了限速與分流。
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 match ip dport 80 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 flowid 1:11

實際上 OvS 能控制的只有 Egress QoS,通過 Shaping 實現。而 Ingress QoS 是無法控制的,只能通過 Policy 將指定的包丟棄。

Ingress policy

ovs-vsctl set Interface tap0 ingress_policing_rate=100000
ovs-vsctl set Interface tap0 ingress_policing_burst=10000

Egress shaping:Port QoS policy 僅支持 HTB。

  • 在 Port 上可以創建 QoS
  • 一個 QoS 可以有多個 Queue
  • 規則通過 Flow 設定

在這里插入圖片描述

Tunnel

OvS 支持三種隧道類型,這三種 Tunnel 的原理均在 《Networking 基礎術語/概念》中講過,不再贅述。

  • GRE
  • VxLAN
  • IPSec_gre

OvS Tunnel 的操作指令示例

# Instance1
ovs-vsctl add-br testbr
ifconfig testbr 10.0.0.1/24
ovs-vsctl add-port testbr gre0 -- set Interface gre0 type=gre options:local_ip=192.168.100.100 options:remote_ip=192.168.100.101
ovs-vsctl add-port testbr vxlan0 -- set Interface vxlan0 type=vxlan options:local_ip=192.168.100.100 options:remote_ip=192.168.100.102

# Instance2
ovs-vsctl add-br testbr
ifconfig testbr 10.0.0.2/24
ovs-vsctl add-port testbr gre0 -- set Interface gre0 type=gre options:local_ip=192.168.100.101 options:remote_ip=192.168.100.100
ovs-vsctl add-port testbr ipsec0 -- set Interface ipsec0 type=ipsec_gre options:local_ip=192.168.100.101 options:remote_ip=192.168.100.102 options:psk=password

# Instance3
ovs-vsctl add-br testbr
ifconfig testbr 10.0.0.3/24
ovs-vsctl add-port testbr vxlan0 -- set Interface vxlan0 type=vxlan options:local_ip=192.168.100.102 options:remote_ip=192.168.100.100
ovs-vsctl add-port testbr ipsec0 -- set Interface ipsec0 type=ipsec_gre options:local_ip=192.168.100.102 options:remote_ip=192.168.100.101 options:psk=password

# enable STP,避免環導致的洪泛(Flood)
# Spanning Tree Protocol,即通過協議,將一個有環的二層網絡變成一顆樹。
ovs-vsctl set Bridge testbr stp_enable=true

在這里插入圖片描述

Flow Table

Open vSwitch 定義了一系列的 Flow Table,通過這些 Tables 來控制網絡包的流向和結構。
在這里插入圖片描述
在這里插入圖片描述
根據 OpenFlow 協議,一行 Flow Entry 應該由兩部分組成:

  • Match Field
  • Action

如果數據包符合 Match 則執行 Action。
在這里插入圖片描述

Match Field 對網絡包進行解析,解析的內容涵蓋了 TCP/IP 協議族各層,具有下列字段,看這些字段是否能夠匹配某個值。
在這里插入圖片描述

  • Layer 1 – Tunnel ID, In Port, QoS priority, skb mark
  • Layer 2 – MAC address, VLAN ID, Ethernet type
  • Layer 3 – IPv4/IPv6 fields, ARP
  • Layer 4 – TCP/UDP, ICMP, ND

Action 主要包含下列操作:

  • Output to port (port range, flood, mirror)
  • Discard, Resubmit to table x
  • Packet Mangling (Push/Pop VLAN header, TOS, …)
  • Send to controller, Learn

常用流表操作指令

OvS 對 Flow Table 的管理,主要通過 ovs-ofctl 工具來完成:

# 查看 Bridge 的流表
ovs-ofctl show <bridge>
# 查詢指定 Bridge 的流表
ovs-ofctl dump-flows <bridge>
# 添加 Bridge 的流表
ovs-ofctl add−flow <bridge> <flow>
# e.g.
ovs-ofctl add-flow ovs_br dl_src=02:a2:a2:a2:a2:a2,dl_dst=02:b2:b2:b2:b2:b2,in_port=2,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2,actions=output:6
# 修改 Bridge 的流表
ovs-ofctl mod−flows <bridge> <flow>
# 刪除 Bridge 的指定流表
ovs-ofctl del−flows <bridge> <flow>
# e.g.
ovs-ofctl del-flows <bridge> dl_src=02:a2:a2:a2:a2:a2,dl_dst=02:b2:b2:b2:b2:b2,in_port=2,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2
# 刪除 Bridge 的所有流表
ovs-ofctl del-flows <bridge>   # This will delete all the flow entries in the flow table

參考文檔

https://www.cnblogs.com/popsuper1982/p/3800576.html
https://blog.csdn.net/w0823m/article/details/71319973
https://blog.csdn.net/tantexian/article/details/46707175


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM