在进行Linux内核转发时,需要在proc文件系统的proc/sys目录设置转发的参数,可以使用下面的方法查看该参数的值 cat /proc/sys/net/ipv4/ip_forward,该参数的默认值为0,可以使用下面的方法进行修改该值,使能Linux内核的IP层的数据抓发,但是下面的方法在系统重启后不再生效。
echo 1 > /proc/sys/net/ipv4/ip_forward
在Linux系统中也提供了一个系统的配置工具sysctl,使用它可以读取和配置Linux内核的一些参数。但是该方法和proc文件系统相关,使用该工具Linux内核需要支持proc文件系统。下面是使用sysctl配置内核的转发参数。
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
/ #
sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
/ # sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
/ #
注意,参数net.ipv4.ip_forward实际是对应的proc目录/proc/sys/net/ipv4/ip_forward,选项-w表示配置该内核配置参数,没有选项表示读内核配置参数,不加任何选项信息,就表示读取操作。
通过上面的方法我们可以设置和读取IP转发的参数。但是本文重点不是讲该参数如何配置,而是在配置完成后,在内核的转发过程中如何生效的,以及如何配置到内核中。既然,该参数是配置使能IP层的转发,那应该在Linux内核的转发部分对该参数进行了判断,该参数的判断实际上是在查找路由时进行判断的,下面这张图显示了其中的调用关系,
在查路由的过程中,如果是转发的数据包调用下面的宏判断转发的参数是否开启。在函数ip_route_input_slow。
if (!IN_DEV_FORWARD(in_dev))
goto
e_hostunreach;
看一下该宏是如何进行定义的,下面的宏定义在include/linux/inetdevice.h文件中。
#define
IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
在把IN_DEV_CONF_GET宏进一步展开了看:
#define IN_DEV_CONF_GET(in_dev, attr) \
ipv4_devconf_get((in_dev),
NET_IPV4_CONF_ ## attr)//这里的##表示连接两个字符串。
下面是ipv4_devconf_get函数的定义:
static
inline int ipv4_devconf_get(struct in_device *in_dev, int index)
{
index--;//这里的index相当于NET_IPV4_CONF_FORWARDING
return in_dev->cnf.data[index];// init_net->ipv4.devconf_dfl.data[0]
}
(1)对于宏NET_IPV4_CONF_FORWARDING,定义在include/linux/sysctl.h文件中,是一个枚举类型的。
enum
{
NET_IPV4_CONF_FORWARDING=1,
NET_IPV4_CONF_MC_FORWARDING=2,
NET_IPV4_CONF_PROXY_ARP=3,
NET_IPV4_CONF_ACCEPT_REDIRECTS=4,
NET_IPV4_CONF_SECURE_REDIRECTS=5,
NET_IPV4_CONF_SEND_REDIRECTS=6,
NET_IPV4_CONF_SHARED_MEDIA=7,
NET_IPV4_CONF_RP_FILTER=8,
NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
NET_IPV4_CONF_BOOTP_RELAY=10,
NET_IPV4_CONF_LOG_MARTIANS=11,
NET_IPV4_CONF_TAG=12,
NET_IPV4_CONF_ARPFILTER=13,
NET_IPV4_CONF_MEDIUM_ID=14,
NET_IPV4_CONF_NOXFRM=15,
NET_IPV4_CONF_NOPOLICY=16,
NET_IPV4_CONF_FORCE_IGMP_VERSION&