- 浏览: 321779 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
JQ_AK47:
...
Linux下直接发送以太包 -
winsen2009:
谢谢分享,如果能再来一个列子就更好了,刚接触看完还是不懂的用
UNPv1_r3读书笔记: SCTP编程
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn
7.12 route route分类是根据数据包的路由信息进行分类的, 路由信息中会带tclassid参数用于分类, 代码在net/sched/cls_route.c中定义, 只支持IPV4。 7.12.1 数据结构和过滤器操作结构 // route 快速映射结构, 相当于分类结果的cache struct route4_fastmap { struct route4_filter *filter; u32 id; int iif; }; // route头结构 struct route4_head { // 16个快速映射结构 struct route4_fastmap fastmap[16]; // 257个bucket链表 struct route4_bucket *table[256+1]; }; struct route4_bucket { /* 16 FROM buckets + 16 IIF buckets + 1 wildcard bucket */ struct route4_filter *ht[16+16+1]; }; // route过滤器结构 struct route4_filter { // 链表中的下一项 struct route4_filter *next; // ID u32 id; // 网卡索引号 int iif; // 分类结构 struct tcf_result res; // TCF扩展 struct tcf_exts exts; // 句柄 u32 handle; // 所在的bucket struct route4_bucket *bkt; }; #define ROUTE4_FAILURE ((struct route4_filter*)(-1L)) static struct tcf_ext_map route_ext_map = { .police = TCA_ROUTE4_POLICE, .action = TCA_ROUTE4_ACT }; static struct tcf_ext_map tcindex_ext_map = { .police = TCA_TCINDEX_POLICE, .action = TCA_TCINDEX_ACT }; // 分类操作结构 static struct tcf_proto_ops cls_route4_ops = { .next = NULL, .kind = "route", .classify = route4_classify, .init = route4_init, .destroy = route4_destroy, .get = route4_get, .put = route4_put, .change = route4_change, .delete = route4_delete, .walk = route4_walk, .dump = route4_dump, .owner = THIS_MODULE, }; 7.12.2 一些哈希函数 // 快速映射表位置哈希 static __inline__ int route4_fastmap_hash(u32 id, int iif) { // 取ID的低4位, 结果在0~15之间 return id&0xF; } // 进入方向路由哈希 static __inline__ int route4_hash_to(u32 id) { // 取ID的低8位, 结果在0~255之间 return id&0xFF; } // 来源方向路由哈希 static __inline__ int route4_hash_from(u32 id) { // 取ID的16~19位, 结果在0~15之间 return (id>>16)&0xF; } // 网卡索引号哈希 static __inline__ int route4_hash_iif(int iif) { // 取网卡索引号的16~19位再加16, 结果在16~31之间 return 16 + ((iif>>16)&0xF); } // 外卡哈希, 返回外卡哈希表号:32 static __inline__ int route4_hash_wild(void) { return 32; } // 插入哈希, 从哈希表中删除时计算 static inline u32 to_hash(u32 id) { // 取低8位 u32 h = id&0xFF; // 第15位为1的话哈希值增加256 if (id&0x8000) h += 256; // 结果范围应该是0~511 return h; } // 来源哈希, 插入哈希表时计算 static inline u32 from_hash(u32 id) { // 高16位清零 id &= 0xFFFF; // 低16位全1的话返回32, 外卡值 if (id == 0xFFFF) return 32; // 如果第15位为0 if (!(id & 0x8000)) { // 超过255的话返回256 if (id > 255) return 256; // 否则返回低4位, 范围为0~15 return id&0xF; } // 第15位为1 // 返回低4位加16, 范围为16~31 return 16 + (id&0xF); } 7.12.3 初始化 // 空函数 static int route4_init(struct tcf_proto *tp) { return 0; } 7.12.4 分类 // 分类结果处理宏 #define ROUTE4_APPLY_RESULT() \ { \ // 要返回的分类结果 *res = f->res; \ if (tcf_exts_is_available(&f->exts)) { \ // 执行TCF扩展操作 int r = tcf_exts_exec(skb, &f->exts, res); \ if (r < 0) { \ // 操作失败, 不需要将结果进cache, 继续循环 dont_cache = 1; \ continue; \ } \ return r; \ } else if (!dont_cache) \ // 将结果进cache, route4_set_fastmap(head, id, iif, f); \ return 0; \ } static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { // route头节点 struct route4_head *head = (struct route4_head*)tp->root; struct dst_entry *dst; struct route4_bucket *b; struct route4_filter *f; u32 id, h; int iif, dont_cache = 0; // 如果数据包路由项为空, 分类失败 if ((dst = skb->dst) == NULL) goto failure; // 类别ID id = dst->tclassid; // 如果头节点空, 用老方法分类 if (head == NULL) goto old_method; // 网卡索引号 iif = ((struct rtable*)dst)->fl.iif; // 根据ID和网卡索引号计算快速映射哈希值 h = route4_fastmap_hash(id, iif); // 如果快速映射表中元素和此ID和网卡匹配, 而且过滤结构有效 if (id == head->fastmap[h].id && iif == head->fastmap[h].iif && (f = head->fastmap[h].filter) != NULL) { // 如果是错误分类, 返回失败 if (f == ROUTE4_FAILURE) goto failure; // 否则返回分类结构, 分类成功 *res = f->res; return 0; } // 单独根据ID计算路由to哈希值 h = route4_hash_to(id); restart: // 如果该哈希值对应的表有效 if ((b = head->table[h]) != NULL) { // 根据ID哈希, 遍历合适的链表 for (f = b->ht[route4_hash_from(id)]; f; f = f->next) // 如果ID匹配, 成功返回 if (f->id == id) ROUTE4_APPLY_RESULT(); // 根据网卡索引哈希, 遍历合适链表 for (f = b->ht[route4_hash_iif(iif)]; f; f = f->next) // 如果网卡索引匹配, 成功返回 if (f->iif == iif) ROUTE4_APPLY_RESULT(); // 还没找到, 如果外卡链表存在的话, 也成功返回 for (f = b->ht[route4_hash_wild()]; f; f = f->next) ROUTE4_APPLY_RESULT(); } // 哈希值对应的表为空的情况 // 如果哈希值太小, 更新其值后重新查找 if (h < 256) { h = 256; id &= ~0xFFFF; goto restart; } // 否则分类失败 // 如果需要保存在cache中, 将ID和网卡索引号保存到快速索引表中 if (!dont_cache) route4_set_fastmap(head, id, iif, ROUTE4_FAILURE); failure: return -1; old_method: // 老分类方法 // 如果ID有效, 而且ID高16位为0或高16位和handle的高16位相同 if (id && (TC_H_MAJ(id) == 0 || !(TC_H_MAJ(id^tp->q->handle)))) { // 将ID作为类别ID返回 res->classid = id; res->class = 0; return 0; } return -1; } 7.12.5 释放 static void route4_destroy(struct tcf_proto *tp) { // 将根节点换出来准备释放 struct route4_head *head = xchg(&tp->root, NULL); int h1, h2; // 如果根节点空, 直接返回 if (head == NULL) return; // 遍历257个表 for (h1=0; h1<=256; h1++) { struct route4_bucket *b; // 如果链表头非空 if ((b = head->table[h1]) != NULL) { // 遍历bucket结构的33个filter链表 for (h2=0; h2<=32; h2++) { struct route4_filter *f; // 遍历每个链表 while ((f = b->ht[h2]) != NULL) { // 断开节点 b->ht[h2] = f->next; // 删除filter route4_delete_filter(tp, f); } } // 释放bucket kfree(b); } } // 释放根节点 kfree(head); } static inline void route4_delete_filter(struct tcf_proto *tp, struct route4_filter *f) { // 解除绑定 tcf_unbind_filter(tp, &f->res); // 释放TCF扩展结构 tcf_exts_destroy(tp, &f->exts); // 释放过滤器空间 kfree(f); } 7.12.6 获取 // 根据handle查找route4_filter结构 static unsigned long route4_get(struct tcf_proto *tp, u32 handle) { // 根节点 struct route4_head *head = (struct route4_head*)tp->root; struct route4_bucket *b; struct route4_filter *f; unsigned h1, h2; // 根节点空的话返回0 if (!head) return 0; // 根据handle计算哈希值 h1 = to_hash(handle); // 超过256的话返回0 if (h1 > 256) return 0; // 根据handle的高16位计算哈希找bucket h2 = from_hash(handle>>16); // 超过32的话返回0 if (h2 > 32) return 0; // 如果bucket非空 if ((b = head->table[h1]) != NULL) { // 遍历链表 for (f = b->ht[h2]; f; f = f->next) // 查找handle匹配的filter节点返回 if (f->handle == handle) return (unsigned long)f; } return 0; } 7.12.7 放下 // 空函数 static void route4_put(struct tcf_proto *tp, unsigned long f) { } 7.12.8 修改 // 增加和修改tc filter规则时调用 static int route4_change(struct tcf_proto *tp, unsigned long base, u32 handle, struct rtattr **tca, unsigned long *arg) { // 根节点 struct route4_head *head = tp->root; struct route4_filter *f, *f1, **fp; struct route4_bucket *b; // 输入的选项参数 struct rtattr *opt = tca[TCA_OPTIONS-1]; struct rtattr *tb[TCA_ROUTE4_MAX]; unsigned int h, th; u32 old_handle = 0; int err; // 选项参数空, 返回 if (opt == NULL) return handle ? -EINVAL : 0; // 解析选项参数, 结果保存到tb数组 if (rtattr_parse_nested(tb, TCA_ROUTE4_MAX, opt) < 0) return -EINVAL; // 过滤器参数非空, 是修改操作 if ((f = (struct route4_filter*)*arg) != NULL) { // 比较handle是否正确 if (f->handle != handle && handle) return -EINVAL; // 如果已经在某bucket的链表里, 保存handle if (f->bkt) old_handle = f->handle; // 设置过滤器参数, 函数最后一个参数为0表示是修改 err = route4_set_parms(tp, base, f, handle, head, tb, tca[TCA_RATE-1], 0); // 操作失败, 返回错误 if (err < 0) return err; // 成功则跳转重新插入, 将f从原链表中断开的操作也在后面进行 goto reinsert; } // 过滤器参数空, 是新建操作 err = -ENOBUFS; if (head == NULL) { // 如果根节点为空, 分配更节点空间 head = kzalloc(sizeof(struct route4_head), GFP_KERNEL); if (head == NULL) goto errout; tcf_tree_lock(tp); // 将其作为tcf_proto的根参数指针 tp->root = head; tcf_tree_unlock(tp); } // 分配新的过滤器空间 f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL); if (f == NULL) goto errout; // 设置过滤器参数, 函数最后一个参数为1表示是新建 err = route4_set_parms(tp, base, f, handle, head, tb, tca[TCA_RATE-1], 1); // 失败的话转失败处理 if (err < 0) goto errout; reinsert: // 重新插入操作, 将过滤器f插入合适的bucket链表, 对于修改操作, 因为参数变了, // 所以要重新插入到合适的bucket中 // 计算from哈希 h = from_hash(f->handle >> 16); // 遍历相应的哈希链表查找插入位置, 该链表是按handle值排序, 小的在前, 大的在后 for (fp = &f->bkt->ht[h]; (f1=*fp) != NULL; fp = &f1->next) if (f->handle < f1->handle) break; // 将新节点插入链表 f->next = f1; tcf_tree_lock(tp); *fp = f; // 如果handle发生了变化, 需要将该过滤器从原来的链表中断开 // 不过找哪个哈希表的过程确挺费解的 if (old_handle && f->handle != old_handle) { // 计算老handle的to哈希 th = to_hash(old_handle); // 计算老handle高16位的from哈希 h = from_hash(old_handle >> 16); // to哈希链表非空 if ((b = head->table[th]) != NULL) { // 遍历链表 for (fp = &b->ht[h]; *fp; fp = &(*fp)->next) { // 查找过滤器节点 if (*fp == f) { // 从链表中断开 *fp = f->next; break; } } } } tcf_tree_unlock(tp); // 复位快速映射数组, 全部清零 route4_reset_fastmap(tp->q->dev, head, f->id); // 返回f的地址 *arg = (unsigned long)f; return 0; errout: kfree(f); return err; } // 设置过滤器参数 static int route4_set_parms(struct tcf_proto *tp, unsigned long base, struct route4_filter *f, u32 handle, struct route4_head *head, struct rtattr **tb, struct rtattr *est, int new) { int err; u32 id = 0, to = 0, nhandle = 0x8000; struct route4_filter *fp; unsigned int h1; struct route4_bucket *b; struct tcf_exts e; // TCF扩展验证 err = tcf_exts_validate(tp, tb, est, &e, &route_ext_map); if (err < 0) return err; err = -EINVAL; // 判断类别ID是否合法 if (tb[TCA_ROUTE4_CLASSID-1]) if (RTA_PAYLOAD(tb[TCA_ROUTE4_CLASSID-1]) < sizeof(u32)) goto errout; // 解析TO参数 if (tb[TCA_ROUTE4_TO-1]) { if (new && handle & 0x8000) goto errout; if (RTA_PAYLOAD(tb[TCA_ROUTE4_TO-1]) < sizeof(u32)) goto errout; to = *(u32*)RTA_DATA(tb[TCA_ROUTE4_TO-1]); // TO参数不能超过255 if (to > 0xFF) goto errout; // 将TO参数作为nhandle的低0~8位 nhandle = to; } // 如果存在FROM参数 if (tb[TCA_ROUTE4_FROM-1]) { // 解析FROM参数 if (tb[TCA_ROUTE4_IIF-1]) goto errout; if (RTA_PAYLOAD(tb[TCA_ROUTE4_FROM-1]) < sizeof(u32)) goto errout; id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_FROM-1]); // FROM参数也不能超过255 if (id > 0xFF) goto errout; // 将FROM参数作为nhandle的16~23位 nhandle |= id << 16; } else if (tb[TCA_ROUTE4_IIF-1]) { // 否则如果存在网卡参数 if (RTA_PAYLOAD(tb[TCA_ROUTE4_IIF-1]) < sizeof(u32)) goto errout; id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_IIF-1]); // 网卡参数不能超过0x7ffff if (id > 0x7FFF) goto errout; // 将网卡参数作为nhandle的16~30位, 同时第15位置1 nhandle |= (id | 0x8000) << 16; } else // 否则nhandle高16位全1 nhandle |= 0xFFFF << 16; if (handle && new) { // 如果是新建而且handle非0 // 更新nhandle, 前面的计算全部费了 nhandle |= handle & 0x7F00; // 对于新建的filter, handle只能是在16~22位可以为1 if (nhandle != handle) goto errout; } // 计算新handle的to哈希 h1 = to_hash(nhandle); // 如果对应哈希值的bucket为空 if ((b = head->table[h1]) == NULL) { err = -ENOBUFS; // 分配bucket空间 b = kzalloc(sizeof(struct route4_bucket), GFP_KERNEL); if (b == NULL) goto errout; tcf_tree_lock(tp); // 赋值到bucket头数组 head->table[h1] = b; tcf_tree_unlock(tp); } else { // 否则计算高16位的from哈希 unsigned int h2 = from_hash(nhandle >> 16); err = -EEXIST; // 遍历bucket中相应的链表, 查找是否已经有相同的handle, 找到的话返回错误 for (fp = b->ht[h2]; fp; fp = fp->next) if (fp->handle == f->handle) goto errout; } tcf_tree_lock(tp); // 如果TO参数存在的话, ID取TO参数 if (tb[TCA_ROUTE4_TO-1]) f->id = to; // 如果FROM参数存在的话, ID放到ID的高16位 if (tb[TCA_ROUTE4_FROM-1]) f->id = to | id<<16; else if (tb[TCA_ROUTE4_IIF-1]) f->iif = id; // 过滤器的新handle f->handle = nhandle; // 过滤器所在的bucket f->bkt = b; tcf_tree_unlock(tp); // 设置类别ID, 绑定过滤器 if (tb[TCA_ROUTE4_CLASSID-1]) { f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]); tcf_bind_filter(tp, &f->res, base); } // TCF扩展修改操作 tcf_exts_change(tp, &f->exts, &e); return 0; errout: tcf_exts_destroy(tp, &e); return err; } 7.12.9 删除 static int route4_delete(struct tcf_proto *tp, unsigned long arg) { // 更节点 struct route4_head *head = (struct route4_head*)tp->root; // f是要删除的节点 struct route4_filter **fp, *f = (struct route4_filter*)arg; unsigned h = 0; struct route4_bucket *b; int i; // 根节点或要删除的节点为空, 参数错误 if (!head || !f) return -EINVAL; // 获取过滤器节点的handle和所在的bucket h = f->handle; b = f->bkt; // 遍历该bucket的链表 for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) { // 查找f节点 if (*fp == f) { // 找到 tcf_tree_lock(tp); // 将该节点从链表中断开 *fp = f->next; tcf_tree_unlock(tp); // 复位快速映射表, 是将fastmap数组全部清零了, 好象是连坐一样 route4_reset_fastmap(tp->q->dev, head, f->id); // 释放该过滤器f route4_delete_filter(tp, f); /* Strip tree */ // 检查该f所在bucket是否已经空了 for (i=0; i<=32; i++) if (b->ht[i]) return 0; /* OK, session has no flows */ // 如果空了, 就准备删除该bucket tcf_tree_lock(tp); // 哈希表头置空 head->table[to_hash(h)] = NULL; tcf_tree_unlock(tp); // 释放bucket kfree(b); return 0; } } return 0; } 7.12.10 遍历 static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) { // 根节点 struct route4_head *head = tp->root; unsigned h, h1; // 根节点空的话设置停止标志 if (head == NULL) arg->stop = 1; // 设置了停止标志时直接返回 if (arg->stop) return; // 遍历257个bucket for (h = 0; h <= 256; h++) { struct route4_bucket *b = head->table[h]; // 如果该bucket非空 if (b) { // 遍历33个链表 for (h1 = 0; h1 <= 32; h1++) { struct route4_filter *f; // 遍历链表 for (f = b->ht[h1]; f; f = f->next) { // 检查是否是需要跳过的节点 if (arg->count < arg->skip) { arg->count++; continue; } // 执行单节点处理函数 if (arg->fn(tp, (unsigned long)f, arg) < 0) { // 失败的话设置停止标志, 返回 arg->stop = 1; return; } arg->count++; } } } } } 7.12.11 输出 static int route4_dump(struct tcf_proto *tp, unsigned long fh, struct sk_buff *skb, struct tcmsg *t) { // 要输出的route过滤器节点 struct route4_filter *f = (struct route4_filter*)fh; // skb数据包缓冲区定位 unsigned char *b = skb->tail; struct rtattr *rta; u32 id; // 过滤器空, 返回 if (f == NULL) return skb->len; // 填写handle t->tcm_handle = f->handle; // 结构定位 rta = (struct rtattr*)b; RTA_PUT(skb, TCA_OPTIONS, 0, NULL); // 输出ROUTE_TO if (!(f->handle&0x8000)) { id = f->id&0xFF; RTA_PUT(skb, TCA_ROUTE4_TO, sizeof(id), &id); } if (f->handle&0x80000000) { // handle最高位为1 if ((f->handle>>16) != 0xFFFF) // handle高16非全1的话输出网卡索引号 RTA_PUT(skb, TCA_ROUTE4_IIF, sizeof(f->iif), &f->iif); } else { // handle最高位为0 // ID高16位是ROUTE_FROM id = f->id>>16; RTA_PUT(skb, TCA_ROUTE4_FROM, sizeof(id), &id); } // 类别ID if (f->res.classid) RTA_PUT(skb, TCA_ROUTE4_CLASSID, 4, &f->res.classid); // TCF扩展输出 if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0) goto rtattr_failure; rta->rta_len = skb->tail - b; // TCF扩展统计 if (tcf_exts_dump_stats(skb, &f->exts, &route_ext_map) < 0) goto rtattr_failure; return skb->len; rtattr_failure: skb_trim(skb, b - skb->data); return -1; } 7.13 小结 分类操作结构分析告一段落, 基本的特点就是对节点操作时都不直接操作, 而是先在链表中查找确认后才操作, 这也是sched各种代码的共同特征, 为什么不能直接操作呢? 难道是怕在get操作时获取的结构指针在后来操作时已经被删除了? 不过的确这些结构中不是所有都有引用计数的原子操作; 另外一点就是handle的取值, 每个操作结构所对应的handle各个位的定义是不同, 同时进行各种哈希操作也不同, 这些都需要注意, 不过在此不仔细比较各类型的handle的不同了, 有兴趣的自己去分析。 ...... 待续 ......
发表评论
-
Linux内核中流量控制(24)
2011-01-10 16:33 2244本文档的Copyleft归yfydz所 ... -
Linux内核中流量控制(23)
2011-01-10 16:30 1530本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(22)
2011-01-10 16:29 1979本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(20)
2011-01-10 16:27 1566本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(19)
2011-01-10 16:27 2021本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(18)
2011-01-10 16:26 1614Linux内核中流量控制(18) ... -
Linux内核中流量控制(17)
2011-01-10 16:25 1989本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(16)
2011-01-10 16:25 1847本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(15)
2011-01-10 16:24 1979本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(14)
2011-01-10 16:23 2000本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(13)
2011-01-10 16:22 2686本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(12)
2011-01-10 16:21 2164本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(11)
2011-01-10 16:21 3287本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(10)
2011-01-10 16:20 2040本文档的Copyleft归yfydz所 ... -
Linux内核中流量控制(9)
2011-01-10 16:19 1874本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(8)
2011-01-10 16:18 1543本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(7)
2011-01-10 16:18 2971本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(6)
2011-01-10 16:17 1537本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(5)
2011-01-10 16:16 1767本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(4)
2011-01-10 16:15 1687本文档的Copyleft归yfydz所有,使用GPL发布,可以 ...
相关推荐
在Linux内核中,TCP和UDP模块处理连接建立、数据传输、流量控制和拥塞控制等问题。 5. **应用层**:这一层包含各种应用协议,如HTTP、FTP、SMTP等,它们直接与用户交互。Linux内核通过socket API为上层应用提供了与...
【基于Linux内核的BT流量控制的原理与实现】 Linux操作系统以其开源、可定制的特点,在系统开发领域广泛应用,尤其在网络流量控制方面具有显著优势。针对BitTorrent(BT)这种大量占用带宽的P2P协议,Linux内核提供...
4. **网络堆栈**:从硬件接口到应用层协议的整个网络传输流程,如TCP/IP协议族、套接字API、网络设备驱动程序以及流量控制策略。 5. **设备驱动**:内核如何与硬件交互,驱动程序的工作原理,包括字符设备、块设备...
通过分析源码,我们可以了解到数据包的接收与发送过程,理解TCP连接的建立与断开、拥塞控制、流量控制等机制,这对于网络编程和网络故障排查非常有帮助。 此外,Linux内核还涉及中断处理、设备驱动、I/O管理等多个...
【基于Linux内核扩展模块的P2P流量控制】这篇文献主要探讨了如何在Linux操作系统中,通过内核扩展模块来实现对P2P流量的有效控制。P2P(Peer-to-Peer)技术的兴起改变了互联网的中心化结构,使得资源分享更为便捷,...
基于Linux内核扩展模块的P2P流量控制
基于LQL库的流量控制方法可以直接在Linux内核的框架下实现,而不需要使用传统方法中的TC命令解析、netlink传输和内核空间执行的三层结构。这可以提高流量控制的效率和可靠性,同时也可以减少流量控制的延迟和资源...
书中的内容涵盖了从内核基础到高级技术的方方面面,为那些希望提升Linux内核理解和开发能力的读者提供了宝贵的资源。在本文中,我们将探讨几个关键的知识点,包括Linux内核的基本结构、进程管理、内存管理和设备驱动...
2.6.24版本在网络方面加强了IPv6的支持,并改进了网络流量控制算法。 6. **安全与权限管理**:Linux内核采用了用户和组的概念,通过权限系统(如chmod、chown等)来控制文件访问。此外,还有SELinux(Security-...
接着,作者深入剖析了网络设备数据结构net_device,它包含了设备的配置信息、统计信息、状态标志以及各种管理列表和流量控制字段,这些细节揭示了网络设备如何在内核中被抽象和管理。 通过以上内容,我们可以看到,...
它处理网络数据的接收和发送,进行网络层的路由选择,以及传输层的拥塞控制和流量控制。 5. **设备驱动**:设备驱动程序是内核与硬件之间的桥梁,使得内核能够控制硬件设备。Linux内核支持大量设备驱动,包括块设备...
该模型内置于Linux内核中,并利用队列算法对不同服务质量(Quality of Service, QoS)需求的数据流进行分类,以提供灵活且差异化的服务。实验结果表明,采用该流量控制模型后,网络性能显著提高,并能很好地适应未来...
在Linux操作系统中,高级路由和流量控制是网络管理员和系统管理员必须掌握的关键技能。这篇文档“Linux高级路由和流量控制HOWTO中文版”由牛老师翻译,为读者提供了深入理解这些概念的宝贵资源。以下是对其中核心...
同时,还会讨论TCP的流量控制和拥塞控制机制,如滑动窗口、慢启动、快速重传和快速恢复算法等,这些都是保证网络通信质量和效率的关键。 其次,关于IP协议,书里会涉及IP地址、子网掩码、路由选择等概念,以及IP分...
TC 工具基于 Linux 内核的网络设备驱动程序,通过对网络设备的控制,来实现流量控制。TC 的工作原理可以分为以下三个阶段: 1. 流量控制方式:TC 提供了多种流量控制方式,包括 Token Bucket Filter(TBF)、...
TC(Linux 下流量控制工具)详细说明及应用实例 TC 是 Linux 下的一种流量控制工具,用于控制和管理网络流量。它提供了一个灵活的方式来管理网络带宽、延迟和丢包率等网络性能参数,以满足不同应用场景的需求。 TC...
2. **TCP/IP协议**:在传输层,TCP(传输控制协议)提供可靠的数据传输服务,通过确认、重传和流量控制确保数据的完整性和顺序。IP(互联网协议)在网络层负责数据包的路由和分片,是互联网的基础协议。 3. **套接...
Linux内核中的sock和socket数据结构是网络编程的核心组成部分,它们是实现网络通信的基础构件。在Linux操作系统中,网络通信的实现依赖于BSD套接字接口,而这一接口在内核中是通过sock和socket数据结构来实现的。 ...