Let's code a TCP/IP stack, 1: Ethernet & ARP (2016)
saminiir.com
saminiir.com
"Operating System Design: The Xinu Approach" and also the books "Internetworking with TCP /IPvolumes1-3." Might you have a link to the title you are referencing here? I have read the Internetworking series which is excellent.
It looks the the second volume that goes with "Operating System Design".
I can't be 100% certain, as I didn't find a table of content for either of the 1st edition books, but the 2nd edition of "Operating System Design" includes a section in implementing ethernet, so perhaps the two volumes got combined into one for the second edition.
But man the three volume Comer books made things so much easier.
Just because a language has a GC it doesn't mean it is the only means to allocate memory.
Go also allows for global statics, stack and plain old C style manual allocations. It is a matter to learn how to use them.
And make use of profilers as well.
For example, on performance critical paths always use a standard for loop, never a for range one.
You can choose not to use it and allocate statically etc, but that does not mean that use of a GC does not introduce jitter.
Also don't confuse high performance with latency-sensitive. Highly performance-optimised code will still have issues with GC jitter if you or someone else is causing it.
There is a reason why the GC-enabled OSs aren't used for anything in reality.
BTW: There should be no difference between for and for-range loops given an optimiser thats working.
Hard real-time garbage collectors (including real-time reference counting approaches) can be used in such a way as to eliminate memory-management jitter.
Region allocation - a form of GC - can be used in such a way as to avoid memory-management jitter.
> GC-enabled OSs aren't used for anything in reality.
You might have a narrow definition of what you consider to be an OS. I would argue that things like the JVM, the Erlang BEAM, and even the browser are OS-like enough to qualify.
> You can choose not to use it and allocate statically etc, but that does not mean that use of a GC does not introduce jitter.
It only introduces jitter if it runs at all.
If one really wants to be drastic in performance critical code, in most GC runtimes it is possible to just turn it off.
On Go's case a runtime.SetGCPercent(-1) will take care of that.
> There is a reason why the GC-enabled OSs aren't used for anything in reality.
And me thinking I had two running on my phones, go figure.
I'm not talking about GC-enabled runtimes such as a JVM or ObjC/Swift runtime, they're application-level.
Both Mach(IOS) and Linux(Android) are non-GC-enabled OSs.
i am curious, why would one use a normal for loop, instead of a range one?
Oh ... you actually need it to be a red-black tree, or a custom hash function ? Tough.
It's interesting to see how this looks in a higher level language.
Go in Fuchsia,
https://fuchsia.googlesource.com/third_party/netstack/
Oberon in Oberon (network stack but not TCP/IP though)
https://www.inf.ethz.ch/personal/wirth/ProjectOberon/Sources...
Active Oberon in A2 - BlueBottle OS (TCP/IP stack)
https://github.com/btreut/a2/blob/48dcfc1f1a6ed2bec110ca3af3...
Mesa at Xerox PARC (Courier RPC, XNX)
http://www.bitsavers.org/pdf/xerox/mesa/3.0_1977/listing/
Sing# on Singularity
https://archive.codeplex.com/?p=singularity
Start at sourceCode\sourceCode\base\Libraries\System.Net\Sockets
https://blog.docker.com/2016/05/docker-unikernels-open-sourc...
That said, since the next field is a uint16_t, you may as well stay in Rome and call them uint8_t. short really is variable on some live architectures.
(Ok, or some DSPs only address words larger than 8 bits, but there's no reason for your compiler not to pick up the slack.)
Also, TIL that __attribute__((packed)) assumes the struct can be malevolently aligned and for some architectures generates very large and slow code to handle that. If you must pack, also add the ",aligned(2)" or whatever you can get away with to mitigate this.
Of course, "int" is less typing than "int_fast16_t". But, int_fast16_t possibly makes it more obvious why you've chosen the type you did (i.e. you only need 16-bits, but aren't relying on any overflow so a bigger type can freely be substituted if that gives better performance.)
TI's C2000 microcontrollers - a byte is 16 bits. Other TI DSPs also have 16 bit bytes.
But you're right - if uint8_t exists, it must be the same as unsigned char.
1. Ethernet & ARP (this post)
2. IPv4 & ICMPv4: http://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4...
3. TCP Basics & Handshake: http://www.saminiir.com/lets-code-tcp-ip-stack-3-tcp-handsha...
4. TCP Data Flow & Socket API: http://www.saminiir.com/lets-code-tcp-ip-stack-4-tcp-data-fl...
5. TCP Retransmission: http://www.saminiir.com/lets-code-tcp-ip-stack-5-tcp-retrans...
But then purchased the Comer books and made it so much easier. Highly recommend buying the Comer books if really interested in writing a TCP/IP stack.
Also if you really want to learning something you write an implementation. To this day makes it so much easier to deal with IP problems, configuration, buying products, etc.
https://www.amazon.com/Internetworking-TCP-IP-One-6th/dp/013...
https://www.amazon.com/Internetworking-TCP-Vol-Implementatio...
https://www.amazon.com/Internetworking-TCP-Vol-III-Client-Se...