Introduce data structures and break up module initialization and exit into subroutines with common functionality for namespace registration. Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx> --- include/net/sctp/structs.h | 150 ++++++++++++++++++++ net/sctp/protocol.c | 332 +++++++++++++++++++++++++++----------------- 2 files changed, 353 insertions(+), 129 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index fc5e600..bc65718 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -77,6 +77,8 @@ union sctp_addr { /* Forward declarations for data structures. */ struct sctp_globals; +struct sctp_ns_globals; +struct sctp_net_params; struct sctp_endpoint; struct sctp_association; struct sctp_transport; @@ -293,6 +295,135 @@ extern struct sctp_globals { #define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift) #define sctp_max_autoclose (sctp_globals.max_autoclose) +struct sctp_net_params { + /* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values + * + * The following protocol parameters are RECOMMENDED: + * + * RTO.Initial - 3 seconds + * RTO.Min - 1 second + * RTO.Max - 60 seconds + * RTO.Alpha - 1/8 (3 when converted to right shifts.) + * RTO.Beta - 1/4 (2 when converted to right shifts.) + */ + unsigned int rto_initial; + unsigned int rto_min; + unsigned int rto_max; + + /* Note: rto_alpha and rto_beta are really defined as inverse + * powers of two to facilitate integer operations. + */ + int rto_alpha; + int rto_beta; + + /* Max.Burst - 4 */ + int max_burst; + + /* Whether Cookie Preservative is enabled(1) or not(0) */ + int cookie_preserve_enable; + + /* Valid.Cookie.Life - 60 seconds */ + unsigned int valid_cookie_life; + + /* Delayed SACK timeout 200ms default*/ + unsigned int sack_timeout; + + /* HB.interval - 30 seconds */ + unsigned int hb_interval; + + /* Association.Max.Retrans - 10 attempts + * Path.Max.Retrans - 5 attempts (per destination address) + * Max.Init.Retransmits - 8 attempts + */ + int max_retrans_association; + int max_retrans_path; + int max_retrans_init; + + /* Potentially-Failed.Max.Retrans sysctl value + * taken from: + * http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05 + */ + int pf_retrans; + + /* + * Policy for preforming sctp/socket accounting + * 0 - do socket level accounting, all assocs share sk_sndbuf + * 1 - do sctp accounting, each asoc may use sk_sndbuf bytes + */ + int sndbuf_policy; + + /* + * Policy for preforming sctp/socket accounting + * 0 - do socket level accounting, all assocs share sk_rcvbuf + * 1 - do sctp accounting, each asoc may use sk_rcvbuf bytes + */ + int rcvbuf_policy; + + /* The following variables are implementation specific. */ + + /* Default initialization values to be applied to new associations. */ + __u16 max_instreams; + __u16 max_outstreams; + + + /* This is the hash of all endpoints. */ + int ep_hashsize; + struct sctp_hashbucket *ep_hashtable; + + /* This is the hash of all associations. */ + int assoc_hashsize; + struct sctp_hashbucket *assoc_hashtable; + + /* This is the sctp port control hash. */ + int port_hashsize; + struct sctp_bind_hashbucket *port_hashtable; + + /* This is the global local address list. + * We actively maintain this complete list of addresses on + * the system by catching address add/delete events. + * + * It is a list of sctp_sockaddr_entry. + */ + struct list_head local_addr_list; + + /* Lock that protects the local_addr_list writers */ + spinlock_t addr_list_lock; + + /* Address Event Parameters */ + int default_auto_asconf; + struct list_head addr_waitq; + struct timer_list addr_wq_timer; + struct list_head auto_asconf_splist; + spinlock_t addr_wq_lock; + + /* Flag to indicate if addip is enabled. */ + int addip_enable; + int addip_noauth_enable; + + /* Flag to indicate if PR-SCTP is enabled. */ + int prsctp_enable; + + /* Flag to idicate if SCTP-AUTH is enabled */ + int auth_enable; + + /* + * Policy to control SCTP IPv4 address scoping + * 0 - Disable IPv4 address scoping + * 1 - Enable IPv4 address scoping + * 2 - Selectively allow only IPv4 private addresses + * 3 - Selectively allow only IPv4 link local address + */ + int ipv4_scope_policy; + + /* Threshold for rwnd update SACKS. Receive buffer shifted this many + * bits is an indicator of when to send and window update SACK. + */ + int rwnd_update_shift; + + /* Threshold for autoclose timeout, in seconds. */ + unsigned long max_autoclose; +}; + /* SCTP Socket type: UDP or TCP style. */ typedef enum { SCTP_SOCKET_UDP = 0, @@ -2056,4 +2187,23 @@ typedef struct { atomic_t *counter; } sctp_dbg_objcnt_entry_t; + +/* Structure for keeping track of namespace globals */ +struct sctp_ns_globals { + struct sock *sctp_ctl_sock; + struct sctp_net_params protocol_params; + struct idr assocs_id; + spinlock_t assocs_id_lock; +#ifdef CONFIG_SYSCTL + struct ctl_table_header *sctp_sysctl_tbl; +#endif +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *sctp_proc_dir; + struct proc_dir_entry *sctp_proc_snmp; + struct proc_dir_entry *sctp_proc_assocs; + struct proc_dir_entry *sctp_proc_eps; + struct proc_dir_entry *sctp_proc_remaddr; +#endif +}; + #endif /* __sctp_structs_h__ */ diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1f89c4e..cafdaac 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -105,13 +105,11 @@ struct sock *sctp_get_ctl_sock(void) /* Set up the proc fs entry for the SCTP protocol. */ static __init int sctp_proc_init(void) { - if (percpu_counter_init(&sctp_sockets_allocated, 0)) - goto out_nomem; #ifdef CONFIG_PROC_FS if (!proc_net_sctp) { proc_net_sctp = proc_mkdir("sctp", init_net.proc_net); if (!proc_net_sctp) - goto out_free_percpu; + goto out_nomem; } if (sctp_snmp_proc_init()) @@ -136,14 +134,12 @@ out_snmp_proc_init: proc_net_sctp = NULL; remove_proc_entry("sctp", init_net.proc_net); } -out_free_percpu: - percpu_counter_destroy(&sctp_sockets_allocated); -#else - return 0; -#endif /* CONFIG_PROC_FS */ out_nomem: return -ENOMEM; +#else + return 0; +#endif /* CONFIG_PROC_FS */ } /* Clean up the proc fs entry for the SCTP protocol. @@ -163,7 +159,6 @@ static void sctp_proc_exit(void) remove_proc_entry("sctp", init_net.proc_net); } #endif - percpu_counter_destroy(&sctp_sockets_allocated); } /* Private helper to extract ipv4 address and stash them in @@ -1194,105 +1189,91 @@ static void sctp_v4_del_protocol(void) unregister_inetaddr_notifier(&sctp_inetaddr_notifier); } -/* Initialize the universe into something sensible. */ -SCTP_STATIC __init int sctp_init(void) +static void sctp_global_param_init(void) { - int i; - int status = -EINVAL; - unsigned long goal; - unsigned long limit; - int max_share; - int order; - - /* SCTP_DEBUG sanity check. */ - if (!sctp_sanity_check()) - goto out; - - /* Allocate bind_bucket and chunk caches. */ - status = -ENOBUFS; - sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", - sizeof(struct sctp_bind_bucket), - 0, SLAB_HWCACHE_ALIGN, - NULL); - if (!sctp_bucket_cachep) - goto out; - - sctp_chunk_cachep = kmem_cache_create("sctp_chunk", - sizeof(struct sctp_chunk), - 0, SLAB_HWCACHE_ALIGN, - NULL); - if (!sctp_chunk_cachep) - goto err_chunk_cachep; - - /* Allocate and initialise sctp mibs. */ - status = init_sctp_mibs(); - if (status) - goto err_init_mibs; - - /* Initialize proc fs directory. */ - status = sctp_proc_init(); - if (status) - goto err_init_proc; - - /* Initialize object count debugging. */ - sctp_dbg_objcnt_init(); - /* * 14. Suggested SCTP Protocol Parameter Values */ /* The following protocol parameters are RECOMMENDED: */ - /* RTO.Initial - 3 seconds */ - sctp_rto_initial = SCTP_RTO_INITIAL; - /* RTO.Min - 1 second */ - sctp_rto_min = SCTP_RTO_MIN; - /* RTO.Max - 60 seconds */ - sctp_rto_max = SCTP_RTO_MAX; - /* RTO.Alpha - 1/8 */ - sctp_rto_alpha = SCTP_RTO_ALPHA; - /* RTO.Beta - 1/4 */ - sctp_rto_beta = SCTP_RTO_BETA; - - /* Valid.Cookie.Life - 60 seconds */ - sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; + /* RTO.Initial - 3 seconds */ + sctp_rto_initial = SCTP_RTO_INITIAL; + /* RTO.Min - 1 second */ + sctp_rto_min = SCTP_RTO_MIN; + /* RTO.Max - 60 seconds */ + sctp_rto_max = SCTP_RTO_MAX; + /* RTO.Alpha - 1/8 */ + sctp_rto_alpha = SCTP_RTO_ALPHA; + /* RTO.Beta - 1/4 */ + sctp_rto_beta = SCTP_RTO_BETA; + + /* Valid.Cookie.Life - 60 seconds */ + sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; /* Whether Cookie Preservative is enabled(1) or not(0) */ - sctp_cookie_preserve_enable = 1; + sctp_cookie_preserve_enable = 1; - /* Max.Burst - 4 */ - sctp_max_burst = SCTP_DEFAULT_MAX_BURST; + /* Max.Burst - 4 */ + sctp_max_burst = SCTP_DEFAULT_MAX_BURST; - /* Association.Max.Retrans - 10 attempts - * Path.Max.Retrans - 5 attempts (per destination address) - * Max.Init.Retransmits - 8 attempts + /* Association.Max.Retrans - 10 attempts + * Path.Max.Retrans - 5 attempts (per destination address) + * Max.Init.Retransmits - 8 attempts */ - sctp_max_retrans_association = 10; - sctp_max_retrans_path = 5; - sctp_max_retrans_init = 8; + sctp_max_retrans_association = 10; + sctp_max_retrans_path = 5; + sctp_max_retrans_init = 8; - /* Sendbuffer growth - do per-socket accounting */ - sctp_sndbuf_policy = 0; + /* Sendbuffer growth - do per-socket accounting */ + sctp_sndbuf_policy = 0; - /* Rcvbuffer growth - do per-socket accounting */ - sctp_rcvbuf_policy = 0; + /* Rcvbuffer growth - do per-socket accounting */ + sctp_rcvbuf_policy = 0; - /* HB.interval - 30 seconds */ + /* HB.interval - 30 seconds */ sctp_hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; /* delayed SACK timeout */ - sctp_sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; + sctp_sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; /* Implementation specific variables. */ /* Initialize default stream count setup information. */ - sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; - sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; + sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; + sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; /* Initialize maximum autoclose timeout. */ - sctp_max_autoclose = INT_MAX / HZ; + sctp_max_autoclose = INT_MAX / HZ; + + /* Disable ADDIP by default. */ + sctp_addip_enable = 0; + sctp_addip_noauth = 0; + sctp_default_auto_asconf = 0; - /* Initialize handle used for association ids. */ - idr_init(&sctp_assocs_id); + /* Enable PR-SCTP by default. */ + sctp_prsctp_enable = 1; + + /* Disable AUTH by default. */ + sctp_auth_enable = 0; + /* Set SCOPE policy to enabled */ + sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE; + + /* Set the default rwnd update threshold */ + sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; + return; +} + +static void sctp_memory_globals_init(void) +{ + unsigned long limit; + int max_share; + + /* Set the pressure threshold to be a fraction of global memory that + * is up to 1/2 at 256 MB, decreasing toward zero with the amount of + * memory, with a floor of 128 pages. + * Note this initializes the data in sctpv6_prot too + * Unabashedly stolen from tcp_init + */ limit = nr_free_buffer_pages() / 8; limit = max(limit, 128UL); sysctl_sctp_mem[0] = limit / 4 * 3; @@ -1310,6 +1291,14 @@ SCTP_STATIC __init int sctp_init(void) sysctl_sctp_wmem[0] = SK_MEM_QUANTUM; sysctl_sctp_wmem[1] = 16*1024; sysctl_sctp_wmem[2] = max(64*1024, max_share); +} + +static int sctp_hashtable_globals_init(void) +{ + unsigned long goal; + int status = -ENOMEM; + int order; + int i; /* Size and allocate the association hash table. * The methodology is similar to that of the tcp hash tables. @@ -1325,11 +1314,13 @@ SCTP_STATIC __init int sctp_init(void) do { sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE / sizeof(struct sctp_hashbucket); - if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0) - continue; + if ((sctp_assoc_hashsize > (64 * 1024)) && (order > 0)) + continue; sctp_assoc_hashtable = (struct sctp_hashbucket *) - __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order); - } while (!sctp_assoc_hashtable && --order > 0); + __get_free_pages(GFP_ATOMIC|__GFP_NOWARN|__GFP_ZERO, + order); + } while (!sctp_assoc_hashtable && (--order > 0)); + if (!sctp_assoc_hashtable) { pr_err("Failed association hash alloc\n"); status = -ENOMEM; @@ -1358,11 +1349,12 @@ SCTP_STATIC __init int sctp_init(void) do { sctp_port_hashsize = (1UL << order) * PAGE_SIZE / sizeof(struct sctp_bind_hashbucket); - if ((sctp_port_hashsize > (64 * 1024)) && order > 0) + if ((sctp_port_hashsize > (64 * 1024)) && (order > 0)) continue; sctp_port_hashtable = (struct sctp_bind_hashbucket *) __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order); - } while (!sctp_port_hashtable && --order > 0); + } while (!sctp_port_hashtable && (--order > 0)); + if (!sctp_port_hashtable) { pr_err("Failed bind hash alloc\n"); status = -ENOMEM; @@ -1376,25 +1368,111 @@ SCTP_STATIC __init int sctp_init(void) pr_info("Hash tables configured (established %d bind %d)\n", sctp_assoc_hashsize, sctp_port_hashsize); - /* Disable ADDIP by default. */ - sctp_addip_enable = 0; - sctp_addip_noauth = 0; - sctp_default_auto_asconf = 0; + goto out; - /* Enable PR-SCTP by default. */ - sctp_prsctp_enable = 1; - /* Disable AUTH by default. */ - sctp_auth_enable = 0; +err_bhash_alloc: + kfree(sctp_ep_hashtable); +err_ehash_alloc: + free_pages((unsigned long)sctp_assoc_hashtable, + get_order(sctp_assoc_hashsize * + sizeof(struct sctp_hashbucket))); +err_ahash_alloc: + sctp_proc_exit(); +out: + return status; +} - /* Set SCOPE policy to enabled */ - sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE; +static void sctp_hashtable_globals_free(void) +{ + free_pages((unsigned long)sctp_assoc_hashtable, + get_order(sctp_assoc_hashsize * + sizeof(struct sctp_hashbucket))); - /* Set the default rwnd update threshold */ - sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; + kfree(sctp_ep_hashtable); + + free_pages((unsigned long)sctp_port_hashtable, + get_order(sctp_port_hashsize * + sizeof(struct sctp_bind_hashbucket))); +} + +static int sctp_kmem_cache_create(void) +{ + /* Allocate bind_bucket and chunk caches. */ + sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", + sizeof(struct sctp_bind_bucket), + 0, SLAB_HWCACHE_ALIGN, + NULL); + + if (!sctp_bucket_cachep) { + pr_err("failed to allocate bucket cache\n"); + goto err_bucket_cachep; + } + sctp_chunk_cachep = kmem_cache_create("sctp_chunk", + sizeof(struct sctp_chunk), + 0, SLAB_HWCACHE_ALIGN, + NULL); + if (!sctp_chunk_cachep) { + pr_err("failed to allocate chunk cache\n"); + goto err_chunk_cachep; + } + + return 0; + +err_chunk_cachep: + kmem_cache_destroy(sctp_bucket_cachep); +err_bucket_cachep: + return -ENOBUFS; +} + +static void sctp_kmem_cache_destroy(void) +{ + /* deallocate bind_bucket and chunk caches. */ + kmem_cache_destroy(sctp_chunk_cachep); + kmem_cache_destroy(sctp_bucket_cachep); +} + +/* Initialize the universe into something sensible. */ +SCTP_STATIC __init int sctp_init(void) +{ + int status = -EINVAL; + + /* SCTP_DEBUG sanity check. */ + if (!sctp_sanity_check()) + goto out; + + /* Allocate bind_bucket and chunk caches. */ + status = sctp_kmem_cache_create(); + if (status) + return status; + + /* Initialize sockets counter */ + if (percpu_counter_init(&sctp_sockets_allocated, 0)) { + status = -ENOMEM; + goto err_percpu_counter_init; + } + + /* Allocate and initialise sctp mibs. */ + status = init_sctp_mibs(); + if (status) + goto err_init_mibs; + + /* Initialize proc fs directory. */ + status = sctp_proc_init(); + if (status) + goto err_init_proc; + + /* Initialize object count debugging. */ + sctp_dbg_objcnt_init(); + + /* Initialize global parameters */ + sctp_global_param_init(); + sctp_memory_globals_init(); + sctp_hashtable_globals_init(); sctp_sysctl_register(); + /* Register the routines for different a-f handling */ INIT_LIST_HEAD(&sctp_address_families); sctp_v4_pf_init(); sctp_v6_pf_init(); @@ -1411,8 +1489,8 @@ SCTP_STATIC __init int sctp_init(void) sctp_addr_wq_timer.expires = 0; setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0); + /* Register SCTP protocol */ status = sctp_v4_protosw_init(); - if (status) goto err_protosw_init; @@ -1435,9 +1513,20 @@ SCTP_STATIC __init int sctp_init(void) if (status) goto err_v6_add_protocol; + /* Set up sysctl parameters. */ + sctp_sysctl_register(); + + /* Allocate and initialise sctp mibs. */ + status = init_sctp_mibs(); + if (status) + goto err_mib_init; + status = 0; -out: - return status; + goto out; + +err_mib_init: + sctp_sysctl_unregister(); + sctp_v6_del_protocol(); err_v6_add_protocol: sctp_v4_del_protocol(); err_add_protocol: @@ -1451,25 +1540,17 @@ err_protosw_init: sctp_v4_pf_exit(); sctp_v6_pf_exit(); sctp_sysctl_unregister(); - free_pages((unsigned long)sctp_port_hashtable, - get_order(sctp_port_hashsize * - sizeof(struct sctp_bind_hashbucket))); -err_bhash_alloc: - kfree(sctp_ep_hashtable); -err_ehash_alloc: - free_pages((unsigned long)sctp_assoc_hashtable, - get_order(sctp_assoc_hashsize * - sizeof(struct sctp_hashbucket))); -err_ahash_alloc: + sctp_hashtable_globals_free(); sctp_dbg_objcnt_exit(); sctp_proc_exit(); err_init_proc: cleanup_sctp_mibs(); err_init_mibs: - kmem_cache_destroy(sctp_chunk_cachep); -err_chunk_cachep: - kmem_cache_destroy(sctp_bucket_cachep); - goto out; + percpu_counter_destroy(&sctp_sockets_allocated); +err_percpu_counter_init: + sctp_kmem_cache_destroy(); +out: + return status; } /* Exit handler for the SCTP protocol. */ @@ -1500,22 +1581,15 @@ SCTP_STATIC __exit void sctp_exit(void) sctp_sysctl_unregister(); - free_pages((unsigned long)sctp_assoc_hashtable, - get_order(sctp_assoc_hashsize * - sizeof(struct sctp_hashbucket))); - kfree(sctp_ep_hashtable); - free_pages((unsigned long)sctp_port_hashtable, - get_order(sctp_port_hashsize * - sizeof(struct sctp_bind_hashbucket))); + sctp_hashtable_globals_free(); sctp_dbg_objcnt_exit(); sctp_proc_exit(); + percpu_counter_destroy(&sctp_sockets_allocated); cleanup_sctp_mibs(); rcu_barrier(); /* Wait for completion of call_rcu()'s */ - - kmem_cache_destroy(sctp_chunk_cachep); - kmem_cache_destroy(sctp_bucket_cachep); + sctp_kmem_cache_destroy(); } module_init(sctp_init); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html