1. 程式人生 > >linux網路協議棧分析筆記14-路由4-FIB3

linux網路協議棧分析筆記14-路由4-FIB3

看完fib的查詢,弄清了一些資料結構的組織,我們再來看看路由表是如何建立的 從ip_fib_init註冊的兩個通知鏈來看,在IP地址傳送變動時會觸發通知鏈的處理函式,都會呼叫fib_add_ifaddr()來新增地址到路由中 這個裡面由呼叫了fib_magic來進行路由地址的操作。 static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
{
     struct net *net = dev_net(ifa->ifa_dev->dev);
     struct fib_table *tb;
    struct fib_config cfg
= {                                  路由配置結構
          .fc_protocol = RTPROT_KERNEL,
          .fc_type = type,
          .fc_dst = dst,
          .fc_dst_len = dst_len,
          .fc_prefsrc = ifa->ifa_local,
          .fc_oif = ifa->ifa_dev->dev->ifindex,
          .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
          .fc_nlinfo = {
               .nl_net = net,
          },
     };

     if (type == RTN_UNICAST)
         tb = fib_new_table(net, RT_TABLE_MAIN);

     else
          tb = fib_new_table(net, RT_TABLE_LOCAL);

     if (tb == NULL)
          return;

     cfg.fc_table = tb->tb_id;

     if (type != RTN_LOCAL)
          cfg.fc_scope = RT_SCOPE_LINK;
     else
          cfg.fc_scope = RT_SCOPE_HOST;

     if (cmd == RTM_NEWROUTE)        如果是新增命令 則插入

          tb->tb_insert(tb, &cfg);                        fn_hash_insert;
     else
          tb->tb_delete(tb, &cfg);          否則,進行刪除
} fib_new_table() 先看CONFIG_IP_MULTIPLE_TABLES開啟的時候 struct fib_table *fib_new_table(struct net *net, u32 id)
{
     struct fib_table *tb;
     unsigned int h;

     if (id == 0)
          id = RT_TABLE_MAIN;
     tb =fib_get_table(net, id);            通過id查詢路由表函式
     if (tb)
          return tb;

     tb = fib_hash_table(id);      申請建立路由表
     if (!tb)
          return NULL;
     h = id & (FIB_TABLE_HASHSZ - 1);
     hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]);
     return tb;
} struct fib_table *fib_get_table(struct net *net, u32 id)
{
     struct fib_table *tb;
     struct hlist_node *node;
     struct hlist_head *head;
     unsigned int h;

     if (id == 0)
          id = RT_TABLE_MAIN;
     h = id & (FIB_TABLE_HASHSZ - 1);

     rcu_read_lock();
head = &net->ipv4.fib_table_hash[h];                    得到衝突鏈頭
     hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {             匹配
          if (tb->tb_id == id) {
               rcu_read_unlock();
               return tb;
          }
     }
     rcu_read_unlock();
     return NULL;
} 當然FIB的東西還有很多很多,資料結構關係錯綜複雜,鑑於時間和精力,無法再深入分析,這裡也只是弄清大概流程,拉通整個協議棧,等到有了系統的、全流程的觀念後,我們再來仔細深入分析具體的模組。 這裡有篇文章很好的闡述了linux kernel路由機制http://blog.csdn.net/bin323/article/details/642192  算是對上述的流程分析一個總結