MLD Implementation (IPv6 Multicasting) Part 3

Process MLD Report

Listing 2-9

Listing 2-9

 

 

 

 

 

 

Listing 2-9

737—748 If a Report message from a different node is received, the receiving node is not responsible for sending Done messages any more. This case is easy for a host, since it does not loop its own Report messages back to itself (see Listing 2-13 following), which means a received Report always comes from a different node. However, a multicast router needs to loop transmitting Report messages to itself so that the multicast routing daemon can notice the local listener, which may confuse the processing. The M_LOOP flag is examined in order to avoid this scenario. As commented, checking the IFF_LOOPBACK flag on the receiving interface does not work, since the packet is looped back via ip6_mloopback() and the receiving interface is set to the physical outgoing interface, which may not have the IFF_LOOPBACK flag.


If the packet is detected as being looped back, it is silently discarded.

750-752 The Multicast Address field of a Report message must carry a multicast address. Otherwise, the packet is invalid and is simply discarded.

757—762 The IN6_LOOKUP_MULTI() macro checks if the local node has joined the reported multicast group. If so, the state for this group is moved to Idle by clearing the entry timer. In addition, now that this node is not the listener who sent the latest Report, the in6m_state member is changed to MLD_OTHERLISTENER.

763—773 The mld6_input() function is only called by function icmp6_input() when the MLD message type is either Multicast Listener Query or Report. As such, the default switch case should not happen.

775 There is no need to keep the packet because the packet is copied in function icmp6_input() to be sent to applications when necessary and can be freed here.

mld6_fasttimeo() Function

The mld6_fasttimeo() function is responsible for processing MLD timers. Unfortunately,this function is unnecessarily complicated by the support for MLDv2. We will only discuss code related to MLDv1 in this section.

Listing 2-10

Listing 2-10

 

799—801 The timer processing completes if the local node is not responsible for reporting any multicast groups the node is joining. Only the mld_group_timers_are_running variable is relevant to MLDv1.

806 Network level interrupts must be disabled by splnet() because the same list can be referred to in the packet input path.

837—935 The code is unnecessarily complicated due to the support for MLDv2, which is omitted in the discussion. The original logic is straightforward: every multicast group entry that enables the timer is examined; the entry timer counter decrements by 1, and, if the timer expires and the local node is responsible for sending the Report, mld6_sendpkt() is called to send the message. Since this node has just sent a Report message, in6m_state is changed to MLD_IREPORTEDLAST. If an entry that has a positive timer value remains in the list, mld6_timers_are_running is set to 1, indicating timer processing needs to be continued.

mld6_sendpkt() Function

The mld6_sendpkt() function is responsible for performing the actual transmission of MLD messages.

Listing 2-11

Listing 2-11

Source Address Selection

996-1005 [RFC3590] specifies that an MLD message must use a link-local address as the source address if the node has a valid link-local address on the outgoing interface (Section 2.3.3). Function in6ifa_ifpforlinklocal() is called to see this condition. The output process fails if there is no valid link-local address found; note that in6ifa_ipfforlinklocal() may return a tentative address.

Listing 2-12

Listing 2-12

Allocate Mbuf

1007—1010 The function mld_allocbuf() creates a chain of two mbufs: one contains the IPv6 header, and the other contains the MLD header.

Set Addresses

1012—1015 A valid nontentative link-local address is chosen for the source address if available; otherwise, the unspecified address is used instead. The destination address is set to the address given by the caller if available; otherwise, the destination address is set to the multicast address for which the MLD message is sent. The former case applies to the Multicast Listener Done messages, which are sent to the All-Routers link-local multicast address regardless of the group address given.

1017—1037 Variables src_sa and dst_sa are sockaddr_in6{} structures that are set to the source and destination addresses of the packet respectively, with each address containing the appropriate scope zone index. The zone indices are determined from the scope of the addresses and the outgoing interface. The function in6_addr2zoneid() embeds the zone index into the addresses. The function ip6_setpktaddrs() attaches the sockaddr_in6{} structures to the mbuf.

Listing 2-13

Listing 2-13

Complete the Packet

1039—1043 The Multicast Address field of the MLD message is filled in with the address of the given multicast group as the function parameter in6m. Since a scope zone index may be embedded in the address, that space in the address must be zero-cleared before the packet is sent on the wire. Finally, in6_cksum() calculates the checksum over the complete MLD header and stores the checksum value into the checksum field.

Construct Multicast Options

1045—1054 Several packet transmission options are set in im6o, an instance of the ip6_moptions{} structure. The im6o_multicast_ifp field contains the outgoing interface, and the im6o_multicast_hlim field contains the packet hop limit, which is 1 as specified in [RFC2710]. im6o_multicast_loop controls the packet loopback behavior. Typically, an MLD message is not looped back to the transmitting node. But if the transmitting node is acting as a multicast router, the message must be looped back to the local node so that the multicast routing daemon can notice the local listener.

Listing 2-14

Listing 2-14

Statistics Update

1057-1069 ICMPv6 and MLD MIB variables are updated. It should be noted that most of them are interface-specific and need the outgoing interface.

Send Packet

1071-1076 The mbuf containing the message is passed to function ip6_output() for transmission. A special flag IPV6_UNSPESRC is set as a function argument if the source address is the unspecified address. This flag prevents ip6_output() from misinterpreting the packet as being invalid.

mld_allocbuf() Function

The mld_allocbuf() function is a subroutine of the mld6_sendpkt() function. It allocates memory for the outgoing MLD message and partially initializes the header.

You may notice that the function naming is inconsistent: only this function has the prefix mld_ while the other MLD-related functions begin with mld6_. This is due to a historical reason: the other functions were first implemented when no standard API was defined. Then the advanced API specification [RFC3542] introduced the convention of the prefix mld_ for MLD-related definitions. The function mld_allocbuf() was implemented after that, following the standard convention. Later versions of KAME snapshot has resolved this inconsistency by changing the prefix to mld_ for all the other functions.

Listing 2-15

Listing 2-15

 

 

 

 

 

 

Listing 2-15

1094-1097 As explained in mld6_sendpkt(), two separate mbufs are allocated for constructing an outgoing MLD message. The M_DONTWAIT flag is set for memory allocation because this routine can be called within an interrupt context.

1108-1114 The two mbufs are linked together if the allocation was successful.

1116-1130 The first mbuf contains the IPv6 header. Only the version field and the next header field in the IPv6 header are initialized here because other fields will be set either in function mld6_sendpkt() or in function ip6_output().

1132-1137 The second mbuf contains the MLD header. Only the MLD message type field is set here.

Next post:

Previous post: