SOME/IP 위에서 서비스 인스턴스를 찾고, 그 인스턴스가 실행 중인지 감지하고, Publish/Subscribe 구독을 성립시키는 프로토콜이 SOME/IP-SD(SOME/IP Service Discovery)다. SOME/IP-SD는 SOME/IP에 의존하지만, SOME/IP 자체가 지원하는 UDP·TCP 중 UDP로만 전송된다[1].
서비스 인스턴스는 로컬에서 가용 여부(서버 쪽)나 요청 여부(클라이언트 쪽) 상태로 관리되고, 이 상태가 바뀔 때 SD가 아래에서 다룰 엔트리를 내보낸다 — 서버 인스턴스가 가용해지면 Offer를, 클라이언트가 인스턴스를 요청하면 Find를 시작하는 식이다. 이 상태 전이가 시간에 따라 어떻게 엔트리 송신으로 이어지는지는 SOME/IP-SD State Machine에서 다룬다[1].
메시지 헤더
SD 메시지는 SOME/IP 메시지의 한 종류다 — Message ID는 항상 0xFFFF 8100으로 고정되고 Message Type은 NOTIFICATION(0x02)이다[1]. SOME/IP 표준 헤더 뒤에 SD 고유 필드가 이어진다.
Flags의 최상위 비트부터 Reboot Flag·Unicast Flag·Explicit Initial Data Control Flag 3개가 정의되고 나머지 비트는 송신 시 0으로 고정된다. Reboot Flag는 송신자가 리부팅하면 1로 바뀌고 SOME/IP 헤더의 Session ID가 다시 1부터 시작하는데, 수신자는 상대의 Reboot Flag가 0→1로 바뀌거나 Flag가 1로 유지된 채 Session ID가 이전 값보다 커지지 않고 되돌아가면 리부팅으로 판단한다 — 이 판정은 유니캐스트·멀티캐스트 상대마다 별도로 추적된다. Unicast Flag와 Explicit Initial Data Control Flag는 현재 구현에서 항상 1로 고정되며 과거 버전과의 호환을 위해 남아 있다[1].
Options Array 뒤에 Entries Array의 뒤를 잇는 옵션 목록이 온다(아래 옵션절). Entries Array와 Options Array 모두 앞선 Length 필드가 뒤따르는 바이트 수를 담고, 엔트리는 도착 순서 그대로 처리된다[1].
엔트리
Entries Array는 고정 16바이트 크기의 엔트리를 여러 개 담을 수 있다. 엔트리 종류는 서비스 인스턴스를 다루는 Service Entry Type과 이벤트그룹을 다루는 Eventgroup Entry Type 두 가지다[1].
| 필드 | 크기 | Service Entry | Eventgroup Entry |
|---|---|---|---|
| Type | 8비트 | FindService(0x00), OfferService(0x01) | Subscribe(0x06), SubscribeAck(0x07) |
| Index 1st/2nd Options | 8비트×2 | 이 엔트리가 참조하는 첫·둘째 옵션 런의 시작 인덱스 | 좌동 |
| # of Options 1/2 | 4비트×2 | 각 옵션 런에 속한 옵션 개수(0이면 해당 런 없음) | 좌동 |
| Service ID | 16비트 | 대상 서비스 ID | 대상 서비스 ID |
| Instance ID | 16비트 | 대상 인스턴스 ID | 대상 인스턴스 ID |
| Major Version | 8비트 | 서비스(인스턴스)의 Major 버전 | 이벤트그룹이 속한 인스턴스의 Major 버전 |
| TTL | 24비트 | 엔트리 유효 기간(초) | 구독 유효 기간(초) |
| Minor Version | 32비트 | 서비스(인스턴스)의 Minor 버전 | — |
| Counter | 4비트 | — | 같은 이벤트그룹의 동시 구독 구분(미사용 시 0) |
| Eventgroup ID | 16비트 | — | 대상 이벤트그룹 ID |
두 엔트리 모두 TTL에 특수값이 있다 — 0xFFFFFF는 다음 리부팅까지 무기한 유효함을, 0x000000은 정지(Stop) 또는 부정 응답(Nack)을 뜻한다[1].
| 엔트리 | Type | 용도 | TTL 규칙 |
|---|---|---|---|
| FindService | 0x00 | 알려지지 않은 서비스 인스턴스를 탐색. Instance ID 0xFFFF·Major 0xFF·Minor 0xFFFFFFFF는 각각 전체를 뜻하는 와일드카드 | 탐색 유효 기간 |
| OfferService | 0x01 | 서비스 인스턴스를 제공 중임을 알림. 도달 방법을 알리는 IPv4 Endpoint 옵션(아래 옵션절)을 최소 1개 참조 | 제공 유효 기간 |
| StopOfferService | 0x01(TTL=0) | OfferService 제공을 중단. 나머지 필드는 중단 대상 OfferService와 동일 | 0x000000(Stop) |
| SubscribeEventgroup | 0x06 | 이벤트그룹을 구독. 이벤트를 받을 IPv4·IPv6 Endpoint 옵션을 1~2개 참조 | 구독 유효 기간 |
| StopSubscribeEventgroup | 0x06(TTL=0) | 구독을 해지. 나머지 필드·참조 옵션은 중단 대상 Subscribe와 동일 | 0x000000(Stop) |
| SubscribeEventgroupAck | 0x07 | 구독 수락. Subscribe 엔트리의 필드를 그대로 복사, 멀티캐스트로 이벤트를 보낼 경우 Multicast 옵션을 참조 | Subscribe와 동일 |
| SubscribeEventgroupNack | 0x07(TTL=0) | 구독 거부 — 대상 조합을 모름·필요한 TCP 연결 미확보·참조 옵션 문제·자원 부족 등이 사유가 될 수 있음 | 0x000000(Nack) |
옵션
옵션은 엔트리에 부가 정보(도달 IP·포트 등)를 실어 나른다. 모든 옵션은 Length(16비트, 이어지는 바이트 수)·Type(8비트)·Discardable Flag(1비트, 나머지 7비트는 예약) 헤더로 시작한다. 엔트리는 자신이 참조하는 옵션의 범위를 Index·개수 필드로만 가리키므로, 여러 엔트리가 같은 옵션을 공유해 메시지 크기를 줄일 수 있다[1].
| 옵션 | Type | 역할 |
|---|---|---|
| IPv4 Endpoint | 0x04 | 서비스 인스턴스의 도달 IP·전송 계층 프로토콜(UDP/TCP)·포트. OfferService가 서버 측 엔드포인트를, SubscribeEventgroup이 클라이언트 측 엔드포인트를 알리는 데 쓰인다 — 같은 엔드포인트가 이벤트·알림의 발신 주소로도 재사용된다 |
| IPv4 SD Endpoint | 0x24 | 발신자 SD 인스턴스 자체의 IP·포트. 패킷의 발신 주소·포트를 그대로 쓸 수 없는 경우(예: 다른 ECU의 멀티캐스트 트래픽을 대신 처리하는 프록시 서비스 디스커버리)를 위한 것으로, 있으면 옵션 배열의 첫 옵션이어야 하고 어떤 엔트리도 이를 인덱스로 참조하지 않는다 |
| Multicast | 0x14(IPv4) | 이벤트·알림을 멀티캐스트로 받을 IP·포트. SubscribeEventgroupAck 엔트리만 참조할 수 있고 전송 계층은 UDP로 고정된다 |
| Configuration | 0x01 | [길이]키=값 형식을 반복하는 0-종단 문자열로 임의의 설정 정보(예: 서비스 이름)를 실어 나른다 |
엔트리 종류마다 허용되는 옵션 개수는 다음과 같다[1]:
| 엔트리 | Endpoint | Multicast | Configuration |
|---|---|---|---|
| FindService | 0 | 0 | 0~1 |
| OfferService / StopOfferService | 1~2 | 0 | 0~1 |
| SubscribeEventgroup / StopSubscribeEventgroup | 1~2 | 0 | 0~1 |
| SubscribeEventgroupAck | 0 | 0~1 | 0~1 |
| SubscribeEventgroupNack | 0 | 0 | 0~1 |
오류 처리
SD 메시지가 12바이트보다 짧으면 메시지 전체를 무시한다. 그렇지 않으면 엔트리를 하나씩 검사한다 — Service ID·Instance ID·Major Version·(이벤트그룹 엔트리라면) Eventgroup ID 조합을 모르거나, 참조하는 옵션이 없거나 유효하지 않거나, 필요한 TCP 연결이 열려 있지 않거나, 자원이 부족하면 그 엔트리는 처리하지 않는다. 이때 SubscribeEventgroup 엔트리는 SubscribeEventgroupNack으로 명시적으로 거부 응답을 보내고, 그 외 엔트리는 응답 없이 조용히 무시한다[1].