Chinaunix首页 | 论坛 | 博客
  • 博客访问: 85721
  • 博文数量: 15
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 210
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-05 15:27
文章分类

全部博文(15)

文章存档

2014年(15)

我的朋友

分类: LINUX

2014-01-08 23:12:28

源设备的选择


源地址的选择

一个网卡可能配有多个ip地址,在发包流程中,如果源地址没有显示指定的话,会通过inet_select_addr选择源地址:
  1. __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
  2. {
  3.     __be32 addr = 0;
  4.     struct in_device *in_dev;
  5.     struct net *net = dev_net(dev);

  6.     rcu_read_lock();
  7.     in_dev = __in_dev_get_rcu(dev);
  8.     if (!in_dev)
  9.         goto no_in_dev;

  10.     for_primary_ifa(in_dev) {
  11.         if (ifa->ifa_scope > scope)
  12.             continue;
  13.         if (!dst || inet_ifa_match(dst, ifa)) {
  14.             addr = ifa->ifa_local;
  15.             break;
  16.         }
  17.         if (!addr)
  18.             addr = ifa->ifa_local;
  19.     } endfor_ifa(in_dev);

  20.     if (addr)
  21.         goto out_unlock;
  22. no_in_dev:

  23.     /* Not loopback addresses on loopback should be preferred
  24.      in this case. It is importnat that lo is the first interface
  25.      in dev_base list.
  26.      */
  27.     for_each_netdev_rcu(net, dev) {
  28.         in_dev = __in_dev_get_rcu(dev);
  29.         if (!in_dev)
  30.             continue;

  31.         for_primary_ifa(in_dev) {
  32.             if (ifa->ifa_scope != RT_SCOPE_LINK &&
  33.              ifa->ifa_scope <= scope) {
  34.                 addr = ifa->ifa_local;
  35.                 goto out_unlock;
  36.             }
  37.         } endfor_ifa(in_dev);
  38.     }
  39. out_unlock:
  40.     rcu_read_unlock();
  41.     return addr;
  42. }
其中scope定义如下 :

  1. enum rt_scope_t {
  2.     RT_SCOPE_UNIVERSE=0,
  3. /* User defined values */
  4.     RT_SCOPE_SITE=200,
  5.     RT_SCOPE_LINK=253,
  6.     RT_SCOPE_HOST=254,
  7.     RT_SCOPE_NOWHERE=255
  8. }
网卡对应的ip信息存在in_device数据结构中:

  1. struct in_device {
  2.     struct net_device    *dev;
  3.     atomic_t        refcnt;
  4.     int            dead;
  5.     struct in_ifaddr    *ifa_list;    /* IP ifaddr chain        */
  6.     struct ip_mc_list __rcu    *mc_list;    /* IP multicast filter chain */
  7.     int            mc_count;    /* Number of installed mcasts    */
  8.     spinlock_t        mc_tomb_lock;
  9.     struct ip_mc_list    *mc_tomb;
  10.     unsigned long        mr_v1_seen;
  11.     unsigned long        mr_v2_seen;
  12.     unsigned long        mr_maxdelay;
  13.     unsigned char        mr_qrv;
  14.     unsigned char        mr_gq_running;
  15.     unsigned char        mr_ifc_count;
  16.     struct timer_list    mr_gq_timer;    /* general query timer */
  17.     struct timer_list    mr_ifc_timer;    /* interface change timer */

  18.     struct neigh_parms    *arp_parms;
  19.     struct ipv4_devconf    cnf;
  20.     struct rcu_head        rcu_head;
  21. }

  1. struct in_ifaddr {
  2.     struct hlist_node    hash;
  3.     struct in_ifaddr    *ifa_next;
  4.     struct in_device    *ifa_dev;
  5.     struct rcu_head        rcu_head;
  6.     __be32            ifa_local;
  7.     __be32            ifa_address;
  8.     __be32            ifa_mask;
  9.     __be32            ifa_broadcast;
  10.     unsigned char        ifa_scope;
  11.     unsigned char        ifa_flags;
  12.     unsigned char        ifa_prefixlen;
  13.     char            ifa_label[IFNAMSIZ];
  14. }
选择源地址主要基于两条:范围要大于传入的参数,即值要小于;属于同一个子网
ip地址存在in_ifaddr 数据结构中,如下:

  1. root@:/opt/module/net/udp# ip addr
  2. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
  3.     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  4.     inet 127.0.0.1/8 scope host lo
  5.     inet6 ::1/128 scope host
  6.        valid_lft forever preferred_lft forever
  7. 2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
  8.     link/ether 60:eb:69:45:29:1b brd ff:ff:ff:ff:ff:ff
  9.     inet 10.1.2.3/24 brd 10.1.2.255 scope global eth0
  10.     inet 11.1.2.3/24 brd 11.1.2.255 scope global eth0:1
  11.     inet 128.1.2.3/16 brd 128.1.255.255 scope global eth0:2
  12.     inet6 fe80::62eb:69ff:fe45:291b/64 scope link
  13.        valid_lft forever preferred_lft forever
  14. 3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
  15.     link/ether 1c:65:9d:2c:fe:f7 brd ff:ff:ff:ff:ff:ff
  16.     inet 192.168.1.109/24 brd 192.168.1.255 scope global wlan0
  17.     inet6 fe80::1e65:9dff:fe2c:fef7/64 scope link
  18.        valid_lft forever preferred_lft forever
  1. for_each_netdev(&init_net, dev_tmp){
  2.         struct in_device *in_dev;
  3.         struct in_ifaddr *ifa;
  4.         in_dev = __in_dev_get_rcu(dev_tmp);
  5.         if (!in_dev)
  6.             return 0;
  7.           for (ifa = (in_dev)->ifa_list; ifa ; ifa = ifa->ifa_next)
  8.               printk("dev=%s,ip=%x,name=%s,scope=%d\n",dev_tmp->name,ifa->ifa_address,ifa->ifa_label,ifa->ifa_scope);


  9. }
输出:

  1. [ 3452.341006] dev=lo,ip=100007f,name=lo,scope=254
  2. [ 3452.341014] dev=eth0,ip=302010a,name=eth0,scope=0
  3. [ 3452.341017] dev=eth0,ip=302010b,name=eth0:1,scope=0
  4. [ 3452.341021] dev=eth0,ip=3020180,name=eth0:2,scope=0
  5. [ 3452.341025] dev=wlan0,ip=6d01a8c0,name=wlan0,scope=0






阅读(1813) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~