kernel中路由表的实现

分类: LINUX

原文地址:TCP/IP学习(41)——Kernel中路由表的实现(4) 作者:GFree_Wind

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
   


在昨天的查找函数中,还有一个函数没有学习,即check_leaf。
  1. /* should be called with rcu_read_lock */
  2. static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
  3.          t_key key, const struct flowi4 *flp,
  4.          struct fib_result *res, int fib_flags)
  5. {
  6.     struct leaf_info *li;
  7.     /* 
  8.     得到叶子节点的hlist_head.
  9.     所谓的hlist_head其实只是list_head的变种,只为了节省一个指针的空间。
  10.     其它的hlist_head的操作也类似于list_head的同等操作。
  11.     */
  12.     struct hlist_head *hhead = &l->list;
  13.     struct hlist_node *node;

     /* 遍历hlist */
  1.     hlist_for_each_entry_rcu(li, node, hhead, hlist) {
 /*struct leaf_info为hlist_node真正的数据 */

          /* 对于同一route,但其它参数不同如TOS等,这时使用fib_alias区分。*/
  1.         struct fib_alias *fa;
  2.         int plen = li->plen;
  3.         __be32 mask = inet_make_mask(plen);
          
          /* 比较目的地址 */
  1.         if (l->key != (key & ntohl(mask)))
  2.             continue;

  3.         list_for_each_entry_rcu(fa, &li->falh, fa_list) {
  4.             /* 获得route的info */
  5.             struct fib_info *fi = fa->fa_info;
  6.             int nhsel, err;
             
             /* 比较route的info,如tos,scope等*/
  1.             if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
  2.                 continue;
  3.             
  4.             if (fa->fa_info->fib_scope < flp->flowi4_scope)
  5.                 continue;
  6.             fib_alias_accessed(fa);
  7.             err = fib_props[fa->fa_type].error;
  8.             if (err) {
  9. #ifdef CONFIG_IP_FIB_TRIE_STATS
  10.                 t->stats.semantic_match_passed++;
  11. #endif
  12.                 return err;
  13.             }
  14.             if (fi->fib_flags & RTNH_F_DEAD)
  15.                 continue;
             /* 
             遍历该route的所有下一跳。
             一般情况下,route只有一个下一跳地址。但是如果enable了multiple path的话,一个route信息就
             可以有多个下一跳地址。
             */
  1.             for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
  2.                 const struct fib_nh *nh = &fi->fib_nh[nhsel];
                 /* 该下一跳不可用 */
  1.                 if (nh->nh_flags & RTNH_F_DEAD)
  2.                     continue;
                 /* 出口dev不匹配 */
  1.                 if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
  2.                     continue;

  3. #ifdef CONFIG_IP_FIB_TRIE_STATS
  4.                 t->stats.semantic_match_passed++;
  5. #endif
                 
                 /* ok。找到了一个合适的路由 */
  1.                 res->prefixlen = plen;
  2.                 res->nh_sel = nhsel;
  3.                 res->type = fa->fa_type;
  4.                 res->scope = fa->fa_info->fib_scope;
  5.                 res->fi = fi;
  6.                 res->table = tb;
  7.                 res->fa_head = &li->falh;
  8.                 if (!(fib_flags & FIB_LOOKUP_NOREF))
  9.                     atomic_inc(&res->fi->fib_clntref);
  10.                 return 0;
  11.             }
  12.         }

  13. #ifdef CONFIG_IP_FIB_TRIE_STATS
  14.         t->stats.semantic_match_miss++;
  15. #endif
  16.     }

  17.     return 1;
  18. }
学习完这个函数,trie方式的路由表查找过程就已结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 Kernel ridge regression 的 C++ 实现示例: ```cpp #include <iostream> #include <vector> #include <cmath> using namespace std; // 高斯核函数 double gaussian_kernel(double x, double y, double sigma) { double diff = x - y; return exp(-diff * diff / (2 * sigma * sigma)); } // 计算带核函数的 Gram 矩阵 vector<vector<double>> compute_gram_matrix(const vector<double>& x, double sigma) { int n = x.size(); vector<vector<double>> gram_matrix(n, vector<double>(n)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { gram_matrix[i][j] = gaussian_kernel(x[i], x[j], sigma); } } return gram_matrix; } // 计算 alpha vector<double> compute_alpha(const vector<vector<double>>& gram_matrix, const vector<double>& y, double alpha) { int n = gram_matrix.size(); vector<vector<double>> I(n, vector<double>(n)); for (int i = 0; i < n; i++) { I[i][i] = 1; } vector<vector<double>> temp(n, vector<double>(n)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { temp[i][j] = gram_matrix[i][j] + alpha * I[i][j]; } } // 求解线性方程组 vector<double> alpha_vec(n); for (int i = 0; i < n; i++) { double sum = 0; for (int j = 0; j < n; j++) { sum += temp[i][j] * y[j]; } alpha_vec[i] = sum; } return alpha_vec; } // 预测 double predict(const vector<vector<double>>& gram_matrix, const vector<double>& alpha, double x, double sigma) { double sum = 0; int n = gram_matrix.size(); for (int i = 0; i < n; i++) { sum += alpha[i] * gaussian_kernel(x, i, sigma); } return sum; } int main() { // 构造数据集 vector<double> x = {1, 2, 3, 4, 5}; vector<double> y = {2, 3, 1, 5, 7}; // 计算带核函数的 Gram 矩阵 double sigma = 1; vector<vector<double>> gram_matrix = compute_gram_matrix(x, sigma); // 计算 alpha double alpha = 0.1; vector<double> alpha_vec = compute_alpha(gram_matrix, y, alpha); // 预测 double x_test = 6; double y_test = predict(gram_matrix, alpha_vec, x_test, sigma); cout << "Predicted value: " << y_test << endl; return 0; } ``` 以上代码实现了基于高斯核函数的 Kernel ridge regression,通过计算带核函数的 Gram 矩阵和求解线性方程组来确定 alpha,然后使用 alpha 进行预测。需要注意的是,Kernel ridge regression 的核函数可以是任意合法的核函数,这里只是提供了高斯核函数的实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值