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

Handle jumbo frames (possibly as WATTCP.CFG option) #69

Open
maraakate opened this issue May 1, 2022 · 7 comments
Open

Handle jumbo frames (possibly as WATTCP.CFG option) #69

maraakate opened this issue May 1, 2022 · 7 comments
Labels
wontfix This will not be worked on

Comments

@maraakate
Copy link

Hello,

We've been using WATTCP for years in some DJGPP DOS applications, but I have noticed that UDP DGRAM fragments are sent as EWOULDBLOCK. This is a problem for old games like Quake 2 where sometimes this stupidity does happen, and we can't send them broken up on the server side because it breaks some client parsing. Unfortunately, some of these engines relied on the routers to take care of the problem.

I did some simple test by removing the DGRAM check in check_non_block_tx() but it appears WATTCP just ends up doing the same thing behind the scenes (i.e. breaking up the sendto()s to be less than MAX_MTU - overhead) and the same problem happens.

It would be great if there was a jumbo frames option to just send the whole thing unfragmented and it's up to the clients router to take care of it.

Thanks for all your hard work over the years, we've really gotten a lot of great use out of the library.
Frank

@maraakate
Copy link
Author

Giles,

I did a bit more poking around, and found out the hard way that even if you change MTU in WATTCP.CFG that there is a hard limit of about 1500. This is from MAX_ETH and friends. Maybe the code could be refactored to allow MAX_ETH, etc. to be controlled by a JUMBO_PACKETS config option?

@gvanem
Copy link
Owner

gvanem commented May 1, 2022

UDP DGRAM fragments are sent as EWOULDBLOCK.

Not sure what this means.

A Jumbo frame-size would depend on the Ethernet card. There is no way AFAICS to obtain the size of that.
How is that obtained on other OSes like Windows or Linux? Some DeviceIoControl() call on Windows for sure.
Or do you mean a JUMBO_PACKETS = 3000 setting should be accepted just like that w/o check what the real jumbo frame-size is?

@maraakate
Copy link
Author

Hi, i mean the JUMBO_PACKETS=3000 just sends it this way and if it fails its the users fault because they explicitly set it and was incompatible. I think this is a decent compromise for the scope of the project.

Referring to EWOULDBLOCK. It just appears to get stuck in that limbo more or less with the software I've been using it with. But again, I think a way to force attempting to send 3000 or some other value beyond MAX_ETH would help in my cases.

@gvanem
Copy link
Owner

gvanem commented May 4, 2022

I think this is a decent compromise for the scope of the project.

Jumbo-frames can only work reliably on a LAN. So the code will need to check the destination before using such a
JUMBO_PACKETS setting. Besides, I've never seen a Packet-driver supporting such Jumbo-frames. Have you?

Referring to EWOULDBLOCK. It just appears to get stuck in that limbo more or less with the software I've been using it with.

The reason is that IPv4 fragmentation (ref. ip4_frag.c) does not work so well. But you need this in Quake? On a LAN only, or what?

@maraakate
Copy link
Author

Hi,

It's not so much that it needs be jumbo frames that need to be 9000 bytes. The problem is a bit more like this... some packets go over 1400 bytes (which is the default in these engines) and some packets in situations with a lot of action/entities on the screen will produce a packet that could be anywhere from 1500-1800 bytes on average (this is kind of rare, but happens enough). I've reduced this issue by reducing the amount of traffic that's being sent out. It's about as optimized as it can get, and if the frame is still over 1400 bytes then it's compressed with an on-the-fly compression scheme (we use quicklzf for this). This usually gets thing sane more than 90% of the time. However, there are corner cases where it's still too large.

In the old days, it kind of depended on your ISP, if you had dial-up or a DSL/Cable modem with router, etc. on how this would work. I've tested these kind of overflows before on a true dial-up and what happens is the packet is just discarded entirely. The player may be "stuck" for about 2-3 seconds until it can receive a frame of the proper size again. DSL/Cable modems will just do what they need to do to fix this and it assembles it properly.

With Watt-32 what happens is EWOULDBLOCK gets set because its a datagram (we are using UDP for all of this). Then this is spammed non-stop. So the packet is discarded, which is fine (not ideal, I'd like to see it be re-assembled, but this is an OK work around because it's not implemented) but the EWOULDBLOCK is still there, so every FD_SELECT it has the real packet of the next frame thats OK, but then there's still that EWOULDBLOCK as well and it never goes away unless I close the socket entirely.

I know this is all more a problem with the engine, and mappers and modders not respecting the limits of MTU being ~1400. And we've done all we can, but the socket driver should also help out in some way as well. With that said, I think allowing the code to go past that MAX_ETH hard limit of 1500 AND fixing UDP datagrams to work with the fragmentation instead of just EWOULDBLOCK would work OK. I have no experience in Watt-32, but I have looked around a bit since opening this issue. It appears that we should send EWOULDBLOCK the one time then just ignore and completely discard it. Otherwise it continues to get spammed and this actually bogs the machine down because every other frame its receiving junk it can do nothing with.

I may have misspoke and it's not that we need 9000 bytes of a jumbo frame, but we need to somehow gracefully handle if we get some UDP packet thats got 1800 bytes because someone forgot to check before sending. And possibly allow the user explicitly in WATTCP.CFG to allow setting that as the max limit. If it works, great, if not because the packet driver doesn't allow it... well too bad that's why it's an option and not a default.

@gvanem
Copy link
Owner

gvanem commented May 14, 2022

I've studied this a bit. It's impossible with WinPcap or any PacketDriver to send any frames > 1514 bytes.
And if could be possible, all references to the constant ETH_MAX would be replaced with a global variable Jumbo_frame_size
for all IP-packets. A major rewrite. Hence a won't fix label. But I'll keep it open.

@gvanem gvanem added the wontfix This will not be worked on label May 14, 2022
@maraakate
Copy link
Author

maraakate commented May 15, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants