Skip to content
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

ktcp status #610

Closed
Mellvik opened this issue May 4, 2020 · 115 comments
Closed

ktcp status #610

Mellvik opened this issue May 4, 2020 · 115 comments
Labels
bug Defect in the product

Comments

@Mellvik
Copy link
Contributor

Mellvik commented May 4, 2020

I believe it makes sense to open a new issue on ktcp: It has not been tested in a while, and much has changed in and around the kernel since.

I fired up KTCP on a physical machine this morning, and the overall status is: It does not work. Then the good news:

  • With DEBUG enabled, all the initializing debug messages from ktcp prints fine.
  • There is (initially) no response when poking ELKS from the outside. Not telnet, not ping, not lynx.
  • killing telnetd gives one successful echo reply (ping). Killing http -> 3 successful echo replies
  • starting https again -> another 3 replies.
  • New kill, 7 replies and so forth.
  • So, when kicked one way or the other, KTCP works somewhat, indicating packet flow, and possibly something broken in the interrupt chain.
  • Possibly interesting observations:
    • After a series of ping responses, KTCP eats 40 ping packets, then the client (from which the ping is coming) is reporting Host Unreachable again. This repeats itself consistently, regardless of how many pings were successfully echoed.
    • Further, when the next batch of successful pings come, the sequence number continues from the previous successful batch (3-4) then jumps about 30, and another 3-4.
  • Finally, when telnet out from ELKS, I get a Connecting to 10.0.2.1 message and maybe 20 successful echoes. Once I even had something coming back from the other end. Garbled, but in terms of byte count, something like a login prompt.
  • The telnet client on ELKS seem to have issues when run from a serial line, triggers a lot of Bad file number` messages on the console.

This is from ELKS:

# ps
  PID   GRP  TTY USER STAT CSEG DSEG  HEAP   FREE   SIZE COMMAND
    1     0      root    S 3e46 3ff0  3072  13252  26800 /bin/init 
    8     8    1 root    S 4e93 5030     0  16275  27344 /bin/getty /dev/tty1 
    9     9   S0 root    S 5540 611d  2193  13914  75648 -/bin/sh 
   10     9   S0 root    S 67b8 6bca  6144  10045  44832 ktcp 10.0.2.15 /dev/eth 
   23    23      root    S 49ca 72aa     0  16253  26864 httpd 
   21    21      root    S 4b6c 44d1     0  16251  25408 telnetd 
   24     9   S0 root    R 4ca7 7ec0  1025  14054  26672 ps 
# telnet 10.0.2.1
Connecting to 10.0.2.1 port 23

This is from the pinging host:

From 10.0.2.1 icmp_seq=67 Destination Host Unreachable
From 10.0.2.1 icmp_seq=68 Destination Host Unreachable
From 10.0.2.1 icmp_seq=69 Destination Host Unreachable
From 10.0.2.1 icmp_seq=70 Destination Host Unreachable
64 bytes from 10.0.2.15: icmp_seq=41 ttl=64 time=34171 ms
64 bytes from 10.0.2.15: icmp_seq=42 ttl=64 time=33151 ms
64 bytes from 10.0.2.15: icmp_seq=43 ttl=64 time=32128 ms
64 bytes from 10.0.2.15: icmp_seq=71 ttl=64 time=3096 ms
64 bytes from 10.0.2.15: icmp_seq=72 ttl=64 time=2069 ms
64 bytes from 10.0.2.15: icmp_seq=73 ttl=64 time=1042 ms
64 bytes from 10.0.2.15: icmp_seq=74 ttl=64 time=54.2 ms
From 10.0.2.1 icmp_seq=109 Destination Host Unreachable
From 10.0.2.1 icmp_seq=110 Destination Host Unreachable
From 10.0.2.1 icmp_seq=111 Destination Host Unreachable
From 10.0.2.1 icmp_seq=112 Destination Host Unreachable
From 10.0.2.1 icmp_seq=113 Destination Host Unreachable
From 10.0.2.1 icmp_seq=114 Destination Host Unreachable
From 10.0.2.1 icmp_seq=115 Destination Host Unreachable
From 10.0.2.1 icmp_seq=116 Destination Host Unreachable
From 10.0.2.1 icmp_seq=117 Destination Host Unreachable
From 10.0.2.1 icmp_seq=118 Destination Host Unreachable
From 10.0.2.1 icmp_seq=119 Destination Host Unreachable
From 10.0.2.1 icmp_seq=120 Destination Host Unreachable
From 10.0.2.1 icmp_seq=121 Destination Host Unreachable
From 10.0.2.1 icmp_seq=122 Destination Host Unreachable
From 10.0.2.1 icmp_seq=123 Destination Host Unreachable
From 10.0.2.1 icmp_seq=124 Destination Host Unreachable
From 10.0.2.1 icmp_seq=125 Destination Host Unreachable
From 10.0.2.1 icmp_seq=126 Destination Host Unreachable
64 bytes from 10.0.2.15: icmp_seq=75 ttl=64 time=54498 ms
64 bytes from 10.0.2.15: icmp_seq=76 ttl=64 time=53465 ms
64 bytes from 10.0.2.15: icmp_seq=77 ttl=64 time=52430 ms
64 bytes from 10.0.2.15: icmp_seq=78 ttl=64 time=51394 ms
64 bytes from 10.0.2.15: icmp_seq=79 ttl=64 time=50359 ms
64 bytes from 10.0.2.15: icmp_seq=80 ttl=64 time=49323 ms
64 bytes from 10.0.2.15: icmp_seq=106 ttl=64 time=22287 ms
64 bytes from 10.0.2.15: icmp_seq=107 ttl=64 time=21253 ms
64 bytes from 10.0.2.15: icmp_seq=108 ttl=64 time=20218 ms
64 bytes from 10.0.2.15: icmp_seq=127 ttl=64 time=487 ms
From 10.0.2.1 icmp_seq=162 Destination Host Unreachable
From 10.0.2.1 icmp_seq=163 Destination Host Unreachable
From 10.0.2.1 icmp_seq=164 Destination Host Unreachable
From 10.0.2.1 icmp_seq=165 Destination Host Unreachable
@Mellvik Mellvik added the bug Defect in the product label May 4, 2020
@ghaerr
Copy link
Owner

ghaerr commented May 4, 2020

Thanks for testing!

However, bad news. It used to work, I'm almost sure Marc was using it years ago, but that could have been slip only.

A couple questions: I assume you're using it on a network card only? What is the startup command line exactly? Which source version are you running, the version before or after Christoph's mods?

@pawosm-arm has tested using slip, and said it works at 300 baud, except for incoming connections to telnetd.

In summary - we need to get to a working version, be it 300 baud slip or ethernet, before or after the waiting PR. If needed, we could go way back to an earlier kernel and/or ktcp version, as it will be much easier to debug from something working than apparently where it is now. And I will have to use an emulator, of which I don't have slip or NE2000 running yet. Ugh!

@pawosm-arm
Copy link
Contributor

Indeed, I managed to establish telnet connection from ELKS to Linux over SLIP (with ktcp on the ELKS side and slattach on the Linux side), having my own custom telnet service started on the Linux side (see [1]). This telnet server imitation enables interaction similar to a serial line connection using miniterm on the ELKS side and minicom on the Linux side. Except it is much slower at the same baud rate selected. Terribly slow I should say. Yet definitely, the packages are going both sides. The slowness of the communication is extremely suspicious though.

[1]. https://sourceforge.net/projects/stdiotelnetd

@Mellvik
Copy link
Contributor Author

Mellvik commented May 4, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented May 4, 2020

Sign of life:
Skjermbilde 2020-05-04 kl  18 19 01

@ghaerr
Copy link
Owner

ghaerr commented May 4, 2020

You're breathing life into it Helge!!

Things sound a bit promising, since its working for at least a little while. I'm a bit curious as to your switching your DOS packet driver and now ELKS works better, untouched. So there could be issues on the DOS end also?

I'd like to see screenshots of the select printks, etc.

With regards to the older 24-hour commit, that's probably ok. The -s option that was added only affects slip operation, the other code wasn't changed, just cleanup.

However - telnetd.c WAS changed, a one-liner at line 28, where /bin/login is execed, rather than /bin/sh. You can change that back and recompile telnetd to see if that changes anything and you get a shell prompt. It wasn't working for Paul.

If you're running with full ktcp debugging, perhaps a screenshot or two when its hung... however I can't duplicate anything over here yet on QEMU.

@Mellvik
Copy link
Contributor Author

Mellvik commented May 4, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented May 4, 2020

Boot messages & hang situation - after some activity. Command triggering the hang:

5283C915-18D4-40C6-AAAE-AA8DE5219F91
8C939246-15BD-43B5-91F5-46D4FF4B490D

@ghaerr
Copy link
Owner

ghaerr commented May 4, 2020

Ok - so you're running ktcp directly from the /etc/rc.d/rc.sys startup script. That's fine.
However, I added the untested "-b" (run in background) option, but looks like the error messages are working, so we're probably ok there. It used to be run from the shell with "&", but that closes output file descriptors so I added the option to make things cleaner.

The 'select: Bad file number' is not a kernel printk. It is coming from the select() call in arp.c. After @cjsthompson's first commit to his outstanding cleanup PR, we realized that the "static int tcpdevfd" was in error in multiple source files, and was cleaned up (that is, all occurrences combined). See discussion in #507 for details. Since there is only one file number in that select(), and that is tcpdevfd, which is static and = 0, that's the problem for sure.

As a result, I suggest adding Christoph's PR #607, and recompiling all of ktcp, I think it will fix that error.

Interestingy, its possible that my -b option broke the incorrectly coded arp select() option - that is, when run async from the shell with "&", tcpdevfd would be the first file opened, and thus have the value of 0 - which would have matched an uninitialized static variable!!

We're making progress!

Thank you!

@ghaerr
Copy link
Owner

ghaerr commented May 5, 2020

I got QEMU to run with the network card finally, and turned on CONFIG_ETH in .config, a couple things to report:

The "static int tcpdevfd" is definitely the problem with the "select Bad file number", all static int declarations of it need "static" removed, or use PR #607.

Also, it seems that the -b option I added some time back may be affecting operation. For the time being, I changed some lines in rootfs_template/etc/rc.d/rc.sys to remove it and run it async from the shell:

    echo 'Starting networking: ktcp'
    # run ktcp as background daemon if successful starting networking
    #if ktcp -b -s $ttybaud $localip $interface ; then
    ktcp  $localip $interface &
    if true ; then
        for daemon in telnetd httpd
        do

This seems to allow netstat to interoperate with ktcp. I still can't get telnet to work. I am running everything within ELKS QEMU at this point. I am not sure how to test httpd within ELKS.

@Mellvik
Copy link
Contributor Author

Mellvik commented May 5, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented May 5, 2020

Having https and telnet active prevents elvis from running (out of memory).

Are you saying that running httpd and telnetd STOP elvis from out of memory? It should be the other way around.

vi seems to be the application that uses the most memory at this time. Back when configurable L2 buffers was added, the default was increased from 64K to 128k of buffers. In further heavy ELKS use with all gettys running and multiple logins, I have seen ELKS run out of memory when trying to run vi. Probably not worth the tradeoff of 128k buffers when vi won't run, and now networking is active. I'm thinking that decreasing the default L2 buffers back to somewhere between 64-96k would be a good idea so vi always runs.

This does not seem to make any difference, i.e the -b options seems fine.

I'm seeing definite differences in the debug output of ktcp and netstat, so it might be best to always run ktcp from the command line for our initial testing - FYI.

@Mellvik
Copy link
Contributor Author

Mellvik commented May 5, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented May 5, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented May 5, 2020

added the changes from #607, removing the static declarations etc. Now the system hangs on any and all network accesses.

Ok, a bit of a mess, when combined with the XT kbd and serial driver problems (please comment on those in #612).

Since #607 is not committed, we'll keep that on hold. Please do a 'git checkout -f master' and recompile from scratch, and we'll start working on each of the three problems separately.

I will submit a small PR that only changes the 'static int tcpdevfd' fix that is required for the arp.c "select bad file descriptor" problem. That will allow you to continue ktcp testing.

See #612 for serial and kbd fixes.

@ghaerr
Copy link
Owner

ghaerr commented May 6, 2020

Helge, here's a minimal patch to fix the "select" and "static int tcpdevfd" errors without yet using the full PR #607. This works on my system using the latest git HEAD.

This patch also starts ktcp asynchronously from sys.rc rather than using the -b option, to keep previous changes to a minimum for testing.

I've reviewed #607 and can't see why it causes system hangs, so I'd like to see whether this does before I test 607 on my own machine.
netpatch.txt

@Mellvik
Copy link
Contributor Author

Mellvik commented May 8, 2020

Here's a serial style screen dump from a minimal tcp test. which also tests /bootopts for the first time. This is indeed a great improvement for debugging. printk needs some CRs to improve readability, otherwise great.
There is a ping running from the other end of the ethernet link, which is where the ICMPs are coming from.

# reboot
ttyS0 at 0x3f8, irq 4 is a 16450
                                ttyS1 at 0x2f8, irq 3 is a 16550A
                                                                 ttyS2 at 0x3e8, irq 5 is a 16550A
                  lp0 at 0x3bc, using polling driver
                                                    [eth] NE2K driver OK
                                                                        bioshd: gethdinfo CHS 979,5,17
                      bioshd: 1 floppy drive and 1 hard drive
                                                             Partitions: bda:(0,83215)  bda1:(1,6374)  bda2:(6375,1275)  bda3:(7650,41565)  bda4:(49215,34000) 
                                                                               device_setup: BIOS drive 0x0, root device 0x380
                                              PC/AT class machine, Intel 80286 CPU, 640K base RAM.
                  ELKS kernel 0.3.0 (56256 text + 6822 data + 53038 bss + 5676 heap)
    Kernel text at c0:0000, data at e7c:0000, 518K for user processes.
                                                                      fd: found valid ELKS disk parameters on /dev/fd0 boot sector
                                                  fd: /dev/fd0 probably has 18 sectors, 2 heads, and 80 cylinders
                                 VFS: Mounted root (minix filesystem).
                                                                      Running /etc/rc.d/rc.sys script
Starting networking: ktcp
KTCP: 1. local_ip

KTCP: 2. init tcpdev
KTCP: 3. init interface
Init /dev/eth
KTCP: 4. ip_init()
KTCP: 5. icmp_init()
 telnetd KTCP: 6. tcp_init()
KTCP: 7. netconf_init()
KTCP: 8. ktcp_run()
tcpdev_process : read 12 bytes
IP : ICMP packet
tcpdev_process : read 6 bytes
 httpd IP : ICMP packet
tcpdev_process : read 8 bytes
IP : ICMP packet
tcpdev_process : read 12 bytes
IP : ICMP packet
tcpdev_process : read 6 bytes
tcpdev_process : read 8 bytes
ELKS built from commit ae1aa713
Fri May 08 12:39:19 2020
IP : ICMP packet
IP : ICMP packet

IP : ICMP packet

EIP : ICMP packet
LKS 0.3.0

login: IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet
IP : ICMP packet

panic: Unable to get timer
                          apparent call stack:
                                              Line: Addr    Parameters
                                                                      ~~~~: ~~~~    ~~~~~~~~~~   
                 0: 87B0 => E9D6 F17A 7200 6F72 0A72 6400 7665   
                                                                 1: F136 => 1001 78E9 55FE E589 06FF 0300 468A   
                                 2: B8FE => 0000 0000 0000 0000 0000 0000 0000 
                                                                                 3: 0000 => 692F 696E 0074 642F 7665 632F 6E6F   
                                                 4: 6E69 => 0000 0000 0000 0000 0000 0000 0000   
                 5: 0000 => 692F 696E 0074 642F 7665 632F 6E6F   
                                                                 6: 6E69 => 0000 0000 0000 0000 0000 0000 0000   
                                 7: 0000 => 692F 696E 0074 642F 7665 632F 6E6F 
                                                                                 8: 6E69 => 0000 0000 0000 0000 0000 0000 0000
                                              SYSTEM HALTED - Press CTRL-ALT-DEL to reboot:

BTW - the halt at this point is hard, not soft - need power recycling.

--M

@Mellvik
Copy link
Contributor Author

Mellvik commented May 8, 2020

Continuation from the previous comment:
rebooting w/o the ongoing PING, and instead telnetting into elks, leaves us with the following. It's not consistent in that it doesn't stop at the same place every time, and sometimes just loops in retransmits.
The elks telnetd responds with login: but continues after a few seconds (doesn't wait for newline) and execs /bin/login with whatever was typed, and emits 'Password:', where it actually waits. The tty (pty) echoes control characters like '^M' etc.

Anyway, this is not bad at all.

ELKS built from commit ae1aa713
Fri May 08 13:08:14 2020


ELKS 0.3.0

login: IP : TCP packet
Retrans buffers : 1 retrans : 4294942271 4294942271 remove
IP : TCP packet
IP : TCP packet
Retrans buffers : 1 retrans : 4294942272 4294942272 remove
IP : TCP packet
tcpdev_process : read 108 bytes
Retrans buffers : 2 retrans : 4294942279 4294942272not
retrans : 4294942272 4294942272 remove
IP : TCP packet
tcpdev_process : read 8 bytes
Retrans buffers : 2 retrans : 4294942279 4294942272not
retrans : 4294942279 4294942272not
IP : TCP packet
Retrans buffers : 3 retrans : 4294942279 4294942272not
retrans : 4294942279 4294942272not
retrans : 4294942279 4294942272not
IP : TCP packet
tcpdev_process : read 108 bytes
Retrans buffers : 5 retrans : 4294942287 4294942272not
retrans : 4294942279 4294942272not
retrans : 4294942279 4294942272not
retrans : 4294942279 4294942272not
retrans : 4294942279 4294942272not
IP : TCP packet
tcpdev_process : read 108 bytes
Retrans buffers : 6 retrans : 4294942288 4294942279not
retrans : 4294942287 4294942279not
retrans : 4294942279 4294942279 remove
retrans : 4294942279 4294942279 remove
retrans : 4294942279 4294942279 remove
retrans : 4294942279 4294942279 remove
IP : TCP packet
tcpdev_process : read 108 bytes
Retrans buffers : 3 retrans : 4294942296 4294942287not
retrans : 4294942288 4294942287not
retrans : 4294942287 4294942287 remove
IP : TCP packet
Retrans buffers : 3 retrans : 4294942296 4294942287not
retrans : 4294942296 4294942287not
retrans : 4294942288 4294942287not
IP : TCP packet
tcpdev_process : read 8 bytes
Retrans buffers : 3 retrans : 4294942296 4294942288not
retrans : 4294942296 4294942288not
retrans : 4294942288 4294942288 remove
IP : TCP packet
Retrans buffers : 2 retrans : 4294942296 4294942296 remove
retrans : 4294942296 4294942296 remove
IP : TCP packet
Retrans buffers : 1 retrans : 4294942296 4294942296 remove
tcpdev_process : read 8 bytes
IP : TCP packet
Retrans buffers : 1 retrans : 4294942296 4294942296 remove
tcpdev_process : read 8 bytes
tcpdev_process : read 108 bytes
Retrans buffers : 1 retrans : 4294942298 4294942296not
IP : TCP packet
Retrans buffers : 1 retrans : 4294942298 4294942298 remove
tcpdev_process : read 108 bytes
Retrans buffers : 1 retrans : 4294942325 4294942298not
IP : TCP packet
Retrans buffers : 1 retrans : 4294942325 4294942325 remove
tcpdev_process : read 108 bytes
Retrans buffers : 1 retrans : 4294942326 4294942325not
IP : TCP packet
Retrans buffers : 1 retrans : 4294942326 4294942326 remove
tcpdev_process : read 108 bytes
Retrans buffers : 1 retrans : 4294942331 4294942326not
IP : TCP packet
Retrans buffers : 1 retrans : 4294942331 4294942331 remove
tcpdev_process : read 108 bytes
Retrans buffers : 1 retrans : 4294942334 4294942331not
IP : TCP packet
Retrans buffers : 1 retrans : 4294942334 4294942334 remove

ON the client:

root@raspberrypi:/home/helge# telnet 10.0.2.15
Trying 10.0.2.15...
Connected to 10.0.2.15.
Escape character is '^]'.
login: rootassword:^M
Login incorrect

login: Password:^M
Login incorrect

login: Password:

Using netcat on the client side I at one point managed to login and get a shell prompt. It stopped (nethang, not system hang) after that (ps reporting the correct terminal).

  PID   GRP  TTY USER STAT CSEG DSEG  HEAP   FREE   SIZE COMMAND
    9     9   p0 root    S 5d34 41b0  1167   2708  67456 -/bin/sh 

@ghaerr
Copy link
Owner

ghaerr commented May 8, 2020

printk needs some CRs to improve readability, otherwise great.

What terminal emulator are you using to read the serial console? I'm running on macOS Terminal, which doesn't have this problem. Perhaps an option can be turned on that converts LFs to CRLFs.

If this is not easily possible, then I can look into always converting LF -> CRLF for printk's in the kernel. Let me know so this can be fixed ASAP for you.

@ghaerr
Copy link
Owner

ghaerr commented May 8, 2020

First, this is using the latest commits, including #614 (basic fixes to enable network testing), correct?

With ongoing PING, sounds like there is nasty memory corruption in either the /dev/eth driver or ktcp. We will need to find out which by running ktcp with slip at some point soon.

rebooting w/o the ongoing PING, and instead telnetting into elks, leaves us with the following. It's not consistent in that it doesn't stop at the same place every time, and sometimes just loops in retransmits.

Sound like networking code is still buggy in other places.

The elks telnetd responds with login: but continues after a few seconds (doesn't wait for newline) and execs /bin/login with whatever was typed, and emits 'Password:', where it actually waits. The tty (pty) echoes control characters like '^M' etc.

That's exciting - that's the first time we've seen telnetd working on ethernet.

I pretty certain the ^M echoing is on your Pi side, check the stty options there.

Anyway, this is not bad at all.

Can you get logged in, or does the system crash afterwards? Suggest looking at ps to see if there's any memory left just before entering the password, the problem may be no more system memory. Run meminfo as well to see.

@Mellvik
Copy link
Contributor Author

Mellvik commented May 8, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented May 8, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented May 8, 2020

yes, I can log in via netcat, even get a shell prompt. Nothing further. The shell does not seem to get any of the input.

Run meminfo when you have the shell prompt connected via netcat. That will report how much free memory there is, in case this might be a memory problem. Another thought is to login as toor, and use sash. Unfortunately, sash is very big with all the builtins and is only 15k smaller than ash at this point. But might be interesting to compare.

Unfortunately I can't do replicate anything over here - running QEMU when I try "telnet localhost" nothing happens. I can't use an external program for testing!!

@Mellvik
Copy link
Contributor Author

Mellvik commented May 8, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented May 8, 2020

It would be extremely beneficial to get you closer into the Debugging loop. There must be a way to get this to work reasonably w qemu. I'm inclined to spend some time figuring that out.

I just got incoming QEMU figured out! Have duplicated httpd running well, telnetd gets a shell and fails with double characters and other problems. Will be figuring this out and submitting PRs shortly. Still don't have outgoing working, so can't test telnet yet.

Not knowing anything about the inside of ktcp, would it make sense to locate and fix the icmp echo problem to begin with, assuming it's on the 'outside' softwarewise as it is in the stack?

QEMU supports host forwarding, I'll be working on seeing if I can ping ELKS. I took a quick look and ktcp is supposed to support ICMP echo.

Btw, outgoing telnet (from elks) connects, then disconnects, leaving the calling shell in a loop, printing prompts. This only if started from the console. If started from serial, outgoing telnet just hangs.

I can't test that yet, but already have a handful of problems I can finally duplicate :)

@ghaerr
Copy link
Owner

ghaerr commented May 9, 2020

Hello @Mellvik,

An update on networking: I've deep-dived into it, and its a big mess. There's lots of work to be done, and I'm a bit hesitant to start, as it could take lots of time.

I have incoming-networking only working, so only tested that. Outgoing remains entirely untested, and internal (localhost) connections appear not to work at all.

Brief synopsis:

  • telnetd is completely broken. It doesn't implement any telnet sequences, its basically a stripped-down login-style daemon. As a result, it works terribly with any telnet-protocol compliant client, and reverts telnet clients to line mode, or double-echoing, which makes it unusable.
  • httpd appears to work well.
  • ktcp works well for a few minutes or connections, then fails with unreported memory allocation fails and subsequent use of NULL pointers. I've got that fixed, but there remains a big memory corruption problem that causes it to run out of memory improperly and stop executing after a few minutes.

Overall, ktcp is poorly written, unfinished, has corruption problems, and is married to the kernel /dev/tcp kluge within the socket implementation. We really need something like Phil Karn's well-written TCP/IP suite, but fear it would take lots of work to understand the kernel handling and subsequent passing to user code and back.

One scenario is to add significant good debugging into ktcp, but it suffers ultimately from never being finished, and writing TCP/IP network code from scratch is not a great idea these days. I fear it can't be made bug-free unless its memory corruption is tracked down. In addition, telnetd needs to be completely replaced with the MINIX 2 version, which I was going to do, but ktcp won't run long enough to be useful. Running outside applications using telnetd and httpd simultaneously will cause ktcp to crash within seconds.

Another possibility is to ditch ktcp and move to userland-only networking. This would be equivalent to running Karn's code or a micro TCP stack as a user program complete within itself, and stay out of the kernel, at least at the start. This could work great, but ultimately fails because we need sockets in the kernel to support arbitrary networking. Since ELKS is real mode, I'm not sure how important this is, versus getting real usable networking running.

@Mellvik
Copy link
Contributor Author

Mellvik commented May 10, 2020 via email

@pawosm-arm
Copy link
Contributor

In our case that would be a choice between ktcp (somewhat workring) and Brian Kern (not entirely from scratch, but as I understand it, a clean kernel-integrated approach). Fully userland just doesn't taste good.

For me it's not a matter of taste, it's the practicality. Fully userland solution isn't that bad and isn't that uncommon, especially if you're limited in space for kernel. Shifting the burden to a daemon running in userspace is the solution then.

@ghaerr
Copy link
Owner

ghaerr commented May 10, 2020

Update on networking status, and thanks for both your comments.

After careful consideration of the work involved, I decided to stick with ktcp and attempt to corral the memory problems. Also, I retract my statement that ktcp is poorly written. The architecture, now that I'm coming to understand it, is nicely albeit crudely written, though definitely unfinished. Not all memory allocations were checked, and there were no provisions for handling unbounded memory growth. There is no routing, very little IP, no UDP. TCP doesn't handle error cases well.

I've now got ktcp able to run for longer periods of time, have fixed a big memory overwrite bug and have added code to prevent it from running out of memory. I have tracked down the unbounded memory growth problem, which happens for a couple reasons: 1) for reasons yet unknown, TCP gets out of sync, and unlimited packets are allocated for retransmission, which grew to a very large size and malloc fails, and 2) TCP close wait operations with httpd do a FIN wait forever, and never close the connection. Since httpd thinks the connection is terminated, it starts a new one for the next browser refresh, each LISTEN/ESTABLISH operation requires 2106 bytes, and ktcp runs out of memory. I hacked the above problems into submission by forcing a ktcp TCP reset on all connections when too many packets are awaiting retransmission, and ktcp now at least stays running.

telnetd now runs for minutes at a time, so it now makes sense to port a real telnetd and that will fix our telnetd problem, as the current implementation can't work with a real telnet client. ktcp doesn't recognize a shell exit or connection close for some reason, and subsequent telnet requests don't work.

httpd will run 3-4 browser refreshes before ktcp runs out of memory on new listen operations. Also, httpd zombies remain and ELKS runs out of process slots.

All of this is being tested with NE2K card emulation on QEMU. I badly need a method of testing SLIP/CSLIP to determine at which level the bugs are. Can anyone help to setup a test SLIP scenaro using an emulator?

I plan on submitting a few cleanup PRs that should allow testing volunteers to help move this forward.

@ghaerr
Copy link
Owner

ghaerr commented Jun 10, 2020

Elks will answer any and all arp reqests. Neither arp.c nor deveth.c checks that the request is for its ip address.

It looks like deveth.c line 94 checks for two MAC addresses: broadcast and ELKS. I'm thinking that ARP requests with a broadcast header (all 0xFF) are coming in through there, into arp_recvpacket, adding the request to the cache (which may not make sense if the request is a query, not a response), then issuing an ARP reply regardless (line 199 in arp.c).

I can't exactly debug this in QEMU, is ELKS responding to all ARP requests with its own MAC/ethernet address? I think we can fix this by comparing the requested src IP in arp.c line 198 and not call arp_reply if its local_ip. Perhaps test this by adding the line if (arp->ip>src == local_ip) before arp_reply on line 199.

I'll read up a bit on ARP headers to see whether the call to arp_cache_add is appropriate. Note that ktcp doesn't timeout ARP entries either, so there's still work to be done.

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 10, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 11, 2020

Diff for arp.c fixes, re. message above:

 typedef struct arp_cache_s arp_cache_t;
 
 static arp_cache_t arp_cache [ARP_CACHE_MAX];
+static int merge_flag = 0;     /* tell arp_cache_get to merge the incoming address */
 
 
 static void arp_cache_init (void)
@@ -57,8 +58,14 @@ int arp_cache_get (ipaddr_t ip_addr, eth_addr_t * eth_addr)
                if (!entry->ip_addr)
                    break;
                if (entry->ip_addr == ip_addr) {
-                       memcpy (eth_addr, entry->eth_addr, sizeof (eth_addr_t));
-                       debug_arp("arp: using cached entry for %s\n", in_ntoa(ip_addr));
+                       if (merge_flag) {
+                               memcpy (entry->eth_addr, eth_addr, sizeof (eth_addr_t));
+                               merge_flag = 0;
+                               debug_arp("arp: updating cached entry for %s\n", in_ntoa(ip_addr));
+                       } else {
+                               memcpy (eth_addr, entry->eth_addr, sizeof (eth_addr_t));
+                               debug_arp("arp: using cached entry for %s\n", in_ntoa(ip_addr));
+                       }
                        return 0;
                }
                entry++;

@@ -190,13 +199,19 @@ int arp_request(ipaddr_t ipaddress)
 void arp_recvpacket(unsigned char *packet, int size)
 {
        register struct arp *arp = (struct arp *)packet;
+       int notfound;
 
        arp_print(arp);
        switch (ntohs(arp->op)) {
        case ARP_REQUEST:
                debug_arp("arp: incoming REQUEST\n");
-               arp_cache_add (arp->ip_src, &arp->eth_src);
-               arp_reply (packet, size);
+               merge_flag++;
+               notfound = arp_cache_get(arp->ip_src, &arp->eth_src); /* possible cache update */
+               if (arp->ip_dst == local_ip) {
+                       if (notfound)
+                               arp_cache_add(arp->ip_src, &arp->eth_src); 
+                       arp_reply (packet, size);
+               }
                break;
 
        case ARP_REPLY:

@ghaerr
Copy link
Owner

ghaerr commented Jun 11, 2020

Hello @Mellvik,

Thanks for the ARP fix!

Is this version RFC 826 compliant, according to your reading of it? I read most of the RFC yesterday.

This fixes the ARP replies being generated by ELKS when it shouldn't, does it fix anything else that can be noted?

I don't have a way to fully test it, but will check what I can on QEMU. I would like to get rid of the merge_flag global and will submit a slightly revised PR with that passed as a parameter to arp_cache_get() for you to test and we'll commit it.

I've been trying to get a PC that will run serial port or ethernet and have struck out twice in the last week. The first system was too modern for an ISA NE2K, but wouldn't boot an ELKS FAT32 MBR USB stick for some reason. The second system was quite ancient but its BIOS didn't support any USB boot. I can't write floppies so USB boot seems to be the way to go. Can't wait to actually get some real hardware that can run ELKS lol :)

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 11, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented Jun 11, 2020

May I recommend compaq portables on ebay?

That's a neat idea, I used to have one years ago that I developed on... but I need a system that will boot an ELKS MBR USB, since I have no way of writing a floppy!

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 11, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented Jun 12, 2020

@Mellvik,

Thanks for you suggestions on hardware. I bought a Compaq Portable 386 on ebay, along with a Gotek floppy drive emulator. I hope to use this to improve the serial port driver for higher speeds, and, with the single ISA expansion bay, get an NE2K network card up and running for network testing, and ultimately the implementation of TFTP for updating ELKS on its internal hard drive.

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 12, 2020

Congratulations!! Presumably with an expansion box so you get the ISA bus. I used a floppy emulator like the gotek for a while, works fine. If the machine has the original (slow) disk, you may consider replacing it with a CF card IDE socket. Too bad I couldn't sell you one - I'm preparing two 386/20s for ebay right now. Let me know if there is anything you need. BTW - I just noticed that the 3COM 503 card uses the same chipset as the ne2k, so expanding ELKS support to that 3com model would be easy.

@ghaerr
Copy link
Owner

ghaerr commented Jun 12, 2020

Presumably with an expansion box so you get the ISA bus

Yes.

I used a floppy emulator like the gotek for a while, works fine.

I've heard that the system has to be booted from 5" floppy first and some sort of setup program run... The Compaq BIOS expects a 1.2M 5.25" drive, will there be a problem if I try running the Gotek as a 1.44M 3.5" drive when attached? I guess I'll have to open the case to even get that working.

the 3COM 503 card uses the same chipset as the ne2k, so expanding ELKS support to that 3com model would be easy.

Just looked on eBay, and the 503 cards have the older BNC connector... what about this one, a 3C509 which has the ethernet connector, do you think that would work?

https://www.ebay.com/itm/Vintage-PC-Hardware-3Com-ISA-Etherlink-III-3c509TP-Ethernet-card/124188175361?_trkparms=aid%3D1110001%26algo%3DSPLICE.SIM%26ao%3D1%26asc%3D225085%26meid%3Daaf9c71aaad94bc5abe27d1fa1c8fcd7%26pid%3D100005%26rk%3D2%26rkt%3D12%26mehot%3Dpf%26sd%3D274236107437%26itm%3D124188175361%26pmt%3D0%26noa%3D1%26pg%3D2047675&_trksid=p2047675.c100005.m1851

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 12, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 16, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented Jun 16, 2020

Thanks for the update!

I’m (partly) rewriting the low level of the ne2k driver, now being tested - incoming ping works, arp works, incoming telnet is almost stable.

Nice - did you find particular areas of the NE2K driver that were broken? What were they?
BTW, I ordered the network card you recommended for the Compaq 386.

The case is incoming telnet to elks. If the client sends a RESET, tcp.c line 239 handles that fine, cleans up the receiving end. But if there are outgoing packets pending, ktcp panics in tcpdev.c line 310.

Unfortunately I haven't been able to determine the problem with this yet. ktcp has a number of problems on session termination, whether from RST, or from normal or abnormal telnet termination. These are complicated with the kernel/tcpdev design which passes socket information to/from user programs and ktcp. I have been testing using localhost, which only works for a while before hanging. None of the session disconnects work properly and there also seems to be memory corruption errors afterwards as well.

@Mellvik
Copy link
Contributor Author

Mellvik commented Jun 16, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented Jul 17, 2020

@Mellvik,

I went ahead and merged #667 which finalized the ethernet and ARP fixes discussed here, with the exception of your enhanced NE2K driver. Since we had a number of other intervening PRs, I figured it would be better to pull everything down from the repo for your next round of testing. Since this ktcp status issue is getting pretty long, go ahead and close this if the ARP wait kluge works, I'll then close the original issue, and you can bring up subsequent problems in a new thread.

Thanks!

@pawosm-arm
Copy link
Contributor

pawosm-arm commented Jul 19, 2020

I've built ELKS this morning with all of the recent ktcp and ARP changes and here are some observations:

  • All tests have been done on SLIP connection at 4800bps, as this machine can't do any better (at least not with hardware flow control). Also, following change was applied for this build
--- a/elks/include/linuxmt/ntty.h
+++ b/elks/include/linuxmt/ntty.h
@@ -9,7 +9,7 @@
 #define INQ_SIZE       128     /* tty/pty input queue size*/
 #define OUTQ_SIZE      64      /* tty/pty output queue size*/
 
-#define RSINQ_SIZE     1024    /* serial input queue SLIP_MTU+128+8*/
+#define RSINQ_SIZE     4096    /* serial input queue SLIP_MTU+128+8*/
 #define RSOUTQ_SIZE    64      /* serial output queue size*/
 
 /*
  • Despite retrans retry messages popping out regularly (see example below), communication never broke, which is a huge progress!
retrans retry #1 rto 2939 mem 21
  • I was trying two simultaneous telnet connections: from Linux to ELKS (running telnetd on ELKS) and from ELKS to stdiotelnetd running on Linux. Also Linux was pinging ELKS for most of the time during my experiment. Both telnet sessions seemed to work correctly, somewhat slow, but it's expected at 4800bps. No huge lags experienced though which is again a huge progress comparing to what it used to be. I'd leave those things opened for a lunch break, and when I returned, I've found ELKS command line in the telnet session being full of regularly repeating rubbish:
login: root
# meminfo
  HEAP   TYPE  SIZE    SEG   TYPE    SIZE  CNT
  e3da   SEG     12   1e55   BUF    65536    1
  e3ee   SEG     12   2e55   BUF    65536    1
  e402   SEG     12   3e55   CSEG    6816    1
  e416   SEG     12   3fff   DSEG    8768    1
  e42a   SEG     12   4223   DSEG    6080    1
  e43e   SEG     12   55cf   DSEG   18672    1
  e452   TTY    128
  e4da   TTY     64
  e522   SEG     12   5a5e   CSEG   17856    1
  e536   SEG     12   72c4   DSEG   18672    1
  e54a   SEG     12   5eba   free   18672    0
  e55e   SEG     12   4a85   CSEG   46240    2
  e572   SEG     12   68bf   DSEG   41040    1
  e586   TTY   4096
  f58e   TTY     64
  f5d6   SEG     12   46b2   CSEG    5856    1
  f5ea   SEG     12   4820   CSEG    5728    1
  f5fe   SEG     12   6349   CSEG    4576    1
  f612   SEG     12   439f   DSEG   12320    1
  f626   SEG     12   4986   free    4080    0
  f63a   SEG     12   46a1   free     272    0
  f64e   TTY    128
  f6d6   TTY     64
  f71e   SEG     12   6467   DSEG   12112    1
  f732   SEG     12   675c   free    5680    0
  f746   SEG     12   7753   free  166608    0
  f75a   free  2214
  Total heap   7214     Total mem  531120
  Memory usage  519KB total,  328KB used,  191KB free
# ps
  PID   GRP  TTY USER STAT CSEG DSEG  HEAP   FREE   SIZE COMMAND
    1     0      root    S 3e55 3fff  3072   2016  15584 /bin/init
    7     7    1 root    S 4a85 55cf  1166   6818  64912 -/bin/sh
   16     7    1 root    S 4820 439f     0   8127  18048 telnet 192.168.0.1 2424
   12     7    1 root    R 5a5e 68bf 13726  12835  58896 ktcp -b -d -m 512 -p slip -s 4800 -l /dev/ttyS0 192.168.0.2 192.168.0.1 255.255.255.0
   14     7    1 root    S 46b2 4223     0   1961  11936 telnetd
   17    17   p0 root    S 4a85 72c4  1166   6818  64912 -/bin/sh
   19    17   p0 root    R 6349 64c9  1024   5952  18624 ps
# ˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń˙ń

Unfortunately. this telnet session didn't seem to work any longer and I couldn't open new telnet connection from Linux to ELKS. I couldn't kill telnetd process in ELKS either, even with kill -9. The other telnet connection (ELKS to Linux) was still working ok though. Pings were still returning but with a huge lag.

A side note about arping. I could not do that on SLIP connection:

$ arping 192.168.0.2
Interface "sl0" is not ARPable (no ll address)

I guess it's only possible on the real n2k-compatible device.

@Mellvik
Copy link
Contributor Author

Mellvik commented Jul 19, 2020

@ghaerr,
the first using the latest commit shows definite ARP issues, so I'm holding back on the closing till I have a clear problem report.
BTW I'm also now seeing some of the same driver issues with the new PnP card as with the older 8390 based card. It's sort of good news. The new card with the old driver apparently working better was lucky timing, not hardware differences.

--Mellvik

@ghaerr
Copy link
Owner

ghaerr commented Jul 19, 2020

Hello @pawosm-arm,

Thanks again for your continued testing of networking over SLIP!

communication never broke, which is a huge progress!

That's great! It is taking a while, but I think we're slugging away slowly eliminating many of the bugs involved in getting networking to operate for a reasonable amount of time.

It sounds like the serial driver is working now (up to 4800 baud) on your system. Did you require the larger 4k input buffer, or can ktcp work with the standard 1k buffer? I worked to change the MTU to 1k bytes so a larger ring buffer wasn't required. I'm wondering whether we need some kind of stty option for buffer size so that recompiling isn't required.

Despite retrans retry messages popping out regularly.

Yes, I'm aware of the retransmission problem, and haven't quite figured out why its happening so often. It doesn't appear to be the result of dropped serial characters, but I don't see it happen on ethernet, so still a bit confusing.

I have no idea what the main "repeating character" problem is you found doing a telnet session. I would guess its not a new bug, but a result of one of the 3-4 major memory corruption bugs still identified and present in the networking stack.

Unfortunately. this telnet session didn't seem to work any longer and I couldn't open new telnet connection from Linux to ELKS.

FYI - ktcp is absolutely NOT reliable yet after any session has closed. I don't yet know the reasons but will attack these after we get the basic networking working (which is almost complete, awaiting further testing and a NIC driver enhancement from @Mellvik).

I couldn't kill telnetd process in ELKS either, even with kill -9. The other telnet connection (ELKS to Linux) was still working ok though. Pings were still returning but with a huge lag.

Yes, once networking has an error or closes a session, it seems there is corruption that causes innumerable other issues. Thanks again for your testing, and its nice to hear progress is being made!

@ghaerr
Copy link
Owner

ghaerr commented Jul 19, 2020

@Mellvik,

the first using the latest commit shows definite ARP issues, so I'm holding back on the closing till I have a clear problem report

Can you explain the ARP issues a bit more? I added the MAC address to arp debug issues after finding how I broke the ARP code for one commit, but am not aware of any new ARP bugs... and am anxious to know whether you're talking about something I might have broken with the ARP wait kluge fix rewrite, or something else. Obviously, the way that ARP works is changed, by delaying the IP packet until a reply is seen, but that's the only change made.

I'm dependent on your testing for ethernet - the QEMU networking is pretty strange... for instance, the ARP commit I broke ended up sending an all-zero MAC address in replying to packets, and guess what? The QEMU "stack" worked, it apparently doesn't even look at the destination packet address! If I hadn't been in the middle of adding the new arp command which showed a table of zero MAC address, I wouldn't even have known it!

@pawosm-arm
Copy link
Contributor

Did you require the larger 4k input buffer, or can ktcp work with the standard 1k buffer?

Nah it wasn't required, it's just a change that slipped in from my previous experiments with the higher baud rates. I'd remove it for next batch of tests.

@pawosm-arm
Copy link
Contributor

pawosm-arm commented Jul 20, 2020

I can confirm that the original input buffer size (1k) is OK, no need to change it. I've been testing today's changes, no change in operation and stability observed.

@Mellvik
Copy link
Contributor Author

Mellvik commented Jul 20, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented Jul 21, 2020 via email

@Mellvik
Copy link
Contributor Author

Mellvik commented Jul 21, 2020 via email

@ghaerr
Copy link
Owner

ghaerr commented Jul 21, 2020

ARP seems to be working flawlessly.

Great! I am going to close the three year old issue regarding the ARP wait hack as being fixed.

I'm not getting any consistency in the ICMP reply duplicates

Lets consider this a separate issue, should it come up again.

I'm also seeing the huge RTO reported by @pawosm-arm some times (telnet session)

Just found that bug: the basic timer mechanism within ktcp was broken, the microsecond time field was being interpreted as signed rather than unsigned and it sign-extended that into other time data, causing wildly inaccurate time values, depending on the microsecond! Kind of amazing it worked at all. Haven't tested everything yet, but this may fix other timeout and retransmission issues.

I'm now starting the merge of the updated ne2k driver and related changes to other files, which will enable more extensive testing of both arp and the tcp level

Super - the ARP and ICMP stuff should hopefully be stable enough to test your new driver for submission!

@Mellvik
Copy link
Contributor Author

Mellvik commented Jul 21, 2020 via email

@pawosm-arm
Copy link
Contributor

pawosm-arm commented Jul 22, 2020

@ghaerr todays pull request indeed fixed those large rto values bug, frankly, I'm not observing retrans at 4800bps at all! So I tried 9600 and although retransmissions started to pop out from time to time (infrequently), with rto 16, my TCP connections were still stable and undisturbed.
I also tried CSLIP again (at 4800bps again). As before, TCP BAD CHECKSUM errors started to pop out, whole lot of retransmissions (whit rto's around 100), yet my telnet sessions were still alive, although severely lagged.

$ telnet 192.168.0.2
Trying 192.168.0.2...
Connected to 192.168.0.2.
Escape character is '^]'.
login: root
# meminfo
  HEAP   TYPE  SIZE    SEG   TYPE    SIZE  CNT
  e3da   SEG     12   1e5d   BUF    65536    1
  e3ee   SEG     12   2e5d   BUF    65536    1
  e402   SEG     12   3e5d   CSEG    6816    1
  e416   SEG     12   4007   DSEG    8768    1
  e42a   SEG     12   422b   DSEG    6080    1
  e43e   SEG     12   55d7   DSEG   18672    1
  e452   TTY    128
  e4da   TTY     64
  e522   SEG     12   5a66   CSEG   17872    1
  e536   SEG     12   72cf   free  185104    0
  e54a   SEG     12   5ec3   DSEG   12112    1
  e55e   SEG     12   4a8d   CSEG   46240    2
  e572   SEG     12   68c9   DSEG   41056    1
  e586   TTY   1024
  e98e   TTY     64
  e9d6   SEG     12   46ba   CSEG    5856    1
  e9ea   SEG     12   4828   CSEG    4576    1
  e9fe   SEG     12   6664   free    9808    0
  ea12   SEG     12   43a7   free   12592    0
  ea26   TTY    128
  eaae   TTY     64
  eaf6   free    12
  eb0a   SEG     12   61d5   DSEG   18672    1
  eb1e   SEG     12   4946   free    5232    0
  eb32   SEG     12   61b8   free     464    0
  eb46   free  5306
  Total heap   7214     Total mem  530992
  Memory usage  518KB total,  310KB used,  208KB free
# ps x
  PID   GRP  TTY USER STAT CSEG DSEG  HEAP   FREE   SIZE COMMAND
    1     0      root    S 3e5d 4007  3072   2016  15584 /bin/init 
    7     7    1 root    S 4a8d 55d7  1166   6746  64912 -/bin/sh 
   13    13   p0 root    S 4a8d 61d5  1166   6818  64912 -/bin/sh 
   10     7    1 root    R 5a66 68c9 14014  12434  58928 ktcp -b -d -m 512 -p cslip -s 4800 -l /dev/ttyS0 192.168.0.2 192.168.0.1 255.255.255.0 
   12     7    1 root    S 46ba 422b     0   1961  11936 telnetd 
   15    13   p0 root    R 4828 5ec3  1024   5948  18624 ps x 
#

Note that with CSLIP it took me minutes to get the above. I guess CSLIP issue deserves separate ticket.

@Mellvik
Copy link
Contributor Author

Mellvik commented Jul 22, 2020

After #667 and #678 it's time to close this very general issue, and open up new ones as required. We've come a long way!!

-- Mellvik

@Mellvik Mellvik closed this as completed Jul 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Defect in the product
Projects
None yet
Development

No branches or pull requests

4 participants