DoIP로 진단 자동화를 붙이다 보면 ECU Reset 이후에만 이상해지는 구간이 있다.
- reset 요청은 성공했다
- ECU도 실제로 재부팅된 것 같다
- 그런데 다음 요청부터 timeout처럼 보인다
- 어떤 경우에는 TCP는 살아 있는데 UDS만 실패한다
이때 reset service 자체를 의심하기 쉽지만,
실제로는 reset 뒤 연결 문맥을 이전 세션처럼 재사용한 문제가 더 자주 보인다.
오늘 메모는 ECU Reset 이후 DoIP 재연결 순서를 어떻게 봐야 덜 헤매는지다.
reset 뒤에는 같은 연결이 아닐 수 있다
UDS ECU Reset은 애플리케이션 기능 하나를 다시 시작하는 정도로 끝나지 않을 수 있다.
- 대상 ECU가 내부 진단 상태를 초기화할 수 있다
- 게이트웨이가 해당 경로를 잠시 끊을 수 있다
- TCP 소켓이 바로 닫히거나, 살아 보여도 진단 컨텍스트가 사라질 수 있다
그래서 reset 직후에 가장 위험한 가정은 이거다.
방금 전까지 되던 소켓과 Routing Activation 상태가 그대로 남아 있을 것이다
실무에서는 이 가정이 자주 틀린다.
흔한 실패 순서
현장에서 자주 보는 흐름은 대략 이렇다.
DiagnosticSessionControl
-> ECU Reset
-> ECU 재부팅 구간
-> 테스터는 기존 TCP 소켓 또는 기존 상태 캐시 유지
-> 다음 UDS 전송
-> 무응답 또는 첫 요청 실패
겉으로는 “reset 뒤 ECU가 안 살아난다”처럼 보이지만,
실제로는 테스터가 예전 연결 세대의 상태를 다시 쓰고 있을 때가 많다.
왜 ACK는 보이는데 실제 진단은 실패할까
reset 직후 특히 헷갈리는 지점이 여기다.
- TCP connect는 유지된 것처럼 보임
- 혹은 DoIP 레벨 ACK가 보임
- 그런데 최종 UDS 응답은 없음
이 경우 ACK만 보고 성공으로 넘기면 안 된다.
reset 이후에는 아래 셋을 따로 봐야 한다.
- 소켓이 진짜 같은 세션인지
- Routing Activation을 다시 해야 하는지
- ECU가 진단 세션과 keepalive 상태를 잃었는지
즉,
TCP alive
!=
진단 세션 alive
가 되는 구간이다.
자주 틀리는 구현 포인트
1) reset 직후 첫 요청을 너무 빨리 보낸다
ECU Reset 응답을 받았다고 해서
대상 ECU가 바로 다음 요청을 받을 준비가 된 것은 아니다.
특히 게이트웨이 뒤 ECU면:
- 재부팅 시간
- 내부 라우팅 복구 시간
- 세션 재초기화 시간
이 따로 걸릴 수 있다.
이때 첫 요청을 바로 던지면
timeout처럼 보이거나 Routing Activation은 됐는데 첫 UDS 실패 패턴으로 이어지기 쉽다.
2) Routing Activation 재수행 조건이 없다
많이 보는 코드가 이렇다.
if (socket_is_open) {
skip_routing_activation();
}
reset 뒤에는 이 조건이 너무 약하다.
소켓이 열려 있어도
게이트웨이 또는 ECU 쪽 진단 컨텍스트는 이미 사라졌을 수 있다.
그래서 reset 이후에는 소켓 상태보다
연결 세대(generation)와 RA 완료 여부를 다시 확인하는 편이 안전하다.
3) Tester Present를 예전 타이머에서 계속 보낸다
reset 직전의 세션을 유지하던 Tester Present 타이머가
reset 이후에도 그대로 살아 있으면 로그가 더 헷갈린다.
- 앱은 keepalive를 보냈다고 생각함
- ECU는 아직 부팅 중이거나 새 세션 상태임
- 테스터는 “응답이 이상하다”고 판단
즉 reset 이후 keepalive도
이전 세션 연장선이 아니라 새 세션 준비 단계로 다시 봐야 한다.
로그를 이렇게 남기면 빨라진다
이 문제는 단일 패킷보다 시간축이 중요하다.
나는 보통 아래 항목을 한 묶음으로 본다.
ECU Reset요청/응답 시각- reset 이후 소켓 close/open 이벤트
- Routing Activation 재수행 여부와 완료 시각
- 첫 후속 UDS 요청 시각
- Tester Present 재개 시각
이 다섯 줄만 이어 붙여도
“ECU가 안 살아난다”와
“테스터가 너무 빨리 예전 상태를 재사용한다”가 꽤 빨리 갈린다.
구현 쪽에서 무난한 패턴
실무에서는 보통 아래 흐름이 덜 아프다.
ECU Reset 요청
-> reset 예상 구간 진입
-> 기존 세션/keepalive 상태 무효화
-> 필요 시 소켓 재연결
-> Routing Activation 재수행
-> 진단 세션 재진입 필요 여부 확인
-> 그 다음 첫 UDS 허용
핵심은 reset을 “서비스 하나 성공”으로 끝내지 말고
연결 문맥을 새로 만드는 이벤트로 다루는 것이다.
프로젝트마다 구현은 다르지만,
아래 플래그를 연결 컨텍스트에 분리해 두면 덜 꼬인다.
- socket generation
- routing activation complete
- current diagnostic session valid
- tester present enabled
- reset recovery in progress
빠른 체크리스트
- reset 이후 기존 소켓을 그대로 재사용하는지 확인
- reset 이후 Routing Activation을 건너뛰는 경로가 있는지 확인
- 첫 후속 UDS가 reset 완료 전에 너무 빨리 나가는지 확인
- Tester Present 타이머를 새 세션 기준으로 다시 시작하는지 확인
- ACK와 실제 UDS 응답을 구분해서 기록하는지 확인
한 줄 요약
DoIP에서 ECU Reset 이후 다시 안 붙는다면, reset service보다 먼저 기존 세션을 버리고 소켓, Routing Activation, Tester Present 재개 순서를 새 연결 기준으로 다시 맞추는 게 빠르다.
추천 키워드
DoIP, UDS, ECU Reset, Routing Activation, Tester Present, reconnect
DevBJ | 오늘을살자, Log Today