linux sysctl 參數實現 暨 ip_forward參數對Linux核心轉寄影響分析__PHP

來源:互聯網
上載者:User

摘自: http://blog.chinaunix.net/uid-20788636-id-4398392.html 


  ip_forward參數對Linux核心轉寄影響分析  2014-08-07 20:40:59

分類: LINUX

在進行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=17,

         NET_IPV4_CONF_ARP_ANNOUNCE=18,

         NET_IPV4_CONF_ARP_IGNORE=19,

         NET_IPV4_CONF_PROMOTE_SECONDARIES=20,

         NET_IPV4_CONF_ARP_ACCEPT=21,

         NET_IPV4_CONF_ARP_NOTIFY=22,

         NET_IPV4_CONF_SRC_VMARK=24,

         __NET_IPV4_CONF_MAX

};

(2)對於return in_dev->cnf.data[index];返回的相當於in_dev->cnf.data[0],那下面我們看一下該初始值是如何產生的。

         首先,in_dev是怎麼擷取到的,在ip_route_input_slow函數中通過struct in_device *in_dev = in_dev_get(dev);函數擷取,在in_dev_get函數中調用__in_dev_get_rcu,通過下面的指派陳述式進行賦值struct in_device *in_dev = dev->ip_ptr;

static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev)

{

         struct in_device *in_dev = dev->ip_ptr;

         if (in_dev)

                   in_dev = rcu_dereference(in_dev);

         return in_dev;

}

 

static __inline__ struct in_device *

in_dev_get(const struct net_device *dev)

{

         struct in_device *in_dev;

 

         rcu_read_lock();

         in_dev = __in_dev_get_rcu(dev);

         if (in_dev)

                   atomic_inc(&in_dev->refcnt);

         rcu_read_unlock();

         return in_dev;

}

         dev->ip_ptr;又是什麼時候賦值呢。答案是在net_device註冊初始化函數inetdev_init中,

static struct in_device *inetdev_init(struct net_device *dev)

{

         struct in_device *in_dev;

 

         ASSERT_RTNL();

 

         in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL);

         if (!in_dev)

                   goto out;

         memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,

                            sizeof(in_dev->cnf));//這裡對in_dev->cnt進行初始化操作,---(1)

         in_dev->cnf.sysctl = NULL;

         in_dev->dev = dev;

         if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)

                   goto out_kfree;

         if (IPV4_DEVCONF(in_dev->cnf, FORWARDING))

                   dev_disable_lro(dev);

         /* Reference in_dev->dev */

         dev_hold(dev);

         /* Account for reference dev->ip_ptr (below) */

         in_dev_hold(in_dev);

 

         devinet_sysctl_register(in_dev);

         ip_mc_init_dev(in_dev);

         if (dev->flags & IFF_UP)

                   ip_mc_up(in_dev);

 

         /* we can receive as soon as ip_ptr is set -- do this last */

         rcu_assign_pointer(dev->ip_ptr, in_dev);//使用RCU保護鎖機制對dev->ip_ptr進行賦值

out:

         return in_dev;

out_kfree:

         kfree(in_dev);

         in_dev = NULL;

         goto out;

}

(1)dev_net(dev)->ipv4.devconf_dfl 也就相當於init_net->ipv4.devconf_dfl,而devconf_dfl的初始化時在/net/ipv4/devinet.c檔案中,devinet_init_net函數中,

static struct ipv4_devconf ipv4_devconf_dflt = {

         .data = {

                   [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,

                   [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,

                   [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,

                   [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,

                   [NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1,

         },

};//這裡並沒有對FORWARDING進行賦值操作

static __net_init int devinet_init_net(struct net *net)

{

         int err;

         struct ipv4_devconf *all, *dflt;

#ifdef CONFIG_SYSCTL

         struct ctl_table *tbl = ctl_forward_entry;

         struct ctl_table_header *forw_hdr;

#endif

 

         err = -ENOMEM;

         all = &ipv4_devconf; //----------------------------進行初始化操作

         dflt = &ipv4_devconf_dflt;

 

         if (net != &init_net) {

                   all = kmemdup(all, sizeof(ipv4_devconf), GFP_KERNEL);

                   if (all == NULL)

                   &nb

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.