文章目录
用户空间程序如ip和netstat等工具都是通过Netlink接口实现对内核空间中路由表的增删改查,route是通过ioctl()系统调用与内核交互的,这篇笔记介绍了较新的Netlink路由配置接口实现。
涉及的文件有:
源代码路径 | 说明 |
---|---|
include/net/ip_fib.h | IPv4路由数据库头文件 |
core/ipv4/fib_frontend.c | IPv4路由数据库对外接口实现文件 |
命令行
ip route命令详细的介绍可以参考手册ip(8),下面是最常用的命令行参数。
ip route {
add | del | change | append | replace } ROUTE
ROUTE := NODE_SPEC [ INFO_SPEC ]
NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ] [ table TABLE_ID ] [ proto RTPROTO ] [ scope SCOPE ]
INFO_SPEC := {
NH | nhid ID } OPTIONS FLAGS [ nexthop NH ] ...
NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS
可以将命令行中路由项的NODE_SPEC和INFO_SPEC分别与内核路由项中的fib_node、fib_info结构对应。
路由项TYPE:可取的值有unicast、unreachable、blackhole、prohibit、local、broadcast、multicast,对应下面rtmsg->type字段。默认的type为unicast;
PREFIX:路由项目的地址前缀,可以附加’/'指定子网掩码,如192.168.1.0/24,如果不指定子网掩码,那么默认长度为32,这样该路由项表示是一个主机路由;
SCOPE: 路由项的作用域,有link、host、global、数字几种,含义对应下面的rtmsg->scope;
via [ FAMILY ] ADDRESS: 下一跳路由的IP地址;
数据结构
路由项配置信息是作为标准的Netlink消息的数据部分传递到内核的,配置内容主要是rtmsg。
路由消息: rtmsg
struct rtmsg
{
unsigned char rtm_family; // 路由项所属协议族,如AF_INET、AF_INET6;
// 路由项目的地址掩码长度,特别注意是掩码长度,和属性中的RTA_DST配合表示路由项的目的网络
unsigned char rtm_dst_len;
unsigned char rtm_src_len; // 源地址掩码长度
unsigned char rtm_tos; // 路由项的服务质量,对应IP首部的服务字段
// 路由项所述路由表ID,由于只有1个字节,所以取值最大为255,因此用户态能够配置256个路由表,
// 但是内核实际上并不是只能保存256个路由表,内核对此是没有限制的;
unsigned char rtm_table;
unsigned char rtm_protocol; // 路由协议,含义见下方
unsigned char rtm_scope; // 路由项的作用域,含义见下方
unsigned char rtm_type; // 路由项类型,含义见下方
unsigned rtm_flags;
};
对于路由表ID,内核有如下规划,从表ID的定义可以看出,当支持策略路由时(多路由表),用户态程序能够新建的表的ID范围为1~252。
路由表ID | 值 | 说明 |
---|---|---|
RT_TABLE_UNSPEC | 0 | 未知,当操作该路由表时,内核默认会操作main表 |
RT_TABLE_DEFAULT | 253 | default表,用于策略路由的默认路由表 |
RT_TABLE_MAIN | 254 | main表,主路由表,不指定具体要操作的表时就是main表 |
RT_TABLE_LOCAL | 255 | local表,该表维护了本机IP地址相关的路由,由内核自己维护,用户态无法操作 |
对于路由协议,表示的是路由项是如何产生的,可取的值如下,其中常见的是RTPROT_KERNEL和RTPROT_STAIC。
路由协议 | 说明 |
---|---|
RTPROT_UNSPEC | 未知 |
RTPROT_REDIRECT | 该路由项是通过ICMP重定向消息添加的 |
RTPROT_KERNEL | 该路由项是由内核自己添加的,local表的路由大多数属于这一类 | <