From owner-svn-src-all@FreeBSD.ORG Tue Nov 16 08:30:40 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 542D8106564A; Tue, 16 Nov 2010 08:30:40 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 427F08FC16; Tue, 16 Nov 2010 08:30:40 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oAG8Ue9U045751; Tue, 16 Nov 2010 08:30:40 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oAG8Ue0I045747; Tue, 16 Nov 2010 08:30:40 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <201011160830.oAG8Ue0I045747@svn.freebsd.org> From: Lawrence Stewart Date: Tue, 16 Nov 2010 08:30:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r215392 - in head/sys/netinet: . cc X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Nov 2010 08:30:40 -0000 Author: lstewart Date: Tue Nov 16 08:30:39 2010 New Revision: 215392 URL: http://svn.freebsd.org/changeset/base/215392 Log: Move protocol specific implementation detail out of the core CC framework. Sponsored by: FreeBSD Foundation Tested by: Mikolaj Golub MFC after: 11 weeks X-MFC with: r215166 Modified: head/sys/netinet/cc/cc.c head/sys/netinet/tcp_subr.c head/sys/netinet/tcp_var.h Modified: head/sys/netinet/cc/cc.c ============================================================================== --- head/sys/netinet/cc/cc.c Tue Nov 16 07:57:56 2010 (r215391) +++ head/sys/netinet/cc/cc.c Tue Nov 16 08:30:39 2010 (r215392) @@ -190,10 +190,7 @@ int cc_deregister_algo(struct cc_algo *remove_cc) { struct cc_algo *funcs, *tmpfuncs; - struct tcpcb *tp; - struct inpcb *inp; int err; - VNET_ITERATOR_DECL(vnet_iter); err = ENOENT; @@ -220,53 +217,14 @@ cc_deregister_algo(struct cc_algo *remov } CC_LIST_WUNLOCK(); - if (!err) { + if (!err) /* - * Check all active control blocks across all network stacks and - * change any that are using this algorithm back to newreno. If - * the algorithm that was in use requires cleanup code to be - * run, call it. - * - * New connections already part way through being initialised - * with the CC algo we're removing will not race with this code - * because the INP_INFO_WLOCK is held during initialisation. - * We therefore don't enter the loop below until the connection - * list has stabilised. + * XXXLAS: + * - We may need to handle non-zero return values in future. + * - If we add CC framework support for protocols other than + * TCP, we may want a more generic way to handle this step. */ - VNET_LIST_RLOCK(); - VNET_FOREACH(vnet_iter) { - CURVNET_SET(vnet_iter); - INP_INFO_RLOCK(&V_tcbinfo); - LIST_FOREACH(inp, &V_tcb, inp_list) { - INP_WLOCK(inp); - /* Important to skip tcptw structs. */ - if (!(inp->inp_flags & INP_TIMEWAIT) && - (tp = intotcpcb(inp)) != NULL) { - /* - * By holding INP_WLOCK here, we are - * assured that the connection is not - * currently executing inside the CC - * module's functions i.e. it is safe - * to make the switch back to newreno. - */ - if (CC_ALGO(tp) == remove_cc) { - tmpfuncs = CC_ALGO(tp); - /* - * Newreno does not - * require any init. - */ - CC_ALGO(tp) = &newreno_cc_algo; - if (tmpfuncs->cb_destroy != NULL) - tmpfuncs->cb_destroy(tp->ccv); - } - } - INP_WUNLOCK(inp); - } - INP_INFO_RUNLOCK(&V_tcbinfo); - CURVNET_RESTORE(); - } - VNET_LIST_RUNLOCK(); - } + tcp_ccalgounload(remove_cc); return (err); } Modified: head/sys/netinet/tcp_subr.c ============================================================================== --- head/sys/netinet/tcp_subr.c Tue Nov 16 07:57:56 2010 (r215391) +++ head/sys/netinet/tcp_subr.c Tue Nov 16 08:30:39 2010 (r215392) @@ -708,6 +708,69 @@ tcp_newtcpcb(struct inpcb *inp) } /* + * Switch the congestion control algorithm back to NewReno for any active + * control blocks using an algorithm which is about to go away. + * This ensures the CC framework can allow the unload to proceed without leaving + * any dangling pointers which would trigger a panic. + * Returning non-zero would inform the CC framework that something went wrong + * and it would be unsafe to allow the unload to proceed. However, there is no + * way for this to occur with this implementation so we always return zero. + */ +int +tcp_ccalgounload(struct cc_algo *unload_algo) +{ + struct cc_algo *tmpalgo; + struct inpcb *inp; + struct tcpcb *tp; + VNET_ITERATOR_DECL(vnet_iter); + + /* + * Check all active control blocks across all network stacks and change + * any that are using "unload_algo" back to NewReno. If "unload_algo" + * requires cleanup code to be run, call it. + */ + VNET_LIST_RLOCK(); + VNET_FOREACH(vnet_iter) { + CURVNET_SET(vnet_iter); + INP_INFO_RLOCK(&V_tcbinfo); + /* + * New connections already part way through being initialised + * with the CC algo we're removing will not race with this code + * because the INP_INFO_WLOCK is held during initialisation. We + * therefore don't enter the loop below until the connection + * list has stabilised. + */ + LIST_FOREACH(inp, &V_tcb, inp_list) { + INP_WLOCK(inp); + /* Important to skip tcptw structs. */ + if (!(inp->inp_flags & INP_TIMEWAIT) && + (tp = intotcpcb(inp)) != NULL) { + /* + * By holding INP_WLOCK here, we are assured + * that the connection is not currently + * executing inside the CC module's functions + * i.e. it is safe to make the switch back to + * NewReno. + */ + if (CC_ALGO(tp) == unload_algo) { + tmpalgo = CC_ALGO(tp); + /* NewReno does not require any init. */ + CC_ALGO(tp) = &newreno_cc_algo; + if (tmpalgo->cb_destroy != NULL) + tmpalgo->cb_destroy(tp->ccv); + } + } + INP_WUNLOCK(inp); + } + INP_INFO_RUNLOCK(&V_tcbinfo); + CURVNET_RESTORE(); + } + VNET_LIST_RUNLOCK(); + + return (0); +} + +/* * Drop a TCP connection, reporting * the specified error. If connection is synchronized, * then send a RST to peer. Modified: head/sys/netinet/tcp_var.h ============================================================================== --- head/sys/netinet/tcp_var.h Tue Nov 16 07:57:56 2010 (r215391) +++ head/sys/netinet/tcp_var.h Tue Nov 16 08:30:39 2010 (r215392) @@ -605,6 +605,7 @@ VNET_DECLARE(int, tcp_ecn_maxretries); #define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries) int tcp_addoptions(struct tcpopt *, u_char *); +int tcp_ccalgounload(struct cc_algo *unload_algo); struct tcpcb * tcp_close(struct tcpcb *); void tcp_discardcb(struct tcpcb *);