MLD Implementation (IPv6 Multicasting) Part 1

Figure 2-18 depicts relationships among various MLD functions. These functions generally work on in6_multi{} structures, each of which maintains kernel internal parameters of a multicast group address that the node joins.

There are three major paths in MLD protocol processing. One is handling inbound MLD messages by the mld6_input() function.These operations are performed by the mld6_start_listening() and mld6_stop_listening() functions, respectively. The last one is timer processing for the in6_multi{} structures. A common single timer is used for all the structures, whose expiration handler is the mld6_fasttimeo() function. It is a fast timeout hander and is called every 200ms.

Types and Structures

Table 2-6 shows standard macro names for MLD message types defined in [RFC3542](*).

TABLE 2-6

Name

Type

Description

MLD_LISTENER_QUERY

130

Multicast Listener Query

MLD_LISTENER_REPORT

131

Multicast Listener Report

MLD_LISTENER_DONE

132

Multicast Listener Done

FIGURE 2-18

FIGURE 2-18


The KAME kernel implementation uses the nonstandard, but more intuitive macro name.

[RFC3542] also defines a template structure of MLD messages, the mld_hdr{} structure as shown in Listing 2-1. This is a straightforward implementation of the header format defined in Figure 2-2, but it begins with an instance of the icmp6_hdr{} structure, since MLD messages are defined as ICMPv6 messages. Shortcut macros are defined to get access to MLD-specific message fields.

Listing 2-1

Listing 2-1

FIGURE 2-19

FIGURE 2-19

MLD Listener State Transition

[RFC2710] defines three states for a "listener" (host) of a particular multicast group address with the MLD protocol operations: Non-Listener, Delaying Listener, and Idle Listener. A listener also has a flag indicating whether it is the member who sent the last Report message for the group on the link, and a timer delaying a Report message for the group.

Figure 2-19 is a state transition diagram between these states. Each arrow indicates the state transition associated with a label representing the event that causes the transition and the actions that take place for the transition. For example, the arrow from the Non-Listener state to the Delaying Listener state means when a listener starts listening to a multicast group, it sends a Report message, sets the flag, and starts the timer.

For brevity, we do not provide a comprehensive description of the states and the transition events, but these should be pretty trivial. The precise definitions can be found in [RFC2710].

In the KAME implementation, the information of a listener is represented in the in6_multi{} structure (Listing 2-2). The two structure members are relevant here: in6m_state and in6m_timer in6m_state can be either MLD_OTHERLISTENER or MLD_lREPORTEDLAST, which means a different listener or this listener sent the latest Report, respectively. in6m_timer is a counter of listener’s timer with the granularity of 200ms(*). If the value of this member is 0, it means the timer is disabled.

Listing 2-2

Listing 2-2

 

 

 

Listing 2-2

(*) The timer granularity is coarse compared to the protocol specification, which suggests using the system’s highest clock granularity. However, this implementation uses the coarse timer because when this code was first written the target version of BSD did not support fine-grained and scalable kernel timers; the "fast timeout" timers called every 200ms were the only reasonable choice when there might be a large number of timers. Later versions of the MLD implementation use more fine-grained timers for each entry.

In this implementation, the Non-Listener state is represented as the nonexistence of the in6_multi{} structure. Otherwise, if the timer is running, i.e., in6m_timer has a non-zero value, the listener is in the Delaying state; otherwise, it is in the Idle state.

mld6_init() Function

The mld6_init() function is called from the icmp6_init() function via the protocol initialization switch table stored in the inet6sw array. The mld6_init() function initializes many common variables used by other MLD routines.

Listing 2-3

Listing 2-3

 

 

 

Listing 2-3

262—263 These variables are templates of commonly used link-local addresses (see lines 282-292 below).

268—270 Some timer-related variables are initialized. The last two variables are used for MLDv2.

272—280 MLD packets must have a Hop-by-Hop Options header containing a Router Alert option. Variable hbh is initialized as the common template of this extension header. A 2-byte padding before the actual option is necessary in meeting the alignment requirement of the Router Alert option.The first 2 bytes of the option specify the option type and its length, followed by the option value specifying MLD Router Alert in the network byte order.

282—292 The link-local address structure templates are filled in and are pointed by file scope pointer variables all_nodes_linklocal and all_routers_linklocal for later use (see Section 2.6.3 for example usage).

302—303 ip6_opts is a file scope variable for storing the Hop-by-Hop Options header initialized above, and will be attached to MLD packets to be sent. The function init_ip6pktopts() initializes the structure and sets the corresponding member to point to hbh.

Joining a Group: mld6_start_listening() Function

The mld6_start_listening() function is called when the local node joins a multicast group specified by function parameter in6m. This function performs the state transition from

Non-Listener to Delaying Listener in Figure 2-19.

Listing 2-4

Listing 2-4

 

 

 

 

Listing 2-4

367—371 Network level interrupts must be disabled by splnet() because the mld6_start_listening() function is usually invoked by a user process, and the function modifies in6m, which can also be referred to in the input path.

375—380 The entire code in this file assumes mld6_init() must be called first, where all_nodes_linklocal is initialized. An unexpected state may cause a severe bad effect if this is not the case. Calling panic here would prevent the situation.

389—396 A local variable all_sa is initialized so that it specifies the All-Nodes link-local multicast address with the proper scope zone ID set for the joining interface. Note that link-local addresses are generally ambiguous within a node and must always be associated with its zone ID for proper operation. The KAME kernel ensures this by maintaining an IPv6 address in the form of the sockaddr_in6{} structure with the appropriate zone ID via the initialization by the in6_addr2zoneid() and in6_embedscope() functions. It should be noted that the sockaddr_in6{} structure may have different contents depending on the interface even if its address part is a constant. This is the reason a local variable must be used here rather than a constant structure. The initialization should always succeed as long as the given interface is valid, but if it happens to fail, the in6m entry transits to the Idle state.

397-406 [RFC2710] states that an MLD message must not be sent for the link-scope All-Nodes multicast address or for multicast addresses that have either 0 (reserved) or 1 (interface-local) scope. In either case, the in6m entry transits to the Idle state.

422 The in6m entry is passed to the mld6_sendpkt() function (Section 2.6.7) where a Report message is sent on the corresponding interface.

423-427 [RFC2710] requires the initial Report message to be repeated with a random delay up to MLD_UNS0LICITED_REP0RT_INTERVAL (10) seconds. The random delay is calculated as follows: PR_FASTHZ is 5, which corresponds to the system’s "fast timeouts" called every 200ms. The MLD_RAND0M_DELAY macro returns a random integer value between 1 and 50 (inclusive), and the in6m_timer member is set to this value. The mld6_fasttimeo() function will decrement this value by 1 every time it is called. When in6m_timer is decremented to 0, the timer expires. Since this node has just sent a Report message, the state of this entry is reset to MLD_IREPORTEDLAST. Finally, the global variable mld_group_timers_are_running is set to 1 to indicate the system needs to maintain MLD timers.

Next post:

Previous post: