SOME/IPのプロトコルを理解しよう ~SOME/IPプロトコル基本編~
今回は業務関連でSOME/IPのプロトコルについて理解を深めていきます。
なお、正式なAUTOSARの規格は以下から取得できるので、興味がある方こちらも参考にしてください。
概要
SOME/IPは車両内のECUどうしがEthernet経由でTCP/UDPを使用して通信を行うための規格です。
DoIP通信が診断機とECUの一対一通信が基本であったのに対し、SOME/IPは車両内の多数のECU間における相互通信を前提としています。
ECU間の通信用途(カメラ、バッテリー、地図アプリ等)ごとにSOME/IPが扱うサービスが存在し、それらはService IDと呼ばれるユーザー/システム設計者が決める任意の値によって識別されます。
ECUはこのサービスを提供する側(サーバ)と利用する側(クライアント)に分かれて相互にやり取りを行います。
Method (メソッド)
SOME/IPの主な用途はRemote Procedure Call (RPC)と呼ばれる、あるECU(クライアント)から別のECU(サーバ)へのメソッド呼び出しです。
ここでいうメソッドとはクライアントからサーバに対して要求可能な、サーバの提供する機能のことを指します。
メソッドにはGetter、Setter、Method call、Fire & forgetの4つがあります。
メソッド | 概要 |
---|---|
Getter | Field(サーバが管理する任意の情報)の値を取得する |
Setter | Field(サーバが管理する任意の情報)の値を更新する |
Method call | 処理を依頼し、処理結果を受け取る |
Fire & forge | 処理を依頼し、処理結果を受け取らない |
Event (イベント)
突発的、あるいは周期的なアクションに応じて、ECU(サーバ)からECU(クライアント)向けに送信される単方向のデータ伝送です。
Notifierとして、サーバが管理するField情報の更新を通知するイベントが定義されています。
SOME/IP ヘッダフォーマット
まずはヘッダのフォーマットからざっくりとみていきます。
以下に示すメッセージフォーマットのうち、Message IDからReturn Codeまでの構造はSOME/IPで扱うフレームにおいて共通のヘッダフォーマットとなります。
メッセージIDはサービスの識別に使用される識別子です。
本値でどのサービスのどのメソッド、またはイベントに関するフレームであるかを識別します。
本値は車両内のシステムにおいて一意でなければなりません。
また、メソッドIDは以下のようにサービスID(16bit)とメソッドID(15bit)、もしくはサービスID(16bit)とイベントID(15bit)の連結となっています。
Length
Request IDから SOME/IP メッセージの終わりまでの⻑さがバイト単位で含まれます。
Request ID
リクエストIDは複数ECUから同一のMessage IDによる要求を受け付けた際、サービスを並列して行えるように区別するための識別子です。
サーバはクライアントから通知されたRequest IDを、そのまま応答メッセージへと使用します。
リクエストIDは、以下のようにクライアントID(16bit)とセッションID(16bit)の連結となっています。
Client ID
クライアントID は車両内ECUのうち、どのECUからの要求であるかを識別するための識別子です。
Session ID
セッション ID は、同じECUから連続して送信されたメッセージを区別するための識別⼦です。
セッション処理がアクティブでない場合セッション ID は0x00、アクティブな場合セッション ID は0x1~0xFFFFのいずれかを使用します。
セッションID使用時は呼び出しごとにインクリメントし、0xFFFF に達すると、ラップアラウンドして0x01から再び開始します。
Protcol Version
プロトコルバージョンは、使⽤されるSOME/IPヘッダーフォーマットを識別するための識別子です。
Interface Version
インターフェースバージョンは、SOME/IPメッセージにおけるペイロードの形式を指定するための識別子です。
Message Type
メッセージタイプはメッセージを区別するために使⽤されます。
具体的には以下の表のとおりに用途に応じて値が設定されます。
設定値 | メッセージタイプ | 概要 |
---|---|---|
0x00 | REQUEST | 応答を必要とする要求(例:Getter、Setter、Method call) |
0x01 | REQUEST_NO_RETURN | 応答を不要とする要求(例:Fire & forge) |
0x02 | NOTIFICATION | 応答を不要とする通知(例:Notifier) |
0x80 | RESPONSE | REQUESTメッセージに対する応答 |
0x81 | ERROR | REQUESTメッセージに対するエラー応答 |
0x20 | TP_REQUEST | 応答を必要とする要求(例:Getter、Setter、Method call) |
0x21 | TP_REQUEST_NO_RETURN | 応答を不要とする要求(例:Fire & forge) |
0x22 | TP_NOTIFICATION | 応答を不要とする通知(例:Notifier) |
0xa0 | TP_RESPONSE | TP_REQUESTメッセージに対する応答 |
0xa1 | TP_ERROR | TP_REQUESTメッセージに対するエラー応答 |
UDPで1パケットに収まりきらないメッセージを扱う場合、SOME/IPトランスポートプロトコル (SOME/IP-TP)を使用し、より大容量のデータを扱うことが可能です。
メッセージ タイプの上位3 番⽬のビット (=0x20) は TP フラグと呼ばれ、現在のSOME/IPメッセージがSOME/IP-TPであることを⽰すために1に設定されます。
SOME/IP-TPについてはこちらでまとめているため、参考にしてください。
Return Code
リターンコードは、クライアントからサーバに対する要求が正常に処理されたかどうかを通知するために使⽤されます。
応答以外のメッセージにおいては、0x00が固定値として設定されます。
設定値 | リターンコード | 概要 |
---|---|---|
0x00 | E_OK | 正常 |
0x01 | E_NOT_OK | 予期せぬエラー発生 |
0x02 | E_UNKNOWN_SERVICE | サービスID不正 |
0x03 | E_UNKNOWN_METHOD | メソッドID不正 |
0x04 | E_NOT_READY | アプリケーションがまだ起動していない |
0x05 | E_NOT_REACHABLE | アプリケーションが異常などにより動作出来ない |
0x06 | E_TIMEOUT | アプリケーション異常によるタイムアウト |
0x07 | E_WRONG_PROTOCOL_VERSION | プロトコルバージョン不正 |
0x08 | E_WRONG_INTERFACE_VERSION | インターフェースバージョン不正 |
0x09 | E_MALFORMED_MESSAGE | ペイロード不正 |
0x0a | E_WRONG_MESSAGE_TYPE | メッセージタイプ不正 |
0x0b | E_E2E_REPEATED | ECU間通信におけるやり取り中の異常 |
0x0c | E_E2E_WRONG_SEQUENCE | ECU間通信におけるやり取り中の異常 |
0x0d | E_E2E | ECU間通信におけるやり取り中の異常 |
0x0e | E_E2E_NOT_AVAILABLE | ECU間通信におけるやり取り中の異常 |
0x0f | E_E2E_NO_NEW_DATA | ECU間通信におけるやり取り中の異常 |
0x10-1f | RESERVED | ⼀般的な SOME/IPエラーのための予約領域 |
0x20-5e | RESERVED | サービスとメソッドの特定のエラーのための予約領域 |
E2E関連のエラーについてはさぼりました。
気になる人は以下などが参考になると思います。
Payload
ペイロードは、シリアル化されたパラメータが格納される領域です。
UDPのペイロード長は 0 〜 1400バイトになりますが、前述のSOME/IP-TPを使用することでより大きなサイズのパラメータを扱うことが可能です。
TCPの場合は、もともとペイロードのセグメント化をサポートしているためフレームサイズ以上のデータを扱うことが出来ます。
ペイロードデータのシリアル化に関してもSOME/IPで規定されているのですが、今回は割愛します。
気になる方は冒頭の規格書を確認してください。
最後に
今回はSOME/IPプロトコルの基本的な部分についてまとめてみました。
引き続き、今回詳細まで解説しきれなかった要素(SOME/IP-TP、SOME/IP-SD)についても勉強していく予定です。
pythonをつかってSOME/IPの相互通信が出来るようなツールも作ってみましたため、こちらも参考にしていただければと思います。