bgp deterministic-med ってなんなんだ

# BGP について

ルーティングプロトコルです。
詳しいことはすごい人がいっぱい書いているので割愛します…

今回は

- ルータ間でルーティングに必要な情報を交換する。
- Path Attributeと言われる要素を元に最適な経路を決める。

くらいの認識で話を進めます。

# 本題
`bgp deterministic-med` … CiscoのBGP設定に出てくるコマンドですが、個人的には**よくわからない**です。

> Enabling the bgp deterministic-med command removes any temporal dependency of MED-based best path decisions. It ensures that an accurate MED comparison is made across all routes received from the same autonomous system (AS).

（参考のCiscoページより引用）

じゃあ実際に動かしてみるぞ。

# 環境

お家に1812Jがあった。
1812JのPeerはvyosを使うことにする。

結局は以下のようにする。

![Untitled Diagram(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/63c79df5-8d7b-90e6-4d37-4371c64f055b.png)

ここでvyos-1、vyos-2、vyos-3 は192.168.2.0/24 をBGPテーブルにinjectしてeBGPで1812Jに広告する。

この192.168.2.0/24への最適経路選択でコマンドの影響を確認する。

バージョンはこんな感じ。

```shell:1812J
1812J#show version 
Cisco IOS Software, C181X Software (C181X-ADVIPSERVICESK9-M), Version 12.4(6)T9, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
# 以下略
```

```shell:vyos
vyos@vyos-1:~$ show version 
Version:          VyOS 1.3-rolling-202001120217
Built by:         autobuild@vyos.net
Built on:         Sun 12 Jan 2020 02:17 UTC
Build UUID:       528774ae-16c7-4ad8-afd0-9ff9ed7008f1
Build Commit ID:  2b332ea0c3cd73

# 以下略

```

# BGP設定

とりあえずBGPを設定する。

```shell:1812J
1812J#show configuration | begin bgp
# no synchronization、bgp log-neighbor-changes、no auto-summaryはデフォルト。
# bgp bestpath compare-routeridを有効にする。後で登場。
router bgp 65009
 no synchronization
 bgp router-id 9.9.9.9
 bgp log-neighbor-changes
 bgp bestpath compare-routerid
 neighbor 192.168.1.1 remote-as 65012
 neighbor 192.168.1.2 remote-as 65012
 neighbor 192.168.1.3 remote-as 65003
 no auto-summary
!
# 以下略
```

```shell:vyos
# vyos-1の場合。vyos-2、vyos-3は図に合わせる。
set interfaces ethernet eth0 address 192.168.2.1/24
set interfaces ethernet eth1 address 192.168.1.1/24

set protocols bgp 65012 parameters router-id 1.1.1.1
set protocols bgp 65012 address-family ipv4-unicast network 192.168.2.0/24
set protocols bgp 65012 neighbor 192.168.1.9 remote-as 65009
```

うまくつながれば以下のようになる。

```shell:1812J
1812J#show ip bgp summary 
BGP router identifier 9.9.9.9, local AS number 65009
BGP table version is 14, main routing table version 14
1 network entries using 117 bytes of memory
3 path entries using 156 bytes of memory
4/1 BGP path/bestpath attribute entries using 496 bytes of memory
2 BGP AS-PATH entries using 48 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 817 total bytes of memory
BGP activity 1/0 prefixes, 22/19 paths, scan interval 60 secs

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
192.168.1.1     4 65012     171     193       14    0    0 00:17:39        1
192.168.1.2     4 65012     172     190       14    0    0 00:17:22        1
192.168.1.3     4 65003     163     178       14    0    0 00:17:55        1
```

`State/PfxRcd`が1以外なら何かがおかしい。

```shell:vyos
vyos@vyos-1:~$ show ip bgp summary 

IPv4 Unicast Summary:
BGP router identifier 1.1.1.1, local AS number 65012 vrf-id 0
BGP table version 1
RIB entries 1, using 184 bytes of memory
Peers 1, using 20 KiB of memory

Neighbor        V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd
192.168.1.9     4      65009      57      54        0    0    0 00:40:44            0

Total number of neighbors 1
```
`State/PfxRcd`は0でよい。

1812JのBGPテーブルは以下のようになる。

```shell:show_bgp
1812J#show ip bgp 
BGP table version is 16, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.3              0             0 65003 i
*                   192.168.1.2              0             0 65012 i
*>                  192.168.1.1              0             0 65012 i
```
最適経路として、`192.168.1.1` (vyos-1) が選ばれている。

# MED設定

ここにMEDを設定する。

```shell:vyos
set policy route-map SET-MED-10 rule 1 action permit
set policy route-map SET-MED-10 rule 1 set metric 10
# metricを変える。

set protocols bgp 65012 neighbor 192.168.1.9 address-family ipv4-unicast route-map export SET-MED-10
```

結果はこうなる。
Metric、の部分にMEDが表示される。
MEDが小さいvyos-2経由が選ばれる。

```shell:1812J
1812J#show ip bgp 
BGP table version is 17, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.3             15             0 65003 i
*>                  192.168.1.2              5             0 65012 i
*                   192.168.1.1             10             0 65012 i
``` 

実を言えば、このときvyos-3のMEDは使われていない。 MEDを低くしても同様の結果になる。

```shell:1812J
1812J#show ip bgp 
BGP table version is 21, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.3              0             0 65003 i
*>                  192.168.1.2              5             0 65012 i
*                   192.168.1.1             10             0 65012 i
```

# 問題の発生

実はこの設定では問題が起きない。
問題を起こすため、vyos-2のrouter-idをvyos-3より大きくする。

```shell:vyos-2
set protocols bgp 65012 parameters router-id 22.2.2.2
```

router-id変更によってvyos-2のBGPプロセスが再起動し、ログが表示される。

その時、不思議なことが起こった！

```shell:1812J
1812J#                    
*Jan 12 16:48:25.367: %BGP-3-NOTIFICATION: received from neighbor 192.168.1.2 6/6 (cease) 0 bytes 
*Jan 12 16:48:25.367: %BGP-5-ADJCHANGE: neighbor 192.168.1.2 Down BGP Notification received
*Jan 12 16:48:27.371: %BGP-5-ADJCHANGE: neighbor 192.168.1.2 U

1812J#show ip bgp             
BGP table version is 22, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.2              5             0 65012 i
*                   192.168.1.3              0             0 65003 i
*>                  192.168.1.1             10             0 65012 i
```

MEDが大きいvyos-1経由が最適経路になっている。

更におかしいのはここから。
vyos-1とのpeerをclearする。

```shell:1812J
1812J#
*Jan 12 16:50:27.367: %BGP-5-ADJCHANGE: neighbor 192.168.1.1 Down User reset
*Jan 12 16:50:27.371: %BGP-5-ADJCHANGE: neighbor 192.168.1.1 Up 

1812J#show ip bgp             
BGP table version is 23, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.1             10             0 65012 i
*                   192.168.1.2              5             0 65012 i
*>                  192.168.1.3              0             0 65003 i
```

今度はvyos-3が選ばれてしまった。
もっとやってみる。

```shell:1812J
1812J#clear ip bgp 192.168.1.3
1812J#
*Jan 12 16:51:30.471: %BGP-5-ADJCHANGE: neighbor 192.168.1.3 Down User reset
*Jan 12 16:51:30.475: %BGP-5-ADJCHANGE: neighbor 192.168.1.3 Up

1812J#show ip bgp             
BGP table version is 24, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.3              0             0 65003 i
*                   192.168.1.1             10             0 65012 i
*>                  192.168.1.2              5             0 65012 i

----------------------------------------------
1812J#clear ip bgp 192.168.1.1
1812J#
*Jan 12 16:52:58.571: %BGP-5-ADJCHANGE: neighbor 192.168.1.1 Down User reset
*Jan 12 16:52:58.575: %BGP-5-ADJCHANGE: neighbor 192.168.1.1 Up 

1812J#show ip bgp             
BGP table version is 24, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.1             10             0 65012 i
*                   192.168.1.3              0             0 65003 i
*>                  192.168.1.2              5             0 65012 i
```

# 結局何が問題なのか

MEDを利用するとき、ネットワーク情報を受信する順番によって、最適経路が変わってしまう。

BGPの最適経路選択は（今回の機器では）以下を**順に**評価する

0. 前略、LOCAL_PREFとか
1. AS_PATH lengthが小さい
2. MEDが小さい（最近のASが同じときのみ評価）
3. iBGPよりeBGP
4. Next Hopへのメトリックが小さい
5. router-idが小さい（`bgp bestpath compare-routerid`が有効なとき）
6. 後略

BGPテーブルをどうやって評価し、最適経路を決定するかは以下のようになる。

- BGPテーブルの一番上と二番目のネットワーク情報に注目する。
- 注目した二つについて、上記評価を**順に**実施する。この時、ある評価項目においてどちらかが優れていれば、そこで評価を終了する。**それ以降の項目は評価しない。**
- 優れていた方のネットワーク情報と、BGPテーブルの三つ目に注目する。以下同様に進める。
- 全てのネットワーク情報を評価したとき、最後に優れていた方が最適経路となる。

**ここで、今回何が起こったか見てみる。**

BGBテーブルがvyos-1、vyos-2、vyos-3の順であるとき、

1. vyos-1とvyos-2に注目する。最近のAS はどちらも65012だから、MEDの評価をする。 MEDが小さいvyos-2が優れている。
2. vyos-2とvyos-3に注目する。最近のASが異なるため、MEDの評価をしない。二つともeBGPであり、Next Hopへのメトリックも同じ。router-idが小さいvyos-3が優れている。

こうしてvyos-3経由が最適として選択される。
こんな感じ。

|BGPテーブルの位置|経由|最近のAS|MED|router-id|
|---|---|---|---|---|
|1|vyos-1|65012|10|1.1.1.1|
|2|vyos-2|65012|5|22.2.2.2| 
|||同じAS|vyos-2の勝ち|評価しない|

|BGPテーブルの位置|経由|最近のAS|MED|router-id|
|---|---|---|---|---|
|2|vyos-2|65012|5|22.2.2.2|
|3|vyos-3|65003|0|3.3.3.3| 
|||異なるAS|評価しない|vyos-3の勝ち|

BGPテーブルがvyos-2、vyos-3、vyos-1の順であれば、

1. vyos-2とvyos-3に注目する。最近のAS が異なるため、MEDの評価をしない。 router-idが小さいvyos-3が優れている。
2. vyos-3とvyos-1に注目する。最近のASが異なるため、MEDの評価をしない。router-idの小さいvyos-1が優れる。

こうしてvyos-1経由が最適として選択される。

こんな感じ。

|BGPテーブルの位置|経由|最近のAS|MED|router-id|
|---|---|---|---|---|
|1|vyos-2|65012|5|22.2.2.2|
|2|vyos-3|65003|0|3.3.3.3| 
|||異なるAS|評価しない|vyos-3の勝ち|

|BGPテーブルの位置|経由|最近のAS|MED|router-id|
|---|---|---|---|---|
|2|vyos-3|65003|0|3.3.3.3|
|3|vyos-1|65012|10|1.1.1.1| 
|||異なるAS|評価しない|vyos-1の勝ち|

このように、BGPテーブルの順によって、最適な経路が変わってしまう。

# ここでdeterministic-medの出番である

これの対策が `bgp deterministic-med`。
以下のように設定する。

```shell:1812J
1812J(config)#router bgp 65009
1812J(config-router)#bgp deterministic-med
```
すると…

```shell:1812J
1812J#clear ip bgp 192.168.1.1
1812J#
*Jan 12 17:41:52.911: %BGP-5-ADJCHANGE: neighbor 192.168.1.1 Down User reset
*Jan 12 17:41:53.927: %BGP-5-ADJCHANGE: neighbor 192.168.1.1 Up 
1812J#
1812J#show ip bgp             
BGP table version is 29, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 192.168.2.0      192.168.1.3              0             0 65003 i
*                   192.168.1.2              5             0 65012 i
*                   192.168.1.1             10             0 65012 i

----------------------------------------------
1812J#clear ip bgp 192.168.1.3
1812J#
*Jan 12 17:42:41.007: %BGP-5-ADJCHANGE: neighbor 192.168.1.3 Down User reset
*Jan 12 17:42:41.011: %BGP-5-ADJCHANGE: neighbor 192.168.1.3 Up 
1812J#                        
1812J#show ip bgp             
BGP table version is 31, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 192.168.2.0      192.168.1.3              0             0 65003 i
*                   192.168.1.2              5             0 65012 i
*                   192.168.1.1             10             0 65012 i


----------------------------------------------
1812J#clear ip bgp 192.168.1.2
1812J#
*Jan 12 17:43:27.007: %BGP-5-ADJCHANGE: neighbor 192.168.1.2 Down User reset
*Jan 12 17:43:28.023: %BGP-5-ADJCHANGE: neighbor 192.168.1.2 Up 
1812J#
1812J#show ip bgp             
BGP table version is 31, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 192.168.2.0      192.168.1.3              0             0 65003 i
*                   192.168.1.2              5             0 65012 i
*                   192.168.1.1             10             0 65012 i
```
常にvyos-3が選ばれる。

これは最適経路を決定する方法が変わったため。

1. あるASについて、そのASを最近のASとするネットワーク情報に注目し、その中で最適なものを決める。最近のASが同じだからMEDを評価する。
2. 全てのASについて、同様に最適なものを決める。
3. ASごとの最適なネットワーク情報の中で、最適なものを最適経路とする。

今回は
1. 最近のASが65012の中では、vyos-2経由のMEDが小さい。vyos-2を選ぶ。
2. 最近のASが65003のものはvyos-3経由しかない。
3. vyos-2とvyos-3を比べる。router-idの小さいvyos-3が選ばれる。

ここでvyos-1のrouter-idはvyos-3より小さいから、`1.`でvyos-1が選ばれればvyos-1が最適経路になるはず。
vyos-1のMEDをvyos-2より小さくする。

```shell:vyos-1
set policy route-map SET-MED-10 rule 1 set metric 3
```

```shell:1812J
1812J#show ip bgp
BGP table version is 32, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  192.168.2.0      192.168.1.3              0             0 65003 i
*>                  192.168.1.1              3             0 65012 i
*                   192.168.1.2              5             0 65012 i
```

vyos-1経由が選ばれた。

# まとめ

deterministic-medは**複数のASから広告を受け**、かつ**ASごとにMEDの評価をする場合**に最適経路選択に一貫性を持たせるものっぽい。

**奥が深いなぁ…（しみじみ）**

#bgp always-compare-medについて

よく一緒に語られるコマンドに`bgp always-compare-med`があります。
これを有効にすると、異なるASでもMEDを比較するようになるみたいです。

```shell:1812J
1812J(config)#router bgp 65009
1812J(config-router)#bgp always-compare-med

1812J#show ip bgp 
BGP table version is 5, local router ID is 9.9.9.9
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 192.168.2.0      192.168.1.3              0             0 65003 i
*                   192.168.1.1              3             0 65012 i
*                   192.168.1.2              5             0 65012 i
```
MEDの小さいvyos-3が選ばれる。

# 参考

BGP で最適パスを選択するアルゴリズム (Document ID:13753)
https://www.cisco.com/c/ja_jp/support/docs/ip/border-gateway-protocol-bgp/13753-25.html

How BGP Routers Use the Multi-Exit Discriminator for Best Path Selection (Document ID:13759)
https://www.cisco.com/c/en/us/support/docs/ip/border-gateway-protocol-bgp/13759-37.html

# ちなみに

物理的にはこうなっている。
![phys.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547524/09b5127e-38fc-4b10-8c60-f5391851b82b.png)

vyosをlibvirtで作るときはこう！
（bridgeなどは事前に作っておく。）

```shell:example
virt-install --disk size=16,bus=virtio,pool=nlvol0 \
  --network type=bridge,model=virtio,source=linbr0 \
  --network type=direct,source=enp4s0,source.mode=vepa \
  --memory 4096 --graphics vnc --cdrom /var/lib/libvirt/images/vyos-1.3-rolling-202001120217-amd64.iso \
  --name vyos-1

# そしてこう！
virt-clone --file /var/lib/libvirt/nimages/vyos-2 --name vyos-2 --original vyos-1
```