Introduction ------------ RMCast is a reliable source-ordered multicast protocol implementation for message-oriented multi-sender group communication built on top of IPv4 multicast. It uses sequence numbers for re-ordering, duplicate suppression and loss detection. Negative acknowledgments (NAK) with retransmissions are used to recover from losses. One new and interesting idea implemented in this protocol is history transmission (dubbed negative retransmission). In a nutshell, each sender, along with normal payload, transmits a list of other sender's IDs along with sequence numbers of last messages received from those senders by this member. This, in some sense, builds a pyramid of information: each subsequent message carries some information for a number of previous messages (from other senders). This helps other receivers detect losses. The protocol does not track group membership. Messages are retained for retransmission for a predefined amount of time. The "last message or lost message" dilemma is solved by periodic history transmissions in cases when there is no useful traffic (idle network). Examples -------- There is a simple example available in examples/RMCast/Send_Msg with the corresponding README file. Protocol -------- Over-the-wire representation is little-endian CDR. The protocol is message-based with information encapsulated into one or multiple profiles (Protocol.h): struct Profile { u16 id; // Profile id. u16 size; // Profile size. }; struct Message { u32 size; // Total size of the message. sequence profiles; // Sequence of profiles. } The following profiles are defined (Protocol.h): struct From: Profile { u32 addr; // IPv4 address. u16 port; }; The 'From' profile appears in each message. It is never transmitted over the wire. Instead the 'Link' layer (see below) adds it. struct To: Profile { u32 addr; // IPv4 address. u16 port; }; The 'To' profile also appears in each message. It is also never transmitted over the wire since all communications are done via well-known group address. It is added by the 'Link' layer and is used by a group member to identify messages from itself ('From' == 'To'). struct Data: Profile { sequence data; }; The 'Data' profile is used to transmit user payload. struct SN: Profile { u64 sn; }; The 'SN' profile carries sequence number for 'Data' and 'NoData' profiles. struct NAK: Profile { u32 addr; // IPv4 address. u16 port; sequence sns; }; The 'NAK' profile carries sequence numbers of all the messages originated from the member identified by addr:port that the receiver detected were lost. struct NRTM: Profile { struct Pair { u32 addr; // IPv4 address. u16 port; u64 max_sn; }; sequence nrtm; }; The 'NRTM' profile carries highest sequence numbers known to this member for (some sub-) set of members. It is used by other members to detect loses. This profile is normally combined with 'Data' transmission. struct NoData: Profile { }; The 'NoData' profile is send in reply to 'NAK' when the lost message is no longer available. Below is the list of actions that trigger messages with various profiles: user calls send(): SN Data NRTM detected loss: NAK received NAK: SN or SN Data NoData NRTM NRTM Implementation -------------- This section describes high-level architecture of the implementation. The protocol is implemented as a stack (Stack.h) of the following elements: 'Socket' 'Acknowledge' 'Retransmit' 'Link' The 'Socket' element is the user interface of the member. When a user calls send() 'Socket' creates a new message with 'SN' and 'Data' profiles and forwards it to the 'Acknowledge' element. It also receives (from 'Acknowledge') and queues incoming messages that are delivered to the user when recv() is called. The 'Acknowledge' element is responsible for re-ordering, duplicate suppression, loss detection and negative acknowledgments. It maintains a dynamically changing "window" (which slides toward higher sequence numbers) of received messages. Messages that arrive out of order are held in this window. Presence of a hole in the windows for a long period of time indicates loss and triggers a negative acknowledgment. The 'Retransmit' element is responsible for message retention, aging and retransmission in response to NAKs. Each message received from the 'Socket' element is held for predetermined amount of time in case retransmission is required. Upon reception of a NAK duplicate is send if the requested message is still available. Otherwise 'NoData' profile is sent. The 'Link' element is responsible for interfacing with the IPv4 multicast socket. It also parses over-the-wire representation into in-memory messages with individually-accessible profiles. -- Boris Kolpackov