はじめての LLDP
LLDP の基本についてメモしておきます。
LLDP とは¶
LLDP (Link Layer Discovery Protocol) とは「隣接検出プロトコル」と呼ばれたりしますが、「接続された隣通しの機器で、お互いの情報を交換するプロトコル」のことです。 簡単に言うと「LLDP を使えば、お隣の機器情報が分かります」ということです。 LLDP を使って隣接する機器を検出 (発見) していくことで、最終的にはネットワーク全体のトポロジーを検出することも可能です。 LLDP は IEEE 802.3AB で標準化されており、ネットワーク機器に限らず Linux や Windows でも対応している為、幅広い機器との間で利用することが可能です。
レイヤー2 で動作するプロトコルですので、IP アドレスが割り当てられていない区間であっても「LLDP フレームで相手が見えていれば、物理的な問題の可能性は低い」とトラブルシューティング時のヒントにすることも可能です。 LLDP は殆どの実装系で送信間隔が「120 秒」等の長めの値となっており、しかも一度に送信するデータ量 (フレーム長) も短い為、有効化しておいても技術的な問題が発生するケースは少ないと考えられます。 但し、「隣接関係を検出する」という性質上、「キャリア機器とユーザ機器」等、情報交換したくない機器間で有効化してしまうとセキュリティ面での事故にも繋がる為、不必要なインターフェイスでは無効化しておく等、注意が必要です。
また昨今では SDN 等で機器が LLDP でトポロジーを学習し、自動的に設定も済ませる… といった用途でも利用されています。
LLDP と CDP の比較表¶
LLDP と似た隣接検出プロトコルに CDP が挙げられます。 以下に LLDP と CDP を比較してみます。
項目 | LLDP | CDP |
---|---|---|
規格 | IEEE 802.3AB | Cisco 独自 |
動作レイヤー | レイヤー2 | レイヤー2 |
アドバタイズ方式 | マルチキャスト | マルチキャスト |
アドバタイズ用 MAC アドレス | 01:80:c2:00:00:0e | 01:00:0c:cc:cc:cc |
CDP は Cisco 独自規格ではあるものの、VMware vSphere の vSwitch でも CDP に対応している等、Cisco 以外でも対応している製品は存在します。
LLDP は標準規格¶
前述した通り、LLDP は IEEE 802.1AB で定義されています。 つまり (特定メーカーの規格では無く)「標準規格」です。
- IEEE 802.1AB-2016 - IEEE Standard for Local and metropolitan area networks - Station and Media Access Control Connectivity Discovery
- 802.1AB-REV - Station and Media Access Control Connectivity Discovery
LLDP のフレームフォーマット¶
LLDP フレームをイーサネットフレームとして全体を俯瞰すると以下のような構造になっています。
宛先 MAC アドレス¶
LLDP はレイヤー 2 で動作しますが、宛先 MAC アドレスは常に 01:80:c2:00:00:0e
という Multicast MAC Address 宛に送信されます。 Wikipedia の Link Layer Discovery Protocol ページ には Destination MAC として以下の記載があります。
01:80:c2:00:00:0e, or 01:80:c2:00:00:03, or 01:80:c2:00:00:00
ですが、これらの MAC アドレスは各々以下の用途で利用されているはずです。 従って LLDP で利用可能なのは下記 1. のアドレスのみ、と思われます。
No. | MAC アドレス | 用途 |
---|---|---|
1 | 01:80:c2:00:00:0e | LLDP |
2 | 01:80:c2:00:00:03 | 802.1X EAPOL |
3 | 01:80:c2:00:00:00 | BPDU (STP/RSTP/MSTP) |
タイプ (Ethertype)¶
LLDP フレームはタイプが常に「0x88cc
」になります。 この値を意識するケースは少ないかも知れませんが、tcpdump で LLDP フレームをキャプチャしたい場合は (http や ssh のように)「lldp」を指定することは出来ず、「Ethertype == 0x88cc」のフレームを指定することで結果的に LLDP フレームだけをキャプチャすることが出来ます (LLD フレームのキャプチャ方法は後述)。 尚、Wireshark の Display Filter には「lldp」というキーワードが利用可能です。
データ (TLV)¶
LLDP フレームのデータは TLV で構成されます。 「TLV」という用語自体は LLDP に特化したものでは無く、いわゆる「下記 3 つを組み合わせたもの」を意味します。
- Type (種類)
- Length (長さ)
- Value (値)
実際の LLDP フレームはイーサフレームのデータ部分に LLDP を表現する TLV を含んだものになります。
LLDP TLV の分類¶
TLV は以下、いずれかに分類されます。
No. | Category | TLV type |
---|---|---|
1 | TLV | 0 ~ 8 |
2 | Organizationally specific TLV | 127 (固定) |
TLV type (7bit) は十進数で 0 ~ 127 の値を取りえますが、TLV type 0 ~ 8 は値に応じて TLV 名・用途が決められています。 9 ~ 126 は予約されており、現状では使われていないようです。 ベンダー毎の拡張用途には TLV type 127 が利用されます。 0 ~ 3 は必須 TLV で、LLDP フレームに必ず含まれている必要があります。 また、TLV type 0 の「End of LLDPDU」は必須/オプション関係無く、全ての TLV より後に (=TLV の最後に) 付与されている必要があります。
TLV type | TLV name | 必須か? |
---|---|---|
0 | End of LLDPDU | 必須 |
1 | Chassis ID | 必須 |
2 | Port ID | 必須 |
3 | Time To Live | 必須 |
4 | Port description | オプション |
5 | System name | オプション |
6 | System description | オプション |
7 | System capabilities | オプション |
8 | Management address | オプション |
9 ~ 126 | (Reserved) | - |
127 | オプション |
代表的な TLV の意味¶
ここでは代表的な TLV の意味を説明します。 パケットの例は主に Wireshark のサイトにある SampleCaptures/lldpmed_civicloc.pcap というファイルから抜粋させて頂きました。
TLV type 1 : Chassis ID¶
シャーシ (筐体 ≒ 機器) を一意に表現します。 「何をもって一意とみなすか?」は Chassis Id Subtype で宣言されます。 下記の例では Chassis Id Subtype が「4」になっていますが、これは「MAC アドレス」を意味し、Chassis Id に MAC アドレスが格納されていることが分かります。
1 2 3 4 5 |
|
TLV type 2 : Port ID¶
LLDP フレームを送信したポートの情報を表現します。 Port Id Subtype の値で「何をキーにするのか?」を宣言します。 下記でh Port Id Subtype が「7」になっていますが、これは「Locally assigned」という意味だそうです。
1 2 3 4 5 |
|
下記は Port Id Subtype が「1」となっていますが、これは Interface alias を意味し、続く Port Id に「Gi1/0/10」という値が入っていることが分かります。
1 2 3 4 5 |
|
TLV type 3 : Time To Live¶
TTL (Tile To Live) は、この LLDP フレームを受信した機器が「何秒間、該当 LLDP フレームに含まれた情報を保持するか?」を定義します。 IEEE 802.3AB 上には「既定の値」は記載が無いようですが、Cisco 機器では「デフォルト 120 秒」というものが多いようです。 また、同じく IEEE 802.3AB を読む限り、仮に LLDP を有効 → 無効へ設定変更した場合 (いわゆる「LLDP の Shutdown 動作」)、機器は TTL = 0 の LLDP フレームを送信することにより、相手側機器の LLDP データベースをクリアする、という振る舞いをするようです (※ 実機では未検証)。
1 2 3 4 |
|
TLV type 4 : Port Description¶
LLDP 送信ポートに設定された Description を送信します。 下記の例では「1」と書かれているだけなので、見てもあまり面白くありません…
1 2 3 4 |
|
下記の例では「LLDP-TEST」という Description が表示されていることが分かります。
1 2 3 4 |
|
TLV type 5 : System Name¶
ホスト名を送信します。
1 2 3 4 |
|
TLV type 6 : System Description¶
システムに関する情報を送信します。 一般的には OS バージョン等を送信する実装が多いようです。 以下の例では ProCurve の OS バージョン等を送信しています。
1 2 3 4 |
|
以下の例では Cisco IOS の OS バージョンを送信しているのが分かります。
1 2 3 4 |
|
TLV type 7 : System Capabilities¶
自身が「どういった機能を持った機器なのか?」という情報を送信します。 具体的には以下 8 つのフラグを送信します。 同時に複数のフラグを立てて送信することも可能です。 「そんな機器が存在するのか!?」は別にして、理論上は全てのフラグを立てた LLDP フレームを送信することも可能なはずです。
- Other
- Repeater
- Bridge
- WLAN Access Point
- Router
- Telephone
- DOCSIS cable device
- Station only
以下の例では Capabilities が 0x0014 ですが、これは「Bridge」と「Router」のフラグ (bit) が立っていることを意味します。 但し、Enabled Capabilities は「0x0004」となっており、これは「Bridge」だけが有効なことを意味する為、総合すると以下だ、ということが分かります。
- この機器は Bridge 機能と Router 機能に対応している
- しかし、現在は Bridge 機能のみを有効化している
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
TLV type 8 : Management Address¶
機器の管理アドレスを送信します。 下記の例では「15.255.122.148」です。
1 2 3 4 5 6 7 8 9 |
|
TLV type 0 : End of LLDPDU¶
LLDP TLV の終わりを意味します。 TLV には順序の意味は無く、「必須 TLV だけが含まれていれば良い」ようですが、TLV type 0 の End of LLDPDU だけは最後に来る必要があります。
1 2 3 |
|
TLV のフォーマット¶
TLV は以下のような構造をしています。
通常の TLV¶
TLV type 0 ~ 8 の、通常の TLV は以下のような構造をとります。
Organizationally specific TLV¶
前述の通り、ベンダー独自の TLV は TLV type 127 決め打ちになります。 通常の TLV と違い、Value 部分が OUI (Organizationally unique identifier) や Organizationally defined subtype、Organizationally defined information string で構成されます。
実際の LLDP フレーム¶
Wireshark のサイトに LLDP パケットをキャプチャしたサンプルが置いてあります。 ここでは Wireshark のサイトにあるサンプルのうち、SampleCaptures/lldpmed_civicloc.pcap という LLDP フレームを Wireshark で開いてみます。 ざっくり全体を見てみると LLDP TLV は以下の 4 パートに分かれていることが分かります。
- 標準 TLV (必須)
- 標準 TLV (オプション)
- Organizationally specific TLV (オプション)
- End of LLDPDU (必須)
尚、LLDP TLV 部分を十六進数でダンプすると以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Python + scapy で LLDP フレームを送信する¶
Python 3.x + scapy で LLDP フレームを送信してみます。
サンプルスクリプト¶
サンプルスクリプトは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
実行例¶
実行例は以下の通りです。 実行時は LLDP フレームを送信したいインターフェイス名を指定します。 尚、今回は Python 3.7.3 + scapy 2.4.3 で動作確認しました。
1 2 3 |
|
Python から送信した LLDP フレームのキャプチャ結果¶
サンプルスクリプトから送信した LLDP フレームをキャプチャすると Wireshark では以下のように表示されました。 「Ieee 802.3 - Link Aggregation」が黄色く表示されていますが、これは Deprecated な TLV を指定している為です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
tcpdump で LLDP フレームをキャプチャする¶
tcpdump を使って LLDP フレームをキャプチャする場合、キャプチャフィルタに lldp
と指定してもエラーになります。
1 2 |
|
LLDP フレームはイーサタイプが 0x88cc
なので、ether proto 0x88cc
を指定することでキャプチャ出来ます。
1 |
|