1. 接收
a. 初始化
1). 创建SOCK_DGRAM socket
2). bind multicast addr
int inet_bind()
{
/*设置inet_rcv_saddr为multicast address, inet_saddr为0*/
inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->inet_saddr = 0; /* Use device */
}
3) IP_ADD_MEMBERSHIP
/*将multicast address以及所绑定的dev(传递本地ip地址表示绑定该ip地址的dev)告诉给内核*/
struct ip_mc_socklist {
struct ip_mc_socklist __rcu *next_rcu;
struct ip_mreqn multi;
.....
};
struct ip_mc_list {
struct in_device *interface;
__be32 multiaddr
};
int ip_mc_join_group()
{
/*imr_ifindex或者imr_address找dev*/
in_dev = ip_mc_find_dev(net, imr);
/*检查是否已经有相同的绑定到这个socket上, 一个socket可以加多个multicast组*/
err = -EADDRINUSE;
ifindex = imr->imr_ifindex;
for_each_pmc_rtnl(inet, i) {
if (i->multi.imr_multiaddr.s_addr == addr &&
i->multi.imr_ifindex == ifindex)
goto done;
count++;
}
/*创建一个新的*/
iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
/*放到inet->mc_list上*/
memcpy(&iml->multi, imr, sizeof(*imr));
iml->next_rcu = inet->mc_list;
rcu_assign_pointer(inet->mc_list, iml);
/*multicast加入到in_dev->mc_list, 设备上的全局multicast list*/
/*创建ip_mc_list加入到in_dev->mac_list*/
ip_mc_inc_group(in_dev, addr);
}
b. 收报文
1) route
int ip_route_input_noref()
{
if (ipv4_is_multicast(daddr)) {
struct in_device *in_dev = __in_dev_get_rcu(dev);
if (in_dev) {
/*查看in_dev->mc_list上是否有地址位daddr的multicast address*/
int our = ip_check_mc_rcu(in_dev, daddr, saddr,
ip_hdr(skb)->protocol);
if (our) {
/*设置rth->dst.input = ip_local_deliver;*/
/*rt->rt_flags = RTCF_MULTICAST*/
int res = ip_route_input_mc(skb, daddr, saddr,
tos, dev, our);
}
}
}
}