• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

TashRouter: An AppleTalk Router

mmjs

Member
What would the code be to force all RTMP broadcasts to short DDP on LocalTalk? I'm also recalling @RolandJuno's ImageWriter stalling out after a minute or so of printing. That would line up with a client throwing its hands up in the air and timing out from not getting a RTMP packet. Given the limited CPU resources and lack of system timer on the Apple IIe, the Workstation card likely handles RTMP with it's onboard CPU and firmware routines. Those routines may not be able to handle an extended packet.
Hey folks, I've been seeing something similar with a 512K. Effectively it times out after about 85 seconds after connecting, and during this time it works fine. I haven't done any proper testing yet, but figured I would share since it seems quite similar to the issue described here. I posted about it in this thread: https://mastodon.vladovince.com/@mejs/112108037975241930

On separate note, thank you for developing both the tashrouter and tashtalk, @tashtari! I've been using them to connect all my LT devices as well as some Mini vMac machines to GlobalTalk.
 

robin-fo

Well-known member
Question for the network experts out there... when sending RTMP broadcasts over EtherTalk, what destination network number should a router use? I've been using 0x0000, but Inside AppleTalk seems to be silent on this point...
Good question, I just had a look at my code and I didn‘t knew either. 0x0000 sounds reasonable, though.

My implementation is as follows, maybe it helps (no guarantee for conformity 😉)

C:
void RTMP_execute(RouterPort_t *port) {
    if (RTMP_SEND_TIMER_PERIOD_SECS < Timer_getElapsedSeconds(&port->rtmp.sendTimer)) {
        if (true /* TBD only if network range already detected. See p.5-17 */
            && port->seed) {
            AppleTalk_RemoteSocket_t dst = {
                .address.networkID = 0U, // TBD find out which network number is needed here
                .address.nodeID = 0xFF, /* Broadcast */
                .socket = SOCKET_SAS_RTMP
            };
            RTMP_sendRoutingTable(port, dst, false);
        }
        port->rtmp.sendTimer = Timer_start();
    }
}

void RTMP_sendRequest(RouterPort_t *port) {
    DDP_Packet_t packet = DDP_createPacket(port->rtmp.ddp);
    AppleTalk_RemoteSocket_t dst = {
        .address.networkID = 0U, /* TBD find out which network number is needed here */
        .address.nodeID = 0xFF, /* Broadcast */
        .socket = SOCKET_SAS_RTMP
    };
    DDP_configurePacket(&packet, dst, port->rtmp.socket, DDP_TYPE_RTMP_REQUEST);
    /* Set RTMP function, located at offset 0 */
    packet.payload.data[0] = RTMP_FUNCTION_REQUEST;
    DDP_setPayloadSize(&packet, RTMP_REQUEST_PACKET_LENGTH);
    DDP_sendPacket(packet);
}

void RTMP_sendRoutingTable(RouterPort_t *port, AppleTalk_RemoteSocket_t dst, bool splitHorizon) {
    assert(NULL != port && NULL != port->rtmp.ddp && NULL != port->rtmp.ddp->thisRouter);
    RoutingTable_t *table = &port->rtmp.ddp->thisRouter->routingTable;
    assert(NULL != table);
    if (!RoutingTable_isEmpty(table)) {
        DDP_Packet_t packet = DDP_createPacket(port->rtmp.ddp);
        
        if (DDP_NETWORK_EXTENDED == port->rtmp.ddp->networkType) {
            /* TBD Set network number */
            //dst.address.networkID = ...
        }
        DDP_configurePacket(&packet, dst, port->rtmp.socket, DDP_TYPE_RTMP_RESPONSE);
        uint8_t *data = packet.payload.data;
        uint32_t payloadLength = 0UL;
        RTMP_DATA_setRouterNetworkNumber(data, port->rtmp.ddp->address->networkID);
        RTMP_DATA_setIdLength(data, 8U);
        RTMP_DATA_setRouterNodeId(data, port->rtmp.ddp->address->nodeID);
        if (DDP_NETWORK_NONEXTENDED == port->rtmp.ddp->networkType) {
 

NJRoadfan

Well-known member
For RTMP broadcast packets, it appears that netatalk uses ATADDR_ANYNET, which appears to be whatever network the NIC is configured for. Ex: The router is at 6502.122, so RTMP packets are broadcast to 6502.255. I can test this after work with atalkd and my Fastpaths by setting up my EtherTalk network with a fairly large netrange.

The reason things "work" for about a minute is that the client get initial network configuration information via ZIP requests. Once it has the network and zone information, things progress as working, but a countdown timer starts. That timer is reset by RTMP packets refreshing the network information for the client. If the timer expires, the client assumes its disconnected and stops responding. Basically things enter an uncertain state without regular RTMP packets refreshing the network information. It doesn't help that Apple's networking stacks have very poor error handling and reporting for this situation.

The Mac 512k errors above lines up with the problems I was having when netatalk wasn't broadcasting RTMP. What version of System Software is it running? Early Macintosh AppleTalk stacks may have the same limitations as the Apple II Workstation card.

Side Note: The Fastpath sends out RTMP information on EtherTalk Phase 1 in short DDP packets too. Yes, Ethertalk Phase 1 supports short packets.
 

tashtari

PIC Whisperer
The reason things "work" for about a minute is that the client get initial network configuration information via ZIP requests.
Aha, interesting...

For RTMP broadcast packets, it appears that netatalk uses ATADDR_ANYNET, which appears to be whatever network the NIC is configured for.
In that case, the fix should be to change destination_network=0x0000 to destination_network=port.network on line 45 of service/rtmp/sending.py - this will also cause LocalTalk ports to use the short header when sending RTMP datagrams.
 

tashtari

PIC Whisperer
I really hope this is it. Not only would the problem be solved, but the finger could be pointed squarely at Apple and their lazy network stack implementations... =D
 

shirsch

Well-known member
I really hope this is it. Not only would the problem be solved, but the finger could be pointed squarely at Apple and their lazy network stack implementations... =D
And, survey says... 'destination_network=port.network' fixed the issue! Session just stayed up for over 15 minutes, which implies forever :) Thanks so much to @tashtari and @NJRoadfan for the assistance.

On to the next issue: Netboot hangs, probably because the router isn't advertising the zone on the localtalk side?

UPDATE: Netboot hangs only on the IIe, //gs works just fine. Probably another firmware issue in the workstation board.
 

shirsch

Well-known member
Victoire!

Crucial question - was this the only change you had in TashRouter versus the current state of the repo, or did you still have any of the previous suggestions in?
No, I dropped that change on top of the repository head. No other changes.
 

tashtari

PIC Whisperer
Okay, I found one more instance of the same issue in the NBP server, it was always sending long-header datagrams when sending a LkUp on the requesting network. The repo has been updated, can you pull from it and retry, just to make sure everything's good?
 

tashtari

PIC Whisperer
I started a print job using Illustrator 3 and it began to print. However, the print stalled about halfway through the job, eventually saying there was an AppleTalk error. I've included the debug output from tashrouter.
Can you pull the latest from the repo, comment out the checksum check again, and see if you can get through a whole print job now?
 

tashtari

PIC Whisperer
Looks like at least one router rewrites ALL NBPLkup packets with the sender's address because of bad behavior and crappy firmware.
I'm starting to be resigned to the fact that I'm going to have to support this approach, ugly though it is... hopefully there's a good way to make it optional, though. I'll have to see...
 

tashtari

PIC Whisperer
Well, maybe not. Zone-based multicasting is only ever done by NBP anyway, so it wouldn't be too bad to make the changes at the LocaltalkPort level. 'Course, that leaves me cracking open the ImageWriter's AppleTalk firmware to try and figure out how it's miscalculating the checksum, which sounds like a barrel of laughs...
 

shirsch

Well-known member
Okay, I found one more instance of the same issue in the NBP server, it was always sending long-header datagrams when sending a LkUp on the requesting network. The repo has been updated, can you pull from it and retry, just to make sure everything's good?
Everything is not only good, it's better! Netboot now works on the IIe. Happiness ensues...

Last remaining nit: The SE/30 still insists
Code:
< no zones available >
Otherwise it's working fine. I can connect to the server and mount volumes. Do you want me to apply any of the patches you're suggesting for @RolandJuno ?
 

NJRoadfan

Well-known member
What OS is the SE/30 running? My System 7.1 install on Basilisk has the same problem with the Network control panel showing no zone no matter what router I use with a single zone (multiple zones is usually fine). A reboot usually fixes it. My Open Transport running machines are usually fine.

Assuming the changes made today return all NBPLkup packets from long to short form on LocalTalk, means that the ImageWriter likely will need "special handling" due to its firmware. Ironically I'm not surprised that the IIe can now netboot as its onboard firmware likely only works with shortform NBPLkups.
 

shirsch

Well-known member
Hmm, okay. Can you copy what TashRouter puts out to the console right as you open the Network control panel? I'm curious what kind of query it's sending out and what it's getting as a response.
Here 'tis.
 

Attachments

  • se30_20240318.zip
    1.4 KB · Views: 1

tashtari

PIC Whisperer
Here 'tis.
Is the SE/30 connected via LocalTalk or EtherTalk? I see two nodes talking in that trace that could be it, either 2.4 (via tap2) or 3.1 (via ttyAMA0)... both of them are doing things that are slightly unexpected:

Code:
12:49:21,774 in to 2.31  tap2     0 2.31  2.4     6   6 6  b'\x05\x00\x00\x00\x00\x00\x01*'                                            // ZIP GetNetInfo
12:49:21,780 out to 2.4  tap2     0 2.4   2.31    6   6 6  b'\x06\xa0\x00\x02\x00\x02\x01*\x06\t\x00\x07\x00\x00e\x0fLocalTalk2ZoneA'  // ZIP GetNetInfo Reply (zone * is invalid; only one zone, LocalTalk2ZoneA)
12:49:21,797 in to 2.31  tap2     0 2.31  2.4     6   6 6  b'\x05\x00\x00\x00\x00\x00\x01*'                                            // ZIP GetNetInfo again (why?)
12:49:21,810 in to 2.31  tap2     0 2.31  2.4     6   6 3  b'@\x01\xba\xf8\t\x00\x00\x01'                                              // ZIP/ATP GetLocalZones
12:49:21,809 out to 2.4  tap2     0 2.4   2.31    6   6 6  b'\x06\xa0\x00\x02\x00\x02\x01*\x06\t\x00\x07\x00\x00e\x0fLocalTalk2ZoneA'  // ZIP GetNetInfo Reply again (same as above)
12:49:21,826 out to 2.4  tap2     0 2.4   2.31    6   6 3  b'\x90\x00\xba\xf8\x01\x00\x00\x01\x0fLocalTalk2ZoneA'                      // ZIP/ATP GetLocalZonesReply
12:49:27,339 in to 3.254 ttyAMA0  0 0.254 0.1     6 251 3  b'@\x01\x00\x01\x07\x00\x00\x01'                                            // ZIP/ATP GetMyZone (with invalid start index of 1)
12:49:27,376 in to 3.254 ttyAMA0  0 0.254 0.1     6 251 3  b'@\x01\x00\x02\x07\x00\x00\x00'                                            // ZIP/ATP GetMyZone (with valid start index of 0)
12:49:27,384 out to 3.1  ttyAMA0  0 3.1   3.254 251   6 3  b'\x90\x00\x00\x02\x00\x00\x00\x01\x0fLocalTalk2ZoneA'                      // ZIP/ATP GetMyZoneReply
12:49:29,388 in to 3.254 ttyAMA0  0 0.254 0.1     6 251 3  b'@\x01\x00\x01\x07\x00\x00\x01'                                            // ZIP/ATP GetMyZone (with invalid start index of 1)
12:49:31,440 in to 3.254 ttyAMA0  0 0.254 0.1     6 251 3  b'@\x01\x00\x01\x07\x00\x00\x01'                                            // ZIP/ATP GetMyZone (with invalid start index of 1)
12:49:33,488 in to 3.254 ttyAMA0  0 0.254 0.1     6 251 3  b'@\x01\x00\x01\x07\x00\x00\x01'                                            // ZIP/ATP GetMyZone (with invalid start index of 1)
12:49:35,538 in to 3.254 ttyAMA0  0 0.254 0.1     6 251 3  b'@\x01\x00\x01\x07\x00\x00\x01'                                            // ZIP/ATP GetMyZone (with invalid start index of 1)

(I removed all the frame-level lines, the RTMP broadcasts, and the lines where 2.4 was pinging the LaserJet)

2.4 for some reason does two GetNetInfos, one immediately after the other, which is a little weird... but 3.1 is doing a raft of GetMyZones (every two seconds) with a nonzero start index, which is a lot weird. According to Inside AppleTalk, page 8-15, this isn't valid, and I'm curious what it's trying to do, especially considering it does a valid one in there too, and gets a valid reply...

If the SE/30 is on LocalTalk, you could try commenting out if start_index != 0: return on line 159 of service/zip/responding.py and see if it gets a zone name, though it seems like one of those things that shouldn't work.
 

shirsch

Well-known member
Yes, the SE/30 was on LocalTalk. And, yes, your suggested workaround above fixes the issue! Not only is it now showing the Zone, but the lookup runs about 10x faster. It used to pause for 5-10 seconds after the Appletalk control panel icon was selected - now it pops up instantly.

The SE/30 is 3.1, BTW.
 
Last edited:
Top