Some protocol layers require the presence of other layers below or above them, e.g. GMS requires that a PING layer be somewhere below it to handle initial membership discovery. Whenever GMS needs to discover the initial membership, it delegates this to the PING layer by passing a FIND_INITIAL_MBRS event down the stack. PING would handle this event and send a FIND_INITIAL_MBRS_OK event back to GMS.
To be more precise: GMS does not actually require the presence of a layer called PING below it, but it requires a layer that catches the FIND_INITIAL_MBRS event and returns the initial membership. So not the type of the layer is important, but which events it catches (provides), and which ones it requires from others. Thus, any layer can provide events ( services) to any other layer.
Class Protocol (and therefore every layer) contains 4 methods that describe which events are required and which events are provided by the layer. Thus, when a protocol stack is assembled, dependency checks ensure that a correct stack is created. Each method returns a list of event types that are required/provided to/by the layers above/below:
The default for all 4 methods is to return null: no services required, no services provided, neither up or down. A protocol implementor may choose to override any method to enforce the presence of an other protocol upon which the current layer's implementation depends, or to specify the services provided by the current protocol.
A dependeny check performed by the Configurator when constructing the protocol stack ensures that all requirements are met. If this is not the case, the construction will fail and the protocol stack will not be created.