DoIP에서 처음에는 대부분 physical request만 테스트한다.
예를 들면:
Tester -> 특정 ECU
이런 형태다.
그런데 실제 차량에서는 functional request도 꽤 자주 사용된다.
예를 들면:
모든 ECU에게 DiagnosticSessionControl 요청
같은 경우다.
이때부터 로그가 갑자기 복잡해진다.
- 응답 ECU가 여러 개
- 응답 순서가 매번 다름
- timeout처럼 보이는 상황 발생
- 예상보다 응답이 늦음
왜냐하면 functional addressing은 point-to-point가 아니라
group diagnostic에 가깝기 때문이다.
같이 보면 좋은 글
- DoIP Vehicle Identification, ECU를 찾는 첫 단계
- DoIP Routing Activation, 진단 시작 전에 왜 필요한가
- DoIP Diagnostic Message, UDS가 실제로 어떻게 실리는지 보자
- DoIP timeout 처리, Response Pending 제대로 이해해야 덜 헤맨다
Physical vs Functional
먼저 차이부터 단순하게 보면 이렇다.
Physical
= 특정 ECU 대상
Functional
= ECU 그룹 대상
예를 들면:
TA = 0x1001
이면 특정 ECU 대상이고,
TA = Functional Group
이면 여러 ECU가 동시에 받을 수 있다.
흐름 자체가 달라진다
Physical request는 단순하다.
Tester
|
| Request
v
Single ECU
|
| Response
v
Tester
Functional request는 흐름이 달라진다.
Tester
|
| Functional Request
v
Multiple ECU
├── Response #1
├── Response #2
├── Response #3
└── ...
즉:
1 request
→ multiple responses
구조가 된다.
그래서 로그가 복잡해진다
초기 구현은 보통 이런 가정을 한다.
send_request()
wait_response()
하지만 functional request에서는 이 가정이 위험하다.
왜냐하면:
어떤 ECU가 먼저 응답할지 모름
상황이기 때문이다.
응답 순서는 보장되지 않는다
예를 들어:
ECU A -> 10ms
ECU B -> 30ms
ECU C -> 120ms
일 수 있다.
심지어 부하 상태에 따라 매번 달라진다.
그래서:
response ordering assumption
을 넣으면 나중에 흔들린다.
테스트 환경에서는 항상 ECU A가 먼저 왔는데,
실차에서는 ECU B가 먼저 오고,
가끔 ECU C가 늦게 따라오는 식이다.
이걸 single response 모델로 처리하면
정상 응답도 이상한 로그처럼 보이기 시작한다.
현장에서 자주 보는 문제
1) 첫 응답만 읽고 종료
예를 들면 이런 구조다.
resp = recv()
return resp
그러면 뒤에 오는 ECU 응답을 놓친다.
특히 ECU scan 기능 만들 때 자주 발생한다.
첫 번째 응답만 보면:
functional request 성공
처럼 보일 수 있다.
하지만 실제로는 뒤에 온 ECU 응답을 버린 상태일 수 있다.
2) timeout 기준이 애매함
Functional request는 결국 이 질문으로 간다.
언제 응답 수집을 종료할 것인가
예를 들면:
100ms wait?
500ms wait?
응답 없으면 종료?
정책이 필요하다.
실제로는 이런 기준을 섞어서 많이 본다.
- short collection window
- maximum response count
- inactivity timeout
- service별 expected response policy
단순히 전체 timeout 하나만 두면
너무 빨리 끝나거나 너무 오래 기다리게 된다.
3) ECU별 response 분리가 안 됨
Payload만 보면 안 된다.
반드시:
SA = source address
를 같이 봐야 한다.
예시 로그:
[doip] rx sa=0x1001
[doip] rx sa=0x1002
[doip] rx sa=0x1003
이렇게 남겨야 누가 응답했는지 보인다.
Functional request에서 source address를 로그에 안 남기면
나중에 trace를 봐도 구분이 어렵다.
Gateway 환경에서는 더 복잡해진다
Gateway가 functional request를 내부 bus로 forwarding할 수 있다.
예를 들면:
Ethernet
|
Gateway
├── CAN ECU
├── LIN ECU
└── Ethernet ECU
이 경우 응답 timing은 더 흔들린다.
- bus latency 차이
- forwarding queue
- ECU wakeup 상태
- 내부 bus 부하
- session 상태 차이
이런 것들이 영향을 준다.
그래서 같은 functional request를 보내도
매번 응답 순서가 달라질 수 있다.
이건 꼭 비정상이라고 볼 수 없다.
Broadcast처럼 보이지만 완전히 같지는 않다
가끔 이렇게 이해하는 경우가 있다.
functional = broadcast
완전히 틀린 느낌은 아니지만,
실제로는 diagnostic policy가 포함된다.
예를 들어 ECU마다:
- 응답 허용 여부
- suppress response 정책
- session 조건
- security 조건
- service support 여부
이 다를 수 있다.
즉:
모든 ECU가 반드시 응답하는 건 아님
이다.
그래서 functional request를 보냈는데
응답이 일부 ECU에서만 와도,
그 자체만으로 실패라고 단정하면 안 된다.
suppress positive response도 영향을 준다
UDS에는 이런 개념이 있다.
Suppress Positive Response
Functional request와 같이 쓰이면 이런 상황이 나온다.
request는 처리
BUT
positive response는 생략
그래서:
응답 없음 = 실패
로 보면 안 되는 경우가 있다.
물론 negative response는 별도로 봐야 한다.
핵심은 이거다.
- positive response가 없을 수 있음
- negative response는 올 수 있음
- ECU별 정책이 다를 수 있음
- tester는 이 차이를 알고 있어야 함
추천하는 수집 구조
Functional request는 보통 이런 흐름이 안전하다.
send request
→ collect responses
→ inactivity timeout
→ finalize
예시 느낌은 이렇다.
responses = []
send_functional_request()
while not total_timeout_expired():
resp = try_recv()
if resp:
responses.append(resp)
reset_inactivity_timer()
if inactivity_timeout_expired():
break
finalize(responses)
즉:
single response model
보다:
response collection model
이 더 맞다.
Wireshark에서도 주의할 점
Functional request는 패킷 수가 갑자기 늘어난다.
특히:
1 request
→ many responses
라서 trace 읽기가 어려워진다.
이럴 때는 이런 기준으로 보면 좋다.
- source address filter
- ECU grouping
- timestamp sorting
- request/response correlation
- service id 기준 필터
개인적으로는 먼저 source address별로 나눠서 본다.
그래야:
누가 빨랐고
누가 늦었고
누가 응답하지 않았는지
가 보인다.
오늘 포인트
DoIP Functional Address는 단순 single ECU request가 아니라
multi-response diagnostic 흐름에 가깝다.
실제로 중요한 건 이 부분이다.
- response collection
- source tracking
- timeout policy
- gateway forwarding
- suppress response 처리
Functional diagnostic 흐름을 이해하기 시작하면
multi ECU 환경 로그가 훨씬 읽히기 쉬워진다.
다음 글에서는 DoIP에서 concurrent diagnostic session이
왜 충돌하는지 이어서 다뤄보면 좋겠다.
추천 대상
- functional diagnostic을 구현 중인 개발자
- multi ECU response 처리에 어려움을 겪는 엔지니어
- gateway 기반 DoIP 로그를 분석하는 사람
한 줄 요약
DoIP Functional Address는 하나의 요청에 여러 ECU 응답이 연결되는 multi-response diagnostic 구조에 가깝다.
추천 키워드
doip, functional address, uds functional request, automotive ethernet, gateway routing, multi ecu
DevBJ | No Bio, Just Log #오늘을살자