覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

ルーティングプロトコル - IGP

「インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門 第2版」を読んでおります。
まだ読んでる途中ですが、めちゃくちゃいい本だと思います。とにかくわかり易いです。
普段プログラミングがメインでインフラ(ネットワーク)と縁遠い人も読んでみる価値あると思います。


この本でなくてもネット上に情報はあると思いますが、
本書籍に書かれているルーティングプロトコルの IGP(Interior Gateway Protocol, 内部ゲートウェイプロトコル) について記録しておくたくなったので、ここにメモしておきます。


ルーティングテーブル

ネットワークのルーティングを司っているのがルーティングテーブルで、このルーティングテーブルをどうやって作るのかがネットワーク層のポイントとなる。
ルーティングテーブルの作り方は大きく分けて 静的ルーティング動的ルーティング の二つがある。

  • 静的ルーティング
    • 手動でルーティングテーブルを作る方法
    • 一つ一つ宛先ネットワークとネクストホップを設定する
    • 管理もしやすいので、小さなネットワーク環境のルーティングに適している。
  • 動的ルーティング
    • 隣接するルータ同士で自分の持っているルート情報を交換して、自動でルーティングテーブルを作る方法
    • ルート情報を交換するプロトコルを ルーティングプロトコル という
    • 大きなネットワーク環境や構成が変わりやすいネットワーク環境であれば動的ルーティングを使用した方がよい
    • 宛先のどこかに障害が発生した場合も、動的に迂回ルートを探してくれるため耐障害性も向上する


2種類のルーティングプロトコル

ルーティングプロトコルはその制御範囲によって以下2種類に分けられる

  • IGP(Interior Gateway Protocol, 内部ゲートウェイプロトコル)
  • EGP(Exterior Gateway Protocol, 外部ゲートウェイプロトコル)

この2つを分ける概念が AS(Autonomous System, 自律システム)
ASは一つのポリシーに基づいて管理されているネットワークの集まりのことで、例えばAS=組織(ISP, 企業, 研究機関, 拠点) のような感じでとらえると良い。
AS内を制御するルーティングプロトコルが IGP, ASとASの間を制御するルーティングプロトコルが EGP。


IGP

色々なIGPが存在するが、現在のネットワーク環境で使用されているプロトコルは RIPv2(Routing Information Protocol version2), OSPF(Open Shortest Path Fast), EIGRP(Enhanced Interior Gateway Routing) のどれかと考えて良い。

これらを説明する上でのポイントが ルーティングアルゴリズムメトリック の二つ。

  • ルーティングアルゴリズム
    • どうやってルーティングテーブルを作るかのルール
    • ルーティングアルゴリズムの違いが収束時間(ネットワーク上のルータがすべてのルートを認識している状態(収束状態)になるまでにかかる時間)や適用規模に直結する
    • IGPのルーティングアルゴリズムは ディスタンスベクタ型リンクステート型 のどちらか
      • ディスタンスベクタ型は、距離(ディスタンス)と方向(ベクタ)にもどついてルートを計算する
        • ここでいう距離とは宛先に行くまでに経由するルータの数(ホップ数)を表し、方向は出力インターフェースを表す
      • リンクステート型は、リンクの状態(ステート)に基づいて最適ルートを計算する
        • 各ルータが自分のリンク(インターフェース)の状態や帯域、IPアドレス等色々な情報を交換してあってデータベースを作り、それをもとにルーティングテーブルを作る
  • メトリック
    • 宛先ネットワークまでの距離を表している
      • ここでいう距離とは物理的な距離ではなく、ネットワークにおける論理的な距離


RIPv2 / OSPF / EIGRP

先にも書いた通り、現在のネットワーク環境で使用されているIGPのルーティングプロトコルは、RIPv2, OSPF, EIGRP のどれか。

RIPv2 OSPF EIGRP
ルーティングアルゴリズム ディスタンスベクタ型 リンクステート型 ディスタンスベクタ型
(ハイブリッド型)
メトリック ホップ数 コスト 帯域幅+遅延
更新間隔 定期的 変更があったとき 変更があったとき
更新に使用する
マルチキャストアドレス
224.0.0.9 224.0.0.5 (ALL OSPF ルータ)
224.0.0.6 (ALL DR ルータ)
224.0.0.10
適用規模 小規模 中規模〜大規模 中規模〜大規模

RIPv2

  • 最近ではあまり見られないが、古い環境にたまに残っている
    • そこからOSPFやEIGRPに移行することがある
    • 新しく作るネットワークでこのプロトコルを使用する必要性は無い
  • RIPv2はルーティングテーブルそのものを定期的にやり取りしあうことで、ルーティングテーブルを作る
  • 動きはとても分かりやすいが、ルーティングテーブルが大きくなればなるほど余計な帯域を消費し、収束にも時間がかかるため大規模なネットワーク環境には不向き
  • メトリックにはホップ数を使用している
    • ルータを経由すればするほど遠いという扱いになる
    • 途中の経路の帯域が小さくても、ホップ数が小さいルートを最適ルートとしてしまうため難がある


OFPF

  • RFCで標準化されているルーティングプロトコルということもあって、マルチベンダのネットワーク環境ではOSPFを使用することが多い
  • OSPFは各ルータがリンク状態や帯域、IPアドレス、ネットワークなど色々な情報を交換しあって「リンクステートデータベース(LSDB)」を作る
    • そこから最適なルート情報を計算し、ルーティングテーブルを作る
  • (RIPv2は定期的にルーティングテーブルを送りあっているのに対して、)OSFPは変更があったときにだけ更新がかかる
    • 通常時は Helloパケットという小さなパケットを送信して、相手が正常に動作しているかどうかだけを確認しているため、必要以上に帯域を圧迫することがない
  • LSDBが大きくなりすぎないように、ネットワークをエリアというものに分けて、同じエリアのルーだだけでLSDBを共有する
  • メトリックに使用するコストは、デフォルトで「100 / 帯域幅(Mbps)」に当てはめて整数値として算出され、ルータを超えるたびに出力インターフェースで加算される
    • したがって、ルートの帯域が大きければ大きいほど最短ルートになりやすい
    • 学習したコストが全く同じだった場合は、コストが同じルートを全て使用してパケットを運び、ルートの負荷分散を行う
      • このような動作を ECMP(Equal Cost Multi Path) という。ECMPは耐障害性の向上だけでなく、帯域の拡張も兼ねることができ、多くのネットワーク環境で使用されている
    • コスト算出の式は、100Mbps以上のインターフェースで同じ値になってしまうため、最近は分子の値を 100 よりも大きくするのが一般的


EIGRP

  • Cisco独自のルーティングプロトコル
    • そのため、CiscoルータやCiscoのCatalystスイッチで構成されているネットワーク環境でしか使用できない。使用できる環境であればかなりの力を発揮する
  • 最初に自分の持つルート情報を交換してそれぞれでトポロジーテーブルを作り、そこから最適なルート情報だけを抽出し、ルーティングテーブルを作る
    • この部分は、RIPv2に似ているが、EIGRPは変更があった時だけ更新がかかる
    • また、通常時はHelloパケットという小さなパケットを送信して、相手が正常に動作しているかを判断する。この部分はOFPFに似ている
  • メトリックはデフォルトで「帯域幅」と「遅延」を使用する
    • 帯域幅は「10000 / 最小帯域幅(Mbps)」の式に当てはめて算出する。宛先ネットワークまでのルートの中で最も小さい値を採用して計算する
    • 遅延は「マイクロ秒 / 10」の式に当てはめて算出する。ルータを超えるごとに出力インターフェース分を加算する
  • 「帯域幅」と「遅延」を足して256をかけたものがEIGRPのメトリックとなる
  • EIGRPもデフォルトの動作はECMP
    • メトリックが全く同じであれば、そのルートを全て使用してパケットを運び負荷分散する

Java 6 - String#substringによるメモリリークの可能性

(もともとQiitaに書いていたものを、ここに移動させました。)


※以下Java 6までの問題です。Java 7では解決されています


String#substring は新しい文字列を new String で生成するにも関わらず切り出し前の文字列を内部(のchar配列)で保持してしまっています。

本内容は通常は意識する必要はありませんが、巨大な文字列をsubstring操作する際はメモリリーク等につながる場合がありますので注意が必要です。
(String#splitにも同様の問題があります)

String s1 = "0123456789";       // -> s1内部のchar配列は {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

String s2 = s1.substring(5);   // -> s2内部のchar配列は {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} ({5, 6, 7, 8, 9}ではない!)

System.out.println(s2);         // -> "56789"
// 対処方法1
String s3 = new String(s1.substring(5));
// 対処方法2
String s4 = s1.substring(5).intern();

「CODE COMPLETE 完全なプログラミングを目指して(下)」 第20章 ソフトウェア品質

「CODE COMPLETE 完全なプログラミングを目指して(下)」 の 第20章 ソフトウェア品質 で気になった部分の抜粋です


ソフトウェアの品質改善技術

  • 組織によっては、その場しのぎのプログラミングが横行している。ボロボロのコードをまき散らし、プログラムを素早く完成させるGloba Garyタイプのプログラマの方が、すばらしいプログラムを書き、正しく動くことを確認してからリリースするHigh-Quality Henryタイプのプログラマよりも褒められる。このような組織では、プログラマが品質を最優先事項と考えないのは当然だ。

  • 開発中のソフトウェアの技術的な特性を制御するのがガイドラインである。

  • ソフトウェアエンジニアリングプロセスの管理の一つに、「最も価値の低い」段階で問題を特定するということがある。つまり投資が少なく、問題を修正するためのコストが最も少ない段階で問題を特定するのである。

開発プロセス

  • ソフトウェアの品質向上を妨げる重大な障害の1つは、変更が管理されていないことである。

  • 評価によって品質保証計画が成功したかどうかが明らかとなり、プロセスを既定の方法で調整し、改善の余地があるかどうかを確かめることができる。

  • 複数のケーススタディでプロトタイピング方式と従来どおり仕様から順に開発する方式とを比較した調査結果がある。この結果からプロトタイピングの方が優れた設計を生み、ユーザーのニーズをよく見たし、保守性を向上させることがわかっている。

目標の設定

  • プログラマは指定された目標に取り組むが、それには目標が何かを知らされていなければならない。


ソフトウェア品質改善技術の相対的な効果

  • ソフトウェアの欠陥検出のもっとも一般的な方法である単体テストと統合テストの欠陥検出率の標準値は30~35%に過ぎない。
    • プロジェクトの開発者が欠陥の排除率をどうしても引き上げたいのなら、様々な方法を組み合わせる必要があることが強くうかがえる。

欠陥検出のコスト

  • ほとんどの研究でインスペクションはテストよりも欠陥検出のコストが低いという結果が出ている。

欠陥修正のコスト

  • 欠陥がシステムに長くとどまればとどまるほど、それを排除するコストは高くなる、したがって、欠陥を早期に発見する検出テクニックには修正コストを抑える働きがある。

ソフトウェア品質の原則

  • ソフトウェア品質とは、品質を改善すると開発コストが低くなることである
  • コーディングのやり直しにかかる時間を減らすことが、生産性と品質を向上させる最善策なのである。
  • ほとんどのプロジェクトで最も時間のかかるアクティビティは、正しく動作しないコードのデバッグと修正である。デバッグとそれに伴うリファクタリングなどの修正作業は、従来の単純なソフトウェア開発サイクルにおいて約50%の時間を占める。エラーを予防してデバッグを減らせば、生産性は向上する。したがって、開発スケジュールを短縮する最も明らかな方法とは、製品の品質を向上させ、ソフトウェアのデバッグや作業のやり残しにかかる時間を減らすことである。



関連エントリ

ネットワークで接続できない時の問題切り分け

「絵で見てわかるOS/ストレージ/ネットワーク」 を読んでまして、

ここだけはメモっておきたいなーと思ったのが、ネットワークで接続できない場合の代表的な切り分け方法でした。

自分なりの言葉に直してメモしておきます。


f:id:nini_y:20200323104736p:plain


  • ping

    • ping {IPアドレス} を実行
      • コマンドが成功すれば、インターネット層 と ネットワークインターフェース層(物理レイヤー)まではOK
      • ただし、 ping を受け付けないようにしているネットワーク(機器)もあるため、その場合は他のコマンドで代用する必要がある。
      • 最初から、ping {ホスト名} を実行して上手くいけば、名前解決とインターネット層 までは問題ないはず
  • ルーティング

    • ping が成功しない場合は、接続対象としている目的のマシンと同一ネットワークに存在する他のマシンに対して ping を実行する。
      • または、トレースルートコマンド(tracerttraceroute) を実行する。
        • これにより、ルーティングが正しいかどうか分かる。
  • ポート

    • インターネット層 までOKだった場合、netstat -ass -a でサーバ側で対象のポートが開いているかを確認する。
    • また、クライアント側から nc {ホスト名} -z {ポート番号}Test-NetConnection {ホスト名} -Port {ポート番号} などのコマンドで確認できる。
  • 変換装置

    • 目的のマシンまでの中継の中に、ファイアウォールや何らかのアドレス変換装置(NAT) が存在しないことを確認する。
      • これらは特定のポートを遮断したり、アドレスを書き換えたりするため、パケットが途中で意図しないものになっていることがある。
    • ファイアウォールで診断用のコマンド(ping で用いられるICMPプロトコル)を許可していないと切り分けできないことがあるので注意が必要。
  • 名前解決

    • 名前解決が怪しい場合は hostsファイル (UNIX系であれば /etc/hosts, Windows系であれば C:¥Windows¥system32¥drivers¥etc¥hosts など)の中を確認する。
      • ホスト名とIPアドレスの対応表が載っているので、これが悪さをしているケースもある。
    • nslookupResolve-DnsName などのコマンドを使って、DNSの情報が正しいかどうかも確認する。
  • アプリケーション層の確認

    • TCPのポートまで正しくたどり着けている場合、TCP/IP や ネットワークインターフェース層 などではなく、アプリケーションのレイヤーに問題がある。
    • アプリケーション(DBMSなど)の設定や、アプリケーションに渡しているユーザ名やパスワード、設定情報が間違っていないかを確認する。


補足

各レイヤーでのトラブルシューティング

f:id:nini_y:20200328102849p:plain

macOS - ipコマンドを使えるようにする

素の状態だとmacOSで ip コマンド使えないんですね。

Homebrewで iproute2mac をインストールして使えるようにしましょう。


とりあえず、念のためにHomebrewで iproute2mac を検索します。(以下コマンドを実行)

brew search iproute2mac


実際に実行した結果が以下。ちゃんと存在するようです。

yukiMacBook-Pro:~ yuki$ brew search iproute2mac
==> Formulae
iproute2mac


以下コマンドを実行してインストールします。

brew install iproute2mac


実際に実行した結果が以下。インストールが完了しました。

yukiMacBook-Pro:~ yuki$ brew install iproute2mac
==> Downloading https://github.com/brona/iproute2mac/releases/download/v1.2.3/iproute2mac-1.2.3.tar.gz
==> Downloading from https://github-production-release-asset-2e65be.s3.amazonaws.com/24814763/b7be4f00-ec67-11e9-8e0e-de
######################################################################## 100.0%
🍺  /usr/local/Cellar/iproute2mac/1.2.3: 6 files, 22.5KB, built in 5 seconds


これで、 ip コマンドが使えるようになりました。

というわけで念のために実行。

yukiMacBook-Pro:~ yuki$ ip help
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
       ip -V
where  OBJECT := { link | addr | route | neigh }
       OPTIONS := { -4 | -6 }

iproute2mac
Homepage: https://github.com/brona/iproute2mac
This is CLI wrapper for basic network utilities on Mac OS X inspired with iproute2 on Linux systems.
Provided functionality is limited and command output is not fully compatible with iproute2.
For advanced usage use netstat, ifconfig, ndp, arp, route and networksetup directly.


ip addr show の実行も問題なしです

yukiMacBook-Pro:~ yuki$ ip addr show
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    inet 127.0.0.1/8 lo0
    inet6 ::1/128
    inet6 fe80::1/64 scopeid 0x1
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether 8c:86:90:08:e4:52
    inet6 fe80::18d3:99ad:79e9:c77f/64 secured scopeid 0x6
    inet6 240b:12:4e60:9800:101e:b5ab:84f2:9c38/64 autoconf secured
    inet6 240b:12:4e60:9800:9518:71c8:b3f:74f6/64 autoconf temporary
    inet 192.168.10.8/24 brd 192.168.10.255 en0
awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484
    ether 5a:61:5d:87:05:90
    inet6 fe80::5870:5cff:fe78:590/64 scopeid 0x8
utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000
    inet6 fe80::2b9e:f27c:48de:6a0c/64 scopeid 0xc
utun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
    inet6 fe80::4a46:be16:5cd1:2038/64 scopeid 0xd