当通过输出设备向目的地址发送报文时,如果没有源地址,则需要调用inet_select_addr来选择ip地址作为源地址;
1 /* 2 选择ip地址 3 4 通过设备找到ip控制块,从ip控制块中遍历地址列表中的主地址, 5 优先选择满足范围,满足于目的地址网络部分相同的地址, 6 找不到则默认第一个满足范围的地址 7 8 找不到ip控制块,则走no_in_dev流程 9 */ 10 __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) 11 { 12 __be32 addr = 0; 13 struct in_device *in_dev; 14 struct net *net = dev_net(dev); 15 int master_idx; 16 17 rcu_read_lock(); 18 19 /* 获取ip配置块 */ 20 in_dev = __in_dev_get_rcu(dev); 21 if (!in_dev) 22 goto no_in_dev; 23 24 /* 遍历链表中的主地址 */ 25 for_primary_ifa(in_dev) { 26 27 /* 当前地址范围> 传入地址范围 28 则实际地址范围小,不满足要求 29 */ 30 if (ifa->ifa_scope > scope) 31 continue; 32 33 /* 如果未提供目的地址|| 目的地址与当前地址网络部分相同 */ 34 if (!dst || inet_ifa_match(dst, ifa)) { 35 /* 设置当前地址为查找地址 */ 36 addr = ifa->ifa_local; 37 break; 38 } 39 40 /* 如果第一次遍历到这里地址未找到, 41 则先将其默认为第一个满足范围主地址 42 */ 43 if (!addr) 44 addr = ifa->ifa_local; 45 } endfor_ifa(in_dev); 46 47 /* 找到地址 */ 48 if (addr) 49 goto out_unlock; 50 51 /* 没有ip控制块 */ 52 no_in_dev: 53 54 /* TODO l3mdev相关不熟 */ 55 56 /* 获取主设备id */ 57 master_idx = l3mdev_master_ifindex_rcu(dev); 58 59 /* For VRFs, the VRF device takes the place of the loopback device, 60 * with addresses on it being preferred. Note in such cases the 61 * loopback device will be among the devices that fail the master_idx 62 * equality check in the loop below. 63 */ 64 /* 主设备id不为空,通过该设备id能够获取到设备, 65 通过该设备能够获取到地址控制块 66 */ 67 if (master_idx && 68 (dev = dev_get_by_index_rcu(net, master_idx)) && 69 (in_dev = __in_dev_get_rcu(dev))) { 70 /* 选择ip地址 */ 71 addr = in_dev_select_addr(in_dev, scope); 72 if (addr) 73 goto out_unlock; 74 } 75 76 /* Not loopback addresses on loopback should be preferred 77 in this case. It is important that lo is the first interface 78 in dev_base list. 79 */ 80 /* 遍历所有设备 */ 81 for_each_netdev_rcu(net, dev) { 82 83 /* 与主设备不等 */ 84 if (l3mdev_master_ifindex_rcu(dev) != master_idx) 85 continue; 86 87 /* 获取地址配置块 */ 88 in_dev = __in_dev_get_rcu(dev); 89 if (!in_dev) 90 continue; 91 92 /* 获取ip地址 */ 93 addr = in_dev_select_addr(in_dev, scope); 94 if (addr) 95 goto out_unlock; 96 } 97 out_unlock: 98 rcu_read_unlock(); 99 return addr; 100 }
1 /* 通过ip控制块和范围选择合适地址 */ 2 static __be32 in_dev_select_addr(const struct in_device *in_dev, 3 int scope) 4 { 5 /* 遍历该ip控制块中主地址 */ 6 for_primary_ifa(in_dev) { 7 /* 找地址范围不是link && 范围小于输入范围的地址 */ 8 if (ifa->ifa_scope != RT_SCOPE_LINK && 9 ifa->ifa_scope <= scope) 10 return ifa->ifa_local; 11 } endfor_ifa(in_dev); 12 13 return 0; 14 }
时间: 2024-10-20 11:09:37