1. 程式人生 > >Neutron 理解 (4): Neutron OVS OpenFlow 流表 和 L2 Population [Netruon OVS OpenFlow tables + L2 Population]

Neutron 理解 (4): Neutron OVS OpenFlow 流表 和 L2 Population [Netruon OVS OpenFlow tables + L2 Population]

學習 Neutron 系列文章:

      OVS bridge 有兩種模式:“normal” 和 “flow”。“normal” 模式的 bridge 同普通的 Linux 橋,而 “flow” 模式的 bridge 是根據其流表(flow tables) 來進行轉發的。Neutron 使用兩種 OVS bridge:br-int 和 br-tun。其中,br-int 是一個 “normal” 模式的虛擬網橋,而 br-tun 是 “flow” 模式的,它比 br-int 複雜得多。

1. 基礎知識

1.1 OpenFlow 結構、流表和資料包處理

下面左圖是 Open vSwitch 中流表的結構。右圖這個流程圖詳細描述了資料包流通過一個 OpenFlow 交換機的過程。

                              

更詳細的描述請參見這裡

1.2 ARP Proxy

Proxy ARP 就是通過一個主機(通常是Router)來作為指定的裝置對另一個裝置作出 ARP 的請求進行應答。

舉個例子:主機A,IP地址是192.168.0.11/24;主機B,IP地址是192.168.1.22/24。主機A和主機B通過路由器R相連線,並且路由器R啟用了Proxy ARP,並配置有路由。網路拓撲如下:      eth0                eth0       eth1                        eth0     A------------------------Router R----------------------B 192.168.0.11/24   192.168.0.0/24 eth0      192.168.1.22/24                              192.168.1.0/24 eth1     在主機A上執行:ping 192.168.1.22,主機 A 不知道主機 B 的 MAC 地址是多少,首先要傳送 ARP 查詢報文,路由器 R 接收到主機 A 發出的 ARP 查詢報文,並代替主機 B 作出應答,應答 ARP 報文中填入的就是路由器 R 的MAC地址。這樣,主機A就會認為路由器R的地址是192.168.1.22。以後所有發往192.168.1.22的報文都發到路由器R,路由器R再根據已配置好的路由表將報文轉發給主機B。   這樣做的好處就是,主機A上不需要設定任何預設閘道器或路由策略,不管路由器R的IP地址怎麼變化,主機A都能通過路由器B到達主機B,也就是實現了所謂的透明代理。相反,若主機A上設定有預設閘道器或路由策略時,當主機A向192.168.1.22傳送報文,首先要查詢路由表,而主機A所在的網段是192.168.0.0/24,主機B所在網段是192.168.1.0/24,主機A只能通過預設閘道器將報文傳送出去,這樣代理ARP也就失去了作用。 優點

最主要的一個優點就是能夠在不影響其他router的路由表的情況下在網路上新增一個新的router,這樣使得子網的變化對主機是透明的。

proxy ARP應該使用在主機沒有配置預設閘道器或沒有任何路由策略的網路上 

缺點
  1.增加了某一網段上 ARP 流量
  2.主機需要更大的 ARP table 來處理IP地址到MAC地址的對映
  3.安全問題,比如 ARP 欺騙(spoofing)
  4.不會為不使用 ARP 來解析地址的網路工作
  5.不能夠概括和推廣網路拓撲

來源:百度百科

2. 不使用 ARP Responder 和 DVR 時 br-tun 中的流表(flow tables)

OpenStack 中,Neutron 作為 OVS 的 Controller,向 OVS 發出管理 tunnel port 的指令,以及提供流表。

2.1 流表分析

  Neutron 定義了多種流表。以下面的配置(配置了 GRE 和 VXLAN 兩種 tunnel types)為例:

1(patch-int): addr:a6:d4:dd:37:00:52
2(vxlan-0a000127): addr:36:ec:de:b4:b9:6b {in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.39"} 計算節點2
3(vxlan-0a000115): addr:4a:c8:21:3c:3f:f1 {in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.21"} 網路節點
4(gre-0a000115): addr:4a:8b:0f:9d:59:52  {in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.21"} 網路節點
5(gre-0a000127): addr:aa:58:6d:0a:f7:6a  {in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.39"} 計算節點2

其中,10.0.1.31 是計算節點1, 10.0.1.21 是網路節點, 10.0.1.39 是計算節點2。

計算節點1 上 ML2 Agent 啟動後的 br-tun 的 flows:

表號 用途 例子
0

table=0, priority=1,in_port=3 actions=resubmit(,4) //從網路節點來的,轉 4,結果被丟棄

table=0, priority=1,in_port=4 actions=resubmit(,3) //從網路節點來的,轉 3


table=0, priority=1,in_port=5 actions=resubmit(,3) //從計算節點來的,轉 3

table=0, priority=1,in_port=2 actions=resubmit(,4) //從計算節點來的,轉 4,結果被丟棄

table=0, priority=1,in_port=1 actions=resubmit(,2) //從虛機來的,轉 2

table=0, priority=0 actions=drop //其餘的丟棄

DVR_PROCESS = 1 handle packets coming from patch_int unicasts go to table UCAST_TO_TUN where remote addresses are learnt  用於 DVR
PATCH_LV_TO_TUN = 2

table=2, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20) //單播包,轉 20
table=2, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22) //組播(包括廣播)包,轉 22

GRE_TUN_TO_LV = 3

table=3, priority=1,tun_id=0x4 actions=mod_vlan_vid:1,resubmit(,10) //將 tun_id 為 4 的,修改 vlan id 為1,轉 10 處理
table=3, priority=0 actions=drop //其餘的丟棄

VXLAN_TUN_TO_LV = 4 table=4, priority=0 actions=drop //丟棄
DVR_NOT_LEARN = 9  用於 DVR
LEARN_FROM_TUN = 10  學習table

table=10,priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1

UCAST_TO_TUN = 20  
外出的單播會被 table 20 處理,table 2

//學習到的規則

table=20, priority=2,dl_vlan=1,dl_dst=fa:16:3e:7e:ab:cc actions=strip_vlan,set_tunnel:0x3e9,output:5 //如果vlan 為1,而且目的MAC地址等於 fa:16:3e:7e:ab:cc,設定 tunnel id,從埠 5 發出

table=20,priority=0 actions=resubmit(,22) //直接轉 22

ARP_RESPONDER = 21  ARP table  當使用 arp_responder 和 l2population 時候用到
FLOOD_TO_TUN  = 22  Flood table

table=22,dl_vlan=1 actions=strip_vlan,set_tunnel:0x4,output:5,output:4 //對於 dl_vlan 為1的,設定 tunnel id 為 4,從埠4 和 5 轉出
table=22,priority=0 actions=drop

來個圖簡單些:

其中比較有意思的是:

(1)為什麼從 VXLAN 過來的流量都被丟棄了,最後發出去也用的是 GRE 埠。看來同時有 GRE 和 VXLAN 隧道的話,OVS 只會選擇 GRE。具體原因待查。

(2)MAC 地址學習:Table 10 會將學習到的規則(Local VLAN id + Src MAC Addr => IN_Port)放到 table 20。當表格20 發現一個單播地址是已知的時候,直接從一個特定的 GRE 埠發出;未知的話,視同組播地址從所有 GRE 埠發出。

2.2 MAC 地址學習

學習規則:

table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]

這語法不是很好理解,這裡 有詳細解釋。

  • table=20:修改 table 20。這是個 MAC 學習流表。
  • hard_timeout:該 flow 的過期時間。
  • NXM_OF_VLAN_TCI[0..11] :記錄 vlan tag,所以學習結果中有 dl_vlan=1

  • NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[] :將 mac source address 記錄,所以結果中有 dl_dst=fa:16:3e:7e:ab:cc

  • load:0->NXM_OF_VLAN_TCI[]:在傳送出去的時候,vlan tag設為0,所以結果中有 actions=strip_vlan

  • load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[] :發出去的時候,設定 tunnul id,所以結果中有set_tunnel:0x3e9

  • output:NXM_OF_IN_PORT[]:指定傳送給哪個port,由於是從 port2 進來的,因而結果中有output:2。

學到的規則:

table=20, n_packets=1239, n_bytes=83620, idle_age=735, hard_age=65534, priority=2,dl_vlan=1,dl_dst=fa:16:3e:7e:ab:cc actions=strip_vlan,set_tunnel:0x3e9,output:2 

這裡可以看到,通過 MAC 地址學習機制,Neutron 可以一定程度地優化網路流向,但是這種機制需要等待從別的節點的流量進來,只能算是一種被動的機制,效率不高。而且,這種機制只對單播幀有效,而對於多播和組播依然無效。其結果是網路成本依然很高。下圖中,A 的廣播包其實只對 3 和 4 有用,但是 2 和 5 也收到了。

3. ARP Responder

    arp_responder 的原理不復雜。Neutorn DB 中儲存了所有的埠的 MAC 和 IP 地址資料。而 ARP 就是一個虛機要根據另一個虛機的 IP 地址查詢它的 MAC。因此,只需要 Neutron server 通過 RPC 告訴每個計算節點上的 ML2 agent 所有活動埠的 MAC 和 IP,那麼就可以將 br-tun 變成一個供本機適用的 ARP Proxy,這樣本機上的虛機的 ARP 請求的響應就可以由 br-tun 在本地解決。Assaf Meller 有篇文章來闡述 ARP Responder。

  使用 ARP Responder 需要滿足兩個條件:

(1)設定 arp_responder = true 來使用 OVS 的ARP 處理能力 。這需要 OVS 2.1 (執行 ovs-vswitchd --version 來檢視 OVS 版本) 和 ML2 l2population 驅動的支援。當使用隧道方式的時候,OVS 可以處理一個 ARP 請求而不是使用廣播機制。如果 OVS 版本不夠的話,Neutorn 是無法設定 arp responder entry 的,你會在 openvswitch agent 日誌中看到 “Stderr: '2015-07-11T04:57:32Z|00001|meta_flow|WARN|destination field arp_op is not writable\novs-ofctl: -:2: actions are invalid with specified match (OFPBAC_BAD_SET_ARGUMENT)\n'”這樣的錯誤,你也就不會在 ”ovs-ofctl dump-flows br-tun“ 命令的輸出中看到相應的 ARP Responder 條目了。

(2)設定 l2_population = true。同時新增 mechanism_drivers = openvswitch,l2population。OVS 需要 Neutron 作為 SDN Controller 向其輸入 ARP Table flows。

3.1 升級 OVS

殺掉 neutron openvswitch, ovs-* 各種程序

#編譯安裝

去 http://openvswitch.org/download/ 下載最新版本的程式碼,解壓,進入解壓後的目錄

安裝依賴包,比如 gcc,make

uname -r

./configure --with-linux=/lib/modules/3.13.0-51-generic/build

make && make install

#檢視安裝的版本

[email protected]:/home/s1# ovs-vsctl --version
ovs-vsctl (Open vSwitch) 2.3.2
Compiled Jul 12 2015 09:09:42
DB Schema 7.6.2

#處理 db

rm /etc/openvswitch/conf.db (老的db要刪除掉,否則會報錯)

ovsdb-tool create /etc/openvswitch/conf.db vswitchd/vswitch.ovsschema

#啟動 ovs

cp /usr/local/bin/ovs-* /usr/bin

ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/usr/local/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:/usr/local/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

#啟動 neutron openvswitch agent,確保log 檔案中 ovs-vsctl 和 ovs-ofctl 呼叫沒有錯誤

#修改 /usr/share/openvswitch/scripts/ovs-lib 檔案,保證機器重啟後 OVS 正常執行

將 rundir=${OVS_RUNDIR-'/var/run/openvswitch'} 改為 rundir=${OVS_RUNDIR-'/usr/local/var/run/openvswitch'}

3.2 ARP Responder

有了 arp_responder 以後,br-tun 的流表增加了幾項和處理:

(1)table 2 中增加一條 flow,是的從本地虛機來的 ARP 廣播幀轉到table 21

# ARP broadcast-ed request go to the local ARP_RESPONDER table to be locally resolved
table=2, n_packets=0, n_bytes=0, idle_age=3, priority=1,arp,dl_dst=ff:ff:ff:ff:ff:ff actions=resubmit(,21)

(2)在 table 21 中增加一條 flow 將其發發往 table 22

# If none of the ARP entries correspond to the requested IP, the broadcast-ed packet is resubmitted to the flooding table
table=21, n_packets=0, n_bytes=0, idle_age=4, priority=0 actions=resubmit(,22)

如果下面第 (3)步增加的 flow rule 都處理不了這條 request,那麼轉到table 22 去 flood 到所有埠。

(3)由 L2 population 發來的 entry 來更新 table 21。

  table 21 是在新的 l2pop 地址進來的時候更新的。比如說,compute C 上增加了新的虛機 VM3,然後計算節點 A 和 B 收到一條 l2pop 訊息說 VM3 (IP 是***,MAC 是 ***) 在 Host C 上,在 network "Z“ 中。然後,Compute A 和 B 會在 table 21 中增加相應的 flows。   

  br.add_flow(table=21, priority=1, proto='arp', dl_vlan=local_vid, nw_dst= ip, actions=actions)

    其中action為: (好晦澀,這是誰定義的奇葩語法。。幸好 這裡 有詳細解釋)

ARP_RESPONDER_ACTIONS = ('move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],'
'mod_dl_src:%(mac)s,'
'load:0x2->NXM_OF_ARP_OP[],'
'move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],'
'move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],'
'load:%(mac)#x->NXM_NX_ARP_SHA[],'
'load:%(ip)#x->NXM_OF_ARP_SPA[],'
'in_port')

(4)table 21 的處理過程

     table 21 中的每一條 flow,會和進來的幀的資料做匹配(ARP 協議,network,虛機的 IP)。如果匹配成功,則構造一個 ARP 響應包,其中包括了 IP 和 MAC,從原來的 port 發回到虛機。如果沒有吻合的,那麼轉發到 table 22 做泛洪。

增加的 flow tables 在紅色部分:

     因此,通過使用 l2-pop mechanism driver 和 OVS 2.1, Neutorn 可以在本地回答虛機的 ARP 請求,從而避免了昂貴的 ARP 廣播。這個功能給 GRE 和  VXLAN 的實現是在 Juno 版本中完成的。 這個 blueprint 似乎在支援VLAN 中的這個功能,但是看起來沒有完成。

4. L2 population

根據這篇文件,l2pop 目前支援 VXLAN with Linux bridge 和 GRE/VXLAN with OVS,其 blueprint 在這裡

4.1 原理

    l2pop 的原理也不復雜。Neutron 中儲存每一個埠的狀態,而埠儲存了網路相關的資料。虛機啟動過程中,其埠狀態會從 down 到build 到 active。因此,在每次埠發生狀態變化時,函式 update_port_postcommit  都將會被呼叫:

{'status': 'DOWN/BUILD/ACTIVE', 'binding:host_id': u'compute1', 'allowed_address_pairs': [], 'extra_dhcp_opts': [], 'device_owner': u'compute:nova', 'binding:profile': {}, 'fixed_ips': [{'subnet_id': u'4ec65731-35a5-4637-a59b-a9f2932099f1', 'ip_address': u'81.1.180.15'}], 'id': u'1167e9ac-e10f-4cf5-bd09-6649eab38b32', 'security_groups': [u'f5377a66-803d-481b-b4c3-a6631e8ab456'], 'device_id': u'30580ea7-c456-416b-a01e-0fe645edf5dc', 'name': u'', 'admin_state_up': True, 'network_id': u'86c0d29b-4880-4739-bd68-eb3c392f5099', 'tenant_id': u'74c8ada23a3449f888d9e19b76d13aab', 'binding:vif_details': {u'port_filter': True, u'ovs_hybrid_plug': True}, 'binding:vnic_type': u'normal', 'binding:vif_type': u'ovs', 'mac_address': u'fa:16:3e:4f:59:9d'} 

    在某些狀態變化下: 

  • update_port_postcommit (down to active) -> _update_port_up -> add_fdb_entries -> fdb_add -> fdb_add_tun -> setup_tunnel_port  (如果 tunnel port 不存在,則建立 tunnel port), add_fdb_flow -> add FLOOD_TO_TUN flow (如果是 Flood port,則將埠新增到 Flood output ports); setup_entry_for_arp_reply('add'。如果不是 Flood port,那麼 新增 ARP Responder entry (MAC -> IP)) 以及 add UCAST_TO_TUN flow Unicast Flow entry (MAC -> Tunnel port number)。
  • update_port_postcommit (active to down) -> _update_port_down -> remove_fdb_entries
  • delete_port_postcommit (active to down) -> _update_port_down -> remove_fdb_entries -> fdb_remove -> fdb_remove_tun -> cleanup_tunnel_port, del_fdb_flow -> mod/del FLOOD_TO_TUN flow; setup_entry_for_arp_reply ('remove'), delete UCAST_TO_TUN flow
  • update_port_postcommit (fixed ip changed) -> _fixed_ips_changed -> update_fdb_entries

    通過這種機制,每個節點上的如下資料得到了實時更新,從而避免了不必要的隧道連線和廣播。

  • Tunnel port
  • FLOOD_TO_TUN (table 22)flow
  • ARP responder flow
  • UCAST_TO_TUN (table 20) flow

有和沒有 l2pop 的效果:

4.2 過程實驗

1. def tunnel_sync(self) 函式除了上報自己的 local_ip 外不再自己見 tunnels,一切等 l2pop 的通知。

2. 在 compute1 上新增第一個虛機 81.1.180.8

neutron-server:

  • 通知 compute1:{'segment_id': 6L, 'ports': {u'10.0.1.21': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:87:40:f3', u'81.1.180.1']]}, 'network_type': u'gre'}}
  • 通知所有 agent: {'segment_id': 6L, 'ports': {u'10.0.1.31': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:b3:e7:7a', u'81.1.180.8']]}, 'network_type': u'gre'}} 

compute1:

  • 新增和網路節點的tunnel options: {df_default="true", in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.21"}
  • 新增到網段閘道器的 Unicast flow:table=20, n_packets=0, n_bytes=0, idle_age=130, priority=2,dl_vlan=2,dl_dst=fa:16:3e:87:40:f3 actions=strip_vlan,set_tunnel:0x6,output:4
  • 增加網段 81.1.180.1 閘道器的 ARP flows:table=21, n_packets=0, n_bytes=0, idle_age=130, priority=1,arp,dl_vlan=2,arp_tpa=81.1.180.1 actions=move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],mod_dl_src:fa:16:3e:87:40:f3,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],load:0xfa163e8740f3->NXM_NX_ARP_SHA[],load:0x5101b401->NXM_OF_ARP_SPA[],IN_PORT
  • 修改 Flood flow

compute 2 節點:因為它上面還沒有執行虛機,所以不做操作。

3. 在 compute 2 上新增一個虛機 81.1.180.9

neutron server:

  • 通知 compute 2 : {'segment_id': 6L, 'ports': {u'10.0.1.31': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:b3:e7:7a', u'81.1.180.8']], u'10.0.1.21': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:87:40:f3', u'81.1.180.1']]}, 'network_type': u'gre'}}
  • 通知所有 agent: {'segment_id': 6L, 'ports': {u'10.0.1.39': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:73:49:41', u'81.1.180.9']]}, 'network_type': u'gre'}

compute1:

  • 建立 tunnel(ID 5):  {df_default="true", in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.39"}
  • 增加 arp responder flow(compute2 上新的虛機 IP -> MAC):table=21, n_packets=0, n_bytes=0, idle_age=79, priority=1,arp,dl_vlan=2,arp_tpa=81.1.180.9 actions=move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],mod_dl_src:fa:16:3e:73:49:41,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],load:0xfa163e734941->NXM_NX_ARP_SHA[],load:0x5101b409->NXM_OF_ARP_SPA[],IN_PORT
  • 增加 unicast flow (新虛機的 MAC -> Tunnel port):table=20, n_packets=0, n_bytes=0, idle_age=79, priority=2,dl_vlan=2,dl_dst=fa:16:3e:73:49:41 actions=strip_vlan,set_tunnel:0x6,output:5
  • 新增新的 Tunnel port 到 Flood flow:table=22, n_packets=13, n_bytes=1717, idle_age=255, hard_age=78, dl_vlan=2 actions=strip_vlan,set_tunnel:0x6,output:5,output:4

compute2:

  • 建立和計算節點以及compute1的tunnel:options: {df_default="true", in_key=flow, local_ip="10.0.1.39", out_key=flow, remote_ip="10.0.1.21"},options: {df_default="true", in_key=flow, local_ip="10.0.1.39", out_key=flow, remote_ip="10.0.1.31"}
  • 增加 ARP flow(compute 1 上的虛機的 MAC -> IP):table=21, n_packets=0, n_bytes=0, idle_age=268, priority=1,arp,dl_vlan=2,arp_tpa=81.1.180.8 actions=move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],mod_dl_src:fa:16:3e:b3:e7:7a,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],load:0xfa163eb3e77a->NXM_NX_ARP_SHA[],load:0x5101b408->NXM_OF_ARP_SPA[],IN_PORT
  • 增加 Unicast flow (compute 1 上的虛機 MAC -> Tunnel port):table=20, n_packets=0, n_bytes=0, idle_age=268, priority=2,dl_vlan=2,dl_dst=fa:16:3e:b3:e7:7a actions=strip_vlan,set_tunnel:0x6,output:4
  • 增加 ARP flow(新虛機的閘道器的 MAC -> IP) table=21, n_packets=0, n_bytes=0, idle_age=268, priority=1,arp,dl_vlan=2,arp_tpa=81.1.180.1 actions=move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],mod_dl_src:fa:16:3e:87:40:f3,load:0x2->NXM_OF_ARP_OP[],move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],load:0xfa163e8740f3->NXM_NX_ARP_SHA[],load:0x5101b401->NXM_OF_ARP_SPA[],IN_PORT

  • 修改 Flood flow(新增到 Compute 1 的 port):table=22, n_packets=13, n_bytes=1717, idle_age=128, dl_vlan=2 actions=strip_vlan,set_tunnel:0x6,output:5,output:4

3. 刪除 compute1 上的一個vm(也是唯一的一個)

neutron server:

  • 通知所有 agent: {'segment_id': 6L, 'ports': {u'10.0.1.31': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:b3:e7:7a', u'81.1.180.8']]}, 'network_type': u'gre'}

compute 1:

  • 因為沒有別的虛機了,刪除所有 tunnel ports
  • 修改或者刪除 ARP, Unicast 和 Flood flows

compute 2:

  • 刪除了 compute1 的 tunnel
  • 刪除該虛機對應的 ARP flow

 4. 在 compute1 上建立第一個不同網路的虛機

neutron server:

  • 通知 compute 1: {u'e2022937-ec2a-467a-8cf1-f642a3f777b6': {'segment_id': 4L, 'ports': {u'10.0.1.21': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:90:e5:50', u'91.1.180.1'], [u'fa:16:3e:17:c9:26', u'90.1.180.1'], [u'fa:16:3e:69:92:30', u'90.1.180.3'], [u'fa:16:3e:69:92:30', u'91.1.180.2']]}, 'network_type': u'gre'}}
  • 通知所有 agent:{u'e2022937-ec2a-467a-8cf1-f642a3f777b6': {'segment_id': 4L, 'ports': {u'10.0.1.31': [['00:00:00:00:00:00', '0.0.0.0'], [u'fa:16:3e:e9:ee:0c', u'91.1.180.9']]}, 'network_type': u'gre'}}

compute 1:建立和網路節點的 tunnel port;更新 Flood flows;新增 ARP flows

compute 2:沒什麼action,因為該節點上沒有新建虛機的網路內的虛機

過程的大概說明:

  • 虛機在收到 fannout FDB entries 後,檢查其中每個 port 的 network_id(即 “segment_id”)。如果本機上有該 network 內的 port,那麼就處理 entries 中的 “ports”部分;否則,不處理該 entries。
  • 因此,當計算節點上沒有執行任何虛機時,不會建立任何 tunnel。如果兩個虛機上有相同網路內的虛機,那麼建立會建立 tunnel。
  • 這種機制能實時建立 tunnel port,Flood entry (建立 Tunnel port 同時新增到 Flood output ports 列表), Unicast flow (虛機和閘道器 MAC -> Tunnel port) 和 ARP Responder entry  (虛機和閘道器 MAC -> IP)。下圖中的藍色部分的流表都會被及時更新。
  • Neutron server 在埠建立/刪除/修改時,如果是該節點上的第一個虛機,首先發送直接訊息;然後發通知訊息給所有的計算和網路節點。

4.3 效能

4.3.1 MQ 效能問題

    應該說 l2pop 的原理和實現都很直接,但是在大規模部署環境中,這種通知機制(通知所有的 ML2 Agent 節點)可能會給 MQ 造成很大的負擔。一旦 MQ 不能及時處理訊息,虛機之間的網路將受到影響。下面是 l2pop 中通知機制程式碼: 

def __init__(self, topic=topics.AGENT):
        super(L2populationAgentNotifyAPI, self).__init__(
            topic=topic, default_version=self.BASE_RPC_API_VERSION)
        self.topic_l2pop_update = topics.get_topic_name(topic, topics.L2POPULATION, topics.UPDATE)

    def _notification_fanout(self, context, method, fdb_entries):
        self.fanout_cast(context, self.make_msg(method, fdb_entries=fdb_entries), topic=self.topic_l2pop_update)

    def _notification_host(self, context, method, fdb_entries, host):
        self.cast(context, self.make_msg(method, fdb_entries=fdb_entries), topic='%s.%s' % (self.topic_l2pop_update, host))

    def add_fdb_entries(self, context, fdb_entries, host=None):
        if fdb_entries:
            if host:
                self._notification_host(context, 'add_fdb_entries',fdb_entries, host) #cast 給指定 host
            else: 
                self._notification_fanout(context, 'add_fdb_entries', fdb_entries) #fanout 給所有計算和網路節點

    這段程式碼是說,l2pop 採用的 MQ topic 是 “L2POPULATION”,訊息通知採用 fanout 或者 cast 機制。如果是 fanout 的話,訊息將發到所有的 ML2 agent 節點。這樣的話,其覆蓋面就有些過於廣泛了,就這個問題有人提了一個 ticket,官方答覆是 work as design,要改的話只能是新增 new feature 了。

4.3.2 大規模網路環境中節點上的 OpenFlow flows 過多

    不知道這個數目有沒有上限?數目很多的情況下會不會有效能問題?OVS 有沒有處理能力上限?這些問題也許得在實際的生產環境中才能得到證實和答案。

歡迎大家關注我的個人公眾號:

相關推薦

Neutron 理解 (4): Neutron OVS OpenFlow L2 Population [Netruon OVS OpenFlow tables + L2 Population]

學習 Neutron 系列文章:       OVS bridge 有兩種模式:“normal” 和 “flow”。“normal” 模式的 bridge 同普通的 Linux 橋,而 “flow” 模式的 bridge 是根據其流表(flow tab

理解OpenShift(1):網路之 Router Route Neutron 理解 (7): Neutron 是如何實現負載均衡器虛擬化的

 理解OpenShift(1):網路之Router 和 Route   1. OpenShift 為什麼需要 Router 和 Route? 顧名思義,Router 是路由器,Route 是路由器中配置的路由。OpenShift 中的這兩個概念是為了解決從叢集外部(就是從除了叢集節點

Neutron 理解 (6): Neutron 是怎麼實現虛擬三層網路的 [How Neutron implements virtual L3 network]

學習 Neutron 系列文章:     Neutron 對虛擬三層網路的實現是通過其 L3 Agent (neutron-l3-agent)。該 Agent 利用 Linux IP 棧、route 和 iptables 來實現內網內不同網路內的虛機之間的網路流量

Neutron 理解 (1): Neutron 所實現的網路虛擬化 [How Neutron Virtualizes Network]

學習 Neutron 系列文章:  1. 為什麼要網路虛擬化? 個人認為,這裡主要有兩個需求:一個是資料中心的現有網路不能滿足雲端計算的物理需求;另一個是資料中心的現有網路不能滿足雲端計算的軟體化即SDN要求。 1.1 現有物理網路不能

Neutron 理解 (8): Neutron 是如何實現虛機防火牆的 [How Neutron Implements Security Group]

學習 Neutron 系列文章: 1. 基礎知識 1.1 防火牆(firewall)     防火牆是依照特定的規則來控制進出它的網路流量的網路安全系統。一個典型的場景是在一個受信任的內網和不受信任的外網比如 Internet 之間建立一個屏障。防火牆

openflow分析(草稿)

OVS bridge 有兩種模式:“normal” 和 “flow”。“normal” 模式的 bridge 同普通的 Linux 橋,而 “flow” 模式的 bridge 是根據其流表(flow tables) 來進行轉發的。Neutron 使用兩種 OVS bridge:br-int 和 br-tun。

Neutron 理解 (7): Neutron 是如何實現負載均衡器虛擬化的 [LBaaS V1 in Juno]

學習 Neutron 系列文章: 1. 基礎知識 1.1 負載均衡的概念   負載均衡(Load Balancing)是將來訪的網路流量在執行相同應用的多個伺服器之間進行分發的一種核心網路服務。它的功能由負載均衡器(load balancer)提供。負

Neutron 理解 (1): Neutron 所實現的虛擬化網路 [How Netruon Virtualizes Network]

1. 為什麼要網路虛擬化? 個人認為,這裡主要有兩個需求:一個是資料中心的現有網路不能滿足雲端計算的物理需求;另一個是資料中心的現有網路不能滿足雲端計算的軟體化即SDN要求。 1.1 現有物理網路不能滿足雲端計算的需求     網際網路行業資料中心的基本特徵就是伺服

openvswitch--OpenFlow 設定

流規則組成 每條流規則由一系列欄位組成,分為基本欄位、條件欄位和動作欄位三部分: 基本欄位包括生效時間duration_sec、所屬表項table_id、優先順序priority、處理的資料包數n_packets,空閒超時時間idle_timeout等

openflow項中有關ip掩碼的匹配的問題(控制器為ryu)

一.寫在前面   唉,被分配到sdn安全方向,頂不住,頂不住,感覺搞不出來什麼有搞頭的東西。可若是讓我水水的應付,我想我也是做不到的,世上無難事只怕有心人。好了,進入正題,本次要討論的時一個比較細節的東西,在流表項中的有關ip掩碼的問題。對了,本文適合於,有一定基礎的openflow使用者,一點點就行。 二、

4.SQL--創建成績內插入數據

.sql insert ima tab creat arch eat core into --創建成績表,並向表內插入數據create table SC(Scid varchar(10),Cid varchar(10),score decimal(18,1))--向表內插入

Open vSwitch(OvS)原始碼分析之工作流程(flow查詢)

前面分析了Open vSwitch幾部分原始碼,對於Open vSwitch也有了個大概的理解,今天要分析的程式碼將是整個Open vSwitch的重中之重。整個Open vSwitch的核心程式碼在datapath檔案中;而datapath檔案中的核心程式碼又在ovs_dp_process_re

Neutron 理解 (9): OpenStack 是如何實現 Neutron 網路 Nova虛機 防火牆的 [How Nova Implements Security Group and How Neutron Implements Virtua

學習 Neutron 系列文章: 1. Nova 安全組 1.1 配置 節點 配置檔案 配置項 說明 controller  /etc/nova/nova.conf security_group_api =

Neutron 理解 (3): Open vSwitch + GRE/VxLAN 組網 [Netruon Open vSwitch + GRE/VxLAN Virutal Network]

學習 Neutron 系列文章:     目前,OpenStack Neutron 支援使用兩種隧道網路技術 通用路由封裝(GRE) 和 VxLAN 來實現虛擬的二層網路。這兩種技術大致看起來非常相似,都是需要使用 OpenStack 在計算和網路節點

Neutron 理解 (2): 使用 Open vSwitch + VLAN 組網 [Neutron Open vSwitch + VLAN Virtual Network]

學習 Neutron 系列文章: 1. L2 基礎知識 1.1 VLAN 基礎知識 1.1.1 VLAN 的含義    LAN 表示 Local Area Network,本地區域網,通常使用 Hub 和 Switch 來連線LAN 中的計算機。一般

Neutron 理解(14):Neutron ML2 + Linux bridge + VxLAN 組網

學習 Neutron 系列文章: 1. 基礎知識 1.1 VXLAN 和 Linux 以及 Linux bridge 的關係     VXLAN 是一個新興的SDN 標準,它定義了一種新的 overlay 網路,它主要的創造者是 VMware,

理解Java中字符與字節流的區別

png 技術 print 復制代碼 bar 顯式 數字 length ava 1. 什麽是流 Java中的流是對字節序列的抽象,我們可以想象有一個水管,只不過現在流動在水管中的不再是水,而是字節序列。和水流一樣,Java中的流也具有一個“流動的方向”,通常可以從中讀

Python 基礎 - Day 4 Assignment - 員工信息程序

mic 基礎 程序 soft 滿足 strong href 需求 pan 作業要求及初步思路 員工信息表程序,實現增刪改查操作: ① 可進行模糊查詢,語法至少支持下面3種: select name,age from staff_table where age > 2

在STM32上實現NTFS之4:GPT分區的C語言實現(1):主GPT表頭的實現

center mbr分區 sum 對齊 字節數 決定 容器 alt 水平 題外話:在荒廢了很久沒有更新之後……某日突然收到讀者的站內信!內容大體是詢問GPT分區表信息的讀取方式,筆者激動萬分之下,決定繼續解剖NTFS……其實GPT嚴格上不算是NTFS的內容, GPT和M

圖論4——探索網絡的足跡:Dinic算法

sizeof 思想 png 概念 算法 如何 IT clu 百度 1. 網絡流:定義與簡析 1.1 網絡流是什麽? 網絡流是一種“類比水流的解決問題方法,與線性規劃密切相關”(語出百度百科)。 其實,在信息學競賽中,簡單的網絡流並不需要太高深的數學知識。 首先我們需要知道一