From owner-svn-src-projects@FreeBSD.ORG Sun Oct 19 08:37:52 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 24A5F1065689; Sun, 19 Oct 2008 08:37:52 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id BB7278FC0C; Sun, 19 Oct 2008 08:37:51 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9J8bpaD038202; Sun, 19 Oct 2008 08:37:51 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9J8bpBY038201; Sun, 19 Oct 2008 08:37:51 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810190837.m9J8bpBY038201@svn.freebsd.org> From: Ulf Lilleengen Date: Sun, 19 Oct 2008 08:37:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184049 - in projects/csup_cvsmode: . contrib usr.bin X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Oct 2008 08:37:52 -0000 Author: lulf Date: Sun Oct 19 08:37:51 2008 New Revision: 184049 URL: http://svn.freebsd.org/changeset/base/184049 Log: - Add initial project directories for cvsmode(mirror mode) for csup, which will be imported from the work done so far in perforce. Added: projects/csup_cvsmode/ projects/csup_cvsmode/contrib/ projects/csup_cvsmode/usr.bin/ From owner-svn-src-projects@FreeBSD.ORG Sun Oct 19 08:41:10 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BB7B31065687; Sun, 19 Oct 2008 08:41:10 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 91DFF8FC1D; Sun, 19 Oct 2008 08:41:10 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9J8fAUO038383; Sun, 19 Oct 2008 08:41:10 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9J8fADn038382; Sun, 19 Oct 2008 08:41:10 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810190841.m9J8fADn038382@svn.freebsd.org> From: Ulf Lilleengen Date: Sun, 19 Oct 2008 08:41:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184052 - projects/csup_cvsmode/contrib/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Oct 2008 08:41:10 -0000 Author: lulf Date: Sun Oct 19 08:41:10 2008 New Revision: 184052 URL: http://svn.freebsd.org/changeset/base/184052 Log: - Import the HEAD csup code which is the basis for the cvsmode work. Added: projects/csup_cvsmode/contrib/csup/ - copied from r184051, head/contrib/csup/ From owner-svn-src-projects@FreeBSD.ORG Sun Oct 19 08:43:17 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 578911065691; Sun, 19 Oct 2008 08:43:17 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2DEC98FC14; Sun, 19 Oct 2008 08:43:17 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9J8hHQB038456; Sun, 19 Oct 2008 08:43:17 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9J8hHLo038455; Sun, 19 Oct 2008 08:43:17 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810190843.m9J8hHLo038455@svn.freebsd.org> From: Ulf Lilleengen Date: Sun, 19 Oct 2008 08:43:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184053 - projects/csup_cvsmode/usr.bin/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Oct 2008 08:43:17 -0000 Author: lulf Date: Sun Oct 19 08:43:16 2008 New Revision: 184053 URL: http://svn.freebsd.org/changeset/base/184053 Log: - Import the Makefile from HEAD for building csup. Added: projects/csup_cvsmode/usr.bin/csup/ - copied from r184052, head/usr.bin/csup/ From owner-svn-src-projects@FreeBSD.ORG Sun Oct 19 09:09:00 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3A7EB1065689; Sun, 19 Oct 2008 09:09:00 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 27D948FC12; Sun, 19 Oct 2008 09:09:00 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9J990iI038935; Sun, 19 Oct 2008 09:09:00 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9J98xMc038924; Sun, 19 Oct 2008 09:08:59 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810190908.m9J98xMc038924@svn.freebsd.org> From: Ulf Lilleengen Date: Sun, 19 Oct 2008 09:08:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184054 - in projects/csup_cvsmode: contrib/csup usr.bin/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Oct 2008 09:09:00 -0000 Author: lulf Date: Sun Oct 19 09:08:59 2008 New Revision: 184054 URL: http://svn.freebsd.org/changeset/base/184054 Log: - Import csup work from p4. Added: projects/csup_cvsmode/contrib/csup/lex.rcs.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsfile.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsfile.h (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsparse.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsparse.h (contents, props changed) projects/csup_cvsmode/contrib/csup/rcstokenizer.h (contents, props changed) projects/csup_cvsmode/contrib/csup/rcstokenizer.l Modified: projects/csup_cvsmode/contrib/csup/Makefile projects/csup_cvsmode/contrib/csup/config.c projects/csup_cvsmode/contrib/csup/detailer.c projects/csup_cvsmode/contrib/csup/diff.c projects/csup_cvsmode/contrib/csup/diff.h projects/csup_cvsmode/contrib/csup/fattr.c projects/csup_cvsmode/contrib/csup/fattr.h projects/csup_cvsmode/contrib/csup/keyword.c projects/csup_cvsmode/contrib/csup/keyword.h projects/csup_cvsmode/contrib/csup/lister.c projects/csup_cvsmode/contrib/csup/misc.c projects/csup_cvsmode/contrib/csup/misc.h projects/csup_cvsmode/contrib/csup/mux.c projects/csup_cvsmode/contrib/csup/proto.c projects/csup_cvsmode/contrib/csup/status.c projects/csup_cvsmode/contrib/csup/stream.c projects/csup_cvsmode/contrib/csup/stream.h projects/csup_cvsmode/contrib/csup/updater.c projects/csup_cvsmode/usr.bin/csup/Makefile Modified: projects/csup_cvsmode/contrib/csup/Makefile ============================================================================== --- projects/csup_cvsmode/contrib/csup/Makefile Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/Makefile Sun Oct 19 09:08:59 2008 (r184054) @@ -9,10 +9,11 @@ UNAME!= /usr/bin/uname -s PROG= csup SRCS= attrstack.c config.c detailer.c diff.c fattr.c fixups.c fnmatch.c \ globtree.c idcache.c keyword.c lister.c main.c misc.c mux.c parse.y \ - pathcomp.c proto.c status.c stream.c threads.c token.l updater.c + pathcomp.c proto.c status.c stream.c threads.c token.l updater.c \ + rcsfile.c rcsparse.c lex.rcs.c CFLAGS+= -I. -I${.CURDIR} -g -pthread -DHAVE_FFLAGS -DNDEBUG -WARNS?= 6 +WARNS?= 1 # A bit of tweaking is needed to get this Makefile working # with the bsd.prog.mk of all the *BSD OSes... Modified: projects/csup_cvsmode/contrib/csup/config.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/config.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/config.c Sun Oct 19 09:08:59 2008 (r184054) @@ -444,10 +444,10 @@ coll_add(char *name) "\"%s\"\n", cur_coll->co_name); exit(1); } - if (!(cur_coll->co_options & CO_CHECKOUTMODE)) { +/* if (!(cur_coll->co_options & CO_CHECKOUTMODE)) { lprintf(-1, "Client only supports checkout mode\n"); exit(1); - } + }*/ if (!STAILQ_EMPTY(&colls)) { coll = STAILQ_LAST(&colls, coll, co_next); if (strcmp(coll->co_host, cur_coll->co_host) != 0) { Modified: projects/csup_cvsmode/contrib/csup/detailer.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/detailer.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/detailer.c Sun Oct 19 09:08:59 2008 (r184054) @@ -30,6 +30,11 @@ #include #include #include +#include + +#include +#include +#include #include "config.h" #include "detailer.h" @@ -37,6 +42,7 @@ #include "misc.h" #include "mux.h" #include "proto.h" +#include "rcsfile.h" #include "status.h" #include "stream.h" @@ -56,8 +62,15 @@ struct detailer { static int detailer_batch(struct detailer *); static int detailer_coll(struct detailer *, struct coll *, struct status *); -static int detailer_dofile(struct detailer *, struct coll *, +static int detailer_dofile_co(struct detailer *, struct coll *, struct status *, char *); +static int detailer_dofile_rcs(struct detailer *, struct coll *, + char *, char *); +static int detailer_dofile_regular(struct detailer *, char *, char *); +static int detailer_checkrcsattr(struct detailer *, struct coll *, char *, + struct fattr *, int); +int detailer_send_details(struct detailer *, struct coll *, char *, + char *, struct fattr *); void * detailer(void *arg) @@ -93,6 +106,7 @@ detailer(void *arg) xasprintf(&args->errmsg, "Detailer failed: " "Network read failure: %s", strerror(errno)); } + lprintf(-1, "Error is '%s'\n", args->errmsg); args->status = STATUS_TRANSIENTFAILURE; break; case DETAILER_ERR_WRITE: @@ -131,8 +145,9 @@ detailer_batch(struct detailer *d) error = proto_get_time(&line, &coll->co_scantime); if (error || line != NULL || strcmp(cmd, "COLL") != 0 || strcmp(collname, coll->co_name) != 0 || - strcmp(release, coll->co_release) != 0) + strcmp(release, coll->co_release) != 0){ return (DETAILER_ERR_PROTO); + } error = proto_printf(wr, "COLL %s %s\n", coll->co_name, coll->co_release); if (error) @@ -147,8 +162,9 @@ detailer_batch(struct detailer *d) return (DETAILER_ERR_MSG); error = detailer_coll(d, coll, st); status_close(st, NULL); - if (error) + if (error) { return (error); + } if (coll->co_options & CO_COMPRESS) { stream_filter_stop(rd); stream_filter_stop(wr); @@ -156,10 +172,12 @@ detailer_batch(struct detailer *d) stream_flush(wr); } line = stream_getln(rd, NULL); - if (line == NULL) + if (line == NULL) { return (DETAILER_ERR_READ); - if (strcmp(line, ".") != 0) + } + if (strcmp(line, ".") != 0) { return (DETAILER_ERR_PROTO); + } error = proto_printf(wr, ".\n"); if (error) return (DETAILER_ERR_WRITE); @@ -186,8 +204,13 @@ detailer_batch(struct detailer *d) } if (fixup->f_coll != coll) break; - error = proto_printf(wr, "Y %s %s %s\n", fixup->f_name, - coll->co_tag, coll->co_date); + if (coll->co_options & CO_CHECKOUTMODE) + error = proto_printf(wr, "Y %s %s %s\n", + fixup->f_name, coll->co_tag, coll->co_date); + else { + error = proto_printf(wr, "A %s\n", + fixup->f_name); + } if (error) return (DETAILER_ERR_WRITE); fixup = NULL; @@ -208,35 +231,107 @@ detailer_batch(struct detailer *d) static int detailer_coll(struct detailer *d, struct coll *coll, struct status *st) { + struct fattr *rcsattr; struct stream *rd, *wr; - char *cmd, *file, *line, *msg; - int error; + char *attr, *cmd, *file, *line, *msg, *target, *path; + int error, attic; rd = d->rd; wr = d->wr; + attic = 0; line = stream_getln(rd, NULL); - if (line == NULL) + if (line == NULL) { return (DETAILER_ERR_READ); + } while (strcmp(line, ".") != 0) { cmd = proto_get_ascii(&line); - if (cmd == NULL || strlen(cmd) != 1) + if (cmd == NULL || strlen(cmd) != 1) { return (DETAILER_ERR_PROTO); + } switch (cmd[0]) { case 'D': /* Delete file. */ file = proto_get_ascii(&line); + if (file == NULL || line != NULL) { + return (DETAILER_ERR_PROTO); + } + error = proto_printf(wr, "D %s\n", file); + if (error) + return (DETAILER_ERR_WRITE); + break; + case 'I': + case 'i': + case 'j': + /* Directory operations. */ + file = proto_get_ascii(&line); if (file == NULL || line != NULL) return (DETAILER_ERR_PROTO); - error = proto_printf(wr, "D %s\n", file); + error = proto_printf(wr, "%s %s\n", cmd, file); + if (error) + return (DETAILER_ERR_WRITE); + break; + case 'J': + /* Set directory attributes. */ + file = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + if (file == NULL || line != NULL || attr == NULL) + return (DETAILER_ERR_PROTO); + error = proto_printf(wr, "%s %s %s\n", cmd, file, attr); if (error) return (DETAILER_ERR_WRITE); break; + case 'H': + case 'h': + /* Create a hard link. */ + file = proto_get_ascii(&line); + target = proto_get_ascii(&line); + if (file == NULL || target == NULL) + return (DETAILER_ERR_PROTO); + error = proto_printf(wr, "%s %s %s\n", cmd, file, + target); + break; + case 't': + file = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + if (file == NULL || attr == NULL || line != NULL) { + return (DETAILER_ERR_PROTO); + } + rcsattr = fattr_decode(attr); + if (rcsattr == NULL) { + return (DETAILER_ERR_PROTO); + } + error = detailer_checkrcsattr(d, coll, file, rcsattr, + 1); + break; + + case 'T': + file = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + if (file == NULL || attr == NULL || line != NULL) + return (DETAILER_ERR_PROTO); + rcsattr = fattr_decode(attr); + if (rcsattr == NULL) + return (DETAILER_ERR_PROTO); + error = detailer_checkrcsattr(d, coll, file, rcsattr, + 0); + break; + case 'U': /* Add or update file. */ file = proto_get_ascii(&line); if (file == NULL || line != NULL) return (DETAILER_ERR_PROTO); - error = detailer_dofile(d, coll, st, file); + if (coll->co_options & CO_CHECKOUTMODE) { + error = detailer_dofile_co(d, coll, st, file); + } else { + path = cvspath(coll->co_prefix, file, 0); + rcsattr = fattr_frompath(path, FATTR_NOFOLLOW); + error = detailer_send_details(d, coll, file, + path, rcsattr); + if (rcsattr != NULL) + fattr_free(rcsattr); + free(path); + } if (error) return (error); break; @@ -248,6 +343,7 @@ detailer_coll(struct detailer *d, struct lprintf(-1, "Server warning: %s\n", msg); break; default: + lprintf(-1, "Line: %s, cmd %s\n", line, cmd); return (DETAILER_ERR_PROTO); } stream_flush(wr); @@ -261,8 +357,81 @@ detailer_coll(struct detailer *d, struct return (0); } +/* + * Tell the server to update a regular file. + */ static int -detailer_dofile(struct detailer *d, struct coll *coll, struct status *st, +detailer_dofile_regular(struct detailer *d, char *name, char *path) +{ + struct stream *wr; + struct stat st; + char md5[MD5_DIGEST_SIZE]; + int error; + + wr = d->wr; + + error = stat(path, &st); + /* If we don't have it or it's unaccessible, we want it again. */ + if (error) { + proto_printf(wr, "A %s\n", name); + return (0); + } + + /* If not, we want the file to be updated. */ + error = MD5_File(path, md5); + if (error) { + lprintf(-1, "Error reading \"%s\"\n", name); + return (error); + } + error = proto_printf(wr, "R %s %O %s\n", name, st.st_size, md5); + if (error) + return (DETAILER_ERR_WRITE); + return (0); +} + +/* + * Tell the server to update an RCS file that we have, or send it if we don't. + */ +static int +detailer_dofile_rcs(struct detailer *d, struct coll *coll, char *name, + char *path) +{ + struct stream *wr; + struct fattr *fa; + struct rcsfile *rf; + int error; + + wr = d->wr; + + path = atticpath(coll->co_prefix, name); + fa = fattr_frompath(path, FATTR_NOFOLLOW); + if (fa == NULL) { + /* We don't have it, so send request to get it. */ + error = proto_printf(wr, "A %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + free(path); + return (0); + } + + rf = rcsfile_frompath(path, name, coll->co_cvsroot, coll->co_tag); + free(path); + if (rf == NULL) { + lprintf(-1, "Error parsing, resend file.\n"); + error = proto_printf(wr, "A %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + return (0); + } + /* Tell to update the RCS file. The client version details follow. */ + rcsfile_send_details(rf, wr); + rcsfile_free(rf); + fattr_free(fa); + return (0); +} + +static int +detailer_dofile_co(struct detailer *d, struct coll *coll, struct status *st, char *file) { char md5[MD5_DIGEST_SIZE]; @@ -274,8 +443,9 @@ detailer_dofile(struct detailer *d, stru wr = d->wr; path = checkoutpath(coll->co_prefix, file); - if (path == NULL) + if (path == NULL) { return (DETAILER_ERR_PROTO); + } fa = fattr_frompath(path, FATTR_NOFOLLOW); if (fa == NULL) { /* We don't have the file, so the only option at this @@ -337,3 +507,78 @@ detailer_dofile(struct detailer *d, stru return (DETAILER_ERR_WRITE); return (0); } + +int +detailer_checkrcsattr(struct detailer *d, struct coll *coll, char *name, + struct fattr *server_attr, int attic) +{ + struct fattr *client_attr; + char *attr, *path; + int error; + + /* + * I don't think we can use the status file, since it only records file + * attributes in cvsmode. + */ + client_attr = NULL; + path = cvspath(coll->co_prefix, name, attic); + if (path == NULL) { + return (DETAILER_ERR_PROTO); + } + + if (access(path, F_OK) == 0 && + ((client_attr = fattr_frompath(path, FATTR_NOFOLLOW)) != NULL) && + fattr_equal(client_attr, server_attr)) { + attr = fattr_encode(client_attr, NULL, 0); + if (attic) { + error = proto_printf(d->wr, "l %s %s\n", name, attr); + } else { + error = proto_printf(d->wr, "L %s %s\n", name, attr); + } + free(attr); + free(path); + fattr_free(client_attr); + if (error) + return (DETAILER_ERR_WRITE); + return (0); + } + /* We don't have it, so tell the server to send it. */ + error = detailer_send_details(d, coll, name, path, client_attr); + fattr_free(client_attr); + free(path); + return (error); +} + +int +detailer_send_details(struct detailer *d, struct coll *coll, char *name, + char *path, struct fattr *fa) +{ + int error; + size_t len; + + /* + * Try to check if the file exists either live or dead to see if we can + * edit it and put it live or dead, rather than receiving the entire + * file. + */ + if (fa == NULL) { + path = atticpath(coll->co_prefix, name); + fa = fattr_frompath(path, FATTR_NOFOLLOW); + } + if (fa == NULL) { + error = proto_printf(d->wr, "A %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + } else if (fattr_type(fa) == FT_FILE) { + if (isrcs(name, &len) && !(coll->co_options & CO_NORCS)) { + detailer_dofile_rcs(d, coll, name, path); + } else { + detailer_dofile_regular(d, name, path); + } + } else { + error = proto_printf(d->wr, "N %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + } + return (0); +} Modified: projects/csup_cvsmode/contrib/csup/diff.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/diff.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/diff.c Sun Oct 19 09:08:59 2008 (r184054) @@ -26,25 +26,33 @@ * $FreeBSD$ */ +#include + #include #include #include #include #include +#include #include "diff.h" #include "keyword.h" #include "misc.h" #include "stream.h" +#include "queue.h" typedef long lineno_t; #define EC_ADD 0 #define EC_DEL 1 +#define MAXKEY LONG_MAX /* Editing command and state. */ struct editcmd { int cmd; + long key; + int havetext; + int offset; lineno_t where; lineno_t count; lineno_t lasta; @@ -55,15 +63,23 @@ struct editcmd { struct diffinfo *di; struct stream *orig; struct stream *dest; + LIST_ENTRY(editcmd) next; +}; + +struct diffstart { + LIST_HEAD(, editcmd) dhead; }; static int diff_geteditcmd(struct editcmd *, char *); static int diff_copyln(struct editcmd *, lineno_t); +static int diff_ignoreln(struct editcmd *, lineno_t); static void diff_write(struct editcmd *, void *, size_t); +static int diff_insert_edit(struct diffstart *, struct editcmd *); +static int diff_free(struct diffstart *); int diff_apply(struct stream *rd, struct stream *orig, struct stream *dest, - struct keyword *keyword, struct diffinfo *di) + struct keyword *keyword, struct diffinfo *di, int comode) { struct editcmd ec; lineno_t i; @@ -104,7 +120,7 @@ diff_apply(struct stream *rd, struct str line = stream_getln(rd, &size); if (line == NULL) return (-1); - if (line[0] == '.') { + if (comode && line[0] == '.') { line++; size--; } @@ -143,6 +159,213 @@ diff_apply(struct stream *rd, struct str return (0); } +static int +diff_write_reverse(struct stream *dest, struct diffstart *ds) +{ + long firstoutputlinedeleted, endline, startline, editline, num_deleted, + num_added; + int num; + struct editcmd *ec, *nextec; + + nextec = LIST_FIRST(&ds->dhead); + editline = 0; + num = 0; + while (nextec != NULL) { + ec = nextec; + nextec = LIST_NEXT(nextec, next); + if (nextec == NULL) + break; + num++; + num_deleted = 0; + if (ec->havetext) + num_deleted = ec->count; + num_added = num_deleted + nextec->offset - ec->offset; + if (num_deleted > 0) { + firstoutputlinedeleted = ec->key - num_deleted + 1; + stream_printf(dest, "d%ld %ld\n", firstoutputlinedeleted, + num_deleted); + if (num_added <= 0) + continue; + } + if (num_added > 0) { + stream_printf(dest, "a%ld %ld\n", ec->key, num_added); + startline = ec->key - num_deleted + 1 + ec->offset; + endline = startline + num_added - 1; + + /* Copy lines from original file. First ignore some. */ + ec->editline = editline; + diff_ignoreln(ec, startline - 1); + diff_copyln(ec, endline); + editline = ec->editline; + } + } + return (0); +} + +/* + * Insert a diff into the list sorted on key. Should perhaps use quicker + * algorithms than insertion sort, but do this for now. + */ +static int +diff_insert_edit(struct diffstart *ds, struct editcmd *ec) +{ + struct editcmd *curec; + + if (ec == NULL) + return (0); + + if (LIST_EMPTY(&ds->dhead)) { + LIST_INSERT_HEAD(&ds->dhead, ec, next); + return (0); + } + + /* Insertion sort based on key. */ + /* XXX: check if this gets too slow. */ + LIST_FOREACH(curec, &ds->dhead, next) { + if (ec->key < curec->key) { + LIST_INSERT_BEFORE(curec, ec, next); + return (0); + } + if (LIST_NEXT(curec, next) == NULL) + break; + } + /* Just insert it after. */ + LIST_INSERT_AFTER(curec, ec, next); + return (0); +} + +static int +diff_free(struct diffstart *ds) +{ + struct editcmd *ec; + int freecount = 0; + + while(!LIST_EMPTY(&ds->dhead)) { + ec = LIST_FIRST(&ds->dhead); + LIST_REMOVE(ec, next); + free(ec); + freecount++; + } + return freecount; +} + +/* + * Write the reverse diff from the diff in rd, and original file into + * destination. This algorithm is the same as used in cvsup. + */ +int +diff_reverse(struct stream *rd, struct stream *orig, struct stream *dest, + struct keyword *keyword, struct diffinfo *di) +{ + struct diffstart ds; + struct editcmd ec, *addec, *delec; + lineno_t i; + char *line; + int error, offset; + int malloccount = 0, freecount = 0; + + memset(&ec, 0, sizeof(ec)); + ec.orig = orig; + ec.dest = dest; + ec.keyword = keyword; + ec.di = di; + addec = NULL; + delec = NULL; + ec.havetext = 0; + offset = 0; + LIST_INIT(&ds.dhead); + + /* Start with next since we need it. */ + line = stream_getln(rd, NULL); + /* First we build up the list of diffs from input. */ + while (line != NULL) { + error = diff_geteditcmd(&ec, line); + /*fprintf(stderr, "Diff line '%s'\n", line);*/ + if (error) + break; + if (ec.cmd == EC_ADD) { + addec = xmalloc(sizeof(struct editcmd)); + malloccount++; + *addec = ec; + addec->havetext = 1; + /* Ignore the lines we was supposed to add. */ + for (i = 0; i < ec.count; i++) { + line = stream_getln(rd, NULL); + /*fprintf(stderr, "Diff line '%s'\n", line);*/ + if (line == NULL) + return (-1); + } + + /* Get the next diff command if we have one. */ + addec->key = addec->where + addec->count - offset; + if (delec != NULL && delec->key == addec->key - addec->count) { + delec->key = addec->key; + delec->havetext = addec->havetext; + delec->count = addec->count; + + diff_insert_edit(&ds, delec); + free(addec); + freecount++; + delec = NULL; + addec = NULL; + } else { + if (delec != NULL) { + diff_insert_edit(&ds, delec); + } + delec = NULL; + addec->offset = offset; + diff_insert_edit(&ds, addec); + addec = NULL; + } + offset -= ec.count; + } else if (ec.cmd == EC_DEL) { + if (delec != NULL) { + /* Update offset to our next. */ + diff_insert_edit(&ds, delec); + delec = NULL; + } + delec = xmalloc(sizeof(struct editcmd)); + malloccount++; + *delec = ec; + delec->key = delec->where - 1 - offset; + delec->offset = offset; + delec->count = 0; + delec->havetext = 0; + /* Important to use the count we had before reset.*/ + offset += ec.count; + } + line = stream_getln(rd, NULL); + } + + while (line != NULL) { + /*fprintf(stderr, "Diff line '%s'\n", line);*/ + line = stream_getln(rd, NULL); + } + /*fprintf(stderr, "Done with diff\n");*/ + if (delec != NULL) { + diff_insert_edit(&ds, delec); + delec = NULL; + } + + addec = xmalloc(sizeof(struct editcmd)); + malloccount++; + /* Should be filesize, but we set it to max value. */ + addec->key = MAXKEY; + addec->offset = offset; + addec->havetext = 0; + addec->count = 0; + diff_insert_edit(&ds, addec); + addec = NULL; + + /*fprintf(stderr, "Done with last diff\n");*/ + diff_write_reverse(dest, &ds); + freecount += diff_free(&ds); + /*fprintf(stderr, "Diff did a total of %d mallocs\n", malloccount); + fprintf(stderr, "Diff did a total of %d frees\n", freecount);*/ + stream_flush(dest); + return (0); +} + /* Get an editing command from the diff. */ static int diff_geteditcmd(struct editcmd *ec, char *line) @@ -194,6 +417,22 @@ diff_copyln(struct editcmd *ec, lineno_t return (0); } +/* Ignore lines from the original version of the file up to line "to". */ +static int +diff_ignoreln(struct editcmd *ec, lineno_t to) +{ + char *line; + size_t size; + + while (ec->editline < to) { + line = stream_getln(ec->orig, &size); + if (line == NULL) + return (-1); + ec->editline++; + } + return (0); +} + /* Write a new line to the file, expanding RCS keywords appropriately. */ static void diff_write(struct editcmd *ec, void *buf, size_t size) Modified: projects/csup_cvsmode/contrib/csup/diff.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/diff.h Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/diff.h Sun Oct 19 09:08:59 2008 (r184054) @@ -45,6 +45,8 @@ struct diffinfo { }; int diff_apply(struct stream *, struct stream *, struct stream *, - struct keyword *, struct diffinfo *); + struct keyword *, struct diffinfo *, int); +int diff_reverse(struct stream *, struct stream *, + struct stream *, struct keyword *, struct diffinfo *); #endif /* !_DIFF_H_ */ Modified: projects/csup_cvsmode/contrib/csup/fattr.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/fattr.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/fattr.c Sun Oct 19 09:08:59 2008 (r184054) @@ -44,7 +44,7 @@ /* * Include the appropriate definition for the file attributes we support. * There are two different files: fattr_bsd.h for BSD-like systems that - * support the extended file flags à la chflags() and fattr_posix.h for + * support the extended file flags ? la chflags() and fattr_posix.h for * bare POSIX systems that don't. */ #ifdef HAVE_FFLAGS @@ -449,7 +449,7 @@ fattr_encode(const struct fattr *fa, fat piece++; } if (mask & FA_DEV) { - vallen = snprintf(piece->val, sizeof(piece->val), "%lld", + vallen = snprintf(piece->val, sizeof(piece->val), "%llx", (long long)fa->dev); len += snprintf(piece->len, sizeof(piece->len), "%lld", (long long)vallen) + vallen + 1; @@ -534,6 +534,13 @@ fattr_getlinkcount(const struct fattr *f return (fa->linkcount); } +char * +fattr_getlinktarget(const struct fattr *fa) +{ + + return (fa->linktarget); +} + /* * Eat the specified attribute and put it in the file attribute * structure. Returns NULL on error, or a pointer to the next @@ -732,23 +739,32 @@ fattr_makenode(const struct fattr *fa, c mode_t modemask, mode; int error; + error = 0; + if (fa->mask & FA_OWNER && fa->mask & FA_GROUP) modemask = FA_SETIDMASK | FA_PERMMASK; else modemask = FA_PERMMASK; /* We only implement fattr_makenode() for dirs for now. */ - assert(fa->type == FT_DIRECTORY); if (fa->mask & FA_MODE) mode = fa->mode & modemask; else mode = 0700; - error = mkdir(path, mode); + + if (fa->type == FT_DIRECTORY) + error = mkdir(path, mode); + else if (fa->type == FT_SYMLINK) { + error = symlink(fa->linktarget, path); + } else if (fa->type == FT_CDEV) { + lprintf(-1, "Character devices not supported!\n"); + } else if (fa->type == FT_BDEV) { + lprintf(-1, "Block devices not supported!\n"); + } return (error); } -int -fattr_delete(const char *path) +int fattr_delete(const char *path) { struct fattr *fa; int error; @@ -830,8 +846,9 @@ fattr_install(struct fattr *fa, const ch error = rmdir(topath); else error = unlink(topath); - if (error) + if (error) { goto bad; + } } } @@ -842,8 +859,9 @@ fattr_install(struct fattr *fa, const ch tv[1].tv_sec = fa->modtime; /* Modification time. */ tv[1].tv_usec = 0; error = utimes(frompath, tv); - if (error) + if (error) { goto bad; + } } if (mask & FA_OWNER || mask & FA_GROUP) { uid = -1; @@ -853,8 +871,9 @@ fattr_install(struct fattr *fa, const ch if (mask & FA_GROUP) gid = fa->gid; error = chown(frompath, uid, gid); - if (error) + if (error) { goto bad; + } } if (mask & FA_MODE) { newmode = fa->mode & modemask; @@ -936,3 +955,12 @@ fattr_equal(const struct fattr *fa1, con return (0); return (1); } + +/* + * Must have to get the correct filesize sendt by the server. + */ +off_t +fattr_filesize(const struct fattr *fa) +{ + return (fa->size); +} Modified: projects/csup_cvsmode/contrib/csup/fattr.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/fattr.h Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/fattr.h Sun Oct 19 09:08:59 2008 (r184054) @@ -101,6 +101,7 @@ int fattr_type(const struct fattr *); void fattr_maskout(struct fattr *, int); int fattr_getmask(const struct fattr *); nlink_t fattr_getlinkcount(const struct fattr *); +char *fattr_getlinktarget(const struct fattr *); void fattr_umask(struct fattr *, mode_t); void fattr_merge(struct fattr *, const struct fattr *); void fattr_mergedefault(struct fattr *); @@ -111,5 +112,7 @@ int fattr_install(struct fattr *, cons int fattr_equal(const struct fattr *, const struct fattr *); void fattr_free(struct fattr *); int fattr_supported(int); +off_t fattr_filesize(const struct fattr *); + #endif /* !_FATTR_H_ */ Modified: projects/csup_cvsmode/contrib/csup/keyword.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/keyword.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/keyword.c Sun Oct 19 09:08:59 2008 (r184054) @@ -152,6 +152,29 @@ keyword_decode_expand(const char *expand return (-1); } +const char * +keyword_encode_expand(int expand) +{ + + switch (expand) { + case EXPAND_DEFAULT: + return ("."); + case EXPAND_KEYVALUE: + return ("kv"); + case EXPAND_KEYVALUELOCKER: + return ("kvl"); + case EXPAND_KEY: + return ("k"); + case EXPAND_OLD: + return ("o"); + case EXPAND_BINARY: + return ("b"); + case EXPAND_VALUE: + return ("v"); + } + return (NULL); +} + void keyword_free(struct keyword *keyword) { Modified: projects/csup_cvsmode/contrib/csup/keyword.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/keyword.h Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/keyword.h Sun Oct 19 09:08:59 2008 (r184054) @@ -42,6 +42,7 @@ struct keyword; struct keyword *keyword_new(void); int keyword_decode_expand(const char *); +const char *keyword_encode_expand(int); int keyword_alias(struct keyword *, const char *, const char *); int keyword_enable(struct keyword *, const char *); int keyword_disable(struct keyword *, const char *); Added: projects/csup_cvsmode/contrib/csup/lex.rcs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/csup_cvsmode/contrib/csup/lex.rcs.c Sun Oct 19 09:08:59 2008 (r184054) @@ -0,0 +1,2094 @@ + +#line 3 "lex.rcs.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-projects@FreeBSD.ORG Mon Oct 20 04:50:07 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 62A501065679; Mon, 20 Oct 2008 04:50:07 +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 382028FC1B; Mon, 20 Oct 2008 04:50:07 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9K4o64s060576; Mon, 20 Oct 2008 04:50:06 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9K4o6uJ060575; Mon, 20 Oct 2008 04:50:06 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810200450.m9K4o6uJ060575@svn.freebsd.org> From: Lawrence Stewart Date: Mon, 20 Oct 2008 04:50:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184068 - projects/tcp_cc_7.x X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Oct 2008 04:50:07 -0000 Author: lstewart Date: Mon Oct 20 04:50:06 2008 New Revision: 184068 URL: http://svn.freebsd.org/changeset/base/184068 Log: Somewhere to maintain the backport of the TCP modular congestion control patch to 7-STABLE. Added: projects/tcp_cc_7.x/ - copied from r184067, stable/7/ From owner-svn-src-projects@FreeBSD.ORG Tue Oct 21 02:47:59 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D40731065670; Tue, 21 Oct 2008 02:47:59 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C30D88FC17; Tue, 21 Oct 2008 02:47:59 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9L2lxUi086864; Tue, 21 Oct 2008 02:47:59 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9L2lxRq086863; Tue, 21 Oct 2008 02:47:59 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200810210247.m9L2lxRq086863@svn.freebsd.org> From: Kip Macy Date: Tue, 21 Oct 2008 02:47:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184105 - projects/release_6_3_xen/sys/i386/conf X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Oct 2008 02:47:59 -0000 Author: kmacy Date: Tue Oct 21 02:47:59 2008 New Revision: 184105 URL: http://svn.freebsd.org/changeset/base/184105 Log: Add xen config Added: projects/release_6_3_xen/sys/i386/conf/XEN Added: projects/release_6_3_xen/sys/i386/conf/XEN ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/release_6_3_xen/sys/i386/conf/XEN Tue Oct 21 02:47:59 2008 (r184105) @@ -0,0 +1,155 @@ +# +# GENERIC -- Generic kernel configuration file for FreeBSD/i386 +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +machine i386 +cpu I686_CPU +ident XEN + +# To statically compile in device wiring instead of /boot/device.hints +#hints "GENERIC.hints" # Default places to look for devices. + +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +makeoptions MODULES_OVERRIDE="" + +#options SCHED_ULE # ULE scheduler +#options PREEMPTION # Enable kernel thread preemption +options SCHED_4BSD +options INET # InterNETworking +options INET6 # IPv6 communications protocols +options FFS # Berkeley Fast Filesystem +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options MD_ROOT # MD is a potential root device +options NFSCLIENT # Network Filesystem Client +options NFSSERVER # Network Filesystem Server +options NFS_ROOT # NFS usable as /, requires NFSCLIENT +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options GEOM_LABEL # Provides labelization +options COMPAT_FREEBSD4 # Compatible with FreeBSD4 +options COMPAT_FREEBSD5 # Compatible with FreeBSD5 +options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI +options KTRACE # ktrace(1) support +options SYSVSHM # SYSV-style shared memory +options SYSVMSG # SYSV-style message queues +options SYSVSEM # SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options AUDIT # Security event auditing + +# Debugging for use in -current +options KDB # Enable kernel debugger support. +options DDB # Support DDB. +options GDB # Support remote GDB. +options INVARIANTS # Enable calls of extra sanity checking +options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed + +# To make an SMP kernel, the next two lines are needed +options SMP # Symmetric MultiProcessor Kernel +device apic # I/O APIC +options PAE + + +# CPU frequency control +#device cpufreq # native only + +# Bus support. +#device pci + +# SCSI peripherals +device scbus # SCSI bus (required for SCSI) +device ch # SCSI media changers +device da # Direct Access (disks) +device sa # Sequential Access (tape etc) +device cd # CD +device pass # Passthrough device (direct SCSI access) +device ses # SCSI Environmental Services (and SAF-TE) + +# atkbdc0 controls both the keyboard and the PS/2 mouse +device atkbdc # AT keyboard controller +device atkbd # AT keyboard +device psm # PS/2 mouse +device kbdmux # keyboard multiplexer +#device vga # VGA video card driver +device splash # Splash screen and screen saver support + +# syscons is the default console driver, resembling an SCO console + +#device agp # support several AGP chipsets + +# Power management support (see NOTES for more options) +#device apm +# Add suspend/resume support for the i8254. +#device pmtimer # native + +device pci + +# Serial (COM) ports +device uart # Generic UART driver + +# If you've got a "dumb" serial or parallel PCI card that is +# supported by the puc(4) glue driver, uncomment the following +# line to enable it (connects to sio, uart and/or ppc drivers): +#device puc + +# PCI Ethernet NICs. +device em # Intel PRO/1000 adapter Gigabit Ethernet Card + +# PCI Ethernet NICs that use the common MII bus controller code. +# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! +device miibus # MII bus support + +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +device sl # Kernel SLIP +device ppp # Kernel PPP +device tun # Packet tunnel. +device pty # Pseudo-ttys (telnet etc) +device md # Memory "disks" +device gif # IPv6 and IPv4 tunneling +device faith # IPv6-to-IPv4 relaying (translation) +device firmware # firmware assist module + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +# Note that 'bpf' is required for DHCP. +device bpf # Berkeley packet filter + + +options XEN +nooption NATIVE +nodevice atpic +options MCLSHIFT=12 + +nodevice isa +nooption ISAPNP + +options KTR +options KTR_COMPILE=(KTR_PMAP) +options KTR_CPUMASK=0xff +options KTR_ENTRIES=65536 +options KTR_MASK=(KTR_PMAP) From owner-svn-src-projects@FreeBSD.ORG Tue Oct 21 12:50:45 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9F1C410656A4; Tue, 21 Oct 2008 12:50:45 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 76AC88FC26; Tue, 21 Oct 2008 12:50:45 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9LCojZW099463; Tue, 21 Oct 2008 12:50:45 GMT (envelope-from des@svn.freebsd.org) Received: (from des@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9LCojpn099462; Tue, 21 Oct 2008 12:50:45 GMT (envelope-from des@svn.freebsd.org) Message-Id: <200810211250.m9LCojpn099462@svn.freebsd.org> From: Dag-Erling Smorgrav Date: Tue, 21 Oct 2008 12:50:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184125 - projects/quota64 X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Oct 2008 12:50:45 -0000 Author: des Date: Tue Oct 21 12:50:45 2008 New Revision: 184125 URL: http://svn.freebsd.org/changeset/base/184125 Log: Project tree for 64-bit quota support. Added: projects/quota64/ - copied from r184124, head/ From owner-svn-src-projects@FreeBSD.ORG Wed Oct 22 00:03:52 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A69B11065674; Wed, 22 Oct 2008 00:03:52 +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 605A08FC13; Wed, 22 Oct 2008 00:03:52 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9M03qYh012031; Wed, 22 Oct 2008 00:03:52 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9M03ptx012021; Wed, 22 Oct 2008 00:03:52 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810220003.m9M03ptx012021@svn.freebsd.org> From: Lawrence Stewart Date: Wed, 22 Oct 2008 00:03:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184147 - in projects/tcp_cc_7.x/sys: . conf netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 00:03:52 -0000 Author: lstewart Date: Wed Oct 22 00:03:51 2008 New Revision: 184147 URL: http://svn.freebsd.org/changeset/base/184147 Log: Initial merge from the 8.x patch branch to create the 7.x version of the patch. Some minor tweaks were required to massage the patch into the 7.x tree. Added: projects/tcp_cc_7.x/sys/netinet/cc.c - copied unchanged from r184025, projects/tcp_cc_8.x/sys/netinet/cc.c projects/tcp_cc_7.x/sys/netinet/cc.h - copied, changed from r184025, projects/tcp_cc_8.x/sys/netinet/cc.h Modified: projects/tcp_cc_7.x/sys/ (props changed) projects/tcp_cc_7.x/sys/conf/files projects/tcp_cc_7.x/sys/netinet/tcp_input.c projects/tcp_cc_7.x/sys/netinet/tcp_output.c projects/tcp_cc_7.x/sys/netinet/tcp_subr.c projects/tcp_cc_7.x/sys/netinet/tcp_timer.c projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c projects/tcp_cc_7.x/sys/netinet/tcp_var.h Modified: projects/tcp_cc_7.x/sys/conf/files ============================================================================== --- projects/tcp_cc_7.x/sys/conf/files Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/conf/files Wed Oct 22 00:03:51 2008 (r184147) @@ -1794,6 +1794,7 @@ netinet/ip_mroute.c optional mrouting i netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet +netinet/cc.c optional inet netinet/sctp_asconf.c optional inet sctp netinet/sctp_auth.c optional inet sctp netinet/sctp_bsd_addr.c optional inet sctp Copied: projects/tcp_cc_7.x/sys/netinet/cc.c (from r184025, projects/tcp_cc_8.x/sys/netinet/cc.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/tcp_cc_7.x/sys/netinet/cc.c Wed Oct 22 00:03:51 2008 (r184147, copy of r184025, projects/tcp_cc_8.x/sys/netinet/cc.c) @@ -0,0 +1,451 @@ +/*- + * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 + * The Regents of the University of California. + * Copyright (c) 2008 Swinburne University of Technology, Melbourne, Australia + * All rights reserved. + * + * The majority of this software was developed at the Centre for + * Advanced Internet Architectures, Swinburne University, by Lawrence Stewart + * and James Healy, made possible in part by a grant from the Cisco University + * Research Program Fund at Community Foundation Silicon Valley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* list of available cc algorithms on the current system */ +struct cc_head cc_list = STAILQ_HEAD_INITIALIZER(cc_list); + +struct rwlock cc_list_lock; + +MALLOC_DECLARE(M_STRING); +MALLOC_DEFINE(M_STRING, "string", "a string"); + +/* create a struct to point to our newreno functions */ +struct cc_algo newreno_cc_algo = { + .name = "newreno", + .init = newreno_init, + .deinit = NULL, + .cwnd_init = newreno_cwnd_init, + .ack_received = newreno_ack_received, + .pre_fr = newreno_pre_fr, + .post_fr = newreno_post_fr, + .after_idle = newreno_after_idle, + .after_timeout = newreno_after_timeout +}; + +/* the system wide default cc algorithm */ +char cc_algorithm[TCP_CA_NAME_MAX]; + +/* + * sysctl handler that allows the default cc algorithm for the system to be + * viewed and changed + */ +static int +cc_default_algorithm(SYSCTL_HANDLER_ARGS) +{ + struct cc_algo *funcs; + + if (!req->newptr) + goto skip; + + CC_LIST_RLOCK(); + STAILQ_FOREACH(funcs, &cc_list, entries) { + if (strncmp((char *)req->newptr, funcs->name, TCP_CA_NAME_MAX) == 0) + goto reorder; + } + CC_LIST_RUNLOCK(); + + return 1; + +reorder: + /* + * Make the selected system default cc algorithm + * the first element in the list if it isn't already + */ + CC_LIST_RUNLOCK(); + CC_LIST_WLOCK(); + if (funcs != STAILQ_FIRST(&cc_list)) { + STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries); + STAILQ_INSERT_HEAD(&cc_list, funcs, entries); + } + CC_LIST_WUNLOCK(); + +skip: + return sysctl_handle_string(oidp, arg1, arg2, req); +} + +/* + * sysctl handler that displays the available cc algorithms as a read + * only value + */ +static int +cc_list_available(SYSCTL_HANDLER_ARGS) +{ + struct cc_algo *algo; + int error = 0, first = 1; + struct sbuf *s = NULL; + + if ((s = sbuf_new(NULL, NULL, TCP_CA_NAME_MAX, SBUF_AUTOEXTEND)) == NULL) + return -1; + + CC_LIST_RLOCK(); + STAILQ_FOREACH(algo, &cc_list, entries) { + error = sbuf_printf(s, (first) ? "%s" : ", %s", algo->name); + if (error != 0) + break; + first = 0; + } + CC_LIST_RUNLOCK(); + + if (!error) { + sbuf_finish(s); + error = sysctl_handle_string(oidp, sbuf_data(s), 1, req); + } + + sbuf_delete(s); + return error; +} + +/* + * Initialise cc on system boot + */ +void +cc_init() +{ + /* initialise the lock that will protect read/write access to our linked list */ + CC_LIST_LOCK_INIT(); + + /* initilize list of cc algorithms */ + STAILQ_INIT(&cc_list); + + /* add newreno to the list of available algorithms */ + cc_register_algorithm(&newreno_cc_algo); + + /* set newreno to the system default */ + strncpy(cc_algorithm, newreno_cc_algo.name, sizeof(cc_algorithm)); +} + +/* + * Returns 1 on success, 0 on failure + */ +int +cc_deregister_algorithm(struct cc_algo *remove_cc) +{ + struct cc_algo *funcs, *tmpfuncs; + register struct tcpcb *tp = NULL; + register struct inpcb *inp = NULL; + int success = 0; + + /* remove the algorithm from the list available to the system */ + CC_LIST_RLOCK(); + STAILQ_FOREACH_SAFE(funcs, &cc_list, entries, tmpfuncs) { + if (funcs == remove_cc) { + if (CC_LIST_TRY_WLOCK()) { + /* if this algorithm is the system default, reset the default to newreno */ + if (strncmp(cc_algorithm, remove_cc->name, TCP_CA_NAME_MAX) == 0) + snprintf(cc_algorithm, TCP_CA_NAME_MAX, "%s", newreno_cc_algo.name); + + STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries); + success = 1; + CC_LIST_W2RLOCK(); + } + break; + } + } + CC_LIST_RUNLOCK(); + + if (success) { + /* + * check all active control blocks and change any that are using this + * algorithm back to newreno. If the algorithm that was in use requires + * deinit code to be run, call it + */ + INP_INFO_RLOCK(&tcbinfo); + LIST_FOREACH(inp, &tcb, inp_list) { + /* skip tcptw structs */ + if (inp->inp_vflag & INP_TIMEWAIT) + continue; + INP_WLOCK(inp); + if ((tp = intotcpcb(inp)) != NULL) { + if (strncmp(CC_ALGO(tp)->name, remove_cc->name, TCP_CA_NAME_MAX) == 0 ) { + tmpfuncs = CC_ALGO(tp); + CC_ALGO(tp) = &newreno_cc_algo; + /* + * XXX: We should stall here until + * we're sure the tcb has stopped + * using the deregistered algo's functions... + * Not sure how to do that yet! + */ + if(CC_ALGO(tp)->init) + CC_ALGO(tp)->init(tp); + if (tmpfuncs->deinit) + tmpfuncs->deinit(tp); + } + } + INP_WUNLOCK(inp); + } + INP_INFO_RUNLOCK(&tcbinfo); + } + + return success; +} + +int +cc_register_algorithm(struct cc_algo *add_cc) +{ + CC_LIST_WLOCK(); + STAILQ_INSERT_TAIL(&cc_list, add_cc, entries); + CC_LIST_WUNLOCK(); + return 1; +} + +/* + * NEW RENO + */ + +int +newreno_init(struct tcpcb *tp) +{ + printf("initialising tcp connection with newreno congestion control\n"); + return 0; +} + +/* + * update ssthresh to approx 1/2 of cwnd + */ +void +newreno_ssthresh_update(struct tcpcb *tp) +{ + u_int win; + + /* reset ssthresh */ + win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; + + if (win < 2) + win = 2; + + tp->snd_ssthresh = win * tp->t_maxseg; +} + +/* + * initial cwnd at the start of a connection + * if there is a hostcache entry for the foreign host, base cwnd on that + * if rfc3390 is enabled, set cwnd to approx 4 MSS as recommended + * otherwise use the sysctl variables configured by the administrator + */ +void +newreno_cwnd_init(struct tcpcb *tp) +{ + struct hc_metrics_lite metrics; + struct inpcb *inp = tp->t_inpcb; + struct socket *so = inp->inp_socket; + + /* + * Set the slow-start flight size depending on whether this + * is a local network or not. + * + * Extend this so we cache the cwnd too and retrieve it here. + * Make cwnd even bigger than RFC3390 suggests but only if we + * have previous experience with the remote host. Be careful + * not make cwnd bigger than remote receive window or our own + * send socket buffer. Maybe put some additional upper bound + * on the retrieved cwnd. Should do incremental updates to + * hostcache when cwnd collapses so next connection doesn't + * overloads the path again. + * + * RFC3390 says only do this if SYN or SYN/ACK didn't got lost. + * We currently check only in syncache_socket for that. + */ + + tcp_hc_get(&inp->inp_inc, &metrics); + +#define TCP_METRICS_CWND +#ifdef TCP_METRICS_CWND + if (metrics.rmx_cwnd) + tp->snd_cwnd = max(tp->t_maxseg, + min(metrics.rmx_cwnd / 2, + min(tp->snd_wnd, so->so_snd.sb_hiwat))); + else +#endif + if (tcp_do_rfc3390) + tp->snd_cwnd = min(4 * tp->t_maxseg, max(2 * tp->t_maxseg, 4380)); +#ifdef INET6 + else if ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || + (!isipv6 && in_localaddr(inp->inp_faddr))) +#else + else if (in_localaddr(inp->inp_faddr)) +#endif + tp->snd_cwnd = tp->t_maxseg * ss_fltsz_local; + else + tp->snd_cwnd = tp->t_maxseg * ss_fltsz; +} + +/* + * increase cwnd on receipt of a successful ACK + * if cwnd <= ssthresh, increases by 1 MSS per ACK + * if cwnd > ssthresh, increase by ~1 MSS per RTT + */ +void +newreno_ack_received(struct tcpcb *tp, struct tcphdr *th) +{ + u_int cw = tp->snd_cwnd; + u_int incr = tp->t_maxseg; + + if (cw > tp->snd_ssthresh) + incr = incr * incr / cw; + + tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<snd_scale); +} + +/* + * update the value of ssthresh before entering FR + */ +void +newreno_pre_fr(struct tcpcb *tp, struct tcphdr *th) +{ + newreno_ssthresh_update(tp); +} + +/* + * decrease the cwnd in response to packet loss or a transmit timeout. + * th can be null, in which case cwnd will be set according to reno instead + * of new reno. + */ +void +newreno_post_fr(struct tcpcb *tp, struct tcphdr *th) +{ + /* + * Out of fast recovery. + * Window inflation should have left us + * with approximately snd_ssthresh + * outstanding data. + * But in case we would be inclined to + * send a burst, better to do it via + * the slow start mechanism. + */ + if (th && SEQ_GT(th->th_ack + tp->snd_ssthresh, tp->snd_max)) + tp->snd_cwnd = tp->snd_max - th->th_ack + tp->t_maxseg; + else + tp->snd_cwnd = tp->snd_ssthresh; +} + +/* + * if a connection has been idle for a while and more data is ready to be sent, + * reset cwnd + */ +void +newreno_after_idle(struct tcpcb *tp) +{ + /* + * We have been idle for "a while" and no acks are + * expected to clock out any data we send -- + * slow start to get ack "clock" running again. + * + * Set the slow-start flight size depending on whether + * this is a local network or not. + * + * Set the slow-start flight size depending on whether + * this is a local network or not. + */ + int ss = ss_fltsz; + +#ifdef INET6 + if (isipv6) { + if (in6_localaddr(&tp->t_inpcb->in6p_faddr)) + ss = ss_fltsz_local; + } else +#endif /* INET6 */ + + if (in_localaddr(tp->t_inpcb->inp_faddr)) + ss = ss_fltsz_local; + + tp->snd_cwnd = tp->t_maxseg * ss; +} + +/* + * reset the cwnd after a transmission timeout. + */ +void +newreno_after_timeout(struct tcpcb *tp) +{ + newreno_ssthresh_update(tp); + + /* + * Close the congestion window down to one segment + * (we'll open it by one segment for each ack we get). + * Since we probably have a window's worth of unacked + * data accumulated, this "slow start" keeps us from + * dumping all that data as back-to-back packets (which + * might overwhelm an intermediate gateway). + * + * There are two phases to the opening: Initially we + * open by one mss on each ack. This makes the window + * size increase exponentially with time. If the + * window is larger than the path can handle, this + * exponential growth results in dropped packet(s) + * almost immediately. To get more time between + * drops but still "push" the network to take advantage + * of improving conditions, we switch from exponential + * to linear window opening at some threshhold size. + * For a threshhold, we use half the current window + * size, truncated to a multiple of the mss. + * + * (the minimum cwnd that will give us exponential + * growth is 2 mss. We don't allow the threshhold + * to go below this.) + */ + tp->snd_cwnd = tp->t_maxseg; +} + +SYSCTL_NODE(_net_inet_tcp, OID_AUTO, cc, CTLFLAG_RW, NULL, + "congestion control related settings"); + +SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm, CTLTYPE_STRING|CTLFLAG_RW, + &cc_algorithm, sizeof(cc_algorithm), cc_default_algorithm, "A", + "default congestion control algorithm"); + +SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, available, CTLTYPE_STRING|CTLFLAG_RD, + NULL, 0, cc_list_available, "A", + "list available congestion control algorithms"); Copied and modified: projects/tcp_cc_7.x/sys/netinet/cc.h (from r184025, projects/tcp_cc_8.x/sys/netinet/cc.h) ============================================================================== --- projects/tcp_cc_8.x/sys/netinet/cc.h Sat Oct 18 07:20:45 2008 (r184025, copy source) +++ projects/tcp_cc_7.x/sys/netinet/cc.h Wed Oct 22 00:03:51 2008 (r184147) @@ -103,8 +103,14 @@ struct cc_algo { STAILQ_ENTRY(cc_algo) entries; }; -#define CC_ALGO(tp) ((tp)->cc_algo) -#define CC_DATA(tp) ((tp)->cc_data) +struct tcp_cc { + struct cc_algo *cc_algo; + void *cc_data; +}; + +#define CC_STRUCT(tp) ((tp)->t_pspare[2]) +#define CC_ALGO(tp) (((struct tcp_cc *)((tp)->t_pspare[2]))->cc_algo) +#define CC_DATA(tp) (((struct tcp_cc *)((tp)->t_pspare[2]))->cc_data) extern struct rwlock cc_list_lock; #define CC_LIST_LOCK_INIT() rw_init(&cc_list_lock, "cc_list") Modified: projects/tcp_cc_7.x/sys/netinet/tcp_input.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_input.c Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/netinet/tcp_input.c Wed Oct 22 00:03:51 2008 (r184147) @@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef TCPDEBUG #include #endif /* TCPDEBUG */ @@ -96,7 +97,7 @@ __FBSDID("$FreeBSD$"); #include -static const int tcprexmtthresh = 3; +const int tcprexmtthresh = 3; struct tcpstat tcpstat; SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW, @@ -123,7 +124,7 @@ static int tcp_do_rfc3042 = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3042, CTLFLAG_RW, &tcp_do_rfc3042, 0, "Enable RFC 3042 (Limited Transmit)"); -static int tcp_do_rfc3390 = 1; +int tcp_do_rfc3390 = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW, &tcp_do_rfc3390, 0, "Enable RFC 3390 (Increasing TCP's Initial Congestion Window)"); @@ -1017,14 +1018,9 @@ tcp_do_segment(struct mbuf *m, struct tc if (SEQ_GT(th->th_ack, tp->snd_una) && SEQ_LEQ(th->th_ack, tp->snd_max) && tp->snd_cwnd >= tp->snd_wnd && - ((!tcp_do_newreno && - !(tp->t_flags & TF_SACK_PERMIT) && - tp->t_dupacks < tcprexmtthresh) || - ((tcp_do_newreno || - (tp->t_flags & TF_SACK_PERMIT)) && - !IN_FASTRECOVERY(tp) && - (to.to_flags & TOF_SACK) == 0 && - TAILQ_EMPTY(&tp->snd_holes)))) { + !IN_FASTRECOVERY(tp) && + (to.to_flags & TOF_SACK) == 0 && + TAILQ_EMPTY(&tp->snd_holes)) { KASSERT(headlocked, ("%s: headlocked", __func__)); INP_INFO_WUNLOCK(&tcbinfo); @@ -1780,9 +1776,7 @@ tcp_do_segment(struct mbuf *m, struct tc th->th_ack != tp->snd_una) tp->t_dupacks = 0; else if (++tp->t_dupacks > tcprexmtthresh || - ((tcp_do_newreno || - (tp->t_flags & TF_SACK_PERMIT)) && - IN_FASTRECOVERY(tp))) { + IN_FASTRECOVERY(tp)) { if ((tp->t_flags & TF_SACK_PERMIT) && IN_FASTRECOVERY(tp)) { int awnd; @@ -1806,7 +1800,6 @@ tcp_do_segment(struct mbuf *m, struct tc goto drop; } else if (tp->t_dupacks == tcprexmtthresh) { tcp_seq onxt = tp->snd_nxt; - u_int win; /* * If we're doing sack, check to @@ -1820,18 +1813,22 @@ tcp_do_segment(struct mbuf *m, struct tc tp->t_dupacks = 0; break; } - } else if (tcp_do_newreno) { + } else { if (SEQ_LEQ(th->th_ack, tp->snd_recover)) { tp->t_dupacks = 0; break; } } - win = min(tp->snd_wnd, tp->snd_cwnd) / - 2 / tp->t_maxseg; - if (win < 2) - win = 2; - tp->snd_ssthresh = win * tp->t_maxseg; + + /* + * If the current tcp cc module has + * defined a hook for tasks to run + * before entering FR, call it + */ + if (CC_ALGO(tp)->pre_fr) + CC_ALGO(tp)->pre_fr(tp, th); + ENTER_FASTRECOVERY(tp); tp->snd_recover = tp->snd_max; tcp_timer_activate(tp, TT_REXMT, 0); @@ -1897,37 +1894,16 @@ tcp_do_segment(struct mbuf *m, struct tc * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) { - if (IN_FASTRECOVERY(tp)) { - if (SEQ_LT(th->th_ack, tp->snd_recover)) { - if (tp->t_flags & TF_SACK_PERMIT) - tcp_sack_partialack(tp, th); - else - tcp_newreno_partial_ack(tp, th); - } else { - /* - * Out of fast recovery. - * Window inflation should have left us - * with approximately snd_ssthresh - * outstanding data. - * But in case we would be inclined to - * send a burst, better to do it via - * the slow start mechanism. - */ - if (SEQ_GT(th->th_ack + - tp->snd_ssthresh, - tp->snd_max)) - tp->snd_cwnd = tp->snd_max - - th->th_ack + - tp->t_maxseg; - else - tp->snd_cwnd = tp->snd_ssthresh; - } + if (IN_FASTRECOVERY(tp)) { + if (SEQ_LT(th->th_ack, tp->snd_recover)) { + if (tp->t_flags & TF_SACK_PERMIT) + tcp_sack_partialack(tp, th); + else + tcp_newreno_partial_ack(tp, th); + } else { + if (CC_ALGO(tp)->post_fr) + CC_ALGO(tp)->post_fr(tp, th); } - } else { - if (tp->t_dupacks >= tcprexmtthresh && - tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; } tp->t_dupacks = 0; /* @@ -2033,13 +2009,9 @@ process_ACK: * If cwnd > maxseg^2, fix the cwnd increment at 1 byte * to avoid capping cwnd (as suggested in RFC2581). */ - if ((!tcp_do_newreno && !(tp->t_flags & TF_SACK_PERMIT)) || - !IN_FASTRECOVERY(tp)) { - u_int cw = tp->snd_cwnd; - u_int incr = tp->t_maxseg; - if (cw > tp->snd_ssthresh) - incr = max((incr * incr / cw), 1); - tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<snd_scale); + if (!IN_FASTRECOVERY(tp)) { + if (CC_ALGO(tp)->ack_received) + CC_ALGO(tp)->ack_received(tp, th); } SOCKBUF_LOCK(&so->so_snd); if (acked > so->so_snd.sb_cc) { @@ -2054,14 +2026,11 @@ process_ACK: /* NB: sowwakeup_locked() does an implicit unlock. */ sowwakeup_locked(so); /* Detect una wraparound. */ - if ((tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) && - !IN_FASTRECOVERY(tp) && + if (!IN_FASTRECOVERY(tp) && SEQ_GT(tp->snd_una, tp->snd_recover) && SEQ_LEQ(th->th_ack, tp->snd_recover)) tp->snd_recover = th->th_ack - 1; - if ((tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) && - IN_FASTRECOVERY(tp) && - SEQ_GEQ(th->th_ack, tp->snd_recover)) + if (IN_FASTRECOVERY(tp) && SEQ_GEQ(th->th_ack, tp->snd_recover)) EXIT_FASTRECOVERY(tp); tp->snd_una = th->th_ack; if (tp->t_flags & TF_SACK_PERMIT) { @@ -2940,41 +2909,11 @@ tcp_mss(struct tcpcb *tp, int offer) if (metrics.rmx_bandwidth) tp->snd_bandwidth = metrics.rmx_bandwidth; - /* - * Set the slow-start flight size depending on whether this - * is a local network or not. - * - * Extend this so we cache the cwnd too and retrieve it here. - * Make cwnd even bigger than RFC3390 suggests but only if we - * have previous experience with the remote host. Be careful - * not make cwnd bigger than remote receive window or our own - * send socket buffer. Maybe put some additional upper bound - * on the retrieved cwnd. Should do incremental updates to - * hostcache when cwnd collapses so next connection doesn't - * overloads the path again. - * - * RFC3390 says only do this if SYN or SYN/ACK didn't got lost. - * We currently check only in syncache_socket for that. - */ -#define TCP_METRICS_CWND -#ifdef TCP_METRICS_CWND - if (metrics.rmx_cwnd) - tp->snd_cwnd = max(mss, - min(metrics.rmx_cwnd / 2, - min(tp->snd_wnd, so->so_snd.sb_hiwat))); - else -#endif - if (tcp_do_rfc3390) - tp->snd_cwnd = min(4 * mss, max(2 * mss, 4380)); -#ifdef INET6 - else if ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || - (!isipv6 && in_localaddr(inp->inp_faddr))) -#else - else if (in_localaddr(inp->inp_faddr)) -#endif - tp->snd_cwnd = mss * ss_fltsz_local; + /* set the initial cwnd value */ + if (CC_ALGO(tp)->cwnd_init) + CC_ALGO(tp)->cwnd_init(tp); else - tp->snd_cwnd = mss * ss_fltsz; + tp->snd_cwnd = mss; /* Check the interface for TSO capabilities. */ if (mtuflags & CSUM_TSO) Modified: projects/tcp_cc_7.x/sys/netinet/tcp_output.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_output.c Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/netinet/tcp_output.c Wed Oct 22 00:03:51 2008 (r184147) @@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef TCPDEBUG #include #endif @@ -98,10 +99,6 @@ int ss_fltsz_local = 4; SYSCTL_INT(_net_inet_tcp, OID_AUTO, local_slowstart_flightsize, CTLFLAG_RW, &ss_fltsz_local, 1, "Slow start flight size for local networks"); -int tcp_do_newreno = 1; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, newreno, CTLFLAG_RW, - &tcp_do_newreno, 0, "Enable NewReno Algorithms"); - int tcp_do_tso = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, tso, CTLFLAG_RW, &tcp_do_tso, 0, "Enable TCP Segmentation Offload"); @@ -162,24 +159,9 @@ tcp_output(struct tcpcb *tp) */ idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una); if (idle && (ticks - tp->t_rcvtime) >= tp->t_rxtcur) { - /* - * We have been idle for "a while" and no acks are - * expected to clock out any data we send -- - * slow start to get ack "clock" running again. - * - * Set the slow-start flight size depending on whether - * this is a local network or not. - */ - int ss = ss_fltsz; -#ifdef INET6 - if (isipv6) { - if (in6_localaddr(&tp->t_inpcb->in6p_faddr)) - ss = ss_fltsz_local; - } else -#endif /* INET6 */ - if (in_localaddr(tp->t_inpcb->inp_faddr)) - ss = ss_fltsz_local; - tp->snd_cwnd = tp->t_maxseg * ss; + /* reset cwnd after a period of idleness */ + if (CC_ALGO(tp)->after_idle) + CC_ALGO(tp)->after_idle(tp); } tp->t_flags &= ~TF_LASTIDLE; if (idle) { Modified: projects/tcp_cc_7.x/sys/netinet/tcp_subr.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_subr.c Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/netinet/tcp_subr.c Wed Oct 22 00:03:51 2008 (r184147) @@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$"); #ifdef INET6 #include #endif +#include +#include #include #include #include @@ -86,6 +88,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef INET6 #include #endif @@ -218,6 +221,7 @@ static void tcp_isn_tick(void *); struct tcpcb_mem { struct tcpcb tcb; struct tcp_timer tt; + struct tcp_cc cc; }; static uma_zone_t tcpcb_zone; @@ -268,6 +272,8 @@ tcp_init(void) tcp_inflight_rttthresh = TCPTV_INFLIGHT_RTTTHRESH; tcp_finwait2_timeout = TCPTV_FINWAIT2_TIMEOUT; + cc_init(); + INP_INFO_LOCK_INIT(&tcbinfo, "tcp"); LIST_INIT(&tcb); tcbinfo.ipi_listhead = &tcb; @@ -592,6 +598,23 @@ tcp_newtcpcb(struct inpcb *inp) if (tm == NULL) return (NULL); tp = &tm->tcb; + + /* + * use the current system default cc algorithm, which is always + * the first algorithm in cc_list + */ + CC_STRUCT(tp) = &tm->cc; + CC_LIST_RLOCK(); + CC_ALGO(tp) = STAILQ_FIRST(&cc_list); + CC_LIST_RUNLOCK(); + + /* if the cc module fails to init, stop building the control block */ + if (CC_ALGO(tp)->init(tp) > 0) { + uma_zfree(tcpcb_zone, CC_STRUCT(tp)); + uma_zfree(tcpcb_zone, tp); + return NULL; + } + tp->t_timers = &tm->tt; /* LIST_INIT(&tp->t_segq); */ /* XXX covered by M_ZERO */ tp->t_maxseg = tp->t_maxopd = @@ -752,8 +775,13 @@ tcp_discardcb(struct tcpcb *tp) } /* Disconnect offload device, if any. */ tcp_offload_detach(tp); - tcp_free_sackholes(tp); + + /* Allow the cc algorithm in use for this cb to clean up after itself */ + if (CC_ALGO(tp)->deinit) + CC_ALGO(tp)->deinit(tp); + + CC_ALGO(tp) = NULL; inp->inp_ppcb = NULL; tp->t_inpcb = NULL; uma_zfree(tcpcb_zone, tp); Modified: projects/tcp_cc_7.x/sys/netinet/tcp_timer.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_timer.c Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/netinet/tcp_timer.c Wed Oct 22 00:03:51 2008 (r184147) @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef TCPDEBUG #include #endif @@ -518,38 +519,11 @@ tcp_timer_rexmt(void * xtp) * If timing a segment in this window, stop the timer. */ tp->t_rtttime = 0; - /* - * Close the congestion window down to one segment - * (we'll open it by one segment for each ack we get). - * Since we probably have a window's worth of unacked - * data accumulated, this "slow start" keeps us from - * dumping all that data as back-to-back packets (which - * might overwhelm an intermediate gateway). - * - * There are two phases to the opening: Initially we - * open by one mss on each ack. This makes the window - * size increase exponentially with time. If the - * window is larger than the path can handle, this - * exponential growth results in dropped packet(s) - * almost immediately. To get more time between - * drops but still "push" the network to take advantage - * of improving conditions, we switch from exponential - * to linear window opening at some threshhold size. - * For a threshhold, we use half the current window - * size, truncated to a multiple of the mss. - * - * (the minimum cwnd that will give us exponential - * growth is 2 mss. We don't allow the threshhold - * to go below this.) - */ - { - u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - if (win < 2) - win = 2; - tp->snd_cwnd = tp->t_maxseg; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_dupacks = 0; - } + + if (CC_ALGO(tp)->after_timeout) + CC_ALGO(tp)->after_timeout(tp); + + tp->t_dupacks = 0; EXIT_FASTRECOVERY(tp); (void) tcp_output(tp); Modified: projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c Wed Oct 22 00:03:51 2008 (r184147) @@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef TCPDEBUG #include #endif @@ -1261,6 +1262,8 @@ tcp_ctloutput(struct socket *so, struct struct inpcb *inp; struct tcpcb *tp; struct tcp_info ti; + char buf[TCP_CA_NAME_MAX]; + struct cc_algo *cc_algo; error = 0; inp = sotoinpcb(so); @@ -1370,6 +1373,58 @@ tcp_ctloutput(struct socket *so, struct error = EINVAL; break; + case TCP_CONGESTION: + INP_WUNLOCK(inp); + bzero(buf, sizeof(buf)); + error = sooptcopyin(sopt, &buf, sizeof(buf), 1); + if (error) + break; + INP_WLOCK_RECHECK(inp); + /* + * We return EINVAL if we can't find the requested cc + * algo. We set error here and reset to 0 if found to + * simplify the error checking, + */ + error = EINVAL; + CC_LIST_RLOCK(); + STAILQ_FOREACH(cc_algo, &cc_list, entries) { + if ( strncmp(buf, + cc_algo->name, + TCP_CA_NAME_MAX) == 0) { + /* + * we've found the requested algo, + * so revert the EINVAL error condition. + */ + error = 0; + /* + * we hold a write lock over the tcb + * so it's safe to do these things + * without ordering concerns + */ + if (CC_ALGO(tp)->deinit) + CC_ALGO(tp)->deinit(tp); + CC_ALGO(tp) = cc_algo; + /* + * if something goes pear shaped + * initialising the new algo, + * fall back to newreno (which + * does not require initialisation) + */ + if (cc_algo->init(tp) > 0) { + CC_ALGO(tp) = &newreno_cc_algo; + /* + * the only reason init() should + * fail is because of malloc + */ + error = ENOMEM; + } + break; /* break the STAILQ_FOREACH */ + } + } + CC_LIST_RUNLOCK(); + INP_WUNLOCK(inp); + break; + default: INP_WUNLOCK(inp); error = ENOPROTOOPT; @@ -1413,6 +1468,12 @@ tcp_ctloutput(struct socket *so, struct INP_WUNLOCK(inp); error = sooptcopyout(sopt, &ti, sizeof ti); break; + case TCP_CONGESTION: + bzero(buf, sizeof(buf)); + memcpy(&(CC_ALGO(tp)->name), buf, TCP_CA_NAME_MAX); + INP_WUNLOCK(inp); + error = sooptcopyout(sopt, buf, TCP_CA_NAME_MAX); + break; default: INP_WUNLOCK(inp); error = ENOPROTOOPT; Modified: projects/tcp_cc_7.x/sys/netinet/tcp_var.h ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_var.h Wed Oct 22 00:01:53 2008 (r184146) +++ projects/tcp_cc_7.x/sys/netinet/tcp_var.h Wed Oct 22 00:03:51 2008 (r184147) @@ -504,7 +504,7 @@ extern int tcp_log_in_vain; extern int tcp_mssdflt; /* XXX */ extern int tcp_minmss; extern int tcp_delack_enabled; -extern int tcp_do_newreno; +extern int tcp_do_rfc3390; extern int path_mtu_discovery; extern int ss_fltsz; extern int ss_fltsz_local; From owner-svn-src-projects@FreeBSD.ORG Wed Oct 22 00:22:32 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B37221065671; Wed, 22 Oct 2008 00:22:32 +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 A00C78FC18; Wed, 22 Oct 2008 00:22:32 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9M0MWaB012399; Wed, 22 Oct 2008 00:22:32 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9M0MW7Q012395; Wed, 22 Oct 2008 00:22:32 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810220022.m9M0MW7Q012395@svn.freebsd.org> From: Lawrence Stewart Date: Wed, 22 Oct 2008 00:22:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184148 - in projects/tcp_cc_8.x/sys: conf modules modules/cc_htcp netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 00:22:32 -0000 Author: lstewart Date: Wed Oct 22 00:22:32 2008 New Revision: 184148 URL: http://svn.freebsd.org/changeset/base/184148 Log: Pull in the HTCP congestion control module from my private dev repo. Needs some tidying up but is functionally good to go. Added: projects/tcp_cc_8.x/sys/modules/cc_htcp/ projects/tcp_cc_8.x/sys/modules/cc_htcp/Makefile (contents, props changed) projects/tcp_cc_8.x/sys/netinet/cc_htcp.c (contents, props changed) Modified: projects/tcp_cc_8.x/sys/conf/files projects/tcp_cc_8.x/sys/modules/Makefile Modified: projects/tcp_cc_8.x/sys/conf/files ============================================================================== --- projects/tcp_cc_8.x/sys/conf/files Wed Oct 22 00:03:51 2008 (r184147) +++ projects/tcp_cc_8.x/sys/conf/files Wed Oct 22 00:22:32 2008 (r184148) @@ -1961,6 +1961,7 @@ netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/cc.c optional inet +netinet/cc_htcp.c optional inet netinet/sctp_asconf.c optional inet sctp netinet/sctp_auth.c optional inet sctp netinet/sctp_bsd_addr.c optional inet sctp Modified: projects/tcp_cc_8.x/sys/modules/Makefile ============================================================================== --- projects/tcp_cc_8.x/sys/modules/Makefile Wed Oct 22 00:03:51 2008 (r184147) +++ projects/tcp_cc_8.x/sys/modules/Makefile Wed Oct 22 00:22:32 2008 (r184148) @@ -48,6 +48,7 @@ SUBDIR= ${_3dfx} \ ${_canbus} \ ${_cardbus} \ ${_cbb} \ + cc_htcp \ cd9660 \ cd9660_iconv \ cdce \ Added: projects/tcp_cc_8.x/sys/modules/cc_htcp/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/tcp_cc_8.x/sys/modules/cc_htcp/Makefile Wed Oct 22 00:22:32 2008 (r184148) @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.include + +.PATH: ${.CURDIR}/../../netinet +KMOD=cc_htcp +SRCS=cc_htcp.c + +.include + Added: projects/tcp_cc_8.x/sys/netinet/cc_htcp.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/tcp_cc_8.x/sys/netinet/cc_htcp.c Wed Oct 22 00:22:32 2008 (r184148) @@ -0,0 +1,623 @@ +/*- + * Copyright (c) 2008 Swinburne University of Technology, Melbourne, Australia + * All rights reserved. + * + * This software was developed at the Centre for Advanced Internet + * Architectures, Swinburne University, by Lawrence Stewart and James Healy, + * made possible in part by a grant from the Cisco University Research Program + * Fund at Community Foundation Silicon Valley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * HTCP + * + * An implementation of HTCP congestion algorithm for FreeBSD 7.0 + * The algorithm is based on the one described in "H-TCP: A framework + * for congestion control in high-speed and long-distance networks" by + * Leith, Shorten and Lee. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* useful defines */ +#define MODNAME "HTCP congestion control" +#define MODVERSION "0.9.1" +#define HTCP_SHIFT 8 +#define HTCP_ALPHA_INC_SHIFT 4 +#define HTCP_INIT_ALPHA 1 +#define HTCP_DELTA_L hz /* 1 sec in ticks */ +#define HTCP_MINBETA 128 /* 0.5 with a shift << 8 */ +#define HTCP_MAXBETA 204 /* ~0.8 with a shift << 8 */ +#define HTCP_MINROWE 26 /* ~0.1 with a shift << 8 */ +#define HTCP_MAXROWE 512 /* 2 with a shift << 8 */ +#define HTCP_RTT_REF 100 /* reference RTT in milliseconds used in the calculation of */ + /* alpha if htcp_rtt_scaling=1 */ +#define HTCP_MIN_RTT_SAMPLES 8 /* don't trust the TCP stack's smoothed rtt estimate */ + /* until this many samples have been taken */ +#define CAST_PTR_INT(X) (*((int*)(X))) + +/* + * HTCP_CALC_ALPHA performs a fixed point math calculation to + * determine the value of alpha, based on the function defined in + * H-TCP: A framework for congestion control in high-speed and long distance networks" + * + * i.e. 1 + 10(delta - delta_l) + ((delta - delta_l) / 2) ^ 2 + * + * "diff" is passed in to the macro as "delta - delta_l" and is + * expected to be in units of ticks. + * + * The joyousnous of fixed point maths means our function implementation + * looks a little funky... + * + * In order to maintain some precision in the calculations, a fixed point + * shift HTCP_ALPHA_INC_SHIFT is used to ensure the integer divisions don't + * truncate the results too badly. + * + * The "16" value is the "1" term in the alpha function shifted up by HTCP_ALPHA_INC_SHIFT + * + * The "160" value is the "10" multiplier in the alpha function multiplied by 2^HTCP_ALPHA_INC_SHIFT + * + * Specifying these as constants reduces the computations required. + * After up-shifting all the terms in the function and performing the + * required calculations, we down-shift the final result by + * HTCP_ALPHA_INC_SHIFT to ensure it is back in the correct range. + * + * The "hz" terms are required as kernels can be configured to run + * with different tick timers, which we have to adjust for in the + * alpha calculation (which originally was defined in terms of seconds). + * + * We also have to be careful to constrain the value of diff such that it + * won't overflow whilst performing the calculation. The middle term i.e. + * (160 * diff) / hz is the limiting factor in the calculation. We must + * constrain diff to be less than the max size of an unsigned long divided + * by the constant 160 figure i.e. + * diff < [(2 ^ (sizeof(u_long) * 8)) - 1] / 160 + * + * NB: Changing HTCP_ALPHA_INC_SHIFT will require you to MANUALLY update + * the constants used in this function! + */ +#define HTCP_CALC_ALPHA(diff) \ +(\ + (\ + (16) + \ + ((160 * (diff)) / hz) + \ + (((diff) / hz) * (((diff) << HTCP_ALPHA_INC_SHIFT) / (4 * hz))) \ + ) >> HTCP_ALPHA_INC_SHIFT \ +) + +/* function prototypes */ +int htcp_init(struct tcpcb *tp); +void htcp_deinit(struct tcpcb *tp); +void htcp_recalc_alpha(struct tcpcb *tp); +void htcp_recalc_beta(struct tcpcb *tp); +void htcp_pre_fr(struct tcpcb *tp, struct tcphdr *th); +void htcp_post_fr(struct tcpcb *tp, struct tcphdr *th); +void htcp_ack_received(struct tcpcb *tp, struct tcphdr *th); +void htcp_after_timeout(struct tcpcb *tp); +void htcp_after_idle(struct tcpcb *tp); +void htcp_ssthresh_update(struct tcpcb *tp); +void htcp_record_rtt(struct tcpcb *tp); + +struct htcp { + u_int alpha; /* alpha param, used for cwnd increase */ + u_int beta; /* beta param, used for cwnd increase and decreade */ + u_long prev_cwnd; /* the value of cwnd before entering fast recovery */ + /* used when setting the cwnd after exiting FR */ + u_long t_last_cong; /* time of last congestion event in ticks */ + u_int minrtt; /* the shortest rtt seen for a flow */ + u_int maxrtt; /* the largest rtt seen for a flow */ +}; + +static u_long htcp_max_diff; +static u_int htcp_rtt_scaling = 0; +static u_int htcp_adaptive_backoff = 0; +static u_int htcp_rtt_ref; + +#ifdef HTCP_DEBUG +static u_int htcp_debug_ticks = 1000; +#endif + +MALLOC_DECLARE(M_HTCP); +MALLOC_DEFINE(M_HTCP, "htcp data", "Per connection data required for the HTCP congestion algorithm"); + +/* function pointers for various hooks into the TCP stack */ +struct cc_algo htcp_cc_algo = { + .name = "htcp", + .init = htcp_init, + .deinit = htcp_deinit, + .cwnd_init = newreno_cwnd_init, + .ack_received = htcp_ack_received, + .pre_fr = htcp_pre_fr, + .post_fr = htcp_post_fr, + .after_idle = htcp_after_idle, + .after_timeout = htcp_after_timeout +}; + +/* + * Initialise HTCP on the specified TCP control block. Creates a + * new struct for HTCP specific data and sticks a pointer to it + * in the control block + */ +int +htcp_init(struct tcpcb *tp) +{ + struct htcp *htcp_data; + +#ifdef HTCP_DEBUG + printf("initialising tcp connection with htcp congestion control\n"); +#endif + + MALLOC(htcp_data, struct htcp *, sizeof(struct htcp), M_HTCP, M_NOWAIT); + + if (htcp_data == NULL) + return 1; + + /* init some key htcp values with sensible defaults */ + htcp_data->alpha = HTCP_INIT_ALPHA; + htcp_data->beta = HTCP_MINBETA; + htcp_data->t_last_cong = ticks; + htcp_data->prev_cwnd = 0; + htcp_data->minrtt = TCPTV_SRTTBASE; + htcp_data->maxrtt = TCPTV_SRTTBASE; + + CC_DATA(tp) = htcp_data; + + return 0; +} + +/* + * Free the struct used to store HTCP specific data for the specified + * TCP control block. + */ +void +htcp_deinit(struct tcpcb *tp) +{ +#ifdef HTCP_DEBUG + printf("deinitialising tcp connection with htcp congestion control\n"); +#endif + + if (CC_DATA(tp)) + FREE(CC_DATA(tp), M_HTCP); +} + +/* + * Recalculate the alpha value used for scaling cwnd up. + * This is currently called once for each ACK that is received. + */ +void +htcp_recalc_alpha(struct tcpcb *tp) +{ + u_int alpha, now; + struct htcp *htcp_data = CC_DATA(tp); + u_long delta = 0, diff = 0; + +#ifdef HTCP_DEBUG + static u_int debug_counter = 0; +#endif + + now = ticks; + + /* + * if ticks has wrapped around (will happen approximately once + * every 49 days on a machine running at 1000hz) and a flow straddles + * the wrap point, our alpha calcs will be completely wrong. + * We cut our losses and restart alpha from scratch + * by setting t_last_cong = now + delta_l + * + * This does not deflate our cwnd at all. It simply slows the rate + * cwnd is growing by until alpha regains the value it held + * prior to taking this drastic measure. + */ + if (now < htcp_data->t_last_cong) + htcp_data->t_last_cong = now + HTCP_DELTA_L; + + delta = now - htcp_data->t_last_cong; + + /* + * if its been less than HTCP_DELTA_L ticks since congestion, + * set alpha to 1. Otherwise, use the function defined in + * the key HTCP paper + */ + if (delta < HTCP_DELTA_L) + htcp_data->alpha = 1; + + else if ((diff = delta - HTCP_DELTA_L) < htcp_max_diff) + { + alpha = HTCP_CALC_ALPHA(diff); + + /* Adaptive backoff fairness adjustment: 2 * (1 - beta) * alpha_raw */ + if(htcp_adaptive_backoff) + alpha = max(1, (2 * ((1 << HTCP_SHIFT) - htcp_data->beta) * alpha) >> HTCP_SHIFT); + + /* + * RTT scaling: (RTT / RTT_ref) * alpha_raw + * alpha will be the raw value from HTCP_CALC_ALPHA() if adaptive backoff + * is off, or the adjusted value if adaptive backoff is on + */ + if(htcp_rtt_scaling) + alpha = max(1, (min(max(HTCP_MINROWE, (tp->t_srtt << HTCP_SHIFT) / htcp_rtt_ref), HTCP_MAXROWE) * alpha) >> HTCP_SHIFT); + + htcp_data->alpha = alpha; + } + + +#ifdef HTCP_DEBUG + /* print out a debug message to syslog periodically */ + if(ticks - debug_counter > htcp_debug_ticks) + { + debug_counter = ticks; + + printf("alpha: %-4u salpha: %-4u beta: %-4d t_last_cong: %-10u delta: %-6u cwnd: %-7u min|max rtt: %5u|%-5u rtt|rtt_ref: %5u|%-5u\n", + (unsigned int)HTCP_CALC_ALPHA(diff), + htcp_data->alpha, + htcp_data->beta, + (unsigned int)htcp_data->t_last_cong, + (unsigned int)delta, + (unsigned int)tp->snd_cwnd, + htcp_data->minrtt, + htcp_data->maxrtt, + tp->t_srtt, + htcp_rtt_ref + ); + } +#endif +} + +/* + * Recalculate the beta value used for scaling cwnd up and down. + * This is currently called once for each ACK that is received + */ +void +htcp_recalc_beta(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + /* + * beta is stored as a fixed point number instead of floating point for + * efficiency reasons. The decimal point is moved 1 byte to the left, + * allowing for a 3 byte whole number and 1 byte fractional + * + * any time a number is multiplied or divided by beta, the answer must be right + * shifted by a byte to get the real answer + * + * beta is bounded to ensure it is always between HTCP_MINBETA and HTCP_MAXBETA + */ + + /* + * TCPTV_SRTTBASE is the initialised value of each connection's srtt, so we only + * calc beta if the connection's srtt has been changed from its inital value + */ + if (htcp_adaptive_backoff && htcp_data->minrtt != TCPTV_SRTTBASE && htcp_data->maxrtt != TCPTV_SRTTBASE) + htcp_data->beta = min(max(HTCP_MINBETA, (htcp_data->minrtt << HTCP_SHIFT) / htcp_data->maxrtt), HTCP_MAXBETA); + else + htcp_data->beta = HTCP_MINBETA; +} + +/* + * Record the minimum and maximum RTT seen on the connection. + * These are used in the calculation of beta if adaptive backoff is enabled. + */ +void +htcp_record_rtt(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + /* TODO: Should there be some hysteresis for minrtt? */ + + /* + * record the current SRTT as our minrtt if it's the smalelst we've + * seen or minrtt is currently equal to its initialised value. + * Ignore srtt until a min number of samples have been taken + */ + if ((tp->t_srtt < htcp_data->minrtt || htcp_data->minrtt == TCPTV_SRTTBASE) && (tp->t_rttupdated >= HTCP_MIN_RTT_SAMPLES)) + htcp_data->minrtt = tp->t_srtt; + + /* + * record the current SRTT as our maxrtt if it's the largest we've + * seen. + * Ignore srtt until a min number of samples have been taken + */ + if (tp->t_srtt > htcp_data->maxrtt && tp->t_rttupdated >= HTCP_MIN_RTT_SAMPLES) + htcp_data->maxrtt = tp->t_srtt; +} + +/* + * Perform any necesary tasks before we enter fast recovery + */ +void +htcp_pre_fr(struct tcpcb *tp, struct tcphdr *th) +{ + struct htcp *htcp_data = CC_DATA(tp); + + htcp_ssthresh_update(tp); + + /* + * grab the current time and record it so we know when the most recent + * congestion event was + */ + htcp_data->t_last_cong = ticks; + + /* reset rttmax to ensure reductions in the rtt become visible */ + htcp_data->maxrtt = (htcp_data->minrtt + (htcp_data->maxrtt - htcp_data->minrtt) * 95) / 100; + + /* + * record the current cwnd so it can be used as the basis for resetting + * cwnd after exiting fr + */ + htcp_data->prev_cwnd = tp->snd_cwnd; +} + +/* + * Decrease cwnd in the event of packet loss. + */ +void +htcp_post_fr(struct tcpcb *tp, struct tcphdr *th) +{ + u_int cwnd_in_pkts; + struct htcp *htcp_data = CC_DATA(tp); + + /* + * if inflight data is less than ssthresh, set cwnd conservatively to avoid a burst of data, as + * suggested in the NewReno RFC. Otherwise, use the HTCP method. + */ + if (th && SEQ_GT(th->th_ack + tp->snd_ssthresh, tp->snd_max)) + tp->snd_cwnd = tp->snd_max - th->th_ack + tp->t_maxseg; + else + { + /* update cwnd as a function of beta ensure that it never falls below 1 MSS */ + cwnd_in_pkts = htcp_data->prev_cwnd / tp->t_maxseg; + tp->snd_cwnd = max(1,((htcp_data->beta * cwnd_in_pkts) >> HTCP_SHIFT)) * tp->t_maxseg; + } +} + +/* + * Increase cwnd on the arrival of an ACK. + */ +void +htcp_ack_received(struct tcpcb *tp, struct tcphdr *th) +{ + struct htcp *htcp_data = CC_DATA(tp); + u_int cwnd_in_pkts, incr; + + htcp_record_rtt(tp); + htcp_recalc_beta(tp); + htcp_recalc_alpha(tp); + + /* + * when alpha equals 1 or we're in slow-start, fall back to newreno increase function. + * Alpha will equal 1 for the first HTCP_DELTA_L ticks after the flow starts and after congestion + */ + if (htcp_data->alpha == 1 || tp->snd_cwnd < tp->snd_ssthresh) + newreno_ack_received(tp, th); + else + { + /* + * increase cwnd as a function of the alpha value, restricting + * it to the maximum window sized advertised by the other host + * This cap is identical to the one used in the newreno code + */ + cwnd_in_pkts = tp->snd_cwnd / tp->t_maxseg; + incr = (((htcp_data->alpha << HTCP_SHIFT) / cwnd_in_pkts) * tp->t_maxseg) >> HTCP_SHIFT; + tp->snd_cwnd = min(tp->snd_cwnd + incr, TCP_MAXWIN << tp->snd_scale); + } +} + +void +htcp_after_idle(struct tcpcb *tp) +{ + printf("after_idle hook called\n"); + newreno_after_idle(tp); +} + +/* + * Reset the cwnd after a retransmission timeout + */ +void +htcp_after_timeout(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + htcp_ssthresh_update(tp); + + /* + * grab the current time and record it so we know when the most recent + * congestion event was. Only record it when the timeout has fired more + * than once, as there is a reasonable chance the first one is a false alarm + * and may not indicate congestion. + */ + if (tp->t_rxtshift >= 2) + htcp_data->t_last_cong = ticks; + + newreno_after_timeout(tp); +} + +/* + * Update the ssthresh in the event of congestion. + */ +void +htcp_ssthresh_update(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + /* + * on the first congestion event, set ssthresh to cwnd * 0.5, on + * subsequent congestion events, set it to cwnd * beta. + */ + if (tp->snd_ssthresh == TCP_MAXWIN << TCP_MAX_WINSHIFT) + tp->snd_ssthresh = (tp->snd_cwnd * HTCP_MINBETA) >> HTCP_SHIFT; + else + tp->snd_ssthresh = (tp->snd_cwnd * htcp_data->beta) >> HTCP_SHIFT; +} + + +static int +htcp_rtt_scaling_handler(SYSCTL_HANDLER_ARGS) +{ + if(!req->newptr) + goto skip; + + /* if the value passed in isn't 0 or 1, return an error */ + if(CAST_PTR_INT(req->newptr) != 0 && CAST_PTR_INT(req->newptr) != 1) + return 1; + +skip: + return sysctl_handle_int(oidp, arg1, arg2, req); +} + +static int +htcp_adaptive_backoff_handler(SYSCTL_HANDLER_ARGS) +{ + if(!req->newptr) + goto skip; + + /* if the value passed in isn't 0 or 1, return an error */ + if(CAST_PTR_INT(req->newptr) != 0 && CAST_PTR_INT(req->newptr) != 1) + return 1; + +skip: + return sysctl_handle_int(oidp, arg1, arg2, req); +} + +#ifdef HTCP_DEBUG +static int +htcp_debug_ticks_handler(SYSCTL_HANDLER_ARGS) +{ + if(!req->newptr) + goto skip; + + /* if the value passed in is less than 1 */ + if(CAST_PTR_INT(req->newptr) < 1) + return 1; + +skip: + return sysctl_handle_int(oidp, arg1, arg2, req); +} +#endif + +/* + * Init the HTCP module when it is first loaded into the kernel. + * Calls the kernel function for registering a new congestion control + * algorithm + */ +static int +init_module(void) +{ + /* + * the maximum time in ticks after a congestion event before alpha stops + * increasing, due to the risk of overflow. + * see comment above HTCP_CALC_ALPHA for more info + */ + htcp_max_diff = (~((u_long)0)) / ((1 << HTCP_ALPHA_INC_SHIFT) * 10); + + /* + * HTCP_RTT_REF is defined in ms, and t_srtt in the tcpcb is stored in + * units of TCP_RTT_SCALE*hz. + * We perform the following calculation to ensure htcp_rtt_ref + * is in the same units as t_srtt. + */ + htcp_rtt_ref = (HTCP_RTT_REF * TCP_RTT_SCALE * hz) / 1000; + +#ifdef HTCP_DEBUG + /* set the default debug interval to 1 second */ + htcp_debug_ticks = hz; +#endif + + /* add htcp to the list of available algorithms */ + cc_register_algorithm(&htcp_cc_algo); + + uprintf("Loaded: %s v%s\n", MODNAME, MODVERSION); + + return 0; +} + +/* + * Called when the module is unloaded from the kernel. + */ +static int +deinit_module(void) +{ + cc_deregister_algorithm(&htcp_cc_algo); + + uprintf("Unloaded: %s v%s\n", MODNAME, MODVERSION); + + return 0; +} + +/* + * Tell the kernel which functions to use to init and de-init the module. + */ +static int +htcp_load_handler(module_t mod, int what, void *arg) +{ + switch(what) { + case MOD_LOAD: + return init_module(); + break; + + case MOD_QUIESCE: + case MOD_SHUTDOWN: + return deinit_module(); + break; + + case MOD_UNLOAD: + return 0; + break; + + default: + return EINVAL; + break; + } +} + +/* a struct that holds basic data on the module */ +static moduledata_t htcp_mod = +{ + "htcp", /* module's name */ + htcp_load_handler, /* execution entry point for the module */ + NULL +}; + +DECLARE_MODULE(htcp, htcp_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); + +SYSCTL_DECL(_net_inet_tcp_cc_htcp); +SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, htcp, CTLFLAG_RW, NULL, "H-TCP related settings"); +SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, rtt_scaling, CTLTYPE_UINT|CTLFLAG_RW, &htcp_rtt_scaling, 0, &htcp_rtt_scaling_handler, "IU", "switch H-TCP RTT scaling on/off"); +SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, adaptive_backoff, CTLTYPE_UINT|CTLFLAG_RW, &htcp_adaptive_backoff, 0, &htcp_adaptive_backoff_handler, "IU", "switch H-TCP adaptive backoff on/off"); + +#ifdef HTCP_DEBUG +SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, debug_ticks, CTLTYPE_UINT|CTLFLAG_RW, &htcp_debug_ticks, 0, &htcp_debug_ticks_handler, "IU", "set the approximate number of ticks between printing debug messages to syslog"); +#endif From owner-svn-src-projects@FreeBSD.ORG Wed Oct 22 01:13:32 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 290191065670; Wed, 22 Oct 2008 01:13:32 +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 1782F8FC24; Wed, 22 Oct 2008 01:13:32 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9M1DVJm013292; Wed, 22 Oct 2008 01:13:31 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9M1DVKe013290; Wed, 22 Oct 2008 01:13:31 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810220113.m9M1DVKe013290@svn.freebsd.org> From: Lawrence Stewart Date: Wed, 22 Oct 2008 01:13:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184149 - projects/tcp_cc_8.x/sys/netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 01:13:32 -0000 Author: lstewart Date: Wed Oct 22 01:13:31 2008 New Revision: 184149 URL: http://svn.freebsd.org/changeset/base/184149 Log: Fix a bug I just noticed in the way the TCP_CONGESTION getsockopt() code worked. memcpy() had the args around the wrong way and was the wrong thing to use there anyway. Also switch the other strncpy use in the patch over to strlcpy whilst I'm at it. Modified: projects/tcp_cc_8.x/sys/netinet/cc.c projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c Modified: projects/tcp_cc_8.x/sys/netinet/cc.c ============================================================================== --- projects/tcp_cc_8.x/sys/netinet/cc.c Wed Oct 22 00:22:32 2008 (r184148) +++ projects/tcp_cc_8.x/sys/netinet/cc.c Wed Oct 22 01:13:31 2008 (r184149) @@ -164,7 +164,7 @@ cc_init() cc_register_algorithm(&newreno_cc_algo); /* set newreno to the system default */ - strncpy(cc_algorithm, newreno_cc_algo.name, sizeof(cc_algorithm)); + strlcpy(cc_algorithm, newreno_cc_algo.name, TCP_CA_NAME_MAX); } /* Modified: projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c ============================================================================== --- projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c Wed Oct 22 00:22:32 2008 (r184148) +++ projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c Wed Oct 22 01:13:31 2008 (r184149) @@ -1490,7 +1490,7 @@ tcp_ctloutput(struct socket *so, struct break; case TCP_CONGESTION: bzero(buf, sizeof(buf)); - memcpy(&(CC_ALGO(tp)->name), buf, TCP_CA_NAME_MAX); + strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX); INP_WUNLOCK(inp); error = sooptcopyout(sopt, buf, TCP_CA_NAME_MAX); break; From owner-svn-src-projects@FreeBSD.ORG Wed Oct 22 01:50:36 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 38E9A106567D; Wed, 22 Oct 2008 01:50:36 +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 254AB8FC28; Wed, 22 Oct 2008 01:50:36 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9M1oaDM013974; Wed, 22 Oct 2008 01:50:36 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9M1oZGK013969; Wed, 22 Oct 2008 01:50:35 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810220150.m9M1oZGK013969@svn.freebsd.org> From: Lawrence Stewart Date: Wed, 22 Oct 2008 01:50:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184150 - in projects/tcp_cc_7.x/sys: . conf modules modules/cc_htcp netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 01:50:36 -0000 Author: lstewart Date: Wed Oct 22 01:50:35 2008 New Revision: 184150 URL: http://svn.freebsd.org/changeset/base/184150 Log: Merge r184148 and r184149 from tcp_cc_8.x Added: projects/tcp_cc_7.x/sys/modules/cc_htcp/ - copied from r184148, projects/tcp_cc_8.x/sys/modules/cc_htcp/ projects/tcp_cc_7.x/sys/netinet/cc_htcp.c - copied unchanged from r184148, projects/tcp_cc_8.x/sys/netinet/cc_htcp.c Modified: projects/tcp_cc_7.x/sys/ (props changed) projects/tcp_cc_7.x/sys/conf/files projects/tcp_cc_7.x/sys/modules/Makefile projects/tcp_cc_7.x/sys/netinet/cc.c projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c Modified: projects/tcp_cc_7.x/sys/conf/files ============================================================================== --- projects/tcp_cc_7.x/sys/conf/files Wed Oct 22 01:13:31 2008 (r184149) +++ projects/tcp_cc_7.x/sys/conf/files Wed Oct 22 01:50:35 2008 (r184150) @@ -1795,6 +1795,7 @@ netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/cc.c optional inet +netinet/cc_htcp.c optional inet netinet/sctp_asconf.c optional inet sctp netinet/sctp_auth.c optional inet sctp netinet/sctp_bsd_addr.c optional inet sctp Modified: projects/tcp_cc_7.x/sys/modules/Makefile ============================================================================== --- projects/tcp_cc_7.x/sys/modules/Makefile Wed Oct 22 01:13:31 2008 (r184149) +++ projects/tcp_cc_7.x/sys/modules/Makefile Wed Oct 22 01:50:35 2008 (r184150) @@ -47,6 +47,7 @@ SUBDIR= ${_3dfx} \ ${_canbus} \ ${_cardbus} \ ${_cbb} \ + cc_htcp \ cd9660 \ cd9660_iconv \ cdce \ Modified: projects/tcp_cc_7.x/sys/netinet/cc.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/cc.c Wed Oct 22 01:13:31 2008 (r184149) +++ projects/tcp_cc_7.x/sys/netinet/cc.c Wed Oct 22 01:50:35 2008 (r184150) @@ -164,7 +164,7 @@ cc_init() cc_register_algorithm(&newreno_cc_algo); /* set newreno to the system default */ - strncpy(cc_algorithm, newreno_cc_algo.name, sizeof(cc_algorithm)); + strlcpy(cc_algorithm, newreno_cc_algo.name, TCP_CA_NAME_MAX); } /* Copied: projects/tcp_cc_7.x/sys/netinet/cc_htcp.c (from r184148, projects/tcp_cc_8.x/sys/netinet/cc_htcp.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/tcp_cc_7.x/sys/netinet/cc_htcp.c Wed Oct 22 01:50:35 2008 (r184150, copy of r184148, projects/tcp_cc_8.x/sys/netinet/cc_htcp.c) @@ -0,0 +1,623 @@ +/*- + * Copyright (c) 2008 Swinburne University of Technology, Melbourne, Australia + * All rights reserved. + * + * This software was developed at the Centre for Advanced Internet + * Architectures, Swinburne University, by Lawrence Stewart and James Healy, + * made possible in part by a grant from the Cisco University Research Program + * Fund at Community Foundation Silicon Valley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * HTCP + * + * An implementation of HTCP congestion algorithm for FreeBSD 7.0 + * The algorithm is based on the one described in "H-TCP: A framework + * for congestion control in high-speed and long-distance networks" by + * Leith, Shorten and Lee. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* useful defines */ +#define MODNAME "HTCP congestion control" +#define MODVERSION "0.9.1" +#define HTCP_SHIFT 8 +#define HTCP_ALPHA_INC_SHIFT 4 +#define HTCP_INIT_ALPHA 1 +#define HTCP_DELTA_L hz /* 1 sec in ticks */ +#define HTCP_MINBETA 128 /* 0.5 with a shift << 8 */ +#define HTCP_MAXBETA 204 /* ~0.8 with a shift << 8 */ +#define HTCP_MINROWE 26 /* ~0.1 with a shift << 8 */ +#define HTCP_MAXROWE 512 /* 2 with a shift << 8 */ +#define HTCP_RTT_REF 100 /* reference RTT in milliseconds used in the calculation of */ + /* alpha if htcp_rtt_scaling=1 */ +#define HTCP_MIN_RTT_SAMPLES 8 /* don't trust the TCP stack's smoothed rtt estimate */ + /* until this many samples have been taken */ +#define CAST_PTR_INT(X) (*((int*)(X))) + +/* + * HTCP_CALC_ALPHA performs a fixed point math calculation to + * determine the value of alpha, based on the function defined in + * H-TCP: A framework for congestion control in high-speed and long distance networks" + * + * i.e. 1 + 10(delta - delta_l) + ((delta - delta_l) / 2) ^ 2 + * + * "diff" is passed in to the macro as "delta - delta_l" and is + * expected to be in units of ticks. + * + * The joyousnous of fixed point maths means our function implementation + * looks a little funky... + * + * In order to maintain some precision in the calculations, a fixed point + * shift HTCP_ALPHA_INC_SHIFT is used to ensure the integer divisions don't + * truncate the results too badly. + * + * The "16" value is the "1" term in the alpha function shifted up by HTCP_ALPHA_INC_SHIFT + * + * The "160" value is the "10" multiplier in the alpha function multiplied by 2^HTCP_ALPHA_INC_SHIFT + * + * Specifying these as constants reduces the computations required. + * After up-shifting all the terms in the function and performing the + * required calculations, we down-shift the final result by + * HTCP_ALPHA_INC_SHIFT to ensure it is back in the correct range. + * + * The "hz" terms are required as kernels can be configured to run + * with different tick timers, which we have to adjust for in the + * alpha calculation (which originally was defined in terms of seconds). + * + * We also have to be careful to constrain the value of diff such that it + * won't overflow whilst performing the calculation. The middle term i.e. + * (160 * diff) / hz is the limiting factor in the calculation. We must + * constrain diff to be less than the max size of an unsigned long divided + * by the constant 160 figure i.e. + * diff < [(2 ^ (sizeof(u_long) * 8)) - 1] / 160 + * + * NB: Changing HTCP_ALPHA_INC_SHIFT will require you to MANUALLY update + * the constants used in this function! + */ +#define HTCP_CALC_ALPHA(diff) \ +(\ + (\ + (16) + \ + ((160 * (diff)) / hz) + \ + (((diff) / hz) * (((diff) << HTCP_ALPHA_INC_SHIFT) / (4 * hz))) \ + ) >> HTCP_ALPHA_INC_SHIFT \ +) + +/* function prototypes */ +int htcp_init(struct tcpcb *tp); +void htcp_deinit(struct tcpcb *tp); +void htcp_recalc_alpha(struct tcpcb *tp); +void htcp_recalc_beta(struct tcpcb *tp); +void htcp_pre_fr(struct tcpcb *tp, struct tcphdr *th); +void htcp_post_fr(struct tcpcb *tp, struct tcphdr *th); +void htcp_ack_received(struct tcpcb *tp, struct tcphdr *th); +void htcp_after_timeout(struct tcpcb *tp); +void htcp_after_idle(struct tcpcb *tp); +void htcp_ssthresh_update(struct tcpcb *tp); +void htcp_record_rtt(struct tcpcb *tp); + +struct htcp { + u_int alpha; /* alpha param, used for cwnd increase */ + u_int beta; /* beta param, used for cwnd increase and decreade */ + u_long prev_cwnd; /* the value of cwnd before entering fast recovery */ + /* used when setting the cwnd after exiting FR */ + u_long t_last_cong; /* time of last congestion event in ticks */ + u_int minrtt; /* the shortest rtt seen for a flow */ + u_int maxrtt; /* the largest rtt seen for a flow */ +}; + +static u_long htcp_max_diff; +static u_int htcp_rtt_scaling = 0; +static u_int htcp_adaptive_backoff = 0; +static u_int htcp_rtt_ref; + +#ifdef HTCP_DEBUG +static u_int htcp_debug_ticks = 1000; +#endif + +MALLOC_DECLARE(M_HTCP); +MALLOC_DEFINE(M_HTCP, "htcp data", "Per connection data required for the HTCP congestion algorithm"); + +/* function pointers for various hooks into the TCP stack */ +struct cc_algo htcp_cc_algo = { + .name = "htcp", + .init = htcp_init, + .deinit = htcp_deinit, + .cwnd_init = newreno_cwnd_init, + .ack_received = htcp_ack_received, + .pre_fr = htcp_pre_fr, + .post_fr = htcp_post_fr, + .after_idle = htcp_after_idle, + .after_timeout = htcp_after_timeout +}; + +/* + * Initialise HTCP on the specified TCP control block. Creates a + * new struct for HTCP specific data and sticks a pointer to it + * in the control block + */ +int +htcp_init(struct tcpcb *tp) +{ + struct htcp *htcp_data; + +#ifdef HTCP_DEBUG + printf("initialising tcp connection with htcp congestion control\n"); +#endif + + MALLOC(htcp_data, struct htcp *, sizeof(struct htcp), M_HTCP, M_NOWAIT); + + if (htcp_data == NULL) + return 1; + + /* init some key htcp values with sensible defaults */ + htcp_data->alpha = HTCP_INIT_ALPHA; + htcp_data->beta = HTCP_MINBETA; + htcp_data->t_last_cong = ticks; + htcp_data->prev_cwnd = 0; + htcp_data->minrtt = TCPTV_SRTTBASE; + htcp_data->maxrtt = TCPTV_SRTTBASE; + + CC_DATA(tp) = htcp_data; + + return 0; +} + +/* + * Free the struct used to store HTCP specific data for the specified + * TCP control block. + */ +void +htcp_deinit(struct tcpcb *tp) +{ +#ifdef HTCP_DEBUG + printf("deinitialising tcp connection with htcp congestion control\n"); +#endif + + if (CC_DATA(tp)) + FREE(CC_DATA(tp), M_HTCP); +} + +/* + * Recalculate the alpha value used for scaling cwnd up. + * This is currently called once for each ACK that is received. + */ +void +htcp_recalc_alpha(struct tcpcb *tp) +{ + u_int alpha, now; + struct htcp *htcp_data = CC_DATA(tp); + u_long delta = 0, diff = 0; + +#ifdef HTCP_DEBUG + static u_int debug_counter = 0; +#endif + + now = ticks; + + /* + * if ticks has wrapped around (will happen approximately once + * every 49 days on a machine running at 1000hz) and a flow straddles + * the wrap point, our alpha calcs will be completely wrong. + * We cut our losses and restart alpha from scratch + * by setting t_last_cong = now + delta_l + * + * This does not deflate our cwnd at all. It simply slows the rate + * cwnd is growing by until alpha regains the value it held + * prior to taking this drastic measure. + */ + if (now < htcp_data->t_last_cong) + htcp_data->t_last_cong = now + HTCP_DELTA_L; + + delta = now - htcp_data->t_last_cong; + + /* + * if its been less than HTCP_DELTA_L ticks since congestion, + * set alpha to 1. Otherwise, use the function defined in + * the key HTCP paper + */ + if (delta < HTCP_DELTA_L) + htcp_data->alpha = 1; + + else if ((diff = delta - HTCP_DELTA_L) < htcp_max_diff) + { + alpha = HTCP_CALC_ALPHA(diff); + + /* Adaptive backoff fairness adjustment: 2 * (1 - beta) * alpha_raw */ + if(htcp_adaptive_backoff) + alpha = max(1, (2 * ((1 << HTCP_SHIFT) - htcp_data->beta) * alpha) >> HTCP_SHIFT); + + /* + * RTT scaling: (RTT / RTT_ref) * alpha_raw + * alpha will be the raw value from HTCP_CALC_ALPHA() if adaptive backoff + * is off, or the adjusted value if adaptive backoff is on + */ + if(htcp_rtt_scaling) + alpha = max(1, (min(max(HTCP_MINROWE, (tp->t_srtt << HTCP_SHIFT) / htcp_rtt_ref), HTCP_MAXROWE) * alpha) >> HTCP_SHIFT); + + htcp_data->alpha = alpha; + } + + +#ifdef HTCP_DEBUG + /* print out a debug message to syslog periodically */ + if(ticks - debug_counter > htcp_debug_ticks) + { + debug_counter = ticks; + + printf("alpha: %-4u salpha: %-4u beta: %-4d t_last_cong: %-10u delta: %-6u cwnd: %-7u min|max rtt: %5u|%-5u rtt|rtt_ref: %5u|%-5u\n", + (unsigned int)HTCP_CALC_ALPHA(diff), + htcp_data->alpha, + htcp_data->beta, + (unsigned int)htcp_data->t_last_cong, + (unsigned int)delta, + (unsigned int)tp->snd_cwnd, + htcp_data->minrtt, + htcp_data->maxrtt, + tp->t_srtt, + htcp_rtt_ref + ); + } +#endif +} + +/* + * Recalculate the beta value used for scaling cwnd up and down. + * This is currently called once for each ACK that is received + */ +void +htcp_recalc_beta(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + /* + * beta is stored as a fixed point number instead of floating point for + * efficiency reasons. The decimal point is moved 1 byte to the left, + * allowing for a 3 byte whole number and 1 byte fractional + * + * any time a number is multiplied or divided by beta, the answer must be right + * shifted by a byte to get the real answer + * + * beta is bounded to ensure it is always between HTCP_MINBETA and HTCP_MAXBETA + */ + + /* + * TCPTV_SRTTBASE is the initialised value of each connection's srtt, so we only + * calc beta if the connection's srtt has been changed from its inital value + */ + if (htcp_adaptive_backoff && htcp_data->minrtt != TCPTV_SRTTBASE && htcp_data->maxrtt != TCPTV_SRTTBASE) + htcp_data->beta = min(max(HTCP_MINBETA, (htcp_data->minrtt << HTCP_SHIFT) / htcp_data->maxrtt), HTCP_MAXBETA); + else + htcp_data->beta = HTCP_MINBETA; +} + +/* + * Record the minimum and maximum RTT seen on the connection. + * These are used in the calculation of beta if adaptive backoff is enabled. + */ +void +htcp_record_rtt(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + /* TODO: Should there be some hysteresis for minrtt? */ + + /* + * record the current SRTT as our minrtt if it's the smalelst we've + * seen or minrtt is currently equal to its initialised value. + * Ignore srtt until a min number of samples have been taken + */ + if ((tp->t_srtt < htcp_data->minrtt || htcp_data->minrtt == TCPTV_SRTTBASE) && (tp->t_rttupdated >= HTCP_MIN_RTT_SAMPLES)) + htcp_data->minrtt = tp->t_srtt; + + /* + * record the current SRTT as our maxrtt if it's the largest we've + * seen. + * Ignore srtt until a min number of samples have been taken + */ + if (tp->t_srtt > htcp_data->maxrtt && tp->t_rttupdated >= HTCP_MIN_RTT_SAMPLES) + htcp_data->maxrtt = tp->t_srtt; +} + +/* + * Perform any necesary tasks before we enter fast recovery + */ +void +htcp_pre_fr(struct tcpcb *tp, struct tcphdr *th) +{ + struct htcp *htcp_data = CC_DATA(tp); + + htcp_ssthresh_update(tp); + + /* + * grab the current time and record it so we know when the most recent + * congestion event was + */ + htcp_data->t_last_cong = ticks; + + /* reset rttmax to ensure reductions in the rtt become visible */ + htcp_data->maxrtt = (htcp_data->minrtt + (htcp_data->maxrtt - htcp_data->minrtt) * 95) / 100; + + /* + * record the current cwnd so it can be used as the basis for resetting + * cwnd after exiting fr + */ + htcp_data->prev_cwnd = tp->snd_cwnd; +} + +/* + * Decrease cwnd in the event of packet loss. + */ +void +htcp_post_fr(struct tcpcb *tp, struct tcphdr *th) +{ + u_int cwnd_in_pkts; + struct htcp *htcp_data = CC_DATA(tp); + + /* + * if inflight data is less than ssthresh, set cwnd conservatively to avoid a burst of data, as + * suggested in the NewReno RFC. Otherwise, use the HTCP method. + */ + if (th && SEQ_GT(th->th_ack + tp->snd_ssthresh, tp->snd_max)) + tp->snd_cwnd = tp->snd_max - th->th_ack + tp->t_maxseg; + else + { + /* update cwnd as a function of beta ensure that it never falls below 1 MSS */ + cwnd_in_pkts = htcp_data->prev_cwnd / tp->t_maxseg; + tp->snd_cwnd = max(1,((htcp_data->beta * cwnd_in_pkts) >> HTCP_SHIFT)) * tp->t_maxseg; + } +} + +/* + * Increase cwnd on the arrival of an ACK. + */ +void +htcp_ack_received(struct tcpcb *tp, struct tcphdr *th) +{ + struct htcp *htcp_data = CC_DATA(tp); + u_int cwnd_in_pkts, incr; + + htcp_record_rtt(tp); + htcp_recalc_beta(tp); + htcp_recalc_alpha(tp); + + /* + * when alpha equals 1 or we're in slow-start, fall back to newreno increase function. + * Alpha will equal 1 for the first HTCP_DELTA_L ticks after the flow starts and after congestion + */ + if (htcp_data->alpha == 1 || tp->snd_cwnd < tp->snd_ssthresh) + newreno_ack_received(tp, th); + else + { + /* + * increase cwnd as a function of the alpha value, restricting + * it to the maximum window sized advertised by the other host + * This cap is identical to the one used in the newreno code + */ + cwnd_in_pkts = tp->snd_cwnd / tp->t_maxseg; + incr = (((htcp_data->alpha << HTCP_SHIFT) / cwnd_in_pkts) * tp->t_maxseg) >> HTCP_SHIFT; + tp->snd_cwnd = min(tp->snd_cwnd + incr, TCP_MAXWIN << tp->snd_scale); + } +} + +void +htcp_after_idle(struct tcpcb *tp) +{ + printf("after_idle hook called\n"); + newreno_after_idle(tp); +} + +/* + * Reset the cwnd after a retransmission timeout + */ +void +htcp_after_timeout(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + htcp_ssthresh_update(tp); + + /* + * grab the current time and record it so we know when the most recent + * congestion event was. Only record it when the timeout has fired more + * than once, as there is a reasonable chance the first one is a false alarm + * and may not indicate congestion. + */ + if (tp->t_rxtshift >= 2) + htcp_data->t_last_cong = ticks; + + newreno_after_timeout(tp); +} + +/* + * Update the ssthresh in the event of congestion. + */ +void +htcp_ssthresh_update(struct tcpcb *tp) +{ + struct htcp *htcp_data = CC_DATA(tp); + + /* + * on the first congestion event, set ssthresh to cwnd * 0.5, on + * subsequent congestion events, set it to cwnd * beta. + */ + if (tp->snd_ssthresh == TCP_MAXWIN << TCP_MAX_WINSHIFT) + tp->snd_ssthresh = (tp->snd_cwnd * HTCP_MINBETA) >> HTCP_SHIFT; + else + tp->snd_ssthresh = (tp->snd_cwnd * htcp_data->beta) >> HTCP_SHIFT; +} + + +static int +htcp_rtt_scaling_handler(SYSCTL_HANDLER_ARGS) +{ + if(!req->newptr) + goto skip; + + /* if the value passed in isn't 0 or 1, return an error */ + if(CAST_PTR_INT(req->newptr) != 0 && CAST_PTR_INT(req->newptr) != 1) + return 1; + +skip: + return sysctl_handle_int(oidp, arg1, arg2, req); +} + +static int +htcp_adaptive_backoff_handler(SYSCTL_HANDLER_ARGS) +{ + if(!req->newptr) + goto skip; + + /* if the value passed in isn't 0 or 1, return an error */ + if(CAST_PTR_INT(req->newptr) != 0 && CAST_PTR_INT(req->newptr) != 1) + return 1; + +skip: + return sysctl_handle_int(oidp, arg1, arg2, req); +} + +#ifdef HTCP_DEBUG +static int +htcp_debug_ticks_handler(SYSCTL_HANDLER_ARGS) +{ + if(!req->newptr) + goto skip; + + /* if the value passed in is less than 1 */ + if(CAST_PTR_INT(req->newptr) < 1) + return 1; + +skip: + return sysctl_handle_int(oidp, arg1, arg2, req); +} +#endif + +/* + * Init the HTCP module when it is first loaded into the kernel. + * Calls the kernel function for registering a new congestion control + * algorithm + */ +static int +init_module(void) +{ + /* + * the maximum time in ticks after a congestion event before alpha stops + * increasing, due to the risk of overflow. + * see comment above HTCP_CALC_ALPHA for more info + */ + htcp_max_diff = (~((u_long)0)) / ((1 << HTCP_ALPHA_INC_SHIFT) * 10); + + /* + * HTCP_RTT_REF is defined in ms, and t_srtt in the tcpcb is stored in + * units of TCP_RTT_SCALE*hz. + * We perform the following calculation to ensure htcp_rtt_ref + * is in the same units as t_srtt. + */ + htcp_rtt_ref = (HTCP_RTT_REF * TCP_RTT_SCALE * hz) / 1000; + +#ifdef HTCP_DEBUG + /* set the default debug interval to 1 second */ + htcp_debug_ticks = hz; +#endif + + /* add htcp to the list of available algorithms */ + cc_register_algorithm(&htcp_cc_algo); + + uprintf("Loaded: %s v%s\n", MODNAME, MODVERSION); + + return 0; +} + +/* + * Called when the module is unloaded from the kernel. + */ +static int +deinit_module(void) +{ + cc_deregister_algorithm(&htcp_cc_algo); + + uprintf("Unloaded: %s v%s\n", MODNAME, MODVERSION); + + return 0; +} + +/* + * Tell the kernel which functions to use to init and de-init the module. + */ +static int +htcp_load_handler(module_t mod, int what, void *arg) +{ + switch(what) { + case MOD_LOAD: + return init_module(); + break; + + case MOD_QUIESCE: + case MOD_SHUTDOWN: + return deinit_module(); + break; + + case MOD_UNLOAD: + return 0; + break; + + default: + return EINVAL; + break; + } +} + +/* a struct that holds basic data on the module */ +static moduledata_t htcp_mod = +{ + "htcp", /* module's name */ + htcp_load_handler, /* execution entry point for the module */ + NULL +}; + +DECLARE_MODULE(htcp, htcp_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); + +SYSCTL_DECL(_net_inet_tcp_cc_htcp); +SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, htcp, CTLFLAG_RW, NULL, "H-TCP related settings"); +SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, rtt_scaling, CTLTYPE_UINT|CTLFLAG_RW, &htcp_rtt_scaling, 0, &htcp_rtt_scaling_handler, "IU", "switch H-TCP RTT scaling on/off"); +SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, adaptive_backoff, CTLTYPE_UINT|CTLFLAG_RW, &htcp_adaptive_backoff, 0, &htcp_adaptive_backoff_handler, "IU", "switch H-TCP adaptive backoff on/off"); + +#ifdef HTCP_DEBUG +SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, debug_ticks, CTLTYPE_UINT|CTLFLAG_RW, &htcp_debug_ticks, 0, &htcp_debug_ticks_handler, "IU", "set the approximate number of ticks between printing debug messages to syslog"); +#endif Modified: projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c Wed Oct 22 01:13:31 2008 (r184149) +++ projects/tcp_cc_7.x/sys/netinet/tcp_usrreq.c Wed Oct 22 01:50:35 2008 (r184150) @@ -1470,7 +1470,7 @@ tcp_ctloutput(struct socket *so, struct break; case TCP_CONGESTION: bzero(buf, sizeof(buf)); - memcpy(&(CC_ALGO(tp)->name), buf, TCP_CA_NAME_MAX); + strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX); INP_WUNLOCK(inp); error = sooptcopyout(sopt, buf, TCP_CA_NAME_MAX); break; From owner-svn-src-projects@FreeBSD.ORG Wed Oct 22 07:06:39 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2C333106567D; Wed, 22 Oct 2008 07:06:39 +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 1B02E8FC0C; Wed, 22 Oct 2008 07:06:39 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9M76cGL021743; Wed, 22 Oct 2008 07:06:38 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9M76cnS021741; Wed, 22 Oct 2008 07:06:38 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810220706.m9M76cnS021741@svn.freebsd.org> From: Lawrence Stewart Date: Wed, 22 Oct 2008 07:06:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184152 - projects/tcp_cc_8.x/sys/netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 07:06:39 -0000 Author: lstewart Date: Wed Oct 22 07:06:38 2008 New Revision: 184152 URL: http://svn.freebsd.org/changeset/base/184152 Log: Move a comment from tcp_input() into the modular cc code and fold in the New Reno cwnd fix from r182885 that I'd forgotten about. Modified: projects/tcp_cc_8.x/sys/netinet/cc.c projects/tcp_cc_8.x/sys/netinet/tcp_input.c Modified: projects/tcp_cc_8.x/sys/netinet/cc.c ============================================================================== --- projects/tcp_cc_8.x/sys/netinet/cc.c Wed Oct 22 02:08:54 2008 (r184151) +++ projects/tcp_cc_8.x/sys/netinet/cc.c Wed Oct 22 07:06:38 2008 (r184152) @@ -333,8 +333,15 @@ newreno_ack_received(struct tcpcb *tp, s u_int cw = tp->snd_cwnd; u_int incr = tp->t_maxseg; + /* + * If cwnd <= ssthresh, open exponentially (maxseg per packet). + * Otherwise, open linearly (approx. maxseg per RTT + * i.e. maxseg^2 / cwnd per ACK received). + * If cwnd > maxseg^2, fix the cwnd increment at 1 byte + * to avoid capping cwnd (as suggested in RFC2581). + */ if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; + incr = max((incr * incr / cw), 1); tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<snd_scale); } Modified: projects/tcp_cc_8.x/sys/netinet/tcp_input.c ============================================================================== --- projects/tcp_cc_8.x/sys/netinet/tcp_input.c Wed Oct 22 02:08:54 2008 (r184151) +++ projects/tcp_cc_8.x/sys/netinet/tcp_input.c Wed Oct 22 07:06:38 2008 (r184152) @@ -2093,12 +2093,8 @@ process_ACK: /* * When new data is acked, open the congestion window. - * If the window gives us less than ssthresh packets - * in flight, open exponentially (maxseg per packet). - * Otherwise open linearly: maxseg per window - * (maxseg^2 / cwnd per packet). - * If cwnd > maxseg^2, fix the cwnd increment at 1 byte - * to avoid capping cwnd (as suggested in RFC2581). + * The specifics of how this is achieved are up to the + * congestion control algorithm in use for this connection. */ if (!IN_FASTRECOVERY(tp)) { if (CC_ALGO(tp)->ack_received) From owner-svn-src-projects@FreeBSD.ORG Wed Oct 22 07:21:02 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8D5031065679; Wed, 22 Oct 2008 07:21:02 +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 7BC588FC2B; Wed, 22 Oct 2008 07:21:02 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9M7L2en022020; Wed, 22 Oct 2008 07:21:02 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9M7L21L022018; Wed, 22 Oct 2008 07:21:02 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200810220721.m9M7L21L022018@svn.freebsd.org> From: Lawrence Stewart Date: Wed, 22 Oct 2008 07:21:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184153 - in projects/tcp_cc_7.x/sys: . netinet X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 07:21:02 -0000 Author: lstewart Date: Wed Oct 22 07:21:02 2008 New Revision: 184153 URL: http://svn.freebsd.org/changeset/base/184153 Log: Merge r184152 from tcp_cc_8.x Modified: projects/tcp_cc_7.x/sys/ (props changed) projects/tcp_cc_7.x/sys/netinet/cc.c projects/tcp_cc_7.x/sys/netinet/tcp_input.c Modified: projects/tcp_cc_7.x/sys/netinet/cc.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/cc.c Wed Oct 22 07:06:38 2008 (r184152) +++ projects/tcp_cc_7.x/sys/netinet/cc.c Wed Oct 22 07:21:02 2008 (r184153) @@ -333,8 +333,15 @@ newreno_ack_received(struct tcpcb *tp, s u_int cw = tp->snd_cwnd; u_int incr = tp->t_maxseg; + /* + * If cwnd <= ssthresh, open exponentially (maxseg per packet). + * Otherwise, open linearly (approx. maxseg per RTT + * i.e. maxseg^2 / cwnd per ACK received). + * If cwnd > maxseg^2, fix the cwnd increment at 1 byte + * to avoid capping cwnd (as suggested in RFC2581). + */ if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; + incr = max((incr * incr / cw), 1); tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<snd_scale); } Modified: projects/tcp_cc_7.x/sys/netinet/tcp_input.c ============================================================================== --- projects/tcp_cc_7.x/sys/netinet/tcp_input.c Wed Oct 22 07:06:38 2008 (r184152) +++ projects/tcp_cc_7.x/sys/netinet/tcp_input.c Wed Oct 22 07:21:02 2008 (r184153) @@ -2002,12 +2002,8 @@ process_ACK: /* * When new data is acked, open the congestion window. - * If the window gives us less than ssthresh packets - * in flight, open exponentially (maxseg per packet). - * Otherwise open linearly: maxseg per window - * (maxseg^2 / cwnd per packet). - * If cwnd > maxseg^2, fix the cwnd increment at 1 byte - * to avoid capping cwnd (as suggested in RFC2581). + * The specifics of how this is achieved are up to the + * congestion control algorithm in use for this connection. */ if (!IN_FASTRECOVERY(tp)) { if (CC_ALGO(tp)->ack_received) From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 00:25:26 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A3E69106566C; Sat, 25 Oct 2008 00:25:26 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 90F6A8FC1B; Sat, 25 Oct 2008 00:25:26 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9P0PQ1l002748; Sat, 25 Oct 2008 00:25:26 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9P0PQnP002735; Sat, 25 Oct 2008 00:25:26 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200810250025.m9P0PQnP002735@svn.freebsd.org> From: Kip Macy Date: Sat, 25 Oct 2008 00:25:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184235 - in projects/releng_6_xen/sys: conf i386/i386 i386/include i386/include/xen i386/xen xen/evtchn X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 00:25:26 -0000 Author: kmacy Date: Sat Oct 25 00:25:25 2008 New Revision: 184235 URL: http://svn.freebsd.org/changeset/base/184235 Log: Merge basic SMP support from HEAD Modified: projects/releng_6_xen/sys/conf/files.i386 projects/releng_6_xen/sys/i386/i386/apic_vector.s projects/releng_6_xen/sys/i386/include/apicvar.h projects/releng_6_xen/sys/i386/include/pcpu.h projects/releng_6_xen/sys/i386/include/smp.h projects/releng_6_xen/sys/i386/include/xen/evtchn.h projects/releng_6_xen/sys/i386/include/xen/xen-os.h projects/releng_6_xen/sys/i386/include/xen/xen_intr.h projects/releng_6_xen/sys/i386/include/xen/xenfunc.h projects/releng_6_xen/sys/i386/xen/clock.c projects/releng_6_xen/sys/i386/xen/exception.s projects/releng_6_xen/sys/i386/xen/mp_machdep.c projects/releng_6_xen/sys/xen/evtchn/evtchn.c Modified: projects/releng_6_xen/sys/conf/files.i386 ============================================================================== --- projects/releng_6_xen/sys/conf/files.i386 Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/conf/files.i386 Sat Oct 25 00:25:25 2008 (r184235) @@ -326,7 +326,8 @@ i386/i386/mp_machdep.c optional native i386/xen/mp_machdep.c optional xen smp i386/i386/mp_watchdog.c optional mp_watchdog smp i386/i386/mpboot.s optional native smp -i386/i386/mptable.c optional apic +i386/xen/mptable.c optional apic xen +i386/i386/mptable.c optional apic native i386/i386/mptable_pci.c optional apic pci i386/i386/msi.c optional apic pci i386/i386/nexus.c standard Modified: projects/releng_6_xen/sys/i386/i386/apic_vector.s ============================================================================== --- projects/releng_6_xen/sys/i386/i386/apic_vector.s Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/i386/apic_vector.s Sat Oct 25 00:25:25 2008 (r184235) @@ -299,6 +299,7 @@ IDTVEC(invlcache) /* * Handler for IPIs sent via the per-cpu IPI bitmap. */ +#ifndef XEN .text SUPERALIGN_TEXT IDTVEC(ipi_intr_bitmap_handler) @@ -320,7 +321,7 @@ IDTVEC(ipi_intr_bitmap_handler) addl $4, %esp /* XXX convert clockframe to trapframe */ MEXITCOUNT jmp doreti - +#endif /* * Executed by a CPU when it receives an Xcpustop IPI from another CPU, * Modified: projects/releng_6_xen/sys/i386/include/apicvar.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/apicvar.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/apicvar.h Sat Oct 25 00:25:25 2008 (r184235) @@ -113,6 +113,17 @@ #define APIC_THERMAL_INT (APIC_LOCAL_INTS + 1) #define APIC_IPI_INTS (APIC_LOCAL_INTS + 2) +#ifdef XEN +#define IPI_RENDEZVOUS (2) /* Inter-CPU rendezvous. */ +#define IPI_INVLTLB (3) /* TLB Shootdown IPIs */ +#define IPI_INVLPG (4) +#define IPI_INVLRNG (5) +#define IPI_INVLCACHE (6) +#define IPI_LAZYPMAP (7) /* Lazy pmap release. */ +/* Vector to handle bitmap based IPIs */ +#define IPI_BITMAP_VECTOR (8) + +#else #define IPI_RENDEZVOUS (APIC_IPI_INTS) /* Inter-CPU rendezvous. */ #define IPI_INVLTLB (APIC_IPI_INTS + 1) /* TLB Shootdown IPIs */ #define IPI_INVLPG (APIC_IPI_INTS + 2) @@ -121,6 +132,7 @@ #define IPI_LAZYPMAP (APIC_IPI_INTS + 5) /* Lazy pmap release. */ /* Vector to handle bitmap based IPIs */ #define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 6) +#endif /* IPIs handled by IPI_BITMAPED_VECTOR (XXX ups is there a better place?) */ #define IPI_AST 0 /* Generate software trap. */ Modified: projects/releng_6_xen/sys/i386/include/pcpu.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/pcpu.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/pcpu.h Sat Oct 25 00:25:25 2008 (r184235) @@ -47,6 +47,24 @@ */ #ifdef XEN +#ifndef NR_VIRQS +#define NR_VIRQS 24 +#endif +#ifndef NR_IPIS +#define NR_IPIS 2 +#endif + +/* These are peridically updated in shared_info, and then copied here. */ +struct shadow_time_info { + uint64_t tsc_timestamp; /* TSC at last update of time vals. */ + uint64_t system_timestamp; /* Time, in nanosecs, since boot. */ + uint32_t tsc_to_nsec_mul; + uint32_t tsc_to_usec_mul; + int tsc_shift; + uint32_t version; +}; + + #define PCPU_MD_FIELDS \ struct pcpu *pc_prvspace; /* Self-reference */ \ struct pmap *pc_curpmap; \ @@ -63,7 +81,14 @@ u_int pc_pdir; \ u_int pc_lazypmap; \ u_int pc_rendezvous; \ - u_int pc_cpuast + u_int pc_cpuast; \ + uint64_t pc_processed_system_time; \ + struct shadow_time_info pc_shadow_time; \ + int pc_resched_irq; \ + int pc_callfunc_irq; \ + int pc_virq_to_irq[NR_VIRQS]; \ + int pc_ipi_to_irq[NR_IPIS] + #else Modified: projects/releng_6_xen/sys/i386/include/smp.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/smp.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/smp.h Sat Oct 25 00:25:25 2008 (r184235) @@ -68,7 +68,9 @@ void ipi_selected(u_int cpus, u_int ipi) void ipi_all(u_int ipi); void ipi_all_but_self(u_int ipi); void ipi_self(u_int ipi); +#ifndef XEN void ipi_bitmap_handler(struct clockframe frame); +#endif u_int mp_bootaddress(u_int); int mp_grab_cpu_hlt(void); void mp_topology(void); @@ -85,7 +87,14 @@ void smp_masked_invltlb(u_int mask); int ipi_nmi_handler(void); void ipi_nmi_selected(u_int32_t cpus); #endif +#ifdef XEN +void ipi_to_irq_init(void); + +#define RESCHEDULE_VECTOR 0 +#define CALL_FUNCTION_VECTOR 1 +#define NR_IPIS 2 +#endif #endif /* !LOCORE */ #endif /* SMP */ Modified: projects/releng_6_xen/sys/i386/include/xen/evtchn.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/xen/evtchn.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/xen/evtchn.h Sat Oct 25 00:25:25 2008 (r184235) @@ -35,13 +35,24 @@ void mask_evtchn(int port); void unmask_evtchn(int port); +#ifdef SMP +void rebind_evtchn_to_cpu(int port, unsigned int cpu); +#else +#define rebind_evtchn_to_cpu(port, cpu) ((void)0) +#endif +static inline +int test_and_set_evtchn_mask(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + return synch_test_and_set_bit(port, s->evtchn_mask); +} static inline void clear_evtchn(int port) { - shared_info_t *s = HYPERVISOR_shared_info; - synch_clear_bit(port, &s->evtchn_pending[0]); + shared_info_t *s = HYPERVISOR_shared_info; + synch_clear_bit(port, &s->evtchn_pending[0]); } static inline void Modified: projects/releng_6_xen/sys/i386/include/xen/xen-os.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/xen/xen-os.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/xen/xen-os.h Sat Oct 25 00:25:25 2008 (r184235) @@ -73,10 +73,7 @@ static inline void rep_nop(void) #define __builtin_expect(x, expected_value) (x) #endif -#define DEFINE_PER_CPU(type, name) \ - __typeof__(type) per_cpu__##name - -#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var)) +#define per_cpu(var, cpu) (pcpu_find((cpu))->pc_ ## var) /* crude memory allocator for memory allocation early in * boot @@ -94,12 +91,6 @@ void printk(const char *fmt, ...); /* some function prototypes */ void trap_init(void); -extern int preemptable; -#define preempt_disable() (preemptable = 0) -#define preempt_enable() (preemptable = 1) -#define preempt_enable_no_resched() (preemptable = 1) - - /* * STI/CLI equivalents. These basically set and clear the virtual * event_enable flag in teh shared_info structure. Note that when @@ -114,10 +105,8 @@ extern int preemptable; #define __cli() \ do { \ vcpu_info_t *_vcpu; \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ _vcpu->evtchn_upcall_mask = 1; \ - preempt_enable_no_resched(); \ barrier(); \ } while (0) @@ -125,36 +114,23 @@ do { do { \ vcpu_info_t *_vcpu; \ barrier(); \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ _vcpu->evtchn_upcall_mask = 0; \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ - preempt_enable(); \ -} while (0) - - -#define __save_flags(x) \ -do { \ - vcpu_info_t *vcpu; \ - vcpu = HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ - (x) = _vcpu->evtchn_upcall_mask; \ } while (0) #define __restore_flags(x) \ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ - preempt_enable(); \ - } else \ - preempt_enable_no_resched(); \ + } \ } while (0) /* Modified: projects/releng_6_xen/sys/i386/include/xen/xen_intr.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/xen/xen_intr.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/xen/xen_intr.h Sat Oct 25 00:25:25 2008 (r184235) @@ -29,7 +29,6 @@ /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ extern void unbind_from_irq(int irq); -extern void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu); extern int bind_caller_port_to_irqhandler(unsigned int caller_port, const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags, void **cookiep); @@ -38,8 +37,12 @@ extern int bind_listening_port_to_irqhan void **cookiep); extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, const char *devname, driver_intr_t handler, unsigned long irqflags); -extern int bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu, const char *devname, - driver_intr_t handler, unsigned long irqflags); +extern int bind_ipi_to_irqhandler(unsigned int ipi, + unsigned int cpu, + const char *devname, + driver_intr_t handler, + unsigned long irqflags); + extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, unsigned int remote_port, const char *devname, @@ -61,7 +64,7 @@ extern void enable_irq(unsigned int); extern void irq_suspend(void); extern void irq_resume(void); -extern void idle_block(void); - +extern void idle_block(void); +extern int ap_cpu_initclocks(int cpu); #endif /* _XEN_INTR_H_ */ Modified: projects/releng_6_xen/sys/i386/include/xen/xenfunc.h ============================================================================== --- projects/releng_6_xen/sys/i386/include/xen/xenfunc.h Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/include/xen/xenfunc.h Sat Oct 25 00:25:25 2008 (r184235) @@ -65,8 +65,6 @@ void _xen_machphys_update(vm_paddr_t, vm void xen_update_descriptor(union descriptor *, union descriptor *); -void ap_cpu_initclocks(void); - extern struct mtx balloon_lock; #if 0 #define balloon_lock(__flags) mtx_lock_irqsave(&balloon_lock, __flags) Modified: projects/releng_6_xen/sys/i386/xen/clock.c ============================================================================== --- projects/releng_6_xen/sys/i386/xen/clock.c Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/xen/clock.c Sat Oct 25 00:25:25 2008 (r184235) @@ -161,19 +161,6 @@ SYSCTL_INT(_machdep, OID_AUTO, xen_disab }) -/* These are peridically updated in shared_info, and then copied here. */ -struct shadow_time_info { - uint64_t tsc_timestamp; /* TSC at last update of time vals. */ - uint64_t system_timestamp; /* Time, in nanosecs, since boot. */ - uint32_t tsc_to_nsec_mul; - uint32_t tsc_to_usec_mul; - int tsc_shift; - uint32_t version; -}; -static DEFINE_PER_CPU(uint64_t, processed_system_time); -static DEFINE_PER_CPU(struct shadow_time_info, shadow_time); - - #define NS_PER_TICK (1000000000ULL/hz) #define rdtscll(val) \ @@ -868,25 +855,26 @@ cpu_initclocks(void) /* should fast clock be enabled ? */ } -/* - * - * XXX - */ -#if 0 && defined(SMP) -void -ap_cpu_initclocks(void) + +int +ap_cpu_initclocks(int cpu) { - int irq; - int cpu = smp_processor_id(); - - per_cpu(processed_system_time, cpu) = processed_system_time; + int time_irq; + + xen_set_periodic_tick.period_ns = NS_PER_TICK; - irq = bind_virq_to_irq(VIRQ_TIMER); - PCPU_SET(time_irq, irq); - PANIC_IF(intr_add_handler("clk", irq, (driver_intr_t *)clkintr, NULL, - NULL, INTR_TYPE_CLK | INTR_FAST, NULL)); + HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, + &xen_set_periodic_tick); + + if ((time_irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, "clk", + (driver_intr_t *)clkintr, + INTR_TYPE_CLK | INTR_FAST)) < 0) { + panic("failed to register clock interrupt\n"); + } + + return (0); } -#endif + void cpu_startprofclock(void) Modified: projects/releng_6_xen/sys/i386/xen/exception.s ============================================================================== --- projects/releng_6_xen/sys/i386/xen/exception.s Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/xen/exception.s Sat Oct 25 00:25:25 2008 (r184235) @@ -37,18 +37,34 @@ #include #include - #include "assym.s" #define SEL_RPL_MASK 0x0002 #define __HYPERVISOR_iret 23 /* Offsets into shared_info_t. */ + #define evtchn_upcall_pending /* 0 */ #define evtchn_upcall_mask 1 -#define XEN_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg) -#define XEN_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg) -#define XEN_TEST_PENDING(reg) testb $0x1,evtchn_upcall_pending(reg) + +#define sizeof_vcpu_shift 6 + + +#ifdef SMP +#define GET_VCPU_INFO(reg) movl PCPU(CPUID),reg ; \ + shl $sizeof_vcpu_shift,reg ; \ + addl HYPERVISOR_shared_info,reg +#else +#define GET_VCPU_INFO(reg) movl HYPERVISOR_shared_info,reg +#endif + +#define __DISABLE_INTERRUPTS(reg) movb $1,evtchn_upcall_mask(reg) +#define __ENABLE_INTERRUPTS(reg) movb $0,evtchn_upcall_mask(reg) +#define DISABLE_INTERRUPTS(reg) GET_VCPU_INFO(reg) ; \ + __DISABLE_INTERRUPTS(reg) +#define ENABLE_INTERRUPTS(reg) GET_VCPU_INFO(reg) ; \ + __ENABLE_INTERRUPTS(reg) +#define __TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg) #define POPA \ popl %edi; \ @@ -161,8 +177,7 @@ call_evtchn_upcall: hypervisor_callback_pending: - movl HYPERVISOR_shared_info,%esi - XEN_BLOCK_EVENTS(%esi) /* cli */ + DISABLE_INTERRUPTS(%esi) /* cli */ jmp 10b /* @@ -327,12 +342,11 @@ doreti_ast: * interrupts provides sufficient locking even in the SMP case, * since we will be informed of any new ASTs by an IPI. */ - movl HYPERVISOR_shared_info,%esi - XEN_BLOCK_EVENTS(%esi) /* cli */ + DISABLE_INTERRUPTS(%esi) /* cli */ movl PCPU(CURTHREAD),%eax testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax) je doreti_exit - XEN_UNBLOCK_EVENTS(%esi) /* sti */ + ENABLE_INTERRUPTS(%esi) /* sti */ pushl %esp /* pass a pointer to the trapframe */ call ast add $4,%esp @@ -346,12 +360,11 @@ doreti_ast: * registers. The fault is handled in trap.c. */ doreti_exit: - movl HYPERVISOR_shared_info,%esi - XEN_UNBLOCK_EVENTS(%esi) # reenable event callbacks (sti) + ENABLE_INTERRUPTS(%esi) # reenable event callbacks (sti) .globl scrit scrit: - XEN_TEST_PENDING(%esi) + __TEST_PENDING(%esi) jnz hypervisor_callback_pending /* More to go */ MEXITCOUNT Modified: projects/releng_6_xen/sys/i386/xen/mp_machdep.c ============================================================================== --- projects/releng_6_xen/sys/i386/xen/mp_machdep.c Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/i386/xen/mp_machdep.c Sat Oct 25 00:25:25 2008 (r184235) @@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -126,6 +127,9 @@ char *bootSTK; static int bootAP; static union descriptor *bootAPgdt; +static char resched_name[NR_CPUS][15]; +static char callfunc_name[NR_CPUS][15]; + /* Free these after use */ void *bootstacks[MAXCPU]; @@ -139,6 +143,9 @@ vm_offset_t smp_tlb_addr1; vm_offset_t smp_tlb_addr2; volatile int smp_tlb_wait; +typedef void call_data_func_t(uintptr_t , uintptr_t); + + #ifdef COUNT_IPIS /* Interrupt counts. */ #ifdef IPI_PREEMPTION @@ -191,6 +198,7 @@ static u_int hyperthreading_cpus; static cpumask_t hyperthreading_cpus_mask; extern void Xhypervisor_callback(void); extern void failsafe_callback(void); +extern void pmap_lazyfix_action(void); void mp_topology(void) @@ -376,6 +384,151 @@ cpu_mp_start(void) set_interrupt_apic_ids(); } + +static void +iv_rendezvous(uintptr_t a, uintptr_t b) +{ + smp_rendezvous_action(); +} + +static void +iv_invltlb(uintptr_t a, uintptr_t b) +{ + xen_tlb_flush(); +} + +static void +iv_invlpg(uintptr_t a, uintptr_t b) +{ + xen_invlpg(a); +} + +static void +iv_invlrng(uintptr_t a, uintptr_t b) +{ + vm_offset_t start = (vm_offset_t)a; + vm_offset_t end = (vm_offset_t)b; + + while (start < end) { + xen_invlpg(start); + start += PAGE_SIZE; + } +} + + +static void +iv_invlcache(uintptr_t a, uintptr_t b) +{ + + wbinvd(); +} + +static void +iv_lazypmap(uintptr_t a, uintptr_t b) +{ + pmap_lazyfix_action(); +} + + +static void +iv_noop(uintptr_t a, uintptr_t b) +{ +} + +static call_data_func_t *ipi_vectors[IPI_BITMAP_VECTOR] = +{ + iv_noop, + iv_noop, + iv_rendezvous, + iv_invltlb, + iv_invlpg, + iv_invlrng, + iv_invlcache, + iv_lazypmap, +}; + +/* + * Reschedule call back. Nothing to do, + * all the work is done automatically when + * we return from the interrupt. + */ +static void +smp_reschedule_interrupt(void *unused) +{ + int cpu = PCPU_GET(cpuid); + u_int ipi_bitmap; + + ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]); + +#ifdef IPI_PREEMPTION + if (ipi_bitmap & (1 << IPI_PREEMPT)) { +#ifdef COUNT_IPIS + *ipi_preempt_counts[cpu]++; +#endif + mtx_lock_spin(&sched_lock); + /* Don't preempt the idle thread */ + if (curthread != PCPU_GET(idlethread)) { + struct thread *running_thread = curthread; + if (running_thread->td_critnest > 1) + running_thread->td_owepreempt = 1; + else + mi_switch(SW_INVOL | SW_PREEMPT, NULL); + } + mtx_unlock_spin(&sched_lock); + } +#endif + + if (ipi_bitmap & (1 << IPI_AST)) { +#ifdef COUNT_IPIS + *ipi_ast_counts[cpu]++; +#endif + /* Nothing to do for AST */ + } +} + +struct _call_data { + uint16_t func_id; + uint16_t wait; + uintptr_t arg1; + uintptr_t arg2; + atomic_t started; + atomic_t finished; +}; + +static struct _call_data *call_data; + +static void +smp_call_function_interrupt(void *arg) +{ + call_data_func_t *func; + uintptr_t arg1 = call_data->arg1; + uintptr_t arg2 = call_data->arg2; + int wait = call_data->wait; + atomic_t *started = &call_data->started; + atomic_t *finished = &call_data->finished; + + if (call_data->func_id > IPI_BITMAP_VECTOR) + panic("invalid function id %u", call_data->func_id); + + func = ipi_vectors[call_data->func_id]; + /* + * Notify initiating CPU that I've grabbed the data and am + * about to execute the function + */ + mb(); + atomic_inc(started); + /* + * At this point the info structure may be out of scope unless wait==1 + */ + (*func)(arg1, arg2); + + if (wait) { + mb(); + atomic_inc(finished); + } + atomic_add_int(&smp_tlb_wait, 1); +} + /* * Print various information about the SMP system hardware and setup. */ @@ -399,6 +552,61 @@ cpu_mp_announce(void) } } +static int +xen_smp_intr_init(unsigned int cpu) +{ + int rc; + + per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1; + + sprintf(resched_name[cpu], "resched%u", cpu); + rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, + cpu, + resched_name[cpu], + smp_reschedule_interrupt, + INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE); + + printf("cpu=%d irq=%d vector=%d\n", + cpu, rc, RESCHEDULE_VECTOR); + + per_cpu(resched_irq, cpu) = rc; + + sprintf(callfunc_name[cpu], "callfunc%u", cpu); + rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR, + cpu, + callfunc_name[cpu], + smp_call_function_interrupt, + INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE); + if (rc < 0) + goto fail; + per_cpu(callfunc_irq, cpu) = rc; + + printf("cpu=%d irq=%d vector=%d\n", + cpu, rc, CALL_FUNCTION_VECTOR); + + + if ((cpu != 0) && ((rc = ap_cpu_initclocks(cpu)) != 0)) + goto fail; + + return 0; + + fail: + if (per_cpu(resched_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); + if (per_cpu(callfunc_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); + return rc; +} + +static void +xen_smp_intr_init_cpus(void *unused) +{ + int i; + + for (i = 0; i < mp_ncpus; i++) + xen_smp_intr_init(i); +} + #define MTOPSIZE (1<<(14 + PAGE_SHIFT)) /* * AP CPU's call this to initialize themselves. @@ -881,19 +1089,24 @@ static void smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2) { u_int ncpu; + struct _call_data data; + call_data = &data; + ncpu = mp_ncpus - 1; /* does not shootdown self */ if (ncpu < 1) return; /* no other cpus */ if (!(read_eflags() & PSL_I)) panic("%s: interrupts disabled", __func__); mtx_lock_spin(&smp_ipi_mtx); - smp_tlb_addr1 = addr1; - smp_tlb_addr2 = addr2; + call_data->func_id = vector; + call_data->arg1 = addr1; + call_data->arg2 = addr2; atomic_store_rel_int(&smp_tlb_wait, 0); ipi_all_but_self(vector); while (smp_tlb_wait < ncpu) ia32_pause(); + call_data = NULL; mtx_unlock_spin(&smp_ipi_mtx); } @@ -901,6 +1114,7 @@ static void smp_targeted_tlb_shootdown(u_int mask, u_int vector, vm_offset_t addr1, vm_offset_t addr2) { int ncpu, othercpus; + struct _call_data data; othercpus = mp_ncpus - 1; if (mask == (u_int)-1) { @@ -925,8 +1139,10 @@ smp_targeted_tlb_shootdown(u_int mask, u if (!(read_eflags() & PSL_I)) panic("%s: interrupts disabled", __func__); mtx_lock_spin(&smp_ipi_mtx); - smp_tlb_addr1 = addr1; - smp_tlb_addr2 = addr2; + call_data = &data; + call_data->func_id = vector; + call_data->arg1 = addr1; + call_data->arg2 = addr2; atomic_store_rel_int(&smp_tlb_wait, 0); if (mask == (u_int)-1) ipi_all_but_self(vector); @@ -934,6 +1150,7 @@ smp_targeted_tlb_shootdown(u_int mask, u ipi_selected(mask, vector); while (smp_tlb_wait < ncpu) ia32_pause(); + call_data = NULL; mtx_unlock_spin(&smp_ipi_mtx); } @@ -1019,6 +1236,8 @@ smp_masked_invlpg_range(u_int mask, vm_o } } +void +ipi_bitmap_handler(struct clockframe frame); void ipi_bitmap_handler(struct clockframe frame) @@ -1058,17 +1277,17 @@ ipi_bitmap_handler(struct clockframe fra * send an IPI to a set of cpus. */ void -ipi_selected(u_int32_t cpus, u_int ipi) +ipi_selected(uint32_t cpus, u_int ipi) { int cpu; u_int bitmap = 0; u_int old_pending; u_int new_pending; - + if (IPI_IS_BITMAPED(ipi)) { bitmap = 1 << ipi; ipi = IPI_BITMAP_VECTOR; - } + } CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi); while ((cpu = ffs(cpus)) != 0) { @@ -1084,11 +1303,15 @@ ipi_selected(u_int32_t cpus, u_int ipi) new_pending = old_pending | bitmap; } while (!atomic_cmpset_int(&cpu_ipi_pending[cpu],old_pending, new_pending)); - if (old_pending) - continue; + if (!old_pending) + ipi_pcpu(cpu, RESCHEDULE_VECTOR); + continue; + } - ipi_pcpu(cpu, ipi); + KASSERT(call_data != NULL, ("call_data not set")); + + ipi_pcpu(cpu, CALL_FUNCTION_VECTOR); } } @@ -1101,7 +1324,7 @@ ipi_all(u_int ipi) { CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); - ipi_selected(all_cpus, ipi); + ipi_selected(PCPU_GET(other_cpus), ipi); } /* @@ -1143,6 +1366,7 @@ release_aps(void *dummy __unused) mtx_unlock_spin(&sched_lock); } SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL); +SYSINIT(start_ipis, SI_SUB_INTR, SI_ORDER_ANY, xen_smp_intr_init_cpus, NULL); #ifdef COUNT_IPIS /* Modified: projects/releng_6_xen/sys/xen/evtchn/evtchn.c ============================================================================== --- projects/releng_6_xen/sys/xen/evtchn/evtchn.c Fri Oct 24 21:52:50 2008 (r184234) +++ projects/releng_6_xen/sys/xen/evtchn/evtchn.c Sat Oct 25 00:25:25 2008 (r184235) @@ -18,6 +18,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -28,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include @@ -101,27 +103,58 @@ enum { IRQT_VIRQ, IRQT_IPI, IRQT_LOCAL_PORT, - IRQT_CALLER_PORT + IRQT_CALLER_PORT, + _IRQT_COUNT + }; + +#define _IRQT_BITS 4 +#define _EVTCHN_BITS 12 +#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS) + /* Constructor for packed IRQ information. */ -#define mk_irq_info(type, index, evtchn) \ - (((uint32_t)(type) << 24) | ((uint32_t)(index) << 16) | (uint32_t)(evtchn)) +static inline uint32_t +mk_irq_info(uint32_t type, uint32_t index, uint32_t evtchn) +{ + + return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn); +} + +/* Constructor for packed IRQ information. */ + /* Convenient shorthand for packed representation of an unbound IRQ. */ #define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0) -/* Accessor macros for packed IRQ information. */ -#define evtchn_from_irq(irq) ((uint16_t)(irq_info[irq])) -#define index_from_irq(irq) ((uint8_t)(irq_info[irq] >> 16)) -#define type_from_irq(irq) ((uint8_t)(irq_info[irq] >> 24)) + +/* + * Accessors for packed IRQ information. + */ + +static inline unsigned int evtchn_from_irq(int irq) +{ + return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1); +} + +static inline unsigned int index_from_irq(int irq) +{ + return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1); +} + +static inline unsigned int type_from_irq(int irq) +{ + return irq_info[irq] >> (32 - _IRQT_BITS); +} + /* IRQ <-> VIRQ mapping. */ -DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1}; /* IRQ <-> IPI mapping. */ -#ifndef NR_IPIS +#ifndef NR_IPIS +#ifdef SMP +#error "NR_IPIS not defined" +#endif #define NR_IPIS 1 #endif -DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1}; /* Bitmap indicating which PIRQs require Xen to be notified on unmask. */ static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)]; @@ -131,9 +164,9 @@ static int irq_bindcount[NR_IRQS]; #define VALID_EVTCHN(_chn) ((_chn) != 0) -#ifdef CONFIG_SMP +#ifdef SMP -static u8 cpu_evtchn[NR_EVENT_CHANNELS]; +static uint8_t cpu_evtchn[NR_EVENT_CHANNELS]; static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG]; #define active_evtchns(cpu,sh,idx) \ @@ -224,8 +257,10 @@ evtchn_do_upcall(struct intrframe *frame void ipi_pcpu(unsigned int cpu, int vector) { - int irq = per_cpu(ipi_to_irq, cpu)[vector]; + int irq; + irq = per_cpu(ipi_to_irq, cpu)[vector]; + notify_remote_via_irq(irq); } @@ -333,6 +368,9 @@ bind_virq_to_irq(unsigned int virq, unsi mtx_lock_spin(&irq_mapping_update_lock); if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { + if ((irq = find_unbound_irq()) < 0) + goto out; + bind_virq.virq = virq; bind_virq.vcpu = cpu; PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, @@ -340,7 +378,6 @@ bind_virq_to_irq(unsigned int virq, unsi evtchn = bind_virq.port; - irq = find_unbound_irq(); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); @@ -350,13 +387,16 @@ bind_virq_to_irq(unsigned int virq, unsi } irq_bindcount[irq]++; - +out: mtx_unlock_spin(&irq_mapping_update_lock); return irq; } -static int + +extern int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu); + +int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) { struct evtchn_bind_ipi bind_ipi; @@ -372,7 +412,6 @@ bind_ipi_to_irq(unsigned int ipi, unsign PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0); evtchn = bind_ipi.port; - irq = find_unbound_irq(); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); @@ -380,7 +419,6 @@ bind_ipi_to_irq(unsigned int ipi, unsign bind_evtchn_to_cpu(evtchn, cpu); } - irq_bindcount[irq]++; out: @@ -518,9 +556,8 @@ bind_ipi_to_irqhandler(unsigned int ipi, driver_intr_t handler, unsigned long irqflags) { - unsigned int irq; - int retval; - + int irq, retval; + irq = bind_ipi_to_irq(ipi, cpu); intr_register_source(&xp->xp_pins[irq].xp_intsrc); retval = intr_add_handler(devname, irq, handler, NULL, irqflags, NULL); @@ -742,6 +779,8 @@ notify_remote_via_irq(int irq) if (VALID_EVTCHN(evtchn)) notify_remote_via_evtchn(evtchn); + else + panic("invalid evtchn"); } /* required for support of physical devices */ @@ -792,6 +831,9 @@ xenpic_pirq_enable_intr(struct intsrc *i bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) { +#ifndef XEN_PRIVILEGED_GUEST + panic("unexpected pirq call"); +#endif if (!probing_irq(irq)) /* Some failures are expected when probing. */ printf("Failed to obtain physical IRQ %d\n", irq); mtx_unlock_spin(&irq_mapping_update_lock); @@ -992,8 +1034,11 @@ evtchn_init(void *dummy __unused) int i, cpu; struct xenpic_intsrc *pin, *tpin; - /* No VIRQ or IPI bindings. */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 00:28:25 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 28CCD1065671; Sat, 25 Oct 2008 00:28:25 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 17F208FC0C; Sat, 25 Oct 2008 00:28:25 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9P0SO7g002832; Sat, 25 Oct 2008 00:28:24 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9P0SOJv002831; Sat, 25 Oct 2008 00:28:24 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200810250028.m9P0SOJv002831@svn.freebsd.org> From: Kip Macy Date: Sat, 25 Oct 2008 00:28:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184236 - projects/releng_6_xen/sys/i386/xen X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 00:28:25 -0000 Author: kmacy Date: Sat Oct 25 00:28:24 2008 New Revision: 184236 URL: http://svn.freebsd.org/changeset/base/184236 Log: hook xen into mptable Added: projects/releng_6_xen/sys/i386/xen/mptable.c (contents, props changed) Added: projects/releng_6_xen/sys/i386/xen/mptable.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/releng_6_xen/sys/i386/xen/mptable.c Sat Oct 25 00:28:24 2008 (r184236) @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2003 John Baldwin + * Copyright (c) 1996, by Steve Passe + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +static int mptable_probe(void); +static int mptable_probe_cpus(void); +static void mptable_register(void *dummy); +static int mptable_setup_local(void); +static int mptable_setup_io(void); + +static struct apic_enumerator mptable_enumerator = { + "MPTable", + mptable_probe, + mptable_probe_cpus, + mptable_setup_local, + mptable_setup_io +}; + +static int +mptable_probe(void) +{ + + return (-100); +} + +static int +mptable_probe_cpus(void) +{ + int i, rc; + + for (i = 0; i < MAXCPU; i++) { + rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL); + if (rc >= 0) + cpu_add(i, (i == 0)); + } + + return (0); +} + +/* + * Initialize the local APIC on the BSP. + */ +static int +mptable_setup_local(void) +{ + + return (0); +} + +static int +mptable_setup_io(void) +{ + + return (0); +} + +static void +mptable_register(void *dummy __unused) +{ + + apic_register_enumerator(&mptable_enumerator); +} +SYSINIT(mptable_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, mptable_register, + NULL); + + + +int +mptable_pci_probe_table(int bus) +{ + + return (0); +} + +int +mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin) +{ + + return (0); +} + From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 04:40:25 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 166171065671; Sat, 25 Oct 2008 04:40:25 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id F370E8FC16; Sat, 25 Oct 2008 04:40:24 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9P4eNjn021119; Sat, 25 Oct 2008 04:40:23 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9P4eNaZ021104; Sat, 25 Oct 2008 04:40:23 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200810250440.m9P4eNaZ021104@svn.freebsd.org> From: Kip Macy Date: Sat, 25 Oct 2008 04:40:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184246 - in projects/release_6_3_xen/sys: conf i386/i386 i386/include i386/include/xen i386/xen xen/evtchn X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 04:40:25 -0000 Author: kmacy Date: Sat Oct 25 04:40:22 2008 New Revision: 184246 URL: http://svn.freebsd.org/changeset/base/184246 Log: MFC SMP support Added: projects/release_6_3_xen/sys/i386/xen/mptable.c Modified: projects/release_6_3_xen/sys/conf/files.i386 projects/release_6_3_xen/sys/i386/i386/apic_vector.s projects/release_6_3_xen/sys/i386/i386/local_apic.c projects/release_6_3_xen/sys/i386/include/apicvar.h projects/release_6_3_xen/sys/i386/include/pcpu.h projects/release_6_3_xen/sys/i386/include/smp.h projects/release_6_3_xen/sys/i386/include/xen/evtchn.h projects/release_6_3_xen/sys/i386/include/xen/xen-os.h projects/release_6_3_xen/sys/i386/include/xen/xen_intr.h projects/release_6_3_xen/sys/i386/include/xen/xenfunc.h projects/release_6_3_xen/sys/i386/xen/clock.c projects/release_6_3_xen/sys/i386/xen/exception.s projects/release_6_3_xen/sys/i386/xen/mp_machdep.c projects/release_6_3_xen/sys/i386/xen/xen_machdep.c projects/release_6_3_xen/sys/xen/evtchn/evtchn.c Modified: projects/release_6_3_xen/sys/conf/files.i386 ============================================================================== --- projects/release_6_3_xen/sys/conf/files.i386 Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/conf/files.i386 Sat Oct 25 04:40:22 2008 (r184246) @@ -323,7 +323,8 @@ i386/i386/mp_machdep.c optional native i386/xen/mp_machdep.c optional xen smp i386/i386/mp_watchdog.c optional mp_watchdog smp i386/i386/mpboot.s optional native smp -i386/i386/mptable.c optional apic +i386/xen/mptable.c optional apic xen +i386/i386/mptable.c optional apic native i386/i386/mptable_pci.c optional apic pci i386/i386/msi.c optional apic pci i386/i386/nexus.c standard Modified: projects/release_6_3_xen/sys/i386/i386/apic_vector.s ============================================================================== --- projects/release_6_3_xen/sys/i386/i386/apic_vector.s Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/i386/apic_vector.s Sat Oct 25 04:40:22 2008 (r184246) @@ -299,6 +299,7 @@ IDTVEC(invlcache) /* * Handler for IPIs sent via the per-cpu IPI bitmap. */ +#ifndef XEN .text SUPERALIGN_TEXT IDTVEC(ipi_intr_bitmap_handler) @@ -320,7 +321,7 @@ IDTVEC(ipi_intr_bitmap_handler) addl $4, %esp /* XXX convert clockframe to trapframe */ MEXITCOUNT jmp doreti - +#endif /* * Executed by a CPU when it receives an Xcpustop IPI from another CPU, * Modified: projects/release_6_3_xen/sys/i386/i386/local_apic.c ============================================================================== --- projects/release_6_3_xen/sys/i386/i386/local_apic.c Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/i386/local_apic.c Sat Oct 25 04:40:22 2008 (r184246) @@ -1068,7 +1068,9 @@ apic_setup_io(void *dummy __unused) if (retval != 0) printf("%s: Failed to setup I/O APICs: returned %d\n", best_enum->apic_name, retval); - +#ifdef XEN + return; +#endif /* * Finish setting up the local APIC on the BSP once we know how to * properly program the LINT pins. Modified: projects/release_6_3_xen/sys/i386/include/apicvar.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/apicvar.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/apicvar.h Sat Oct 25 04:40:22 2008 (r184246) @@ -113,6 +113,18 @@ #define APIC_THERMAL_INT (APIC_LOCAL_INTS + 1) #define APIC_IPI_INTS (APIC_LOCAL_INTS + 2) +#ifdef XEN +#define IPI_RENDEZVOUS (2) /* Inter-CPU rendezvous. */ +#define IPI_INVLTLB (3) /* TLB Shootdown IPIs */ +#define IPI_INVLPG (4) +#define IPI_INVLRNG (5) +#define IPI_INVLCACHE (6) +#define IPI_LAZYPMAP (7) /* Lazy pmap release. */ +/* Vector to handle bitmap based IPIs */ +#define IPI_BITMAP_VECTOR (8) +#define IPI_STOP (9) + +#else #define IPI_RENDEZVOUS (APIC_IPI_INTS) /* Inter-CPU rendezvous. */ #define IPI_INVLTLB (APIC_IPI_INTS + 1) /* TLB Shootdown IPIs */ #define IPI_INVLPG (APIC_IPI_INTS + 2) @@ -121,6 +133,8 @@ #define IPI_LAZYPMAP (APIC_IPI_INTS + 5) /* Lazy pmap release. */ /* Vector to handle bitmap based IPIs */ #define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 6) +#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */ +#endif /* IPIs handled by IPI_BITMAPED_VECTOR (XXX ups is there a better place?) */ #define IPI_AST 0 /* Generate software trap. */ @@ -128,7 +142,7 @@ #define IPI_BITMAP_LAST IPI_PREEMPT #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST) -#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */ + /* * The spurious interrupt can share the priority class with the IPIs since Modified: projects/release_6_3_xen/sys/i386/include/pcpu.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/pcpu.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/pcpu.h Sat Oct 25 04:40:22 2008 (r184246) @@ -47,6 +47,24 @@ */ #ifdef XEN +#ifndef NR_VIRQS +#define NR_VIRQS 24 +#endif +#ifndef NR_IPIS +#define NR_IPIS 2 +#endif + +/* These are peridically updated in shared_info, and then copied here. */ +struct shadow_time_info { + uint64_t tsc_timestamp; /* TSC at last update of time vals. */ + uint64_t system_timestamp; /* Time, in nanosecs, since boot. */ + uint32_t tsc_to_nsec_mul; + uint32_t tsc_to_usec_mul; + int tsc_shift; + uint32_t version; +}; + + #define PCPU_MD_FIELDS \ struct pcpu *pc_prvspace; /* Self-reference */ \ struct pmap *pc_curpmap; \ @@ -63,7 +81,14 @@ u_int pc_pdir; \ u_int pc_lazypmap; \ u_int pc_rendezvous; \ - u_int pc_cpuast + u_int pc_cpuast; \ + uint64_t pc_processed_system_time; \ + struct shadow_time_info pc_shadow_time; \ + int pc_resched_irq; \ + int pc_callfunc_irq; \ + int pc_virq_to_irq[NR_VIRQS]; \ + int pc_ipi_to_irq[NR_IPIS] + #else Modified: projects/release_6_3_xen/sys/i386/include/smp.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/smp.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/smp.h Sat Oct 25 04:40:22 2008 (r184246) @@ -68,7 +68,9 @@ void ipi_selected(u_int cpus, u_int ipi) void ipi_all(u_int ipi); void ipi_all_but_self(u_int ipi); void ipi_self(u_int ipi); +#ifndef XEN void ipi_bitmap_handler(struct clockframe frame); +#endif u_int mp_bootaddress(u_int); int mp_grab_cpu_hlt(void); void mp_topology(void); @@ -85,7 +87,14 @@ void smp_masked_invltlb(u_int mask); int ipi_nmi_handler(void); void ipi_nmi_selected(u_int32_t cpus); #endif +#ifdef XEN +void ipi_to_irq_init(void); + +#define RESCHEDULE_VECTOR 0 +#define CALL_FUNCTION_VECTOR 1 +#define NR_IPIS 2 +#endif #endif /* !LOCORE */ #endif /* SMP */ Modified: projects/release_6_3_xen/sys/i386/include/xen/evtchn.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/xen/evtchn.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/xen/evtchn.h Sat Oct 25 04:40:22 2008 (r184246) @@ -35,13 +35,24 @@ void mask_evtchn(int port); void unmask_evtchn(int port); +#ifdef SMP +void rebind_evtchn_to_cpu(int port, unsigned int cpu); +#else +#define rebind_evtchn_to_cpu(port, cpu) ((void)0) +#endif +static inline +int test_and_set_evtchn_mask(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + return synch_test_and_set_bit(port, s->evtchn_mask); +} static inline void clear_evtchn(int port) { - shared_info_t *s = HYPERVISOR_shared_info; - synch_clear_bit(port, &s->evtchn_pending[0]); + shared_info_t *s = HYPERVISOR_shared_info; + synch_clear_bit(port, &s->evtchn_pending[0]); } static inline void Modified: projects/release_6_3_xen/sys/i386/include/xen/xen-os.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/xen/xen-os.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/xen/xen-os.h Sat Oct 25 04:40:22 2008 (r184246) @@ -73,10 +73,7 @@ static inline void rep_nop(void) #define __builtin_expect(x, expected_value) (x) #endif -#define DEFINE_PER_CPU(type, name) \ - __typeof__(type) per_cpu__##name - -#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var)) +#define per_cpu(var, cpu) (pcpu_find((cpu))->pc_ ## var) /* crude memory allocator for memory allocation early in * boot @@ -94,12 +91,6 @@ void printk(const char *fmt, ...); /* some function prototypes */ void trap_init(void); -extern int preemptable; -#define preempt_disable() (preemptable = 0) -#define preempt_enable() (preemptable = 1) -#define preempt_enable_no_resched() (preemptable = 1) - - /* * STI/CLI equivalents. These basically set and clear the virtual * event_enable flag in teh shared_info structure. Note that when @@ -114,10 +105,8 @@ extern int preemptable; #define __cli() \ do { \ vcpu_info_t *_vcpu; \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ _vcpu->evtchn_upcall_mask = 1; \ - preempt_enable_no_resched(); \ barrier(); \ } while (0) @@ -125,36 +114,23 @@ do { do { \ vcpu_info_t *_vcpu; \ barrier(); \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ _vcpu->evtchn_upcall_mask = 0; \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ - preempt_enable(); \ -} while (0) - - -#define __save_flags(x) \ -do { \ - vcpu_info_t *vcpu; \ - vcpu = HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ - (x) = _vcpu->evtchn_upcall_mask; \ } while (0) #define __restore_flags(x) \ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ - preempt_enable(); \ - } else \ - preempt_enable_no_resched(); \ + } \ } while (0) /* Modified: projects/release_6_3_xen/sys/i386/include/xen/xen_intr.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/xen/xen_intr.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/xen/xen_intr.h Sat Oct 25 04:40:22 2008 (r184246) @@ -29,7 +29,6 @@ /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ extern void unbind_from_irq(int irq); -extern void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu); extern int bind_caller_port_to_irqhandler(unsigned int caller_port, const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags, void **cookiep); @@ -38,8 +37,12 @@ extern int bind_listening_port_to_irqhan void **cookiep); extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, const char *devname, driver_intr_t handler, unsigned long irqflags); -extern int bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu, const char *devname, - driver_intr_t handler, unsigned long irqflags); +extern int bind_ipi_to_irqhandler(unsigned int ipi, + unsigned int cpu, + const char *devname, + driver_intr_t handler, + unsigned long irqflags); + extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, unsigned int remote_port, const char *devname, @@ -61,7 +64,7 @@ extern void enable_irq(unsigned int); extern void irq_suspend(void); extern void irq_resume(void); -extern void idle_block(void); - +extern void idle_block(void); +extern int ap_cpu_initclocks(int cpu); #endif /* _XEN_INTR_H_ */ Modified: projects/release_6_3_xen/sys/i386/include/xen/xenfunc.h ============================================================================== --- projects/release_6_3_xen/sys/i386/include/xen/xenfunc.h Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/include/xen/xenfunc.h Sat Oct 25 04:40:22 2008 (r184246) @@ -65,8 +65,6 @@ void _xen_machphys_update(vm_paddr_t, vm void xen_update_descriptor(union descriptor *, union descriptor *); -void ap_cpu_initclocks(void); - extern struct mtx balloon_lock; #if 0 #define balloon_lock(__flags) mtx_lock_irqsave(&balloon_lock, __flags) Modified: projects/release_6_3_xen/sys/i386/xen/clock.c ============================================================================== --- projects/release_6_3_xen/sys/i386/xen/clock.c Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/xen/clock.c Sat Oct 25 04:40:22 2008 (r184246) @@ -161,19 +161,6 @@ SYSCTL_INT(_machdep, OID_AUTO, xen_disab }) -/* These are peridically updated in shared_info, and then copied here. */ -struct shadow_time_info { - uint64_t tsc_timestamp; /* TSC at last update of time vals. */ - uint64_t system_timestamp; /* Time, in nanosecs, since boot. */ - uint32_t tsc_to_nsec_mul; - uint32_t tsc_to_usec_mul; - int tsc_shift; - uint32_t version; -}; -static DEFINE_PER_CPU(uint64_t, processed_system_time); -static DEFINE_PER_CPU(struct shadow_time_info, shadow_time); - - #define NS_PER_TICK (1000000000ULL/hz) #define rdtscll(val) \ @@ -868,25 +855,26 @@ cpu_initclocks(void) /* should fast clock be enabled ? */ } -/* - * - * XXX - */ -#if 0 && defined(SMP) -void -ap_cpu_initclocks(void) + +int +ap_cpu_initclocks(int cpu) { - int irq; - int cpu = smp_processor_id(); - - per_cpu(processed_system_time, cpu) = processed_system_time; + int time_irq; + + xen_set_periodic_tick.period_ns = NS_PER_TICK; - irq = bind_virq_to_irq(VIRQ_TIMER); - PCPU_SET(time_irq, irq); - PANIC_IF(intr_add_handler("clk", irq, (driver_intr_t *)clkintr, NULL, - NULL, INTR_TYPE_CLK | INTR_FAST, NULL)); + HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, + &xen_set_periodic_tick); + + if ((time_irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, "clk", + (driver_intr_t *)clkintr, + INTR_TYPE_CLK | INTR_FAST)) < 0) { + panic("failed to register clock interrupt\n"); + } + + return (0); } -#endif + void cpu_startprofclock(void) Modified: projects/release_6_3_xen/sys/i386/xen/exception.s ============================================================================== --- projects/release_6_3_xen/sys/i386/xen/exception.s Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/xen/exception.s Sat Oct 25 04:40:22 2008 (r184246) @@ -37,18 +37,34 @@ #include #include - #include "assym.s" #define SEL_RPL_MASK 0x0002 #define __HYPERVISOR_iret 23 /* Offsets into shared_info_t. */ + #define evtchn_upcall_pending /* 0 */ #define evtchn_upcall_mask 1 -#define XEN_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg) -#define XEN_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg) -#define XEN_TEST_PENDING(reg) testb $0x1,evtchn_upcall_pending(reg) + +#define sizeof_vcpu_shift 6 + + +#ifdef SMP +#define GET_VCPU_INFO(reg) movl PCPU(CPUID),reg ; \ + shl $sizeof_vcpu_shift,reg ; \ + addl HYPERVISOR_shared_info,reg +#else +#define GET_VCPU_INFO(reg) movl HYPERVISOR_shared_info,reg +#endif + +#define __DISABLE_INTERRUPTS(reg) movb $1,evtchn_upcall_mask(reg) +#define __ENABLE_INTERRUPTS(reg) movb $0,evtchn_upcall_mask(reg) +#define DISABLE_INTERRUPTS(reg) GET_VCPU_INFO(reg) ; \ + __DISABLE_INTERRUPTS(reg) +#define ENABLE_INTERRUPTS(reg) GET_VCPU_INFO(reg) ; \ + __ENABLE_INTERRUPTS(reg) +#define __TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg) #define POPA \ popl %edi; \ @@ -161,8 +177,7 @@ call_evtchn_upcall: hypervisor_callback_pending: - movl HYPERVISOR_shared_info,%esi - XEN_BLOCK_EVENTS(%esi) /* cli */ + DISABLE_INTERRUPTS(%esi) /* cli */ jmp 10b /* @@ -327,12 +342,11 @@ doreti_ast: * interrupts provides sufficient locking even in the SMP case, * since we will be informed of any new ASTs by an IPI. */ - movl HYPERVISOR_shared_info,%esi - XEN_BLOCK_EVENTS(%esi) /* cli */ + DISABLE_INTERRUPTS(%esi) /* cli */ movl PCPU(CURTHREAD),%eax testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax) je doreti_exit - XEN_UNBLOCK_EVENTS(%esi) /* sti */ + ENABLE_INTERRUPTS(%esi) /* sti */ pushl %esp /* pass a pointer to the trapframe */ call ast add $4,%esp @@ -346,12 +360,11 @@ doreti_ast: * registers. The fault is handled in trap.c. */ doreti_exit: - movl HYPERVISOR_shared_info,%esi - XEN_UNBLOCK_EVENTS(%esi) # reenable event callbacks (sti) + ENABLE_INTERRUPTS(%esi) # reenable event callbacks (sti) .globl scrit scrit: - XEN_TEST_PENDING(%esi) + __TEST_PENDING(%esi) jnz hypervisor_callback_pending /* More to go */ MEXITCOUNT Modified: projects/release_6_3_xen/sys/i386/xen/mp_machdep.c ============================================================================== --- projects/release_6_3_xen/sys/i386/xen/mp_machdep.c Sat Oct 25 03:41:36 2008 (r184245) +++ projects/release_6_3_xen/sys/i386/xen/mp_machdep.c Sat Oct 25 04:40:22 2008 (r184246) @@ -83,18 +83,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include -#define WARMBOOT_TARGET 0 -#define WARMBOOT_OFF (KERNBASE + 0x0467) -#define WARMBOOT_SEG (KERNBASE + 0x0469) - -#define CMOS_REG (0x70) -#define CMOS_DATA (0x71) -#define BIOS_RESET (0x0f) -#define BIOS_WARM (0x0a) - /* * this code MUST be enabled here and in mpboot.s. * it follows the very early stages of AP boot by placing values in CMOS ram. @@ -126,6 +118,9 @@ char *bootSTK; static int bootAP; static union descriptor *bootAPgdt; +static char resched_name[NR_CPUS][15]; +static char callfunc_name[NR_CPUS][15]; + /* Free these after use */ void *bootstacks[MAXCPU]; @@ -139,6 +134,9 @@ vm_offset_t smp_tlb_addr1; vm_offset_t smp_tlb_addr2; volatile int smp_tlb_wait; +typedef void call_data_func_t(uintptr_t , uintptr_t); + + #ifdef COUNT_IPIS /* Interrupt counts. */ #ifdef IPI_PREEMPTION @@ -179,8 +177,6 @@ static int cpu_apic_ids[MAXCPU]; /* Holds pending bitmap based IPIs per CPU */ static volatile u_int cpu_ipi_pending[MAXCPU]; -static u_int boot_address; - static void assign_cpu_ids(void); static void set_interrupt_apic_ids(void); static int start_all_aps(void); @@ -191,6 +187,7 @@ static u_int hyperthreading_cpus; static cpumask_t hyperthreading_cpus_mask; extern void Xhypervisor_callback(void); extern void failsafe_callback(void); +extern void pmap_lazyfix_action(void); void mp_topology(void) @@ -320,40 +317,6 @@ cpu_mp_start(void) cpu_ipi_pending[i] = 0; } -#if 0 - /* - * IPI list that has to be converted to Xen - * - */ - /* Install an inter-CPU IPI for TLB invalidation */ - setidt(IPI_INVLTLB, IDTVEC(invltlb), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - setidt(IPI_INVLPG, IDTVEC(invlpg), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - setidt(IPI_INVLRNG, IDTVEC(invlrng), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - - /* Install an inter-CPU IPI for cache invalidation. */ - setidt(IPI_INVLCACHE, IDTVEC(invlcache), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - - /* Install an inter-CPU IPI for lazy pmap release */ - setidt(IPI_LAZYPMAP, IDTVEC(lazypmap), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - - /* Install an inter-CPU IPI for all-CPU rendezvous */ - setidt(IPI_RENDEZVOUS, IDTVEC(rendezvous), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - - /* Install generic inter-CPU IPI handler */ - setidt(IPI_BITMAP_VECTOR, IDTVEC(ipi_intr_bitmap_handler), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - - /* Install an inter-CPU IPI for CPU stop/restart */ - setidt(IPI_STOP, IDTVEC(cpustop), - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#endif - /* Set boot_cpu_id if needed. */ if (boot_cpu_id == -1) { boot_cpu_id = PCPU_GET(apic_id); @@ -376,6 +339,151 @@ cpu_mp_start(void) set_interrupt_apic_ids(); } + +static void +iv_rendezvous(uintptr_t a, uintptr_t b) +{ + smp_rendezvous_action(); +} + +static void +iv_invltlb(uintptr_t a, uintptr_t b) +{ + xen_tlb_flush(); +} + +static void +iv_invlpg(uintptr_t a, uintptr_t b) +{ + xen_invlpg(a); +} + +static void +iv_invlrng(uintptr_t a, uintptr_t b) +{ + vm_offset_t start = (vm_offset_t)a; + vm_offset_t end = (vm_offset_t)b; + + while (start < end) { + xen_invlpg(start); + start += PAGE_SIZE; + } +} + + +static void +iv_invlcache(uintptr_t a, uintptr_t b) +{ + + wbinvd(); +} + +static void +iv_lazypmap(uintptr_t a, uintptr_t b) +{ + pmap_lazyfix_action(); +} + + +static void +iv_noop(uintptr_t a, uintptr_t b) +{ +} + +static call_data_func_t *ipi_vectors[IPI_BITMAP_VECTOR] = +{ + iv_noop, + iv_noop, + iv_rendezvous, + iv_invltlb, + iv_invlpg, + iv_invlrng, + iv_invlcache, + iv_lazypmap, +}; + +/* + * Reschedule call back. Nothing to do, + * all the work is done automatically when + * we return from the interrupt. + */ +static void +smp_reschedule_interrupt(void *unused) +{ + int cpu = PCPU_GET(cpuid); + u_int ipi_bitmap; + + ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]); + +#ifdef IPI_PREEMPTION + if (ipi_bitmap & (1 << IPI_PREEMPT)) { +#ifdef COUNT_IPIS + *ipi_preempt_counts[cpu]++; +#endif + mtx_lock_spin(&sched_lock); + /* Don't preempt the idle thread */ + if (curthread != PCPU_GET(idlethread)) { + struct thread *running_thread = curthread; + if (running_thread->td_critnest > 1) + running_thread->td_owepreempt = 1; + else + mi_switch(SW_INVOL | SW_PREEMPT, NULL); + } + mtx_unlock_spin(&sched_lock); + } +#endif + + if (ipi_bitmap & (1 << IPI_AST)) { +#ifdef COUNT_IPIS + *ipi_ast_counts[cpu]++; +#endif + /* Nothing to do for AST */ + } +} + +struct _call_data { + uint16_t func_id; + uint16_t wait; + uintptr_t arg1; + uintptr_t arg2; + atomic_t started; + atomic_t finished; +}; + +static struct _call_data *call_data; + +static void +smp_call_function_interrupt(void *arg) +{ + call_data_func_t *func; + uintptr_t arg1 = call_data->arg1; + uintptr_t arg2 = call_data->arg2; + int wait = call_data->wait; + atomic_t *started = &call_data->started; + atomic_t *finished = &call_data->finished; + + if (call_data->func_id > IPI_BITMAP_VECTOR) + panic("invalid function id %u", call_data->func_id); + + func = ipi_vectors[call_data->func_id]; + /* + * Notify initiating CPU that I've grabbed the data and am + * about to execute the function + */ + mb(); + atomic_inc(started); + /* + * At this point the info structure may be out of scope unless wait==1 + */ + (*func)(arg1, arg2); + + if (wait) { + mb(); + atomic_inc(finished); + } + atomic_add_int(&smp_tlb_wait, 1); +} + /* * Print various information about the SMP system hardware and setup. */ @@ -399,6 +507,61 @@ cpu_mp_announce(void) } } +static int +xen_smp_intr_init(unsigned int cpu) +{ + int rc; + + per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1; + + sprintf(resched_name[cpu], "resched%u", cpu); + rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, + cpu, + resched_name[cpu], + smp_reschedule_interrupt, + INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE); + + printf("cpu=%d irq=%d vector=%d\n", + cpu, rc, RESCHEDULE_VECTOR); + + per_cpu(resched_irq, cpu) = rc; + + sprintf(callfunc_name[cpu], "callfunc%u", cpu); + rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR, + cpu, + callfunc_name[cpu], + smp_call_function_interrupt, + INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE); + if (rc < 0) + goto fail; + per_cpu(callfunc_irq, cpu) = rc; + + printf("cpu=%d irq=%d vector=%d\n", + cpu, rc, CALL_FUNCTION_VECTOR); + + + if ((cpu != 0) && ((rc = ap_cpu_initclocks(cpu)) != 0)) + goto fail; + + return 0; + + fail: + if (per_cpu(resched_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); + if (per_cpu(callfunc_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); + return rc; +} + +static void +xen_smp_intr_init_cpus(void *unused) +{ + int i; + + for (i = 0; i < mp_ncpus; i++) + xen_smp_intr_init(i); +} + #define MTOPSIZE (1<<(14 + PAGE_SHIFT)) /* * AP CPU's call this to initialize themselves. @@ -613,10 +776,6 @@ start_all_aps(void) bootstacks[cpu] = (char *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE); - /* setup a vector to our boot code */ - *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET; - *((volatile u_short *) WARMBOOT_SEG) = (boot_address >> 4); - bootSTK = (char *)bootstacks[cpu] + KSTACK_PAGES * PAGE_SIZE - 4; bootAP = cpu; bootAPgdt = gdt + (512*cpu); @@ -703,7 +862,6 @@ cpu_initialize_context(unsigned int cpu) * Page 0,[0-3] PTD * Page 1, [4] boot stack * Page [5] PDPT - * */ for (i = 0; i < NPGPTD + 2; i++) { @@ -881,19 +1039,24 @@ static void smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2) { u_int ncpu; + struct _call_data data; + call_data = &data; + ncpu = mp_ncpus - 1; /* does not shootdown self */ if (ncpu < 1) return; /* no other cpus */ if (!(read_eflags() & PSL_I)) panic("%s: interrupts disabled", __func__); mtx_lock_spin(&smp_ipi_mtx); - smp_tlb_addr1 = addr1; - smp_tlb_addr2 = addr2; + call_data->func_id = vector; + call_data->arg1 = addr1; + call_data->arg2 = addr2; atomic_store_rel_int(&smp_tlb_wait, 0); ipi_all_but_self(vector); while (smp_tlb_wait < ncpu) ia32_pause(); + call_data = NULL; mtx_unlock_spin(&smp_ipi_mtx); } @@ -901,6 +1064,7 @@ static void smp_targeted_tlb_shootdown(u_int mask, u_int vector, vm_offset_t addr1, vm_offset_t addr2) { int ncpu, othercpus; + struct _call_data data; othercpus = mp_ncpus - 1; if (mask == (u_int)-1) { @@ -925,8 +1089,10 @@ smp_targeted_tlb_shootdown(u_int mask, u if (!(read_eflags() & PSL_I)) panic("%s: interrupts disabled", __func__); mtx_lock_spin(&smp_ipi_mtx); - smp_tlb_addr1 = addr1; - smp_tlb_addr2 = addr2; + call_data = &data; + call_data->func_id = vector; + call_data->arg1 = addr1; + call_data->arg2 = addr2; atomic_store_rel_int(&smp_tlb_wait, 0); if (mask == (u_int)-1) ipi_all_but_self(vector); @@ -934,6 +1100,7 @@ smp_targeted_tlb_shootdown(u_int mask, u ipi_selected(mask, vector); while (smp_tlb_wait < ncpu) ia32_pause(); + call_data = NULL; mtx_unlock_spin(&smp_ipi_mtx); } @@ -1019,56 +1186,21 @@ smp_masked_invlpg_range(u_int mask, vm_o } } - -void -ipi_bitmap_handler(struct clockframe frame) -{ - int cpu = PCPU_GET(cpuid); - u_int ipi_bitmap; - - ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]); - -#ifdef IPI_PREEMPTION - if (ipi_bitmap & (1 << IPI_PREEMPT)) { -#ifdef COUNT_IPIS - *ipi_preempt_counts[cpu]++; -#endif - mtx_lock_spin(&sched_lock); - /* Don't preempt the idle thread */ - if (curthread != PCPU_GET(idlethread)) { - struct thread *running_thread = curthread; - if (running_thread->td_critnest > 1) - running_thread->td_owepreempt = 1; - else - mi_switch(SW_INVOL | SW_PREEMPT, NULL); - } - mtx_unlock_spin(&sched_lock); - } -#endif - - if (ipi_bitmap & (1 << IPI_AST)) { -#ifdef COUNT_IPIS - *ipi_ast_counts[cpu]++; -#endif - /* Nothing to do for AST */ - } -} - /* * send an IPI to a set of cpus. */ void -ipi_selected(u_int32_t cpus, u_int ipi) +ipi_selected(uint32_t cpus, u_int ipi) { int cpu; u_int bitmap = 0; u_int old_pending; u_int new_pending; - + if (IPI_IS_BITMAPED(ipi)) { bitmap = 1 << ipi; ipi = IPI_BITMAP_VECTOR; - } + } CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi); while ((cpu = ffs(cpus)) != 0) { @@ -1084,11 +1216,15 @@ ipi_selected(u_int32_t cpus, u_int ipi) new_pending = old_pending | bitmap; } while (!atomic_cmpset_int(&cpu_ipi_pending[cpu],old_pending, new_pending)); - if (old_pending) - continue; + if (!old_pending) + ipi_pcpu(cpu, RESCHEDULE_VECTOR); + continue; + } - ipi_pcpu(cpu, ipi); + KASSERT(call_data != NULL, ("call_data not set")); + + ipi_pcpu(cpu, CALL_FUNCTION_VECTOR); } } @@ -1112,7 +1248,7 @@ ipi_all_but_self(u_int ipi) { CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); - ipi_selected(all_cpus & ~(1< + * Copyright (c) 1996, by Steve Passe + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 04:44:22 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 79E3B1065671; Sat, 25 Oct 2008 04:44:22 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 68BE38FC0C; Sat, 25 Oct 2008 04:44:22 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9P4iMvQ021463; Sat, 25 Oct 2008 04:44:22 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9P4iMGC021462; Sat, 25 Oct 2008 04:44:22 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200810250444.m9P4iMGC021462@svn.freebsd.org> From: Kip Macy Date: Sat, 25 Oct 2008 04:44:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184247 - projects/releng_6_xen/sys/i386/xen X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 04:44:22 -0000 Author: kmacy Date: Sat Oct 25 04:44:22 2008 New Revision: 184247 URL: http://svn.freebsd.org/changeset/base/184247 Log: handle case where actual eflags is passed to restore Modified: projects/releng_6_xen/sys/i386/xen/xen_machdep.c Modified: projects/releng_6_xen/sys/i386/xen/xen_machdep.c ============================================================================== --- projects/releng_6_xen/sys/i386/xen/xen_machdep.c Sat Oct 25 04:40:22 2008 (r184246) +++ projects/releng_6_xen/sys/i386/xen/xen_machdep.c Sat Oct 25 04:44:22 2008 (r184247) @@ -349,6 +349,9 @@ void xen_restore_flags(u_int eflags) { + if (eflags > 1) + eflags = ((eflags & PSL_I) == 0); + __restore_flags(eflags); } From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 10:23:24 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B925A1065673; Sat, 25 Oct 2008 10:23:24 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A80348FC13; Sat, 25 Oct 2008 10:23:24 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9PANO3b029992; Sat, 25 Oct 2008 10:23:24 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9PANOSx029991; Sat, 25 Oct 2008 10:23:24 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810251023.m9PANOSx029991@svn.freebsd.org> From: Ulf Lilleengen Date: Sat, 25 Oct 2008 10:23:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184255 - projects/csup_cvsmode/contrib/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 10:23:24 -0000 Author: lulf Date: Sat Oct 25 10:23:24 2008 New Revision: 184255 URL: http://svn.freebsd.org/changeset/base/184255 Log: - Add size_t format specifier to proto_printf. Modified: projects/csup_cvsmode/contrib/csup/proto.c Modified: projects/csup_cvsmode/contrib/csup/proto.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/proto.c Sat Oct 25 08:31:20 2008 (r184254) +++ projects/csup_cvsmode/contrib/csup/proto.c Sat Oct 25 10:23:24 2008 (r184255) @@ -768,6 +768,7 @@ proto_printf(struct stream *wr, const ch va_list ap; char *cp, *s, *attr; ssize_t n; + size_t size; off_t off; int rv, val, ignore; char c; @@ -834,6 +835,11 @@ proto_printf(struct stream *wr, const ch rv = proto_escape(wr, attr); free(attr); break; + case 'z': + size = va_arg(ap, size_t); + rv = stream_printf(wr, "%zu", size); + break; + case '%': n = stream_write(wr, "%", 1); if (n == -1) From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 10:52:23 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1BDD81065679; Sat, 25 Oct 2008 10:52:23 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0A9C28FC0C; Sat, 25 Oct 2008 10:52:23 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9PAqM4o030501; Sat, 25 Oct 2008 10:52:22 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9PAqMG2030499; Sat, 25 Oct 2008 10:52:22 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810251052.m9PAqMG2030499@svn.freebsd.org> From: Ulf Lilleengen Date: Sat, 25 Oct 2008 10:52:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184256 - projects/csup_cvsmode/contrib/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 10:52:23 -0000 Author: lulf Date: Sat Oct 25 10:52:22 2008 New Revision: 184256 URL: http://svn.freebsd.org/changeset/base/184256 Log: - Implement support for retrieving a size_t type from the protocol stream. Modified: projects/csup_cvsmode/contrib/csup/proto.c projects/csup_cvsmode/contrib/csup/proto.h Modified: projects/csup_cvsmode/contrib/csup/proto.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/proto.c Sat Oct 25 10:23:24 2008 (r184255) +++ projects/csup_cvsmode/contrib/csup/proto.c Sat Oct 25 10:52:22 2008 (r184256) @@ -950,6 +950,26 @@ proto_get_int(char **s, int *val, int ba } /* + * Get a size_t token. + */ +int +proto_get_sizet(char **s, size_t *val, int base) +{ + unsigned long long tmp; + char *cp, *end; + + cp = proto_get_ascii(s); + if (cp == NULL) + return (-1); + errno = 0; + tmp = strtoll(cp, &end, base); + if (errno || *end != '\0') + return (-1); + *val = (size_t)tmp; + return (0); +} + +/* * Get a time_t token. * * Ideally, we would use an intmax_t and strtoimax() here, but strtoll() Modified: projects/csup_cvsmode/contrib/csup/proto.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/proto.h Sat Oct 25 10:23:24 2008 (r184255) +++ projects/csup_cvsmode/contrib/csup/proto.h Sat Oct 25 10:52:22 2008 (r184256) @@ -44,6 +44,7 @@ int proto_printf(struct stream *, const char *proto_get_ascii(char **); char *proto_get_rest(char **); int proto_get_int(char **, int *, int); +int proto_get_sizet(char **, size_t *, int); int proto_get_time(char **, time_t *); #endif /* !_PROTO_H_ */ From owner-svn-src-projects@FreeBSD.ORG Sat Oct 25 10:54:28 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A82D91065675; Sat, 25 Oct 2008 10:54:28 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 959B38FC08; Sat, 25 Oct 2008 10:54:28 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9PAsS4u030584; Sat, 25 Oct 2008 10:54:28 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9PAsSmS030578; Sat, 25 Oct 2008 10:54:28 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810251054.m9PAsSmS030578@svn.freebsd.org> From: Ulf Lilleengen Date: Sat, 25 Oct 2008 10:54:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184257 - projects/csup_cvsmode/contrib/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Oct 2008 10:54:28 -0000 Author: lulf Date: Sat Oct 25 10:54:28 2008 New Revision: 184257 URL: http://svn.freebsd.org/changeset/base/184257 Log: - Implement rsync support in csup, which is chosen as a protocol for regular files if the client supports it. The support is implemented with an API to operate on files, calculating the rolling checksum and md5 checksum for the blocks etc. - Remove unneeded stream_filter_stop and stream_flush before stream_close. Added: projects/csup_cvsmode/contrib/csup/rsyncfile.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rsyncfile.h (contents, props changed) Modified: projects/csup_cvsmode/contrib/csup/Makefile projects/csup_cvsmode/contrib/csup/config.c projects/csup_cvsmode/contrib/csup/detailer.c projects/csup_cvsmode/contrib/csup/updater.c Modified: projects/csup_cvsmode/contrib/csup/Makefile ============================================================================== --- projects/csup_cvsmode/contrib/csup/Makefile Sat Oct 25 10:52:22 2008 (r184256) +++ projects/csup_cvsmode/contrib/csup/Makefile Sat Oct 25 10:54:28 2008 (r184257) @@ -10,7 +10,7 @@ PROG= csup SRCS= attrstack.c config.c detailer.c diff.c fattr.c fixups.c fnmatch.c \ globtree.c idcache.c keyword.c lister.c main.c misc.c mux.c parse.y \ pathcomp.c proto.c status.c stream.c threads.c token.l updater.c \ - rcsfile.c rcsparse.c lex.rcs.c + rcsfile.c rcsparse.c lex.rcs.c rsyncfile.c CFLAGS+= -I. -I${.CURDIR} -g -pthread -DHAVE_FFLAGS -DNDEBUG WARNS?= 1 Modified: projects/csup_cvsmode/contrib/csup/config.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/config.c Sat Oct 25 10:52:22 2008 (r184256) +++ projects/csup_cvsmode/contrib/csup/config.c Sat Oct 25 10:54:28 2008 (r184257) @@ -133,8 +133,6 @@ config_init(const char *file, struct col coll->co_options &= ~CO_CHECKRCS; /* In recent versions, we always try to set the file modes. */ coll->co_options |= CO_SETMODE; - /* XXX We don't support the rsync updating algorithm yet. */ - coll->co_options |= CO_NORSYNC; error = config_parse_refusefiles(coll); if (error) goto bad; Modified: projects/csup_cvsmode/contrib/csup/detailer.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/detailer.c Sat Oct 25 10:52:22 2008 (r184256) +++ projects/csup_cvsmode/contrib/csup/detailer.c Sat Oct 25 10:54:28 2008 (r184257) @@ -43,6 +43,7 @@ #include "mux.h" #include "proto.h" #include "rcsfile.h" +#include "rsyncfile.h" #include "status.h" #include "stream.h" @@ -67,6 +68,7 @@ static int detailer_dofile_co(struct det static int detailer_dofile_rcs(struct detailer *, struct coll *, char *, char *); static int detailer_dofile_regular(struct detailer *, char *, char *); +static int detailer_dofile_rsync(struct detailer *, char *, char *); static int detailer_checkrcsattr(struct detailer *, struct coll *, char *, struct fattr *, int); int detailer_send_details(struct detailer *, struct coll *, char *, @@ -106,7 +108,6 @@ detailer(void *arg) xasprintf(&args->errmsg, "Detailer failed: " "Network read failure: %s", strerror(errno)); } - lprintf(-1, "Error is '%s'\n", args->errmsg); args->status = STATUS_TRANSIENTFAILURE; break; case DETAILER_ERR_WRITE: @@ -343,7 +344,6 @@ detailer_coll(struct detailer *d, struct lprintf(-1, "Server warning: %s\n", msg); break; default: - lprintf(-1, "Line: %s, cmd %s\n", line, cmd); return (DETAILER_ERR_PROTO); } stream_flush(wr); @@ -390,6 +390,33 @@ detailer_dofile_regular(struct detailer } /* + * Tell the server to update a file with the rsync algorithm. + */ +static int +detailer_dofile_rsync(struct detailer *d, char *name, char *path) +{ + struct stream *wr; + struct rsyncfile *rf; + + rf = rsync_open(path, 0, 1); + if (rf == NULL) { + /* Fallback if we fail in opening it. */ + proto_printf(wr, "A %s\n", name); + return (0); + } + wr = d->wr; + proto_printf(wr, "r %s %z %z\n", name, rsync_filesize(rf), + rsync_blocksize(rf)); + /* Detail the blocks. */ + while (rsync_nextblock(rf) != 0) { + proto_printf(wr, "%s %s\n", rsync_rsum(rf), rsync_blockmd5(rf)); + lprintf(-1, "%s %s\n", rsync_rsum(rf), rsync_blockmd5(rf)); + } + proto_printf(wr, ".\n"); + rsync_close(rf); +} + +/* * Tell the server to update an RCS file that we have, or send it if we don't. */ static int @@ -572,6 +599,9 @@ detailer_send_details(struct detailer *d } else if (fattr_type(fa) == FT_FILE) { if (isrcs(name, &len) && !(coll->co_options & CO_NORCS)) { detailer_dofile_rcs(d, coll, name, path); + } else if (!(coll->co_options & CO_NORSYNC) || + !globtree_test(coll->co_norsync, name)) { + detailer_dofile_rsync(d, name, path); } else { detailer_dofile_regular(d, name, path); } Added: projects/csup_cvsmode/contrib/csup/rsyncfile.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/csup_cvsmode/contrib/csup/rsyncfile.c Sat Oct 25 10:54:28 2008 (r184257) @@ -0,0 +1,228 @@ +/*- + * Copyright (c) 2008, Ulf Lilleengen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "misc.h" +#include "fattr.h" +#include "rsyncfile.h" + +#define MINBLOCKSIZE 1024 +#define MAXBLOCKSIZE (16 * 1024) +#define RECEIVEBUFFERSIZE (15 * 1024) +#define BLOCKINFOSIZE 26 +#define SEARCHREGION 10 +#define MAXBLOCKS (RECEIVEBUFFERSIZE / BLOCKINFOSIZE) + +#define CHAR_OFFSET 3 +#define RSUM_SIZE 9 + +struct rsyncfile { + char *start; + char *buf; + char *end; + size_t blocksize; + size_t fsize; + struct fattr *fa; + int fd; + + char *blockptr; + int blocknum; + char blockmd5[MD5_DIGEST_SIZE]; + char rsumstr[RSUM_SIZE]; + uint32_t rsum; +}; + +static size_t rsync_chooseblocksize(size_t); +static uint32_t rsync_rollsum(uint8_t *, size_t); + +/* Open a file and initialize variable for rsync operation. */ +struct rsyncfile * +rsync_open(char *path, size_t blocksize, int read) +{ + struct rsyncfile *rf; + struct stat st; + int error; + + rf = malloc(sizeof(*rf)); + if (rf == NULL) + return (NULL); + error = stat(path, &st); + if (error) { + free(rf); + return (NULL); + } + rf->fsize = st.st_size; + rf->fa = fattr_fromstat(&st); + + rf->fd = open(path, read ? O_RDONLY : O_RDWR); + if (rf->fd < 0) { + free(rf); + return (NULL); + } + rf->buf = mmap(0, rf->fsize, PROT_READ, MAP_SHARED, rf->fd, 0); + if (rf->buf == MAP_FAILED) { + free(rf); + return (NULL); + } + rf->start = rf->buf; + rf->end = rf->buf + rf->fsize; + rf->blocksize = (blocksize == 0 ? rsync_chooseblocksize(rf->fsize) : + blocksize); + rf->blockptr = rf->buf; + rf->blocknum = 0; + return (rf); +} + +/* Close and free all resources related to an rsync file transfer. */ +int +rsync_close(struct rsyncfile *rf) +{ + int error; + + error = munmap(rf->buf, rf->fsize); + if (error) + return (error); + close(rf->fd); + free(rf); +} + +/* + * Choose the most appropriate block size for an rsync transfer. Modeled + * algorithm after cvsup. + */ +static size_t +rsync_chooseblocksize(size_t fsize) +{ + size_t bestrem, blocksize, bs, hisearch, losearch, rem; + + blocksize = fsize / MAXBLOCKS; + losearch = blocksize - SEARCHREGION; + hisearch = blocksize + SEARCHREGION; + + if (losearch < MINBLOCKSIZE) { + losearch = MINBLOCKSIZE; + hisearch = losearch + (2 * SEARCHREGION); + } else if (hisearch > MAXBLOCKSIZE) { + hisearch = MAXBLOCKSIZE; + losearch = hisearch - (2 * SEARCHREGION); + } + + bestrem = MAXBLOCKSIZE; + for (bs = losearch; bs <= hisearch;) { + rem = fsize % bs; + if (rem < bestrem) { + bestrem = rem; + blocksize = bs; + } + } + return (bestrem); +} + +/* Get the next rsync block of a file. */ +int +rsync_nextblock(struct rsyncfile *rf) +{ + uint32_t rolling; + char *ptr; + MD5_CTX ctx; + size_t blocksize, i; + + if (rf->blockptr >= rf->end) + return (0); + blocksize = min((rf->end - rf->blockptr), rf->blocksize); + /* Calculate MD5 of the block. */ + MD5_Init(&ctx); + MD5_Update(&ctx, rf->blockptr, blocksize); + MD5_End(rf->blockmd5, &ctx); + + rf->rsum = rsync_rollsum(rf->blockptr, blocksize); + snprintf(rf->rsumstr, RSUM_SIZE, "%x", rf->rsum); + rf->blocknum++; + rf->blockptr += blocksize; + return (1); +} + +/* Get the rolling checksum of a file. */ +static uint32_t +rsync_rollsum(uint8_t *buf, size_t len) +{ + uint32_t a, b; + uint8_t *ptr, *limit; + + a = b = 0; + ptr = buf; + limit = buf + len; + + while (ptr < limit) { + a += *ptr + CHAR_OFFSET; + b += a; + ptr++; + } + return ((b << 16) | a); +} + +/* Get running sum so far. */ +char * +rsync_rsum(struct rsyncfile *rf) +{ + + return (rf->rsumstr); +} + +/* Get MD5 of current block. */ +char * +rsync_blockmd5(struct rsyncfile *rf) +{ + + return (rf->blockmd5); +} + +/* Accessor for blocksize. */ +size_t +rsync_blocksize(struct rsyncfile *rf) +{ + + return (rf->blocksize); +} + +/* Accessor for filesize. */ +size_t +rsync_filesize(struct rsyncfile *rf) +{ + + return (rf->fsize); +} Added: projects/csup_cvsmode/contrib/csup/rsyncfile.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/csup_cvsmode/contrib/csup/rsyncfile.h Sat Oct 25 10:54:28 2008 (r184257) @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2008, Ulf Lilleengen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _RSYNCFILE_H_ +#define _RSYNCFILE_H_ + +struct rsyncfile; + +struct rsyncfile *rsync_open(char *, size_t, int); +int rsync_nextblock(struct rsyncfile *); +char *rsync_rsum(struct rsyncfile *); +char *rsync_blockmd5(struct rsyncfile *); +int rsync_close(struct rsyncfile *); +size_t rsync_blocksize(struct rsyncfile *); +size_t rsync_filesize(struct rsyncfile *); + +#endif /* !_RSYNCFILE_H_ */ Modified: projects/csup_cvsmode/contrib/csup/updater.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/updater.c Sat Oct 25 10:52:22 2008 (r184256) +++ projects/csup_cvsmode/contrib/csup/updater.c Sat Oct 25 10:54:28 2008 (r184257) @@ -115,6 +115,8 @@ static int updater_rcsedit(struct updat char *); int updater_append_file(struct updater *, struct file_update *, off_t); +static int updater_rsync(struct updater *, struct file_update *, size_t); +static int updater_read_checkout(struct stream *, struct stream *); static struct file_update * fup_new(struct coll *coll, struct status *st) @@ -345,7 +347,7 @@ updater_docoll(struct updater *up, struc struct coll *coll; struct statusrec srbuf, *sr; struct fattr *rcsattr, *tmp; - char *cmd, *line, *msg, *attr; + char *cmd, *blocksize, *line, *msg, *attr; char *name, *tag, *date, *revdate; char *expand, *wantmd5, *revnum; char *optstr, *rcsopt, *pos; @@ -601,7 +603,30 @@ updater_docoll(struct updater *up, struc if (error) return (error); break; - case 'r': /* XXX: rsync support. */ + case 'r': + name = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + blocksize = proto_get_ascii(&line); + wantmd5 = proto_get_ascii(&line); + if (name == NULL || attr == NULL || blocksize == NULL || + wantmd5 == NULL) { + return (UPDATER_ERR_PROTO); + } + error = fup_prepare(fup, name, 0); + if (error) + return (UPDATER_ERR_PROTO); + sr->sr_type = SR_FILELIVE; + fup->wantmd5 = xstrdup(wantmd5); + fup->temppath = tempname(fup->destpath); + sr = &fup->srbuf; + sr->sr_file = xstrdup(name); + sr->sr_serverattr = fattr_decode(attr); + if (sr->sr_serverattr == NULL) + return (UPDATER_ERR_PROTO); + error = updater_rsync(up, fup, strtol(blocksize, NULL, + 10)); + if (error) + return (error); break; case 'I': @@ -1457,8 +1482,6 @@ updater_addfile(struct updater *up, stru remains -= nread; stream_write(to, buf, nread); } while (remains > 0); - stream_flush(to); - stream_filter_stop(to); stream_close(to); line = stream_getln(up->rd, NULL); if (line == NULL) @@ -1749,8 +1772,6 @@ updater_rcsedit(struct updater *up, stru } stream_filter_start(dest, STREAM_FILTER_MD5RCS, md5); error = rcsfile_write(rf, dest); - stream_flush(dest); - stream_filter_stop(dest); stream_close(dest); rcsfile_free(rf); if (error) @@ -1927,8 +1948,6 @@ updater_append_file(struct updater *up, bytes -= nread; stream_write(to, buf, nread); } while (bytes > 0); - stream_flush(to); - stream_filter_stop(to); stream_close(to); line = stream_getln(up->rd, NULL); @@ -1959,3 +1978,142 @@ updater_append_file(struct updater *up, return (error); return (0); } + +/* + * Read file data from stream of checkout commands, and write it to the + * destination. + */ +static int +updater_read_checkout(struct stream *src, struct stream *dest) +{ + char *line; + size_t size; + ssize_t nbytes; + int error, first; + + first = 1; + line = stream_getln(src, &size); + while (line != NULL) { + if (line[size - 1] == '\n') + size--; + if ((size == 1 && *line == '.') || + (size == 2 && strncmp(line, ".+", 2) == 0)) + break; + if (size >= 2 && strncmp(line, "..", 2) == 0) { + size--; + line++; + } + if (!first) { + nbytes = stream_write(dest, "\n", 1); + if (nbytes == -1) + return (UPDATER_ERR_MSG); + } + nbytes = stream_write(dest, line, size); + if (nbytes == -1) + return (UPDATER_ERR_MSG); + line = stream_getln(src, &size); + first = 0; + } + if (line == NULL) + return (UPDATER_ERR_READ); + if (size == 1 && *line == '.') { + nbytes = stream_write(dest, "\n", 1); + if (nbytes == -1) + return (UPDATER_ERR_MSG); + } + return (0); +} + +/* Update file using the rsync protocol. */ +static int +updater_rsync(struct updater *up, struct file_update *fup, size_t blocksize) +{ + struct statusrec *sr; + struct coll *coll; + struct stream *to; + char md5[MD5_DIGEST_SIZE]; + char *buf, *line; + int error, orig; + size_t size, blocknum, blockstart, blockcount; + ssize_t nbytes; + + sr = &fup->srbuf; + + lprintf(1, " Rsync %s\n", fup->coname); + /* First open all files that we are going to work on. */ + to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC, + 0600); + if (to == NULL) { + xasprintf(&up->errmsg, "%s: Cannot create: %s", + fup->temppath, strerror(errno)); + return (UPDATER_ERR_MSG); + } + orig = open(fup->destpath, O_RDONLY); + if (orig < 0) { + xasprintf(&up->errmsg, "%s: Cannot open: %s", + fup->destpath, strerror(errno)); + return (UPDATER_ERR_MSG); + } + stream_filter_start(to, STREAM_FILTER_MD5, md5); + + error = updater_read_checkout(up->rd, to); + if (error) { + xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath, + strerror(errno)); + return (error); + } + + /* Buffer must contain blocksize bytes. */ + buf = xmalloc(blocksize); + /* Done with the initial text, read and write chunks. */ + line = stream_getln(up->rd, NULL); + while (line != NULL) { + if (strcmp(line, ".") == 0) + break; + error = UPDATER_ERR_PROTO; + if (proto_get_sizet(&line, &blockstart, 10) != 0) + goto bad; + if (proto_get_sizet(&line, &blockcount, 10) != 0) + goto bad; + /* Read blocks from original file. */ + lseek(orig, SEEK_SET, (blocksize * blockstart)); + blocknum = 0; + error = UPDATER_ERR_MSG; + for (blocknum = 0; blocknum < blockcount; blocknum++) { + nbytes = read(orig, buf, blocksize); + if (nbytes < 0) { + xasprintf(&up->errmsg, "%s: Cannot read: %s", + fup->destpath, strerror(errno)); + goto bad; + } + nbytes = stream_write(to, buf, nbytes); + if (nbytes == -1) { + xasprintf(&up->errmsg, "%s: Cannot write: %s", + fup->temppath, strerror(errno)); + goto bad; + } + } + /* Get the remaining text from the server. */ + error = updater_read_checkout(up->rd, to); + if (error) { + xasprintf(&up->errmsg, "%s: Cannot write: %s", + fup->temppath, strerror(errno)); + goto bad; + } + line = stream_getln(up->rd, NULL); + } + stream_close(to); + close(orig); + + sr->sr_clientattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); + if (sr->sr_clientattr == NULL) + return (UPDATER_ERR_PROTO); + fattr_override(sr->sr_clientattr, sr->sr_serverattr, + FA_MODTIME | FA_MASK); + + error = updater_updatefile(up, fup, md5, 0); + fup->wantmd5 = NULL; /* So that it doesn't get freed. */ +bad: + free(buf); + return (error); +}