4141#include <net/icmp.h> /* for icmp_send */
4242#include <net/route.h>
4343#include <net/ip6_checksum.h>
44+ #include <net/netns/generic.h> /* net_generic() */
4445
4546#include <linux/netfilter.h>
4647#include <linux/netfilter_ipv4.h>
@@ -68,6 +69,12 @@ EXPORT_SYMBOL(ip_vs_conn_put);
6869EXPORT_SYMBOL (ip_vs_get_debug_level );
6970#endif
7071
72+ int ip_vs_net_id __read_mostly ;
73+ #ifdef IP_VS_GENERIC_NETNS
74+ EXPORT_SYMBOL (ip_vs_net_id );
75+ #endif
76+ /* netns cnt used for uniqueness */
77+ static atomic_t ipvs_netns_cnt = ATOMIC_INIT (0 );
7178
7279/* ID used in ICMP lookups */
7380#define icmp_id (icmph ) (((icmph)->un).echo.id)
@@ -1813,6 +1820,44 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
18131820#endif
18141821};
18151822
1823+ /*
1824+ * Initialize IP Virtual Server netns mem.
1825+ */
1826+ static int __net_init __ip_vs_init (struct net * net )
1827+ {
1828+ struct netns_ipvs * ipvs ;
1829+
1830+ if (!net_eq (net , & init_net )) {
1831+ pr_err ("The final patch for enabling netns is missing\n" );
1832+ return - EPERM ;
1833+ }
1834+ ipvs = net_generic (net , ip_vs_net_id );
1835+ if (ipvs == NULL ) {
1836+ pr_err ("%s(): no memory.\n" , __func__ );
1837+ return - ENOMEM ;
1838+ }
1839+ /* Counters used for creating unique names */
1840+ ipvs -> gen = atomic_read (& ipvs_netns_cnt );
1841+ atomic_inc (& ipvs_netns_cnt );
1842+ net -> ipvs = ipvs ;
1843+ printk (KERN_INFO "IPVS: Creating netns size=%lu id=%d\n" ,
1844+ sizeof (struct netns_ipvs ), ipvs -> gen );
1845+ return 0 ;
1846+ }
1847+
1848+ static void __net_exit __ip_vs_cleanup (struct net * net )
1849+ {
1850+ struct netns_ipvs * ipvs = net_ipvs (net );
1851+
1852+ IP_VS_DBG (10 , "ipvs netns %d released\n" , ipvs -> gen );
1853+ }
1854+
1855+ static struct pernet_operations ipvs_core_ops = {
1856+ .init = __ip_vs_init ,
1857+ .exit = __ip_vs_cleanup ,
1858+ .id = & ip_vs_net_id ,
1859+ .size = sizeof (struct netns_ipvs ),
1860+ };
18161861
18171862/*
18181863 * Initialize IP Virtual Server
@@ -1821,8 +1866,11 @@ static int __init ip_vs_init(void)
18211866{
18221867 int ret ;
18231868
1824- ip_vs_estimator_init ();
1869+ ret = register_pernet_subsys (& ipvs_core_ops ); /* Alloc ip_vs struct */
1870+ if (ret < 0 )
1871+ return ret ;
18251872
1873+ ip_vs_estimator_init ();
18261874 ret = ip_vs_control_init ();
18271875 if (ret < 0 ) {
18281876 pr_err ("can't setup control.\n" );
@@ -1843,15 +1891,23 @@ static int __init ip_vs_init(void)
18431891 goto cleanup_app ;
18441892 }
18451893
1894+ ret = ip_vs_sync_init ();
1895+ if (ret < 0 ) {
1896+ pr_err ("can't setup sync data.\n" );
1897+ goto cleanup_conn ;
1898+ }
1899+
18461900 ret = nf_register_hooks (ip_vs_ops , ARRAY_SIZE (ip_vs_ops ));
18471901 if (ret < 0 ) {
18481902 pr_err ("can't register hooks.\n" );
1849- goto cleanup_conn ;
1903+ goto cleanup_sync ;
18501904 }
18511905
18521906 pr_info ("ipvs loaded.\n" );
18531907 return ret ;
18541908
1909+ cleanup_sync :
1910+ ip_vs_sync_cleanup ();
18551911 cleanup_conn :
18561912 ip_vs_conn_cleanup ();
18571913 cleanup_app :
@@ -1861,17 +1917,20 @@ static int __init ip_vs_init(void)
18611917 ip_vs_control_cleanup ();
18621918 cleanup_estimator :
18631919 ip_vs_estimator_cleanup ();
1920+ unregister_pernet_subsys (& ipvs_core_ops ); /* free ip_vs struct */
18641921 return ret ;
18651922}
18661923
18671924static void __exit ip_vs_cleanup (void )
18681925{
18691926 nf_unregister_hooks (ip_vs_ops , ARRAY_SIZE (ip_vs_ops ));
1927+ ip_vs_sync_cleanup ();
18701928 ip_vs_conn_cleanup ();
18711929 ip_vs_app_cleanup ();
18721930 ip_vs_protocol_cleanup ();
18731931 ip_vs_control_cleanup ();
18741932 ip_vs_estimator_cleanup ();
1933+ unregister_pernet_subsys (& ipvs_core_ops ); /* free ip_vs struct */
18751934 pr_info ("ipvs unloaded.\n" );
18761935}
18771936
0 commit comments