Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.25-rc7 /net/ipv4/fib_frontend.c

Filename:/net/ipv4/fib_frontend.c
Lines Added:212
Lines Deleted:71
Also changed in: (Previous) 2.6.25-rc6  2.6.25-rc5  2.6.25-rc4  2.6.25-rc3  2.6.25-rc2  2.6.25-rc1 
(Following) 2.6.25-rc8  2.6.25-rc9  2.6.25  2.6.25-git2  2.6.25-git3  2.6.25-git4 

Location
[  2.6.25-rc7
  [  net
    [  ipv4
       o  fib_frontend.c

Patch

diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 97abf93..86ff271 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -47,59 +47,65 @@
 #include <net/ip_fib.h>
 #include <net/rtnetlink.h>
 
-#define FFprint(a...) printk(KERN_DEBUG a)
+#ifndef CONFIG_IP_MULTIPLE_TABLES
 
-static struct sock *fibnl;
+static int __net_init fib4_rules_init(struct net *net)
+{
+   struct fib_table *local_table, *main_table;
 
-#ifndef CONFIG_IP_MULTIPLE_TABLES
+   local_table = fib_hash_table(RT_TABLE_LOCAL);
+   if (local_table == NULL)
+      return -ENOMEM;
 
-struct fib_table *ip_fib_local_table;
-struct fib_table *ip_fib_main_table;
+   main_table  = fib_hash_table(RT_TABLE_MAIN);
+   if (main_table == NULL)
+      goto fail;
 
-#define FIB_TABLE_HASHSZ 1
-static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+   hlist_add_head_rcu(&local_table->tb_hlist,
+            &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX]);
+   hlist_add_head_rcu(&main_table->tb_hlist,
+            &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]);
+   return 0;
 
-static void __init fib4_rules_init(void)
-{
-   ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
-   hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
-   ip_fib_main_table  = fib_hash_init(RT_TABLE_MAIN);
-   hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
+fail:
+   kfree(local_table);
+   return -ENOMEM;
 }
 #else
 
-#define FIB_TABLE_HASHSZ 256
-static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
-
-struct fib_table *fib_new_table(u32 id)
+struct fib_table *fib_new_table(struct net *net, u32 id)
 {
    struct fib_table *tb;
    unsigned int h;
 
    if (id == 0)
       id = RT_TABLE_MAIN;
-   tb = fib_get_table(id);
+   tb = fib_get_table(net, id);
    if (tb)
       return tb;
-   tb = fib_hash_init(id);
+
+   tb = fib_hash_table(id);
    if (!tb)
       return NULL;
    h = id & (FIB_TABLE_HASHSZ - 1);
-   hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]);
+   hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]);
    return tb;
 }
 
-struct fib_table *fib_get_table(u32 id)
+struct fib_table *fib_get_table(struct net *net, u32 id)
 {
    struct fib_table *tb;
    struct hlist_node *node;
+   struct hlist_head *head;
    unsigned int h;
 
    if (id == 0)
       id = RT_TABLE_MAIN;
    h = id & (FIB_TABLE_HASHSZ - 1);
+
    rcu_read_lock();
-   hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb_hlist) {
+   head = &net->ipv4.fib_table_hash[h];
+   hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
       if (tb->tb_id == id) {
          rcu_read_unlock();
          return tb;
@@ -110,15 +116,32 @@ struct fib_table *fib_get_table(u32 id)
 }
 #endif /* CONFIG_IP_MULTIPLE_TABLES */
 
-static void fib_flush(void)
+void fib_select_default(struct net *net,
+         const struct flowi *flp, struct fib_result *res)
+{
+   struct fib_table *tb;
+   int table = RT_TABLE_MAIN;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+   if (res->r == NULL || res->r->action != FR_ACT_TO_TBL)
+      return;
+   table = res->r->table;
+#endif
+   tb = fib_get_table(net, table);
+   if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+      tb->tb_select_default(tb, flp, res);
+}
+
+static void fib_flush(struct net *net)
 {
    int flushed = 0;
    struct fib_table *tb;
    struct hlist_node *node;
+   struct hlist_head *head;
    unsigned int h;
 
    for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
-      hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist)
+      head = &net->ipv4.fib_table_hash[h];
+      hlist_for_each_entry(tb, node, head, tb_hlist)
          flushed += tb->tb_flush(tb);
    }
 
@@ -130,7 +153,7 @@ static void fib_flush(void)
  *   Find the first device with a given source address.
  */
 
-struct net_device * ip_dev_find(__be32 addr)
+struct net_device * ip_dev_find(struct net *net, __be32 addr)
 {
    struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
    struct fib_result res;
@@ -141,7 +164,7 @@ struct net_device * ip_dev_find(__be32 addr)
    res.r = NULL;
 #endif
 
-   local_table = fib_get_table(RT_TABLE_LOCAL);
+   local_table = fib_get_table(net, RT_TABLE_LOCAL);
    if (!local_table || local_table->tb_lookup(local_table, &fl, &res))
       return NULL;
    if (res.type != RTN_LOCAL)
@@ -155,33 +178,51 @@ out:
    return dev;
 }
 
-unsigned inet_addr_type(__be32 addr)
+/*
+ * Find address type as if only "dev" was present in the system. If
+ * on_dev is NULL then all interfaces are taken into consideration.
+ */
+static inline unsigned __inet_dev_addr_type(struct net *net,
+                   const struct net_device *dev,
+                   __be32 addr)
 {
    struct flowi      fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
    struct fib_result   res;
    unsigned ret = RTN_BROADCAST;
    struct fib_table *local_table;
 
-   if (ZERONET(addr) || BADCLASS(addr))
+   if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr))
       return RTN_BROADCAST;
-   if (MULTICAST(addr))
+   if (ipv4_is_multicast(addr))
       return RTN_MULTICAST;
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
    res.r = NULL;
 #endif
 
-   local_table = fib_get_table(RT_TABLE_LOCAL);
+   local_table = fib_get_table(net, RT_TABLE_LOCAL);
    if (local_table) {
       ret = RTN_UNICAST;
       if (!local_table->tb_lookup(local_table, &fl, &res)) {
-         ret = res.type;
+         if (!dev || dev == res.fi->fib_dev)
+            ret = res.type;
          fib_res_put(&res);
       }
    }
    return ret;
 }
 
+unsigned int inet_addr_type(struct net *net, __be32 addr)
+{
+   return __inet_dev_addr_type(net, NULL, addr);
+}
+
+unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
+            __be32 addr)
+{
+       return __inet_dev_addr_type(net, dev, addr);
+}
+
 /* Given (packet source, input interface) and optional (dst, oif, tos):
    - (main) check, that source is valid i.e. not broadcast or our local
      address.
@@ -202,6 +243,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
    struct fib_result res;
    int no_addr, rpf;
    int ret;
+   struct net *net;
 
    no_addr = rpf = 0;
    rcu_read_lock();
@@ -215,7 +257,8 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
    if (in_dev == NULL)
       goto e_inval;
 
-   if (fib_lookup(&fl, &res))
+   net = dev->nd_net;
+   if (fib_lookup(net, &fl, &res))
       goto last_resort;
    if (res.type != RTN_UNICAST)
       goto e_inval_res;
@@ -239,7 +282,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
    fl.oif = dev->ifindex;
 
    ret = 0;
-   if (fib_lookup(&fl, &res) == 0) {
+   if (fib_lookup(net, &fl, &res) == 0) {
       if (res.type == RTN_UNICAST) {
          *spec_dst = FIB_RES_PREFSRC(res);
          ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
@@ -278,13 +321,14 @@ static int put_rtax(struct nlattr *mx, int len, int type, u32 value)
    return len + nla_total_size(4);
 }
 
-static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
+static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
              struct fib_config *cfg)
 {
    __be32 addr;
    int plen;
 
    memset(cfg, 0, sizeof(*cfg));
+   cfg->fc_nlinfo.nl_net = net;
 
    if (rt->rt_dst.sa_family != AF_INET)
       return -EAFNOSUPPORT;
@@ -345,7 +389,7 @@ static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
       colon = strchr(devname, ':');
       if (colon)
          *colon = 0;
-      dev = __dev_get_by_name(&init_net, devname);
+      dev = __dev_get_by_name(net, devname);
       if (!dev)
          return -ENODEV;
       cfg->fc_oif = dev->ifindex;
@@ -368,7 +412,7 @@ static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
    if (rt->rt_gateway.sa_family == AF_INET && addr) {
       cfg->fc_gw = addr;
       if (rt->rt_flags & RTF_GATEWAY &&
-          inet_addr_type(addr) == RTN_UNICAST)
+          inet_addr_type(net, addr) == RTN_UNICAST)
          cfg->fc_scope = RT_SCOPE_UNIVERSE;
    }
 
@@ -409,7 +453,7 @@ static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
  *   Handle IP routing ioctl calls. These are used to manipulate the routing tables
  */
 
-int ip_rt_ioctl(unsigned int cmd, void __user *arg)
+int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 {
    struct fib_config cfg;
    struct rtentry rt;
@@ -425,18 +469,18 @@ int ip_rt_ioctl(unsigned int cmd, void __user *arg)
          return -EFAULT;
 
       rtnl_lock();
-      err = rtentry_to_fib_config(cmd, &rt, &cfg);
+      err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
       if (err == 0) {
          struct fib_table *tb;
 
          if (cmd == SIOCDELRT) {
-            tb = fib_get_table(cfg.fc_table);
+            tb = fib_get_table(net, cfg.fc_table);
             if (tb)
                err = tb->tb_delete(tb, &cfg);
             else
                err = -ESRCH;
          } else {
-            tb = fib_new_table(cfg.fc_table);
+            tb = fib_new_table(net, cfg.fc_table);
             if (tb)
                err = tb->tb_insert(tb, &cfg);
             else
@@ -466,8 +510,8 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = {
    [RTA_FLOW]      = { .type = NLA_U32 },
 };
 
-static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
-              struct fib_config *cfg)
+static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
+             struct nlmsghdr *nlh, struct fib_config *cfg)
 {
    struct nlattr *attr;
    int err, remaining;
@@ -491,6 +535,7 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 
    cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
    cfg->fc_nlinfo.nlh = nlh;
+   cfg->fc_nlinfo.nl_net = net;
 
    if (cfg->fc_type > RTN_MAX) {
       err = -EINVAL;
@@ -538,15 +583,16 @@ errout:
 
 static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
+   struct net *net = skb->sk->sk_net;
    struct fib_config cfg;
    struct fib_table *tb;
    int err;
 
-   err = rtm_to_fib_config(skb, nlh, &cfg);
+   err = rtm_to_fib_config(net, skb, nlh, &cfg);
    if (err < 0)
       goto errout;
 
-   tb = fib_get_table(cfg.fc_table);
+   tb = fib_get_table(net, cfg.fc_table);
    if (tb == NULL) {
       err = -ESRCH;
       goto errout;
@@ -559,15 +605,16 @@ errout:
 
 static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
+   struct net *net = skb->sk->sk_net;
    struct fib_config cfg;
    struct fib_table *tb;
    int err;
 
-   err = rtm_to_fib_config(skb, nlh, &cfg);
+   err = rtm_to_fib_config(net, skb, nlh, &cfg);
    if (err < 0)
       goto errout;
 
-   tb = fib_new_table(cfg.fc_table);
+   tb = fib_new_table(net, cfg.fc_table);
    if (tb == NULL) {
       err = -ENOBUFS;
       goto errout;
@@ -580,10 +627,12 @@ errout:
 
 static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
 {
+   struct net *net = skb->sk->sk_net;
    unsigned int h, s_h;
    unsigned int e = 0, s_e;
    struct fib_table *tb;
    struct hlist_node *node;
+   struct hlist_head *head;
    int dumped = 0;
 
    if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
@@ -595,7 +644,8 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
 
    for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
       e = 0;
-      hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
+      head = &net->ipv4.fib_table_hash[h];
+      hlist_for_each_entry(tb, node, head, tb_hlist) {
          if (e < s_e)
             goto next;
          if (dumped)
@@ -624,6 +674,7 @@ out:
 
 static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
 {
+   struct net *net = ifa->ifa_dev->dev->nd_net;
    struct fib_table *tb;
    struct fib_config cfg = {
       .fc_protocol = RTPROT_KERNEL,
@@ -633,12 +684,15 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad
       .fc_prefsrc = ifa->ifa_local,
       .fc_oif = ifa->ifa_dev->dev->ifindex,
       .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
+      .fc_nlinfo = {
+         .nl_net = net,
+      },
    };
 
    if (type == RTN_UNICAST)
-      tb = fib_new_table(RT_TABLE_MAIN);
+      tb = fib_new_table(net, RT_TABLE_MAIN);
    else
-      tb = fib_new_table(RT_TABLE_LOCAL);
+      tb = fib_new_table(net, RT_TABLE_LOCAL);
 
    if (tb == NULL)
       return;
@@ -668,7 +722,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
    if (ifa->ifa_flags&IFA_F_SECONDARY) {
       prim = inet_ifa_byprefix(in_dev, prefix, mask);
       if (prim == NULL) {
-         printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n");
+         printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n");
          return;
       }
    }
@@ -682,7 +736,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
    if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
       fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
 
-   if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
+   if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
        (prefix != addr || ifa->ifa_prefixlen < 32)) {
       fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
            RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);
@@ -715,7 +769,7 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
    else {
       prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
       if (prim == NULL) {
-         printk(KERN_DEBUG "fib_del_ifaddr: bug: prim == NULL\n");
+         printk(KERN_WARNING "fib_del_ifaddr: bug: prim == NULL\n");
          return;
       }
    }
@@ -747,15 +801,15 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
       fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
 
       /* Check, that this local address finally disappeared. */
-      if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
+      if (inet_addr_type(dev->nd_net, ifa->ifa_local) != RTN_LOCAL) {
          /* And the last, but not the least thing.
             We must flush stray FIB entries.
 
             First of all, we scan fib_info list searching
             for stray nexthop entries, then ignite fib_flush.
          */
-         if (fib_sync_down(ifa->ifa_local, NULL, 0))
-            fib_flush();
+         if (fib_sync_down_addr(dev->nd_net, ifa->ifa_local))
+            fib_flush(dev->nd_net);
       }
    }
 #undef LOCAL_OK
@@ -797,11 +851,13 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
 
 static void nl_fib_input(struct sk_buff *skb)
 {
+   struct net *net;
    struct fib_result_nl *frn;
    struct nlmsghdr *nlh;
    struct fib_table *tb;
    u32 pid;
 
+   net = skb->sk->sk_net;
    nlh = nlmsg_hdr(skb);
    if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
        nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn)))
@@ -813,26 +869,37 @@ static void nl_fib_input(struct sk_buff *skb)
    nlh = nlmsg_hdr(skb);
 
    frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
-   tb = fib_get_table(frn->tb_id_in);
+   tb = fib_get_table(net, frn->tb_id_in);
 
    nl_fib_lookup(frn, tb);
 
    pid = NETLINK_CB(skb).pid;       /* pid of sending process */
    NETLINK_CB(skb).pid = 0;         /* from kernel */
    NETLINK_CB(skb).dst_group = 0;  /* unicast */
-   netlink_unicast(fibnl, skb, pid, MSG_DONTWAIT);
+   netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT);
 }
 
-static void nl_fib_lookup_init(void)
+static int nl_fib_lookup_init(struct net *net)
 {
-   fibnl = netlink_kernel_create(&init_net, NETLINK_FIB_LOOKUP, 0,
-                  nl_fib_input, NULL, THIS_MODULE);
+   struct sock *sk;
+   sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0,
+               nl_fib_input, NULL, THIS_MODULE);
+   if (sk == NULL)
+      return -EAFNOSUPPORT;
+   net->ipv4.fibnl = sk;
+   return 0;
+}
+
+static void nl_fib_lookup_exit(struct net *net)
+{
+   netlink_kernel_release(net->ipv4.fibnl);
+   net->ipv4.fibnl = NULL;
 }
 
 static void fib_disable_ip(struct net_device *dev, int force)
 {
-   if (fib_sync_down(0, dev, force))
-      fib_flush();
+   if (fib_sync_down_dev(dev, force))
+      fib_flush(dev->nd_net);
    rt_cache_flush(0);
    arp_ifdown(dev);
 }
@@ -869,9 +936,6 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
    struct net_device *dev = ptr;
    struct in_device *in_dev = __in_dev_get_rtnl(dev);
 
-   if (dev->nd_net != &init_net)
-      return NOTIFY_DONE;
-
    if (event == NETDEV_UNREGISTER) {
       fib_disable_ip(dev, 2);
       return NOTIFY_DONE;
@@ -909,23 +973,100 @@ static struct notifier_block fib_netdev_notifier = {
    .notifier_call =fib_netdev_event,
 };
 
-void __init ip_fib_init(void)
+static int __net_init ip_fib_net_init(struct net *net)
 {
+   int err;
    unsigned int i;
 
+   net->ipv4.fib_table_hash = kzalloc(
+         sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL);
+   if (net->ipv4.fib_table_hash == NULL)
+      return -ENOMEM;
+
    for (i = 0; i < FIB_TABLE_HASHSZ; i++)
-      INIT_HLIST_HEAD(&fib_table_hash[i]);
+      INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]);
+
+   err = fib4_rules_init(net);
+   if (err < 0)
+      goto fail;
+   return 0;
 
-   fib4_rules_init();
+fail:
+   kfree(net->ipv4.fib_table_hash);
+   return err;
+}
 
-   register_netdevice_notifier(&fib_netdev_notifier);
-   register_inetaddr_notifier(&fib_inetaddr_notifier);
-   nl_fib_lookup_init();
+static void __net_exit ip_fib_net_exit(struct net *net)
+{
+   unsigned int i;
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+   fib4_rules_exit(net);
+#endif
+
+   for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
+      struct fib_table *tb;
+      struct hlist_head *head;
+      struct hlist_node *node, *tmp;
+
+      head = &net->ipv4.fib_table_hash[i];
+      hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) {
+         hlist_del(node);
+         tb->tb_flush(tb);
+         kfree(tb);
+      }
+   }
+   kfree(net->ipv4.fib_table_hash);
+}
+
+static int __net_init fib_net_init(struct net *net)
+{
+   int error;
+
+   error = ip_fib_net_init(net);
+   if (error < 0)
+      goto out;
+   error = nl_fib_lookup_init(net);
+   if (error < 0)
+      goto out_nlfl;
+   error = fib_proc_init(net);
+   if (error < 0)
+      goto out_proc;
+out:
+   return error;
+
+out_proc:
+   nl_fib_lookup_exit(net);
+out_nlfl:
+   ip_fib_net_exit(net);
+   goto out;
+}
+
+static void __net_exit fib_net_exit(struct net *net)
+{
+   fib_proc_exit(net);
+   nl_fib_lookup_exit(net);
+   ip_fib_net_exit(net);
+}
 
+static struct pernet_operations fib_net_ops = {
+   .init = fib_net_init,
+   .exit = fib_net_exit,
+};
+
+void __init ip_fib_init(void)
+{
    rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
    rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
    rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
+
+   register_pernet_subsys(&fib_net_ops);
+   register_netdevice_notifier(&fib_netdev_notifier);
+   register_inetaddr_notifier(&fib_inetaddr_notifier);
+
+   fib_hash_init();
 }
 
 EXPORT_SYMBOL(inet_addr_type);
+EXPORT_SYMBOL(inet_dev_addr_type);
 EXPORT_SYMBOL(ip_dev_find);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.