Skip to content
Snippets Groups Projects
protocol.c 34 KiB
Newer Older
  • Learn to ignore specific revisions
  • Linus Torvalds's avatar
    Linus Torvalds committed
    					       sizeof(struct sctp_bind_bucket),
    					       0, SLAB_HWCACHE_ALIGN,
    					       NULL, NULL);
    
    	if (!sctp_bucket_cachep)
    		goto err_bucket_cachep;
    
    	sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
    					       sizeof(struct sctp_chunk),
    					       0, SLAB_HWCACHE_ALIGN,
    					       NULL, 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();
    
    	/* Initialize the SCTP specific PF functions. */
    	sctp_register_pf(&sctp_pf_inet, PF_INET);
    	/*
    	 * 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;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* Whether Cookie Preservative is enabled(1) or not(0) */
    	sctp_cookie_preserve_enable 	= 1;
    
    	/* Max.Burst		    - 4 */
    	sctp_max_burst 			= SCTP_MAX_BURST;
    
    	/* 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;
    
    
    	/* Sendbuffer growth	    - do per-socket accounting */
    	sctp_sndbuf_policy		= 0;
    
    
    	/* Rcvbuffer growth	    - do per-socket accounting */
    	sctp_rcvbuf_policy		= 0;
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	/* HB.interval              - 30 seconds */
    
    	sctp_hb_interval		= SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
    
    	/* delayed SACK timeout */
    	sctp_sack_timeout		= SCTP_DEFAULT_TIMEOUT_SACK;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/* Implementation specific variables. */
    
    	/* Initialize default stream count setup information. */
    	sctp_max_instreams    		= SCTP_DEFAULT_INSTREAMS;
    	sctp_max_outstreams   		= SCTP_DEFAULT_OUTSTREAMS;
    
    	/* Initialize handle used for association ids. */
    	idr_init(&sctp_assocs_id);
    
    	/* Size and allocate the association hash table.
    	 * The methodology is similar to that of the tcp hash tables.
    	 */
    	if (num_physpages >= (128 * 1024))
    		goal = num_physpages >> (22 - PAGE_SHIFT);
    	else
    		goal = num_physpages >> (24 - PAGE_SHIFT);
    
    	for (order = 0; (1UL << order) < goal; order++)
    		;
    
    	do {
    		sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE /
    					sizeof(struct sctp_hashbucket);
    		if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0)
    			continue;
    		sctp_assoc_hashtable = (struct sctp_hashbucket *)
    					__get_free_pages(GFP_ATOMIC, order);
    	} while (!sctp_assoc_hashtable && --order > 0);
    	if (!sctp_assoc_hashtable) {
    		printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
    		status = -ENOMEM;
    		goto err_ahash_alloc;
    	}
    	for (i = 0; i < sctp_assoc_hashsize; i++) {
    		rwlock_init(&sctp_assoc_hashtable[i].lock);
    		sctp_assoc_hashtable[i].chain = NULL;
    	}
    
    	/* Allocate and initialize the endpoint hash table.  */
    	sctp_ep_hashsize = 64;
    	sctp_ep_hashtable = (struct sctp_hashbucket *)
    		kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
    	if (!sctp_ep_hashtable) {
    		printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
    		status = -ENOMEM;
    		goto err_ehash_alloc;
    	}
    	for (i = 0; i < sctp_ep_hashsize; i++) {
    		rwlock_init(&sctp_ep_hashtable[i].lock);
    		sctp_ep_hashtable[i].chain = NULL;
    	}
    
    	/* Allocate and initialize the SCTP port hash table.  */
    	do {
    		sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
    					sizeof(struct sctp_bind_hashbucket);
    		if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
    			continue;
    		sctp_port_hashtable = (struct sctp_bind_hashbucket *)
    					__get_free_pages(GFP_ATOMIC, order);
    	} while (!sctp_port_hashtable && --order > 0);
    	if (!sctp_port_hashtable) {
    		printk(KERN_ERR "SCTP: Failed bind hash alloc.");
    		status = -ENOMEM;
    		goto err_bhash_alloc;
    	}
    	for (i = 0; i < sctp_port_hashsize; i++) {
    		spin_lock_init(&sctp_port_hashtable[i].lock);
    		sctp_port_hashtable[i].chain = NULL;
    	}
    
    	spin_lock_init(&sctp_port_alloc_lock);
    	sctp_port_rover = sysctl_local_port_range[0] - 1;
    
    	printk(KERN_INFO "SCTP: Hash tables configured "
    			 "(established %d bind %d)\n",
    		sctp_assoc_hashsize, sctp_port_hashsize);
    
    	/* Disable ADDIP by default. */
    	sctp_addip_enable = 0;
    
    	/* Enable PR-SCTP by default. */
    	sctp_prsctp_enable = 1;
    
    	sctp_sysctl_register();
    
    	INIT_LIST_HEAD(&sctp_address_families);
    	sctp_register_af(&sctp_ipv4_specific);
    
    	status = sctp_v6_init();
    	if (status)
    		goto err_v6_init;
    
    	/* Initialize the control inode/socket for handling OOTB packets.  */
    	if ((status = sctp_ctl_sock_init())) {
    		printk (KERN_ERR
    			"SCTP: Failed to initialize the SCTP control sock.\n");
    		goto err_ctl_sock_init;
    	}
    
    	/* Initialize the local address list. */
    	INIT_LIST_HEAD(&sctp_local_addr_list);
    	spin_lock_init(&sctp_local_addr_lock);
    
    	/* Register notifier for inet address additions/deletions. */
    	register_inetaddr_notifier(&sctp_inetaddr_notifier);
    
    	sctp_get_local_addr_list();
    
    	__unsafe(THIS_MODULE);
    	status = 0;
    out:
    	return status;
    err_ctl_sock_init:
    	sctp_v6_exit();
    err_v6_init:
    	sctp_sysctl_unregister();
    	list_del(&sctp_ipv4_specific.list);
    	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_dbg_objcnt_exit();
    err_init_proc:
    	sctp_proc_exit();
    	cleanup_sctp_mibs();
    err_init_mibs:
    	kmem_cache_destroy(sctp_chunk_cachep);
    err_chunk_cachep:
    	kmem_cache_destroy(sctp_bucket_cachep);
    err_bucket_cachep:
    	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
    	inet_unregister_protosw(&sctp_seqpacket_protosw);
    	inet_unregister_protosw(&sctp_stream_protosw);
    
    err_add_protocol:
    	proto_unregister(&sctp_prot);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	goto out;
    }
    
    /* Exit handler for the SCTP protocol.  */
    SCTP_STATIC __exit void sctp_exit(void)
    {
    	/* BUG.  This should probably do something useful like clean
    	 * up all the remaining associations and all that memory.
    	 */
    
    	/* Unregister notifier for inet address additions/deletions. */
    	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
    
    	/* Free the local address list.  */
    	sctp_free_local_addr_list();
    
    	/* Free the control endpoint.  */
    	sock_release(sctp_ctl_socket);
    
    	sctp_v6_exit();
    	sctp_sysctl_unregister();
    	list_del(&sctp_ipv4_specific.list);
    
    	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)));
    
    	kmem_cache_destroy(sctp_chunk_cachep);
    	kmem_cache_destroy(sctp_bucket_cachep);
    
    	sctp_dbg_objcnt_exit();
    	sctp_proc_exit();
    	cleanup_sctp_mibs();
    
    	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
    	inet_unregister_protosw(&sctp_seqpacket_protosw);
    	inet_unregister_protosw(&sctp_stream_protosw);
    	proto_unregister(&sctp_prot);
    }
    
    module_init(sctp_init);
    module_exit(sctp_exit);
    
    
    /*
     * __stringify doesn't likes enums, so use IPPROTO_SCTP value (132) directly.
     */
    MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
    MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
    MODULE_LICENSE("GPL");