현장에서 DoIP 붙일 때 의외로 자주 보는 로그가 있다.
- TCP 연결 성공
- Routing Activation 성공
- 그런데 첫 UDS 요청이 실패
실패 모양은 제각각이다.
- 어떤 날은 DoIP NACK가 온다
- 어떤 날은 그냥 timeout처럼 보인다
- 어떤 날은 응답이 오긴 오는데, 기대한 ECU가 아닌 것처럼 보인다
이럴 때 ECU 애플리케이션부터 파기 시작하면 시간이 길어진다.
내가 먼저 보는 건 보통 이쪽이다.
Routing Activation에 쓴 주소 정보와, 실제 Diagnostic Message에 쓴 SA/TA가 같은 맥락으로 이어지고 있나?
핵심부터
DoIP에서는 “연결이 됐다”와 “진단 경로가 맞다”가 같은 말이 아니다.
- TCP 연결: 소켓이 열렸다
- Routing Activation: 이 테스터 세션을 진단용으로 인정했다
- Diagnostic Message: 실제로 어떤 SA에서 어떤 TA로 UDS를 보낼지 결정한다
그래서 RA가 성공해도,
그 다음 Diagnostic Message의 주소 조합이 어긋나면 바로 실패할 수 있다.
가장 흔한 패턴: 재연결 뒤에 상태를 절반만 복구한다
재현이 잘 안 되는 팀 코드를 보면 대체로 이런 순서가 숨어 있다.
1) TCP 세션이 한번 끊김
2) 소켓 자동 재연결
3) Routing Activation 재시도
4) 기존에 캐시한 SA/TA/세션 정보를 그대로 재사용
5) 첫 UDS 요청 실패
문제는 4)다.
재연결 후에는 애플리케이션 입장에서 “같은 차량, 같은 ECU”처럼 보여도,
DoIP 세션 관점에서는 새 연결이다.
이때 흔한 실수는 아래 셋이다.
- 예전 소켓에 매핑된 테스터 주소 상태를 그대로 믿는다
- ECU별 Target Address를 라우팅 재구성 없이 바로 쓴다
- 재연결 직후 첫 요청을 너무 빨리 보내서 RA 완료 상태와 섞인다
SA/TA를 왜 같이 봐야 하나
현장에서는 종종 SA만 맞추면 된다고 생각한다.
하지만 실제 실패는 SA와 TA 조합에서 난다.
- SA(Source Address): “이 요청을 보내는 테스터가 누구냐”
- TA(Target Address): “어느 ECU로 보내려는 거냐”
Routing Activation이 끝났더라도,
DoIP Entity가 현재 세션에서 허용한 SA와
내가 실제 Diagnostic Message에 넣은 SA가 다르면 거절될 수 있다.
반대로 SA는 맞아도,
TA가 현재 게이트웨이 라우팅 테이블과 안 맞으면 또 실패한다.
즉 이런 식으로 나눠 봐야 한다.
RA 성공
!=
모든 SA/TA 조합으로 UDS 가능
첫 요청만 실패하는 이유
첫 요청만 실패하고 두 번째부터는 되는 현상도 있다.
이것도 보통 타이밍과 상태 캐시 문제다.
1) RA 완료 이벤트보다 먼저 UDS를 보낸다
소켓 재연결 직후 비동기 상태머신이 꼬이면,
애플리케이션은 “RA 보냈다”를 “RA 완료”로 오해할 수 있다.
이 상태에서 첫 UDS가 먼저 나가면:
- NACK
- 무응답
- 게이트웨이 내부 discard
중 하나로 보일 수 있다.
2) ECU 선택 상태를 이전 연결에서 끌고 온다
멀티 ECU 환경에서는 테스터 쪽 캐시가 남아 있는 경우가 많다.
- 이전 연결에서
TA = ECU_A - 재연결 후에는 게이트웨이 라우팅이 아직 ECU_B 경로만 유효
- 그런데 애플리케이션은 그대로 ECU_A 요청 전송
그러면 현상은 “가끔 다른 ECU가 응답하는 것 같다”처럼 보이기도 한다.
사실은 주소/경로 상태가 정리되지 않은 것이다.
3) Diagnostic ACK를 성공으로 착각한다
RA 직후 첫 요청에서 ACK가 보이면,
테스터 쪽에서는 성공으로 넘어가기 쉽다.
하지만 ACK는 DoIP 레벨 신호일 뿐이고,
UDS가 원하는 ECU에 정상 전달됐다는 뜻은 아니다.
그래서 첫 요청 실패를 볼 때는
ACK 유무보다 SA/TA, 소켓 ID, RA 완료 시각을 같은 줄에 놓고 봐야 한다.
로그를 이렇게 남기면 빨라진다
나는 첫 요청 실패 이슈에서는 아래 항목을 묶어 본다.
- TCP 연결 카운터 또는 소켓 핸들
- Routing Activation 요청/응답 시각
- 해당 연결에서 사용한 SA
- 첫 Diagnostic Message의 SA/TA
- ACK/NACK 유무
- 실제 UDS 응답 또는 timeout
이걸 한 화면에 붙여 놓으면,
“재연결은 됐지만 주소 상태는 안 맞는다”가 바로 드러난다.
구현 쪽에서 안전한 패턴
실무에서는 아래 패턴이 덜 아프다.
TCP connected
-> Routing Activation complete
-> connection context 초기화
-> SA 확정
-> TA 선택 또는 재검증
-> 첫 UDS 요청 허용
포인트는 “첫 UDS 요청 허용”을
연결 이벤트가 아니라 RA 완료 + 주소 상태 검증 완료 뒤로 미루는 것이다.
가능하면 연결 컨텍스트에 이런 값을 같이 묶어두는 편이 좋다.
- socket/session id
- activated SA
- last selected TA
- RA completion flag
- reconnect generation counter
그러면 예전 연결의 SA/TA가 새 연결에 섞이는 실수를 줄일 수 있다.
빠른 체크리스트
- 재연결 후 Routing Activation을 다시 했는지 확인
- RA에 사용한 테스터 주소와 실제 Diagnostic Message의 SA가 같은지 확인
- 첫 요청의 TA가 현재 ECU 라우팅 상태와 맞는지 확인
- “RA 전송 완료”와 “RA 응답 수신 완료”를 구분했는지 확인
- 첫 요청 로그에 소켓 ID와 연결 카운터를 남기는지 확인
- ACK를 UDS 성공으로 처리하는 코드가 없는지 확인
한 줄 요약
Routing Activation이 성공했는데 첫 UDS 요청이 실패하면, ECU 로직보다 먼저 재연결 이후 SA/TA 상태와 RA 완료 순서를 같은 연결 컨텍스트 안에서 확인하는 게 제일 빠르다.
추천 키워드
DoIP, UDS, Routing Activation, Source Address, Target Address, reconnect
DevBJ | 오늘을살자, Log Today