RFC 1934

Ascend's Multilink Protocol Plus (MP+)

πŸ“… published April 1996, from ietf

Okay bestie, the title block first πŸ’… This is RFC 1934, written by K. Smith of Ascend Communications for the Network Working Group. It's filed as Informational and dated April 1996. The header doesn't list anything it obsoletes or updates.

Status of This Memo πŸ“œ

This memo is for information only 🌸 It's aimed at the Internet community, and it does not specify an Internet standard of any kind. Distribution is unlimited, so share it with everyone πŸ¦‹

Abstract ✨

This doc proposes an extension to the PPP Multilink Protocol (MP) [1]. Multilink Protocol Plus (MP+) is a brand new control protocol for managing multiple data links bundled together by MP. It's giving upgrade energy πŸš€

Table Of Contents πŸ—‚οΈ

1.      Introduction.................................................2
        1.1     Functional Description...............................2
        1.2     Conventions..........................................3
2.      General Overview.............................................3
        2.1     Operation............................................4
3.      MP+ Frame Formats............................................4
        3.1     Error Control (EC) Layer.............................6
                3.1.1   Error Control State Machine..................7
        3.2     Multilink Plus Control Messages......................9
        3.3     Multilink Plus Message Formats......................10
                3.3.1   VERSION_EXCHANGE_REQ Message Format.........10
                3.3.2   VERSION_EXCHANGE_RSP Message Format.........12
                3.3.3   ADD_REQ Message Format......................13
                3.3.4   ADD_RSP Message Format......................15
                3.3.5   ADD_COMPLETE Message Format.................16
                3.3.6   REMOVE_REQ Message Format...................17
                3.3.7   REMOVE_RSP Message Format...................17
                3.3.8   REMOVE_COMPLETE Message Format..............18
                3.3.9   CLOSE_REQ Message Format....................19
                3.3.10  CLOSE_RSP Message Format....................19
                3.3.11  REMOTE_MGMT_REQ Message Format..............20
                3.3.12  REMOTE_MGMT_RSP Message Format..............20
                3.3.13  REMOTE_MGMT_RX_REQ Message Format...........21
                3.3.14  REMOTE_MGMT_TX_REQ Message Format...........22
                3.3.15  REMOTE_MGMT_TX_RSP Message Format...........22
                3.3.16  CLEAR_REQ Message Format....................23
        3.4     Events..............................................23
        3.5     State Machine.......................................25
                3.5.1   States......................................25
                3.5.2   Common Actions..............................26
                3.5.3   MP+STATE_INITIAL state machine..............32
                3.5.4   MP+STATE_IDLE state machine.................35
                3.5.5   MP+STATE_ADD state machine..................37
                3.5.6   MP+STATE_REMOVE state machine...............41
                3.5.7   MP+STATE_CLOSE state machine................44
4.      PPP LCP Extensions..........................................46
5.      Security Considerations.....................................47
6.      References..................................................47
7.      Author's Address............................................47

1. Introduction 🌈

So the PPP Multilink Protocol (MP) is a set of features that does inverse multiplexing at the packet/fragment level. It bundles multiple independent links between a fixed pair of systems, which gives you one virtual link with more bandwidth than any single member on its own. It's giving speed πŸ’¨

Once multiple channels are up, MP handles managing channel use so user packets still arrive in sequence 🧚

MP+ is an extension to MP that adds an inband control channel, which unlocks a whole new level of session management and control πŸ‘‘

MP+ also lets you remotely manage devices that aren't configured yet 🫢 A network operations center can dial into an unconfigured system and manage it before the ethernet interface, IP address, and other LCP and system configuration info is entered. (You do need to set up the WAN interfaces locally, just enough to answer an incoming call.)

1.1 Functional Description πŸ’–

Here's what MP+ brings to the table:

  • Ability to negotiate to add and subtract channels when bandwidth needs change.
  • Phone number management so calling stations need not know every possible number; answering stations can manage their own resources.
  • A simple remote management interface.

To pull all of that off, MP+ is split into a call management layer and a reliable delivery layer. The call management layer is the source and sink of MP+ control messages. The reliable delivery layer adds a simple acknowledge and retry mechanism. Two layers, one vibe πŸŽ€

MP+ only uses network bandwidth while it's busy with a user request, like adding or subtracting bandwidth. Very efficient, very iconic ✨

NOTE: Neither MP, or MP+ define the process that makes the bandwidth requirement determination. That is outside the scope of either of these protocols and will likely be implementation dependent. (So that part is up to whoever builds it πŸ™ˆ)

1.2 Conventions πŸ“š

These are the language conventions used in the items of specification in this document:

  • MUST, SHALL or MANDATORY -- the item is an absolute requirement of the specification.
  • SHOULD or RECOMMENDED -- the item should generally be followed for all but exceptional circumstances.
  • MAY or OPTIONAL -- the item is truly optional and may be followed or ignored according to the needs of the implementor.

2. General Overview πŸ¦‹

PPP To set up communications over a point-to-point link, each end of the PPP [2] link has to send LCP packets first to configure the data link during the link establishment phase. Once the link is up, PPP provides an authentication phase πŸ”

MP The goal of multilink operation is to bundle multiple independent links between a fixed pair of systems, which gives a virtual link with greater bandwidth than any of the constituent members. Bundles, bundles, bundles πŸ“¦

MP+ MP+ is also negotiated during the initial LCP option negotiation. A system tells its peer it's willing to do MP+ by sending the MP+ option as part of that initial LCP option negotiation. The MP+ option MUST NOT be negotiated unless MP is also negotiated. When it's used, MP+ adds a virtual unit-to-unit control channel πŸ’œ

A peer has a few options for how it responds:

  • Acknowledge both the MP and MP+ options, indicating that both MP and MP+ will be used.
  • Acknowledge the MP option and reject the MP+ option. Operation will fall back to MP.
  • Reject both options. Standard PPP will be used for this connection.

2.1. Operation πŸŽ€

Standard PPP In standard PPP, the LCP negotiation phase is followed by an optional authentication phase, and then one or more NCPs get initiated.

PPP with MP The LCP negotiation phase and authentication phase are identical to standard PPP. The ability to start an MP aggregate data link gets signaled by sending an MP option, as described in [1] 🌸

PPP with MP and MP+ When MP+ is negotiated at LCP startup, the same procedures get followed as when MP is negotiated alone. The MP+ LCP option is negotiated to signal the ability to use the MP+ feature. The first connection between endpoints kicks off the MP+ process for that connection πŸš€

3. MP+ Frame Formats 🧁

Here's the long sequence number format:

                    +---------------+---------------+
       PPP Header:  | Address 0xff  | Control 0x03  |
                    +---------------+---------------+
                    | PID(H)  0x00  | PID(L)  0x73  |
                    +-+-+-+-+-------+---------------+
       MP Header:   |1|1|0|0|0|0|0|1| seq # high    |
                    +-+-+-+-+-------+---------------+
                    |   sequence number low bits    |
                    +---------------+---------------+
                    |         control data          |
                    |               .               |
                    |               .               |
                    |               .               |
                    +---------------+---------------+
       PPP FCS:     |              FCS              |
                    +---------------+---------------+

Figure 1: Multilink Plus Frame Format (long sequence number format)

And here's the short sequence number format:

                    +---------------+---------------+
       PPP Header:  | Address 0xff  | Control 0x03  |
                    +---------------+---------------+
                    | PID(H)  0x00  | PID(L)  0x73  |
                    +-+-+-+-+-------+---------------+
       MP Header:   |1|1|0|1|  sequence number      |
                    +-+-+-+-+-------+---------------+
                    |         control data          |
                    |               .               |
                    |               .               |
                    |               .               |
                    +---------------+---------------+
       PPP FCS:     |              FCS              |
                    +---------------+---------------+

Figure 2: Multilink Plus Frame Format (short sequence number format)

MP+ frames use a similar structure to MP fragments, so they look like cousins πŸ‘―β€β™€οΈ

The MP+ assigned PID is designated 00 73 πŸ”’

MP+ control follows these two rules:

  • MP+ control frames have their own sequence number space, controlled by MP+.
  • MP+ control frames MUST NOT be fragmented.
NOTE: Implementations of this protocol prior to the date of submission of this specification to the IETF use the same PID as MP, but set the LSB of the reserved bits in the MP header to 1. This is how MP+ packets are told apart from MP fragments. So the header of an MP+ packet looks like: 00 3d c1 ...... As compared to an MP packet that looks like: 00 3d c0 ...... or 00 3d 80 ...... or 00 3d 40 ......

3.1. Error Control (EC) Layer (MP+ control only) 🫢

okay so the error control layer that runs over the virtual inband channel is giving minimal, and i am obsessed 😭 it's still handling the fact that the line can have errors on it, just in the simplest way possible ✨

the big assumption here is that errors are rare, and messages are rarely if ever dropped on the floor πŸ™ˆ so "timing out" on a retransmission doesn't really hurt anything. if a message doesn't get through, it just gets retried a set number of times. once it gives up, the only thing left to do is tell the call management layer (of MP) that the session is dead πŸ’€

                    +---------------+---------------+
       PPP Header:  | Address 0xff  | Control 0x03  |
                    +---------------+---------------+
                    | PID(H)  0x00  | PID(L)  0x73  |
                    +-+-+-+-+-------+---------------+
       MP+ Header:  |1|1|0|0|0|0|0|1| seq # high    |
                    +-+-+-+-+-------+---------------+
                    |   sequence number low bits    |
                    +---------------+---------------+
        EC Header:  | Error Control Message Type    |
                    |   32 bits reserved            |
                    +---------------+---------------+
         MP+ Data:  |    MP+ Message                |  May not be
                    |                               |  present.

   Figure 3: MP+ control message format (shown long sequence number
             format)

the Error Control Message Type field tells you what kind of EC message you're looking at πŸŽ€

  Error Control Message Type:

   1      DATA_MSG:         This message contains MP+ data transferred
                            between the peers.

   2      ACK_MSG:          An acknowledgement of a previous data message.

when the type is DATA_MSG, the rest of the frame holds an MP+ Control message πŸ“¦

when the type is ACK_MSG, the rest of the frame is just the PPP Frame Check Sum (FCS) and nothing else πŸ¦‹


3.1.1. Error Control State Machine πŸ’œ

this layer runs on a simple state machine with three states 🧚

  • Stopped: there's no connection between the peers.
  • Idle: there's a connection between the peers, and nothing is waiting on an acknowledgement.
  • Pending: there's a connection between the peers, and it's waiting on an acknowledgement for the last message that got sent.

messages from the call management layer get queued for transmission whenever the link is in the Pending state πŸ“ to keep things simple, only one outstanding message can be on the link at a time ✨ the whole procedure is laid out in table 1 πŸ‘‘

Event                           State
______________________________________________________________________
                                Stopped    Idle         Pending
======================================================================
Start                           1,Idle     -,*          -,*
______________________________________________________________________
Received ACK_MSG                **         2,Start      5,Idle|Pending
current tx sequence number
______________________________________________________________________
Received ACK_MSG                **         -,*          -,*
last tx sequence number
______________________________________________________________________
Received ACK_MSG                **         2,Start      2,Start
other tx sequence number
______________________________________________________________________
Received DATA_MSG               **         6,*          6,*
current rx sequence number
______________________________________________________________________
Received DATA_MSG               **         7,*          7,*
previous rx sequence number
______________________________________________________________________
Received DATA_MSG               **         2,Start      2,Start
other rx sequence number
______________________________________________________________________
Receive Invalid Frame           **         2,Start      2,Start
______________________________________________________________________
Retransmit Timer Expire         **         **           4,Start|*
______________________________________________________________________
______________________________________________________________________
Transmit Request from call      -,*        3,Pending    8,*
management layer
______________________________________________________________________
Stop                            9,Start    9,Start      9,Start
______________________________________________________________________

                  Table 1: Error Control State Machine

Legend:

        -       No action

        *       Stay in same state

        **      Invalid or meaningless event for state, ignored.

a few notes to keep in your back pocket πŸ”₯

Note [1]: data from the call management layer always gets copied before it's queued for transmission πŸ’… the call management layer is in charge of its own buffers, not EC.

Note [2]: MP always copies data for transmission and returns right away 🌸 any buffers allocated to build control messages MUST be released immediately upon return from MP transmission requests, no exceptions bestie 😀

here's what each numbered action does when the table tells you to run it ⭐

Actions:

   1       Reset rx sequence number
           Reset tx sequence number
           Reset tx retransmit count
           Stop retransmit timer

   2       Report error to user
           Stop retransmit timer
           Stop frame transmit timer
           Free buffers

   3       Save call management message in pending transmit queue
           Build DATA_MSG from first message in pending transmit
           queue using current tx sequence number.
           Send message to MP for transmission.
           Reset tx retransmit count

   4       Increment tx retransmit count
           If tx retransmit count >= RETRANSMIT_COUNT
                   Action 2 (followed by state change to the Start state)
           else
                   Build DATA_MSG from first message in pending
                   transmit queue using current tx sequence number.
                   Send message to MP for transmission.

   5       Dequeue first element on pending transmit queue and release
           its buffer
           Increment the tx sequence number
           Stop the retransmit timer
           if pending transmit queue not empty
                   Build DATA_MSG from first message in pending
                   transmit queue using current tx sequence number.
                   Send message to MP for transmission.
                   Reset tx retransmit count

   6       Build ACK_MSG using the current rx sequence number
           Send ack message to MP for transmission
           Pass message to call managment layer
           Increment rx sequence number

   7       Build ACK_MSG using the previous rx sequence number
           Send the ack message to MP for transmission

   8       Add the message to the end of the pending transmit queue

   9       Stop retransmit timer
           Free buffers

these are the MP+ control message types and the value each one gets πŸŽ€ you'll see them all again in the sections that follow 🧚

    Message Type                Value
    VERSION_EXCHANGE_REQ        1
    VERSION_EXCHANGE_RSP        2
    ADD_REQ                     3
    ADD_RSP                     4
    ADD_COMPLETE                5
    REMOVE_REQ                  6
    REMOVE_RSP                  7
    REMOVE_COMPLETE             8
    CLOSE_REQ                   9
    CLOSE_RSP                   10
    REMOTE_MGMT_REQ             11
    REMOTE_MGMT_RSP             12
    REMOTE_MGMT_RX_REQ          13
    REMOTE_MGMT_TX_REQ          14
    REMOTE_MGMT_TX_RSP          15
    CLEAR_REQ                   16

every field in every message defined here MUST be encoded and decoded in Network Byte Order (big endian) 😀 no skipping this one, it's non-negotiable πŸ’…

3.3.1. VERSION_EXCHANGE_REQ Message Format 🌈

the version exchange message is the call originator's way of telling the answerer which MP+ protocol version it's running, plus any other info that needs to get across outside the normal PPP parameter negotiation 🫢

   +---------------+---------------+
   |         Message type          |
   |          0x00000001           |
   +---------------+---------------+
   |       Protocol Version        |
   +---------------+---------------+
   |      Protocol Revision        |
   +---------------+---------------+
   |       Session Identifier      |
   +---------------+---------------+
   |         Hardware Type         |
   +---------------+---------------+
   |          Nailed Mode          |
   +---------------+---------------+
   |   Use Multiple Trunk Groups   |
   +---------------+---------------+
   |       Descriptor Length       |
   +---------------+---------------+
   |          Descriptor           |
   +---------------+---------------+

   Figure 4:  Version Exchange Request

so the caller sends this to the answerer to share its protocol version and state info, and to ask the answerer to send its own version info back πŸ’–

  • Protocol Version: the caller's MP+ protocol version number. 2 octets, fixed length (initially 1).
  • Protocol Revision: the caller's MP+ protocol revision number. 2 octets, fixed length (initially 4).
  • Session Identifier: a non-zero identifier that's unique to the caller. 2 octets, fixed length.
  • Hardware Type: the caller's hardware type (this can be vendor defined). 2 octets, fixed length.
  • Nailed Mode: the caller's nailed mode, taken from the session profile. 2 octets, fixed length.
  • Use Multiple Trunk Groups: non-zero if the call may use channels from multiple trunk groups. 2 octets, fixed length.
  • Descriptor Length: the length of the end point descriptor. 2 octets, fixed length.
  • Descriptor: the end point descriptor πŸ”₯ this field lets a vendor identify its peer in a vendor-specific way. It's variable length, as defined above.

3.3.2. VERSION_EXCHANGE_RSP Message Format ✨

okay so the version exchange response is what the call answerer sends back after getting a version exchange request πŸ’Œ The answerer uses it to tell the caller which MP+ protocol version is being used, plus any other info that needs to get across outside the normal PPP parameter negotiation πŸŽ€

   +---------------+---------------+
   |         Message type          |
   |          0x00000002           |
   +---------------+---------------+
   |      Protocol Version         |
   +---------------+---------------+
   |     Protocol Revision         |
   +---------------+---------------+
   |       Session Identifier      |
   +---------------+---------------+
   |         Hardware Type         |
   +---------------+---------------+
   |          Nailed Mode          |
   +---------------+---------------+
   |   Use Multiple Trunk Groups   |
   +---------------+---------------+
   |       Descriptor Length       |
   +---------------+---------------+
   |         Descriptor            |
   +---------------+---------------+

Figure 5: Version Exchange Response

A message sent from call answerer to the call originator specifying the answerers protocol version and other state info. Sent in response to receiving a version exchange request. πŸ¦‹

  • Protocol Version: caller MP+ protocol version number. 2 octets fixed length (initially 1) 🌸
  • Protocol Revision: caller MP+ protocol revision number. 2 octets fixed length (initially 4) πŸ’œ
  • Session Identifier: A non-zero identifier unique to the answerer. 2 octets fixed length. πŸ”₯
  • Hardware Type: caller hardware type (can be vendor defined). 2 octets fixed length. 🧚
  • Nailed Mode: caller nailed mode from the session profile. 2 octets fixed length. ⭐
  • Use Multiple Trunk Groups: non-zero if call may use channels from multiple trunk groups. 2 octets fixed length 🌈
  • Descriptor Length: length of the remote descriptor in 4-octet units. 2 octets fixed length πŸ“
  • Descriptor: the remote unit descriptor. This field allows for vendor specific identification of the peer. Variable length Nx4 octets long, total length defined above. πŸ‘‘

3.3.3. ADD_REQ Message Format πŸ’…

ADD_REQ is sent by either the caller or the answerer when they want to increase bandwidth πŸ“ˆ If the caller sends it, it's asking permission to dial a certain number of channels, and the response will have the permission plus the phone numbers to dial. If the answerer sends it, this message is the one carrying the phone numbers to dial πŸ“ž The message looks like this:

   +---------------+---------------+
   |         Message type          |
   |          0x00000003           |
   +---------------+---------------+
   | Number of channels requested  |
   +---------------+---------------+
   |    Number of phone numbers    |
   +---------------+---------------+
   |    A phone number list for    |
   |      each phone number        |
   |               .               |
   |               .               |
   |               .               |
   +---------------+---------------+

Figure 6: Add Request

A message sent by either caller or answerer to request that additional bandwidth be added to a session. 🫢

  • Number of channels requested: The maximum number of channels to add. 2 octets fixed length. ✨
  • Number of phone numbers: The number of phone numbers provided. This value will always be zero when the caller initiates an add and will be at least Number of channels requested when the answerer initiates the add. 2 octets fixed length. πŸ’–
  • Phone number list: A list of up to 32 phone number lists containing the phone numbers to call. Each description is of fixed length as described below. πŸŽ€

Each phone number is represented by a phone number list. The format of a phone number list is:

   +---------------+---------------+
   |          in use flag          |
   +---------------+---------------+
   |        call service type      |
   +---------------+---------------+
   |         Phone number          |
   |          20 octets            |
   |     plus null terminator      |
   |       (21 octet total)        |
   |                               |
   |                               |
   |                               |
   |                               |
   |                               |
   |                               |
   |               +---------------+
   |               |  Must be 0    |
   +---------------+---------------+
   |           must be 0           |
   +---------------+---------------+

Figure 7: Phone number list

A structure containing information about a connection within the system. πŸ¦‹

  • in use flag: non-zero if the phone number indicated in this descriptor is currently in use. 2 octets fixed length 🌸
  • call service type: Defines the type of service, switched, nailed, or other, associated with a phone number. 1 Nailed, 2 Switched, >=3 Undefined πŸ”₯
  • Phone number: The null terminated phone number of this channel. Fixed length 21 octets. Each octet contains IA5 character representation of a digit (or #, *). 🧚
  • Must be 0: Filler to force alignment to 32-bit boundary. 🌈

3.3.4 ADD_RSP Message Format πŸ’œ

ADD_RSP gives permission to dial some number of channels. When the answerer of the original call sends it, it also gives the phone numbers of the channels to dial πŸ“²

   +---------------+---------------+
   |         Message type          |
   |          0x00000004           |
   +---------------+---------------+
   |  Number of channels allowed   |
   +---------------+---------------+
   |    Number of phone numbers    |
   +---------------+---------------+
   |   A  phone number list for    |
   |      each phone number        |
   |               .               |
   |               .               |
   |               .               |
   +---------------+---------------+

Figure 8: Add Response

A message sent by either caller or answerer to indicate the number of channels that may be added to a session. ✨

  • Number of channels allowed: The actual number of channels to add. This may be less than the number requested. 2 octets fixed length. πŸ“
  • Number of phone numbers: The number of phone numbers provided. This value will always be zero when sent by the caller and will be at least channelCount when sent by the answerer. 2 octets fixed length. πŸ‘‘
  • Phone number list: A list of up to 32 phone number lists containing the phone numbers to call. Each description is of fixed length as described above. πŸ’…

3.3.5. ADD_COMPLETE Message Format πŸŽ‰

This one is sent by the caller to the answerer after all the calls have been placed πŸ“ž It tells the answerer the add transaction is complete and it may return to the idle state. Done and dusted, iykyk πŸ’€

   +---------------+---------------+
   |         Message type          |
   |          0x00000005           |
   +---------------+---------------+
   |       Channels added          |
   +---------------+---------------+
   |          Must be zero         |
   +---------------+---------------+

Figure 9: Add Complete

A message sent by caller to indicate the number of channels that were added successfully. This message was added in MP+ Version 1.1. 🌸

  • Channels added: The actual number of channels added. 2 octets fixed length πŸ¦‹
  • Must be zero: Padding to 32-bit boundary. 2 octets fixed length πŸ’–

3.3.6. REMOVE_REQ Message Format πŸ™ˆ

A REMOVE_REQ gets sent when a peer decides, for any reason, to remove channels from use 😭 The point is to tell the other end about the remove and give it a chance to adjust the number of channels being removed.

   +---------------+---------------+
   |         Message type          |
   |          0x00000006           |
   +---------------+---------------+
   | Number of channels to remove  |
   +---------------+---------------+
   |          Must be zero         |
   +---------------+---------------+

Figure 10: Remove Request

A message sent by either caller or answerer to request that bandwidth be removed from a session. 🧚

  • Number of channels to remove: The maximum number of channels to remove. 2 octets fixed length πŸŽ€
  • Must be zero: Padding to 32-bit boundary. 2 octets fixed length 🌈

3.3.7. REMOVE_RSP Message Format πŸ’…

This is the reply to a remove request. The responder says how many channels can be removed. If the response says 0 channels, the remove is cancelled 🚫

   +---------------+---------------+
   |         Message type          |
   |          0x00000007           |
   +---------------+---------------+
   | Number of channels to remove  |
   +---------------+---------------+
   |          Must be zero         |
   +---------------+---------------+

Figure 11: Remove Response

A message sent in response to a remove request specifying the number of channels that the peer agrees can be removed. πŸ’œ

  • Number of channels to remove: The maximum number of channels to remove. May be zero, in which case the remove is cancelled. 2 octets fixed length πŸ‘‘
  • Must be zero: Padding to 32-bit boundary. 2 octets fixed length ⭐

3.3.8. REMOVE_COMPLETE Message Format πŸ₯Ή

This message is sent by whoever started the remove transaction once the agreed number of channels have been removed 🎊 It tells the peer the remove transaction is complete and it may return to the idle state.

   +---------------+---------------+
   |         Message type          |
   |          0x00000008           |
   +---------------+---------------+
   | Number of channels removed    |
   +---------------+---------------+
   |          Must be zero         |
   +---------------+---------------+

Figure 12: Remove Complete

A message sent by the caller or answerer to indicate how many channels were actually removed. This message was added in MP+ CM version 1.1. πŸ¦‹

  • Number of channels removed: The number of channels that were removed. 2 octets fixed length 🌸
  • Must be zero: Padding to 32-bit boundary. 2 octets fixed length πŸ”₯

3.3.9. CLOSE_REQ Message Format πŸ‘‹

This message is sent when the peer wants to close the whole session πŸšͺ It's typically triggered by a configuration option that says when a system should ask to close the session, for example when a link has been idle for longer than a preconfigured time period πŸ’€

   +---------------+---------------+
   |         Message type          |
   |          0x00000009           |
   +---------------+---------------+

Figure 13: MP+ close request.

There are no data fields associated with this message. 🫧

3.3.10. CLOSE_RSP Message Format 🌸

Okay so this is the reply to a close request πŸ’… It's sent when the peer is cool with closing the session based on its own configuration. Example reject reason: the peer is set up with a minimum number of channels it wants to keep active, so no closing for them πŸ™ˆ

+---------------+---------------+
|         Message type          |
|          0x0000000a           |
+---------------+---------------+
|          OK To Close          |
+---------------+---------------+
|          Must be zero         |
+---------------+---------------+

Figure 14: MP+ close response

The response to a close request. It may be sent by the caller or the answerer. πŸ¦‹

OK To Close: If non-zero, the peer is saying "I can close all channels." πŸ’œ 2 octets fixed length

Must be zero: Padding to 32-bit boundary. πŸŽ€ 2 octets fixed length

3.3.11. REMOTE_MGMT_REQ Message Format ✨

This one goes from a master station to a slave station when the master wants to manage the remote station πŸ‘‘ It's also what cancels remote management once it's already been started. Main character energy, literally.

+---------------+---------------+
|         Message type          |
|          0x0000000b           |
+---------------+---------------+
|              Mode             |
+---------------+---------------+
|          Must be zero         |
+---------------+---------------+

Figure 15: Remote Management Request

A message sent from master to slave to start or clear a remote management session. 🧚

Mode: One to start session. Zero to stop session. 2 octets fixed length

Must be zero: Padding to 32-bit boundary. πŸŽ€ 2 octets fixed length

3.3.12. REMOTE_MGMT_RSP Message Format πŸ¦‹

The slave side of a remote management session gets to decide whether it's down for remote management or not πŸ™…β€β™€οΈ The master finds out whether it was accepted or denied through this remote management response. Iconic.

+---------------+---------------+
|         Message type          |
|          0x0000000c           |
+---------------+---------------+
|              Mode             |
+---------------+---------------+

Figure 16: Remote Management Response

A message sent from slave to master to allow or deny starting a remote management session. πŸ’–

Mode: One to accept session. Zero to deny session. 2 octets fixed length

Must be zero: Padding to 32-bit boundary. πŸŽ€ 2 octets fixed length

3.3.13. REMOTE_MGMT_RX_REQ Message Format ⌨️

This type carries keyboard input from the management master over to the management slave to get processed 😭 The message is an octet count (in network byte order) followed by an array of octets to process. It looks like this:

+---------------+---------------+
|         Message type          |
|          0x0000000d           |
+---------------+---------------+
|         character count       |
+---------------+---------------+
|      array of characters      |
|               .               |
|               .               |
|               .               |
+---------------+---------------+

Figure 17: Remote Management Receive Request

A message sent from master to slave, carrying keystrokes typed on the master's keyboard that the slave will process. 🫢

character count: Number of characters to process. 2 octets fixed length

array of characters: Array of characters to process.

3.3.14. REMOTE_MGMT_TX_REQ Message Format πŸ“

The remote management slave sends output to show up on the master's terminal, using a remote management transmit request. Only one message can be outstanding at a time πŸ™ˆ The next transmit request can't go out until the previous one has been acknowledged. Patience, bestie ✨

+---------------+---------------+
|         Message type          |
|          0x0000000e           |
+---------------+---------------+
|         character count       |
+---------------+---------------+
|      array of characters      |
|               .               |
|               .               |
|               .               |
+---------------+---------------+

Figure 18: Remote Management Transmit Request

A message sent from slave to master, carrying output to be shown on the master's display. 🌈

Character count: Number of characters to process. 2 octets fixed length

array of characters: Array of characters to process.

3.3.15. REMOTE_MGMT_TX_RSP Message Format πŸ’œ

This is the ack for remote management transmit requests 🫢 Once the slave gets this message, it's allowed to send the next transmit request.

+---------------+---------------+
|         Message type          |
|          0x0000000f           |
+---------------+---------------+

Figure 19: Remote Management Transmit Response

There are no data fields in this message. Super simple, no cap. πŸ’…

3.3.16. CLEAR_REQ Message Format πŸŒ™

This message starts a friendly shutdown of an MP+ link πŸ¦‹ The sender stops sending data right away. The receiver also stops sending user data and begins a clean shutdown of all NCPs and the LCP on each member link of the bundle. Once the last member link terminates, the whole session is completely closed. Bye bye, bundle πŸ‘‹

+---------------+---------------+
|         Message type          |
|          0x00000010           |
+---------------+---------------+

Figure 20: Clear Request

There are no data fields in this message. ✨


3.4. Events πŸŽ€

The MP+ state machine is event driven, which is giving very reactive. When an event comes in, it triggers an action and maybe a state change. The events fall into roughly two types:

  • Events that originate within the unit, e.g. notification that a call has cleared, or that an MP+ session may be started.
  • Events that originate with the reception of an MP+ control message from the peer unit.

Both types get processed by the state machine in the order they happened πŸ”₯ The events are:

MP+START_SESSION:    Notification from PPP/MP that an
                     MP+ session is starting.

MP+SESSION_DOWN:     Notification from the error-control
                     layer that end-to-end connectivity
                     has been lost and control messages can
                     not be delivered.

MP+SESSION_TERM:     Session termination notification from
                     PPP/MP.  This event is not sent until
                     the last channel of a multi-channel
                     session is cleared.

MP+TIMER_EXPIRED:    Timers are used in various states and
                     sub-states.  This event is signaled whenever
                     a timer expires.

MP+CALL_COMPLETE:    A call placed during an add request has
                     completed.  The call may have succeeded or
                     failed.

MP+UTILIZATION:      Notification from MP/PPP that link
                     utilization has crossed a threshold and that
                     channels may need to be added/removed.
                     (The number of channels to add/remove will be
                      passed with the notification).

MP+RX_VERSION_REQ:   A Version Exchange request message has
                     been received from the peer.

MP+RX_VERSION_RSP:   A Version Exchange response message has
                     been received from the peer.

MP+ADD_REQ:          An Add request message has been received
                     from the peer.

MP+ADD_RSP:          An Add response message has been received
                     from the peer.

MP+ADD_COMP:         An Add Complete message has been received
                     from the peer.

MP+REMOVE_REQ:       A Remove request message has been received
                     from the peer.

MP+REMOVE_RSP:       A Remove response message has been
                     received from the peer.

MP+REMOVE_COMP:      A Remove Complete message has been received
                     from the peer.

MP+RX_RM_REQ:        A Remote Management request has been received
                     from the peer.

MP+RX_RM_RSP:        A Remote Management response has been received
                     from the peer.

MP+RX_RM_RX_REQ:     A Remote Management Receive Request has been
                     received from the far end.

MP+RX_RM_TX_REQ:     A Remote Management Transmit Request has
                     been received from the peer.

MP+RX_RM_TX_RSP:     A Remote Management Transmit Response has
                     been received from the peer.

MP+RX_CLEAR:         A request to shut down the session has been
                     received from the peer.

MP+CLOSE_REQ:        A Close Request message has been received
                     from the peer.

MP+CLOSE_RSP:        A Close Response message has been received
                     from the peer.

MP+START_RM          Request to start a remote management session
                     with this station being the master.

MP+SEND_RMS:         Request to send data to a remote management
                     master from a slave.

MP+SEND_RMM:         Request to send data to a remote management
                     slave from a master.

MP+RECV_RMM:         Request to send an ack to a remote management
                     slave for data received from the slave.

MP+STOP_RM:          Request to stop a remote management session.

3.5. State Machine πŸ’–

3.5.1. States ✨

To make things easier to read and understand, the major states are treated as separate state machines, each with two to four sub-states 🧚 The sub-states are named by the letters A, B, C, and D. State information is kept for every interface.

The major states are:

MP+STATE_INITIAL: The state of an unused session. Session table
                  entries are intialized to this state at startup
                  and return to this state when sessions are
                  terminated.

MP+STATE_IDLE:    The state of an active session that is not
                  performing any MP+ function.

MP+STATE_ADD:     The state of a session when an add transaction is
                  in progress.

MP+STATE_REMOVE:  The state of a session when a remove transaction is
                  in progress.

MP+STATE_CLOSE:   The state of a session that is in the process of
                  being closed.

State transitions are triggered when an event is received. Tables 2 through 6 have the state tables for the major states. All state tables use these symbols:

     -       No action

     *       Stay in same state

     +       Target state is defined by the action taken

     **      An error has occurred, log an error message but no
             state change.

States and sub-state transitions are written as state:sub-state, e.g., initial:A. Alternative transitions are listed on separate lines. 🌸

3.5.2. Common Actions πŸ¦‹

Some actions are shared by all states, so they're defined here πŸ’…

Error Close Action

Called to close a session when an error occurs. The actions are:

[1]  Stop timer if running.

[2]  Log an error message.

[3]  Close the MP+EC layer for this session.

[4]  Close MP for this session

[5]  Clean up, restore state variables to their initial state.

Okay bestie, the Term Action is the "we're done here, pack it up" move πŸ’…. It runs when a MP+SESSION_TERM event shows up in most states, and it does four things:

  1. Stop the timer if it's running ⏱️
  2. Close the MP+EC layer for this session πŸ”Œ
  3. Call the passed termination callback function, but only if it isn't null πŸ“ž
  4. Clean up and restore the state variables to their initial state ✨

Ignore Action is the most chill one ever. We don't care about this event in this state, so we do absolutely nothing πŸ™ˆ

Timer Action runs when a timer expires in one of the on-line states πŸ•°οΈ. The timer handles add and remove locks πŸ”’. A lock gets set when an add or remove fails, and it stays on until there's a bandwidth change or the timer expires. This keeps us from spamming retries of adds and subtracts until there's a real chance they'll work 🫢.

  1. Check the add lock flag.
    1. If it's set, an add lock happened during the last timeout period, so triple the timeout value (to a max of 81 minutes) πŸ“ˆ.
    2. If it's not set, restore the timeout value to its initial value of one minute ⏳.
  2. Clear the add lock flag.
  3. Clear the remove lock flag.
  4. Restart the retry timer.

Enter Remove [local] Action is when the local unit starts a remove transaction, and we're given the desired bandwidth πŸ—‘οΈ.

  1. Restart the idle timer.
  2. Calculate how many channels to remove (the difference between the number in use and the number desired).
  3. Build a remove request and send it to the remote.
  4. Go to REMOVE:A.

Enter Remove [remote] Action is when the remote unit starts a remove transaction, and the incoming message tells us how many channels to remove πŸ“¨.

  1. Restart the idle timer.
  2. Request the number of channels required. If that's more than the number available after removing the channels in the incoming message, reduce the number of channels to remove and set a remove lock πŸ”’.
  3. Build a remove response saying how many channels we'll let the requester remove, and send it to the remote.
  4. Go to REMOVE:B.

Enter Add [local] Action is when the local unit starts an add transaction. We're given the number of channels we want 🌈.

  1. Restart the idle timer.
  2. Calculate how many channels to add (the difference between the number desired and the number in use).
  3. Reserve that many channels, retrieving their phone numbers πŸ“±.
  4. If fewer channels were reserved than desired, set an add lock πŸ”’.
  5. If the number of channels reserved is greater than zero:
    1. Build an add request. If we're the answerer, the request includes the phone numbers for the caller to dial.
    2. If we're the caller, go to ADD:A.
    3. If we're the answerer, go to ADD:C.
  6. Go to the IDLE state.

Enter Remove [remote] Action (the second version) is also when the remote unit starts a remove transaction, and the incoming message has the number of channels to remove 🫧.

  1. Clear the remove lock πŸ”“.
  2. Restart the idle timer.
  3. Request the number of channels required. If that's greater than the number available after removing the channels in the incoming message, reduce the number of channels to remove.
  4. Build a remove response message indicating how many channels we'll let the requester remove, and send it to the remote.
  5. Go to REMOVE, sub-state B.

Enter Add [remote answerer] Action is when we get a message from the remote asking to add bandwidth. The message has the number of channels to add, and since the remote is the answerer, it also has the phone numbers to dial πŸ“ž. We might dial fewer than requested, which is totally fine πŸ’….

  1. Restart the idle timer.
  2. If the requested number of channels would put us over the maximum allowed for the session, reduce the channel count.
  3. For each channel to add:
    1. Combine the phone number returned from the answerer with the original phone number dialed.
    2. Request that a session be extended by dialing the combined phone number. A callback goes along with the request, so MP+ can hear back about success or failure πŸ™Œ.
  4. Go to ADD:B.
Note: This change must actually happen before we request the first outgoing call. If it doesn't, the callback could get called (and ignored) because the session isn't in the correct state πŸ™ˆ.

Enter Add [remote caller] Action is when we get a message from the remote asking to add bandwidth. The message has the number of channels to add. Since the remote is the caller, it needs us to send the phone numbers to dial. We might send fewer phone numbers than requested 🌸.

  1. Restart the idle timer.
  2. If the requested number of channels would put us over the maximum allowed for the session, reduce the channel count.
  3. Reserve the adjusted number of channels, retrieving their phone numbers.
  4. If the number of channels reserved is less than the adjusted number requested.
  5. Build an add response message, including the phone numbers for the channels we'll let the caller add, and send it to the far end πŸ“€.
  6. Go to ADD:C.

Enter Idle Action is where we land at the end of normal transactions 🏁. When we enter, we should check the current status of the connection and start new transactions if needed. To be safe, this state can also act as a catch-all for releasing any bandwidth reserved for adds 🧹. Here's what it does:

  1. Restart the idle timer using the current retry value.
  2. Release any reserved bandwidth that isn't actually in use.
  3. Check whether a bandwidth change was requested during the last transaction. If one was indicated:
    1. Query the channel counts.
    2. If the current bandwidth is less than the suggested bandwidth and removes aren't locked, store the requested bandwidth and start a remove transaction (Enter Remove Action).
    3. If the current bandwidth is greater than the suggested bandwidth and adds aren't locked:
      1. Store the requested bandwidth.
      2. Start an add transaction (Enter Add [local] Action).
  4. Go to the IDLE state.

Remote Management Request Action is when we get a request to start or stop remote management πŸ–₯️. The logic goes like this:

If this is a start request
        If we can/allow remote management:
                Build and send a Remote management response Allow
                message.
        Else
                Build and send a Remote management response Deny
                message.
Else (this is a stop)
        Notify the remote management slave process to terminate.

Remote Management Response Action is when we get a response to our remote management start request πŸ’Œ. If the response was an Allow, we tell the remote management master process that it can start sending keystrokes and commands ⌨️. If not, the peer said no, so we tell the master process that it failed 😭.

If the response was an Allow response
        Notify the remote management master process, we can
        start sending keystrokes/commands
Else
        The peer denied the request, so notify the remote
        management master process of failure.

Remote Management Receive Data Action is when we (the slave) get data from the remote management master πŸ“₯. We pass that data along to the remote management slave process. This is usually keystroke data coming from the remote user interface ⌨️.

Remote Management Transmit Data Action is when we (the master) get data from the remote management slave πŸ“Ί. We pass it to the remote management master process, and this is usually screen updates heading for the user interface ✨.

Remote Management Transmit Data Response Action is when we (the slave) get an ack for data we sent to the master 🫢. We tell the remote management slave process about it so it can queue up more transmissions πŸš€.

Remote management (Master) start Action builds a REMOTE_MGMT_REQ start message and sends it to the far end πŸ’«. We also send a proceeding message to the RM master process πŸŽ€.

Remote management (Slave) data Action builds a REMOTE_MGMT_TX_REQ message with the data passed from the remote management slave process, and sends it to the far end πŸ“¦.

Remote management (Master) data Action builds a REMOTE_MGMT_RX_REQ message with the data passed from the remote management master process, and sends it to the far end πŸ¦‹.

Remote management data acknowledgement Action builds a REMOTE_MGMT_TX_RSP message and sends it so the slave can send the next block πŸ’œ. There's no data attached to this one 🌈.

Remote management (Master) stop Action builds a REMOTE_MGMT_REQ stop message and sends it to the far end πŸ›‘.


3.5.3. MP+STATE_INITIAL state machine ✨

All sessions start from this state, sub-state A. We don't leave this state until version exchange succeeds πŸ¦‹.

The sub-states are:

  • A Initial state
  • B Sent version request, waiting for version response.
  • C Waiting for version request.

Here's the table, exactly as it is in the spec πŸ“‹:

Event                                   Sub-state
______________________________________________________________________
                           A                    B               C
======================================================================
MP+START_SESSION           1,+                  **              **
______________________________________________________________________
MP+SESSION_DOWN            **              2,Initial:A    2,Initial:A
______________________________________________________________________
MP+SESSION_TERM            **              3,Initial:A    3,Initial:A
______________________________________________________________________
MP+TIMER_EXPIRED           **              4,Initial:A    7,Initial:B
______________________________________________________________________
MP+RX_VERSION_REQ          **              8,Initial:A         5,+
______________________________________________________________________
MP+RX_VERSION_RSP          **                  6,+             **
______________________________________________________________________
MP+START_RM               9,*                  9,*             9,*
______________________________________________________________________
All other events           **                  **              **
______________________________________________________________________

                    Table 2:  Initial State Machine

Table 2: Initial State Machine 🌸

3.5.3. MP+STATE_INITIAL state machine (wrapping up the Actions) πŸŽ€

Actions:

  1. Okay, first things first: start the timer! ⏰ It's 60 seconds if you're the originator and 30 seconds if you're the answerer. Then:
    • Start MP+
    • If originator
      • Build and send version exchange request
      • Go to INITIAL, sub-state B.
    • Go to INITIAL, sub-state C.
  2. Do Error Close Action, then go to INITIAL, sub-state A. 😬
  3. Do Term Action, then go to INITIAL, sub-state A. 🌸
  4. Do Error Close Action, then go to INITIAL, sub-state A. πŸ’€
  5. Stop the idle timer. βœ‹ Then compare protocol versions. If they don't match, do Error Close Action and go to INITIAL, sub-state A. If they do match:
    • Store off the info received from the remote end πŸ—‚οΈ
    • Build a version exchange response and send it to the remote end
    • Do Enter Idle Action, which causes a state change ✨
  6. Stop the retry timer. Compare protocol versions. If they don't match, do Error Close Action and go to INITIAL, sub-state A. If they do match:
    • Store off the info received from the remote end
    • Check the base channel count in the caller's profile πŸ‘€
    • If it's greater than 1:
      • Set the requested bandwidth to the base channel count
      • Do Enter Add Caller action, which causes a state change
    • Do Enter Idle Action, which causes a state change πŸ¦‹
  7. Okay, this one's a plot twist. πŸŒ€ Both sides think they're the answerer. This is possible if both dial each other at the same time and the first channel that finished PPP negotiation happened to be the channel tied to the incoming call on both units. We fix it by trying to become the originator. If both sides try to become the originator, the one with the largest endpoint discriminator falls back to being the answerer. So:
    • Restart the Idle timer at 60 seconds
    • Build and send a Version Exchange Request message
    • Go to Initial:B
  8. Both sides think they're the originator. This can happen if both dial each other at the same time and the first channel that finished PPP negotiation happened to be the channel tied to the originating call on both units. MP+ figures out who's the caller and who's the answerer by comparing the endpoint discriminator in the version exchange request with the local endpoint discriminator. The unit with the smaller endpoint is arbitrarily called the originator. Here's the drama:
    • Compare the local endpoint discriminator with the endpoint discriminator in the message.
    • If the local endpoint discriminator is less than the remote value, we are the caller, so ignore the incoming message. πŸ™ˆ
    • Otherwise, if the local endpoint discriminator is greater than the remote value, we are the answerer:
      • Compare protocol versions. If they do not match, do Error Close Action and go to INITIAL, sub-state A.
      • Store off the info received from the remote end.
      • Build a version exchange response and send it to the remote end.
      • Do Enter Idle Action, which causes a state change.
    • If the two values match, there's a problem. Do Error Close Action and go to INITIAL, sub-state A. 🚨
  9. Log an error message. πŸ“ Then notify the user interface of the remote management failure. 😭

3.5.4. MP+STATE_IDLE state machine πŸ’œ

The Idle state is the state of an active session with no call management activity in progress. It's the chill zone. 🧚

There are no sub-states. Simple as that. πŸ’…

   Event                    State
   _____________________________________________
                               A
   =============================================
   MP+SESSION_DOWN         1,Initial:A
   _____________________________________________
   MP+SESSION_TERM         2,Initial:A
   _____________________________________________
   MP+TIMER_EXPIRED        3,*
   _____________________________________________
   MP+UTILIZATION          4,+
   _____________________________________________
   MP+RX_ADD_REQ           5,+
   _____________________________________________
   MP+RX_REMOVE_REQ        6,Remove:B
   _____________________________________________
   MP+RX_RM_REQ            7,+
   _____________________________________________
   MP+RX_RM_RSP            8,+
   _____________________________________________
   MP+RX_RM_RX_REQ         9,+
   _____________________________________________
   MP+RX_RM_TX_REQ         10,+
   _____________________________________________
   MP+RX_RM_TX_RSP         11,+
   _____________________________________________
   MP+RX_CLOSE_REQ         12,+
   _____________________________________________
   MP+START_RM             13,*
   _____________________________________________
   MP+SEND_RMS             14,*
   _____________________________________________
   MP+SEND_RMM             15,*
   _____________________________________________
   MP+RECV_RMM             16,*
   _____________________________________________
   MP+STOP_RM              17,*
   _____________________________________________
   All other events        **
   _____________________________________________

   Table 3:  Idle State Machine

Actions:

  1. Do Error Close Action, then go to INITIAL, sub-state A. 😡
  2. Do Term Action, then go to INITIAL, sub-state A. πŸ‘‹
  3. Do Timer Action. ⏱️
  4. Note that a bandwidth change has been reqested. Then do Enter Idle Action, which may cause a state change. πŸ“ˆ
  5. If we are the caller:
    • Do Enter Add [remote answerer] Action.

Else:

  • Do Enter Add [remote caller] Action.
  1. Do Enter Remove [remote] Action. πŸ—‘οΈ
  2. Do Remote Management Request Action. πŸ“¨
  3. Do Remote Management Response Action. πŸ“¬
  4. Do Remote Management Receive Data Action. πŸ“₯
  5. Do Remote Management Transmit Data Action. πŸ“€
  6. Do Remote Management Transmit Data Response Action. πŸ”
  7. Clear the remove lock. πŸ”“ Then:
    • If the local recommended channels == 0, send a Close Response message with OK To Close set to TRUE.
    • Else, send a Close Response message with OK To Close set to FALSE.
    • Do Enter Idle Action.
  8. Do Remote management (Master) start Action. πŸš€
  9. Do Remote management (Slave) data Action. 🫢
  10. Do Remote management (Master) data Action. πŸ’«
  11. Do Remote management data acknowledgement Action. βœ…
  12. Do Remote management (Master) stop Action. πŸ›‘

3.5.5. MP+STATE_ADD state machine 🌈

The add state is used by both the caller and the answerer when an add transaction is in progress. It's giving teamwork. 🀝

The sub-states are:

  • A: Add request sent to answerer, waiting for add response from the answerer. πŸ“€
  • B: Caller waiting for call complete notification for calls placed. πŸ“ž
  • C: Answerer waiting for add complete message from caller. πŸ“₯
Event                                           Sub-state
______________________________________________________________________
                                A               B               C
======================================================================
MP+SESSION_DOWN         1,Initial:A      7,Closing:A    1,Initial:A
______________________________________________________________________
MP+SESSION_TERM         2,Initial:A      7,Closing:B    2,Initial:A
______________________________________________________________________
MP+TIMER_EXPIRED           3,+              3,+            3,+
______________________________________________________________________
MP+UTILIZATION             4,*              4,*            4,*
______________________________________________________________________
MP+CALL_COMPLETE            **            8,Idle:A         **
______________________________________________________________________
MP+RX_VERSION_REQ          -,*              **             **
______________________________________________________________________
MP+ADD_REQ                5,Add:B           **             **
______________________________________________________________________
MP+ADD_RSP                 6,+              **             **
______________________________________________________________________
MP+ADD_COMP                 **              **           9,Idle:A
______________________________________________________________________
MP+RX_RM_REQ              10,+             10,+           10,+
______________________________________________________________________
MP+RX_RM_RSP              11,+             11,+           11,+
______________________________________________________________________
MP+RX_RM_RX_REQ           12,+             12,+           12,+
______________________________________________________________________
MP+RX_RM_TX_REQ           13,+             13,+           13,+
______________________________________________________________________
MP+RX_RM_TX_RSP           14,+             14,+           14,+
______________________________________________________________________
MP+RX_REMOVE_REQ           -,*              **             **
______________________________________________________________________
MP+START_RM               15,*             15,*           15,*
______________________________________________________________________
MP+SEND_RMS               16,*             16,*           16,*
______________________________________________________________________
MP+SEND_RMM               17,*             17,*           17,*
______________________________________________________________________
MP+RECV_RMM               18,*             18,*           18,*
______________________________________________________________________
MP+STOP_RM                19,*             19,*           19,*
______________________________________________________________________
All other events            **              **             **
______________________________________________________________________

Table 4:  Add State Machine

Okay so bestie, the actions for Table 4 are where the add logic really comes together πŸ’…βœ¨

  1. Phone numbers (may) have already been reserved πŸ“ž, and they must be released before normal error processing happens πŸ™…β€β™€οΈ
    • Release all reserved phone numbers
    • Do Error Close Action.
  2. Phone numbers (may) have already been reserved πŸ“ž, and they must be released before normal close processing happens 🫢
    • Release all reserved phone numbers
    • Do Term Action.
  3. Do Timer Action ⏰
  4. A bandwidth change has been requested πŸ“. It gets processed the next time the IDLE state is entered.
  5. Okay, this one is a whole drama 😭 An add collision happened. Since the answerer sent phone numbers, we try to use what they sent, but only within the limits of the local system.
    • Compare local channels to add with current channels to add.
    • If the local channels to add is less than the remote channels to add:
      • If the remote number of channels requested would put us over the maximum number of channels allowed for the session, reduce the channel count and set an add lock.
      • Re-reserve the channels. If the number reserved is less than the number of phone numbers provided by the far end, set an add lock and reduce the number of channels to add to what we could reserve.
    • Now treat the remote add request as if it were an add response, and process it by:
      • Integrating the phone number returned from the answerer with the original phone number dialed.
      • Requesting that a session be extended by dialing the integrated phone number. A callback is passed with the request, so call success or failure can be reported back to MP+.
    • Go to ADD:B. Note: this change must actually happen before requesting the first outgoing call. If not, the callback could be called (and ignored) because the session isn't in the correct state πŸ™ˆ
  6. If the answerer provided fewer phone numbers than requested, set an add lock.
    • If the number of channels is zero, send an add complete message (there's nothing to do) and go to the IDLE state.
    • For each phone number returned:
      • Integrate the phone number returned from the answerer with the original phone number dialed.
      • Request that a session be extended by dialing the integrated phone number. A callback is passed with the request, so call success or failure can be reported back to MP+.
    • Go to ADD:B. Note: this change must actually happen before requesting the first outgoing call. If not, the callback could be called (and ignored) because the session isn't in the correct state.
  7. Restart the idle timer for abort ⏳
  8. Increment the count of calls completed.
    • If the call succeeded, increment the count of calls that succeeded.
    • If the count of calls completed equals the number of calls placed:
      • If the number of calls completed is not the same as the number that succeeded, set an add lock.
      • Build an add complete message and send it to the far end.
      • If at least one channel was added, clear any remove lock.
      • Go to the IDLE state.
  9. If the number of channels requested is not equal to the number connected, set an add lock.
    • If at least one channel was added, clear any remove lock.
    • Go to the IDLE state.
  10. Do Remote Management Request Action πŸ›°οΈ
  11. Do Remote Management Response Action
  12. Do Remote Management Receive Data Action
  13. Do Remote Management Transmit Data Action
  14. Do Remote Management Transmit Data Response Action
  15. Do Remote management (Master) start Action
  16. Do Remote management (Slave) data Action
  17. Do Remote management (Master) data Action
  18. Do Remote management data acknowledgement Action
  19. Do Remote management (Master) stop Action 🌸

3.5.6. MP+STATE_REMOVE state machine ✨

This is the state of a session while it's processing a remove transaction πŸ—‘οΈπŸ’– It has two sub-states:

  • A: Remove request sent, waiting for remove response
  • B: Remove response sent, waiting for remove complete
Event                                   Sub-state
_________________________________________________________
                                A               B
=========================================================
MP+SESSION_DOWN             1,Initial:A    1,Initial:A
_________________________________________________________
MP+SESSION_TERM             2,Initial:A    2,Initial:A
_________________________________________________________
MP+TIMER_EXPIRED               3,+            3,+
_________________________________________________________
MP+UTILIZATION                 4,*            4,*
_________________________________________________________
MP+RX_ADD_REQ                  5,+             **
_________________________________________________________
MP+RX_REMOVE_REQ               6,+             **
_________________________________________________________
MP+RX_REMOVE_RSP            7,Idle:A           **
_________________________________________________________
MP+RX_REMOVE_COMP              **           8,Idle:A
_________________________________________________________
MP+RX_CLOSE_REQ               -,*              **
_________________________________________________________
MP+RX_RM_REQ                  9,*             9,*
_________________________________________________________
MP+RX_RM_RSP                 10,*            10,*
_________________________________________________________
MP+RX_RM_RX_REQ              11,*            11,*
_________________________________________________________
MP+RX_RM_TX_REQ              12,*            12,*
_________________________________________________________
MP+RX_RM_TX_RSP              13,*            13,*
_________________________________________________________
MP+START_RM                  14,*            14,*
_________________________________________________________
MP+SEND_RMS                  15,*            15,*
_________________________________________________________
MP+SEND_RMM                  16,*            16,*
_________________________________________________________
MP+RECV_RMM                  17,*            17,*
_________________________________________________________
MP+STOP_RM                   18,*            18,*
_________________________________________________________
All other events              **               **
_________________________________________________________

Table 5: Remove State Machine

Actions:

  1. Do Error Close Action
  2. Do Term Action
  3. Do Timer Action ⏰
  4. A bandwidth change has been requested πŸ“. It gets processed the next time the IDLE state is entered.
  5. Our remove conflicted with the remote end's Add, and the add takes preference πŸ‘‘
    • Set a remove lock.
    • If we are the caller, Do Enter Add [remote answerer] Action.
    • Otherwise, Do Enter Add [remote caller] Action.
  6. Two remove requests collided. We give preference to the caller (an arbitrary decision, but we're committed πŸ’…)
    • If caller, ignore the message.
    • Else:
      • Check the maximum number of channels needed by the local end.
      • Reduce the requested remove count, and set a remove lock if necessary.
      • Build and send a remove response to the remote.
      • Go to Remove:B.
  7. Compare the number of channels requested with the number allowed in the response. If fewer are allowed, set a remove lock.
    • Look at the current bandwidth. If the number to remove would bring the current bandwidth below requirements, reduce the number of channels to remove.
    • If there are still channels to remove:
      • Remove the channels.
      • Clear any add lock.
    • Send a remove complete indicating the number of channels removed.
  8. If at least one channel was removed, clear any add lock.
  9. Do Remote Management Request Action
  10. Do Remote Management Response Action
  11. Do Remote Management Receive Data Action
  12. Do Remote Management Transmit Data Action
  13. Do Remote Management Transmit Data Response Action
  14. Do Remote management (Master) start Action
  15. Do Remote management (Slave) data Action
  16. Do Remote management (Master) data Action
  17. Do Remote management data acknowledgement Action
  18. Do Remote management (Master) stop Action

3.5.7. MP+STATE_CLOSE state machine ✨

The close state is used when we're gracefully closing a session, or when we were told that a session terminated mid-transaction πŸšͺπŸ’œ It has three sub-states:

  • A: Waiting for call complete after session down notification
  • B: Waiting for call complete after session terminate notification.
  • C: Waiting for close response after session close request sent.
Event                                     Sub-state
______________________________________________________________________
                                A               B               C
======================================================================
MP+SESSION_DOWN                **            -,*        7,Initial:A
______________________________________________________________________
MP+SESSION_TERM           1,Close:B           **        8,Initial:A
______________________________________________________________________
MP+TIMER_EXPIRED          2,Initial:A     5,Initial:A       6,*
______________________________________________________________________
MP+UTILIZATION                -,*            -,*            9,*
______________________________________________________________________
MP+CALL_COMPLETE              3,+         6,Initial:A        **
______________________________________________________________________
MP+ADD_REQ                    **             -,*           10,+
______________________________________________________________________
MP+REMOVE_REQ                 **              **        11,Remove:B
______________________________________________________________________
MP+CLOSE_REQ                  -,*            -,*           12,*
______________________________________________________________________
MP+CLOSE_RSP                  -,*            -,*           13,+
______________________________________________________________________
MP+START_RM                   4,*            4,*           4,*
______________________________________________________________________
All other events              **              **            **
______________________________________________________________________

Table 6: Close State Machine

Okay so the Close state machine has a whole list of actions, and bestie, they're the plot πŸ’…

Actions:

1       The session was closed while waiting for call completes.
        Just go to Close:B.

2       We timed out waiting for completes.  Just process the link down,
        now.
        Do Error Close Action.

3       Increment the number of calls complete.

        If equal to the number of calls placed then:
                Do Error Close Action, go to Initial:A.
        Else
                No state change.

4       Log an error message.
        Notify the user interface of remote management failure.

5       We didn't get all the notifications that we expect.  Give up and
        close the session anyway.  Do Term Action .

6       Increment the number of calls complete.

        If equal to the number of calls placed then:
                Do  Term Action, go to Initial:A.
        Else
                No state change

7       Do Error Close Action

8       Do Term Action

9       Note that a bandwidth change has been reqested. This will be

        processed the next time IDLE state is entered.

10      This is an Add & Close collision. Add wins. Perform current
        remote add action.
        If we are originator
                Do Add [Remote Answerer] Action
        else
                Do Add [Remote Caller] Action

11      This is a Remove & Close collision, the Remove will win:
                Set remove lock to FALSE
                Do Remove [Remote] Action.

12      This is a Close collision. But since we both agree:
        If we are originator
                Send a Close Response with okToClose set to TRUE.
        Else
                Send a Close Response with okToClose set to FALSE.

13      If Close Response is received with okToClear is TRUE then:
                Do Term Action
        Else
                set remove lock to TRUE and do Enter Idle Action.

4. PPP LCP Extensions ✨

MP+ Configuration Option

Okay, so the Multilink Protocol Plus adds one extra LCP Configuration Option, and it's giving very neat little packet πŸŽ€

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  type = 22    |  length = 4   |    Currently unused           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   Figure 21: MP+ Option

The type is 22 πŸ¦‹

NOTE: The current implementation uses option 0. This is not an assigned number, so an IANA assigned official identifier has been obtained (22). 🧚

When the option is sent to a peer, it tells the peer that:

  • the unit is capable of running the MP+ protocol;

The peer can accept or reject the option. Its call, bestie πŸ’–

NOTE: The MP+ option MUST NOT be included unless MP is also negotiated. πŸ™ˆ


5. Security Considerations πŸ”’

Security issues are not discussed in this memo. Not gonna lie, this is the one section where we're just leaving it there, so please don't go looking for a security story in here πŸ’€

6. References πŸ“š

[1] K. Sklower, B. Lloyd, G. McGregor, D. Carr, "The PPP Multilink Protocol (MP)".

[2] Simpson, W., Editor, "The Point-to-Point Protocol (PPP)", STD 51, RFC 1661, Daydreamer, July 1994.

7. Author's Address πŸŽ€

Kevin Smith is the author, and here's how to reach him, iykyk 🫢

   Kevin Smith
   Ascend Communications
   1275 Harbor Bay Parkway
   Alameda, CA 94502

   Phone:  (510) 769-6001
   FAX:    (510) 814-2300
   EMail:  ksmith@ascend.com
πŸ“¦ where this page comes from