HN user

mitchs

221 karma
Posts0
Comments44
View on HN
No posts found.

The most fun I've had with strace was debugging a 3-process deadlock. An snmp daemon was blocked waiting for a cli child process to finish, the cli was waiting for a response to a message on a socket it had open with a routing protocol daemon, which was waiting for a response from the snmp daemon.

It is also a great way to figure out why programs without useful debug output die. Ie. after a program opens and reads a config file it doesn't like, it starts cleaning up and exits.

The doubling of J as a means of striding across the array also gives me some concern. While it is cache related, it is cache related for sneaky reasons. J is going to end up, in binary, with a ton of 0s at the end after being doubled over and over. After 6 iterations after each reset, the position within the cache line is guaranteed to be 0. Using the standard 32K of L1 D$ would be 512x64 byte lines. Assuming 8-way associative (decently common as far as I know) means these 512 lines are organized into 64 set indexes, each with 8 lines. So after the next 6 post-reset iterations you are guaranteed to only be hitting the 0th index into the cache, effectively reducing the L1 cache size to 8 lines.

(edit: Not the 0th index, but the same index as the base of the array.)

The important part is it safely allows you to pass references or other objects with lifetimes to those threads. (Or at least lets the compiler know so you can avoid having to write unsafe things yourself.)

This happened to be useful for something I was doing at work where the wrapper for a native C library expressed the required lifetimes of the library constructs using lifetimes. (Eg. You must set up Foo before Bar, and Foo must outlive Bar. It was OK to pass Bar and use it from multiple threads, but it had a lifetime attached. Using scoped threads we can satisfy the compiler's lifetime checker, since it knows even though we gave Bar to many threads, none of them outlive Foo.)

The big issue with v6 is you don't know what every ISP is doing with their IP space. The current RIPE recommendation is to delegate somewhere between a /48 to a /56 to every customer. Some ISPs might only delegate a 64, and perhaps typical home wifi setup may only use a single /64. For data aggregation maybe the error is ok, but I've wondered about what IP banning/filtering looks like for v6. Assume everyone gets a /64 and most cats will have 256 lives, and sometimes 16384. Assume everyone has anything larger than a 64, and you may block 255+ other people with the intended target.

Neat. I had made something similar for work a while back, but as a LD_PRELOAD library that intercepted calls to malloc and friends. It would add extra space to every allocation so it could add a pointer at the end that would point into a leaf node of a call graph backtrace tree it maintained. Each node in the tree had lifetime allocated/freed block counts and bytes by code site. The cool part about it was that it barely affected the performance of the application.

It made its own socket and thread to listen on it. It would just dump a snapshot of tree to anything that connected. I also had some tooling that would let you diff two snapshots, since it was helpful to see if particular stimuli cause persistent extra allocations. While finding the largest outstanding delta between allocated and free bytes was great for finding leaks, sorting by lifetime count of blocks allocated was also fun. I remember some little puzzle game I enjoyed playing at the time would allocate and free tens of thousands of blocks as you dragged a line around for a second.

There was a tricky chicken and egg problems with LD_PRELOAD wrapping one of the allocation functions, because it was used internally by dlsym, which I was using to retrieve pointers to the proper function implementations. (calloc if I recall correctly.) I hacked around it by making my library allocate bytes out of a static char array for the calloc call that would happen while dlsym-ing for calloc. Debugging this was a nightmare, since it would break so early in the process's lifetime that GDB breakpoints weren't functioning. Tracking in a second process seems like a way simpler idea, and probably doesn't have too much of an impact on performance.

I don't like the idea of using caps lock frequently as a modifier. To me a frequently used modifier should either be on a thumb or on the opposite hand.

I recently started trying to learn a one handed layout to give my injured right wrist some rest and have been reasonably happy with the space bar doing double duty. (Tap is space and hold is flip.) Though this isn't something that most keyboards can be configured to do.

So far I'd say the flip style is OKish to learn, but I'm still at a tiny fraction of my normal speed. It will take a lot of dedicated practice for me to be anywhere near as fast.

"all observable behaviors of your system will be depended on by somebody"

Ugh, a former team I was on had that to the extreme. We were customizing open source software for internal use. A lot of operators had (over years) developed scripts that would just SSH in and use a CLI to interact with the software, using regex to parse output. We once thought we were safe adding a new line to the output rather than modifying an existing output line. Nope, someone somewhere used a multi-line regex.

Kicking everyone's automation out of the shells of those boxes was a multi-year project that is, as far as I know, still ongoing.

It depends on the context. Not every bgp speaker needs the full internet table and frequent route changes. If you use the network to balance traffic across servers, you just need a bgp speaker on a server to inject a few routes for the ip addresses it will handle. In that case a good api outweighs performance.

Eh, I think of the menu of options, taking out Starlink in Europe with a DDOS has a high probability of providing value for Russia and is safer to execute compared with the theoretical attack of getting locations out of a starlink ground station. Even if they managed to gain access to the ground stations, they would then need to wade through a proprietary stack and hope that what they have access to actually has useful location data. SpaceX apparently operates on cells that are "5 miles in radius" hexagons, though people on reddit claim to get service up to 15 miles away from home. In any case, I could see a world where the ground station only knew what one of those cells a person was in, and the whole exercise of breaking into a ground station would have been for nothing.

Anyone with typescript code that references the non-optional field will get type errors if it is made optional. Though stuffing the string with the v6 subnet wouldn't be the worst thing in the world. Any code that is blindly using it expecting v4 addresses will already be broken if a v6 only subnet is passed in.

I wonder how long it will take for CDK to support this stuff. I'm not sure how they will back themselves out of the corner of subnets having a required ipv4 CIDR property.

BGP is spoken between networks. There are a lesser known "IGP" protocols stitching together the insides of those networks. IS-IS and OSPF being the most notable. Though the nature of the beast is that when you screw up BGP everyone sees it, and when you screw up your IGP it could just look like servers or load balancers having a bad day. Though if a telco messes them up everyone notices.

Or just cast the pointer to uint##_t and use be##toh and htobe## from <endian.h>? I think this is making a mountain out of a mole hill. I've spent tons of time doing wire (de)serialization in C for network protocols and endian swaps are far from the most pressing issue I see. The big problem imo is the unsafe practices around buffer handling allowing buffer over runs.

Refresh, as in transitioning from one image to another on the display. Partial refresh as in not running the waveform on pixels that don't change color, which dramatically reduces the visual noise for the user. The problem with partial refreshes is the accumulated errors on pixels, and the effects of updating a pixel on the neighboring pixels. The longer you go between full refreshes, the more ghosted cruft you end up with on screen.

There is a waveform that specifically maintains image quality over many partial refreshes. (Interestingly it only works for black text on white backgrounds, and not the other way around, though I'd hope they would have fixed that by now.) It required quite a bit of pre-processing before you slam the frame buffers into the hardware. That logic came to us as a pre-baked kernel module from our hardware vendor, and EIH did not want us to know what was in it, though it wasn't too hard for us to figure out what it did.

And, to some extent, you can just say screw them, I'm making my own waveforms. However, a junk waveform can damage the display if they aren't correctly built to prevent static charge build up. Also, each batch of displays comes out different enough that EIH provides slightly tuned versions of the waveform on a per batch basis. I'm not sure how well the open source model will work when people don't have equivalent hardware. If someone is tuning the waveforms for their panel, that may not work for all users.

The static build up is interesting. I've seen pictures return to the display minutes after it was cleared to white because the charge built up on the display was still affecting the pigments. Never seen a display break due to it, but it was described to us as a theoretical possibility if a waveform wasn't roughly balanced in its actions.

Do I get my nerd cred now? Have I satisfied you, all knowing hacker news poster?

From what I've seen working on an e-reader, a big problem for any open source e ink product is the things EIH wants to keep secret about their displays. If you want to use the nice partial refresh waveform, the open source aspect of this is going to run face first into secrecy requirements. The company selling you the display controller may be willing to build you an out of tree kernel module, and you can totally figure out what it does, but it won't be open source at that point.

I was initially troubled by the booting of Parler, but I've come around to seeing AWS's position as similar to the payment processors who don't want to deal with porn sites. Doing business with some clients creates risks. Traditional players don't want to deal with risky clients, but there are specialized services who are willing to take them. However, they are more expensive for the same nominal service (because of the risks.) While the payment processors are dealing with frequent charge-backs, the risks I'd see in hosting Parler are more about liability and litigation.

There are clearly hosting providers (like Epik) who would be willing to take them on as clients from the start. If you read AWS's acceptable use policy, and then read the Parler's TOS, it is clear AWS was a terrible match as a hosting provider. By my read, AWS doesn't want to deal with anything that can be construed as "harmful" where Parler only forbade directly illegal behavior. (And it is apparent they barely felt a responsibility to moderate even to that level.) This was never going to work. Jan 6 brought things to a head, but as I see it, this business relationship was doomed from the start.

(I work for Amazon, these opinions are my own.)

They need to be capturing src/dest IPs as well as ports for AT&T to have any hope of using that data.

Edit to make the comment more useful: If anyone is curious, look up "ECMP hashing." There are probably tons of parallel paths through AT&T's network, and to narrow down to the hardware causing problems, they will need to identify which specific path was chosen. Hardware switches packets out equally viable pathways by hashing some of the attributes of the packet. Hash output % number of pathways selects which pathway at every hop.

Hardware does this because everyone wants all packets involved in the same "flow" (all packets with the same src/dest IP and port and protocol (TCP)) to deterministically go through the same set of pipes to avoid packet re-ordering. If you randomly sprayed packets, the various buffer depths of routers (or even speed of light and slightly different length fibers along the way) could cause packets to swap ordering. While TCP "copes" with reordering, it doesn't like it and and older implementations slowed way down when it happened.

Unfortunately TCP checksums are hot garbage given switch ASIC design. They are a 16 bit one's complement sum over a packet. If you get two bit flips in the same offset % 16, you can pass a checksum.

The problem is routers slow down the high speed serial signals from fiber to by splitting the bits over a large number of slower speed signals internally. Often those wider busses are a multiple of 16 bits. For example, one ASIC I know of moves things around in 204 byte chunks. (Might have been 208, been a while.) Anyway, the problem is that if there is a defect in one of those parallel elements it will always flip bits in the same offset position mod 204 bytes, which is the same position mod 16 bits. If the hardware is degraded enough, it can end up flipping two bits in the same position, and that has a fairly good chance of passing the checksum.

Ethernet has proper CRCs on packets, which is a lot less vulnerable to shenanigans like this, but unfortunately those can end up being checked on the way in, discarded, and then re-generated on the way out of a router. If anything is corrupted in the middle of the switch ASIC, nothing notices and it passes along. I once helped troubleshoot an issue in our network where a BGP packet was corrupted in this way. The flipped bits ended up causing a more specific route to be generated, and we had the world weirdest BGP route hijack within the bounds of our own data center.

Something I see as wrong with C outside of the context of the Linux kernel is mostly something wrong with us the developers. We are far too content to live in filth.

In addition to unsafe/irregular buffer handling, I also constantly see poor data structure choice, presumably due to a lack of default choice of library. It is very common to see code scanning linked lists when they should be doing map look ups. (And often even the linked list operations are ad-hoc and repeated for every type of struct with an embedded next/prev pointer.) Everyone always defaults to linked listing it up because they never have to pay the up-front cost of finding a library or investing in re-inventing the wheel. I think this is also why you see so much sketchy buffer code - no one has bothered investing in safer buffer abstractions.

Perhaps some of this is caused by the difficulty of taking on dependencies in a portable way. (CMake/Autotools can make this better, but it is a far cry from NPM.)

For labbing with quagga you can get pretty far with Linux containers to emulate multiple routers on a single host. (I've used both lxc and docker to manage containers.) You can create virtual ethernet device pairs (ip link add veth0 type veth peer name veth1) , and drop either end into running containers (ip link set veth0 netns <container process ID>.) Make sure to turn on the ip forwarding sysctls inside the containers and Linux will behave quite nicely as a virtual router.

Also, consider consider upgrading to the more active fork called Free Range Routing.

BGP operates as a rumor mill. Convergence is the process of all of the rumors settling into a steady state. The rumors are of the form "I can reach this range of IP addresses by going through this path of networks." Networks will refuse to listen to rumors that have themselves in the path, as that would cause traffic to loop.

For each IP range described in the rumor table, each network is free to choose whichever rumor they like best among all they have heard, and send traffic for that range along the described path. Typically this is the shortest, but it doesn't have to be.

ISPs will pass on their favorite rumor for each range, adding themselves to the path of networks. (They must also withdraw the rumors if they become disconnected from their upstream source, or their upstream withdraws it.) Business like hosting providers won't pass on any rumors other than those they started, as no one involved wants them to be a path between the ISPs. (Most ISPs will generally restrict the kinds of rumors their non ISP peers can spread, usually in terms of what IP ranges the peer owns.)

Convergence in BGP is easy in the "good news" direction, and a clusterfuck in the "bad news" direction. When a new range is advertised, or the path is getting shorter, it is smooth sailing, as each network more or less just takes the new route as is and passes it on without hesitation. In the bad news direction, where either something is getting retracted entirely, or the path is going to get much longer, we get something called "path hunting."

As an example of path hunting: Lets say the old paths for a rumor were A-B-C and A-B-D, but C is also connected to D. (C and D spread rumors to each other, but the extended paths A-B-C-D and A-B-D-C are longer, thus not used yet.) A-B gets cut. B tells both C and D that it is withdrawing the rumor. Simultaneously D looks at the rumor A-B-C-D and C looks at the rumor A-B-D-C, and say "well I've got this slightly worse path lying around, might as well use it." Then they spread that rumor to their down streams not realizing that it is vulnerable to the same event that cost them the more direct route. (They have no idea why B withdraw the rumor from them.) The paths, especially when removing an IP range entirely, can get really crazy. (A lot of core internet infrastructure uses delays to prevent the same IP range from updating too often, which tamps down on the crazy path exploration and can actually speed things up in these cases.)

Something worth knowing: TCP checksums should not be relied upon. If you aren't using TLS, your application needs to do its own checksums. A 16 bit 1's complement sum over a packet is not sufficient, especially given modern switch ASIC design. They take really fast signals off the fiber and turn them into slow moving, parallel signals within the ASIC. Often these signal buses are nice even numbers of bytes wide, 204 in this example. When there is something flawed in the chip in the slower moving internal pipeline, it will hit the same bit position every 204 bytes. If it is borked enough to flip two bits within the packet, those flips will be in the same bit position a multiple of 204 bytes away, meaning the same bit position in the 1's complement checksum. If one flips up, and the other flips down, it passes! In my case it ended up corrupting data in a BGP session's TCP stream, executing the world's most confusing route hijack in our network.

Heh, std::new was some cruft I got out of backtrace(3) with some wacky embedded tool chain.

Are these gains supposed to be from inlining the top level function of malloc into new? Compared to the costs of what can go on inside malloc... Is that the biggest problem?