wayne@ultra.UUCP (Wayne Hathaway) (05/02/89)
Whilst doing some load-testing of our in-house net, I noticed some surprising behavior; I'd be interested in some expert comments. First the configuration: Several Sun 3's running SunOS 4.0.1, connected by an UltraNet (our product, but basically irrelevant to the question). Next the situation: We seemed to be having some troubles with the checksum hardware on one of our cards (in a diskless Sun 3/140, to be specific), resulting in excessive discarding of datagrams. To test it, I started up a process on another Sun which sent a steady stream of 8K UDP datagrams to a random port on the 3/140. Since I was interested in datagrams tossed by the card rather than the SunOS kernel, I did not bother having anybody do a "recvfrom" on the 3/140 (in other words, the datagrams would be tossed by the 3/140's UDP). [By the way, the UltraNet MTU is larger than 8K, so these datagrams are legal.] Okay, the strangeness: Looking at counters, I noticed that not only did the 3/140 receive (say) 854 datagrams, it also SENT exactly 854 datagrams. It didn't take too much detective work to figure out what the outgoing datagrams were -- they were ICMP messages with Type 3, Code 3: "Destination Port Unreachable". My question is "Why?" I realize this behavior is perfectly LEGAL (since the ICMP spec [RFC 792] says "If ... the IP module cannot deliver the datagram because the ... process port is not active, the destination host may send a destination unreachable message to the source host."), it just seemed strange to see 4.3 BSD actually doing it. First of all, I'm a great believer in the idea of "if something weird happens, build a datagram describing it and launch it towards some logging host, then forget it." But if that host's logging program isn't up, this is going to result in DOUBLE the network traffic (at least in number of datagrams). No great "overload" problem, of course, but it does seem silly, particularly since (for UDP datagrams, at least) the original sending host isn't really going to be able to DO anything with the information. And second, what is IP doing talking about ports anyway??? I mean, ports are upper layer artifacts, no? According to my trusty grep, the word "port" does not even APPEAR in the IP spec (RFC 791)! But then, the ICMP spec DOES say "If ... the IP module cannot deliver the datagram because the ... process PORT is not active" so SOMEBODY sure expects IP to be in the port business! (The spec also mentions ports in a couple of other places, but they don't seem to be particularly relevant.) Actually, what is happening in 4.3 BSD is that UDP is turning around and causing its ICMP to send the ICMP_UNREACH_PORT message. Nothing illegal about this, of course, but it does get us back to the previous question: why bother? (The UDP action is in udp_usrreq.c and is prefaced by the comment "don't send ICMP response for broadcast packet" -- I would ask why EVER send it?! Also I note that TCP does not seem to ever send an ICMP_UNREACH_PORT.) Anyway, any thoughts from all the IP/ICMP/BSD gurus out there? Wayne Hathaway Ultra Network Technologies domain: wayne@Ultra.COM 101 Daggett Drive Internet: ultra!wayne@Ames.ARC.NASA.GOV San Jose, CA 95134 uucp: ...!ames!ultra!wayne 408-922-0100
droid@earth.cray.com (Andy Nicholson) (05/03/89)
> It didn't take too much detective work to figure out what > the outgoing datagrams were -- they were ICMP messages with Type 3, > Code 3: "Destination Port Unreachable". My question is "Why?" The answer probably is "Because the protocol spec makes it available and it is probably a good thing to do." Note that this is more of a rationalization. Nowhere that I can think of does the spec say it has to be done this way. I would tend to agree that it is probably a good thing to do. I find it easy to conceive of an IP implementation on a more advanced operating system where the IP could receive the ICMP message, make a determination of the process sending the offending datagram, and asynchronously notify that process (via a mechanism like signals, and using a signal like SIGPIPE) that the destination port was not there. Or the IP could keep a list of unavailable ports and return a write error to UDP (but only for a short period of time, as a port may appear later). There are probably lots of things that could be done with the message. It is probably there because it seemed like "the right thing" to the implementor. > And second, what is IP doing talking about ports anyway??? I mean, > ports are upper layer artifacts, no? According to my trusty grep, the > word "port" does not even APPEAR in the IP spec (RFC 791)! But then, > the ICMP spec DOES say "If ... the IP module cannot deliver the > datagram because the ... process PORT is not active" so SOMEBODY sure > expects IP to be in the port business! (The spec also mentions ports > in a couple of other places, but they don't seem to be particularly > relevant.) I see you are naive regarding layering of TCP/IP. They are, but only sometimes. TCP and UDP protocols make a lot of assumptions about how IP works in order to gain some performance improvements, like sticking in a partially filled IP header at the front of the TCP or UDP packet that is passed on to IP. The fact of the matter is that layering is great from a conceptual view, but it nukes performance. Finally, the IP concept of an upper level protocol port is not the same as the UDP or IP port. The IP protocol merely makes the assumption that upper level protocols will have some demultiplexing mechanism (which they may or may not) and call this the port. They could have called this something like endpoint id or demux, or whatever, but port gets the point across just fine. Again, although the protocols are layered, it was pretty much assumed that there was a great likelyhood of finding TCP and UDP above IP. > Actually, what is happening in 4.3 BSD is that UDP is turning around > and causing its ICMP to send the ICMP_UNREACH_PORT message. Nothing > illegal about this, of course, but it does get us back to the previous > question: why bother? (The UDP action is in udp_usrreq.c and is > prefaced by the comment "don't send ICMP response for broadcast > packet" -- I would ask why EVER send it?! Also I note that TCP does > not seem to ever send an ICMP_UNREACH_PORT.) TCP does not send an unreachable port message because it sends a reset segment instead, as the TCP protocol spec says to. That is why telnet returns immediately with "connection refused" if you telnet to a machine that is up but does not have its telnet server running. Andy Nicholson droid@earth.cray.com
barns@GATEWAY.MITRE.ORG (Bill Barns) (05/04/89)
I hold that there is an inherent layering wart in dealing with error reporting of nonexistent layer-specific address selectors. You get to choose the form and location of your wart(s) when you design a protocol suite, but there will be one somewhere, in some form, if you try to implement such a function. The justification for this argument gets pretty involved; send mail if you want to hear it. ICMP's approach is arguably "best" because it provides an optional layer 3 wart which you may use if you believe it belongs in layer 3, but (since it's optional) you can implement a layer 4 wart when you design a layer 4 protocol if you're so inclined, or you can ignore the whole problem by never reporting such errors. As for the utility of sending these errors, certainly there is no knowing in advance whether the recipient will do anything worthwhile with them, but the forthcoming Host Requirements RFC is attempting to clarify the issue of service interfaces in such a way that in any conformant implementation, there will at least be the potential for the error report to actually be put to use. For the case of UDP it is required that the ICMP error be passed back to the application whose datagram inspired it. Whether the application makes any intelligent use of it is an application layer issue. See sections 3.4 and 4.1.3.3 of the HR RFC draft. Latest edition of this draft is dated April 17, 1989. Bill Barns / MITRE-Washington / barns@gateway.mitre.org
romkey@asylum.SF.CA.US (John Romkey) (05/04/89)
In article <8905021609.AA00846@lear.ultra.com> wayne@ultra.UUCP (Wayne
Hathaway) writes about not understanding why he got some ICMP port
unreachables.
The system you tested against was behaving quite properly, both
according to the specs and according to the intentions.
The port unreachables aren't meant to go to some logging host, they're
meant to go back to the system that generated the packets that
couldn't be delivered. Port unreachable is an error indication
mechanism so that UDP-based applications can find out that no one was
home on the other side. Otherwise, there's no way for UDP to tell. You
could do this for TCP, too, but TCP explicitly uses the TCP reset
mechanism, instead.
IP doesn't and shouldn't send these messages. The layering works like
this: UDP gets a packet, checks if there's something listening on the
destination port. If there is, it delivers it, no problem. If there
isn't, it asks ICMP to generate a port unreachable message.
IP should send PROTOCOL unreachables. I don't have a copy of the IP
RFC handy, so I'm not going to double check on what the actual text
says.
Anyway, 4.3 is doing things correctly here.
--
- john romkey
USENET/UUCP: romkey@asylum.sf.ca.us Internet: romkey@xx.lcs.mit.edu
"We had some good machines/But they don't work no more" - Shriekback
barmar@think.COM (Barry Margolin) (05/04/89)
In article <8905021609.AA00846@lear.ultra.com> wayne@ultra.UUCP (Wayne Hathaway) writes: >And second, what is IP doing talking about ports anyway??? I think that ICMP is providing this as a service to higher-level protocols that have no way of doing this on their own. It's not necessarily a waste of bandwidth; when using an unreliable datagram protocol, a client is likely to retransmit the operation if it doesn't get a response. One ICMP Port Unreachable message is better than a half dozen retransmitted UDP packets. Of course, if the protocol is one-way with no response expected, this is an extraneous packet; however, that style is generally only used with broadcasts, which also don't prompt the port unreachable response, so it's probably OK. > Also I note that TCP does >not seem to ever send an ICMP_UNREACH_PORT.) TCP doesn't need it, because it has its own protocol for indicating an invalid port (it sends a RST packet). Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
djm@lupine.UUCP (Dave Mackie) (05/04/89)
Well, you are a bit off-base on your description of the ICMP error logging mechanism. ICMP messages are logged (at least in BSD) down in the IP/ICMP code itself. There is no network error logger program that listens on a special port for ICMP error messages. Also, the information contained in an ICMP Port Unreachable message is not useless. The problem is that (at least in BSD again) most applications using UDP simply send their packets out using the sendto() system call and use the parameters of that call to specify the destination. That's great if your application is going to be sending packets all over creation and you only want to have the overhead/complexity of a single socket. But that's not always the case for many applications. The problem with this approach is that the poor networking code doesn't remember where you sent your packets, and therefore can't correlate any incoming ICMP port unreachable messages with your application. So what generally happens is the application retransmits it's UDP packets for a while and then gives up. All the while the kernel is getting ICMP port unreachable's from the other host. This results in extra network traffic, and the user waiting around for the !@#$ application to timeout. Now the solution to this situation is to have the application do a connect() to the destination. Yes, you can do a connect on a UDP socket. It just tells the networking code who you will be talking to with this socket, without generating any actual network traffic. Then the application can use send() instead of sendto(). When it attempts to reach a non-existent service on the destination host, it *does* get notification of the ICMP port unreachable message, and voila it can stop wasting everybody's time, and report the problem to the user. Now obviously this model doesn't work for every type of application, but it does for quite a few. In the case of TCP, the TCP spec gives the implementor a nastier more direct way of indicating displeasure about the destination port number. It sends a RESET back to the source machine. Now that should get it's attention! Dave Mackie Network Computing Devices djm@ncd.com