IP结构与操作之inet_select_addr

当通过输出设备向目的地址发送报文时,如果没有源地址,则需要调用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 }

 

posted @ 2017-09-17 20:14  AlexAlex  阅读(1157)  评论(0编辑  收藏  举报