Projects

Step-By-Step Setting Up Networking for Virtualization on OpenShift 4.19 for a Homelab

As we continue our Openshift journey to get virtualization working, we have a vanilla node already setup and now we need to get the networking configured. The examples here are from Openshift 4.19.17.

Networking in OpenShift is conceptually two parts that connect. The first part is the host level networking; this is your CoreOS OpenShift host itself. Then there is how do the pods connect into that networking. Usually, the network connects through your network interface card (NIC), to the Container Networking Interface (CNI), then to your pod. Here we will be using a meta plugin that connects between the NIC and the CNI called Multus. Redhat has a good post about it.

Host Level Networking

This part of the networking stack is straight forward if you are used to Linux system networking, and it is setup the same way. Treat the CoreOS node like any other Linux system. The big decision to make in the beginning is how many interfaces you will have.

Networking diagram without sub interface

If you have 1 interface and plan on using virtualization, are you going to use VLANs? If so, then you may want to move the IP of the interface off of the primary interface and onto a VLAN sub interface. This moves the traffic from untagged to tagged traffic for your network infrastructure.

Another reason is there are bugs in the Mellanox firmware, mlx5e, where Mellanox 4 and 5 cards can think you are double VLAN encapsulating, and will start automatically stripping VLAN tags. The solution is to move all traffic to sub interfaces. You will get an error in your dmesg/journalctl of: mlx5e_fs_set_rx_mode_work:843:(pid 146): S-tagged traffic will be dropped while C-tag vlan stripping is enabled

With the interface moved, that frees us up to use it for other VLANs as well. If you deployed network settings via a MachineConfig, you would have to override them there.

Networking diagram with sub interface

The rest of the configuration will be done via the NMState Operator and native Openshift.

NMState VLAN and Linux Bridge Setup

NMState is a Network Manager policy system. It allows you to set policies like you would in Windows Group Policy, or Puppet to tell each host how the network should be configured. You can filter down to specific hosts (I do that for testing, to only apply to 1 host) or deploy rules for your whole fleet assuming nodes are all configured the same way. It’s possible to use tags on your hosts to specify which rules go to which hosts.

NMState can also be used to configure port bonding and other network configurations you may need. After configuration, you get a screen that tells you the state of that policy on all the servers it applies to. Each policy sets one or more Network Manager configurations, if you have multiple NICs and want to configure all of them, you can do them in one policy, but it may be worth breaking the policies apart and having more granularity.

Another way to go about this section, is to SSH into each node, and use a tool such as nmtui to manually set the networking. I like NMState because I get a screen that shows all my networking is set correctly on each node, and updates to make sure it stays that way. I put an example below of setting up port bonding.

  • Go to the OpenShift web console, if you need to setup OpenShift I suggest checking out either my SNO guide or HA Guide.
  • Click Operators -> OperatorHub.
  • Once installed, you will need to create an “instance” of NMState for it to activate.
  • Then there will be new options under the Networking section on the left. We want NodeNetworkConfigurationPolicy. Here we create policies of how networking should be configured per host. This is like Group Policy or Puppet configurations.
  • At the NodeNetworkConfigurationPolicy screen, click “Create” -> “With YAML”.
  • We need to create a new sub-interface off of our eno1 main interface for our new vlan, then we need to create a Linux Bridge off that interface for our VMs to attach to.
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
  name: vlan19-with-bridge           <-- Change This
spec:
  desiredState:
    interfaces:
      - name: eno1.19             <-- Change This
        type: vlan
        state: up
        ipv4:
          enabled: false
        vlan:
          base-iface: eno1
          id: 19                     <-- Change This
      - name: br19                   <-- Change This
        type: linux-bridge
        state: up
        ipv4:
          enabled: false
        bridge:
          options:
            stp:
              enabled: false
          port:
            - name: eno1.19       <-- Change This
              vlan: {}
  • Important things here:
    • Change the 19s to whichever VLAN ID you want to use.
    • “ipv4: enabled: false” says we want an interface here, but we are not giving it host level IP networking on our OpenShift node.
    • Remove the <– Change This comments
    • You MUST leave the “vlan: {}” at the end or it will not work, adding this tells it to leave vlan data how it is because we are processing via the kernel via sub interfaces.

Now we have this configuration, with a secondary interface off of our NIC, and an internal Linux Bridge for the VMs.

The great thing about doing this configuration via NMState, it applies to all your nodes unless you put a filter in, and you get a centralized status about if each node could deploy the config.

Here is an example from my Homelab, with slightly different VLAN IDs than we have been discussing. You can see all three nodes have successfully taken the configuration.

OpenShift VM Network Configuration

Kubernetes and OpenShift use Network Attachment Definitions (NADs) to configure rules of how pods can connect to host level networking or to the CNI. We have created the VLANs and Bridges we need on our host system, now we need to create Network Attachment Definitions to allow our VMs or other pods to attach to the Bridges.

  • Go to “Networking” -> “NetworkAttachmentDefinitions”.
  • Click “Create NetworkAttachmentDefinition”
  • This is easily done, and can be done via the interface or via YAML, first we will do via the UI then YAML.
  • Before entering the name, make sure you are in the Project / Namespace you want to be in, NADs are Project / Namespace locked. This is nice because you can have different projects for different groups to have VMs and limit which networks they can go to.
  • Name: This is what the VM Operator will select, make it easy to understand, I do “vlan#-purpose“, example: “vlan2-workstations”.
  • Network Type: Linux Bridge.
  • Bridge Name: what was set above, in that example “br19“, no quotes.
  • VLAN tag number: Leave this blank, we are processing VLAN data at the kernel level not overlay.
  • MAC spoof check: Do you want the MAC addresses checked on the line. This is a feature which allows the network admin to pin certain MAC addresses and only send traffic out to those allowed. I usually turn this off.
  • Click “Create

The alternative way to do a NAD is via YAML, here is an example block:

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: vlan19-data-integration
  namespace: default
spec:
  config: |-
    {
        "cniVersion": "0.3.1",
        "name": "vlan19-data-integration",
        "type": "bridge",
        "bridge": "br19",
        "ipam": {},
        "macspoofchk": false,
        "preserveDefaultVlan": false
    }

You can verify the NAD was created successfully by checking the NetworkAttachmentDefinitions list. Your networking is ready now. Next post, we will discuss getting storage setup.

Additional NodeNetworkConfigurationPolicy YAMLs

NIC Bonding / Teaming

Use mode 4 (802.3ad/LACP) if your switch supports link aggregation; otherwise mode 1 (active-backup) is the safest fallback.

apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
  name: bond0-config
spec:
  desiredState:
    interfaces:
      - name: bond0
        type: bond
        state: up
        ipv4:
          enabled: false
        link-aggregation:
          # mode=1 active-backup
          # mode=2 balance-xor
          # mode=4 802.3ad
          # mode=5 balance-tlb
          # mode=6 balance-alb
          mode: 802.3ad
          options:
            miimon: '140'
          port:
            - eno1
            - eno2

Useful Links

https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/how-to-use.md

https://medium.com/@tcij1013/how-to-configure-bonded-vlan-interfaces-in-openshift-4-18-0bcc22f71200

Manually Flashing a AsRock BIOS

At the start of 2022 I went about building a new desktop. The system came out well in the end, and I am still using it although it has always had one issue that I mentioned back then… When the system tries to reboot it shuts down Windows, then the fans spin up, and it never resets the CPU. I always assumed this was due to the fact: mistakes were made and when I needed a BIOS update to support the AMD Ryzen 5800X on that motherboard, I flashed the X570 Pro4, NOT X570M Pro4 BIOS. I decided the time had come to fix this and flash the board back to the proper BIOS.

Note: I will use BIOS and UEFI interchangeably here, I know they are technically different.

AsRock gives out the BIOS updates, and you are supposed to load them on a USB drive and select the “Instant Flash” utility in the UEFI menu. The issue is the system thinks it’s a X570 Pro4 (not M), and refuses to flash to the M variant. I saw some people on the internet mention you can use the “AMIBIOS and Aptio AMI Firmware Update Utility” utility to force a BIOS flash on the system and get around this. I did that, and then… the system never booted again… I don’t know what went wrong, or if the utility flashed everything correctly, but I couldn’t get the system to boot.

This led me to another rabbit hole, flashing your bios with an EEPROM writer. There are several to choose from, and of course I got both. The CH341A, and T48 TL866-3G programmers. I tried for a while to get the CH341A to work, and it may have in the end, but I had a better time with the TL866 software of XgPro.

I unplugged everything and took out the BIOS battery. At first, I tried to use some of the tools that came with the flashers to grab the chip on the motherboard. Here was the first hurtle, the chip was a surface mount part that made it very difficult to connect to and every time I tried to read the chip I got an error. Then I found this post, https://www.reddit.com/r/ASRock/comments/1cz1bcz/guide_asrock_spi_tpm_j1_bios_ph_pinout_for_ch341a/, which mentioned the SPI_TPM_J1 header on the motherboard actually hooked directly to all those pins and could be used to flash the chip much easier.

Pinout from Reddit

This diagram was the key to getting it working, which pins went to where on the motherboard.

Connecting to the pins proved to be a bit difficult because of how small they were. Turns out they are 2mm pitch instead of 2.54mm (more standard), so I had to order https://www.amazon.com/dp/B07FKLKM7L as one of the commenters suggested to be able to connect easily to the pins. Then I did some janky stuff with jumper wires to get it into the TL866 programmer.

The programmer also uses Windows-only software, and I was on my Linux laptop. I installed a Windows 11 VM and forwarded the USB device to use the software. The Reddit post mentioned that they had a similar motherboard and needing to use the 1.8V adapter for their Winbond W25Q256JW BIOS chip. I assumed the same but when I went to read the bad BIOS back, I was given “ID Check Failed 0xC2 25 39”. Which turns out to be a 3.3V Macronix MX25L256, with Claude assuming it’s a MX25L25673G. I pulled out the 1.8V adapter and hooked right to the chip. I still failed to get an ID with the built in tool, and when I forced the chip type, I was told one pin wasn’t connected right. I adjusted the pin and hit READ again and got a hit, the ID didn’t match the software’s record for that chip type. I ended up disabling ID Check and then doing a read. AND I GOT DATA! This showed my wiring was good enough.

From there I went and got a new BIOS from AsRocks site. Seeing the BIOS file was exactly 32MB, and the BIOS was 256 megabits = 32MB, I felt confident that I could write this whole image and it didn’t have a header or something that would break directly writing this image to the chip.

I hit program and crossed my fingers. After a minute of erasing, then a minute of programming and verifying it said it was done. I unplugged my laptop, and plugged power back in. The system came on when I hit power, but again no POST. Then I waited a minute, and it powered off, this time, when I powered it back on the system came to life with the AsRock UEFI screen! I had to re-enter UEFI settings but we are back!

The last and final irony… on the correct BIOS, up to date, the system still fails to restart…

Mellanox Driver Ignoring Vlans

Recently I spend more hours than I want to talk about fixing a server that had a Mellanox ConnectX6-lx card, where I could not get Openshift to get traffic to VMs. I was creating bridges just like I normally do, and traffic was working to the main interface. After a lot of trial and error I wanted to make a quick post in case anyone runs into this.

All of this assumes a trunk port to an interface on Linux (or a bonded interface). If you have an interface in Linux on the native vlan, and that is a standard interface (example eno1). Then you add a sub interface for tagged traffic, eno1.10, the Mellanox mlx5 driver will – in hardware -ignore your vlan tag and just send traffic to the main interface.

One way to see if your card is doing this is search dmesg for “mlx5”: dmesg | grep mlx5, you may see the following:

mlx5_core 0000:0b:00.1: mlx5e_fs_set_rx_mode_work:843:(pid 156): S-tagged traffic will be dropped while C-tag vlan stripping is enabled

(https://github.com/oracle/linux-uek/issues/20)

The Mellanox card is worried about double tagged packets and will drop tags on data coming in. It does this in hardware. You can see the settings for 8021Q kernel module being loaded, and vlan filtering is disabled, but this wont matter. If you change settings like ethtool -K <interface> rx-vlan-offload off it will say the setting is off, but the underlying driver loaded this at init time, and then the settings you set will be ignored. The only way I found to fix it is to move all the IPed interfaces off the main interface.

Once you move the IPed interface under its own sub interface and reboot, data will start flowing to your VMs.

Homelab Dial-Up Networking for Retro Computing

I started mentioning about my LAN Before Time project before. The idea is to have a rack of the most diverse CPU, OS, and Networking technologies I can find. Each computer and piece of equipment bringing something new and unique to the collection. One part of this collection was the network. Coming from a networking background, I also wanted to have the most diverse set of networking technologies that I could. To do this I would need to find a core router that could talk all the different protocols I wanted. Having worked at Cisco in the past, I knew they had gear that went back in time, and could add in some additional fun like AppleTalk. That is where I started my search.

Why the Cisco 3825

I knew I needed a Router and not a switch, because we would be going between several protocols. I could time box the router a bit because I wanted to support AppleTalk and IPX. Support from these no longer exists, and thus would give a cutoff for devices I could get.

Years ago, I was the Cisco 7200 VXR guy at work. They were great routers, that could go up to gigabit and go in and out of a ton of different connections, including some voice ones. The issue was they could do lines like T1, but they couldn’t host an analog modem, and that was one thing I very much wanted.

Now we are getting down to a select group of Cisco devices. I started making a table of the pros and cons of each. I also was hoping for something slightly newer to have 1gb/s links available, and hoping that it wouldn’t use a 1000 watts at idle.

This is a table I made of all the different options for routers and the features they supported:

Model (U) Small Bays Large Bays Token Ring IPX / AppletalkDial-Up Base Speed EOL Date Flash
2513 (1) 10mb Before time Internal?
3640 (2)Y / Y100mb 2008-12-31 PCMCIA
3725 (2)Y / Y100mb 2012-03-31 CF
3745 (3)Y / Y100mb 2012-03-31 CF
3825 (2)Y / Y1000mb 2016-11-1 CF + USB 
3845 (3)Y / Y1000mb 2016-11-1 CF + USB 
3945 (3)N / N1000mb 2022-12-31  
7206XVR (3)Y / Y1000mb 2017-02-28? CF/PCMICA 

The Cisco 1800/2800/3800 line all came out around the same time, they were considered the G1 generation routers. Things before them were legacy, and the systems after them like the 3945 were the G2 devices. G2 was a step to get rid of legacy, this means dropping AppleTalk, IPX and some of the things I was interested in. By this point I had realistically narrowed down to a Cisco 3725 or 3825. The 3825 had gigabit on the main controller, allowing my to get a little closer to modern systems; that put me over the edge for it. I also was not interested in its giant cousin, the 3845; the 3825 had enough bays and should be quiet enough for me to run routinely.

Cisco 3825 Back

In searching for the voice features I wanted, I found I would need the Advanced Services image loaded, and that required a minimum of 512MB of memory. I ordered a system with Advanced Services and 1GB of memory, the max! When it came it had 256MB! I emailed the seller and he mailed me the proper 1GB of RAM. Once I installed it, the system would boot loop, I found one of the 2 sticks was bad. I ended up putting in one of the 512MB sticks he sent, and the 256MB one it came with for a total of 768MB of RAM.

Upgrading the Cisco 3825

Once I had the device on order, I started learning about the world of voice. I had not done much with voice before, there was a lot to learn. First, I needed to know which cards I would need. The 3825 can run older WIC cards, and the newer high speed HWIC cards. I needed analog modems, and to host those, I needed FX-S/FX-O cards. In learning about them: FX-S Foreign Exchange Station, FX-O Office. The office is for a branch office dialing OUT. You usually want FX-S because it provides a dial tone to dial into. S is to get a dial tone and you can call INTO. O is it receives a dial tone.

I got 4 FX-S Ports. One port is used to dial into, another to route the call out. I need more ports than you would think because of this. I got a CISCO VIC3-4FXS/DID, this gives 4 ports in/out. 2 CISCO WIC-1AM-V2, giving 2 modems I can dial into. There are cards that are 2 modems in one card, but they are rare and expensive. (I would get one later)

The system now has 768MB of memory, but I would also need PVDMs; Packet Voice Digital Signal Processor (DSP) Module (PVDM2). I had not worked with these before. They are ASICs that come process voice channels. They come in different numbers of channels, PVDM2-8, PVDM2-16, PVDM2-32, PVDM2-48, PVDM2-64. They were cheap, obviously I got 4 PVDM2-64 to go to 256 voice channels for $20 USD. The math is odd here, there are different complexity channels and some knock you down to 1/2 or less of the listed available channels. A “high complexity codec” can make an 8-channel card only handle 4 or less channels. Like I said, these were cheap, so I got 4 256-Channel cards. The cards go into slots that look like DIMMs.

I bought a T1 card because I thought it would be fun to eventually play with. Then I bought a CISCO NME-16ES-1G-P. This is a Cisco Switch as a card module. They are odd. It runs its own OS. It has an internal port to the main system, then to configure any of the 16 x 10/100mb/s or 1 x 1gb/s ports you run ‘service-module gigabitEthernet 2/0 session’ and it opens a serial connection into the controller of this switch. It has a separate login, configuration, and IOS version. At first, I had to password bypass it because someone had left a password on it. I have used it some, but not much. It needs a firmware update. This is my main source of ethernet ports for devices.

The last card I got is one of the main ones I wanted, a CISCO NM-1FE-1R-2W. This is a 1 FastEthernet (10/100), 1 Token Ring (DB9 or RJ45), and 2 WIC slots. I will do another post on Token Ring later.

Its worth mentioning, for the configuration and tests below, ports 0/0/0 – 3 are our 4FXS ports in HWIC slot 0. In HWIC1 slot (0/1/0 – 1) we have our dual modem card now, a WIC-2AM-v2.

Configuration

As mentioned, you do need a router with the Advanced Services image on it to do voice related features. Once that is loaded, and our hardware was in place, we started configuring the router to move voice data.

We need a pool of IPs that will be given out to clients as they dial in. To do this enter configuration mode and use:

ip local pool dialin-pool 192.168.9.10 192.168.9.20 recycle delay 3600 

You can tell from reading this blog that I have a way too complicated home network. I have the router itself on 192.168.7.0/24, then I made 192.168.9.0/24 for dial in addresses. To be able to send data to them and have them route on my core network, I have RIP running between my home firewall and this Cisco router. When I turn the router on, the routes pop up; when I stop using it for a while, the routes go away. You can set the start and stop of your pool to whatever you like.

dial-peer voice 3 pots 
 destination-pattern 3 
 port 0/0/3 

We need to say how the connection is handled once it comes in the modem. These connections are handled as “line” interfaces from there. We need to tell it this is a dial in line, what its max supported speed is (I just do the max, it will communicate less to the end modem), how flow control will work, and how auth will work.

The line configuration says it beeds ppp, since I do not specify the the auth system, any user is currently allowed… which is great!

line 0/1/0 
 modem Dialin 
 modem autoconfigure discovery 
 transport input all 
 autoselect ppp 
 stopbits 1 
 speed 115200 
 flowcontrol hardware 

Last, we need to configure the IP interface of this line, we do that by configuring the async line assigned to the modem port. This also is where we set which pool will be used for dial in users. I added the ppp timeout command because some of the older systems I have were taking a while to respond.

interface Async0/1/0 
 ip address 192.168.9.1 255.255.255.0 
 encapsulation ppp 
 peer default ip address pool dialin-pool
 async mode interactive 
 no keepalive 
 ppp timeout authentication 30

That is the key configuration needed to get dial up working! Below I will put my full config (minus password) in case any of it helps someone. Leave a comment if this helps you, or you need extra help!

Full Configuration

hostname router 
! 
boot-start-marker 
boot system flash:c3825-adventerprisek9-mz.151-4.M10.bin 
boot-end-marker 
! 
enable secret 0 test
! 
aaa new-model 
aaa authentication login default local line 
!
aaa session-id common 
no network-clock-participate slot 1 
dot11 syslog 
ip source-route 
ip cef 
! 
ip dhcp pool TOKEN 
 network 192.168.8.0 255.255.255.0 
 default-router 192.168.8.1 
 dns-server 192.168.7.1 
!
ip domain name lbt.home.ntbl.co 
no ipv6 cef 
!
multilink bundle-name authenticated 
voice-card 0 
crypto pki token default removal timeout 0 
username admin privilege 15 secret 0 admin
username test privilege 0 password 0 test 
!
redundancy 
!
ip ssh version 2 
!
interface GigabitEthernet0/0 
 ip address 192.168.7.10 255.255.255.0 
 duplex auto 
 speed auto 
 media-type rj45 
! 
interface GigabitEthernet0/1 
 no ip address 
 shutdown 
 duplex auto 
 speed auto 
 media-type rj45 
!
interface Serial0/3/0 
 no ip address 
 shutdown 
 clock rate 2000000 
! 
interface FastEthernet1/0 
 no ip address 
 shutdown 
 duplex auto 
 speed auto 
! 
interface TokenRing1/0 
 ip address 192.168.8.1 255.255.255.0 
 ring-speed 4 
! 
interface GigabitEthernet2/0 
 ip address 100.64.0.1 255.255.255.0 
!
interface Async0/1/0 
 ip address 192.168.9.1 255.255.255.0 
 encapsulation ppp 
 peer default ip address pool dialin-pool 
 async mode interactive 
 no keepalive 
 ppp timeout authentication 30 
!
interface Async0/1/1 
 no ip address 
 encapsulation slip 
! 
interface Async0/2/0 
 no ip address 
 encapsulation slip 
! 
interface Async1/0/0 
 no ip address 
 encapsulation slip 
! 
router rip
 network 100.0.0.0 
 network 192.168.7.0 
 network 192.168.9.0 
 neighbor 100.64.0.2 
 neighbor 192.168.7.1 
!
ip local pool dialin-pool 192.168.9.10 192.168.9.20 recycle delay 3600 
ip forward-protocol nd 
no ip http server 
no ip http secure-server 
! 
ip route 0.0.0.0 0.0.0.0 192.168.7.1 
!
control-plane
!
voice-port 0/0/0
!
voice-port 0/0/1
!
voice-port 0/0/2
! 
voice-port 0/0/3 
!
mgcp profile default 
! 
dial-peer voice 3 pots 
 destination-pattern 3 
 port 0/0/3 
!
telephony-service 
 max-conferences 12 gain -6 
 transfer-system full-consult 
!
line con 0 
line aux 0 
line 0/1/0 
 modem Dialin 
 modem autoconfigure discovery 
 transport input all 
 autoselect ppp 
 stopbits 1 
 speed 115200 
 flowcontrol hardware 
line 0/1/1 
 stopbits 1 
 speed 115200 
 flowcontrol hardware 
line 0/2/0 
 stopbits 1 
 speed 115200 
 flowcontrol hardware 
line 1/0/0 
 stopbits 1 
 speed 115200 
 flowcontrol hardware 
line 130 
 no activation-character 
 no exec 
 transport preferred none 
 transport input all 
 transport output lat pad telnet rlogin lapb-ta mop udptn v120 ssh 
line vty 0 4 
 transport input ssh 
!
scheduler allocate 20000 1000 
end 

The High Nibble Cromemco Z-1 Replica

The High Nibble is back with another fun retro computer kit. This one of the Cromemco Z-1. I reached out to the creator of the kit when it first went up, and he asked if I was sure I was interested. The kit is 99% the same as the IMSAI 8080, including most of the components except the acrylic panel and new firmware. The kits are so similar the PCB for the main board is the IMSAI 8080. I enjoyed the last one so much and wanted to support the creator (not to mention a new kit means more blinky lights on the shelf); thus, I ordered the new kit.

The kits are not cheap at $300, but come with everything you need, including a ready to go controller. The packaging is done well with individually slotted spots for each switch and IC in cardboard. The metal case is a nice touch. And just like before, the firmware is fantastic. You get a full web interface, external serial ports, the gorgeous front panel, and the system can update over the air update via Wi-Fi.

I won’t go too in-depth about the kit because it is so similar to the other one. The soldering is not too bad, the process starts with one small IC that has to be soldered in the front of the pcb, after that things like sockets and LEDs are easy, large, and straight forward.

I got a new soldering iron, the Pinecil from Pine64. This was my first project using it and I found it delightful. It’s smaller than my old iron, making it easier to handle. It’s advertised as a “smart” soldering iron which means when you put it down in a holder it quickly cools when not in use. A very nice safety feature.

The parts of the last build that were difficult are here too, having to put the system together as a sandwich of acrylic and circuit boards it’s a bit tricky, but once you get it in the right spot tightens up easily. Tape helped keep the build aligned during assembly.

The website for the project has a lot of good information, https://thehighnibble.com/cromemcoZ1/. There’s also a helpful YouTube video, same one as the IMSAI kit, that walks through the construction step-by-step.

The main step that gave me an issue was when you get to Testing, the LS2 light would not come on. After looking in the forums, https://github.com/orgs/thehighnibble/discussions/120, turns out that is a difference in the firmware, and it is not supposed to come on. With the video being for the other kit, it is not mentioned.

Overall, another great kit, and another fun system to add to the collection!

Dell 316SX (Intel 386) Restoration

I recently got around to restoring a Dell 316SX—my first childhood computer. It’s a 386SX that lived in my parents’ attic for decades, and reviving it was a journey full of debugging, power supply replacing, and data recovery.

Early Memories

This computer was the first computer I had growing up: a Dell 316SX, with a Intel 386SX. I remember being little and playing Sesame Street games on Prodigy on a parallel port dial up modem (I need to see if I can find that). Shout out to the people trying to bring Prodigy back, https://www.vintagecomputing.com/index.php/archives/1063/bringing-prodigy-back-from-the-dead. There is a photo of my mother pregnant with me, playing the original Sim City on this computer. I always knew I had this computer in my parents attic, and one day I would need to get it out to play with it. Now that I have a bit more space to work on these projects, I got that system (and an old 486DX2 that someone gave me well past its prime) to play with.

More will come of the 486 on here, but that one got going pretty easily and is my go to machine since it has 5.25″ floppy, 3.5″ floppy, a CD-ROM drive, and its hard drive died so I gave it an SD card reader. That makes the 486 very useful; it also has a ton of ISA slots and is easy to work in.

I found a catalog with this computer in it! A PC World from 1990, page 27! I think the monitor is long gone, being a big heavy thing to store. I know my parents got it through a program at one of their work that discounted computers so people could work at home.

I am guessing this was the 40MB VGA Color Plus system. This one also has 4MB of ram, which would have been added on later.

Powering On

Anyway, back to the Dell 316SX. I could do the right thing and check all the capacitors and everything in the system; that’s what I should have done… So I turn the system on, and I get the familiar fan noise, and the 1990s smell. But no beep, no post, no nothing. The floppy drives don’t even attempt to seek. I left it for some time hoping that the capacitors would reform on their own, and come back. No luck.

I took the case off for the first time in 30 years or so, and it all looks in good condition. No rust or corrosion from anything leaking. Below are some nice photos of the board and the system. It is a Dell 316SX (no math co-processor) Motherboard revision B03. (I had some glare on the board, so I uploaded several photos)

My first thought after chatting with ChatGPT was that this system was old, and had a Dallas clock chip. The Dallas DS1287 is a real-time clock with built-in battery — a common failure point in old PCs because the internal battery can’t be replaced easily. The internet said some 386 systems will fail to post if this chip is completely dead. I order a replacement (https://www.ebay.com/itm/134217827379) from the same vendor I got the PS2 Serial adapter from. Wait a few days, it comes, pop it in AND… nothing…

At this point I figure we are probably looking at a power problem. This system is 35 or so years old, its big capacitors failing would not be a shock.

Power Supply Restoration

I don’t love dealing with power, but here we are. I got the multimeter out and started probing the connections I could see. This is an older power supply than anyone today is used to, this is following the original IBM AT standard, minus the fact that is a seemingly proprietary Dell header on the motherboard. For anyone with the same system, the connector is a MOLEX 09-50-8121, more on that later.

Reading the motherboard pins +12V, +5V looked good, -5V, and -12V looked a tiny bit low, but within tolerance for a system like this. I popped in a ISA/PCI diagnostic card and see that the RESET line is holding high, and the CPU is never being released. Then I probed the last line on the motherboard PSU connector, POWER GOOD; this pin goes high once the power supply has all the lines at a good voltage, releasing the processor to start… processing… That line never came up for me, and thus never released the processor. I opened the power supply and saw it was 2 boards with many wires going in-between them. I may eventually repair this power supply, but I do not feel like tackling that whole thing right now. I put that power supply on the shelf, and started the task at building a new one to meet this computers needs.

A while ago I bookmarked this device, https://www.tindie.com/products/dekunukem/picopsu-adaptor-for-ibm-5155-ibm-pc-compatibles/, an ISA card that can replace a power supply in these old machines. Looking at that I thought it would be a good place to start. I didn’t want to use this exact thing here, because the Dell 316SX only has 3 ISA slots, and I didn’t want to lose one to power. That brought me to 3D printing a bracket to hold whatever parts I needed for this power supply. The original power supply was a 85 watt, Astec SA85-3407.

The low wattage supply was neat because there are tiny modern supplies that can do 200ish watts. They are a bit scary because they are an exposed power supply delivering 200 watts. They also deliver ATX power, not the AT power I need. These days there are cables to convert between the two standards. Yet, again, the Dell used a specific MOLEX 09-50-8121 header, which I found on Mouser for $0.92. I gathered up my adapter cable, and the new header, and a cable kit from Amazon for Molex connectors; and spent the evening rewiring a new header, very slowly and carefully. I checked every pin several times to not spell doom for the system.

Its also interesting to point out, with the PicoPSU, it takes 12V DC in. This helps it be smaller and cooler, since the AC-DC conversion is done with a brick outside the chassis.

Then I plugged in just the motherboard, and with the power supply held in a little soldering clip, hit the power. And the system came up! Well at least I got video with the BIOS showing up! Plugging in the diagnostic card I saw +12V, -12V, +5V were all good, but the card said 3.3V was failing. That’s odd, 3.3V is not a voltage I provide. Turns out the motherboard uses the -5V rail to create the 3.3V rail. Searching online shown that -5V wasn’t really needed for anything, but its part of the ISA spec and some Sound Blasters and network cards need it, which means I wanted to have it. It’s worth noting this rail is used in very little quantities, the original power supply had .30A for the -5V line max. While the ATX standard mentions -5V, its not longer used in modern PCs. Thus, no modern power supply tends to give out the -5V. I got a step down converter that can do negative voltages and stepped -12V to -5V. Wired that in line, and I suddenly had all the power rails I needed!

Now that we had our semi-sketchy power situation working, I wanted to design a bracket to drop in where the old power supply went and could hold all these pieces nicely in place. I ended up working on a cover to mostly protect myself from the open PicoPSU running at the heart of the system. I added a fan with a speed controller as well, since the original power supply fan in the system was the only airflow the whole computer has. Then I added another fan to the front of the chassis. The system originally only had the one power supply fan, and when I took thermal measurements some of the chips were getting toasty and I thought another fan couldn’t hurt.

One last fun fact about this old power situation. The old computers didn’t have “soft power” like we do today; where you hit on and it tells the BIOS to start booting. This system had a big ON/OFF switch in the front with mains voltage (120V for the US) going to it. In replacing the PSU, I swapped this for a ATX, low voltage on, switch.

Video

While the Dell 316SX does have standard VGA on the back, there is not a spot for pin 7; the second pin in the second row. If you lookup pinouts for VGA online, this pin is either called “green ground” or “not used”. These days even if not used we include a spot or pin for it and not connect it. This machine has no spot for a pin. I had to get a VGA cable, and cut the pin out; allowing the cable to plug in.

Data Recovery

Now we had power, and can POST. The Dell 316SX had a Seagate ST-157A-1 – 44MB IDE/ATA-1 HDD; and a Hardcard II XL – 100MB ISA card. The first thing I wanted to do was get a backup of each of these storage devices just in case after 35 years they suddenly died. The Hardcard was easy, I moved it over to the 486 I had, used an old copy of Norton Ghost, and captured the drive no issues.

The hard drive was a bit harder since the 486 is old enough it can only have 1 drive on its primary IDE channel; that left the secondary channel. In trying different setups I realized that the Dell 316SX did not have the correct hard drive parameters entered when it was in use. This means, when I tried to read it on a machine where I couldn’t set those settings, I wouldn’t get the correct data back. I HAD to have the disk read from the primary 486 IDE channel where I could edit the parameters to be incorrect on the 486 like it was on the 386. I got an ADAPTEC AHA-1542CP ISA SCSI CONTROLLER (from this seller), this allowed be to boot a DOS floppy, load Ghost, and image the drive to the new SCSI device, with the correct – incorrect hard drive parameters. This SCSI card has a full BIOS on it, allowing DOS to reference and even boot off of it without a driver.

The true savior here was Spinrite. I didn’t realize the hard drive parameters were causing my issues, and I thought the drive had just died. I figured I would give one last shot with Spinrite before calling the drive dead, and the data lost. Before I could start a scan, Spinrite popped up saying that the drive wasn’t recorded correctly and I should edit those settings!

After capturing images of both devices, I started cleaning the system, taking some photos, and putting it back together. One last test of powering it up, and the Hardcard died. It would no longer POST, freezing when the card tried to spin up. I am very glad I captured an image while I could! I copied that image into an image for the BlueSCSI device I had, and we were back in business! The Hardcard started giving “1703(K) — Hardcard IIXL Error at BIOS address C8000h.” which the internet said was the drive had died.

For those of us who haven’t done that much with MS-DOS in years, here is a reminder how partitions work (this is important because the old system had the Seagate drive as C and E, then the Hardcard as D); all Primary partitions that are accessible to the BIOS are added as the system boots, THEN all extended/logical partitions. This means, with the internal drive coming up as C: D:, then the Hardcard as E: I had to figure out how to switch them. In the end, it ended up being that the Hardcard was coming up as a extended partition, and it needed to be a primary one to force it earlier in the order. Turns out the Seagate drive had 1 primary, and one extended partition. After doing that change, and copying all the data back the system and all the links within Windows 3.1 came up correctly.

Cards

I got the Dell 316SX with a Hardcard II XL – 100MB ISA card and a Sound Blaster 16. I put some deoxit into the volume control knob of the Sound Blaster, it had the crackles when you moved it. That cleared it up.

I mentioned swapping the Hardcard for a SCSI controller. While I was in the system I also decided to get a 10MB Ethernet controller off ebay and put that into the system to have easier file transfers in the future.

Drives

This Dell 316SX has a 5.25″ drive bay, and a 3.5″ bay. Both are working happily, but I did give them some lubricating grease on their rails after cleaning them up.

Case Cleanup

I put some time into cleaning the case. For being ~35 years old, it was looking in good condition.

Conclusion

In the end, I am very excited to have my childhood Dell 316SX back up and happily running. It took some work, with non-stop issues along the way; but in the end, its working with most of its original hardware. Below are some other photos I have taken. While I was working on the system I ordered 4 more 1MB SIMMs to bring the total memory to 8MB. I figured I would max it out while I had the system open. The only downside is the POST checks all the memory and this slows it down a bit.

I uploaded this playlist of a few videos I took working on the computer; they are in a playlist below.

Ruckus H550 Odd Recovery, & Wifi Upgrades

I have a bad habit of buying networking gear when my work/life gets hectic. In a recent time of chaos I decided I should update a Ruckus H510 AP I have to a H550. I saw one on eBay, gave an offer and it was accepted! When the unit came, it still had the config of a news company. I had to factory reset it like mentioned in previous articles. The odd thing is it would not come up for me to access. I could see the “Configure.Me” Wifi network, but when I went to it nothing. I tried going to the web page and got nothing, I set the default IP and couldn’t contact it via wired. I then took out Wireshark and started looking for what happened when I joined its Wifi.

It was looking for assets from 10.154.231.125? (Later I would find others mention this https://community.ruckuswireless.com/t5/Apps-and-SPoT/Wrong-IP-on-mobile-device-using-unleashed-Configure-Me-xxxxxx/m-p/25722) I set my laptops IP to 10.154.231.124/24, and I was able to connect and flash the Unleashed firmware like normal. I was getting other IP information and failing to get a web page on the wired port. I hope this helps someone out there.

One other thing I didn’t realize… The H550 is taller than the H510… and I had a shelf right above the spot it was mounted. So I did the right thing, and mounted the new one upside down, so the taller part goes down and doesn’t hit the shelf.

While I was here getting more Wifi 6 goodness in my home (I have been running mostly Wifi 5 (802.11ac Wave 2) I thought I would look for deals. I saw someone selling a R550 for sale for parts. It said that when turned on it had a red light. I know that these access points can take a good 3-5 minutes to start, and while they do, they have a red light on… What are the chances that this access point just has a bad firmware image, or… nothing is wrong with it and this person just didn’t wait…

I offered $50 for the broken access point that usually goes for $250, and they accepted! Then I waited for the device to come, and later that week, I plugged it in, powered it up, and… it booted fine! I flashed it over to Unleashed and suddenly I had another great Wifi 6 access point.

I have mostly moved all my access points to Wifi 6 at this point which means I can go above firmware 200.15 (the last for the Wifi 5 systems), but I still haven’t since its still recommended to stay there by some places. And I am pondering setting up the old H510 as a small access point and ethernet port at my workbench.

PS/2 to RS-232 Serial Mouse Converter

As part of my LAN Before Time rack project, I’m setting up classic PCs with a VGA and PS/2 KVM to manage them. However, one of my systems—a 486—lacks a PS/2 port for the mouse. A simple PS/2-to-serial adapter wasn’t enough; it required a proper signal conversion to work.

After some searching, I found this adapter kit on eBay: PS/2 to Serial Mouse Adapter. It’s based on an open-source project: necroware/ps2-serial-mouse-adapter. The kit didn’t include instructions, and the project assumes you already know how to assemble it; I decided to document my build process step by step.

A Quick Note on KVM Compatibility

This adapter worked flawlessly when I plugged a PS/2 HP Laser Mouse directly into the 486. However, when connected through my KVM, it worked for a few seconds before stopping. After some digging, I found a pull request from last year that mentioned a KVM fix. Flashing that updated firmware completely resolved my issue! Unfortunately, the main repository hasn’t been updated in two years, so hopefully, it gets some attention.

What’s Next?

Below, I’ll walk through assembling the adapter. After that, I’ll cover how to flash the updated firmware using a USB-to-TTL converter. These converters are cheap and easy to find—here’s the one I used: USB to TTL Adapter. Finally, I will show a case I designed and 3D printed for the device.

Steps

  • Put the serial connector through the top side of the board and solder it in place on the bottom, starting with the mounting legs and using plenty of solder. These take a lot of the strain of the connections. Then carefully do each of the data pins, making sure not to bridge any.
  • Insert the lower chip socket, and solder in place on the underside.
  • The Arduino Pro has 3 different parts we need to solder. The first is the head with the 90 degree pins at the end. This will allow us later to flash the controller if we want to move to other firmware. Put those through the top (the side with the chip) and then solder them in the underside.
  • Next, put the Arduino header pins in the bottom. I put them into the header connector to hold them in place. Do not put too much heat on each pin with the plastic part below. (Not my best soldering job)
  • Solder in the 10k resister, here I am soldering it on the bottom while it went in through the top. After it is in, cut of the excess legs.
  • Solder in the PS/2 port, use a good amount of solder on the mounting points so it doesn’t move when inserted, then solder the data pins.
  • Solder in the micro-usb port, careful of the tiny pins.
  • Add the jumper pins, solder them in.
  • Now time for the capacitors, these are polarized, note the right side of the silk screen is white that should line up with the white side of the cap. (the shorter leg side)
  • Finish up by soldering all the pin headers for the controller to sit on the board.

The board should now be complete! If you bought it from the seller I did, (who has been great, and I have bought other items from) then you have the main repos firmware on it. I won’t go too far in depth for this, but if you clone the fork down you can then use Platform.IO to flash the firmware. There are guides out there to do this on. Platform.IO is great when doing Arduino projects.

If you go the same kit I did, then it comes with a “pro16MHzatmega168” not the “pro16MHzatmega328” used in the Pull Request. Change the two lines where the 328 is mentioned to the 168-model string. If you do not, you will get a “timeout connecting to Arduino” when attempting to flash.

As mentioned, you need a TTL converter, then to flash the chip. The TTL converter (which I hadn’t used before) pins actually line up with the pins on the Arduino Pro. You need to hold it there for a total of 30 seconds while it flashes. You can just stick the header pins of the Arduino through the holes of the converter, then hit send via Platform.IO.

Flashing the new firmware on my messy desk, I did not need long cables like this…

3D Printed Case

This is a device I will keep behind my old PC, and I didn’t want it to be a raw circuit board. I didn’t see any cases to 3D print, so I put one together. This was the first time I made a case that used little feet to snap the top and bottom half together; no screws! I also put little towers in to hold down the PCB in place. It took a few revisions, but I think came out nicely. There is also a little window to hit the reset button if needed. The black case was the second revision, the white case is the first.

Model: https://thangs.com/mythangs/file/1301661

Hamster holding a CD with Java in the background

IsoFileReader

A while ago I was working on a system to handle network boot operations. The main server is written in Java, and I needed to be able to read contents out of ISO files. The easy solution would have been to extract the ISO to the hard drive. I was trying to avoid that to save space; and with all the different images, not have thousands of tiny files littering the drive.

Then I found stephenc repo (java-iso-tools) for reading ISO files in Java. This library worked great! It had examples which helped me get started, and was fast to dive though a file. It supported the traditional ISO-9660 formatted files, which I needed, and I was good to go. Years later, the people over at CentOS and Redhat Linux had the idea to start putting giant SHA hashes as file names. Suddenly the disc images I was getting contained filenames that were 128 characters in length; and sadly java-iso-tools was failing to parse these names. To explain why, we need a bit of a dive into how the ISO-9660 standard works.

ISO-9660 is Developed by ECMA (European Computer Manufacturers Association) as ECMA-119, and then was adopted into ISO-9660. Thus, technically I was able to get the standards documents and investigate how ECMA-119 worked. Images start with a header; pointing to several tables, and the root folder file. The information about files on the disc span out from that root file. The root file, is the root directory on the image. From there every file is either a directory (with/without children) or a file which can be read.

The standard has had many changes to it over the years. While the original ECMA-119/ISO-9660 standard dates back to the start of the CD-ROM, over time people added to the standard. With PC’s at the time running MS-DOS and being able to save files to a FAT file system as 8 letter then 3 letter for extensions, the formatted needed added onto so one day CentOS could have 128 character file names. Some early additions to the format were Rock Ridge, and the Enhanced tables. When reading the first bytes from an image, there are several byte blocks which state which version of the standard they work with; this was forward thinking in this way. The basic tables help simple devices easily be able to read the discs. They can offer short file names, and point to the same binary data other tables later do. Then the enhanced tables can offer more information, and be able to add additional features to the disc. Some of these features can include things like file permissions.

At this point I had decided I needed to fix the problem and was going to write my own library to do it. While it sounds crazy, I enjoy writing these low level libraries. I started with the ECMA-119 standard, and going through the flow, like I was a CD-ROM device reading an image. I would later add on code for Rock Ridge, and reading all the enhanced tables, and even adding on a UDF parser.

I don’t want to spend too much time going through the standard. If you are interested: ECMA-119/ISO 9660 Standard, ECMA-167/ISO_IEC 13346/Original UDF Standard, Rock Ridge, UDF 2.60, there is a collection of the standard documents in depth. This post is more to talk about the project in general, and how I enjoyed working on it. A few constraints I set upon myself were I wanted it to be 100% in Java 8. That way it could be natively compiled if someone wanted to do that, wouldn’t just be connecting to some native binary tool, and would work with older Java code bases. The project currently targets Java 11 being the LTS out at the time I was working on it. I know there are many code bases out there which are Java 8, and I actually dont think there is any code except some tests using Java 9+ features. If someone had a Java 8 project, they could remove the tests and compile to 8. We live in a little bit of an odd time now, where a project like this targets more enterprise users who tend to be back on older versions. And at the same time Java 24 is coming out. I wanted to give high level classes that a user needing a simple tool could use; but at the same time have deeper level objects publicly available.

I was using this in the earlier mentioned network booting environment.There I can be building 100+ servers at a time; speed, small, and fast code were important. I ended up adding as test some performance benchmarks. I test the old library as my control, then I do normal file lookups as well as pre-indexed. I developed a system where certain heuristics of the image are taken and can be stored. Then you can feed in this initial “vector” I called it, of the image and a file vector. If the image matched the initial vector for a few characteristics, we could reasonably assume its the same image originally scanned, then instead of reading all the header tables, we jump to the location of the file vector with trust. This does leave it up to the developer to make sure they are matching pre-indexed images with vectors; but if you do, you can much faster serve files.

This project was fairly straight forward to test, I had many and there are many ISO images out on the internet. And plenty of them are Linux Images! I also had the older library which I could use as a control to test against. I ended up writing many tests which help when people send Pull Requests to make sure nothing has broken. This project I needed done to support what I was working on. There were a few places where I didn’t fully flush out the metadata, but left it to the end user to, if they cared about that data type. I spent a lot of time in Hex Fiend hex editor marking segments and trying to understand where code I had was breaking down.

Over the years of working in Open Source, and going to a technical college, I have seen many strong technical projects that are very impressive code, and can do a ton of interesting things. And then the developer focuses on interesting things they can make their code do, and spends no time putting documentation together. At the same time there are many project that get the job done, but aren’t anything special; these projects put a few documents together and maybe an example, and then get all the usage. The area developers hate to spend time, but can be the most valuable is documentation. That pushed me to spend a lot of time commenting the code, and writing a large README file showing how to work with the library.

I hope you will take a look at the project, maybe use it, and feel free to drop issues as they arise! I have been using the library in production for years now. It doesn’t get a ton of updates, because there hasn’t been a lot I need to add to it. When a PR or Issue arise I take care of it. And with the project being published under my work, I get a lot of automated PRs to help upgrade the library.

Take a look! https://github.com/palantir/isofilereader

Ruckus FastIron ICX 8.0.x SSH Issues

I have had two of these little Ruckus ICX7150 switches for years now. They are great little units with 12(ish) 1gb switch ports, and 2 SFP+ cages. My primary one hosts the Wifi APs in my house since the switch is also POE! I have bumped it to its latest recommended firmware on the Ruckus support page, and not had to do much of anything else.

Until recently when I went to SSH into the switch and Windows 11 built in SSH client no longer accepts SHA1 hashes that the switch gives. Or more specifically:

no matching key exchange method found. Their offer: diffie-hellman-group14-sha1,diffie-hellman-group1-sha1

There are two ways of going about fixing this, the first is to tell SSH it is allowed to access less secure clients, adding the following to C:\Users\your_user\.ssh\config does this:

HostKeyAlgorithms = +ssh-rsa
PubkeyAcceptedAlgorithms = +ssh-rsa
KexAlgorithms +diffie-hellman-group1-sha1
ForwardX11 no
ForwardAgent no

This isn’t the best, because we are just lowering generally accepted security practices, but it works.

The next thing I found out is that while 8.0.x is still the recommended release, FastIron 9.0 and 10.0 are out! One of the big recent features of 9.x is much newer crypto standards for SSH. 8.x simply doesn’t have them present.

I upgraded my switch from 8.0.95n to 9.0.10j_cd6; both the switch firmware, not routing. Apparently some releases have a “continual development” release which is smaller than a 0.0.1 release. I haven’t had any issues with the upgrade, it went the same as any other.

A quick note, these days if you attempt to scp it actually uses sftp as the backing protocol, to upload the firmware file to the switch use the following command:

scp -O SPS09010j_cd6ufi.bin dan@192.168.3.1:flash:secondary

Then on the switch:

conf t
boot system flash secondary 
wr mem 
reload

After the switch reloaded, which seemed to take a bit longer than normal with firmware updates, I was right back to my normal working switch and SSH worked happily.