From 4db67e808640e3934d82ce61ee8e2e89fd877ba8 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 6 Aug 2012 08:42:04 +0000 Subject: sctp: Make the address lists per network namespace - Move the address lists into struct net - Add per network namespace initialization and cleanup - Pass around struct net so it is everywhere I need it. - Rename all of the global variable references into references to the variables moved into struct net Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 143 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 61 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1f89c4e69645..7025d96bae5f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -201,29 +201,29 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, /* Extract our IP addresses from the system and stash them in the * protocol structure. */ -static void sctp_get_local_addr_list(void) +static void sctp_get_local_addr_list(struct net *net) { struct net_device *dev; struct list_head *pos; struct sctp_af *af; rcu_read_lock(); - for_each_netdev_rcu(&init_net, dev) { + for_each_netdev_rcu(net, dev) { __list_for_each(pos, &sctp_address_families) { af = list_entry(pos, struct sctp_af, list); - af->copy_addrlist(&sctp_local_addr_list, dev); + af->copy_addrlist(&net->sctp.local_addr_list, dev); } } rcu_read_unlock(); } /* Free the existing local addresses. */ -static void sctp_free_local_addr_list(void) +static void sctp_free_local_addr_list(struct net *net) { struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; - list_for_each_safe(pos, temp, &sctp_local_addr_list) { + list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); list_del(pos); kfree(addr); @@ -231,14 +231,14 @@ static void sctp_free_local_addr_list(void) } /* Copy the local addresses which are valid for 'scope' into 'bp'. */ -int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, - gfp_t gfp, int copy_flags) +int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, + sctp_scope_t scope, gfp_t gfp, int copy_flags) { struct sctp_sockaddr_entry *addr; int error = 0; rcu_read_lock(); - list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { + list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { if (!addr->valid) continue; if (sctp_in_scope(&addr->a, scope)) { @@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk) void sctp_addr_wq_timeout_handler(unsigned long arg) { + struct net *net = (struct net *)arg; struct sctp_sockaddr_entry *addrw, *temp; struct sctp_sock *sp; - spin_lock_bh(&sctp_addr_wq_lock); + spin_lock_bh(&net->sctp.addr_wq_lock); - list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { + list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", - " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state, + " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state, addrw); #if IS_ENABLED(CONFIG_IPV6) @@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) goto free_next; in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; - if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 && + if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && addrw->state == SCTP_ADDR_NEW) { unsigned long timeo_val; @@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) SCTP_ADDRESS_TICK_DELAY); timeo_val = jiffies; timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); - mod_timer(&sctp_addr_wq_timer, timeo_val); + mod_timer(&net->sctp.addr_wq_timer, timeo_val); break; } } #endif - list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) { + list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) { struct sock *sk; sk = sctp_opt2sk(sp); @@ -679,31 +680,32 @@ free_next: list_del(&addrw->list); kfree(addrw); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); } -static void sctp_free_addr_wq(void) +static void sctp_free_addr_wq(struct net *net) { struct sctp_sockaddr_entry *addrw; struct sctp_sockaddr_entry *temp; - spin_lock_bh(&sctp_addr_wq_lock); - del_timer(&sctp_addr_wq_timer); - list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { + spin_lock_bh(&net->sctp.addr_wq_lock); + del_timer(&net->sctp.addr_wq_timer); + list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { list_del(&addrw->list); kfree(addrw); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); } /* lookup the entry for the same address in the addr_waitq * sctp_addr_wq MUST be locked */ -static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr) +static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net, + struct sctp_sockaddr_entry *addr) { struct sctp_sockaddr_entry *addrw; - list_for_each_entry(addrw, &sctp_addr_waitq, list) { + list_for_each_entry(addrw, &net->sctp.addr_waitq, list) { if (addrw->a.sa.sa_family != addr->a.sa.sa_family) continue; if (addrw->a.sa.sa_family == AF_INET) { @@ -719,7 +721,7 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr return NULL; } -void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) +void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd) { struct sctp_sockaddr_entry *addrw; unsigned long timeo_val; @@ -730,38 +732,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) * new address after a couple of addition and deletion of that address */ - spin_lock_bh(&sctp_addr_wq_lock); + spin_lock_bh(&net->sctp.addr_wq_lock); /* Offsets existing events in addr_wq */ - addrw = sctp_addr_wq_lookup(addr); + addrw = sctp_addr_wq_lookup(net, addr); if (addrw) { if (addrw->state != cmd) { SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", " in wq %p\n", addrw->state, &addrw->a, - &sctp_addr_waitq); + &net->sctp.addr_waitq); list_del(&addrw->list); kfree(addrw); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); return; } /* OK, we have to add the new address to the wait queue */ addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); if (addrw == NULL) { - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); return; } addrw->state = cmd; - list_add_tail(&addrw->list, &sctp_addr_waitq); + list_add_tail(&addrw->list, &net->sctp.addr_waitq); SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", - " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq); + " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq); - if (!timer_pending(&sctp_addr_wq_timer)) { + if (!timer_pending(&net->sctp.addr_wq_timer)) { timeo_val = jiffies; timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); - mod_timer(&sctp_addr_wq_timer, timeo_val); + mod_timer(&net->sctp.addr_wq_timer, timeo_val); } - spin_unlock_bh(&sctp_addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); } /* Event handler for inet address addition/deletion events. @@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; struct sctp_sockaddr_entry *addr = NULL; struct sctp_sockaddr_entry *temp; + struct net *net = dev_net(ifa->ifa_dev->dev); int found = 0; - if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net)) - return NOTIFY_DONE; - switch (ev) { case NETDEV_UP: addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); @@ -789,27 +789,27 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, addr->a.v4.sin_port = 0; addr->a.v4.sin_addr.s_addr = ifa->ifa_local; addr->valid = 1; - spin_lock_bh(&sctp_local_addr_lock); - list_add_tail_rcu(&addr->list, &sctp_local_addr_list); - sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); - spin_unlock_bh(&sctp_local_addr_lock); + spin_lock_bh(&net->sctp.local_addr_lock); + list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); + spin_unlock_bh(&net->sctp.local_addr_lock); } break; case NETDEV_DOWN: - spin_lock_bh(&sctp_local_addr_lock); + spin_lock_bh(&net->sctp.local_addr_lock); list_for_each_entry_safe(addr, temp, - &sctp_local_addr_list, list) { + &net->sctp.local_addr_list, list) { if (addr->a.sa.sa_family == AF_INET && addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { - sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); + sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); found = 1; addr->valid = 0; list_del_rcu(&addr->list); break; } } - spin_unlock_bh(&sctp_local_addr_lock); + spin_unlock_bh(&net->sctp.local_addr_lock); if (found) kfree_rcu(addr, rcu); break; @@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void) unregister_inetaddr_notifier(&sctp_inetaddr_notifier); } +static int sctp_net_init(struct net *net) +{ + /* Initialize the local address list. */ + INIT_LIST_HEAD(&net->sctp.local_addr_list); + spin_lock_init(&net->sctp.local_addr_lock); + sctp_get_local_addr_list(net); + + /* Initialize the address event list */ + INIT_LIST_HEAD(&net->sctp.addr_waitq); + INIT_LIST_HEAD(&net->sctp.auto_asconf_splist); + spin_lock_init(&net->sctp.addr_wq_lock); + net->sctp.addr_wq_timer.expires = 0; + setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler, + (unsigned long)net); + + return 0; +} + +static void sctp_net_exit(struct net *net) +{ + /* Free the local address list */ + sctp_free_addr_wq(net); + sctp_free_local_addr_list(net); +} + +static struct pernet_operations sctp_net_ops = { + .init = sctp_net_init, + .exit = sctp_net_exit, +}; + /* Initialize the universe into something sensible. */ SCTP_STATIC __init int sctp_init(void) { @@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void) sctp_v4_pf_init(); sctp_v6_pf_init(); - /* Initialize the local address list. */ - INIT_LIST_HEAD(&sctp_local_addr_list); - spin_lock_init(&sctp_local_addr_lock); - sctp_get_local_addr_list(); - - /* Initialize the address event list */ - INIT_LIST_HEAD(&sctp_addr_waitq); - INIT_LIST_HEAD(&sctp_auto_asconf_splist); - spin_lock_init(&sctp_addr_wq_lock); - sctp_addr_wq_timer.expires = 0; - setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0); - status = sctp_v4_protosw_init(); if (status) @@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void) goto err_ctl_sock_init; } + status = register_pernet_subsys(&sctp_net_ops); + if (status) + goto err_register_pernet_subsys; + status = sctp_v4_add_protocol(); if (status) goto err_add_protocol; @@ -1441,13 +1463,14 @@ out: err_v6_add_protocol: sctp_v4_del_protocol(); err_add_protocol: + unregister_pernet_subsys(&sctp_net_ops); +err_register_pernet_subsys: inet_ctl_sock_destroy(sctp_ctl_sock); err_ctl_sock_init: sctp_v6_protosw_exit(); err_v6_protosw_init: sctp_v4_protosw_exit(); err_protosw_init: - sctp_free_local_addr_list(); sctp_v4_pf_exit(); sctp_v6_pf_exit(); sctp_sysctl_unregister(); @@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void) /* Unregister with inet6/inet layers. */ sctp_v6_del_protocol(); sctp_v4_del_protocol(); - sctp_free_addr_wq(); /* Free the control endpoint. */ inet_ctl_sock_destroy(sctp_ctl_sock); + unregister_pernet_subsys(&sctp_net_ops); + /* Free protosw registrations */ sctp_v6_protosw_exit(); sctp_v4_protosw_exit(); - /* Free the local address list. */ - sctp_free_local_addr_list(); - /* Unregister with socket layer. */ sctp_v6_pf_exit(); sctp_v4_pf_exit(); -- cgit v1.2.3 From 2ce955035081112cf1590c961da8d94324142b5e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 6 Aug 2012 08:43:06 +0000 Subject: sctp: Make the ctl_sock per network namespace - Kill sctp_get_ctl_sock, it is useless now. - Pass struct net where needed so net->sctp.ctl_sock is accessible. Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 7025d96bae5f..f20bd708e89c 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -78,12 +78,6 @@ struct proc_dir_entry *proc_net_sctp; struct idr sctp_assocs_id; DEFINE_SPINLOCK(sctp_assocs_id_lock); -/* This is the global socket data structure used for responding to - * the Out-of-the-blue (OOTB) packets. A control sock will be created - * for this socket at the initialization time. - */ -static struct sock *sctp_ctl_sock; - static struct sctp_pf *sctp_pf_inet6_specific; static struct sctp_pf *sctp_pf_inet_specific; static struct sctp_af *sctp_af_v4_specific; @@ -96,12 +90,6 @@ long sysctl_sctp_mem[3]; int sysctl_sctp_rmem[3]; int sysctl_sctp_wmem[3]; -/* Return the address of the control sock. */ -struct sock *sctp_get_ctl_sock(void) -{ - return sctp_ctl_sock; -} - /* Set up the proc fs entry for the SCTP protocol. */ static __init int sctp_proc_init(void) { @@ -822,7 +810,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, * Initialize the control inode/socket with a control endpoint data * structure. This endpoint is reserved exclusively for the OOTB processing. */ -static int sctp_ctl_sock_init(void) +static int sctp_ctl_sock_init(struct net *net) { int err; sa_family_t family = PF_INET; @@ -830,14 +818,14 @@ static int sctp_ctl_sock_init(void) if (sctp_get_pf_specific(PF_INET6)) family = PF_INET6; - err = inet_ctl_sock_create(&sctp_ctl_sock, family, - SOCK_SEQPACKET, IPPROTO_SCTP, &init_net); + err = inet_ctl_sock_create(&net->sctp.ctl_sock, family, + SOCK_SEQPACKET, IPPROTO_SCTP, net); /* If IPv6 socket could not be created, try the IPv4 socket */ if (err < 0 && family == PF_INET6) - err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET, + err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, - &init_net); + net); if (err < 0) { pr_err("Failed to create the SCTP control socket\n"); @@ -1196,6 +1184,14 @@ static void sctp_v4_del_protocol(void) static int sctp_net_init(struct net *net) { + int status; + + /* Initialize the control inode/socket for handling OOTB packets. */ + if ((status = sctp_ctl_sock_init(net))) { + pr_err("Failed to initialize the SCTP control sock\n"); + goto err_ctl_sock_init; + } + /* Initialize the local address list. */ INIT_LIST_HEAD(&net->sctp.local_addr_list); spin_lock_init(&net->sctp.local_addr_lock); @@ -1210,6 +1206,9 @@ static int sctp_net_init(struct net *net) (unsigned long)net); return 0; + +err_ctl_sock_init: + return status; } static void sctp_net_exit(struct net *net) @@ -1217,6 +1216,9 @@ static void sctp_net_exit(struct net *net) /* Free the local address list */ sctp_free_addr_wq(net); sctp_free_local_addr_list(net); + + /* Free the control endpoint. */ + inet_ctl_sock_destroy(net->sctp.ctl_sock); } static struct pernet_operations sctp_net_ops = { @@ -1438,12 +1440,6 @@ SCTP_STATIC __init int sctp_init(void) if (status) goto err_v6_protosw_init; - /* Initialize the control inode/socket for handling OOTB packets. */ - if ((status = sctp_ctl_sock_init())) { - pr_err("Failed to initialize the SCTP control sock\n"); - goto err_ctl_sock_init; - } - status = register_pernet_subsys(&sctp_net_ops); if (status) goto err_register_pernet_subsys; @@ -1465,8 +1461,6 @@ err_v6_add_protocol: err_add_protocol: unregister_pernet_subsys(&sctp_net_ops); err_register_pernet_subsys: - inet_ctl_sock_destroy(sctp_ctl_sock); -err_ctl_sock_init: sctp_v6_protosw_exit(); err_v6_protosw_init: sctp_v4_protosw_exit(); @@ -1506,9 +1500,6 @@ SCTP_STATIC __exit void sctp_exit(void) sctp_v6_del_protocol(); sctp_v4_del_protocol(); - /* Free the control endpoint. */ - inet_ctl_sock_destroy(sctp_ctl_sock); - unregister_pernet_subsys(&sctp_net_ops); /* Free protosw registrations */ -- cgit v1.2.3 From 632c928a6a77fe96cda34a9978e1f6019ffc38f4 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 6 Aug 2012 08:44:24 +0000 Subject: sctp: Move the percpu sockets counter out of sctp_proc_init The percpu sctp socket counter has nothing at all to do with the sctp proc files, and having it in the wrong initialization is confusing, and makes network namespace support a pain. Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index f20bd708e89c..48a5989c98ce 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -93,8 +93,6 @@ int sysctl_sctp_wmem[3]; /* 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); @@ -125,12 +123,9 @@ out_snmp_proc_init: 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; } @@ -151,7 +146,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 @@ -1261,6 +1255,10 @@ SCTP_STATIC __init int sctp_init(void) if (status) goto err_init_mibs; + status = percpu_counter_init(&sctp_sockets_allocated, 0); + if (status) + goto err_percpu_counter_init; + /* Initialize proc fs directory. */ status = sctp_proc_init(); if (status) @@ -1481,6 +1479,8 @@ err_ahash_alloc: sctp_dbg_objcnt_exit(); sctp_proc_exit(); err_init_proc: + percpu_counter_destroy(&sctp_sockets_allocated); +err_percpu_counter_init: cleanup_sctp_mibs(); err_init_mibs: kmem_cache_destroy(sctp_chunk_cachep); @@ -1521,6 +1521,7 @@ SCTP_STATIC __exit void sctp_exit(void) sizeof(struct sctp_bind_hashbucket))); sctp_dbg_objcnt_exit(); + percpu_counter_destroy(&sctp_sockets_allocated); sctp_proc_exit(); cleanup_sctp_mibs(); -- cgit v1.2.3 From 13d782f6b4fbbaf9d0380a9947deb45a9de46ae7 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 6 Aug 2012 08:45:15 +0000 Subject: sctp: Make the proc files per network namespace. - Convert all of the files under /proc/net/sctp to be per network namespace. - Don't print anything for /proc/net/sctp/snmp except in the initial network namespaces as the snmp counters still have to be converted to be per network namespace. Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 87 +++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 49 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 48a5989c98ce..de7994edb4ca 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -71,10 +71,6 @@ struct sctp_globals sctp_globals __read_mostly; DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly; -#ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_sctp; -#endif - struct idr sctp_assocs_id; DEFINE_SPINLOCK(sctp_assocs_id_lock); @@ -91,60 +87,52 @@ int sysctl_sctp_rmem[3]; int sysctl_sctp_wmem[3]; /* Set up the proc fs entry for the SCTP protocol. */ -static __init int sctp_proc_init(void) +static __net_init int sctp_proc_init(struct net *net) { #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; - } - - if (sctp_snmp_proc_init()) + net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net); + if (!net->sctp.proc_net_sctp) + goto out_proc_net_sctp; + if (sctp_snmp_proc_init(net)) goto out_snmp_proc_init; - if (sctp_eps_proc_init()) + if (sctp_eps_proc_init(net)) goto out_eps_proc_init; - if (sctp_assocs_proc_init()) + if (sctp_assocs_proc_init(net)) goto out_assocs_proc_init; - if (sctp_remaddr_proc_init()) + if (sctp_remaddr_proc_init(net)) goto out_remaddr_proc_init; return 0; out_remaddr_proc_init: - sctp_assocs_proc_exit(); + sctp_assocs_proc_exit(net); out_assocs_proc_init: - sctp_eps_proc_exit(); + sctp_eps_proc_exit(net); out_eps_proc_init: - sctp_snmp_proc_exit(); + sctp_snmp_proc_exit(net); out_snmp_proc_init: - if (proc_net_sctp) { - proc_net_sctp = NULL; - remove_proc_entry("sctp", init_net.proc_net); - } -out_free_percpu: -#else - return 0; -#endif /* CONFIG_PROC_FS */ + remove_proc_entry("sctp", net->proc_net); + net->sctp.proc_net_sctp = NULL; +out_proc_net_sctp: return -ENOMEM; +#endif /* CONFIG_PROC_FS */ + return 0; } /* Clean up the proc fs entry for the SCTP protocol. * Note: Do not make this __exit as it is used in the init error * path. */ -static void sctp_proc_exit(void) +static void sctp_proc_exit(struct net *net) { #ifdef CONFIG_PROC_FS - sctp_snmp_proc_exit(); - sctp_eps_proc_exit(); - sctp_assocs_proc_exit(); - sctp_remaddr_proc_exit(); - - if (proc_net_sctp) { - proc_net_sctp = NULL; - remove_proc_entry("sctp", init_net.proc_net); - } + sctp_snmp_proc_exit(net); + sctp_eps_proc_exit(net); + sctp_assocs_proc_exit(net); + sctp_remaddr_proc_exit(net); + + remove_proc_entry("sctp", net->proc_net); + net->sctp.proc_net_sctp = NULL; #endif } @@ -1180,6 +1168,13 @@ static int sctp_net_init(struct net *net) { int status; + /* Initialize proc fs directory. */ + status = sctp_proc_init(net); + if (status) + goto err_init_proc; + + sctp_dbg_objcnt_init(net); + /* Initialize the control inode/socket for handling OOTB packets. */ if ((status = sctp_ctl_sock_init(net))) { pr_err("Failed to initialize the SCTP control sock\n"); @@ -1202,6 +1197,9 @@ static int sctp_net_init(struct net *net) return 0; err_ctl_sock_init: + sctp_dbg_objcnt_exit(net); + sctp_proc_exit(net); +err_init_proc: return status; } @@ -1213,6 +1211,10 @@ static void sctp_net_exit(struct net *net) /* Free the control endpoint. */ inet_ctl_sock_destroy(net->sctp.ctl_sock); + + sctp_dbg_objcnt_exit(net); + + sctp_proc_exit(net); } static struct pernet_operations sctp_net_ops = { @@ -1259,14 +1261,6 @@ SCTP_STATIC __init int sctp_init(void) if (status) goto err_percpu_counter_init; - /* 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 */ @@ -1476,9 +1470,6 @@ err_ehash_alloc: get_order(sctp_assoc_hashsize * sizeof(struct sctp_hashbucket))); err_ahash_alloc: - sctp_dbg_objcnt_exit(); - sctp_proc_exit(); -err_init_proc: percpu_counter_destroy(&sctp_sockets_allocated); err_percpu_counter_init: cleanup_sctp_mibs(); @@ -1520,9 +1511,7 @@ SCTP_STATIC __exit void sctp_exit(void) get_order(sctp_port_hashsize * sizeof(struct sctp_bind_hashbucket))); - sctp_dbg_objcnt_exit(); percpu_counter_destroy(&sctp_sockets_allocated); - sctp_proc_exit(); cleanup_sctp_mibs(); rcu_barrier(); /* Wait for completion of call_rcu()'s */ -- cgit v1.2.3 From bb2db45b5495455ec7580315029184550709f4a2 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 6 Aug 2012 08:46:26 +0000 Subject: sctp: Enable sctp in all network namespaces - Fix the sctp_af operations to work in all namespaces - Enable sctp socket creation in all network namespaces. Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index de7994edb4ca..059c914c09f2 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -367,7 +367,8 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, /* Should this be available for binding? */ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) { - int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr); + struct net *net = sock_net(&sp->inet.sk); + int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr); if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && @@ -454,7 +455,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", __func__, &fl4->daddr, &fl4->saddr); - rt = ip_route_output_key(&init_net, fl4); + rt = ip_route_output_key(sock_net(sk), fl4); if (!IS_ERR(rt)) dst = &rt->dst; @@ -500,7 +501,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, (AF_INET == laddr->a.sa.sa_family)) { fl4->saddr = laddr->a.v4.sin_addr.s_addr; fl4->fl4_sport = laddr->a.v4.sin_port; - rt = ip_route_output_key(&init_net, fl4); + rt = ip_route_output_key(sock_net(sk), fl4); if (!IS_ERR(rt)) { dst = &rt->dst; goto out_unlock; @@ -1033,6 +1034,7 @@ static const struct net_protocol sctp_protocol = { .handler = sctp_rcv, .err_handler = sctp_v4_err, .no_policy = 1, + .netns_ok = 1, }; /* IPv4 address related functions. */ -- cgit v1.2.3 From b01a24078fa3fc4f0f447d1306ce5adc495ead86 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 6 Aug 2012 08:47:55 +0000 Subject: sctp: Make the mib per network namespace Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 059c914c09f2..d58db315db85 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -69,7 +69,6 @@ /* Global data structures. */ struct sctp_globals sctp_globals __read_mostly; -DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly; struct idr sctp_assocs_id; DEFINE_SPINLOCK(sctp_assocs_id_lock); @@ -961,7 +960,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; - SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); + SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); return ip_queue_xmit(skb, &transport->fl); } @@ -1102,16 +1101,16 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family) return 1; } -static inline int init_sctp_mibs(void) +static inline int init_sctp_mibs(struct net *net) { - return snmp_mib_init((void __percpu **)sctp_statistics, + return snmp_mib_init((void __percpu **)net->sctp.sctp_statistics, sizeof(struct sctp_mib), __alignof__(struct sctp_mib)); } -static inline void cleanup_sctp_mibs(void) +static inline void cleanup_sctp_mibs(struct net *net) { - snmp_mib_free((void __percpu **)sctp_statistics); + snmp_mib_free((void __percpu **)net->sctp.sctp_statistics); } static void sctp_v4_pf_init(void) @@ -1170,6 +1169,11 @@ static int sctp_net_init(struct net *net) { int status; + /* Allocate and initialise sctp mibs. */ + status = init_sctp_mibs(net); + if (status) + goto err_init_mibs; + /* Initialize proc fs directory. */ status = sctp_proc_init(net); if (status) @@ -1202,6 +1206,8 @@ err_ctl_sock_init: sctp_dbg_objcnt_exit(net); sctp_proc_exit(net); err_init_proc: + cleanup_sctp_mibs(net); +err_init_mibs: return status; } @@ -1217,6 +1223,7 @@ static void sctp_net_exit(struct net *net) sctp_dbg_objcnt_exit(net); sctp_proc_exit(net); + cleanup_sctp_mibs(net); } static struct pernet_operations sctp_net_ops = { @@ -1254,11 +1261,6 @@ SCTP_STATIC __init int sctp_init(void) if (!sctp_chunk_cachep) goto err_chunk_cachep; - /* Allocate and initialise sctp mibs. */ - status = init_sctp_mibs(); - if (status) - goto err_init_mibs; - status = percpu_counter_init(&sctp_sockets_allocated, 0); if (status) goto err_percpu_counter_init; @@ -1474,8 +1476,6 @@ err_ehash_alloc: err_ahash_alloc: percpu_counter_destroy(&sctp_sockets_allocated); err_percpu_counter_init: - cleanup_sctp_mibs(); -err_init_mibs: kmem_cache_destroy(sctp_chunk_cachep); err_chunk_cachep: kmem_cache_destroy(sctp_bucket_cachep); @@ -1514,7 +1514,6 @@ SCTP_STATIC __exit void sctp_exit(void) sizeof(struct sctp_bind_hashbucket))); percpu_counter_destroy(&sctp_sockets_allocated); - cleanup_sctp_mibs(); rcu_barrier(); /* Wait for completion of call_rcu()'s */ -- cgit v1.2.3 From ebb7e95d9351f77a8ec1fca20eb645051401b7b2 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 7 Aug 2012 07:23:59 +0000 Subject: sctp: Add infrastructure for per net sysctls Start with an empty sctp_net_table that will be populated as the various tunable sysctls are made per net. Signed-off-by: "Eric W. Biederman" Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d58db315db85..0f2342be61f3 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1169,6 +1169,10 @@ static int sctp_net_init(struct net *net) { int status; + status = sctp_sysctl_net_register(net); + if (status) + goto err_sysctl_register; + /* Allocate and initialise sctp mibs. */ status = init_sctp_mibs(net); if (status) @@ -1208,6 +1212,8 @@ err_ctl_sock_init: err_init_proc: cleanup_sctp_mibs(net); err_init_mibs: + sctp_sysctl_net_unregister(net); +err_sysctl_register: return status; } @@ -1224,6 +1230,7 @@ static void sctp_net_exit(struct net *net) sctp_proc_exit(net); cleanup_sctp_mibs(net); + sctp_sysctl_net_unregister(net); } static struct pernet_operations sctp_net_ops = { -- cgit v1.2.3 From e7ff4a7037e6908b7a5f4682945a0b097d5b3535 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 7 Aug 2012 07:27:02 +0000 Subject: sctp: Push struct net down into sctp_in_scope struct net will be needed shortly when the tunables are made per network namespace. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- net/sctp/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 0f2342be61f3..59965bdea07a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -210,7 +210,7 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { if (!addr->valid) continue; - if (sctp_in_scope(&addr->a, scope)) { + if (sctp_in_scope(net, &addr->a, scope)) { /* Now that the address is in scope, check to see if * the address type is really supported by the local * sock as well as the remote peer. -- cgit v1.2.3 From e1fc3b14f9a90d9591016749289f2c3d7b35fbf4 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 7 Aug 2012 07:29:57 +0000 Subject: sctp: Make sysctl tunables per net Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- net/sctp/protocol.c | 128 ++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) (limited to 'net/sctp/protocol.c') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 59965bdea07a..2d518425d598 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1169,6 +1169,70 @@ static int sctp_net_init(struct net *net) { int status; + /* + * 14. Suggested SCTP Protocol Parameter Values + */ + /* The following protocol parameters are RECOMMENDED: */ + /* RTO.Initial - 3 seconds */ + net->sctp.rto_initial = SCTP_RTO_INITIAL; + /* RTO.Min - 1 second */ + net->sctp.rto_min = SCTP_RTO_MIN; + /* RTO.Max - 60 seconds */ + net->sctp.rto_max = SCTP_RTO_MAX; + /* RTO.Alpha - 1/8 */ + net->sctp.rto_alpha = SCTP_RTO_ALPHA; + /* RTO.Beta - 1/4 */ + net->sctp.rto_beta = SCTP_RTO_BETA; + + /* Valid.Cookie.Life - 60 seconds */ + net->sctp.valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; + + /* Whether Cookie Preservative is enabled(1) or not(0) */ + net->sctp.cookie_preserve_enable = 1; + + /* Max.Burst - 4 */ + net->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 + */ + net->sctp.max_retrans_association = 10; + net->sctp.max_retrans_path = 5; + net->sctp.max_retrans_init = 8; + + /* Sendbuffer growth - do per-socket accounting */ + net->sctp.sndbuf_policy = 0; + + /* Rcvbuffer growth - do per-socket accounting */ + net->sctp.rcvbuf_policy = 0; + + /* HB.interval - 30 seconds */ + net->sctp.hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; + + /* delayed SACK timeout */ + net->sctp.sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; + + /* Disable ADDIP by default. */ + net->sctp.addip_enable = 0; + net->sctp.addip_noauth = 0; + net->sctp.default_auto_asconf = 0; + + /* Enable PR-SCTP by default. */ + net->sctp.prsctp_enable = 1; + + /* Disable AUTH by default. */ + net->sctp.auth_enable = 0; + + /* Set SCOPE policy to enabled */ + net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE; + + /* Set the default rwnd update threshold */ + net->sctp.rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; + + /* Initialize maximum autoclose timeout. */ + net->sctp.max_autoclose = INT_MAX / HZ; + status = sctp_sysctl_net_register(net); if (status) goto err_sysctl_register; @@ -1272,59 +1336,12 @@ SCTP_STATIC __init int sctp_init(void) if (status) goto err_percpu_counter_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; - - /* Whether Cookie Preservative is enabled(1) or not(0) */ - sctp_cookie_preserve_enable = 1; - - /* 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 - */ - 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; - - /* HB.interval - 30 seconds */ - sctp_hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; - - /* delayed SACK timeout */ - 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; - /* Initialize maximum autoclose timeout. */ - sctp_max_autoclose = INT_MAX / HZ; - /* Initialize handle used for association ids. */ idr_init(&sctp_assocs_id); @@ -1411,23 +1428,6 @@ 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; - - /* 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; - sctp_sysctl_register(); INIT_LIST_HEAD(&sctp_address_families); -- cgit v1.2.3