VPPはじめました

#はじめに

2018年も残り一ヶ月、徐々に寒くなり、クリスマス・キャロルが聞こえてくる頃になりましたねw
こんな日は少しテクニカルな事に時間を割いて、熱量高めに、Linux Foundationプロジェクトの１つである、
FD.io　VPPについて、shimadyuが紹介いたします！　以下のサイトからVPPのdeepdiveが可能です。

[FD.IOのリンクはこちら](https://fd.io/)
[FD.IO wikiのページはこちら](https://wiki.fd.io/view/VPP)
[VPPとは何か](https://wiki.fd.io/view/VPP/What_is_VPP%3F)
[VPPデザインと実装のoverviewはこちら](https://wiki.fd.io/images/d/d6/Fd.io_vpp_overview_29.03.17.pptx)

Service Providers、Network Vendors,Chip Vendors、Integratorsさんにて、オープンソースコミュニティ活動を進めているVPPですが
VPPは約10年間、シスコ社内にて開発していた仮想スイッチモジュールとなっています。
NFVに携わるみなさんに使っていただけるように、2016年の早い段階にて、Linux Foundation project FD.ioとしてオープンソースになり、CommodityなCPUを搭載したx86/64サーバにて動作して、且つ、柔軟性がありスケーラブルなデータプレーン転送の実現を目指し、これからも新しいネットワーキングのチャレンジを解決していくことがプロジェクトの目的となります。2018年12月5日時点で最新のVPP Releaseは18.10となっており、タイムリーにソフトウェアがリリースされております。apt-get installでvppインストールは比較的簡単です。proxy環境の場合は、proxyオプションを忘れずに設定頂き、apt-getやcurl -x proxy...な形で事前準備します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/05bd6fe4-5c2c-86a5-d8b8-bccc8b711de8.png)

#オープンソースFD.IO/VPPの特徴

いろんなサイトにてVPPを日本語で紹介されておりますので、shimadyu目線にて以下8つのテクニカルなポイントを取り上げます。

1. VPPはDPDKに依存しておらず、IntelさんのAdaptive Virtual Function (AVF)がVPP native driverに対応しております。[詳細はこちらです。](https://docs.fd.io/vpp/18.04/avf_plugin_doc.html)　将来的にはVPPをSmart NICにオフロードしてくれるはず(期待)
2. 　VPPはOVS-DPDKよりもパフォーマンスが圧倒的に優れている
3. 　OVSのようにパケットを一個ずつ処理するのではなく、一度に256個までのパケットを、L2/L3ルックアップを実行するパイプラインに入れて処理する。マイクロプロセッサ上のinstruction cacheの読み込み再利用できたり、事前にパケットをデータキャッシュにプリフェッチさせることができるため、同様のシーケンスを持ったIPv4/IPv6パケットは、独立したIPv4/IPv6モジュールにて同時に処理可能となり、メモリーへのアクセス遅延とメモリー使用量を最小化します![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/f1a2d051-78bf-9a91-c7c0-2a41bf475f95.png)



3. 　VPPはvSwitchとしてVNFを接続し、ユーザスペースで動作する　（OSS vSwitch)
4. 　VNFをbuildするためのフレームワークとして動作させる事も可能
5. 　コントロールプレーンを担当するOpen Day Light(ODL)連携も可能
6. 　OpenStack Neutron FD.io ML2 agentをサポート (本当はこれを試したかったのですが、次回への宿題とさせていただきます!)
7. 　様々なL2/L3機能のデータプレーンに対応　[本記事ではSRv6-VPNをご紹介します] (https://wiki.fd.io/view/VPP/Segment_Routing_for_IPv6) 

ここで、2のパフォーマンスがどんなに優れているのか、一部、FD.IO wikiに公開されておりますが、触れたいと思います。最も、特徴的なのは、L2 MACエントリーやL3 FIB数のスケールに依存せず、スループットは安定、さらには、CPUコアあたり、約14Mppsの転送性能を持ち、24CPUコア搭載した場合には500Gbpsのスループットを実現可能な転送アーキテクチャとなっております。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/8df82515-489f-9785-2f96-6ebfae4ff045.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/2d0878b2-63e4-9867-5d26-3acc2e8c1a9b.png)

#SRv6-VPN DX4 (IPv4 over IPv6)をVPPで設定してみよう

[VPPのインストール](https://wiki.fd.io/view/VPP/Installing_VPP_binaries_from_packages)説明は今回は割愛しまして、[draft-filsfils-spring-srv6-network-programming] (https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-06)で定義されているSRv6-VPN DX4 functionをVPPで動かして見たいと思います。
両端にR1とR2とCisco CSR1kvでIPv4のみを有効として、IPv4 over IPv6にてIPv4通信をSRv6-VPN NW経由で可能にしてみたいと思います。

1.VPP1,VPP2,VPP3はSRv6-VPNのデータプレーンに対応したVPPノード
2.VPP1は2.2.2.2/24を宛先とするIPv4パケットをR1から受信すると、SR policyにてL3 steeringし、T.Encaps functionを実施(IPv6headerと　SRH with segment lists (B1::1, C4::4)の両方をencapして、B1::1を宛先としたIPv6パケットをVPP#2に送出)
3.VPP2はB1::1を宛先とした自分宛てのパケットをEnd functionし、Segment listsを1->0に減算し、IPv6　宛先アドレスはC4::4にrewrite
4.VPP3はC4::4を宛先とした自分宛てのパケットを受信すると、IPV6ヘッダーとSRHをdecapし、指定したIPv4 I/F経由でIPv4パケットをcross-connect (END.DX4 function)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/58713a7c-0e1e-2edf-610a-1bf99d2f23c1.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/47ffb972-e6b0-25c1-f212-fd71778816a5.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/121c43b8-b635-3746-ea44-db67155a7194.png)


VPP1では以下のような出力結果となります。VPP3も同じような設定となります。

SR policyにより、2.2.2.0/24を宛先とするIPv4パケットは、T.encapされ、B1::1,C4::4をSRH Segment Listにセットします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/2ad66ce1-7dd7-48f4-5458-4842b96b3244.png)

以下のshowコマンドからもL3 SteeringのためのSR policyが正しく反映されていることがわかります。また、vpp1はDX4 functionを実行するSRv6ノードでもあるため、DX4 functionも合わせて設定しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/71072cec-655a-ac4f-cd20-7750c3408467.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/ea74384c-c5b8-aac1-cf96-d7fb8b02f837.png)

VPP2では以下のような出力結果となります。B1::1をENDするための役割ですので、特に難しい設定はありません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/cdd0e0b3-a588-a0fa-71a5-1048b04ad025.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/5ed8283a-a114-dfc4-b829-e4356c6a3b2b.png)

#VPP1＜−＞VPP2間のSRv6パケットをキャプチャしてみよう

R1からR2へICMPを実行した状態で、VPP1<->VPP2間のパケットキャプチャを実行します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/af35a940-18ea-6526-1d5d-01de72d5efae.png)

確かに、IPv4パケットがIPv6にてencapされて、転送されています！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/314318/4c8948d4-217a-2e91-5726-a541dbf2eaeb.png)

#おわりに

今回は、オープンソースのVPPを使用して、SRv6-VPNのデータプレーンを確認しました。
VPPはvswitchとしてのユースケースもサポートしているため、次回はNeutron ML2連携やコンテナ(Contiv-VPP)にもチャレンジしたいとおもいます。
ご覧いただきまして有難うございます。

simadyu