Path: utzoo!dciem!nrcaer!scs!spl1!laidbak!att!pacbell!ames!pasteur!ucbvax!XX.LCS.MIT.EDU!ROMKEY From: ROMKEY@XX.LCS.MIT.EDU (John Romkey) Newsgroups: comp.protocols.tcp-ip.ibmpc Subject: Re: Hacking CMU sources to TurboC Message-ID: <12403600997.23.ROMKEY@XX.LCS.MIT.EDU> Date: 3 Jun 88 23:35:15 GMT Article-I.D.: XX.12403600997.23.ROMKEY References: <8806031044.aa21819@Louie.UDEL.EDU> Sender: daemon@ucbvax.BERKELEY.EDU Organization: The Internet Lines: 63 The ping problems that people have been talking about are probably an old problem due to the way PC/IP works. If you ping a PC/IP program multiple times from one host, the first ping shouldn't get a reply, but the others should. Here's why: Suppose you're pinging an IBM PC-type machine (P) running PC/IP from something else, X. If X doesn't have an entry in its ARP cache for P then X ARP's P and P responds. When P responds, it adds an entry to its ARP cache for X (on the reasoning that if someone ARP's you then you're pretty likely to need to send packets to them soon). In this case, everything should be fine. [Actually...I can't remember if the MIT/CMU PC/IP cached IP/ethernet address pairs when it got responses or if I added that at FTP Software. I think that got put in back at MIT.] The more interesting case is when X doesn't ARP P (or, more correctly, when P doesn't already know X's ethernet address). X sends an ICMP echo request to P. In detail, P takes an interrupt from the ethernet interface, copies the packet into the PC's memory, queues it and makes the ethernet demultiplexing task runnable. Eventually P actually runs the ethernet demultiplexing task, which upcalls IP (indemux()) passing it the received packet. IP then decides it's an ICMP packet and then calls ICMP. ICMP decides it's an echo request, which needs an echo reply sent back to the source of this packet. At this point, ICMP is still running on the ethernet demultiplexer task's stack. It formats up an echo reply and passes it to in_write() to transmit it. Here's where you lose. If X isn't in P's ARP cache, P transmit an ARP request and most likely gets back an ARP reply. P's interrupt handler copies the ARP reply in and queues it up and makes the ethernet demultiplexer task runnable. Eventually it runs again, BUT when it does, it's still in ICMP. ICMP says - "Oh? Did we get a response? No... Did we time out? No... Okay, let's wait some more." and the ARP reply doesn't get processed. Eventually ARP times out, ICMP gives up and the ethernet demultiplexer task finishes demultiplexing the original ICMP echo request and gets to process more received packets, finally getting to handle the ARP reply. It's too late for this ICMP echo reply, now, but the ARP reply still gets entered into the ARP cache, so if we do this again everything should work okay. Now, this behaviour is a little weird, but it's a fairly straightforward consequence of the way PC/IP is structured. The easiest way around it would be to have ICMP create a new task to send the echo reply back, but task creation in PC/IP is kind of expensive, so we don't do that. It's also not so out-of-line with the way the ARP RFC says ARP should work, either. The ARP RFC says that when you're transmitting an IP packet and you need to send an ARP request because of it, you should send the request and drop the IP packet you're sending. This greatly simplifies the output side of IP and the ethernet layer. It also would lead to the behavior that you're seeing with PC/IP, but for different reasons. In fact, PC/IP doesn't obey the ARP RFC in this area; ARP holds on to the packet that's being transmitted and waits a while for the ARP reply to come in. I did it this way because the whole ARP cache in PC/IP is very transient - it gets cleared everytime you run a program (since there's a copy of it in every program). That meant that the first packet any program sent was guaranteed to be discarded, which seemed like a waste of time. That, in great detail, is probably why you're losing. - john -------