VyOSにおけるOSPFコストの計算ロジック

#1. はじめに
[先日設定したOSPF設定](http://qiita.com/testnin2/items/468daaa714bfd98ad366)でコストについて気になったのでメモ

- 実はこのVyOS環境は100Mbps NICの仮想サーバーを注文していた
- OSPFのデフォルトのコスト計算では、
    - コスト = 100Mbps　/ 帯域幅 (Mbps) <br>のようになる。よって、10Mbpsのコストは10だし、100Mbpsや1Gbpsのコストは全部1になってくれるハズ。
- しかし、`show ip ospf interface`や`show ip route`の結果を見ると各インターフェースのコストは10になっている。

というのでその理由を探ってみた。

※ちなみに、100Mbps/大域幅（Mbps）でコスト計算するというのは、今の時代には合っていない。100Mbpsの時のコスト値は1だが、1Gbpsや10Gbpsでのコスト値も1になってしまう。そこで、もっと大きな値をコスト計算の分子として使うことで100Mbps以上のインターフェースでコストの違いを出すために考えられたのが、reference-bandwidthというパラメーター。reference-bandwidthを10Gbpsにしておけば、10Mbps/100Mbps/1Gbps/10Gbpsでコスト値はそれぞれ1000,100,10,1になる。当然だが、reference-bandwidthを変更する際には利用しているルーター全部で変更してコスト評価の基準をそろえるべき。

#2. 仮想サーバーのNICの速度を調べてみた
まずはこの仮想サーバーの仮想NICの速度を確認してみようと思ったのだが、そもそもethtoolコマンドなどを実行しても出てこない！もしかしたら、「NIC速度を認識できないEthernet環境では、OSPFは該当リンクを10Mbpsとみなす」という暗黙の前提があるのかもしれないと思って次にソースを見てみた。

```txt:NICの速度調査
vyos@vyostok1:~$ show interfaces ethernet eth0 physical
Settings for eth0:
        Link detected: yes
driver: vif
version:
firmware-version:
bus-info: vif-0
vyos@vyostok1:~$ sudo ethtool eth0
Settings for eth0:
        Link detected: yes
```

#3. 実際のソースを見てみた

以下の順序で計算が行われているっぽい

1. インターフェースからbandwidthを取得する。取得できなかった場合には、OSPF_DEFAULT_BANDWIDTH（10000Kbps=10Mbps)を利用する。
2. インターフェースに明示的に設定したコストがあれば、その値をコストとして採用する
3. reference-bandwidth（デフォルト値はOSPF_DEFAULT_REF_BANDWIDTHであり100000  Kbps=100Mbps)をbandwidthで割ったものをコストとして採用する。（0.5を足してintでcastしているのは四捨五入のためだと思われる）

以下、ソースの抜粋。

```c:ospf_interface.c
#https://github.com/vyos/vyos-frr/blob/current/ospfd/ospf_interface.c
62: bw = oi->ifp->bandwidth ? oi->ifp->bandwidth : OSPF_DEFAULT_BANDWIDTH;
63: refbw = oi->ospf->ref_bandwidth;
73:       cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5);
```

```c:ospfd.c
#https://github.com/vyos/vyos-frr/blob/current/ospfd/ospfd.c
250:  new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
```

```c:ospfd.h
#https://github.com/vyos/vyatta-quagga/blob/current/ospfd/ospfd.h
 93:  /* OSPF interface default values. */
 94: #define OSPF_OUTPUT_COST_DEFAULT           10
 95: #define OSPF_OUTPUT_COST_INFINITE	   UINT16_MAX
 96: #define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT  40
 97: #define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL   1
 98: #define OSPF_HELLO_INTERVAL_DEFAULT        10
 99: #define OSPF_ROUTER_PRIORITY_DEFAULT        1
100: #define OSPF_RETRANSMIT_INTERVAL_DEFAULT    5
101: #define OSPF_TRANSMIT_DELAY_DEFAULT         1
102: #define OSPF_DEFAULT_BANDWIDTH		 10000	/* Kbps */
103:
104: #define OSPF_DEFAULT_REF_BANDWIDTH	100000  /* Kbps */
105:
106: #define OSPF_POLL_INTERVAL_DEFAULT         60
107: #define OSPF_NEIGHBOR_PRIORITY_DEFAULT      0
108:
109: #define OSPF_MTU_IGNORE_DEFAULT             0
110: #define OSPF_FAST_HELLO_DEFAULT             0
```

#参考. 対応するコマンド
```
vyos@vyostok1# set interfaces ethernet eth0 ip ospf cost
Possible completions:
   <1-65535>    OSPF interface cost
```
```
vyos@vyostok1# set interfaces ethernet eth0 ip ospf bandwidth
Possible completions:
   <1-10000000> Bandwidth in kilobits/sec (for calculating OSPF cost)
```
```
vyos@vyostok1# set protocols ospf auto-cost reference-bandwidth
Possible completions:
   <1-4294967>  Reference bandwidth cost in Mbits/sec (default 100)
```