kernel 4.15のUbuntu 18.04で試しています。
前提条件
kernel 4.14以上
ipコマンド(iproute2)が2.4.14以上。2.4.16で試験、kernelに対応したバージョン番号らしい(2.kernel rev)
Ubuntu 17.10.1はkernelが4.13?だった
/etc/systemctl.conf
net.ipv6.conf.all.seg6_enabled =1 net.ipv6.conf.all.seg6_require_hmac = 0 sysctl –w net.ipv6.conf.all.seg6_enabled=1 sysctl –w net.ipv6.conf..seg6_enabled=1
localsid用のテーブルを作る
# echo 100 localsid >> /etc/iproute2/rt_tables # ip -6 rule add to fc00::/64 lookup localsid # ip -6 route add blackhole default table localsid
unknownな物は全てドロップ
試験構成
node X 二つのインターフェースを持つ
node Y 二つのインターフェースを持つ
Xのenp14s0f1とYのenp14s0f0は同一セグメント、ISISでIGPを動かし。X loopback(lo)2001:3e8::39/128、Y loopback(lo)2001:3e8::40/128も広報している。Yのenp14s0f1の先に2001:3e8:4014::/64のネットワークが存在する。
X | Y | Z | ||||
---|---|---|---|---|---|---|
loopback | ::38/128 | 2001:3e8::39/128 | 2001:3e8::40/128 | ::36/128 | ||
int name | enp14s0f0 | enp14s0f1 | enp14s0f0 | enp14s0f1 | ||
IPv6 add | 4008::38/64 | 4008::39/64 | 4009::39/64 | 4009::40/64 | 4010::40/64 | 4010::36/64 |
prefix | 4008::/64 | 4009::/64 | 4010::/64 |
ENCAP T.encap
Xで受け取るパケットを対象に。指定の経路あてのパケットにSRHヘッダー付のIPv6でカプセルする場合
# ip -6 route add 2001:3e8:0:4014::/64 encap seg6 mode encap segs 2001:3e8:0:4009::40 dev enp14s0f1
route add 2001:3e8:0:4014::/64 対象となるパケットのdestination addressのマスク。
L2の時はどう記述するのか?
mode encap T.encapかT.inlineの指定
segs 2001:3e8:0:4009::40 付加するSRHの情報、"mode encap"の時は生成するパケットのDAの指定にもなる。ヘッダ(segs)は複数付けられるから。EndノードでDAは更新される。
dev enp14s0f0 出力するインターフェースの指定
dev かviaかはor
encapする時のSA(ソースアドレス)の指定
ip sr tunsrc set 2001:3e8::39
通常は出力インターフェースのアドレスがセットされるが明示的にloopbackアドレスなどを設定する事が多い。
確認方法は
#ip -6 route 2001:3e8:0:4044::/64 encap seg6 mode encap segs 1 [2001:3e8:0:4009::49 ] dev enp14s0f1 metric 1024 pref medium #ip sr tunsrc show tunsec addr 2001:3e8::37
出力されるパケットフォーマット
SA
|
DA
|
SRH
|
SA
|
DA
|
Payload
|
---|---|---|---|---|---|
2001:3e8::39
|
2001:3e8:0:4009::40
|
2001:3e8:0:4009::40
|
oiginal
|
route matched
|
original
|
T.insert
# ip -6 route add 2001:3e8:0:4060::/64 encap seg6 mode insert segs 2001:3e8:0:4044::100 dev enp14s0f1
SA
|
DA
|
SRH
|
payload
|
---|---|---|---|
original
|
segs
2001:3e8:0:4044::100
|
segs
|
original
|
insertされたSRHを取る(pop)するのは誰?
End, End.X, End.Tで条件がそろった時にSRHはpop(削除)される。
途中にEnd処理を行わない(SRv6をサポートしていない)ノードがあっても、intertで問題が無い気がする。encapを指定したオーバーレイとしてスマートではあるかもしれないけど。
1:すべてのノードがEnd処理をサポートしていれば、encapを使う必要はない。
2:一部のノードがEnd処理をしなくてもヘッダー付のまま転送してくれるのでinsertでも疎通性は確保できる。
Decap End.DX6
Yでdecapする場合
# ip -6 route add 2001:3e8:4009::40/128 encap seg6local action End.DX6 nh6 :: dev enp14s0f0 table localsid
2001:3e8:4009::40/128 ここで指定するのはDAではなくあくまでもSRHに記述されたSIDの値。しかしdecapの条件はnode Yが受け取れるDAである必要があるのでノードが持つインターフェースのアドレスかloopbackである必要がある。
nh6で指定するのはSID?"::"はlocal RIBを参照とあるけど、最後のvia or devで指定されているのとどっちを優先するのか不明
"End.DX4 nh4"の場合はIPv4アドレスだけでnh6のようなlocal lookupの指定方法は無し
dev or via、出力インターフェースを指定するときは"dev"、nexthopを指定する時は"via"、nh6の指定があるので省略できる気がするけど記述しないと"RTNETLINK answers: No such device"エラーになる。このメッセージの意味が分からずハマった。
既に指定してあるlocalsidを被ると、 "RTNETLINK answers: File exists"エラーになる、このメッセージも紛らわしい。
受け取るパケットフォーマット
SA | DA | SRH | SA | DA | payload |
---|---|---|---|---|---|
tunsrc set | segs | segs | original | original |
original |
確認は"ip -6 route show table localsid"
loopbackアドレスをSIDにする場合
node X
# ip -6 route add 2001:3e8:0:4014::/64 encap seg6 mode encap segs 2001:3e8::40 dev enp14s0f1
node Y
# ip -6 route add 2001:3e8::40/128 encap seg6local action End.DX6 nh6 :: dev enp14s0f1
IGPによるEnd処理の広報
Q:End.Xの指定は箱固有のインターフェース名を指定してるんじゃないのか?複数の箱に配っても整合性が取れない。固定のノードアドレスなら良いのか。
Q:End.Tで指定するtableの同一性を担保する別なコントロールプレーンが必要ではないのか?
2018年6月時点で実装されているのは、Hawuei, Controle centerでIS-ISで可能?
https://datatracker.ietf.org/doc/draft-bashandy-isis-srv6-extensions/
https://datatracker.ietf.org/doc/draft-li-ospf-ospfv3-srv6-extensions/
NFV等で、ダイナミックにサービス機能を起動する場合にSIDを動的に配布できる。metricを使えば多重化も容易。複数のノードから広報されても同じサービスが提供されるのであれば問題ない。
SRv6以外の設定
インターフェースのアドレス設定はnetplan
deamonの追加はsystemd
Zebra2.0での設定例
syntax
set routing-options ipv6 route-srv6 <prefix> nexthop <nexthop> seg6 <mode> segments <segs> set routing-options ipv6 localsid <sid> nexthop <nexthop> action <end.*> nh6
X encap
set routing-options ipv6 route-srv6 2001:3e8:0:4014::/64 nexthop 2001:3e8:0:4009::40 seg6 encap segments 2001:3e8:0:4009::40
encap SA指定のコマンド
set routing-options ipvv6 route-srv6 2001:3e8::39
Y decap
set routing-options ipv6 localsid 2001:3e8:0:4009::40/128 nexthop 2001:3e8:0:4010::36 action End.DX6
何故、viaやdevが不要なのか?
VPPでの設定例
https://wiki.fd.io/view/VPP/Segment_Routing_for_IPv6
X encap
vpp-X# sr policy add bsid 2001:3e8::40 next 2001:3e8::40 encap vpp-X# sr steer l3 2001:3e8:0:4014::/64 via sr policy bsid 2001:3e8::40 vpp-Y# set sr encaps source addr 2001:3e8::39
確認方法
vpp-X# show sr pol SR policies: [0].- BSID: 2001:3e8::40 Behavior: Encapsulation Type: Default FIB table: 0 Segment Lists: [0].- < 2001:3e8::40 > weight: 1 ----------- vpp-X# show sr steering policies SR steering policies: Traffic SR policy BSID 2001:3e8:0:4014::/64 2001:3e8::40
Y deap
vpp-Y# sr localsid address 2001:3e8::40 behavior end.dx6 GigabitEthernet0/5/0 2001:3e8:0:4010::36
確認方法
vpp-Y# show sr localsid SRv6 - My LocalSID Table: ========================= Address: 2001:3e8::40 Behavior: DX6 (Endpoint with decapsulation and IPv6 cross-connect) Iface: GigabitEthernet0/5/0 Next hop: 2001:3e8:0:4010::36 Good traffic: [6686 packets : 678832 bytes] Bad traffic: [0 packets : 0 bytes] --------------------
SIDの使い方
様々なusecaseが考えられているが、ここではサービスチェイニングを考えてみる。
SIDのモデルとしてlocater, function, argumentsの三層が想定されているが128bitをどのように割り当てるかの定義はユーザー任せ。IPv6の経路情報として/64が一般的であると考えると、これにlocaterを合わせて、残り64bitをfunctionとsrgumentsに割り当てるのが自然に思う。
SIDの前半をサービスを実現するpoolのを指定するアドレスとして使用し、後半を使用するサービスの指定に利用する。後半はビット列で複数のサービスを指定できる。
FW, NAT,
FWを2001:3e8:2::1
NATを2001:3e8:2::2
加入者を収容しているサービスの上流側のルータで、加入者に割り当てたプリフィックスに対して、T.insertでFWとNATのsegを指定する。
いやいや、そもそもNAT指定しないと疎通性ないし。
あるサーバーからアドレスAを持つ顧客に対してサービスを付加したい場合、サーバーからの出力を中継するルータにはS::FWのSIDをSRHを付加する(T.inline)。次段のルータはSRHを認識し、出力インターフェースを通常の経路とは異なるインターフェースに出力する。(End.X)
帰りの経路は何処で指定する?
ソースアドレスでひっかけるしかないのか?
ーーーーーーーーーーーーーーーー
localsid
個々のノードに指定される受け取ったSIDがマッチしたら行う処理のこと。
SRv6の処理タイプ
http://www.segment-routing.net/open-software/linux/
action | function | user case | param |
---|---|---|---|
T.insert | IPv6ヘッダは変更せずSRHを付加する | ||
T.encaps | IPv6ヘッダとSRHを付加するIPv4もpayload可能 | ||
T.encaps.L2 | L2のVPN/Tunnel,IPv6ヘッダとSRHを付加 | End.DX2の対抗 | |
End | 通常の処理、SRHに基づいてDAを書き換え | TE | |
End.X | xconnect、指定したインターフェースに振る | サービスチェイン | nh6 |
End.T | 指定したIPv6 tableで参照する | 複数の経路表を想定 | table |
End.DX2 | decap L2VPNの終端 | L2VPN | oif |
End.DX6 | decap | L3VPN | nh6 |
End.DX4 | decap | L3VPN | nh4 |
End.DT6 | decapして指定のIPv6経路表を参照 | L3VPN | table |
End.DT4 | decapして指定のIPv4経路表を参照 | L3VPN | table |
End.B6 | srh segs | ||
End.B6.Ecaps | srh segs | ||
End.BM | |||
End.S | |||
End.AD | 既存サービスの収容 | proxy | |
End.AM |
HMAC(Hash-Based Message Authentication Code)
トラフィック認証。
net.ipv6.conf.*.seg6_require_hmac
(integer)
-1
: Ignore HMAC field.0
: Accept SR packets without HMAC, validate SR packets with HMAC.1
: Drop SR packets without HMAC, validate SR packets with HMAC.
このパラメータに"1"を設定してしまうと、HMACが付いていないパケットはすべて捨ててしまう。HMACはアンプやループ攻撃を避けるためにSRHに付ける認証コード。
ip sr hmac set <keyid> <algorithm>
RFCからの抜粋
4.5. End.DX6: Endpoint with decapsulation and IPv6 cross-connect
The "Endpoint with decapsulation and cross-connect to an array of IPv6 adjacencies" function (End.DX6 for short) is a variant of the End and End.X functions. When N receives a packet destined to S and S is a local End.DX6 SID, N does:
1. IF NH=SRH and SL > 0
2. drop the packet ;; Ref1
3. ELSE IF ENH = 41 ;; Ref2
4. pop the (outer) IPv6 header and its extension headers
5. forward to layer-3 adjacency bound to the SID S ;; Ref3
6. ELSE
7. drop the packet
Ref1: The End.DX6 SID must always be the last SID, or it can be the
Destination Address of an IPv6 packet with no SRH header.
Ref2: 41 refers to IPv6 encapsulation as defined by IANA allocation
for Internet Protocol Numbers
Ref3: Selected based on a hash of the packet's header (at least SA,
DA, Flow Label)
The End.DX6 is used for L3VPN use-cases where a FIB lookup in a
specific tenant table at the egress PE is not required. This would
be equivalent to the per-CE VPN label in MPLS[RFC4364].
DA書き換えの例、SIDは不変
XからYのパケットを。AからDまでencapしてB,Cを経由するSRHを付ける。
action | SA | DA | SRH1 | SRH2 | SRH3 | SL | SA | DA |
---|---|---|---|---|---|---|---|---|
generate X | X | Y | ||||||
T.Encaps A | A | B | B | C | D | 3 | X | Y |
End B | A | C | B | C | D | 2 | X | Y |
End C | A | D | B | C | D | 1 | X | Y |
End.DX6 D | X | Y |
XからYのパケットを。B,C,D経由するSRHをAでinsert
action | SA | DA | SRH1 | SRH2 | SRH3 | SL | SA | DA |
---|---|---|---|---|---|---|---|---|
generate X | X | Y | ||||||
T.Insert A | X | B | B | C | D | 3 | ||
End B | X | C | B | C | D | 2 | ||
End C | X | D | B | C | D | 1 | ||
End D | X | Y |
End.AS / End.AM
基本的んは、サービスノードもSRHを解釈することが期待されていますが。収容する機器で機能を代行してSRv6を意識していないサービスを使うためにAS/AMがあります。
End.ASは指定されたSIDがついたパケットからヘッダを外してサービスノードにわたし、帰ってきたパケットに再びヘッダを付加します。End.AMは本来サービスノードが行うべきSRHの書き換えを行います。
IPv6 SA | IPv6 DA | SRH | IPv4 SA | IPv4 DA |
E1:: | F1::A1 | F1::A1 | A | B |
outbound End.AS F1::A1 | ||||
A | B | |||
A | B | |||
inbound insert SRH F2:: | ||||
F1:: | F2:: | A | B |