RFC 1326

Mutual Encapsulation Considered Dangerous

๐Ÿ“… published May 1992, from ietf

Mutual Encapsulation Considered Dangerous ๐Ÿฆ‹

RFC: 1326 Title: Mutual Encapsulation Considered Dangerous Author: P. Tsuchiya, Paul Tsuchiya of Bellcore ๐ŸŽ€ Date: May 1992 Status: provides information for the Internet community, and does not specify an Internet standard Obsoletes / Updates: its title block doesn't list any Obsoletes or Updates lines โœจ


Status of this Memo ๐Ÿ“œ

This memo provides information for the Internet community. It does not specify an Internet standard. Distribution of this memo is unlimited. ๐ŸŒธ

Abstract ๐Ÿ’œ

okay so this memo is all about a packet explosion problem that can happen when two protocols encapsulate each other (A wraps B, and B wraps A) ๐Ÿ˜ญ it's giving chaos, fr fr.

The Current Environment ๐ŸŒˆ

ngl, even with all the international standardization efforts ๐Ÿ™„, we're seeing a plethora of protocols, both standard and proprietary, each one built for some technical or marketing niche ๐Ÿ’…. Eventually they bump into each other and are expected to work together.

One way to make that happen is to encapsulate one protocol inside another. This has led to mutual encapsulation, where protocol A runs over protocol B in some cases, and protocol B runs over protocol A in others. For example, there are real cases of both IP over AppleTalk and AppleTalk over IP ๐Ÿ“. (The term "mutual encapsulation" comes from the paper by Shoch, Cohen, and Taft, called Mutual Encapsulation of Internetwork Protocols, Computer Networks 5, North-Holland, 1981, 287-300. The problem identified in this RFC is not mentioned in the Shoch et. al. paper.)

If there aren't already other instances of mutual encapsulation, there will likely be more later ๐Ÿ”ฎ. This is especially true for the various internet protocols, like IP, CLNP, AppleTalk, IPX, DECNET, and so on.

The Problem ๐Ÿ’ฅ

so here's the tea. Picture the topology in Figure 1 ๐Ÿงš. We've got two backbones and four stubs. Backbone B(X) uses a native protocol of X (so it expects to receive packets with an X header). B(Y) uses a native protocol of Y. The left and right S(Y) stubs use protocol Y, and the left and right S(X) stubs use protocol X.

          :::  :::::          :::::   :::          :::
 +------+ :Y   :X:Y  +------+ :X:Y    :Y  +------+ :Y   +------+
 |      | :::  ::::: |      | :::::   ::: |      | :::  |      |
 | S(Y) |-----Ra-----|      |-------Rb----|      |------| S(Y) |
 |      |            |      |             |      |      |      |
 +------+            |      |             |      |      +------+
                     | B(X) |             | B(Y) |
                     |      |             |      |
                :::  |      | :::   ::::: |      | :::::  :::
       +------+  X:  |      |  X:    X:Y: |      |  X:Y:   X: +------+
       |      | :::  |      | :::   ::::: |      | :::::  ::: |      |
       | S(X) |------|      |-----Rc------|      |------Rd----| S(X) |
       |      |      |      |             |      |            |      |
       +------+      |      |-----Re------|      |            +------+
                     +------+             +------+
        :::::
         X:Y:  A packet with protocol X encapsulated in protocol
        :::::  Y, moving left to right

           Rx  Router x

         S(Y)  A stub network whose native protocol is protocol Y

         B(X)  A backbone network whose native protocol is protocol X


             FIGURE 1:  MUTUAL ENCAPSULATION

Figure 1 shows how packets travel from left S(X) to right S(X), and from right S(Y) to left S(Y) โœˆ๏ธ. Let's follow a packet from left S(X) to right S(X). It has just an X header until it reaches router Rc. Since B(Y) can't forward an X header, Rc wraps the packet in a Y header addressed to Rd. When Rd gets the packet from B(Y), it strips off the Y header and forwards the X packet on to right S(X). Packets going from right S(Y) to left S(Y) do the same thing in reverse.

In this example, Rc and Rd treat B(Y) as a lower-level subnetwork, exactly the way an IP router currently treats an Ethernet as a lower-level subnetwork. Also notice that Rc treats Rd as the right "exit router" for packets headed to right S(X), and Rb treats Ra as the right "exit router" for packets headed to left S(Y) ๐Ÿšช.

Now, imagine a routing loop somehow forms. The routers in B(Y) think Rd is reachable via Rb, Rb thinks Rd is reachable via Re, and the routers in B(X) think Re is reachable via Rc. (This could be a temporary glitch in the routing algorithm if Rd and Re crashed at the same time ๐Ÿ˜ฌ.) When the first packet from left S(X) reaches Rc, it gets wrapped in Y and sent into B(Y), which forwards it to Rb. (The notation for this packet is Y<X>, meaning that X is encapsulated in Y.)

When Rb gets Y<X> from B(Y), it wraps the packet in an X header to get it to Re through B(X). Now the packet has headers X<Y<X>>, so it has two X encapsulations. When Rc gets X<Y<X>>, it wraps the packet again, resulting in Y<X<Y<X>>>. The packet keeps growing with every encapsulation ๐Ÿซ .

Now here's the scary part. If each new encapsulation doesn't preserve the hop count from the previous header, the packet will never expire ๐Ÿ’€. Worse, it will eventually hit the Maximum Transmission Unit (MTU) size and fragment. Each fragment keeps circling the loop, getting bigger until those fragments fragment too. The result is an exponential explosion of looping packets! ๐Ÿงจ

The explosion lasts until the links are saturated, and they stay saturated until the loop is broken. If the looping packets crowd out other packets, like routing updates or management packets, and those get thrown away, the loop may not break on its own. That means someone has to step in manually ๐Ÿ†˜. Once the loop is broken, the packets get flushed out of the network pretty quickly.

Potential Fixes ๐Ÿ”ง

Fix #1: preserve the hop count. The first fix that comes to mind is to always preserve the hop count information in the new header. Since hop count info is kept in fragments, the explosion won't happen even if some fragmentation occurs before the hop count runs out. The catch is that not all headers have hop count info (X.25 and SMDS, for instance) ๐Ÿ™ƒ.

Also, hop count ranges differ between protocols, so a direct translation isn't always possible. For example, AppleTalk has a maximum hop count of 16, while IP goes up to 256. You could define a mapping that lowers the hop count to fit into the smaller range when needed. But that can cause unnecessary black holes because the hop counts end up overly small. There are plenty of IP paths that are longer than 16 hops ๐Ÿ—บ๏ธ.

It's worth noting that the current IP over AppleTalk Internet Draft does not preserve hop counts ("A Standard for the Transmission of Internet Packets Over AppleTalk Networks") ๐Ÿ‘€.

Fix #2: peek into the network layer headers. Another potential fix is to have routers peek into network layer headers to see if the planned encapsulation already exists ๐Ÿ•ต๏ธโ€โ™€๏ธ. For example, in Figure 1, when Rb receives Y<X>, it would look at what Y is encapsulating (say, by checking the protocol id field of X's header). It would notice that X has already been encapsulated and throw the packet away. If the encapsulation loop involves more than two protocols, the router might have to peek into successive network layer headers. It would stop when it finally reached a transport layer header.

There are several pitfalls with this approach:

  • Pitfall one: A network layer protocol could be encapsulated within a transport layer protocol, so, I suppose, the router would need to keep peeking even above the transport layer ๐Ÿ˜ตโ€๐Ÿ’ซ.
  • Pitfall two: The router might not recognize one of the network layer headers, which stops it from peeking any further. For example, consider a loop with three routers, Rxy, Ryz, and Rzx, and three protocols X, Y, and Z (the subscripts on the routers show which protocols each router recognizes). After the first loop, Rxy receives X<Z<Y<X>>>. Since Rxy doesn't recognize Z, it can't peek past Z to find the embedded Y header ๐Ÿ™ˆ.
  • Pitfall three: A router might be encrypting the packet it sends to its peer, like Blacker routers do. For example, Rc might be encrypting packets it encapsulates for Rd, expecting Rd to decrypt them. When Rb receives this packet (because of the loop), it can't peek past the Y header ๐Ÿ”’.
  • Pitfall four: Sometimes it's actually appropriate to have multiple instances of the same header. In the nested mutual encapsulation of Figure 2, Ra encapsulates Y in X to reach Rd, but Rb encapsulates X<Y> in Y to reach Rc. In this case, it's appropriate for Rb to transmit a packet with two Y headers ๐Ÿ‘ฏ.

Fix #3: the hybrid. A third (somewhat hybrid) solution is to outlaw nested mutual encapsulation, use both hop count preservation and header peeking where appropriate, and generally discourage mutual encapsulation. (Or you can just adopt the attitude that people who engage in mutual encapsulation deserve what they get ๐Ÿ’…๐Ÿ˜ค.)

                     +--------------------+
                     |                    |
                     |               B(X) |
       +------+      |      +------+      |      +------+
       |      |      |      |      |      |      |      |
       | S(Y) |--Ra--+   Rb-| B(Y) |-Rc   +--Rd--| S(Y) |
       |      |      |      |      |      |      |      |
       +------+      |      +------+      |      +------+
                     |                    |
                     |                    |
                     +--------------------+

                FIGURE 2:  NESTED MUTUAL ENCAPSULATION

Security Considerations ๐Ÿšจ

Security issues are not discussed in this memo. (Yes, this is the part where we all go "hmm." ๐Ÿซฃ Consider it a flag for anyone implementing this stuff. Take the security side seriously and dig into it yourself.)

Author's Address ๐Ÿ–‹๏ธ

Paul Tsuchiya
Bellcore
435 South St.
MRE 2L-281
Morristown, NJ 07960

Phone: (908) 829-4484
EMail:  tsuchiya@thumper.bellcore.com

thanks for reading, bestie!! ๐ŸŒˆ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from