Run P4 without P4factory - A Simple Example In Tutorials. -2
Reference:Github-Tutorial Exercise 2: Implementing TCP flowlet switching
實驗準備:
參考之前的博客:Run P4 without P4factory - A Simple Example In Tutorials.
由于本次實驗在初始階段大部分內容已經完成,所以貼出幾個關鍵文件的內容。
command.txt(無需改動)
table_set_default ecmp_group _drop table_set_default ecmp_nhop _drop table_set_default forward _drop table_set_default send_frame _drop table_add ecmp_group set_ecmp_select 10.0.0.1/32 => 0 2 table_add ecmp_nhop set_nhop 0 => 10.0.1.1 1 table_add ecmp_nhop set_nhop 1 => 10.0.2.1 2 table_add forward set_dmac 10.0.1.1 => 00:04:00:00:00:00 table_add forward set_dmac 10.0.2.1 => 00:04:00:00:00:01 table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00 table_add send_frame rewrite_mac 2 => 00:aa:bb:00:00:01env.sh(其中bmv2和p4c-bm修改為自己的路徑)
拷貝到目錄:/home/wasdns/tutorials/SIGCOMM_2015/flowlet_switching
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )# ---------------- EDIT THIS ------------------ BMV2_PATH=/home/wasdns/bmv2 # e.g. BMV2_PATH=$THIS_DIR/../bmv2 P4C_BM_PATH=/home/wasdns/p4c-bmv2 # e.g P4C_BM_PATH=$THIS_DIR/../p4c-bm # ---------------- END ------------------run_demo.sh(修改路徑)
#!/bin/bash# Copyright 2013-present Barefoot Networks, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )source $THIS_DIR/env.shP4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.pySWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switchCLI_PATH=$BMV2_PATH/tools/runtime_CLI.py# Probably not very elegant but it works nice here: we enable interactive mode # to be able to use fg. We start the switch in the background, sleep for 2 # minutes to give it time to start, then add the entries and put the switch # process back in the foreground set -m $P4C_BM_SCRIPT p4src/simple_router.p4 --json simple_router.json # This gets root permissions, and gives libtool the opportunity to "warm-up" sudo $SWITCH_PATH >/dev/null 2>&1 sudo $SWITCH_PATH simple_router.json \-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \--nanolog ipc:///tmp/bm-0-log.ipc \--pcap & sleep 2 $CLI_PATH --json simple_router.json < commands.txt echo "READY!!!" fg實驗過程:
實驗中運行的交換機如圖所示:
--------------------------------- nhop-0 10.0.1.1| 00:04:00:00:00:001 - 00:aa:bb:00:00:00| -------- 3--sw|2 - 00:aa:bb:00:00:01|--------------------------------- nhop-1 10.0.2.100:04:00:00:00:01第一部分
原理
使用的P4程序(詳細的代碼:->Github),關鍵部分:
field_list l3_hash_fields {ipv4.srcAddr;ipv4.dstAddr;ipv4.protocol;tcp.srcPort;tcp.dstPort; }field_list_calculation ecmp_hash {input {l3_hash_fields;}algorithm : crc16;output_width : ECMP_BIT_WIDTH; }可以看到,采用的是簡單的五元組匹配進行路徑和端口的選擇,實現簡單的ECMP - flowlet switching。
Github中的介紹:
Flowlet switching leverages the burstiness of TCP flows to achieve better load balancing of TCP traffic. In this exercise, you will start from a program that load-balances based on layer 4 flows: this is generally considered "classic" ECMP. To do this, we compute a hash over the 5-tuple and use this value to choose from a set of possible next hops. This means that all packets belonging to the same flow (i.e. with the same 5-tuple) will be routed to the same nexthop.
通過五元組hash的計算,我們知道,多個屬于同一條業務流的數據報結果計算會產生相同的hash值,從而走同一個端口。
1.啟動交換機
首先,執行打開端口:
./veth_setup.sh運行P4交換機:
./run_demo.sh結果如下:
root@ubuntu:/home/wasdns/tutorials/SIGCOMM_2015/flowlet_switching# ./run_demo. h parsing successful semantic checking successful Header type standard_metadata_t not byte-aligned, adding padding Header type ingress_metadata_t not byte-aligned, adding padding WARNING:gen_json:The P4 program defines a checksum verification on field 'ipv4.hdrChecksum'; as of now bmv2 ignores all checksum verifications; checksum updates are processed correctly. Generating json output to /home/wasdns/tutorials/SIGCOMM_2015/flowlet_switching/simple_router.json Thrift port was not specified, will use 9090 Calling target program-options parser Adding interface veth0 as port 0 Adding interface veth2 as port 1 Adding interface veth4 as port 2 Adding interface veth6 as port 3 Adding interface veth8 as port 4 Thrift server was started Control utility for runtime P4 table manipulation RuntimeCmd: Setting default action of ecmp_group action: _drop runtime data: RuntimeCmd: Setting default action of ecmp_nhop action: _drop runtime data: RuntimeCmd: Setting default action of forward action: _drop runtime data: RuntimeCmd: Setting default action of send_frame action: _drop runtime data: RuntimeCmd: Adding entry to lpm match table ecmp_group match key: LPM-0a:00:00:01/32 action: set_ecmp_select runtime data: 00:00 00:02 Entry has been added with handle 0 RuntimeCmd: Adding entry to exact match table ecmp_nhop match key: EXACT-00:00 action: set_nhop runtime data: 0a:00:01:01 00:01 Entry has been added with handle 0 RuntimeCmd: Adding entry to exact match table ecmp_nhop match key: EXACT-00:01 action: set_nhop runtime data: 0a:00:02:01 00:02 Entry has been added with handle 1 RuntimeCmd: Adding entry to exact match table forward match key: EXACT-0a:00:01:01 action: set_dmac runtime data: 00:04:00:00:00:00 Entry has been added with handle 0 RuntimeCmd: Adding entry to exact match table forward match key: EXACT-0a:00:02:01 action: set_dmac runtime data: 00:04:00:00:00:01 Entry has been added with handle 1 RuntimeCmd: Adding entry to exact match table send_frame match key: EXACT-00:01 action: rewrite_mac runtime data: 00:aa:bb:00:00:00 Entry has been added with handle 0 RuntimeCmd: Adding entry to exact match table send_frame match key: EXACT-00:02 action: rewrite_mac runtime data: 00:aa:bb:00:00:01 Entry has been added with handle 1 RuntimeCmd: READY!!! sudo $SWITCH_PATH simple_router.json -i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 --nanolog ipc:///tmp/bm-0-log.ipc --pcap其中,veth3是實驗中的端口1,veth5是實驗中的端口2,veth7是實驗中的端口3.
2.打開新的終端運行test樣例:
New Terminal:
./run_test.py這里我對腳本略作修改,將腳本中的:
NUM_PACKETS = 500改為
NUM_PACKETS = 100從發500個包,變為發100個包,以節省運行時間。
此時,數據報的目的IP地址為:10.0.0.1,TTL均為64.
結果如下:
root@ubuntu:/home/wasdns/tutorials/SIGCOMM_2015/flowlet_switching# ./run_test1.py WARNING: No route found for IPv6 destination :: (no default route?) Sending 100 packets ... [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]可以看到,這一條流所有的數據報均選擇了端口2作為出端口。
第二部分:
原理
在上面的實驗中,我們看到五元組匹配局限于源目IP、源目Mac以及傳輸層協議,同一條的業務流所屬的數據報只能走同一條路由。
通過改動交換機的P4程序,我們可以實現基于Flowlet_switching的L4LB。
這里的原理是利用時間戳,當某條流的某一個數據報的時間戳-第一個數據報的時間戳大于某一個值的時候,從這個數據報開始改變它的流id,從而走不同的路。
For each flow, you need to store 2 things: a) a timestamp for the last observed packet belonging to this flow and b) a flowlet_id. Flowlet switching is very simple: for each packet which belongs to the flow, you need to update the timestamp. Then, if the time delta between the last observed packet and the current packet exceeds a certain timeout value (in our case, we suggest using 50ms), then the flowlet_id needs to be incremented.
P4程序中,利用寄存器register來實現這個方法:
To maintain state in P4, you will need to use 'register' objects (look them up in the spec). In this case, you will need to use two separate registers for each packet (one for the timestamp and one for the flowlet_id).
源碼:附 simple_router源碼
P4程序中的關鍵部分,時間戳和流id的寄存器及Table如下:
register flowlet_lasttime {width : 32;instance_count : 8192; }register flowlet_id {width : 16;instance_count : 8192; }action lookup_flowlet_map() {modify_field_with_hash_based_offset(ingress_metadata.flowlet_map_index, 0,flowlet_map_hash, FLOWLET_MAP_SIZE);register_read(ingress_metadata.flowlet_id,flowlet_id, ingress_metadata.flowlet_map_index);modify_field(ingress_metadata.flow_ipg,intrinsic_metadata.ingress_global_timestamp);register_read(ingress_metadata.flowlet_lasttime,flowlet_lasttime, ingress_metadata.flowlet_map_index);subtract_from_field(ingress_metadata.flow_ipg,ingress_metadata.flowlet_lasttime);register_write(flowlet_lasttime, ingress_metadata.flowlet_map_index,intrinsic_metadata.ingress_global_timestamp); }table flowlet {actions { lookup_flowlet_map; } }command.txt如下:
table_set_default ecmp_group _drop table_set_default ecmp_nhop _drop table_set_default forward _drop table_set_default send_frame _drop table_set_default flowlet lookup_flowlet_map table_set_default new_flowlet update_flowlet_id table_add ecmp_group set_ecmp_select 10.0.0.1/32 => 0 2 table_add ecmp_nhop set_nhop 0 => 10.0.1.1 1 table_add ecmp_nhop set_nhop 1 => 10.0.2.1 2 table_add forward set_dmac 10.0.1.1 => 00:04:00:00:00:00 table_add forward set_dmac 10.0.2.1 => 00:04:00:00:00:01 table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00 table_add send_frame rewrite_mac 2 => 00:aa:bb:00:00:011.啟動P4交換機(同上)
變化:
RuntimeCmd: Setting default action of flowlet action: lookup_flowlet_map runtime data: RuntimeCmd: Setting default action of new_flowlet action: update_flowlet_id runtime data:新增了兩個默認動作。
2.運行測試樣例
打開新終端,進入目錄,執行命令。
New Terminal:
./run_test.py這里我沒有對腳本進行修改,以便看的更加清晰。
結果:
root@ubuntu:/home/wasdns/tutorials/SIGCOMM_2015/flowlet_switching# ./run_test.py WARNING: No route found for IPv6 destination :: (no default route?) Sending 500 packets ... [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] root@ubuntu:/home/wasdns/tutorials/SIGCOMM_2015/flowlet_switching#可以看到,該條流的數據報基于流id選擇了不同的端口。
實驗結論
我們能夠通過P4語言編寫程序,部署到P4交換機中來實現L4的LB,從而更好的支持ECMP,妥善的處理多條TCP業務流并發的情況,最大化鏈路利用率。
2016/12/21 冬至陽生
總結
以上是生活随笔為你收集整理的Run P4 without P4factory - A Simple Example In Tutorials. -2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AMD 发布 23.2.2 WHQL 驱
- 下一篇: 龚宇:爱奇艺已成功解决债务问题