Step 1: Unit Fuzzing
When initially setting up fuzz testing in an automotive environment, the easiest way to do this is using pre-existing unit tests as a sort of template. In most projects, these unit tests already exist, since many automotive developers use unit tests to test the functionality of their software.
During the first hours after setting up the fuzzer, you will usually find the majority of security issues, just by testing with these self-contained units. Ideal candidates for these low-hanging fruits are libraries, API functions, and different kinds of parsers.
In this stage, you can also set up a continuous integration very easily, by simply repeating this already defined procedure at every upcoming merge request (similar to DAST or IAST).
Step 2: Interface Fuzzing
On the network level, fuzzing requires more efforts as different network interface protocols have to be taken into account (TCP/IP, Ethernet, CANBus, etc.). To simulate this, the fuzzing engines have to be able to understand certain protocols, such as IPSec, UDS, and Protobuf. That's why, interface fuzzing can take several days to weeks, but as the complexity increases, you will also find more bugs.
If you would start with interface fuzzing before unit test fuzzing you would most likely also detect all the findings that you could detect with unit test fuzzing. However, it might take you more time to debug and analyze the bugs when they are found via interface fuzzing. Therefore, it's usually better to start with unit fuzzing first.
Step 3: System(-like) Fuzzing
Especially in automotive and complex embedded projects, system fuzzing is the long-term goal. At a certain point all tests should be connected to the hardware to find out what actually happens on the operating system with the commercial compiler. Luckily, it's possible to simulate the input of those systems. The simulations built during unit testing can serve as a fundament for testing the actual hardware.