一覧NW-16-4 · WAN・トンネル・VPN

WANの品質とMPLS

品質で経路を選ぶ処理と、ラベルで次ホップへ送る処理を比較します。

説明

WANでは、測定した遅延や損失から利用経路を選ぶ仕組みと、選ばれた経路に沿ってパケットを転送する仕組みを分けて理解すると整理しやすくなります。

前半はSD-WANの品質条件を単純化したモデルで、利用経路の切替と条件未達を確認します。後半は別の転送方式であるMPLSの4バイトラベルを復号し、swapとpopの処理を追います。

1回線ごとの品質記録

latencyとjitterはms、lossは百分率です。どちらもリンク自体はupとします。

links=測定値と選好順位[dict(name="A",latency=20,jitter=3,loss=0.2,priority=1),dict(name="B",latency=40,jitter=2,loss=0.1,priority=2)]; links二回線の状態

Aは低遅延、Bは少し長い遅延です。物理リンクがupでも要求品質を満たすとは限らないため、通信の用途に応じた条件で比較します。

2要求条件を満たす回線を選ぶ

この用途の条件を遅延50ms以下、jitter10ms以下、loss1%以下とし、条件内でpriorityが小さい回線を選びます。

def choose(links):品質と方針で選択 eligible=三条件を満たす候補[r for r in links if r["latency"]<=50 and r["jitter"]<=10 and r["loss"]<=1] return min候補内で優先回線を選ぶ(eligible,key=lambda r:r["priority"])["name"] if eligible else None

三条件をすべて満たす候補から選びます。これは教材の方針モデルで、製品既定値や測定窓の実装を再現したものではありません。測定方法と判断時刻によって切替の挙動は変わります。

3リンクはupのまま品質が悪化する

Aの遅延80ms、jitter15ms、loss3%へ変え、選択の前後を比較します。

before=変更前の選択choose(links); links[0].updateAの品質が悪化(latency=80,jitter=15,loss=3); (before切替前後,choose(links))

AからBへ変わります。断線検出とは別に、アプリケーションの要求品質を下回ったことが切替の理由です。実環境では検出窓、ヒステリシス、既存フローへの適用も確認します。

4どちらも条件を満たさない場合

Bのlossも2%に悪化した場合を計算します。

links[1]["loss"]=2Bも損失条件を超える; print(choose(links)候補なしを確認)

結果はNoneです。このモデルには要求条件を満たす経路がありません。実運用では最良の候補へ緩和して送るか、送信しないか等の方針を別に決めます。何も定めず「自動で最適になる」と考えることはできません。

5MPLSの4バイトを組み立てる

ここからはMPLSの転送識別子を調べます。label16000、TC0、Bottom of Stack1、TTL64です。

import structラベルのバイト列; label,tc,bottom,ttl=四つの欄16000,0,1,64; word=ビット位置へ配置(label<<12)|(tc<<9)|(bottom<<8)|ttl; encoded=ネットワーク順で4バイト化struct.pack("!I",word); (encoded.hex符号化結果(" "),len(encoded))

20ビットのlabel、3ビットのTC、1ビットのS、8ビットのTTLで4バイトです。S=1はスタックの最下段を示します。label16000は全世界共通の宛先番号ではなく、受信する装置・文脈で解釈される値です。

6受信ラベルを次ホップへ置き換える

入力インターフェースin1のlabel16000を、out2のlabel24000へswapする転送表です。

table=入力ラベルから出力を決める表{("in1",16000):("out2",24000)}; incoming=4バイトを復号struct.unpack("!I",encoded)[0]; decoded=label・TC・S・TTL(incoming>>12,(incoming>>9)&7,(incoming>>8)&1,incoming&255); out,label2=転送表を参照table[("in1",decoded[0])]; replacement=ラベルとTTLを更新(label2<<12)|(decoded入力値と出力ラベル[1]<<9)|(decoded[2]<<8)|(decoded[3]-1); (decoded,out,struct.pack("!I",replacement).hex(" "))

出力先out2、label24000、TTL63へ変わります。各中継装置がこの転送表を使う段階と、SD-WANの品質条件を評価する段階は異なります。二つの技術は同じ機能の別名ではなく、組み合わせる構成もあります。

7外側ラベルを外した後にもラベルが残る場合

二段のスタックをラベル番号とSの組で表します。外側16000のSは0、内側900のSは1です。

stack=二段のラベルスタック[(16000,0),(900,1)]; popped=外側だけを除くstack[1:]; popped残ったサービス側ラベル

外側をpopしても内側900が残ります。たとえば外側を運搬経路、内側をサービスの識別に使う構成があります。popしたら必ず直ちにIPが出てくるわけではなく、Sビットと残りのスタックを確認します。

まとめ

品質条件で利用経路を選ぶ処理と、ラベルを参照して転送する処理は役割が異なります。

MPLSのラベル値・TC・S・TTLを復号し、swapやpopの後に残る情報を確認します。

操作履歴と解説を振り返れます。

Python 3

1
links=[dict(name="A",latency=20,jitter=3,loss=0.2,priority=1),dict(name="B",latency=40,jitter=2,loss=0.1,priority=2)]; links
[{'name': 'A', 'latency': 20, 'jitter': 3, 'loss': 0.2, 'priority': 1}, {'name': 'B', 'latency': 40, 'jitter': 2, 'loss': 0.1, 'priority': 2}]
2
def choose(links): eligible=[r for r in links if r["latency"]<=50 and r["jitter"]<=10 and r["loss"]<=1] return min(eligible,key=lambda r:r["priority"])["name"] if eligible else None
3
before=choose(links); links[0].update(latency=80,jitter=15,loss=3); (before,choose(links))
('A', 'B')
4
links[1]["loss"]=2; print(choose(links))
None
5
import struct; label,tc,bottom,ttl=16000,0,1,64; word=(label<<12)|(tc<<9)|(bottom<<8)|ttl; encoded=struct.pack("!I",word); (encoded.hex(" "),len(encoded))
('03 e8 01 40', 4)
6
table={("in1",16000):("out2",24000)}; incoming=struct.unpack("!I",encoded)[0]; decoded=(incoming>>12,(incoming>>9)&7,(incoming>>8)&1,incoming&255); out,label2=table[("in1",decoded[0])]; replacement=(label2<<12)|(decoded[1]<<9)|(decoded[2]<<8)|(decoded[3]-1); (decoded,out,struct.pack("!I",replacement).hex(" "))
((16000, 0, 1, 64), 'out2', '05 dc 01 3f')
7
stack=[(16000,0),(900,1)]; popped=stack[1:]; popped
[(900, 1)]

演習完了