Skip to content

Add Layer Build and Validation for DoIP (Diagnostic over IP) Support #1655

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 54 commits into
base: dev
Choose a base branch
from

Conversation

raissi-oussema
Copy link

@raissi-oussema raissi-oussema commented Dec 7, 2024

DoIP Protocol Overview

The Diagnostic over IP (DoIP) protocol is used in automotive diagnostic systems to facilitate communication between diagnostic tools and ECUs (Electronic Control Units) over IP-based networks. It enables remote diagnostics, configuration, and software updates over Ethernet, offering an efficient and scalable solution for modern vehicles.

Header Structure (8 bytes)

protocol version (1 byte)
invert protocol version (1 byte)
payload type (2 bytes)
payload length (4 bytes)

Pyload types / code / structure

  • "Generic DOIP header Nack" (0x0000) (header + nackCode (1 byte : required))
  • "Vehicle identification request" (0x0001) (header)
  • "Vehicle identification request with EID" (0x0002) (header + EID (6 bytes : required))
  • "Vehicle identification request with VIN" (0x0003) (header + VIN (17 bytes : required))
  • "Vehicle announcement message" (0x0004) (header + VIN (17 bytes : required) + logical address (2bytes : required) + EID (6 bytes : required) + GID (6 bytes : required) + further action (1 bytes : required)+ sync status (1 bytes : optional)).
  • "Routing activation request" (0x0005) (header + source address (2 bytes : required) + activation type (1 byte:required) + reservedISO (4 bytes : required) + reservedOEM (4 bytes : optional)).
  • "Routing activation response" (0x0006) (header + tester adress(2 bytes : required) + response code (1 byte:required) + reservedISO (4 bytes : required) + reservedOEM (4 bytes : optional)).
  • "Alive check request" (0x0007) (header)
  • "Alive check response" (0x0008) (header + source address (2 byte : required))
  • "DOIP entity status request" (0x4001) (header)
  • "DOIP entity status response" (0x4002) (header + node type (1 byte : required) + max concurrent socket (1 byte : required) + currently opened sockets (1 byte : required) + max data size(4 bytes : optional))
  • "Diagnostic power mode request information" (0x4003) (header)
  • "Diagnostic power mode response information" (0x4004) (header + power mode (1 byte : required))
  • "Diagnostic message" (0x8001) (header + source address (2 bytes : required) + target address (2 bytes : required) + UDS message (n bytes : required ; n > 1))
  • "Diagnostic message Ack" (0x8002) (header + source address (2 bytes : required) + target address (2 bytes : required) + ack code (1 byte : required)) + previous message (n bytes : optional ; n>0))
  • "Diagnostic message Nack" (0x8003) (header + source address (2 bytes : required) + target address (2 bytes : required) + Nack code (1 byte : required)) + previous message (n bytes : optional ; n>0))

@Dimi1010
Copy link
Collaborator

Dimi1010 commented Dec 8, 2024

As per the contributing guidelines, please retarget the PR to the dev branch instead of the master.

@tigercosmos tigercosmos changed the base branch from master to dev December 8, 2024 09:37
@egecetin egecetin closed this Dec 8, 2024
@egecetin egecetin reopened this Dec 8, 2024
@egecetin egecetin linked an issue Dec 8, 2024 that may be closed by this pull request
@raissi-oussema
Copy link
Author

Observed several issues in the CI pipelines, likely due to missing definitions for htobe16 and other endianness conversion macros. All tests and pre-commit checks are passed in my linux machine.
Adding an import for "EndianPortable.h" in last PR is expected to resolve these problems.

Copy link

codecov bot commented Dec 10, 2024

Codecov Report

Attention: Patch coverage is 97.85388% with 47 lines in your changes missing coverage. Please review.

Project coverage is 83.62%. Comparing base (74322eb) to head (885809a).
Report is 35 commits behind head on dev.

Files with missing lines Patch % Lines
Packet++/src/DoIpLayer.cpp 96.32% 27 Missing and 8 partials ⚠️
Packet++/header/DoIpLayer.h 96.16% 7 Missing and 3 partials ⚠️
Packet++/src/TcpLayer.cpp 83.33% 1 Missing ⚠️
Packet++/src/UdpLayer.cpp 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1655      +/-   ##
==========================================
+ Coverage   83.10%   83.62%   +0.52%     
==========================================
  Files         283      287       +4     
  Lines       48929    51047    +2118     
  Branches    10303    10963     +660     
==========================================
+ Hits        40664    42690    +2026     
- Misses       7113     7241     +128     
+ Partials     1152     1116      -36     
Flag Coverage Δ
alpine320 75.78% <94.81%> (+0.70%) ⬆️
fedora40 ?
fedora42 75.87% <94.72%> (?)
macos-13 81.17% <95.87%> (+0.56%) ⬆️
macos-14 81.17% <95.87%> (+0.56%) ⬆️
macos-15 81.15% <95.87%> (+0.57%) ⬆️
mingw32 71.61% <76.37%> (+0.85%) ⬆️
mingw64 71.56% <76.45%> (+0.84%) ⬆️
npcap 85.41% <95.41%> (+0.34%) ⬆️
rhel94 75.63% <94.10%> (+0.65%) ⬆️
ubuntu2004 58.63% <60.39%> (+0.07%) ⬆️
ubuntu2004-zstd 58.74% <60.39%> (+0.07%) ⬆️
ubuntu2204 75.58% <94.10%> (+0.69%) ⬆️
ubuntu2204-icpx 61.52% <62.36%> (+0.02%) ⬆️
ubuntu2404 75.84% <94.82%> (+0.69%) ⬆️
ubuntu2404-arm64 75.82% <94.82%> (?)
unittest 83.62% <97.85%> (+0.52%) ⬆️
windows-2019 85.43% <95.41%> (+0.34%) ⬆️
windows-2022 85.45% <95.41%> (+0.33%) ⬆️
winpcap 85.58% <95.41%> (+0.32%) ⬆️
xdp 52.05% <94.10%> (+1.48%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@seladb
Copy link
Owner

seladb commented Jan 3, 2025

@raissi-oussema are you planning to continue working on this PR?

@raissi-oussema
Copy link
Author

Hi, I was engaged with other tasks, but I plan to get back to this PR soon. Thanks for your understanding!

raissi-oussema and others added 2 commits January 6, 2025 01:52
.improve  maps searchs for doipEnumsToStrings
.cover more uses cases based on codecov feedback
@raissi-oussema
Copy link
Author

Design suggestions or code improvements are always welcome and greatly appreciated.

@seladb
Copy link
Owner

seladb commented Jan 8, 2025

@raissi-oussema to make it easier to review, do you think you can add some documentation on the DoIP protocol to the PR body?

It'd mostly be helpful to get more details on the header structure and different possible message

@raissi-oussema
Copy link
Author

@seladb I need support for CI pipelines, I can't figure out why are they still failing. And a clear documentation was successfully added to PR body to make it easier for you to start the code review.

@Dimi1010
Copy link
Collaborator

Dimi1010 commented Jan 12, 2025

@seladb I need support for CI pipelines, I can't figure out why are they still failing. And a clear documentation was successfully added to PR body to make it easier for you to start the code review.

Doxigen pipeline:
/__w/PcapPlusPlus/PcapPlusPlus/Packet++/header/DoIpLayer.h:42: error: Compound pcpp::DoIpLayer is not documented. (warning treated as error, aborting now)

XDP pipeline:
That is an issue with the CI image. Merge latest changes from dev branch and it should be fine.

VS pipeline:
Tbh, no idea om that one. It seems the opencoverage download link stopped working for a bit or something.

@raissi-oussema
Copy link
Author

@seladb I need support for CI pipelines, I can't figure out why are they still failing. And a clear documentation was successfully added to PR body to make it easier for you to start the code review.

Doxigen pipeline: /__w/PcapPlusPlus/PcapPlusPlus/Packet++/header/DoIpLayer.h:42: error: Compound pcpp::DoIpLayer is not documented. (warning treated as error, aborting now)

XDP pipeline: That is an issue with the CI image. Merge latest changes from dev branch and it should be fine.

VS pipeline: Tbh, no idea om that one. It seems the opencoverage download link stopped working for a bit or something.

What could be the problem for dioxygen pipeline, doipLayer.h is well documented [line 42] ?

// implement abstract methods

/**
* TODO, parse UDS layer
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for another PR? If so, should the remaining data be parsed as a generic payload layer for now?

Copy link
Author

@raissi-oussema raissi-oussema Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_NextLayer is intended to be the UDS layer, which has not been implemented yet. In the future, as more knowledge is gained, either I or another contributor may add this functionality. For now, I suggest parsing it as a generic layer, as you mentioned.
PS: the nextLayer will be parsed only when the payloadType is 0x8001.

Copy link
Author

@raissi-oussema raissi-oussema Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your feedback is highly appertiated, what do you think about adding this snippet of code:

void  parseNextLayer() override
		{
			if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE)
			{
				size_t headerLen = sizeof(doiphdr);

				if (m_DataLen <= headerLen + 2 /*source address size*/ + 2 /*target address size*/)
					return;

				uint8_t* payload = m_Data + (headerLen + 2 + 2);
				size_t payloadLen = m_DataLen - (headerLen + 2 + 2);
				m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
				return;
			}
		}`

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your feedback is highly appertiated, what do you think about adding this snippet of code:

void  parseNextLayer() override
		{
			if (getPayloadType() == DoIpPayloadTypes::DIAGNOSTIC_MESSAGE_TYPE)
			{
				size_t headerLen = sizeof(doiphdr);

				if (m_DataLen <= headerLen + 2 /*source address size*/ + 2 /*target address size*/)
					return;

				uint8_t* payload = m_Data + (headerLen + 2 + 2);
				size_t payloadLen = m_DataLen - (headerLen + 2 + 2);
				m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
				return;
			}
		}`

Seems good. Can the source address and target address used in that type of message be accessed from this layer? Since we are excluding it from the generic payload.

A minor tip, having headerLen be marked as constexpr might allow some compiler optimizations (such as the arithmetic using it + a literal being computed during compilation and hardcoded if possible).

Also why the return statement that is at the end of the block anyway?

Copy link
Author

@raissi-oussema raissi-oussema Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Dimi1010 , this approach appears both safer and cleaner. It allows us to construct a DiagnosticMessage directly from the current layer, providing direct access to the diagnostic data. Using this data, we can then build a generic PayloadLayer.

void parseNextLayer() override
{
	DiagnosticMessageData diagnosticMessage;

	if (diagnosticMessage.buildFromLayer(this))
	{
		m_NextLayer = new PayloadLayer(diagnosticMessage.diagnosticData.data(),
				                             diagnosticMessage.diagnosticData.size(), this, m_Packet);
	}
}

buildFromLayer safely parses the current layer and verifies whether it represents a valid diagnostic message.
what do you think ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but my question stands. DiagnosticMessageData has two other members (sourceAddress and targetAddress) which at the moment I don't see how the user can access them easily. They have neither accessors in the current DoIPLayer or are included as part of the UDSLayer (currently PayloadLayer).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sourceAddress and targetAddress are public members of DiagnosticMessageData class just like diagnosticData and they are not part of the UDS layer:

uint16_t sourceAddress;              /**< Source address of the message. */
uint16_t targetAddress;              /**< Target address for the diagnostic message. */
std::vector<uint8_t> diagnosticData; /**< Diagnostic message data with dynamic length. */

the user can access these fields by the method buildFromLayer .
I've made this dummy function just to show how to access to these fields :

void DoIpLayer::resolveDiagMessageFields()
	{
		DiagnosticMessageData diagnosticMessage;
		if (diagnosticMessage.buildFromLayer(this))
		{
			uint16_t srcAddr = diagnosticMessage.sourceAddress;
			uint16_t targetAddr = diagnosticMessage.targetAddress;
			std::vector<uint8_t> diagData = diagnosticMessage.diagnosticData;
		}
	}

Do you think this implementation need more improvement ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, if i am understanding correctly the sequence is this?

  1. User somehow receives a DoIPLayer from a Packet
  2. User checks the payload type (via DoIPLayer::getPayloadType())
  3. Depending on the payload type user uses T::buildFromLayer(DoIPLayer) (T being the corresponding message struct) to populate the data from the layer into the struct.

Am I understanding the flow correctly?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes you are absolutely correct.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that works fine. 👍

Co-authored-by: Dimitar Krastev <dimi1010100@gmail.com>
@raissi-oussema
Copy link
Author

I'm about trying to modify some other parsing logic using some structs to store fields like in announcement, routing request... and remove private vars.
I'll try to share solution in 2 days.
@seladb , @Dimi1010

@raissi-oussema
Copy link
Author

@seladb, could you please have a look, I've made serval changes in this current version and layer now is more aligned with other layer implementation, you can start reviewing this PR,
Waiting for your feedbacks.

Copy link
Owner

@seladb seladb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raissi-oussema I mostly reviewed the base class DoIpLayer but since there are enough comments, I suggest you address those before I review the rest of the classes and files

@raissi-oussema raissi-oussema requested a review from seladb May 1, 2025 13:40
@raissi-oussema
Copy link
Author

@seladb , could you please have a look and suggest what we can improve more

@raissi-oussema
Copy link
Author

@seladb , could you have a look, I've made suggested changes.

@raissi-oussema raissi-oussema requested a review from seladb May 6, 2025 19:25
std::string DoIpVehicleIdentificationRequestVIN::getSummary() const
{
std::ostringstream oss;
oss << "VIN: " << std::string(reinterpret_cast<const char*>(getVIN().data()), DOIP_VIN_LEN) << "\n";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If VIN is always a string, should getVIN() return a string and setVIN() accept a string? 🤔

Same for the constructor - should it accept a string VIN?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will keep it like this as disscussed in this comment .

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If VIN can include non-printable characters, we shouldn't convert it to string... We should either print the hex representation of it using pcpp::byteArrayToHexString() or not print it at all

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raissi-oussema I'm not sure you saw this comment ☝️

@raissi-oussema raissi-oussema requested a review from seladb May 11, 2025 21:12
@raissi-oussema raissi-oussema requested a review from Dimi1010 May 13, 2025 08:38
@raissi-oussema
Copy link
Author

@seladb , Could you check if there are any areas left to improve or optimize further?

std::string DoIpVehicleIdentificationRequestVIN::getSummary() const
{
std::ostringstream oss;
oss << "VIN: " << std::string(reinterpret_cast<const char*>(getVIN().data()), DOIP_VIN_LEN) << "\n";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If VIN can include non-printable characters, we shouldn't convert it to string... We should either print the hex representation of it using pcpp::byteArrayToHexString() or not print it at all

Comment on lines 1121 to 1125
if (currentDiagnosticDataLen > 0)
{
shortenLayer(DIAGNOSTIC_DATA_OFFSET, currentDiagnosticDataLen);
}
extendLayer(DIAGNOSTIC_DATA_OFFSET, data.size());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if currentDiagnosticDataLen > 0 we're shortening the layer and then extending it again. Insead we can calculate the length and do a single change:

auto layerExtensionLen = data.size() - currentDiagnosticDataLen;
if (layerExtensionLen > 0)
{
	extendLayer(DIAGNOSTIC_DATA_OFFSET + currentDiagnosticDataLen, layerExtensionLen );
}
else if (layerExtensionLen < 0)
{
	shortenLayer(DIAGNOSTIC_DATA_OFFSET, layerExtensionLen );
}

Copy link
Author

@raissi-oussema raissi-oussema May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the logic here might be incorrect. When subtracting two size_t values, a negative result causes unsigned underflow and produces a very large number. If layerExtensionLen is negative, we likely need to shrink the layer starting from DIAGNOSTIC_DATA_OFFSET + data.size(), using the absolute value of the difference (i.e., -1 * layerExtensionLen).
code will looks like this :

void DoIpDiagnosticMessage::setDiagnosticData(const std::vector<uint8_t>& data)
	{
		const size_t newPayloadLength = DOIP_SOURCE_ADDRESS_LEN + DOIP_TARGET_ADDRESS_LEN + data.size();
		const size_t currentDiagnosticDataLen = m_DataLen - DIAGNOSTIC_DATA_OFFSET;
		setPayloadLength(newPayloadLength);

		ptrdiff_t layerExtensionLen =
		    static_cast<ptrdiff_t>(data.size()) - static_cast<ptrdiff_t>(currentDiagnosticDataLen);
		if (layerExtensionLen > 0)
		{
			extendLayer(DIAGNOSTIC_DATA_OFFSET + currentDiagnosticDataLen, layerExtensionLen);
		}
		else if (layerExtensionLen < 0)
		{
			shortenLayer(DIAGNOSTIC_DATA_OFFSET + data.size(), (-1 * layerExtensionLen));
		}
		memcpy((m_Data + DIAGNOSTIC_DATA_OFFSET), data.data(), data.size());
	}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! Another option is to static_cast both sizes to int and then we can get a negative number. I think it's a bit safer than extracting pointers 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works correctly since data.size() is implicitly convertible to int meaning it's guaranteed to be less than INT_MAX. In the automotive context, it's unlikely that diagnostic data will ever exceed 2,147,483,647 bytes on a 32-bit system.

That said, relying on this assumption can be risky in edge cases (e.g., malformed input or fuzzing). I used ptrdiff_t to ensure we avoid potential overflows or undefined behavior.

If we’re confident this situation will never arise in production, I’m open to simplifying it.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, using ptrdiff_t is a good option here 👍

Comment on lines 1189 to 1194
if (hasPreviousMessage())
{
shortenLayer(PREVIOUS_MSG_OFFSET, currentPayloadLen);
}
extendLayer(PREVIOUS_MSG_OFFSET, msg.size());
uint8_t* ptr = getDataPtr(PREVIOUS_MSG_OFFSET);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto: instead of shortening and then extending we can calculate the size and decide which action is needed

@raissi-oussema raissi-oussema requested a review from seladb May 25, 2025 22:06
std::string DoIpVehicleIdentificationRequestVIN::getSummary() const
{
std::ostringstream oss;
oss << "VIN: " << std::string(reinterpret_cast<const char*>(getVIN().data()), DOIP_VIN_LEN) << "\n";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raissi-oussema I'm not sure you saw this comment ☝️

Comment on lines +1534 to +1537
DoIpDiagnosticBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);

/// @brief default c'tor.
DoIpDiagnosticBase(size_t length) : DoIpLayer(length) {};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is an abstract layer, maybe we can make these constructors protected?

/// @param[in] dataLen Length of the data buffer.
/// @param[in] prevLayer Pointer to the previous protocol layer.
/// @param[in] packet Pointer to the parent packet.
DoIpDiagnosticResponseMessageBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto: this c'tor can also be protected

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains 16 packets, but there are 20 .dat files... are there packets missing in the pcap file?

Comment on lines +28 to +29
PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::IPv4));
PTF_ASSERT_TRUE(RoutingActivationRequest.isPacketOfType(pcpp::TCP));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure these checks are needed, we only need to assert that the packet is of type DoIP.

Same for the other tests below

Comment on lines +50 to +53
PTF_ASSERT_VECTORS_EQUAL(doipLayer->getReservedIso(), isoField);
PTF_ASSERT_TRUE(doipLayer->hasReservedOem());
std::array<uint8_t, 4> oemField = { 0x0, 0x0, 0x0, 0x0 };
PTF_ASSERT_BUF_COMPARE(doipLayer->getReservedOem().data(), oemField.data(), 4);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's be consistent and use either PTF_ASSERT_VECTORS_EQUAL or PTF_ASSERT_BUF_COMPARE in both of these asserts?

Comment on lines +81 to +84
pcpp::DoIpRoutingActivationRequest doipLayer(0x00, pcpp::DoIpActivationTypes::WWH_OBD);

doipLayer.setSourceAddress(0x0e80);
doipLayer.setActivationType(pcpp::DoIpActivationTypes::DEFAULT);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to set sourceAddress and activateType both in the c'tor and again here. We can set the expected values in the c'tor, and test the setters later in this test.

Same in the other tests below

Comment on lines +100 to +103
PTF_ASSERT_EQUAL(doipLayer.getPayloadType(), pcpp::DoIpPayloadTypes::ROUTING_ACTIVATION_REQUEST, enumclass);
PTF_ASSERT_EQUAL(doipLayer.getPayloadTypeAsStr(), "Routing activation request");
PTF_ASSERT_EQUAL(doipLayer.getPayloadLength(), 11);
PTF_ASSERT_EQUAL(doipLayer.toString(), "DoIP Layer, Routing activation request (0x0005)");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These getters are already tested in DoIpRoutingActivationRequestPacketParsing, no?

Comment on lines +163 to +170
try
{
doipLayer->getReservedOem();
}
catch (const std::runtime_error& e)
{
PTF_ASSERT_EQUAL(std::string(e.what()), "Reserved OEM field not present!");
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use PTF_ASSERT_RAISES here.

Same in the other tests that use try...catch

pcpp::Packet doIpPacket(100);
pcpp::EthLayer ethLayer(pcpp::MacAddress("00:13:72:25:fa:cd"), pcpp::MacAddress("00:e0:b1:49:39:02"));
pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("172.22.178.234"), pcpp::IPv4Address("10.10.8.240"));
pcpp::TcpLayer tcpLayer((uint16_t)13400, (uint16_t)13400);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The casting to uint16_t is not needed. Same in the other tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

support of doip (diagnostic over IP protocol)
5 participants