• 3 Posts
  • 296 Comments
Joined 3 years ago
cake
Cake day: July 2nd, 2023

help-circle

  • For folks that are space constrained and would only use a trailer infrequently, folding utility trailers are available. Specifically, Harbor Freight in the USA sells one such 4x8 utility trailer for some $400. It weighs 250 lbs, though closer to 300 lbs (180 kg) after adding a 5/8" (10 mm) plywood deck; not included.

    This makes it fairly reasonable to tow even with a small car, for light-but-bulky payloads (eg sectional sofa) a few times per year. Some US States like Oregon don’t even require registration for such small trailers, while California has an extremely reasonable $25 plate fee that lasts 5 years.

    To be abundantly clear, towing anything is a departure from run-of-the-mill driving, and carrying a load of any size presents hazards that require some attention and care. But it’s entirely feasible and costs a lot less than a truck. The tradeoffs can be worth it, if it works with your use-case. It certainly does for mine.



  • In some cases, the game server’s IP address is actually anycasted, which is an approach that (very carefully) breaks the notion that a network identity belongs to a single machine. Instead, that one IP address would actually be routed to a nearby machine which is authorized to assume the identity of the game server, and will thus handle the game traffic for that region. So long as all regions handle their traffic identically and the results are consistent as if there were one giant machine that were handling all the traffic, this can work. An example where the seams are visible are how YouTube’s view counters will momentarily not match up across all geographies, because the backend servers don’t sync up to each other instantly or even quickly; and few people require that precision anyway, so they just don’t bother engineering it to do that. When you’re providing a global service, that is exactly the sort of engineering tradeoff that must be considered, because even they do not have unlimited money.

    In other situations, the game server IP address really is for a single machine, but that machine is a specialized hardware load-balancer that is situated in a cloud provider’s network. All that this machine does is to be the frontend for the 5-tuple, and will create a new conversation/connection 5-tuple with a cluster of game servers within the cloud provider’s network. There might be some superficial comparisons between a load-balancer and NAT, but the latter works by fraudulence whereas a load-balancer is a subcontractor.


  • The other commenters have provided many disparate answers that do reply to parts of your question, but allow me to approach the question holistically and thoroughly.

    my basic understanding is that computer networking relies on constructs like IP addresses and port numbers to direct data packets to the correct device and application.

    This is substantially correct. An IP address is a network identity of some “node” machine that participates on the network. A port number is a protocol-specific number for how to interact with a given node. For gaming, we are almost always talking about UDP as the protocol, so the port number will be a UDP port number; the same logic applies for TCP, but I’m going to gloss over that unless you specifically want details about this.

    In the case of Legacy IPv4, an IP address is a 32-bit number that is usually presented as four decimal bytes separated by dots (eg 203.0.113.67). Or for modern IPv6, it will be a 128-bit number presented as hexadecimal groups of double bytes that are colon-separated, but where zeros can be abbreviated (eg 2001:db8::67). A TCP port number is any value between 1 and 65535 inclusive; 0 is technically usable but most software will not allow its use.

    So, if I’m playing an online game like Minecraft or Counter-Strike, I am able to connect to the dedicated game server using the server’s IP address … and port number

    Correct. Your client aims at the server’s IP address, and the UDP port number on that server. And on your end, you will have your own client IP address and client UDP port number. Implicit to the internet, we know that this must be using IP (v4 or v6 does not matter in this scenario) and the client and server only know how to speak UDP. Thus, there are five pieces of information which capture the entire connection: the source IP, source port number, destination IP, destination port number, and the protocol (UDP). In the networking parlance, we call this as the 5-tuple, because it captures the notion of a single conversation between two applications across the network.

    Note that I’m specifically using the word “conversation” and not “connection” because the latter has a specific meaning in the business. A connection means that we’re holding a resource open – like a telephone line --for the entire duration that data is being exchanged. But UDP doesn’t reserve resources like that, and is more like sending a post card and hoping for a reply.

    The 5-tuple concept is important because like an IRL conversation, it’s entirely possible to send data in the reverse direction, and while the source IP/port and destination IP/port will be reversed, it’s easy to see that this is functionally the same “conversation”, just in reverse. The network doesn’t really care if the tables have turned: it just passes packets around. So I will simplify and say that if a 5-tuple reverses its source and destination values, then that’s functionally no change at all.

    I can now answer your question with technical precision: a game server can distinguish multiple game clients by using their unique 5-tuple. The rest of your question is answered by a brief explanation of various workarounds that are needed for the post-1995 Legacy IPv4 world, but which were fixed in the modern IPv6.

    In some cases, each client will be connecting from their own network modem, with their own IP address assigned to them dynamically or statically by their ISP. In that case, I would imagine that the server could just keep a list of client connections and route relevant data back to each client.

    This is exactly what existed pre-1995 when the end-to-end principle was alive-and-well on the public Legacy IPv4 Internet. As I mentioned before, an IP address is a network identity, and in the original conception of IP going back to ARPANet, an identity was not meant to be shared amongst multiple machines. Instead, every machine was expected to have its own IP address. However, during the 1995 explosion of dial-up users, network operators could not (or would) not) obtain new tranches of IP addresses to hand out to users, so they began using NAT as a workaround, to reduce their need for public IP addresses. But the keyword was “reduce” not “eliminate”, and by 2012, the world had officially run out of available IP addresses to hand out to ISPs.

    But in other cases, you might have a multiple clients playing a game behind one modem (like housemates or a LAN party where multiple players join the same remote/internet server), or a newer problem, multiple different networks sharing an IP address due to CG-NAT at the ISP level.

    All of these workarounds (NAT/NPAT, CG-NAT, etc) all work by mutilating the 5-tuple and then unmutilating it for return traffic. When a home router performs NAT, it replaces the client’s source IP (eg 192.168.3.42) with the router’s (eg 203.0.113.67), and usually also replaces the client’s UDP port (eg 12345) with a random one available on the router (eg 45467). The resulting 5-tuple is what the game server will receive. NAT must save the mapping (12345 -> 45467) for future reference.

    When the game server wants to reply, it will – exactly the same as the case with the end-to-end principle – reverse the source/destination fields in the 5-tuple, and send the packet. This means the destination is now the home router’s IP (203.0.113.670 and UDP port (45467). What NAT will now do is to again modify the source IP (to restore the original value of 192.168.3.42) and then use its stored mapping to restore the original UDP port number of 12345.

    From the client’s perspective, it receives a reversed 5-tuple of the one it sent to earlier. Thus, it’s perfectly happy to receive that traffic and nobody is the wiser.

    In which case, from the perspective of the server, multiple players would be playing from the same IP address and communicating over the same port, right?

    Recall that NAT on the router will: 1) generate a random, new UDP port number, and 2) store the mapping of the originator’s port number. So if there are two clients at home playing Minecraft, the router will have generated a different random UDP port number for each, meaning the 5-tuple that arrives to the game server will match 4 out of 5 parts, but not all five. The crucial – and only – distinction between these two clients at the same house are that they present a different source UDP port number to the server. And that is also how the game server will treat those two clients separately.

    If the home router were to spontaneously reboot – thus forgetting the NAT mapping table for UDP port numbers – then both clients cannot recover the conversation at all, even after the home router is back online: the mappings are lost, and nothing can be done but to reconnect to the game server as a new 5-tuple. The end-to-end scenario does not have this problem, and pre-1995, routers did in-fact crash more often than they do now. Genuinely, today’s Legacy IPv4 service is poorer than it was in the past, and certainly poorer than what modern IPv6 can deliver.

    So how does the server differentiate between >2 players connecting from the same IP address and communicating over the same port?

    As long as the home router has available UDP port numbers, NAT can continue to randomly generate a unique UDP port number for each client that is behind the NAT. Since UDP port numbers can be as large at 65535, that’s a lot of clients. Though practically, no home router would ever see that many Minecraft clients. Even CG-NAT tends to only support approximately 64-128 clients on a single Legacy IPv4 address.

    As for why, all this mutilation of packets takes a little bit longer than just passing the packet through the internet. It is not fun for the ISP to have to build CG-NAT infrastructure. It is not fun to build home router firmware that will get blamed for the user’s bandwidth or firewall problems. Also, NAT would require a (relatively large) table in memory store lots of mappings, and so they just don’t do that for consumer routers.

    In the USA, AT&T’s fibre internet modem/router is known to max out after a critical number of UDP conversations or TCP connections, because the NAT feature has run out of memory. This is precisely why some people bypass the modem/router (so they can use their own high-end router) or will use IPv6 for their connection-intensive workloads, like sharing Linux ISOs.

    Or does it not even try, and instead just broadcast all of the relevant game data to every client?

    Game servers definitely do not do this, because broadcast is not permitted on the public Internet whatsoever, whether on Legacy IPv4 or modern IPv6. The original conception of the internet did describe “multicast” which can target a group of IPs on a network, but this was never well-implemented for IPv4 and is only implemented on LANs for IPv6. The public internet does not support multicast, for a number of historical and bandwidth/security reasons.

    If a game server wanted to send the same data to each client, one after another, it can. But it still must know the 5-tuple that identifies each client. Fortunately, the game server’s OS will have taken care to record this info (eg BSD sockets).

    And if that’s the case, how do huge games like battle royales or MMOs handle sending game state to a large number of users?

    The way that MMOs deal with 100k+ clients goes deep into the realm of clustering, load-balancing, and network engineering. The only things that get more complex than that are high-bandwidth applications involving hundreds of thousands of clients (eg Netflix) or are massive hyper-scaler cloud providers (eg Azure, Alibaba).

    That said, the fundamentals are still there: clients are identified by their 5-tuple, and all the engineering done to spread that load must still end up producing a reply that has the reversed 5-tuple.

    (cont)



  • I’ll add some color to this post.

    The original FTP is, frankly, a monster of a protocol. Very useful, but an anomalous protocol that even without NAT breaking the end-to-end principle, it is unlikely to have survived modern corporate firewall rulesets in any case. The fact that FTP was even ported for TCP is its own historical quirk.

    BTW, that is the term which this post is missing: the end-to-end principle is the design philosophy that the network itself should not have to perform work on payloads transmitted, except to carry it towards the destination. This also implies that no fields or bits should be modified in transit, once it leaves the sender; encap/decap restores the fields so that the receiver is none the wiser.

    NAT breaks end-to-end in two respects: corruption of the original sender, and corruption of L4 port numbers. Note that Legacy IP also violated end-to-end, when packets are fragmented due to MTU issues. With IPv6, fragmentation by the network is disallowed outright, and the technical case for NAT is non-existent.

    There’s something to be said about adopters of NAT, that they were facing a Hobson’s choice: use NAT so that they could connect early dial-up users to the emerging Internet, or reinvent the 20 year experiment of the Internet so that it could scale properly. In 1995, IPv6 did not exist so they made the only real choice available.

    In the year 2026 though, that argument doesn’t hold water: it is a choice to continue to ignore the dual-stack and IPv6-only internet. There’s a quote that all sufficiently complex technical problems are in-fact political, and this is that: the modern case for Legacy IP and NAT is rooted in inertia, resource scarcity (eg hyperscale cloud companies buying up IP subnets), and recalcitrance by professionals that abdicate their responsibility to their clients to pursue the available technology.

    There is no colorable technical rationale for why IPv6 best practices cannot be adopted today for most organizations, when all network hardware, all major consumer and enterprise OS’s, and all mobile phones support v6. Note that I said “best practices”, because a minority of orgs such as certain American ISPs have undertaken truly bonkers decisions that are putting us on track for the very same sins as Legacy IP.

    The fact that some ISPs assign nothing but a single /128 via DHCP6 is absurd: this malpractice perpetuates the same problem as NAT44, except that there’s no good excuse for it. Even the most delusional of ISPs will never run out of /128 addresses in their assigned /32. Per best practice, even handing out /48’s to customers is not a problem either, because that’s 65536 customers and if that’s really a problem, just ask the RIR for another /32, which they can do as RIR dues-paying members. There is no practical limit, except that some people just cannot math properly to see that there’s no practical limit. When a technical solution to a technical problem fails because of innumeracy by those tasked with implementing it, then that’s so much worse than any 1990s workaround.

    I’ve harped a lot about IPv6 because its strength today is that it’s technically competent, future-proofed, and most importantly, practitioners that saw the first travesty of NAT will not allow a redux to play out with IPv6. The technical reasons to deploy NAT66 are non-existent: it is always a workaround for political issues.

    I can (just barely) accept NPTv6 as a like subnet-for-subnet mapping that does not harm L4, but that’s still glossing over a political issue. IPv6 gave network engineers real choices in numbers and administering their networks, and while some will squander it, I will be encouraging people to not let that happen.


  • The case "eBay Domestic Holdings, Inc. v. Craig Newmark, et al." in Delaware’s Court of Chancery does not support the assertion at all. What the two corporate officers did wrong was to dilute a minority stakeholder’s shares for an impermissible reason under Delaware law. One permissible reason to justify such dilution would be if the change was “reasonable to promote shareholder value” (page 49). The two officers could not prove that their actions were reasonable, nor could they prove any other permissible reason, so they lost the case.

    At bottom, the major question in that case was whether the corporate officers can conspire with the majority stakeholders to harm a minority stakeholder. It was about two corporate officers that were acting out of self preservation (page 59):

    Jim and Craig simply disliked the possibility that he Grim Reaper someday will catch up with them and that a company like eBay might, in the future, purchase a controlling interest in craigslist.

    The minor question (whether shareholder value would be promoted) could have been answered in the affirmative and those two would still have lost the case, because Delaware law also doesn’t allow harming a stakeholder, violating their fiduciary duty to eBay in this case (page 61):

    If Jim and Craig were the only stockholders affected by their decisions, then there would be no one to object. eBay, however, holds a significant stake in craigslist, and Jim and Craig’s actions affect others besides themselves.

    The court only looked at the minor question to appeal-proof the ruling, because the two corporate officers had tried to match their argument to an earlier DE Supreme Court ruling.

    For the purposes of my point in this discussion, the distinction doesn’t matter.

    I disagree. Drawing the correct conclusion from the wrong cause is pure sophistry (ie “arbitrary, inauthentic, or deceptive styles of reasoning” -Wikipedia). It is intellectually dishonest to state a conclusion but then decline to support your basis, dismiss your own basis as irrelevant, and then circularly assert that the conclusion stands on its own.


  • I can agree that corporations are immoral, but no one has ever offered a citation for “legally required to maximize profit”. Many corporations have failed in spectacular fashion and yet where are the lawsuits or criminal prosecutions for leaders that fail this supposed obligation?

    What does exist is the fiduciary duty to be frank with shareholders, and many corporate officers have been sued for lying by omission. I believe that a corporate officer can choose to prioritize something else besides profit/value, so long as they inform the shareholders. In turn, the shareholders can fire the officer and replace them.

    It’s no surprise that most officers won’t stick out their neck for non-financial causes, but let’s be honest if it’s simply self preservation rather than some oft-cited but wrong assertion of the law.






  • The CS job market is very location specific, so I don’t have much advice in that regard.

    I’ve got quite a bit of experience with Linux and I manage a home server, but that probably doesn’t differentiate me much.

    That said, I have been on my company’s rotating interview panel for about a decade now, and while my company’s line of work involves a lot of Linux development, I can say that most of our college hires do not possess very much Linux background at all. Sure, they might have used Linux machines for school projects, but rarely do any of them assert to be “experienced” with Linux.

    By that, I mean deeper knowledge than just using Bash. If a candidate can tell me why they prefer csh over Bash, or any syntax difference between POSIX sh compared to Bash, that is definitely a distinguishing quality. It speaks of an operator who has enough usage under their belt that they’re annoyed by the typical distro’s defaults, and more importantly, assessed the available tools, and picked the right tool that works for them.

    I cannot understate how valuable it is to us to find a candidate that understands their tooling, especially right out of college. Considering that we assume most new hires have to be brought up to speed over the first few months, a candidate that saves us that effort is at least one rank above their peers.

    Deeper functional knowledge comes in other forms as well. It’s one thing to know how a C program’s main() function is invoked by an OS, but anything which shows a fuller understanding of, say, system architecture and how a timer interrupt leads to a context switch in an assembly ISR, to a returned service call to load an ELF, to a CPU privilege ring change, to crt0, to main(), that is another level entirely.

    I’ve interviewed candidates that had side projects involving retro game disassembly. So maybe they couldn’t give me the above level of detail for x86, they could describe the same for MIPS. And that’s good enough, because most architectures do roughly the same thing, with a few different semantics and names.

    Circling back to managing a server, if you had to deal with PAM, NAT and port forwarding, tunnels and VPNs, compiling from source, or abything like that which is non-trivial, do not sell yourself short. All that stuff is resume material, because if you can relay to an interviewer that you’ve dealt with real network or machine security tasks, it is distinguishing.

    The best part is that you have all of college to learn the CS curriculum, but it’s also time that you have to pursue any particular focus that excites you. I’ve written earlier about how embedded engineers don’t really get caught in the hype cycle, so jobs don’t suddenly appear then disappear a few years later. If you wanted to do that route, getting started with any microcontroller (eg Arduino, STM32) would help, with a goal to understand all the “magic” that the IDE and compiler are doing. Maybe instead you like das blinkenlights and find yourself drawn to hardware design. It wouldn’t be too late to consider a switch to the Computer Engineer (CE) major, so you have a small taste of the EE life.

    CS as a field is so large that there are many routes between “I want to work with computers” to a declared major and to a career thereafter. Fortunately, time is on your side; this would be a very different conversation if you were a 4th year college student.



  • IIRC, the IAU’s definition of planet – infamously applied so that Pluto fell off the list of Solar System planets – requires that a candidate planet be large enough that its own gravity is strong enough to force it into a rough sphere, whatever it might be made of.

    So a disc-shaped planet could not ever meet this criteria, because if it were made of something strong enough to remain a disk, then it’s too small to be a planet. And if it did exceed the critical size for gravity to make a sphere, then it wouldn’t be disc shaped anymore.

    But setting that definitional quibble aside, we will focus on sizes and materials that allow a disk shape object to exist and be large enough for humans (or Mario) to visit. So no Wensleydale cheese. If we say that this object is mostly uniform in its mass distribution, then it would have to be the case that for any disc shape (including cylindrical), different points along the surface will be farther or closer to the center of gravity. Thus, inhabitants would experience gravity differently depending on where they are.

    Note that we haven’t even considered whether the disc is rotating. If it is, then there’s a chance that the centrifugal acceleration at some points will completely negate the gravitational acceleration. At such points, one could hop up and off the surface, linger for a bit, and then get pulled back down once the disc has rotated to a position where there’s a net force upon you again. Or if the centrifugal acceleration is too strong, it might repel visitors on the surface altogether.

    Alternatively, there would be a danger of playing on a trampoline that accidentally crosses into a net-zero gravity region. Here, a double bounce could send someone very high up, only to then plummet back down to their death when re-entering a downward gravity zone.

    I have almost no citations for the above, but I thank you for posing an interesting question.



  • I agree that RPM isn’t the primary quality to assess here, but I think angular momentum doesn’t really matter either. As a quantity, momentum describes a conserved capacity to store kinetic energy. As in, it could tell us how long the fan would stay in motion when the wind stops blowing. But that’s not the objective for a wind turbine, which is supposed to convert lift from the wind to do some work.

    At bottom, none of these quantities are the useful metric for what makes a good wind turbine. And that’s expected, because we have few details about the fan itself: the blade pitch, stall speed, and fan diameter, to list a few parameters. The only firm detail we can see is the blade count from the picture.



  • I’m more in the software side of things, but have worked with hardware engineers that use formal verification before committing to a design. How I understand the point of formal verification is to answer the question: does this implementation satisfy the given specification?

    With that in mind, I’m having trouble squaring away my definition with your passage:

    I can imagine a scenario where you no longer review the code but a simulation of all the behaviours of the system, perhaps before any code has been written, and then you can trust the output will have accordingly …?

    The whole point, I think, of formal verification is to verify a specific, concrete thing. Simulation doesn’t seem to be remotely relevant at all, because it is not the thing itself. C’est nest pas une pipe. Likewise, formal verification isn’t about stress testing either, such as hardware shock and vibration testing. At bottom, formal is about reducing the thing to its most basic assumptions, and checking those.

    If those assumptions turn out to violate the specification, then that answers the question posed earlier. If however the formal process proves that a specific signal within an FPGA will never take longer than 47 ns and another signal always takes longer than 68 ns, then it’s provable that those two signals will not cause a race condition when they come together. And this too answers the question.

    Given that formal verification is rooted in mathematical proofs, I don’t see how LLMs can help there. In terms if making formal easier to use regarding inputs and outputs, LLMs are still a poor fit. To trust an LLM to write or even audit the specification that will be inputted to formal verification, that’s adding a very weak link at the very start of a very robust process, essentially negating all the guarantees of formal verification.

    As for the output side, I’m not seeing how a yes/no answer from formal could somehow benefit from the mis-confident elaborations of an LLM. Perhaps in the case of a failure result, an LLM can hone in on the exact hardware or software component that the spec violation is occurring. But my understanding is that formal verification software already does that, because that’s the obvious thing to identify once an implementation is proven as faulty.

    What practical limits of formal verification are there for this?

    Formal verification definitely has limits, and one of the greatest limiting factors for its use in the software domain is the fact that compatible software (meaning it can target many platforms, OS, phones, etc) is an utter mindfield to prove correctness for. Just look at memory ordering: x86 and ARM, in the desktop and mobile spaces respectively, behave very different, yet an ideal formal verification would tell us if a race condition could ever arise. We don’t have that today, because the test matrix to verify is outside the limits of our computational power, for any nontrivial example.

    Adding AI in any current form – and maybe any future form too – will not change this gap in what can be achieved by raw logic and induction. Formal is simply unbothered by LLMs, neither helped nor hindered.