Comments (49)
Can we implement it this way: I pass an ip address to the ne2k driver and that handles ARP then?
from elks.
The Ethernet driver is not supposed to have any knowledge of the higher level protocols encapsulated in the Ethernet frames, as the serial driver does not know what protocol is used on the serial line (VT52, SLIP, etc). Its role is only to send and receive raw packets.
On other systems, that role is exposed to user space with a socket with AF_PACKET and SOCK_RAW attributes.
Moreover, ARP is a part of the IPv4 protocol suite, and is tightly coupled to IP. IP should direct ARP on the right subnet (so the right device), and IP knows the local addresses that could be responded to ARP.
For that reason, best place to implement ARP is ktcp
, not the driver.
from elks.
I opened the /dev/eth driver with ktcp but I did not receive any packets. The select works with the new version of select.c but reports no data available. I would need to see the ARP requests to be able to respond.
When ip.c receives a ping it will call icmp.c and that sends a response packet for the ping. One could add that a new program arp.c will be called when an ARP request is received. This builds and sends the ARP reply if the request is for the "right" ip address.
from elks.
To get incoming ARP request, follow the steps in #18 to cause QEMU to send that ARP request to the guest.
ktcp
should not only respond to incoming ARP request, but also send that request as a client to find which MAC should be used for a given remote IP address, and should maintain a local IP <-> MAC table to avoid repeating that request.
As ARP is at the same level as IP, ktcp
should first get the packet from the driver, look at the packet header, and then forward either to the IP layer or to the ARP layer. ICMP is wrapped into IP, one level higher than ARP.
from elks.
I implemented ARP so far that I can properly send an ARP Reply and get TCP/IP packets following that. However, the "read" instruction always returns a length of 64. This is too short for TCP/IP, I can see no data, just part of the header.
from elks.
Please push your commits on the ne2k
branch to make your latest changes visible, so that I can have a look at them, and try to figure out what is going wrong here.
Please also rebase your ne2k
branch on upstream master, and avoid mixing bug fixes, improvements or enhancements in the same branch in general. Otherwise it is difficult for other contributors to "cherry pick", or to get back your changes in their context.
from elks.
I can push the code but I have to run through the programs first to see what junk has to be removed before posting.
This is what I observed. I do the following read:
#define BUFFER_SIZE 2048
len = read(devfd, &sbuf, BUFFER_SIZE);
However, at ne2k_main.c
in static size_t eth_read()
the requested length (len) which is passed to thei function is always 64 bytes. But the received packet has a size of 1792 bytes. So, as the comment says, (1792-64) are lost since I cannot repeat the read call.
Any ideas? Seems ELKS limits the read to 64bytes.
Georg
from elks.
If you don't push your commits in your repository, I cannot see the code and so cannot help.
from elks.
Finally managed to push the code. However, the rebase command did not allow me to push since the remote and the local branches became different. So I got pretty entangled.
The commit is "Add working ARP reply."
I now made a new branch ne2k-2 which is rebased on the latest elks/master
from elks.
Wireshark shows that everything works fine: after ARP request + reply, QEMU sends a TCP SYN packet as the first step of connexion, then repeats continuously that packet as it gets no response from ktcp
.
But as this TCP packet is less than 64 bytes (actually 58), as for ARP packet, it is padded up to the minimum Ethernet frame size, that is 60 + 4 (CRC) = 64. So the Ethernet driver returns 64 to you for the ARP request, the TCP SYN, and the N x TCP retransmit.
You should not rely on the packet total size, but on the values in the IP / TCP headers. Play again !
from elks.
Marc-Francois,
I got ARP working and the host is sending now TCP/IP packets of 1792 bytes in size. As I outlined above, I always do a read for 2048 bytes in deveth.c
and check how many bytes read returns. But the request for 2048 bytes is changed to 64 bytes when it arrives at ne2k_main.c
in eth_read()
. This is what I hoped you would look into.
Why is my read request for 2048 bytes converted to 64 bytes by ELKS?
Georg
from elks.
It is not possible to have packet of 1792 bytes. The standard MTU for the Ethernet payload is 1500, and on NE2K, the maximum is 256 * 6 = 1536 - 4 CRC - 4 ring header = 1528 by packet.
It is also normal that the driver returns 64 bytes if the packet is 64 bytes, even if you requested 2048. That's the nature of a network driver, even if we implemented it as a character driver.
I already explained you why small packets are padded up to 64 bytes. Please use the QEMU option -net dump and look at the packets sent by the host. Nothing is going wrong here.
from elks.
OK, my test code did fool me with the 1792 bytes. And yes, I receive packets of 64 bytes.
When I get an ARP request I return an ARP reply and the host is following that with TCP/IP packets. Why is the host sending these empty packets and what does it expect from the ELKS system?
from elks.
These are empty packets but with TCP port = 23 and flags = SYN. It means that the host is trying to establish a TCP stream connection to port 23, and the guest should reply with TCP flags = ACK.
This should be already implemented in ktcp
, but I guess, as nobody in user space opened a socket AF_INET + SOCK_STREAM listening to port 23, ktcp
ignores the connection request.
from elks.
E.g. ktcp
does not have a link layer since it did not need that for slip. So I have to add that. Plus work my way through the code and see where it is stuck.
from elks.
I enabled the link layer and my echo server is listening on port 23. So ELKS answers to the TCP/IP SYN packets now and this results in the following tcp/ip communication:
qemu-vlan0.pcap.zip
Can please you look at the file with Wireshark and tell me why the host is sending a reset after ELKS has sent an ACK answer to the SYN packet?
from elks.
It is because the acknowledgement number in packet 4 is incorrect. The client (= the host initiating the connection) sent a SYN with sequence number = 0 in packet 3. It expected a reply from the server (= the guest that responds to the connection request) with acknowledgement number = 0 + 1 = 1. But the server sent 0.
So for the client, the server acknowledged a sequence number of 0 - 1 = 0xFFFFFFFF, meaning that the TCP connection was already established before (and for a long time with a so huge sequence number !), so it aborts immediately the current connection with RST.
Note : the sequence and acknowledgement numbers here are relative ones, as displayed by Wireshark. Actual numbers are absolute.
from elks.
When I look at the hex code, the sequence number field should be eight zeros I guess. Since it is 32 bit. From the ELKS code it seems that ELKS uses a time based number here. The field contains:
20 00 00 8F
Wonder why Wireshark reports a zero here. Same with the ACK number which is also not fully zeros.
I forced the code to put 00 00 00 01
into the field but Wireshark remained to report the field to be zero.
I guess it is late now, you were talking about the acknowledgement number, not the sequence number. But stil the hex code is not zero in this field.
from elks.
Now I forced 00 00 00 01
into the acknowledgement number field. Wireshark tells me that this is an acknowledgement number of 4293943296. I am confused.
from elks.
Ok, I now just added 1 to the acknowledgement number (which was not zero) and that satisfied the host. I will see why that has not been done be ELKS yet and proceed.
from elks.
Please read more carefully my posts:
Note : the sequence and acknowledgement numbers here are relative ones, as displayed by Wireshark. Actual numbers are absolute.
Wireshark displays relative numbers to ease the reading, starting from 0 for both numbers.
I can see that these numbers are already managed in tcp.c, so I don't understand why you need to force the numbering ?
from elks.
I usually read your posts carefully, but as I said it was late yesterday for me.
Yes, these numbers are managed by tcp.c but if I do not modify them the result will wrong as you write:
It is because the acknowledgement number in packet 4 is incorrect
Before analysing the code in detail to make a proper fix I wanted to see what difference the correct number would make, therefore I forced the numbering as a temporary test.
from elks.
When I tested SLIP I could not access the http server from the host. Therefore I currently think there may be a bug when tcp.c is in the listening state. As you found, the acknowledgement number produced by tcp.c is wrong.
from elks.
Mmm... not good to see that the current network stack could be buggy... let me ask the question to the mailing list, because I was expecting to get a working network stack just at the cost of adding the Ethernet capability, not at the cost of a long tuning of the whole.
from elks.
Since I spent quite some time on the ktcp stack already I am not interested to replace it with a different one.
This stack has not been used for 15 years and you have to expect that bugs show up. ELKS itself contains quite a number of bugs which have not been found yet. Getting this stack to work properly with ethernet is not quickly done though.
But I expect to get this sequence number problem fixed during this week and then add ARP request and stack next weekend. Then you can also establish a connection from the ELKS side too.
from elks.
I could solve the last problem, ntohl() did not work well with pointers and converted the one in the sequence number to zero. Now I get the following trace when I send a string of ones to the echo server on ELKS. Can you please tell me why the host is not satisfied with the response from ELKS?
qemu-vlan0.pcap.zip
Here is a second trace where I sent just a single "a":
qemu-vlan0-2.pcap.zip
OK, I advanced, forget about the traces above. Here is my latest trace. Please just comment on this one:
from elks.
I like the "Marc-Francois" as telnet data :-)
In the latest *-4 sequence, everything works fine for ARP and TCP connection, but the guest faults on packet 7 with a wrong sequence number.
At packet 6, the host sends 15 bytes as telnet data, so it expects the guest to ACK with a relative sequence number of 1 + 15 = 16.
In packet 7, the guest ACK correctly with number 16.
But in the same packet 7, the guest incremented his own sequence number, despite it sent no data before, meaning for the host (and Wireshark), that a packet with data has been lost just before (and so the message "previous segment not captured").
from elks.
Puh, I got it working now. The problem was that bcc does not support shifting 32bit numbers by 24 bits. This made the macro in netorder.h fail. Therefore the htonl() and ntohl() macros failed and corrupted the sequence numbers.
Here is an example trace using my echo server and client: working-now.pcap.zip
Sorry for the name, but I am quite happy that it seems to work now :)
I have to remove the test codes first before I can commit my current version. I guess in the end I only needed to change two lines in the code. Sigh.
Georg
from elks.
Looks far better, nice job !
However, the sequence is incomplete: the graceful shutdown was initiated by the host (FIN + ACK), and acknowledged by the guest (ACK), but I guess you stopped the test before closing the socket on the guest, so one cannot see the end of the TCP connection shutdown (normally 4 TCP packets).
Another visible problem in Wireshark is a bad Ethernet frame in ARP response that I have to investigate, because I think it is linked to QEMU NE2K emulation, not the network layers on the guest.
from elks.
I have the echo server running on ELKS and the echo client on the host. To terminate the client I enter CTRL-C, so this may be the reason that there is no normal shutdown sequence.
Since I programmed the ARP response I would at first look at my code. If you tell me what is wrong, I will try to modify the code.
I want to do a commit with my corrected netorder.h file and since you usually comment my commits I ask you in advance. I would like to rename it to inet.h and put it into elks/include/linuxmt. Then I would change all programs that use a local netorder.h to use the linuxmt/inet.h file. Including my not yet commit new version of echo server and client with additional af_inet support. Any comments to this?
from elks.
I usually comment the pull requests from anybody, because it a good moment in Github workflow to make code reviews and to discuss the changes at the whole team level. But on ELKS, Jody is straightforward: either he trusts the pusher / likes the changes, and he merges before end of any discussion, or he does not trust / does not like, and he rejects.
Issues are also good places to discuss before any pull request, like we are doing these days, but he spends no time to manage them that way.
So my advice would be to limit the perimeter of your changes to ktcp
, and to postpone modifications on other parts until we make a few iterations to stabilize the network layers and demonstrate to him that we could propagate the mature changes safely.
from elks.
I have updated the netorder.h. file and find there are three or four basically identical netorder.h files in different directories in the ELKS code. Also I want to test the httpd application with the ktcp version I am working on and that also uses netorder.h.
So this commit is basically part of what I am currently working on.
It does not seem to take a long time to make this commit and so I will make that and see if it is accepted. If not I would not know how to proceed with ktcp though since I do not want to continue with a netorder.h file I know is faulty.
from elks.
What do you mean by "make this commit" : pushing the commit from your local Git to Github to make it visible in the version tree, or requesting a pull to merge the commit into the main repository (so Jody's one) ?
from elks.
I think having a faulty and duplicated netorder.h file is no good in jody's master. So I will make a new branch based on the current master and make the proposed changes to that and ask for these to be pulled.
Then after that has been merged I can sync my ne2k-2 branch again and commit my current ktcp changes to that for you to download and test.
This is my plan.
from elks.
I am stuck again. Now I have put the echoclient on the ELKS side and the echoserver on the host side. The server listens on 127.0.0.1:2323. The client sends to 10.0.2.2:2323.
I can send data from the client and receive an ACK for that but the echoserver reports no data and sends nothing back.
In Qemu I have -net user,hostfwd=tcp:127.0.0.1:2323-10.0.2.15:23
Do not know if this correct for this setup. Please find the current communication here:
Georg
from elks.
Could you make your current code visible through a commit push to your own repository (not a pull request), please, so that I can have a look ?
from elks.
I removed the host forwarding rule in the qemu.sh script and now I can connect from the echoclient on ELKS to the echoserver on the host!
Let me check my code for test printf's and stuff and then I will commit it to my own repository.
Georg
from elks.
I have posted a new version of ktcp modified for ne2k. This passes the following tests running Qemu:
- run echoserver on ELKS and connect to that with an echoclient on the host. Send data back and forth.
- run echoserver on the host and connect to that with an echoclient on ELKS. Send data back and forth.
- download web page from google using urlget
- slip still works, i.e. ping is working, did no further tests.
You have to run qemu with host forwarding if you connect from the host to ELKS. However, hostforwarding should not be specified if you want to connect from ELKS to the host.
For this I implemented ARP reply and request, a one entry ARP cache, routing to the gateway, reading the local mac with ioctl, adding the link layer, fix netorder.h and rename to arpa/inet.h.
Also got httpd to be installed in the /bin directory and have that loaded during boot. Made separate echoclient/echoserver code for internet and unix domain sockets in the test directory. Modified qemu.sh to support slip and http.
I will continue testing and see if I can make a readme file documenting how to use this.
Todo e.g.:
- test httpd web server with ne2k and slip
- test telnet from ELKS
- the download of web page pauses in between the download
- add name resolution
- add dhcp support
Georg
from elks.
Looks very nice ! Let me play a bit with your branch to see it working...
from elks.
The httpd
daemon responds well, after adding /usr/lib/httpd
in the rootfs
template, so that the default index.html
is correctly copied to the target.
Well, I think you reached a first milestone there, congratulations !
Please request the pull into Jody's master, to share this valuable contribution.
from elks.
Thank you Marc-F.! I will write a readme file today how to test ktcp/ne2k and then make a pull request.
from elks.
Marc-F.,
I do not want to make a single commit from this, but the "static" has to be removed in ip.h here:
char local_mac [6];
Otherwise it seems to have zero value when used in ip.c
Also the code is still using slip_mtu. This should be increased I think.
Georg
from elks.
Done for first point.
from elks.
Marc-F.,
maybe we should tell each other at what part of the networking code each of us is working to avoid duplication and conflicts.
Currently I try to implement querying a name server with tcp/ip. What are you working on?
Georg
from elks.
Yes, sure. For the Ethernet sub-project, I am testing and tuning ktcp
and ne2k
on a real network, so my next related commits would probably consist of improvements on the current code, no new features. I am focusing now on having an ARP cache with multiple entries (5 would be a good number).
from elks.
I have code for an ARP cache here. However, you need to init, search, delete, add functions to handle that. Also save the time to deprecate the entries after about five minutes. This is more code than I currently have in arp.c and therefore I did not include and test that yet to be able to come up with a working solution for networking quickly. And most of the time you will use the mac of the gateway anyway. So you end up with an arp cache of various internet addresses all having the mac of the gateway stored as their mac address.
from elks.
I have a question. I find the in_aton() function is used in many programs, e.g. ktcp.c or ttn.c. How can you avoid the duplication?
If I link the function to the kernel it is not found when linking the user programs even if I put it into a header file. Since the kernel code is not linked with ktcp.c it does not find the function.
There is also no library I could add the function in_aton() to which is linked by all network user space programs. Putting the function code into the header file is no good style. What would you suggest?
Georg
from elks.
The right place is the dev86 libc
library.
from elks.
Our first ARP implementation is roughly enough for a first milestone (except issue jbruchon#67), so I am closing this improvement task.
from elks.
Related Issues (20)
- /dev/eth HOT 1
- NE2K basic ethernet driver HOT 3
- Serial / Ethernet switch HOT 9
- Basic IP routing HOT 2
- NE2K test program HOT 2
- DHCP tiny client HOT 1
- ETH test program HOT 3
- QEMU configuration for NE2K HOT 1
- [ne2k] Georg's feedback HOT 1
- Make network card visible on the host HOT 2
- ktcp will not start HOT 5
- Qemu script HOT 3
- Menuconfig HOT 3
- kill command working? HOT 2
- Move ne2k.h HOT 4
- [eth] Add ioctl() to get / set MAC address
- Telnet test HOT 1
- [romfs] Replace low-level routines by generic code
- Recover ongoing activities from upstream HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from elks.