前回は、実際に送信されるMPTCPのMP_CAPABLEのパケットを眺めてみました。
今回は、ADD_ADDR、DSS、DSS FIN、MP_JOINのフォーマットと実際のパケットを見比べてみます。
MPTCPのオプションは、前回の内容を参考にしてください。
ADD_ADDR
ADD_ADDRは、使用可能なアドレスがある場合、そのアドレスの情報を対向ノードに知らせる際に使用されます。
フォーマット
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------+---------------+-------+-------+---------------+ | Kind | Length |Subtype| IPVer | Address ID | +---------------+---------------+-------+-------+---------------+ | Address (IPv4 - 4 octets / IPv6 - 16 octets) | +-------------------------------+-------------------------------+ | Port (2 octets, optional) | +-------------------------------+ Figure 12: Add Address (ADD_ADDR) Option
IPVerは、IPv4の場合は4、IPv6の場合は6が入ります。Portはポート番号を示し、これが含まれるかどうかはLengthから推測します。
ADD_ADDRパケット
16:02:40.957874 IP (tos 0x0, ttl 64, id 23374, offset 0, flags [DF], proto TCP (6), length 68) 192.168.101.2.51080 > 192.168.109.2.5001: Flags [.], cksum 0x538c (incorrect -> 0x3225), seq 1, ack 1, win 229, options [nop,nop,TS val 1091645 ecr 1094284,mptcp add-addr id 2 192.168.105.2,mptcp dss ack 3821824259], length 0 0x0000: 0004 0001 0006 a036 9fa1 459f 0000 0800 0x0010: 4500 0044 5b4e 4000 4006 8c10 c0a8 6502 0x0020: c0a8 6d02 c788 1389 2fc6 f375 5007 007f 0x0030: c010 00e5 538c 0000 0101 080a 0010 a83d 0x0040: 0010 b28c 1e08 3402 c0a8 6902 1e08 2001 0x0050: e3cc 6903
TCPヘッダのデータオフセットが0xcなので、オプション領域を含むTCPヘッダの長さは、48バイトです。
最後の16バイト目からの8バイトがADD_ADDRの領域です。
0x1eがMPTCPオプション、0x08が長さで8バイト、Subtypeが3、IPVerが4、Address IDが2で、Addressが”c0a8 6902″で192.168.105.2です。
このパケットのTCPヘッダの長さは48バイトで、あと12バイトのデータを含むことができます。今回はIPv4アドレスだったのでサイズは4バイトでしたが、IPv6アドレスの場合は16バイトです。IPv6アドレスを通知する場合、TCPヘッダの最大長である60バイトが使われます。
DSS
DSSは、MPTCPのデータのACKとシーケンス番号の情報を対向ノードに知らせるために使用されます。
フォーマット
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------+---------------+-------+----------------------+ | Kind | Length |Subtype| (reserved) |F|m|M|a|A| +---------------+---------------+-------+----------------------+ | Data ACK (4 or 8 octets, depending on flags) | +--------------------------------------------------------------+ | Data sequence number (4 or 8 octets, depending on flags) | +--------------------------------------------------------------+ | Subflow Sequence Number (4 octets) | +-------------------------------+------------------------------+ | Data-Level Length (2 octets) | Checksum (2 octets) | +-------------------------------+------------------------------+ Figure 9: Data Sequence Signal (DSS) Option
FはDATA_FINで、設定されている場合は送信者からの最後のデータが含まれていることを表します。
mはDSNが8オクテットかどうかを示し、設定されていない場合は4オクテットです。
MはDSN、SSN、DLL、Checksumがあるかどうかを示します。
aはData ACKが8オクテットかどうかを示し、設定されていない場合は4オクテットです。
AはData ACKが存在するかどうかを示します。
DSSパケット
16:02:40.958028 IP (tos 0x0, ttl 64, id 23378, offset 0, flags [DF], proto TCP (6), length 1500) 192.168.101.2.51080 > 192.168.109.2.5001: Flags [.], seq 25:1453, ack 1, win 229, options [nop,nop,TS val 1091645 ecr 1094284,mptcp dss ack 3821824259 seq 3197154524 subseq 25 len 1428 csum 0xb2ba], length 1428 0x0000: 0004 0001 0006 a036 9fa1 459f 0000 0800 0x0010: 4500 05dc 5b52 4000 4006 8674 c0a8 6502 0x0020: c0a8 6d02 c788 1389 2fc6 f38d 5007 007f 0x0030: d010 00e5 2ec7 0000 0101 080a 0010 a83d 0x0040: 0010 b28c 1e14 2005 e3cc 6903 be90 b4dc 0x0050: 0000 0019 0594 b2ba 0000 0000 0000 0001 0x0060: 0000 1389 0000 0000 0000 0000 ffff fe0c 0x0070: 3435 3637 3839 3031 3233 3435 3637 3839 0x0080: 3031 3233 3435
TCPヘッダのデータオフセットが0xdなので、オプション領域を含むTCPヘッダの長さは、52バイトです。
0x45バイト目からの20バイトがDSSの領域です。
フラグの領域は0x05なので、2進数では00101となり、MフラグとAフラグが設定されています。Aフラグが設定されているのでData ACKが存在し、またMフラグが設定されているので、DSN、SSN、DLL、Checksumが存在します。
DSSのフォーマットに従って解釈すると、”0xe3cc6903″がData ACK、”0xbe90b4dc”がDSN、”0x00000019″がSSN、”0x0594″がDLL、”0xb2ba”がChecksumです。
DSS FINパケット
ついでにDSSでFINフラグが設定されているパケットを見てみます。
16:02:46.265276 IP (tos 0x0, ttl 63, id 25527, offset 0, flags [DF], proto TCP (6), length 72) 192.168.109.2.5001 > 192.168.106.2.48361: Flags [.], cksum 0x9d24 (correct), seq 1, ack 6224317, win 5805, options [nop,nop,TS val 1095613 ecr 1092968,mptcp dss fin ack 3221927133 seq 3821824259 subseq 0 len 1 csum 0x2d3a], length 0 0x0000: 0000 0001 0006 00a2 89f3 73c5 abdf 0800 0x0010: 4500 0048 63b7 4000 3f06 7fa3 c0a8 6d02 0x0020: c0a8 6a02 1389 bce9 4781 e03d 466e 497e 0x0030: d010 16ad 9d24 0000 0101 080a 0010 b7bd 0x0040: 0010 ad68 1e14 2015 c00a b4dd e3cc 6903 0x0050: 0000 0000 0001 2d3a
TCPヘッダのデータオフセットが0xdなので、オプション領域を含むTCPヘッダの長さは、52バイトです。
先程と同様に、0x45バイト目からの20バイトがDSSの領域です。
フラグの領域は0x15なので、2進数では10101となり、Fフラグが設定されています。このパケットでMPTCPレベルでのFINが送られていることが分かります。
MP_JOIN
MP_JOINオプションは、MPTCPの2本目以降のコネクションを確立する際に送受信されるSYN、SYN+ACK、ACKに付きます。2本目以降には第4のACKが送られますが、このパケットにはMP_JOINオプションは付きません。
SYN+MP_JOINのフォーマット
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------+---------------+-------+-----+-+---------------+ | Kind | Length = 12 |Subtype| |B| Address ID | +---------------+---------------+-------+-----+-+---------------+ | Receiver's Token (32 bits) | +---------------------------------------------------------------+ | Sender's Random Number (32 bits) | +---------------------------------------------------------------+ Figure 5: Join Connection (MP_JOIN) Option (for Initial SYN)
Bフラグは、このコネクションがバックアップ回線かどうかを示します。
Address IDはADD_ADDRで通知されたアドレスIDです。
TokenはMPTCPのコネクションを特定するために使用され、ランダム値はリプレイ攻撃を防ぐために使用されます。
1本目のコネクションのAddress IDは通知されないので、暗黙的に0になります。
SYN+MP_JOINのパケット
16:02:40.979297 IP (tos 0x0, ttl 64, id 63400, offset 0, flags [DF], proto TCP (6), length 72) 192.168.105.2.43992 > 192.168.109.2.5001: Flags [S], cksum 0x5790 (incorrect -> 0xbfda), seq 3268763626, win 29200, options [mss 1460,sackOK,TS val 1091650 ecr 0,nop,wscale 7,mptcp join id 2 token 0x60804130 nonce 0x4341f13e], length 0 0x0000: 0004 0001 0006 a036 9fa1 459d 0000 0800 0x0010: 4500 0048 f7a8 4000 4006 ebb1 c0a8 6902 0x0020: c0a8 6d02 abd8 1389 c2d5 5fea 0000 0000 0x0030: d002 7210 5790 0000 0204 05b4 0402 080a 0x0040: 0010 a842 0000 0000 0103 0307 1e0c 1002 0x0050: 6080 4130 4341 f13e
TCPヘッダのデータオフセットが0xdなので、オプション領域を含むTCPヘッダの長さは、52バイトです。
最後の12バイトがMP_JOINの領域です。
Bフラグは設定されておらず、Address IDが2、Tokenが”0x60804130″、ランダム値が”0x4341f13e”であることが分かります。
SYN+ACK+MP_JOINのフォーマット
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------+---------------+-------+-----+-+---------------+ | Kind | Length = 16 |Subtype| |B| Address ID | +---------------+---------------+-------+-----+-+---------------+ | | | Sender's Truncated HMAC (64 bits) | | | +---------------------------------------------------------------+ | Sender's Random Number (32 bits) | +---------------------------------------------------------------+ Figure 6: Join Connection (MP_JOIN) Option (for Responding SYN/ACK)
MP_JOINを含むSYNパケットを受け取った側は、SYN+ACK+MP_JOINパケットを返します。Tokenを知らなかったり、追加のコネクションの作成を拒否する場合はRSTパケットが飛びます。
SYN+ACK+MP_JOINのパケット
16:02:40.979591 IP (tos 0x0, ttl 63, id 45808, offset 0, flags [DF], proto TCP (6), length 76) 192.168.109.2.5001 > 192.168.105.2.43992: Flags [S.], cksum 0x3008 (correct), seq 2014172733, ack 3268763627, win 28560, options [mss 1460,sackOK,TS val 1094291 ecr 1091650,nop,wscale 7,mptcp join id 3 hmac 0x2ccfecb525bed145 nonce 0x4bb9fb37], length 0 0x0000: 0000 0001 0006 00a2 89f3 73c4 0000 0800 0x0010: 4500 004c b2f0 4000 3f06 3166 c0a8 6d02 0x0020: c0a8 6902 1389 abd8 780d d63d c2d5 5feb 0x0030: e012 6f90 3008 0000 0204 05b4 0402 080a 0x0040: 0010 b293 0010 a842 0103 0307 1e10 1003 0x0050: 2ccf ecb5 25be d145 4bb9 fb37
TCPヘッダのデータオフセットが0xeなので、オプション領域を含むTCPヘッダの長さは、56バイトです。
最後の16バイトがMP_JOINの領域です。
Bフラグは設定されておらず、Address IDが3、切り詰められたHMACが”0x2ccfecb525bed145″、ランダム値が”0x4bb9fb37″であることが分かります。
ACK+MP_JOINのフォーマット
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------+---------------+-------+-----------------------+ | Kind | Length = 24 |Subtype| (reserved) | +---------------+---------------+-------+-----------------------+ | | | | | Sender's HMAC (160 bits) | | | | | +---------------------------------------------------------------+ Figure 7: Join Connection (MP_JOIN) Option (for Third ACK)
切り詰められていないHMACが送信されます。このパケットを送ったSocketはPRE_ESTABLISHED状態となり、第4のACKを待ちます。第4のACKが届くとESTABLISHED状態になりますが、それまではこのSocketではデータは送信されません。
ACK+MP_JOINのパケット
16:02:40.979668 IP (tos 0x0, ttl 64, id 63401, offset 0, flags [DF], proto TCP (6), length 76) 192.168.105.2.43992 > 192.168.109.2.5001: Flags [.], cksum 0x5794 (incorrect -> 0xa02d), seq 1, ack 1, win 685, options [nop,nop,TS val 1091650 ecr 1094291,mptcp join hmac 0xf2e30d4fb4e4f4cc4562c61e59d9ce7a544c30f1], length 0 0x0000: 0004 0001 0006 a036 9fa1 459d 0000 0800 0x0010: 4500 004c f7a9 4000 4006 ebac c0a8 6902 0x0020: c0a8 6d02 abd8 1389 c2d5 5feb 780d d63e 0x0030: e010 02ad 5794 0000 0101 080a 0010 a842 0x0040: 0010 b293 1e18 1000 f2e3 0d4f b4e4 f4cc 0x0050: 4562 c61e 59d9 ce7a 544c 30f1
TCPヘッダのデータオフセットが0xeなので、オプション領域を含むTCPヘッダの長さは、56バイトです。
最後の24バイトがMP_JOINの領域です。
切り詰められていないHMACは、”0xf2e30d4fb4e4f4cc4562c61e59d9ce7a544c30f1″であることが分かります。
まとめ
前回と今回で、RFCで定義されているパケットフォーマットと実際のMPTCPのオプションが付いたパケットを見比べてきました。
他のTCPのオプションも含まれる状態での40バイトという長さの制約の中で、どうにかして新しい機能を実現させようとする強い意気込みが見て取れます。
RFC 6824は現在策定中の仕様なので、変更される可能性もありますが、既存のL2 Switchなどの機器に変更を加えることなく、新しい機能を追加しようという試みは非常に素晴らしいと思います。
対向ノードがMPTCPに対応していない場合は通常のTCPで通信できますので、ちょっとでも興味のある方は是非是非MPTCPを試してみてください。