本篇主要是介紹如何配置VPP的編譯開發環境,具體配置請參考VPP開發文檔:https://wiki.fd.io/view/VPP/Setting_Up_Your_Dev_Environment
- 搭建開發環境
首先我們需要在主機上安裝Vagrant軟件和虛擬機,並在虛擬化里面設置編譯開發環境,當然也可以不在虛擬機里面直接在主機host上來配置VPP的編譯開發環境也是一樣的,我這里面主要是剛開始使用對VPP還不熟悉的時候還是老老實實的按照官方文檔上面的步驟來吧。
默認的配置是支持VMWare和Virtualbox的,首先需要安裝這兩者之一。
VMWare比Virtualbox運行的快,但是需要購買授權的。Virtualbox卻是免費的,我們這里使用的是Virtualbox,可以從這里下載安裝:https://www.virtualbox.org/wiki/Downloads。
安裝Vagrant軟件,可以從這里下載安裝:https://www.vagrantup.com/downloads.html。
安裝Vagrant插件
我們安裝vagrant-cachier插件,這個插件主要是為了cache apt/yum命令的一些安裝包,為了讓Vagrant虛擬機重建的時候速度更快,當然這個插件的安裝是可選的。
安裝完Vagrant程序之后,我們可以使用下面的命令來安裝vagrant-cachier插件,當然如有必要的話請設置好代理:
$ vagrant plugin install vagrant-cachier
安裝Vagrant的虛擬機box文件,這里有兩種類型的系統box文件,一種是Ubuntu系統,一種是CentOS系統。在這里Vagrant會直接從指定的URL處下載box文件並導入虛擬機,所以請保持網絡通暢。
使用下面的命令來安裝Ubuntu系統:
$ vagrant box add --provider virtualbox https://atlas.hashicorp.com/puppetlabs/ubuntu-14.04-64-nocm
使用下面的命令來安裝CentOS系統:
$ vagrant box add --provider virtualbox https://atlas.hashicorp.com/puppetlabs/centos-7.2-64-nocm
- 獲取VPP的源碼
$ cd $HOME/source/vpp $ git clone https://gerrit.fd.io/r/vpp
- 定制Vagrant虛擬機
使用Vagrant啟動虛擬機的時候是使用一個Vagrantfile文件來配置啟動的虛擬機的一些配置的,我們VPP的開發環境虛擬機的配置文件在下面位置:
$ cd $HOME/source/vpp
$ vim ./build-root/vagrant/Vagrantfile
在這個Vagrantfile文件里面初始時使用的是默認配置,在這個文件里可以指定CPU、內存、網絡、共享目錄等等,具體更詳細的配置信息請參考Vagrant的官網:https://www.vagrantup.com/docs/vagrantfile/。
- 操作虛擬機
一旦確定配置好了Vagrantfile文件,那么我們就可以開始操作虛擬機了。首先我們需要切換當前目錄到Vagrantfile所在的目錄下,這樣我們才能夠正確的操作虛擬機使用下面的一些命令:
$ cd $HOME/source/vpp/build-root/vagrant/
然后我們使用下面的命令來建立和啟動VM:
$ vagrant up
在第一次啟動的時候會比較慢,但是后續再啟動的時候就會快一些。
成功啟動VM之后,使用下面的命令登陸進入虛擬機中:
$ vagrant ssh
虛擬機使用完畢之后,我們可以使用下面的命令來關閉虛擬機:
$ vagrant halt
還有一些其他的操作命令如下:
$ vagrant suspend //暫停虛擬機的運行 $ vagrant resume //恢復虛擬機的運行 $ vagrant destroy //關閉虛擬機並destroy所有的資源,但是下載下來的虛擬機box文件還是存在的,下次依然可以使用vagrant up命令來建立並啟動虛擬機,如果要刪除box文件,請使用vagrant box remove
- 編譯、安裝並測試VPP
當我們成功的啟動了虛擬機並在虛擬機中使用git命令獲取了VPP的源代碼之后,我們就可以編譯安裝並對VPP進行一些基本的功能測試了。
具體的編譯安裝以及測試請參考VPP的官網幫助:https://wiki.fd.io/view/VPP/Build,_install,_and_test_images。
--------------------------------------------------------------------------------------------------------------------------------------------------
這里是本人初次配置VPP的開發環境以及編譯、安裝和測試VPP的時候遇到的一些問題和解決方法,在此記錄作為后續的參考:
1. 安裝Vagrant插件的時候報錯,報錯信息如下:
[root@demo-sff1 gems]# vagrant plugin install vagrant-cachier Installing the 'vagrant-cachier' plugin. This can take a few minutes... Bundler, the underlying system Vagrant uses to install plugins, reported an error. The error is shown below. These errors are usually caused by misconfigured plugin installations or transient network issues. The error from Bundler is: An error occurred while installing net-ssh (2.9.4), and Bundler cannot continue. Make sure that `gem install net-ssh -v '2.9.4'` succeeds before bundling. Warning: this Gemfile contains multiple primary sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source. To upgrade this warning to an error, run `bundle config disable_multisource true`.Warning: this Gemfile contains multiple primary sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source. To upgrade this warning to an error, run `bundle config disable_multisource true`.Gem::RemoteFetcher::FetchError: Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://rubygems.org/gems/net-ssh-2.9.4.gem)
這里報錯信息提示我們要先使用命令"gem install net-ssh -v 2.9.4"來安裝net-ssh包,但是使用gem命令來安裝缺失的net-ssh包的時候,又報錯了:
[root@demo-sff1 gems]# gem install net-ssh -v '2.9.4' Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://rubygems.org/)
這個原因是由於我們國內無法訪問https://rubygems.org/,被GFW給屏蔽了。所以我們需要換成國內的gem源。使用下面的命令:
[root@demo-sff1 gems]# gem sources -l //查看當前gem的源 *** CURRENT SOURCES *** https://rubygems.org/ //當前使用的gem源是https://rubygems.org/ [root@demo-sff1 gems]# gem sources -a https://ruby.taobao.org/ //更改源為淘寶提供的源 [root@demo-sff1 gems]# gem sources --remove https://rubygems.org/ //刪除原來的那個被屏蔽的源
關於這個問題可以參考這個link:http://blog.csdn.net/u012336923/article/details/50447835
如果有代理的話請正確的設置使用的代理,編輯文件/etc/profile, 在文件最后加入下面的命令:
export http_proxy=http://proxy-prc.intel.com:911 export https_proxy=http://proxy-prc.intel.com:912 export ftp_proxy=http://proxy-prc.intel.com:911 export socks_proxy=http://proxy-prc.intel.com:1080 export no_proxy=intel.com,.intel.com,10.0.0.0/8,192.168.0.0/16,localhost,127.0.0.0/8,134.134.0.0/16 export HTTP_PROXY=http://proxy-prc.intel.com:911 export HTTPS_PROXY=http://proxy-prc.intel.com:912 export FTP_PROXY=http://proxy-prc.intel.com:911 export SOCKS_PROXY=http://proxy-prc.intel.com:1080 export NO_PROXY=intel.com,.intel.com,10.0.0.0/8,192.168.0.0/16,localhost,127.0.0.0/8,134.134.0.0/16
進行上面的一些設置之后,我們就可以使用gem install命令來安裝缺失的包,之后就可以使用vagrant plugin install命令來安裝插件了,請使用下面的命令來安裝,防止出現其他的錯誤。
[root@demo-sff1 gems]# gem install net-ssh -v '2.9.4' --install-dir /opt/vagrant/embedded/gems
請注意: 我們必須顯示的指定gem將net-ssh包安裝到目錄/opt/vagrant/embedded/gems中,這樣安裝完成之后net-ssh包就可以被vagrant識別到,否則即使我們用gem install命令安裝net-ssh成功了,但是vagrant還是會報"An error occurred while installing net-ssh (2.9.4), and Bundler cannot continue"的錯誤。
我們可以使用命令gem environment來查看下gem默認的一些環境配置。
[root@demo-sff1 vagrant]# gem environment RubyGems Environment: - RUBYGEMS VERSION: 2.1.11 - RUBY VERSION: 2.0.0 (2013-06-27 patchlevel 247) [x86_64-linux] - INSTALLATION DIRECTORY: /usr/local/share/gems //gem命令將安裝的包都安裝到目錄/usr/local/share/gems中了,但是很遺憾這個目錄vagrant識別不到。有一種方法是將該目錄下的相應子目錄拷貝到vagrant的目錄/opt/vagrant/embedded/gems中也是可以的,但是太麻煩;
//第二種方法是直接在gem install命令安裝的時候加上--install-dir /opt/vagrant/embedded/gems參數來指定安裝位置。 - RUBY EXECUTABLE: /usr/bin/ruby - EXECUTABLE DIRECTORY: /usr/local/bin - SPEC CACHE DIRECTORY: /root/.gem/specs - RUBYGEMS PLATFORMS: - ruby - x86_64-linux - GEM PATHS: - /usr/local/share/gems - /root/.gem/ruby - /usr/share/gems - GEM CONFIGURATION: - :update_sources => true - :verbose => true - :backtrace => false - :bulk_threshold => 1000 - :sources => ["https://ruby.taobao.org/"] - REMOTE SOURCES: - https://ruby.taobao.org/ - SHELL PATH: - /usr/lib64/ccache - /usr/local/sbin - /usr/local/bin - /usr/sbin - /usr/bin - /usr/local/bin - /usr/local/sbin - /root/bin - /root/minion - /root/bin
安裝提示使用gem命令安裝完所有確實的包之后,我們就可以使用vagrant命令來安裝插件了。
[root@demo-sff1 gems]# vagrant plugin install vagrant-cachier --plugin-source https://ruby.taobao.org/
在這里我們使用--plugin-source https://ruby.taobao.org/來指定插件下載源為國內淘寶源,如果不加這個參數那么默認使用的是源https://rubygems.org
具體可以參考下面的links:http://stackoverflow.com/questions/32805193/vagrant-plugin-install-error-gem-install-little-plugger-v-1-1-4-succeeds-be
2. 使用vagrant來啟動VPP開發環境虛擬機
首先我們使用git命令來獲取VPP source code:
$ cd /home $ git clone https://gerrit.fd.io/r/vpp
上述命令完成之后,就會有一個/home/vpp/目錄,該目錄中為VPP的源碼。
$ cd /home/vpp/build-root/vagrant $ vi Vagrantfile
在源碼中有一個Vagrantfile文件,這個文件是vagrant的配置文件。請注意: 我們后續使用vagrant命令對虛擬機進行的一系列操作(比如:vagrant up、vagrant ssh、vagrant halt等等命令)都必須先cd到目錄/home/vpp/build-root/vagrant中,因為在這個目錄下有vagrant操作虛擬機所需要的配置文件Vagrantfile。我們也可以看到VPP的官方文檔中也提到了這些:
cd to the vagrant directory In the command-line interface, navigate to the directory that has the pre-configured Vagrantfile. (In the following sample command, <install_dir> is the directory where you unzipped or cloned the VPP software.) $ cd <install_dir>/build-root/vagrant/ //操作虛擬機之前請切換當前目錄到<install_dir>/build-root/vagrant/ NOTE: The .../build-root directory contains the files that make up most of the build system. It contains all of the generic targets, including: xxx-build, xxx-rebuild, xxx-install, xxx-clean, xxx-wipe, xxx-configure, and xxx-find-source. Build the VM with Vagrant By default this will build an Ubuntu 14.0.4 VM. If you wish instead to build a Centos7 VM instead: $ (export VPP_VAGRANT_DISTRO=centos7;vagrant up) //默認情況下搭建的VM是Ubuntu 14.0.4的系統,不過也可以使用這條命令來搭建一個CentOS 7的系統 If you wish to use VMWareFusion as your provider, use: $ (export VAGRANT_DEFAULT_PROVIDER=vmware_fusion;vagrant up) //默認情況下使用的是Virtualbox,如果要使用VMWare請使用這條命令 When you first start Vagrant, it is normal for it to run for several minutes, building the VM, building VPP, and then a README will be displayed telling you how to run VPP. Use the Vagrant up command to cause Vagrant to start. Vagrant uses the Vagrantfile in the current working directory. $ vagrant up 這個命令會默認建立一個Ubuntu 14.0.4的VM,首先vagrant會從https://vagrantcloud.com/puppetlabs/boxes/ubuntu-14.04-64-nocm/versions/1.0.3/providers/virtualbox.box下載一個box文件,隨后會將該box文件用virtualbox來啟動起來。 Access the shell Use the Vagrant SSH command to access the running Vagrant machine and give you access to a shell. $ vagrant ssh If you wish to forward X-windows server requests, use this variation: $ vagrant ssh -- -X Success!
3. 關於vagrant設置proxy的問題
首先我們安裝vagrant的一個插件vagrant-proxyconf,這個插件可以幫助我們設置在VM中的一些代理配置。
[root@demo-sff1 gems]# vagrant plugin install vagrant-proxyconf --plugin-source https://ruby.taobao.org/
安裝完這個插件之后,我們在host宿主機上必須設置幾個環境變量。
export VAGRANT_HTTP_PROXY=http://proxy-prc.intel.com:911 export VAGRANT_HTTPS_PROXY=http://proxy-prc.intel.com:912 export VAGRANT_FTP_PROXY=http://proxy-prc.intel.com:911 export VAGRANT_NO_PROXY=intel.com,.intel.com,10.0.0.0/8,192.168.0.0/16,localhost,127.0.0.0/8,134.134.0.0/16
隨后當我們使用vagrant up命令來啟動虛擬機的時候,vagrant-proxyconf插件就會獲取到宿主機上設置的VAGRANT_HTTP_PROXY、VAGRANT_HTTPS_PROXY等環境變量的值並自動的對VM中的代理做一些配置。
比如我現在啟動了一個Ubuntu 14.04版本的VM,那么vagrant-proxyconf插件會幫我設置好相應的proxy的環境變量。我們可以使用vagrant ssh命令登陸進入虛擬機並使用命令來查看當前虛擬機的代理是否正確設置了:
vagrant@localhost:/vpp/build-root$ env | grep -i proxy NO_PROXY=intel.com,.intel.com,10.0.0.0/8,192.168.0.0/16,localhost,127.0.0.0/8,134.134.0.0/16 http_proxy=http://proxy-prc.intel.com:911 ftp_proxy=http://proxy-prc.intel.com:911 FTP_PROXY=http://proxy-prc.intel.com:911 https_proxy=http://proxy-prc.intel.com:912 HTTPS_PROXY=http://proxy-prc.intel.com:912 no_proxy=intel.com,.intel.com,10.0.0.0/8,192.168.0.0/16,localhost,127.0.0.0/8,134.134.0.0/16 HTTP_PROXY=http://proxy-prc.intel.com:911
請注意: 這里需要在宿主機上設置的環境變量是VAGRANT_HTTP_PROXY、VAGRANT_HTTPS_PROXY等項,而不是http_proxy、https_proxy等項,根據實驗證明設置http_proxy、https_proxy等項沒有作用。
當然我們也可以直接修改Vagrantfile配置文件,將proxy配置進行修改即可。
# use http proxy if avaiable if ENV['http_proxy'] && Vagrant.has_plugin?("vagrant-proxyconf") config.proxy.http = "$http_proxy" //將$http_proxy修改為http://proxy-prc.intel.com:911 config.proxy.https = "$https_proxy" //將$https_proxy修改為http://proxy-prc.intel.com:912 config.proxy.no_proxy = "localhost,127.0.0.1" end
參考links: http://www.rubydoc.info/gems/vagrant-proxyconf/1.0.
4. 關於vagrant啟動時配置provision的問題
在我們目前使用的Vagrantfile配置文件中,有如下的配置:
# Pick the right distro and bootstrap, default is ubuntu1404 distro = ENV['VPP_VAGRANT_DISTRO'] if distro == 'centos7' config.vm.box = "puppetlabs/centos-7.2-64-nocm" config.vm.provision 'shell', path: 'bootstrap.centos7.sh' else config.vm.box = "puppetlabs/ubuntu-14.04-64-nocm" config.vm.provision 'shell', path: 'bootstrap.ubuntu1404.sh' end
這里配置了VM的provision,表示在VM啟動完成后就會自動執行一個shell腳本,在我們這里執行的是當前目錄下的bootstrap.ubuntu1404.sh腳本文件。
Provisioners are run in three cases: the initial vagrant up, vagrant provision, and vagrant reload --provision. By default, provisioners are only run once, during the first vagrant up since the last vagrant destroy, unless the --provision flag is set, as noted above.
這個provision只在3種情況下運行: 第一次初始化的vagrant up命令運行時; 使用vagrant provision命令來顯式的指定運行provision; 使用vagrant reload --provision命令來顯式的指定重新加載provision。
默認情況下,從第一次vagrant up命令到最后的vagrant destroy命令之間, provisioners只會運行一次。 也就是說從第2次的vagrant up命令都不會再自動運行provisioners,除非使用vagrant destroy命令來destroy這個VM並再次使用vagrant up來啟動虛擬機或者可以使用顯式的運行provisioners命令來運行它。
參考links: https://www.vagrantup.com/docs/provisioning/basic_usage.html
5. 使用git命令下載源碼包
使用git config命令來設置git使用的代理:
git config --system http.proxy http://proxy-chain.intel.com:911 git config --system https.proxy http://proxy-chain.intel.com:912
隨后可以使用git命令來查看當前設置的代理:
[root@demo-sff1 home]# git config -l http.proxy=http://proxy-prc.intel.com:911 https.proxy=http://proxy-prc.intel.com:912
但是這里只設置了http和https的代理,所以我們只能使用git clone命令從http或者https管理的資源庫來下載了。
[root@demo-sff1 home]# git clone git://git.linaro.org/lng/odp.git Cloning into 'odp'... fatal: unable to connect to git.linaro.org: git.linaro.org[0: 23.21.56.198]: errno=Connection timed out
這里因為沒有設置git資源庫的代理,所以當我們從git://git.linaro.org/lng/odp.git地址下載源碼包時下載是失敗的,但是我們可以改為從http或者https服務器來下載。
[root@demo-sff1 home]# git clone https://git.linaro.org/lng/odp.git Cloning into 'odp'... remote: Counting objects: 22946, done. remote: Compressing objects: 100% (5427/5427), done. remote: Total 22946 (delta 17185), reused 22205 (delta 16693) Receiving objects: 100% (22946/22946), 4.63 MiB | 2.95 MiB/s, done. Resolving deltas: 100% (17185/17185), done. Checking connectivity... done
直接改為從https服務器下載就成功了。
6. 使用vagrant配置public network
我們想從外部直接訪問VM內部,在vagrant啟動虛擬機的時候,默認會自動啟動一個NAT類型的網絡,也就是VM可以通過這個NAT類型的網絡訪問外部internet,但是外部不能通過這個NAT類型的網絡來直接訪問VM. 有兩種方法可以進行配置:
a. 我們可以設置vagrant的forwarded_port網絡,這樣可以配置訪問宿主機host的某個端口的數據直接轉發到VM的某個端口
b. 我們可以給VM配置一個public_network網絡並使用dhcp來給它分配一個IP地址
首先修改Vagrantfile配置文件,加入如下的配置:
config.vm.network "public_network" //給VM額外配置一個public network
當使用vagrant up命令來啟動虛擬機時,會提示需要給public network指定一個橋接的宿主機host的NIC網絡接口,我們應該指定為宿主機上的連接外網的那個NIC網卡接口卡,比如我的宿主機上是em0網卡。
[root@demo-sff1 home]# ifconfig em0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.239.129.177 netmask 255.255.254.0 broadcast 0.0.0.0 inet6 fe80::21e:67ff:fed8:19b9 prefixlen 64 scopeid 0x20<link> ether 00:1e:67:d8:19:b9 txqueuelen 1000 (Ethernet) RX packets 2750043 bytes 1188719586 (1.1 GiB) RX errors 0 dropped 2 overruns 0 frame 0 TX packets 469131 bytes 171203709 (163.2 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
這樣指定之后,隨后VM就會啟動並自動建立一個網絡橋接到宿主機的em0網卡上,並且會使用dhcp來分配一個IP地址。
root@localhost:/# ifconfig eth0 Link encap:Ethernet HWaddr 08:00:27:76:7a:6b //這個是vagrant啟動時默認的一個NAT類型的網卡 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe76:7a6b/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6768 errors:0 dropped:0 overruns:0 frame:0 TX packets:5066 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:601359 (601.3 KB) TX bytes:587636 (587.6 KB) eth1 Link encap:Ethernet HWaddr 08:00:27:a9:cd:45 //這個是public network類型的網卡 inet addr:10.239.128.208 Bcast:10.239.129.255 Mask:255.255.254.0 inet6 addr: fe80::a00:27ff:fea9:cd45/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:125714 errors:0 dropped:0 overruns:0 frame:0 TX packets:1277 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:23733064 (23.7 MB) TX bytes:297446 (297.4 KB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:56 errors:0 dropped:0 overruns:0 frame:0 TX packets:56 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3354 (3.3 KB) TX bytes:3354 (3.3 KB)
使用ping命令來測試網絡是否通暢,發現VM可以ping通外網IP,但是外網IP無法ping通VM。這個原因是沒有加入路由信息到系統路由表中。
vagrant@localhost:~$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0 10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 10.239.128.0 0.0.0.0 255.255.254.0 U 0 0 0 eth1 root@localhost:~# route add -net 10.239.0.0 netmask 255.255.0.0 gw 10.239.128.1 dev eth1 //加入一條路由信息訪問網絡10.239.0.0/16的數據直接從eth1網卡發送到網關10.239.128.1 root@localhost:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0 10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 10.239.0.0 10.239.128.1 255.255.0.0 UG 0 0 0 eth1 10.239.128.0 0.0.0.0 255.255.254.0 U 0 0 0 eth1
7. 配置vagrant啟動虛擬機使用多個CPU
現在VPP項目啟動時需要配置多個core來進行運行,所以我們必須配置VM啟動時使用多個CPU。我們修改配置文件Vagrantfile:
config.vm.provider "virtualbox" do |vb| //這里表示,我們使用的虛擬機工具是virtualbox, 目前我們使用的是virtualbox vb.customize ["modifyvm", :id, "--ioapic", "on"] //注意: 如果要配置VM使用多個CPU,那么必須將ioapic功能開啟,否則設置多個CPU是不會生效的 #vb.customize ["modifyvm", :id, "--memory", "8192"] #vb.customize ["modifyvm", :id, "--cpus", "16"] vb.memory = 8192 //設置VM的內存為8G vb.cpus = 16 //設置VM的CPU個數為16個 end config.vm.provider "vmware_fusion" do |fusion,override| //這里表示,我們使用的虛擬機工具是vmware fusion, vmware fusion是面向蘋果電腦推出的一款軟件 fusion.vmx["memsize"] = "4096" end config.vm.provider "vmware_workstation" do |vws,override| //這里表示,我們使用的虛擬機工具是vmware workstation vws.vmx["memsize"] = "8192" vws.vmx["numvcpus"] = "4" end
具體可以參考如下的一些links:
