netns on Ubuntu on GNS3にてLinuxのMPLS機能を見てみる。

##はじまりのごあいさつ
あられさ(@A_Resas)でございます。
この記事は[Linux Advent Calendar 2016](http://qiita.com/advent-calendar/2016/linux)の12日目の記事となっております。

この度Advent Calenderというものに投稿したくなり、Linuxというキーワードを見つけたのでとりあえず得意分野で書いてみることにしますた。[以前、LinuxがMPLSの対応をしているという記事](http://qiita.com/kwi/items/bccf38b69e089b729da9)を発見し、どう動くのか気になるなぁと思っていたので実際に動かしてみるでござるの巻、であります！
##MPLSとはなんでしょうか？
[MPLS(Multi-Protocol Label Switching)](https://ja.wikipedia.org/wiki/Multi-Protocol_Label_Switching)とはL2ヘッダとL3ヘッダの間にShimヘッダ(通称ラベルヘッダ)と呼ばれるヘッダをつけて通信の高速化しちゃうんだぜな次世代（というには広まってから時間が結構経過しているが笑）のバックボーンネットワーク技術です。日本語では[Yahoo!](https://techblog.yahoo.co.jp/infrastructure/evpn/)さんや[net one](http://www.netone.co.jp/training/detail/zki034.html)さんくらいしか説明するサイトがないのでまぁ日本じゃ次世代では笑

アプリ屋の方でもVLANやOSPFとかなら知ってるぞ～みたいな人もいらっしゃるでしょうが、MPLSはなかなかマイナーなので知らない方も多いかもしれません。全く意味不明な状態でただコマンドだけを見せられても微妙でしょうから、かる～く説明しておきたいと思います。

***
*と言いつつガッツリ説明を書いてしまったので、お時間に限りのある方は「実行環境！」まで飛んでください。*
***

基本的にRIPやOSPFやBGP等のダイナミックルーティングはとにもかくにも以下のルールを守ります。

①自分配下にいるのセグメントの経路情報を自分のルーティングテーブルと呼ばれる表に書く。
②ルーティングテーブルの内容を同じプロトコルを話している隣のルータとルールに従い交換する。
③パケットが来たらそのルーティングテーブルに従い、より宛先のアドレスと似てる経路を持ってると書いてある隣のルータ（もしくは自分配下のセグメント）に向けて投げる。

基本的に通常のIPネットワークではこのルールに従います。
***
因みにCisco IOS等のルーティングテーブルはこんな感じです。

|Protocols     |Prefix       |Next Hop|Outgoing   | 
|:----------|:----------|:----------|:----------|
C|        12.0.0.0/24 |is directly connected| Ethernet3/2
L|        12.0.0.2/32 |is directly connected| Ethernet3/2
O|        14.0.0.0/24 |via 12.0.0.1| Ethernet3/2
O|        15.0.0.0/24 |via 25.0.0.3| Ethernet4/4
C|        23.0.0.0/24 |is directly connected| Ethernet3/3
L|        23.0.0.1/32 |is directly connected| Ethernet3/3
C|        25.0.0.0/24 |is directly connected| Ethernet4/4
L|        25.0.0.1/32 |is directly connected| Ethernet4/4
O|        35.0.0.0/24 |via 25.0.0.3| Ethernet4/4
例えばですが、表の一番上の記述は「12.0.0.0/24」というネットワークは「is directly connected」、つまりこのルータの直下にあり、「Ethernet3/2」がそのネットワークに繋がっているという事を示します。

一方、「14.0.0.0/24」というネットワークは「via 12.0.0.1」、つまりこの12.0.0.1というIPアドレスの先にあり、そこへは「Ethernet3/2」を介して投げるという意味合いとなります。
<img width="404" alt="6743869d1dd7631473f5b4f78c948c4c.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/1f35043f-f788-8bf9-f256-874e1ee56420.png">


***

一方、MPLSを使ったネットワークではこのルールを改造して基本的に以下のようにして投げます。

①自分配下にいるのセグメントの経路情報を自分のルーティングテーブルと呼ばれる表に書く。
②そのルーティングテーブルを元に「経路情報」を「ラベルの番号」としたフォワーディングテーブルを書く。
③ルーティングテーブルの内容を同じプロトコルを話している隣のルータとルールに従い交換する。
④フォワーディングテーブルのラベルの番号もラベル交換プロトコルを話している隣のルータをルールに従い交換する。
⑤パケットが来たらフォワーディングテーブルに従い、宛先のアドレスと対応付けられて広告されてきたラベル番号に従い、その番号を広告してきた隣のルータ（もしくは自分配下のセグメント）に向けて投げる。

という感じです。更に砕いて言うのであればRIPやOSPFやBGPが走っているルータが「基本的には、より近い（Metric,Longest Match等）宛先の経路情報を持ってるルータに向けて投げる」に対して、MPLS上のルータは「事前に宛先の経路情報に対してラベル番号をつけておき、投げられてきたラベル番号に従い、次のルータに向けて投げる」という動きをするわけです。

これをする事で、ルーティングテーブルを見て凄いいっぱいある経路情報の中から、一番近い経路を持ってるルータはどれかな・・・・なんて考えずに、この宛先はこの番号！ばしゅん！と投げれば良くなり、ルーティングの高速化を実現することができます（本当は[パトリシアツリー](https://github.com/ethereum/wiki/wiki/%5BJapanese%5D-Patricia-Tree)の原理から説明したいですが、スペースの関係上、かなり簡潔に書きました・・・・）。

***
因みにCisco IOS等のフォワーディングテーブルはこんな感じです。

|Local Lable     |Outgoing   Lable |Prefix     |Outgoing IF  |   Next Hop IF|
|:----------|:----------|:----------|:----------|:----------|
16         |Pop Label  |59.0.0.0/24    |     Et4/4  |   25.0.0.3|
17         |Pop Label  |57.0.0.0/24    |       Et4/4  |   25.0.0.3|
18         |Pop Label  |56.0.0.0/24    |      Et4/4  |   25.0.0.3|
19         |Pop Label  |36.0.0.0/24    |      Et3/3  |   23.0.0.2|
20         |Pop Label  |35.0.0.0/24    |      Et3/3  |   23.0.0.2|
           |Pop Label  |35.0.0.0/24    |     Et4/4  |   25.0.0.3|
21         |Pop Label  |15.0.0.0/24    |    Et3/2  |   12.0.0.1|
22         |Pop Label  |14.0.0.0/24    |      Et3/2  |   12.0.0.1|
23         |Pop Label  |100.0.0.0/24   |   Et3/2  |   12.0.0.1|
24         |24         |69.0.0.0/24    |       Et3/3  |   23.0.0.2|
           |19         |69.0.0.0/24    |    Et4/4  |   25.0.0.3|
25         |23         |200.0.0.0/24   |    Et3/3  |   23.0.0.2|
           |20         |200.0.0.0/24   |    Et4/4  |   25.0.0.3|
26         |26         |47.0.0.0/24    |     Et3/2  |   12.0.0.1|
           |23         |47.0.0.0/24    |    Et4/4  |   25.0.0.3|
27         |22         |78.0.0.0/24    |    Et4/4  |   25.0.0.3|
28         |21         |89.0.0.0/24    |     Et4/4  |   25.0.0.3|
30         |Pop Label  |58.0.0.0/24    |     Et4/4  |   25.0.0.3|
例では、下から三番目、「78.0.0.0/24 」のネットワークに対しては、Local Label「27」がセットされています。これは隣接ルータが宛先「78.0.0.0/24」のネットワークに向けて自分に向けて投げる際にこの数字をつけて来ます（という事が既に分かっています）。そうしたらOutgoing Lable「22」をつけて投げると書いてあります。一番右の二つは「78.0.0.0/24」に向かうには自分のルータのIF（Outgoing IF）Et4/4から、ネクストホップアドレス25.0.0.3に投げれば良いと書いてます。

これをまとめるとこのルータは、
『ラベル番号27をつけて投げてきたMPLSパケットには、ラベル番号22つけてEt4/4からネクストホップ25.0.0.3に向けて投げる』と読み取れるわけです。実際に投げる際にはラベルしかルータは見ていないことがこれで分かるかと思います（ただ、LDP等でラベル情報を隣接同士で交換する際にはルーティングテーブルから引用するという事は忘れずに）。

<img width="504" alt="d0b26a6b0f4a8fa8b639aa762399988a.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/cdfc3b74-cd39-6b08-6b05-23ee5aff560b.png">


***
*※MPLS界隈では、ラベルをつける事を「Push」、ラベルを外す事を「Pop」、PopとPushを併せてラベルを違うものに交換することを「Swap」といいます。覚えておくと英文を読む際に便利です。*
***

*※上の記述により勘の良い方はお気づきかもしれませんが、上の表の「Pop Lable」これは「ラベルを何もつけずに投げる」事を意味します。ネクストホップルータがMPLS網のエッジだった場合、その先はIPのルーティングなりEthernetなりPPPで飛ばせるのでラベルつける必要がないよねという事です。
参考：http://www.itbook.info/study/mpls4.html*
***

##なんとなぁく分かってたような？
とりあえず「なんかOSPFとかよりつえーやつなんだぁ！」「数字見て投げるってだけで速くなるって意外と今までのルータっておバカさんだったの？」みたいに思えたらいいんだと思います。（そもそもMPLSなんてただのIP網に被せる形で実現する癖になんで速くなるの？複雑になってるじゃん等、そういうのが気になる人は調べると深淵に入れますので是非）。さて、こっから本題に戻っていきたいと思います。
##実行環境！
今回の検証環境の基盤には別にスループットなんて測らないし、1からオンプレで立てるのはしんどいので、仮想環境を使い私はパソコン一台で全てやりきってしまいます笑

####使用ソフトウェア####
[ホストPC]
・Windows 10
・GNS3 -version 1.5.1 on Windows (64-bit) with Python 3.5.1 Qt 5.6.0-
・Oracle VirtualBox -version 5.1.8 r111374 (Qt5.5.1)-

[ゲストVM]
・Ubuntu16.04LTS -kernel version 4.60-
・Wireshark -version 2.0.2-
・iproute  -version 4.4.0-1vyos2 -
・iproute2 -version 4.4.0-1vyos2-
・mpls_gso(modprobe)
・mpls_router(modprobe)
・mpls_iptunnel(modprobe)

検証環境のトポロジーは下に記しました。

<img width="558" alt="e6f7aad0a17e125fad5aea8ad259d091.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/c8f88810-9b02-427b-c9c2-1c7f6f49856d.png">

今回の構成ですが、やや複雑に見えますが、蓋を開けてみれば、Ubuntuを2台[GNS3](https://www.gns3.com/)の中に作り、Ubuntuの中にnetnsの仮想空間を作っているだけでございます。netns on Ubuntu on GNS3みたいな？笑
実はよくよく世のLinuxのMPLSの先駆者の方々のブログを見ると、「ラベルをPop」と「ラベルをPush」まではやっているのですが「ラベルをSwap」までやっているブログは海外含め私は今のところ発見できていません笑（Pop、Push、Swapに関しては前述）。
ただ他のサイトを検証を丸パクリをするのもなんですし、この「ラベルをSwap」つまりラベル交換までやってみましょう！というのが今回の検証の大項目であります！

***
*もっとも、今回やるMPLSは『Static MPLS』と呼ばれるものでございます。
参考:http://www.networkers-online.com/blog/2009/01/static-routes-label-mapping-in-mpls/*

*普通、GoogleでMPLSを検索するとたいていは『LDP』や『RSVP』という動的にラベル情報を交換するプロトコルとセットで構築する前提で使われているのが目にいくとおもいます。一方、この『LDP』や『RSVP』を使わないで、経路に直接手打ちでラベル情報と経路情報をリンクさせてしまうのが『Static MPLS』となっております。今回はあくまでMPLSの動きだけ見たいし、QuaggaのLDPデーモンはまだ開発版ですので、『Static MPLS』でやっていきます。因みにStaticの方が段違いで設計が面倒です笑*
***

##とにかくやっていくのだぁ##
とりあえずVirtualboxとGNS3のくだりは本題から大幅にずれるので飛ばします。
VirtualboxでUbuntuを2台つくりーの、GNS3でUbuntuを2台つなぎーの、トツギーノでございまする！笑

<img width="960" alt="40f63b32be3cfc30b9da4aaa6a3f0bfa.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/576ff703-c060-30da-41c0-f701fed9b429.png">

とりあえずぴゃぴゃっと仮想環境を立ててしまい、次はネットワークの設定をする前のインストール作業をします。

##インストール作業##
事前準備ではUbunu2台分同じ事をしますのでそのつもりで(≧▽≦)

まずは今回、カーネルモジュールとしてmpls_routerを読み込むとします。
ですがそもそもLinuxカーネルとしてのサポートとしてMPLS Multipathとかサポートされたのはv4.3からだとか、[git.kernel.org](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=f8efb73c97e2fa0abbe2e07c5c5df07800312643)に書いてあります。

おっとちょうどいいところに、私のデスクトップにv4.6のURLがメモってあったのでそのカーネルにしてしまいます笑　([このサイト](http://pieknywidok.blogspot.jp/2015/12/mpls-testbed-on-ubuntu-linux-with.html)にはv4.3以上でやったほうがいいよ～って書いてあるので多分4.4とかならいけると思います適当)

```
# wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.6-yakkety/linux-headers-4.6.0-040600_4.6.0-040600.201606100558_all.deb
# wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.6-yakkety/linux-headers-4.6.0-040600-generic_4.6.0-040600.201606100558_amd64.deb
# wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.6-yakkety/linux-image-4.6.0-040600-generic_4.6.0-040600.201606100558_amd64.deb
# dpkg -i *.deb
# update-grub 
# reboot
```

```bat:uname
Linux ubuntu01-VirtualBox 4.6.0-040600-generic #201606100558 SMP Fri Jun 10 10:01:15 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
```

カーネルをv4.60にしました。
更に今回iproute及びiproute2を新しいものにコンパイルしてしまいます。
[此方のサイト](https://github.com/higebu/vyatta-iproute/releases/tag/debian/4.4.0-1vyos2)から、vyos/vyos-iprouteのiproute、iproute2のversion4.40を頂戴いたしました。

```
# wget https://github.com/higebu/vyatta-iproute/releases/download/debian%2F4.4.0-1vyos2/iproute_4.4.0-1vyos2_all.deb
# wget https://github.com/higebu/vyatta-iproute/releases/download/debian%2F4.4.0-1vyos2/iproute2_4.4.0-1vyos2_amd64.deb
# dpkg -i iproute_4.4.0-1vyos2_all.deb
# dpkg -i iproute2_4.4.0-1vyos2_amd64.deb
```
```bat:dpkg
# dpkg -l | grep iproute
ii  iproute                                              1:4.4.0-1vyos2                                all          transitional dummy package for iprout2
ii  iproute2                                             1:4.4.0-1vyos2                                amd64        networking and traffic control tools
ii  iproute2-doc                                         4.3.0-1ubuntu3                                all          networking and traffic control tools - documentation
```

iprouteもバージョンアップしました。

次に必要なカーネルモジュールを追加します。

```
# sudo modprobe mpls_gso
# sudo modprobe mpls_router
# sudo modprobe mpls_iptunnel
```

尚カーネルをv4.60にしていれば、今回はカーネルモジュールを再コンパイルしたり、なんて事は発生しませんのでご安心を。

ついで、ラベルの最大値を設定します。実はこれはMPLSのラベルを生成するのに必須設定となっております。他のサイトを参考にさせていただきますと

>mpls_routerを読み込むと /proc/sys/net/mpls 以下ができる。platform_labels は MPLS のラベルで扱う数字の最大値を決める。…これ制限する必要性はよくわからないけれど、一般的なMPLS ハードウェアルータでは設定するものが多い様子。とりあえず 64 あたりにしてみた。いずれにせよ mpls の最大値は 20bit を超えられない。それから 0--15 は予約されているものとして、使うことができない。
(参考:http://qiita.com/kwi/items/bccf38b69e089b729da9)

という事らしいですので、ま、気分で1000にします。
ところでCiscoのIOSではラベルの最大値は設定しますがCisco IOS XRやjuniper SRXとかでは設定は必要なかったイメージがありますが、ま、いいや。

```
# echo 1000 > /proc/sys/net/mpls/platform_labels
```
実際には、MPLSは20bitですので、16-1048576まで指定可能ですので、100万個くらいの経路には設定可能となるわけですね。

次に、今回のネットワーク基盤となる以下のnetns環境を構築していきます。ここからはUbuntu2台それぞれ分けて設定を行っていきます。

<img width="558" alt="e6f7aad0a17e125fad5aea8ad259d091.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/ec31db7c-c896-57d3-2f4a-90dc8e75a566.png">


***
*netns(netnsのmanページは[コチラ](http://man7.org/linux/man-pages/man8/ip-netns.8.html))とはなんだらホイ、と思ったかもしれませんが、こちらが参考になります。
http://kernhack.hatenablog.com/entry/2014/12/09/000827*

*仮想ホスト作成及び仮想NIC作成が出来る優れものであり、vethやnamespace等はopenstackやdocker等で使われる技術でありまして、かなりLinuxのカーネル準拠な仮想化技術となっております。namespaceを主に使用するので、ま、VMというよりコンテナですかね。
気軽に仮想ホストも作ることができ、また作成した仮想NICに対してtcpdump等も動きます。動作も安定しており、非常に使い勝手がよいネットワーク検証ソフトウェアと言えます。*
***

####環境設計####
とりあえずコマンドをだばーっと書きます。

```bat:ubuntu01
# ip link add veth0 type veth peer name veth1
# sysctl -w net.mpls.conf.veth0.input=1
# sysctl -w net.mpls.conf.eth1.input=1
# ifconfig veth0 10.0.0.1/24 up
# ip netns add host1
# ip link set veth1 netns host1
# ip netns exec host1 ifconfig lo 1.1.1.1/32 up
# ip netns exec host1 ifconfig veth1 10.0.0.2/24 up
```

```bat:ubuntu02
# ip link add veth2 type veth peer name veth3
# sysctl -w net.mpls.conf.veth2.input=1
# sysctl -w net.mpls.conf.eth1.input=1
# ifconfig veth2 30.0.0.1/24 up
# ip netns add host2
# ip link set veth3 netns host2
# ip netns exec host2 ifconfig lo 2.2.2.2/32 up
# ip netns exec host2 ifconfig veth3 30.0.0.2/24 up
```

環境周りはUbuntu01Ubuntu02どちらも左右対称な設定なのでUbuntu01だけを中心に説明させていただきます。

まず、

```
# ip link add veth0 type veth peer name veth1
# sysctl -w net.mpls.conf.veth0.input=1
# sysctl -w net.mpls.conf.eth1.input=1
```

ここでは仮想NICであるvethを作っています。
Linux界隈ではほぼvSwitchに美味しい所を持ってかれたvethですが笑 ただ「２つの仮想ノードを仮想的につなげる」というザ・シンプルな動きをします。
上記ではveth0-1という2つの仮想NICをくっついた状態で作ってあげます。
そして、vethを作り終わったらeth1とveth0にmplsのラベル受信を許可します。

ついで、

```
# ip netns add host1
# ip link set veth1 netns host1
# ip netns exec host1 ifconfig lo 1.1.1.1/32 up
# ip netns exec host1 ifconfig veth1 10.0.0.2/24 up
```

作成したvethにアドレスを振り、仮想ホストhost1を作成します。
そしてついにvethとhostを接続しますが、少しわかりにくい点があります。
veth0は作成した時に既に本体のUbuntuにくっついておりますが、その先のveth1は浮いています。
ので、ip link set veth netns hostという形で浮いているveth1を仮想hostに差し込み、その後に仮想ホストのアドレスを振っていく流れとなっております。

そして最後に重要な所、フォワーディングテーブル、つまりラベルをつけるルールを設定いたします。ここからはUbuntu02と共にネットワーク設計全体を見ていきましょう

####ネットワーク設計####
そもそも、今回のネットワークですが、大まかな流れを以下に記しました。
<img width="600" alt="ac173eb74222c09e4c715766c92cbdf8.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/fe7e95af-2009-e1cd-df2f-87230e57005d.png">

<img width="600" alt="bdfff4732eefff60a49c3c5deba74023.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/20f10718-c7a3-0315-f9c6-c3a07cc7869b.png">


それぞれの役割として、

☆宛先2.2.2.2の場合
仮想host1⇒宛先2.2.2.2/32のパケットに対して、ラベル101をつけて(Push!)ネクストホップ10.0.0.1に投げる
Ubuntu01⇒ラベル101をつけたパケットが来たら111に付け替えて(Pop+Push=Swap!)ネクストホップ20.0.0.2に投げる
Ubuntu02⇒ラベル111をつけたパケットが来たらラベルを外して(Pop!)ネクストホップ30.0.0.2に投げる

☆宛先1.1.1.1の場合
仮想host2⇒宛先1.1.1.1/32のパケットに対して、ラベル201をつけて(Push!)ネクストホップ30.0.0.1に投げる
Ubuntu02⇒ラベル201をつけたパケットが来たら211に付け替えて(Pop+Push=Swap!)ネクストホップ20.0.0.1に投げる
Ubuntu01⇒ラベル211をつけたパケットが来たらラベルを外して(Pop!)ネクストホップ10.0.0.2に投げる

という設計にしていきまする。これを設定に反映するとこうなります。

```bat:ubuntu01
# ip netns exec host1 ip route add 2.2.2.2/32 encap mpls 101 via inet 10.0.0.1
# ip -f mpls route add 101 via inet 20.0.0.2 as 111
# ip -f mpls route add 211 via inet 10.0.0.2 
```

```bat:ubuntu02
# ip netns exec host2 ip route add 1.1.1.1/32 encap mpls 201 via inet 30.0.0.1
# ip -f mpls route add 201 via inet 20.0.0.1 as 211
# ip -f mpls route add 111 via inet 30.0.0.2 
```

さて、最後にちゃんとアドレスやフォワーディングテーブルに適用されているか確認いたします。

```bat:Ubuntu01Interface情報
# ip addr
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:bb:53:39 brd ff:ff:ff:ff:ff:ff
    inet 20.0.0.1/24 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:febb:5339/64 scope link 
       valid_lft forever preferred_lft forever
6: veth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 62:25:5e:be:b4:87 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.0.1/24 brd 10.0.0.255 scope global veth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6025:5eff:febe:b487/64 scope link 
       valid_lft forever preferred_lft forever

# ip netns exec host1 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/0 scope host lo
       valid_lft forever preferred_lft forever
    inet 1.1.1.1/32 scope global lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
5: veth1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 3e:1e:b0:36:b7:f7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.0.2/24 brd 10.0.0.255 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::3c1e:b0ff:fe36:b7f7/64 scope link 
       valid_lft forever preferred_lft forever
```
```bat:Ubuntu01フォワーディングテーブル情報
# ip -M route
101 as to 111 via inet 20.0.0.2 dev eth1 
211 via inet 10.0.0.2 dev veth0 

# ip netns exec host1 ip route
2.2.2.2  encap mpls  101 via 10.0.0.1 dev veth1 
10.0.0.0/24 dev veth1  proto kernel  scope link  src 10.0.0.2
```

```bat:Ubuntu02Interface情報
# ip addr
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:57:b9:5b brd ff:ff:ff:ff:ff:ff
    inet 20.0.0.2/24 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe57:b95b/64 scope link 
       valid_lft forever preferred_lft forever
6: veth2@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether fa:29:06:fc:29:26 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 30.0.0.1/24 brd 30.0.0.255 scope global veth2
       valid_lft forever preferred_lft forever
    inet6 fe80::f829:6ff:fefc:2926/64 scope link 
       valid_lft forever preferred_lft forever

# ip netns exec host2 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/0 scope host lo
       valid_lft forever preferred_lft forever
    inet 2.2.2.2/32 scope global lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
5: veth3@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 3e:8b:48:f0:90:41 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 30.0.0.2/24 brd 30.0.0.255 scope global veth3
       valid_lft forever preferred_lft forever
    inet6 fe80::3c8b:48ff:fef0:9041/64 scope link 
       valid_lft forever preferred_lft forever
```


```bat:Ubuntu02フォワーディングテーブル
# ip -M  route
111 via inet 30.0.0.2 dev veth2 
201 as to 211 via inet 20.0.0.1 dev eth1 
# ip netns exec host2 ip route
1.1.1.1  encap mpls  201 via 30.0.0.1 dev veth3 
30.0.0.0/24 dev veth3  proto kernel  scope link  src 30.0.0.2 
```

##さぁて検証なのら！##

検証はPingとWiresharkで確認いたします。

####れっつら疎通確認♪####

```bat:ubuntu01
# ip netns exec host1 ping 2.2.2.2 -I 1.1.1.1
PING 2.2.2.2 (2.2.2.2) from 1.1.1.1 : 56(84) bytes of data.
64 bytes from 2.2.2.2: icmp_seq=1 ttl=62 time=0.430 ms
64 bytes from 2.2.2.2: icmp_seq=2 ttl=62 time=0.384 ms
64 bytes from 2.2.2.2: icmp_seq=3 ttl=62 time=0.478 ms
64 bytes from 2.2.2.2: icmp_seq=4 ttl=62 time=0.715 ms
64 bytes from 2.2.2.2: icmp_seq=5 ttl=62 time=0.494 ms
^C
--- 2.2.2.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.384/0.500/0.715/0.114 ms
```

```bat:ubuntu02
# ip netns exec host2 ping 1.1.1.1 -I 2.2.2.2
PING 1.1.1.1 (1.1.1.1) from 2.2.2.2 : 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=62 time=0.536 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=62 time=1.06 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=62 time=0.530 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=62 time=1.16 ms
64 bytes from 1.1.1.1: icmp_seq=5 ttl=62 time=0.570 ms
^C
--- 1.1.1.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4002ms
rtt min/avg/max/mdev = 0.530/0.771/1.160/0.281 ms
```

お～疎通出来ています。

####れっつらWireshark♪####

***

☆宛先2.2.2.2のパケットでWireshark！

[host1]--[veth0]--[Ubuntu01]--[eth1]--[eth1]--[Ubuntu02]--[veth2]--[host2]

#####To2.2.2.2_Ubuntu01_veth0#####
<img width="481" alt="0d81b27bd31ddf824b6bc0dbb2a32c41.jpng.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/c4af3ecc-2244-a84c-c38b-526733e4d5d2.png">

ラベル101つけております！

#####To2.2.2.2_Ubuntu01_eth1#####
<img width="483" alt="9b8846e8c8ebc25752213055164b59fe.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/4caa2f75-4ca5-0544-87e0-2ecc84c91c3d.png">

ラベル111つけております！

#####To2.2.2.2_Ubuntu02_eth1#####
<img width="480" alt="87749e45de069b993c199950d6ad0bf9.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/8cc34450-7f35-da74-0a95-f0f270469936.png">

ラベル111つけております！

#####To2.2.2.2_Ubuntu02_veth2#####
<img width="481" alt="10ad9ad20e48c32a11c217dbe1f5c6d4.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/5783a108-108a-dbd5-a59a-0afd6a25a0fd.png">

ラベルをPop!しております！

***

☆宛先1.1.1.1のパケットでWireshark！

[host1]--[veth0]--[Ubuntu01]--[eth1]--[eth1]--[Ubuntu02]--[veth2]--[host2]

#####To1.1.1.1_Ubuntu02_veth2#####
<img width="480" alt="85005ecdaa5f7324d5adc49d45a7ddd2.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/8dc7ca3a-bc36-55be-a9b5-eeca65309ff7.png">

ラベル201をつけております！

#####To1.1.1.1_Ubuntu02_eth1#####
<img width="480" alt="6716dbb2a2cf5c9b02121a11363d0a60.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/bf99a786-9e08-525a-ee45-14f911ead7c0.png">

ラベル211をつけております！

#####To1.1.1.1_Ubuntu01_eth1#####
<img width="479" alt="43dff543b9633edadceb88e3e80b851f.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/c03cd4c2-a1f0-8b09-32f9-19087bd83f5c.png">

ラベル211をつけております！

#####To1.1.1.1_Ubuntu01_veth0#####
<img width="481" alt="415ded4f5b2a85b1c35d40f0029ef1f6.png" src="https://qiita-image-store.s3.amazonaws.com/0/124502/262046ee-f24d-c34a-980f-4a04b71f7d49.png">

ラベルをPopしております！

***

ミッションコンプリーーーーーーーーーーーート！！！笑

##おわりのごあいさつ##
というわけでnetns内でMPLSのラベル貼りを見ることに成功しました。
実はこれ、最初ラベルのmpls_routerのラベルSwapの資料があまりにも無い上にうまくいかず、作っては壊しコンパイルしてはエラーの繰り返しで笑 最後の最後まで粘っていたら出来上がった次第です笑

今回はただただラベルをPopPushSwapさせただけとなりますが、
実際にはMPLSのラベルは高速化以外にもRSVPと組み合わせる事で帯域制御を行うRSVP-TEであったり、MP-BGPと組み合わせる事によりL2VPNやL3VPNとして使えるようになります。こういったように今までは「最短経路を選ぶ」という事で偏っていたり、VMのマイグレーションによるVM移動によるARP解決に切り戻しに時間かかっていたものをMPLSに色々な情報を載せる事により解決出来たりと、ラベルをただ貼るだけ以外にもMPLSは活躍出来る舞台はいっぱいあります。

そこにLinuxとして最近標準搭載してきたMPLSでありますので、より柔軟なルーティングが手軽に、汎用的に使われるようになる事を期待しております。またぜひ、MPLSの導入をご検討してください笑