Skip to content
오늘을살자
Go back

DoIP에서 Response Pending 중 Tester Present를 섞으면 꼬인다: 같은 세션 유지와 대기 흐름을 분리해서 봐야 한다

Edit page

긴 UDS 요청을 붙이다 보면 이런 구간이 나온다.

이때 “세션 유지를 잘한 것 같은데 왜 더 꼬이지?”라는 느낌을 자주 받는다.

오늘 메모는 DoIP에서 Response Pending 대기 중 Tester Present를 섞어 보낼 때 어디서 꼬이기 쉬운지다.

결론부터

0x78이 왔다는 것은 보통 이미 보낸 본 요청이 아직 진행 중이라는 뜻이다.

반면 Tester Present는 보통 세션을 유지하기 위한 별도 관리 요청이다.

둘 다 UDS 위에 있지만 역할은 다르다.

본 요청:
RoutineControl / ReadData / Download ...
-> 0x78
-> 최종 응답 대기

세션 유지 요청:
Tester Present
-> 세션 timeout 방지 목적

따라서 구현에서는
대기 중인 본 요청 흐름과 세션 유지 흐름을 분리해서 다루는 편이 안전하다.

왜 바로 섞고 싶어지나

현장에서는 이유가 충분히 있다.

그래서 자연스럽게 이런 코드를 넣기 쉽다.

request 전송
-> 0x78 수신
-> 대기 타이머 시작
-> 중간에 Tester Present 주기 송신
-> 응답 처리 복잡도 증가

문제는 여기서부터다.

자주 터지는 실수 1: 응답 대기 슬롯이 하나뿐이다

테스터가 “지금 기다리는 응답”을 하나의 전역 상태로만 들고 있으면,
Tester Present 응답이 본 요청 응답 상태를 덮어쓸 수 있다.

예를 들면 이런 식이다.

ReadDataByIdentifier 전송
-> 0x78 수신
-> waiting_sid = 0x22
-> Tester Present 전송
-> Tester Present 응답 수신
-> waiting_sid 갱신 또는 초기화
-> 실제 0x22 최종 응답 도착
-> 응답 매칭 실패

패킷은 정상인데
앱 상태머신만 꼬이는 전형적인 패턴이다.

자주 터지는 실수 2: Tester Present를 같은 retry 흐름에 묶는다

0x78은 timeout이 아니다.
이미 받은 정상 응답의 한 종류다.

그런데 코드가 아래처럼 짜여 있으면 문제가 생긴다.

0x78 수신
-> "응답이 아직 안 끝남"
-> 같은 요청 큐에 Tester Present 삽입
-> 대기 타이머와 세션 유지 타이머가 같은 정책을 공유

그러면 이런 혼선이 나온다.

즉 네트워크보다 먼저
타이머 책임을 분리했는지를 봐야 한다.

자주 터지는 실수 3: ECU가 다른 요청 끼어들기를 싫어한다

모든 ECU가 똑같이 동작하지는 않는다.

어떤 구현은 0x78을 보낸 뒤에도
같은 세션의 Tester Present를 잘 받아 준다.

하지만 어떤 구현은:

이 경우 증상은 이런 식으로 보일 수 있다.

그래서 “세션 유지를 위해 넣은 패킷”이
오히려 디버깅 노이즈가 되기도 한다.

suppress positive response도 같이 보면 헷갈림이 줄어든다

Tester Present는 suppress positive response 비트를 함께 쓰는 경우가 많다.

이 옵션이 들어가면 로그 해석이 더 헷갈릴 수 있다.

Tester Present 송신
-> positive response 없음
-> 정상인지 누락인지 헷갈림

이 상태에서 본 요청의 최종 응답만 기다려야 하는데,
구현이 “왜 응답이 안 왔지?”로 오해하면
불필요한 재전송이나 재연결로 이어진다.

즉 Tester Present 자체도
응답이 반드시 오는 관리 요청인지, 무응답이 정상일 수 있는지를 코드가 알고 있어야 한다.

구현 쪽에서 무난한 패턴

가장 단순한 방향은 이렇다.

본 요청 상태머신:
request 전송
-> 0x78 수신
-> 같은 transaction 유지
-> 최종 응답 대기

세션 유지 상태머신:
idle일 때 주기 관리
-> 필요 시 Tester Present 전송
-> suppress 설정에 맞춰 별도 처리

그리고 긴 작업 중에는 정책을 명확히 두는 편이 좋다.

핵심은 본 요청 응답 대기 상태를 Tester Present가 건드리지 않게 하는 것이다.

로그를 이렇게 남기면 빨라진다

이 이슈는 패킷 캡처만 보면 “둘 다 정상 송수신”처럼 보일 수 있다.

나는 보통 아래 항목을 같이 남긴다.

  1. 현재 대기 중인 본 요청 SID
  2. 마지막 0x78 수신 시각
  3. Tester Present 송신 시각과 suppress 사용 여부
  4. 응답 매칭 키가 SID인지, transaction 상태인지
  5. 본 요청 timeout과 세션 유지 타이머가 서로 다른지

이 다섯 줄이 있으면
“ECU가 이상한가”보다
“테스터 상태머신이 서로 섞였는가”를 빨리 볼 수 있다.

빠른 체크리스트

  1. 0x78 대기 중인 본 요청 상태와 Tester Present 상태를 별도 변수로 관리하는지 확인
  2. 기다리는 응답 슬롯이 하나뿐이라서 Tester Present 응답이 본 요청 상태를 덮어쓰지 않는지 확인
  3. Tester Present의 suppress positive response 사용 여부를 로그에 남기는지 확인
  4. 본 요청 timeout 정책과 세션 유지 주기를 같은 타이머로 돌리지 않는지 확인
  5. 특정 ECU가 긴 작업 중 병렬 요청을 허용하는지 실제 캡처로 확인했는지 점검

한 줄 요약

DoIP에서 0x78 Response Pending 대기 중 Tester Present를 섞어 보내야 한다면, 세션 유지 요청과 본 요청 응답 대기 상태를 같은 큐와 같은 타이머로 처리하지 말고 서로 분리해 관리하는 편이 안전하다.

추천 키워드

DoIP, UDS, Tester Present, Response Pending, NRC, Diagnostic Session


DevBJ | 오늘을살자, Log Today


Edit page
Share this post on:

Previous Post
lwIP RAW UDP callback 뒤에 수신이 멈춘다: pbuf_free를 놓치면 PBUF_POOL이 먼저 마른다
Next Post
Wireshark Reassembled TCP Segments 의미: 여러 TCP 조각이 하나의 메시지로 보일 때