IPv6 Multicast Routing API Part 2

add_m6if() Function

The add_m6if() function adds a multicast interface into the kernel via the MRT6_ADD_MIF socket option. The option argument is a pointer to the mif6ctl{} structure, which is defined in Listing 2-22.

Listing 2-22

Listing 2-22

mif6c_mifi specifies the index of the multicast interface to be created. The mif6c_flags member specifies attributes of the interface. The only available flag in this implementation is MIFF_REGISTER, which means the specified interface should be the Register interface. mif6c_pifi specifies the interface index of the corresponding physical interface.

Through the following listings, we will see the details of the add_m6if() function.

Listing 2-23

Listing 2-23


717—718 If the given interface index is out of range, an error of EINVAL will be returned.

719—721 If the interface corresponding to the given index is in use in the interface table, mif6table, an error of EADDRINUSE will be returned. The error code was derived from the IPv4 multicast routing implementation, but may not be appropriate for IPv6 as indicated by the comment at line 721. The error code was reasonable for IPv4 multicast routing, since the interface was specified by an address. In this code for IPv6, however, the interface is specified by an integer index, for which the error may not really make sense.

719—734 If the index of the physical interface specified by mif6c_pifi is out of range, an error of ENXIO will be returned. Even if the index is in the valid range, the corresponding interface may not exist when the system allows dynamic addition or deletion of interfaces. An error of ENXIO will be returned in such cases.

Listing 2-24

Listing 2-24

 

 

 

 

Listing 2-24

736—754 The ifnet{} data structure represented by multicast_register_if is initialized if the new multicast interface is designated as the Register interface. Some of the structure members are initialized here if the Register interface is seen for the first time. The if_index member is set to the multicast interface index, although this may not be really appropriate because this index value may conflict with that of a "real" interface. The interface attachment function for the AF_INET6 domain, in6_domifattach(), performs IPv6 specific initialization for this new interface. The global variable reg_mif_num is set for tracking the Register interface.

Listing 2-25

Listing 2-25

755—758 The physical interface must have link-level multicast capability in order for a multicast interface to operate over it. Otherwise, an error of EOPNOTSUPP is returned.

763—778 Function if_allmulti() puts the interface into the multicast promiscuous mode so that the router can receive and forward multicast packets not directly destined for it.

Listing 2-26

Listing 2-26

 

 

 

Listing 2-26

784—812 The multicast interface flags, the pointer to the physical interface, and the packet counters are initialized. The global variable nummifs is adjusted if necessary to contain the highest index value among the existing multicast interfaces.

del_m6if() Function

The del_m6if() function deletes a multicast interface from the kernel via the MRT6_DEL_MIF socket option. It takes the multicast interface index as the key for the entry to be deleted.

Listing 2-27

Listing 2-27

817—832 An error of EINVAL is returned if either the given multicast interface index is out of the range or the multicast interface has not been initialized.

837—847 If the Register interface is being deleted, global variable reg_mif_num is reset to indicate the system does not have the Register interface installed. In addition, the inet6domain.dom_ifdetach function is called to clean up the IPv6 specific parameters stored in the ifnet{} structure associated with the interface.

Listing 2-28

Listing 2-28

848—862 For a physical interface, the function if_allmulti() is called with the second argument being 0 to disable the multicast promiscuous mode on the interface. This operation is erroneous in a dual stack environment where IPv4 multicast routing is running in parallel with IPv6 multicast routing: the disabling operation takes place regardless of whether there is another application that requires the promiscuous mode (the IPv4 multicast routing daemon in this case), thereby interfering with the other application.

864—884 The memory occupied by the deleted multicast interface is zero-cleared. The global variable nummifs is adjusted to the next highest index value found in the multicast interface table.

ip6_mrouter_done() Function

The multicast routing daemon calls ip6_mrouter_done() to disable kernel multicast routing and perform necessary cleanups. This function is also called when the corresponding socket is closed, either explicitly or implicitly as a result of process termination, so that the things will be cleaned up even if the multicast routing daemon terminates without performing the cleanup procedure.

Listing 2-29

Listing 2-29

 

 

 

Listing 2-29

604 Network level interrupts must be disabled by splnet() to prevent multicast forwarding during the cleanup procedure.

607—633 This part of the code tries to disable the multicast promiscuous mode for each physical interface used for IPv6 multicast routing. It does not actually work as intended, however, since on FreeBSD it is not possible to disable the promiscuous mode by directly issuing the SIOCDELMULTI command. The if_allmulti() function must be used as we saw in Listing 2-28.

It also tries to address the issue for a dual-stack multicast router described in Listing 2-28 by issuing the ioctl command only when it is not acting as an IPv4 multicast router. As commented, however, this should actually be done in a more fine-grained manner. Ideally, the code should check to see whether each particular interface is used in IPv4 multicast routing so that the promiscuous mode is disabled only if it is not.

Listing 2-30

Listing 2-30

 

 

 

Listing 2-30

634—641 The multicast routing interface table is cleared and the PIM routing is disabled.

644 The function callout_stop() cancels the timer identified by variable expire_upcalls_ch.

654—672 The for loop goes through the entire hash buckets of the multicast forwarding cache entries (see Section 2.9). The inner while loop examines each hash entry in a single bucket, discards all pending packets at the entry and releases the entry itself. Finally, the forwarding cache table is zero-cleared.

Listing 2-31

Listing 2-31

674-683 The dom_ifdetach member of the inet6domain{} structure points to the in6_domifdetach() function, which handles IPv6 specific interface cleanups. Then the global variable reg_mif_num is reset to indicate there is no virtual Register interface in the system.

685 ip6_mrouter is reset to NULL to indicate there is no active IPv6 multicast routing daemon attached in the system that performs multicast routing functions.

mrt6_ioctl() Function

The mrt6_ioctl() function, shown below, is called from in6_control() to provide IPv6 multicast routing-related statistics to interested applications. The get_mif6_cnt() function will be described in the next subsection, while the description of get_sg_cnt() will be deferred until Section 2.9.4.

Listing 2-32

Listing 2-32

get_mif6_cnt() Function

The get_mif6_cnt() function returns statistics for the given multicast interface.

Listing 2-33

Listing 2-33

487-497 The multicast interface index specified by the application is validated. An error of EINVAL is returned if the index is out of range. The index refers to an entry in the multicast interface table, and the statistics from this entry are copied into the storage provided by the application.

Next post:

Previous post: