From owner-svn-src-projects@FreeBSD.ORG Thu Jan 1 20:47:10 2009 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 81BE2106566C; Thu, 1 Jan 2009 20:47:10 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 560F08FC25; Thu, 1 Jan 2009 20:47:10 +0000 (UTC) (envelope-from rwatson@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 n01KlAFh078636; Thu, 1 Jan 2009 20:47:10 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n01KlAH6078635; Thu, 1 Jan 2009 20:47:10 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200901012047.n01KlAH6078635@svn.freebsd.org> From: Robert Watson Date: Thu, 1 Jan 2009 20:47: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: r186685 - in projects/pnet: . sys 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: Thu, 01 Jan 2009 20:47:10 -0000 Author: rwatson Date: Thu Jan 1 20:47:09 2009 New Revision: 186685 URL: http://svn.freebsd.org/changeset/base/186685 Log: Create pnet, parallel network stack, project branch. This branch will hold a variety of bits and pieces I have in flight, including netisr2 (multi-CPU netisr model), IP subset (multiple sockets with the same binding for load-balancing purposes), and other WIPs. Added: projects/pnet/ projects/pnet/sys/ (props changed) - copied from r186684, head/sys/ From owner-svn-src-projects@FreeBSD.ORG Thu Jan 1 22:11:44 2009 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 B7A73106566C; Thu, 1 Jan 2009 22:11:44 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A2C088FC1B; Thu, 1 Jan 2009 22:11:44 +0000 (UTC) (envelope-from rwatson@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 n01MBiPL080225; Thu, 1 Jan 2009 22:11:44 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n01MBist080219; Thu, 1 Jan 2009 22:11:44 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200901012211.n01MBist080219@svn.freebsd.org> From: Robert Watson Date: Thu, 1 Jan 2009 22:11:44 +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: r186686 - projects/pnet/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: Thu, 01 Jan 2009 22:11:45 -0000 Author: rwatson Date: Thu Jan 1 22:11:44 2009 New Revision: 186686 URL: http://svn.freebsd.org/changeset/base/186686 Log: Add IP SUBSET patch to pnet branch: the IP_SUBSET socket option allows identically bound UDP sockets to balance load between them using various strategies, including random assignment, flow-based assignment, CPU-based assignment, and kernel thread ID-based assignment. UDP applications, such as BIND, memcached, etc, can create multiple sockets, each with SO_REUSEPORT set, followed by specifying their index among a set of matching sockets all servicing the same port number. Modified: projects/pnet/sys/netinet/in.h projects/pnet/sys/netinet/in_pcb.c projects/pnet/sys/netinet/in_pcb.h projects/pnet/sys/netinet/in_proto.c projects/pnet/sys/netinet/udp_usrreq.c projects/pnet/sys/netinet/udp_var.h Modified: projects/pnet/sys/netinet/in.h ============================================================================== --- projects/pnet/sys/netinet/in.h Thu Jan 1 20:47:09 2009 (r186685) +++ projects/pnet/sys/netinet/in.h Thu Jan 1 22:11:44 2009 (r186686) @@ -486,6 +486,21 @@ __END_DECLS #define MCAST_BLOCK_SOURCE 84 /* block a source */ #define MCAST_UNBLOCK_SOURCE 85 /* unblock a source */ +/* Binding subsets. */ +#define IP_SUBSET 86 /* get/set binding subset */ + +struct ip_subset { + u_int is_strategy; + u_int is_count; + u_int is_member; +}; + +#define IP_SUBSET_STRATEGY_DISABLED 0 +#define IP_SUBSET_STRATEGY_FLOW 1 +#define IP_SUBSET_STRATEGY_RANDOM 2 +#define IP_SUBSET_STRATEGY_THREADID 3 +#define IP_SUBSET_STRATEGY_CPU 4 + /* * Defaults and limits for options */ Modified: projects/pnet/sys/netinet/in_pcb.c ============================================================================== --- projects/pnet/sys/netinet/in_pcb.c Thu Jan 1 20:47:09 2009 (r186685) +++ projects/pnet/sys/netinet/in_pcb.c Thu Jan 1 22:11:44 2009 (r186686) @@ -204,6 +204,7 @@ in_pcballoc(struct socket *so, struct in inp->inp_socket = so; inp->inp_cred = crhold(so->so_cred); inp->inp_inc.inc_fibnum = so->so_fibnum; + inp->inp_subset_strategy = IP_SUBSET_STRATEGY_DISABLED; #ifdef MAC error = mac_inpcb_init(inp, M_NOWAIT); if (error != 0) @@ -1284,12 +1285,114 @@ in_pcblookup_local(struct inpcbinfo *pcb #undef INP_LOOKUP_MAPPED_PCB_COST /* + * Implement various subsetting strategies: determine whether a particular + * inpcb, implementing a particular strategy, matches the passed tuple or + * not. + */ +static int +in_subset_match(struct inpcb *inp, struct in_addr faddr, u_short fport, + struct in_addr laddr, u_short lport, u_short ip_id, u_int32_t flowid) +{ + + switch (inp->inp_subset_strategy) { + case IP_SUBSET_STRATEGY_FLOW: + /* + * If the packet has a flow tag, use that, but otherwise, + * calculate our own flow tag using the IP/port tuple. + */ + if (flowid != 0) { + if ((flowid % inp->inp_subset_count) == + inp->inp_subset_member) + return (1); + } else { + /* + * XXXRW: This hash is not the hash that you are + * looking for. + */ + if (((faddr.s_addr ^ laddr.s_addr ^ fport ^ lport) % + inp->inp_subset_count) == inp->inp_subset_member) + return (1); + } + return (0); + + case IP_SUBSET_STRATEGY_RANDOM: + /* + * If there is a flow tag, use that and the IP ID as a source + * of entropy. Otherwise, calculate our own flow tag as + * above and combine with the IP ID. + * + * XXXRW: This hash is also not the hash that you are looking + * for. + */ + if (flowid != 0) { + if (((flowid ^ ip_id) % inp->inp_subset_count) == + inp->inp_subset_member) + return (1); + } else { + if (((faddr.s_addr ^ laddr.s_addr ^ fport ^ lport ^ + ip_id) % inp->inp_subset_count) == + inp->inp_subset_member) + return (1); + } + return (0); + + case IP_SUBSET_STRATEGY_THREADID: + /* + * Experiment: pick the socket to use based on the kernel + * thread ID processing the packet. This will be fixed for + * particular RSS input queues, so will assign work to a + * particular socket based on which input queue it came from. + * This doesn't attempt to balance the work at all, simply + * ensure that datagrams local to a particular CPU are + * assigned to the same socket consistently. + */ + if ((curthread->td_tid % inp->inp_subset_count) == + inp->inp_subset_member) + return (1); + return (0); + + case IP_SUBSET_STRATEGY_CPU: + /* + * Experimental: packets from the same CPU will always get + * assigned to the same socket. Doesn't attempt to load + * balance or maintain ordering, as source threads may not + * always be on the same CPU. However, may achieve a more + * even or predictable balance than + * IP_SUBSET_STRATEGY_THREADID. + * + * This might be quite a bit more interesting if sockets had + * a formal affinity themselves, as then we could direct + * datagrams to that explicitly. + */ + if ((curcpu % inp->inp_subset_count) == + inp->inp_subset_member) + return (1); + return (0); + + /* case IP_SUBSET_STRATEGY_FILLSOCK: */ + /* + * In this theoretical mode, we attempt to fill sockets in + * the order they are matched, and don't move onto the next + * socket unless the previous one is filled. This requires + * us to peak up a layer and see if there is room for the + * current datagram; this proves somewhat tricky as we need + * to make sure we don't return ICMP when the last one proves + * full, so we don't try to do that yet. + */ + + default: + panic("in_subset_match: strategy %d", + inp->inp_subset_strategy); + } +} + +/* * Lookup PCB in hash list. */ struct inpcb * -in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, - u_int fport_arg, struct in_addr laddr, u_int lport_arg, int wildcard, - struct ifnet *ifp) +in_pcblookup_hash_full(struct inpcbinfo *pcbinfo, struct in_addr faddr, + u_int fport_arg, struct in_addr laddr, u_int lport_arg, u_short ip_id, + u_int32_t flowid, int wildcard, struct ifnet *ifp) { struct inpcbhead *head; struct inpcb *inp, *tmpinp; @@ -1309,20 +1412,25 @@ in_pcblookup_hash(struct inpcbinfo *pcbi if ((inp->inp_vflag & INP_IPV4) == 0) continue; #endif - if (inp->inp_faddr.s_addr == faddr.s_addr && - inp->inp_laddr.s_addr == laddr.s_addr && - inp->inp_fport == fport && - inp->inp_lport == lport) { - /* - * XXX We should be able to directly return - * the inp here, without any checks. - * Well unless both bound with SO_REUSEPORT? - */ - if (jailed(inp->inp_cred)) - return (inp); - if (tmpinp == NULL) - tmpinp = inp; - } + if (inp->inp_faddr.s_addr != faddr.s_addr || + inp->inp_laddr.s_addr != laddr.s_addr || + inp->inp_fport != fport || + inp->inp_lport != lport) + continue; + if (inp->inp_subset_strategy != IP_SUBSET_STRATEGY_DISABLED + && !in_subset_match(inp, faddr, fport, laddr, lport, + ip_id, flowid)) + continue; + + /* + * XXX We should be able to directly return + * the inp here, without any checks. + * Well unless both bound with SO_REUSEPORT? + */ + if (jailed(inp->inp_cred)) + return (inp); + if (tmpinp == NULL) + tmpinp = inp; } if (tmpinp != NULL) return (tmpinp); @@ -1372,6 +1480,12 @@ in_pcblookup_hash(struct inpcbinfo *pcbi continue; } + if (inp->inp_subset_strategy != + IP_SUBSET_STRATEGY_DISABLED && + !in_subset_match(inp, faddr, fport, laddr, lport, + ip_id, flowid)) + continue; + if (inp->inp_laddr.s_addr == laddr.s_addr) { if (injail) return (inp); @@ -1405,6 +1519,16 @@ in_pcblookup_hash(struct inpcbinfo *pcbi return (NULL); } +struct inpcb * +in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, + u_int fport_arg, struct in_addr laddr, u_int lport_arg, int wildcard, + struct ifnet *ifp) +{ + + return (in_pcblookup_hash_full(pcbinfo, faddr, fport_arg, laddr, + lport_arg, 0, 0, wildcard, ifp)); +} + /* * Insert PCB onto various hash lists. */ Modified: projects/pnet/sys/netinet/in_pcb.h ============================================================================== --- projects/pnet/sys/netinet/in_pcb.h Thu Jan 1 20:47:09 2009 (r186685) +++ projects/pnet/sys/netinet/in_pcb.h Thu Jan 1 22:11:44 2009 (r186686) @@ -199,6 +199,9 @@ struct inpcb { } inp_depend6; LIST_ENTRY(inpcb) inp_portlist; /* (i/p) */ struct inpcbport *inp_phd; /* (i/p) head of this list */ + u_int inp_subset_strategy; + u_int inp_subset_count; + u_int inp_subset_member; #define inp_zero_size offsetof(struct inpcb, inp_gencnt) inp_gen_t inp_gencnt; /* (c) generation count */ struct rwlock inp_lock; @@ -493,6 +496,11 @@ struct inpcb * struct inpcb * in_pcblookup_hash(struct inpcbinfo *, struct in_addr, u_int, struct in_addr, u_int, int, struct ifnet *); +struct inpcb * + in_pcblookup_hash_full(struct inpcbinfo *pcbinfo, + struct in_addr faddr, u_int fport_arg, struct in_addr laddr, + u_int lport_arg, u_short ip_id, u_int32_t flowid, int wildcard, + struct ifnet *ifp); void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr, int, struct inpcb *(*)(struct inpcb *, int)); void in_pcbref(struct inpcb *); Modified: projects/pnet/sys/netinet/in_proto.c ============================================================================== --- projects/pnet/sys/netinet/in_proto.c Thu Jan 1 20:47:09 2009 (r186685) +++ projects/pnet/sys/netinet/in_proto.c Thu Jan 1 22:11:44 2009 (r186686) @@ -124,7 +124,7 @@ struct protosw inetsw[] = { .pr_flags = PR_ATOMIC|PR_ADDR, .pr_input = udp_input, .pr_ctlinput = udp_ctlinput, - .pr_ctloutput = ip_ctloutput, + .pr_ctloutput = udp_ctloutput, .pr_init = udp_init, .pr_usrreqs = &udp_usrreqs }, Modified: projects/pnet/sys/netinet/udp_usrreq.c ============================================================================== --- projects/pnet/sys/netinet/udp_usrreq.c Thu Jan 1 20:47:09 2009 (r186685) +++ projects/pnet/sys/netinet/udp_usrreq.c Thu Jan 1 22:11:44 2009 (r186686) @@ -526,8 +526,8 @@ udp_input(struct mbuf *m, int off) /* * Locate pcb for datagram. */ - inp = in_pcblookup_hash(&V_udbinfo, ip->ip_src, uh->uh_sport, - ip->ip_dst, uh->uh_dport, 1, ifp); + inp = in_pcblookup_hash_full(&V_udbinfo, ip->ip_src, uh->uh_sport, + ip->ip_dst, uh->uh_dport, ip->ip_id, m->m_pkthdr.flowid, 1, ifp); if (inp == NULL) { if (udp_log_in_vain) { char buf[4*sizeof "123"]; @@ -621,6 +621,9 @@ udp_ctlinput(int cmd, struct sockaddr *s * * XXX: We never get this from ICMP, otherwise it makes an excellent * DoS attack on machines with many connections. + * + * XXXRW: With subsetting, we should deliver this to all matching + * connections for the specific tuple. */ if (cmd == PRC_HOSTDEAD) ip = NULL; @@ -644,6 +647,67 @@ udp_ctlinput(int cmd, struct sockaddr *s udp_notify); } +int +udp_ctloutput(struct socket *so, struct sockopt *sopt) +{ + INIT_VNET_INET(so->so_vnet); + struct ip_subset is; + struct inpcb *inp; + int error; + + inp = sotoinpcb(so); + KASSERT(inp != NULL, ("udp_ctloutput: inp == NULL")); + + if (sopt->sopt_level != IPPROTO_UDP) + return (ip_ctloutput(so, sopt)); + + switch (sopt->sopt_dir) { + case SOPT_GET: + switch (sopt->sopt_name) { + case IP_SUBSET: + bzero(&is, sizeof(is)); + INP_RLOCK(inp); + is.is_strategy = inp->inp_subset_strategy; + is.is_count = inp->inp_subset_count; + is.is_member = inp->inp_subset_member; + INP_RUNLOCK(inp); + return (sooptcopyout(sopt, &is, sizeof(is))); + } + break; + + case SOPT_SET: + switch (sopt->sopt_name) { + case IP_SUBSET: + error = sooptcopyin(sopt, &is, sizeof(is), + sizeof(is)); + if (error) + return (error); + switch (is.is_strategy) { + case IP_SUBSET_STRATEGY_DISABLED: + break; + + case IP_SUBSET_STRATEGY_FLOW: + case IP_SUBSET_STRATEGY_RANDOM: + if (is.is_count == 0 || + is.is_member >= is.is_count) + return (EINVAL); + break; + + default: + return (EINVAL); + } + INP_WLOCK(inp); + inp->inp_subset_strategy = is.is_strategy; + inp->inp_subset_count = is.is_count; + inp->inp_subset_member = is.is_member; + INP_WUNLOCK(inp); + return (0); + } + break; + } + return (ENOPROTOOPT); +} + static int udp_pcblist(SYSCTL_HANDLER_ARGS) { @@ -758,6 +822,11 @@ udp_getcred(SYSCTL_HANDLER_ARGS) error = SYSCTL_IN(req, addrs, sizeof(addrs)); if (error) return (error); + + /* + * XXXRW: with IP subsetting, potentially more than one socket may + * match, so we just return the cred for the first one. + */ INP_INFO_RLOCK(&V_udbinfo); inp = in_pcblookup_hash(&V_udbinfo, addrs[1].sin_addr, addrs[1].sin_port, addrs[0].sin_addr, addrs[0].sin_port, 1, NULL); Modified: projects/pnet/sys/netinet/udp_var.h ============================================================================== --- projects/pnet/sys/netinet/udp_var.h Thu Jan 1 20:47:09 2009 (r186685) +++ projects/pnet/sys/netinet/udp_var.h Thu Jan 1 22:11:44 2009 (r186686) @@ -106,6 +106,7 @@ extern u_long udp_recvspace; extern int udp_log_in_vain; void udp_ctlinput(int, struct sockaddr *, void *); +int udp_ctloutput(struct socket *so, struct sockopt *sopt); void udp_init(void); void udp_input(struct mbuf *, int); struct inpcb *udp_notify(struct inpcb *inp, int errno); From owner-svn-src-projects@FreeBSD.ORG Fri Jan 2 12:35:02 2009 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 2807A1065670; Fri, 2 Jan 2009 12:35:02 +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 182178FC0C; Fri, 2 Jan 2009 12:35:02 +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 n02CZ1kr097457; Fri, 2 Jan 2009 12:35:01 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n02CZ1o0097456; Fri, 2 Jan 2009 12:35:01 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901021235.n02CZ1o0097456@svn.freebsd.org> From: Ulf Lilleengen Date: Fri, 2 Jan 2009 12:35:01 +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: r186697 - 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: Fri, 02 Jan 2009 12:35:02 -0000 Author: lulf Date: Fri Jan 2 12:35:01 2009 New Revision: 186697 URL: http://svn.freebsd.org/changeset/base/186697 Log: - Check for NULL in case fattr_frompath fails. Modified: projects/csup_cvsmode/contrib/csup/lister.c Modified: projects/csup_cvsmode/contrib/csup/lister.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/lister.c Fri Jan 2 08:21:21 2009 (r186696) +++ projects/csup_cvsmode/contrib/csup/lister.c Fri Jan 2 12:35:01 2009 (r186697) @@ -434,7 +434,7 @@ lister_dorcsfile(struct lister *l, struc free(path); } else fa = sr->sr_clientattr; - if (fattr_equal(fa, sr->sr_clientattr)) { + if (fa != NULL && fattr_equal(fa, sr->sr_clientattr)) { /* * If the file is an RCS file, we use "loose" equality, so sizes * may disagress because of differences in whitespace. From owner-svn-src-projects@FreeBSD.ORG Fri Jan 2 12:36:59 2009 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 9C895106566C; Fri, 2 Jan 2009 12:36:59 +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 8C6088FC12; Fri, 2 Jan 2009 12:36:59 +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 n02Cax3Y097525; Fri, 2 Jan 2009 12:36:59 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n02CaxWq097524; Fri, 2 Jan 2009 12:36:59 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901021236.n02CaxWq097524@svn.freebsd.org> From: Ulf Lilleengen Date: Fri, 2 Jan 2009 12:36: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: r186698 - 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: Fri, 02 Jan 2009 12:36:59 -0000 Author: lulf Date: Fri Jan 2 12:36:59 2009 New Revision: 186698 URL: http://svn.freebsd.org/changeset/base/186698 Log: - Fattrs are not used for rsync, so remove unused code. Modified: projects/csup_cvsmode/contrib/csup/rsyncfile.c Modified: projects/csup_cvsmode/contrib/csup/rsyncfile.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/rsyncfile.c Fri Jan 2 12:35:01 2009 (r186697) +++ projects/csup_cvsmode/contrib/csup/rsyncfile.c Fri Jan 2 12:36:59 2009 (r186698) @@ -34,10 +34,10 @@ #include #include #include +#include #include #include "misc.h" -#include "fattr.h" #include "rsyncfile.h" #define MINBLOCKSIZE 1024 @@ -56,7 +56,6 @@ struct rsyncfile { char *end; size_t blocksize; size_t fsize; - struct fattr *fa; int fd; char *blockptr; @@ -84,7 +83,6 @@ rsync_open(char *path, size_t blocksize, return (NULL); } rf->fsize = st.st_size; - rf->fa = fattr_fromstat(&st); rf->fd = open(path, rdonly ? O_RDONLY : O_RDWR); if (rf->fd < 0) { From owner-svn-src-projects@FreeBSD.ORG Fri Jan 2 12:37:31 2009 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 81142106566C; Fri, 2 Jan 2009 12:37:31 +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 7179B8FC1A; Fri, 2 Jan 2009 12:37:31 +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 n02CbV3n097572; Fri, 2 Jan 2009 12:37:31 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n02CbVSQ097571; Fri, 2 Jan 2009 12:37:31 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901021237.n02CbVSQ097571@svn.freebsd.org> From: Ulf Lilleengen Date: Fri, 2 Jan 2009 12:37: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: r186699 - 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: Fri, 02 Jan 2009 12:37:31 -0000 Author: lulf Date: Fri Jan 2 12:37:31 2009 New Revision: 186699 URL: http://svn.freebsd.org/changeset/base/186699 Log: - Disable rsync support for now, as it is not fully working. Modified: projects/csup_cvsmode/contrib/csup/config.c Modified: projects/csup_cvsmode/contrib/csup/config.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/config.c Fri Jan 2 12:36:59 2009 (r186698) +++ projects/csup_cvsmode/contrib/csup/config.c Fri Jan 2 12:37:31 2009 (r186699) @@ -133,6 +133,7 @@ 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; + coll->co_options |= CO_NORSYNC; error = config_parse_refusefiles(coll); if (error) goto bad; From owner-svn-src-projects@FreeBSD.ORG Fri Jan 2 12:40:58 2009 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 988D2106564A; Fri, 2 Jan 2009 12:40:58 +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 877EE8FC0C; Fri, 2 Jan 2009 12:40:58 +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 n02CewRc097687; Fri, 2 Jan 2009 12:40:58 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n02Cew09097681; Fri, 2 Jan 2009 12:40:58 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901021240.n02Cew09097681@svn.freebsd.org> From: Ulf Lilleengen Date: Fri, 2 Jan 2009 12:40:58 +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: r186700 - 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: Fri, 02 Jan 2009 12:40:58 -0000 Author: lulf Date: Fri Jan 2 12:40:58 2009 New Revision: 186700 URL: http://svn.freebsd.org/changeset/base/186700 Log: - Add an optimization when parsing rcsfiles when the intention is to only send details to the cvsup server. The deltatext does not need parsing, and some parts of the rcsfile data structure doesn't need to be set up. - Fix a bug where the RCS expansion mode is not written out. Modified: projects/csup_cvsmode/contrib/csup/detailer.c projects/csup_cvsmode/contrib/csup/rcsfile.c projects/csup_cvsmode/contrib/csup/rcsfile.h projects/csup_cvsmode/contrib/csup/rcsparse.c projects/csup_cvsmode/contrib/csup/rcsparse.h projects/csup_cvsmode/contrib/csup/updater.c Modified: projects/csup_cvsmode/contrib/csup/detailer.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/detailer.c Fri Jan 2 12:37:31 2009 (r186699) +++ projects/csup_cvsmode/contrib/csup/detailer.c Fri Jan 2 12:40:58 2009 (r186700) @@ -432,7 +432,7 @@ detailer_dofile_rcs(struct detailer *d, return (0); } - rf = rcsfile_frompath(path, name, coll->co_cvsroot, coll->co_tag); + rf = rcsfile_frompath(path, name, coll->co_cvsroot, coll->co_tag, 1); free(path); if (rf == NULL) { error = proto_printf(wr, "A %s\n", name); Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsfile.c Fri Jan 2 12:37:31 2009 (r186699) +++ projects/csup_cvsmode/contrib/csup/rcsfile.c Fri Jan 2 12:40:58 2009 (r186700) @@ -119,6 +119,7 @@ struct rcsfile { int strictlock; char *comment; int expand; + int ro; struct branch *trunk; /* The tip delta. */ LIST_HEAD(, delta) deltatable; @@ -153,6 +154,7 @@ const char *state_space = "\t"; const char *next_space = "\t"; const char *branches_space = "\t"; const char *comment_space ="\t"; +const char *expand_space = "\t"; void print_stream(struct stream *); @@ -174,7 +176,7 @@ print_stream(struct stream *s) * Parse rcsfile from path and return a pointer to it. */ struct rcsfile * -rcsfile_frompath(char *path, char *name, char *cvsroot, char *colltag) +rcsfile_frompath(char *path, char *name, char *cvsroot, char *colltag, int ro) { struct rcsfile *rf; FILE *infp; @@ -206,6 +208,7 @@ rcsfile_frompath(char *path, char *name, rf->comment = NULL; rf->expand = EXPAND_DEFAULT; rf->desc = NULL; + rf->ro = ro; infp = fopen(path, "r"); if (infp == NULL) { @@ -213,7 +216,7 @@ rcsfile_frompath(char *path, char *name, rcsfile_free(rf); return (NULL); } - error = rcsparse_run(rf, infp); + error = rcsparse_run(rf, infp, ro); fclose(infp); if (error) { lprintf(-1, "Error parsing \"%s\"\n", name); @@ -343,6 +346,9 @@ rcsfile_write(struct rcsfile *rf, struct /* Write out the comment. */ if (rf->comment != NULL) stream_printf(dest, "comment%s%s;\n", comment_space, rf->comment); + if (rf->expand != EXPAND_DEFAULT) + stream_printf(dest, "expand%s@%s@;\n", expand_space, + keyword_encode_expand(rf->expand)); stream_printf(dest, "\n\n"); @@ -694,7 +700,7 @@ rcsfile_print(struct rcsfile *rf) lprintf(1, "Strict!\n"); if (rf->comment != NULL) lprintf(1, "comment: '%s'\n", rf->comment); - if (rf->expand >= 0) + if (rf->expand != EXPAND_DEFAULT); lprintf(1, "expand: '%s'\n", keyword_encode_expand(rf->expand)); /* Print all deltas. */ @@ -769,7 +775,8 @@ rcsfile_free(struct rcsfile *rf) /* Free all deltas in global list */ while (!LIST_EMPTY(&rf->deltatable)) { d = LIST_FIRST(&rf->deltatable); - LIST_REMOVE(d, delta_next); + if (!rf->ro) + LIST_REMOVE(d, delta_next); LIST_REMOVE(d, table_next); rcsfile_freedelta(d); } @@ -871,7 +878,8 @@ rcsfile_deleterev(struct rcsfile *rf, ch struct delta *d; d = rcsfile_getdelta(rf, revname); - LIST_REMOVE(d, delta_next); + if (!rf->ro) + LIST_REMOVE(d, delta_next); LIST_REMOVE(d, table_next); rcsfile_freedelta(d); } @@ -1065,6 +1073,17 @@ rcsfile_importdelta(struct rcsfile *rf, d_next->diffbase = d; } + /* If we're opening read-only, do minimal work. */ + if (rf->ro) { + if (!d->placeholder) + rcsfile_insertsorteddelta(rf, d); + else + d->placeholder = 0; + if (d_next != NULL) + rcsfile_insertsorteddelta(rf, d_next); + return; + } + /* If it's trunk, insert it in the head branch list. */ b = rcsrev_istrunk(d->revnum) ? rf->trunk : rcsfile_getbranch(rf, d->revnum); @@ -1152,10 +1171,7 @@ rcsfile_getbranch(struct rcsfile *rf, ch return (NULL); } -/* - * Insert a delta into the correct place in the table of the rcsfile. Sorted by - * date. - */ +/* Insert a delta into the correct place in the table of the rcsfile. */ static void rcsfile_insertsorteddelta(struct rcsfile *rf, struct delta *d) { Modified: projects/csup_cvsmode/contrib/csup/rcsfile.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsfile.h Fri Jan 2 12:37:31 2009 (r186699) +++ projects/csup_cvsmode/contrib/csup/rcsfile.h Fri Jan 2 12:40:58 2009 (r186700) @@ -42,7 +42,7 @@ struct delta; struct stream; /* Fetching, sending and writing an RCS file. */ -struct rcsfile *rcsfile_frompath(char *, char *, char *, char *); +struct rcsfile *rcsfile_frompath(char *, char *, char *, char *, int); int rcsfile_send_details(struct rcsfile *, struct stream *); int rcsfile_write(struct rcsfile *, struct stream *); void rcsfile_print(struct rcsfile *); Modified: projects/csup_cvsmode/contrib/csup/rcsparse.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsparse.c Fri Jan 2 12:37:31 2009 (r186699) +++ projects/csup_cvsmode/contrib/csup/rcsparse.c Fri Jan 2 12:40:58 2009 (r186700) @@ -82,7 +82,7 @@ duptext(yyscan_t *sp, int *arglen) * Start up parser, and use the rcsfile hook to add objects. */ int -rcsparse_run(struct rcsfile *rf, FILE *infp) +rcsparse_run(struct rcsfile *rf, FILE *infp, int ro) { yyscan_t scanner; char *desc; @@ -99,9 +99,12 @@ rcsparse_run(struct rcsfile *rf, FILE *i rcsfile_setval(rf, RCSFILE_DESC, desc); free(desc); tok = rcslex(scanner); - error = parse_deltatexts(rf, &scanner, tok); - if (error) - return (error); + /* Parse deltatexts if we need to edit. */ + if (!ro) { + error = parse_deltatexts(rf, &scanner, tok); + if (error) + return (error); + } rcslex_destroy(scanner); return (0); } Modified: projects/csup_cvsmode/contrib/csup/rcsparse.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsparse.h Fri Jan 2 12:37:31 2009 (r186699) +++ projects/csup_cvsmode/contrib/csup/rcsparse.h Fri Jan 2 12:40:58 2009 (r186700) @@ -37,5 +37,5 @@ #define COLON 6 struct rcsfile; -int rcsparse_run(struct rcsfile *, FILE *); +int rcsparse_run(struct rcsfile *, FILE *, int); #endif /* !_RCSPARSE_H_ */ Modified: projects/csup_cvsmode/contrib/csup/updater.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/updater.c Fri Jan 2 12:37:31 2009 (r186699) +++ projects/csup_cvsmode/contrib/csup/updater.c Fri Jan 2 12:40:58 2009 (r186700) @@ -1575,7 +1575,7 @@ updater_rcsedit(struct updater *up, stru lprintf(1, " -> Attic"); \ lprintf(1, "\n"); \ (rf) = rcsfile_frompath((path), (name), (cvsroot), \ - (tag)); \ + (tag), 0); \ if ((rf) == NULL) { \ xasprintf(&(up)->errmsg, \ "Error reading rcsfile %s\n", (name)); \ From owner-svn-src-projects@FreeBSD.ORG Fri Jan 2 13:48:03 2009 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 CE87C106566B; Fri, 2 Jan 2009 13:48:02 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8911F8FC0C; Fri, 2 Jan 2009 13:48:02 +0000 (UTC) (envelope-from rwatson@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 n02Dm2tI098928; Fri, 2 Jan 2009 13:48:02 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n02Dm2A0098924; Fri, 2 Jan 2009 13:48:02 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200901021348.n02Dm2A0098924@svn.freebsd.org> From: Robert Watson Date: Fri, 2 Jan 2009 13:48: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: r186701 - in projects/pnet/sys: conf net 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: Fri, 02 Jan 2009 13:48:04 -0000 Author: rwatson Date: Fri Jan 2 13:48:02 2009 New Revision: 186701 URL: http://svn.freebsd.org/changeset/base/186701 Log: Drop netisr2 prototype from a few years ago into svn; previously it was in Perforce. This prototype has per-CPU netisr threads, and allows protocols to provide handlers to analyze packets to decide where they should be processed. The current implementation is fairly dated, and is not aware of per-mbuf flow IDs, for example, but may be a useful starting point for future work. Added: projects/pnet/sys/net/netisr2.c (contents, props changed) projects/pnet/sys/net/netisr2.h (contents, props changed) Modified: projects/pnet/sys/conf/files projects/pnet/sys/conf/options Modified: projects/pnet/sys/conf/files ============================================================================== --- projects/pnet/sys/conf/files Fri Jan 2 12:40:58 2009 (r186700) +++ projects/pnet/sys/conf/files Fri Jan 2 13:48:02 2009 (r186701) @@ -2192,6 +2192,7 @@ net/if_vlan.c optional vlan net/mppcc.c optional netgraph_mppc_compression net/mppcd.c optional netgraph_mppc_compression net/netisr.c standard +net/netisr2.c optional netisr2 net/ppp_deflate.c optional ppp_deflate net/ppp_tty.c optional ppp net/pfil.c optional ether | inet Modified: projects/pnet/sys/conf/options ============================================================================== --- projects/pnet/sys/conf/options Fri Jan 2 12:40:58 2009 (r186700) +++ projects/pnet/sys/conf/options Fri Jan 2 13:48:02 2009 (r186701) @@ -404,6 +404,7 @@ MBUF_STRESS_TEST MROUTING opt_mrouting.h NCP NETATALK opt_atalk.h +NETISR2 opt_netisr.h NFSLOCKD PPP_BSDCOMP opt_ppp.h PPP_DEFLATE opt_ppp.h Added: projects/pnet/sys/net/netisr2.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/pnet/sys/net/netisr2.c Fri Jan 2 13:48:02 2009 (r186701) @@ -0,0 +1,861 @@ +/*- + * Copyright (c) 2007-2009 Robert N. M. Watson + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * netisr2 is a work dispatch service, allowing synchronous and asynchronous + * processing of packets by protocol handlers. Each protocol registers a + * handler, and callers pass the protocol identifier and packet to the netisr + * dispatch routines to cause them to be processed. Processing may occur + * synchonously via direct dispatch, or asynchronously via queued dispatch in + * a worker thread. + * + * Maintaining ordering for protocol streams is a critical design concern. + * Enforcing ordering limits the opportunity for concurrency, but maintains + * the strong ordering requirements found in some protocols, such as TCP. Of + * related concern is CPU affinity--it is desirable to process all data + * associated with a particular stream on the same CPU over time in order to + * avoid acquiring locks associated with the connection on different CPUs, + * keep connection data in one cache, and to generally encourage associated + * user threads to live on the same CPU as the stream. + * + * We handle three cases: + * + * - The protocol is unable to determine an a priori ordering based on a + * cheap inspection of packet contents, so we either globally order (run in + * a single worker) or source order (run in the context of a particular + * source). + * + * - The protocol exposes ordering information in the form of a generated + * flow identifier, and relies on netisr2 to assign this work to a CPU. We + * can execute the handler in the source thread, or we can assign it to a + * CPU based on hashing flows to CPUs. + * + * - The protocol exposes ordering and affinity information in the form of a + * CPU identifier. We can execute the handler in the source thread, or we + * can dispatch it to the worker for that CPU. + * + * When CPU and flow affinities are returned by protocols, they also express + * an affinity strength, which is used by netisr2 to decide whether or not to + * directly dispatch a packet on a CPU other than the one it has an affinity + * for. + * + * We guarantee that if two packets come from the same source have the same + * flowid or CPU affinity, and have the same affinity strength, they will + * remain in order with respect to each other. We guarantee that if the + * returned affinity is strong, the packet will only be processed on the + * requested CPU or CPU associated with the requested flow. + * + * Protocols that provide flowids but not affinity should attempt to provide + * a uniform distribution over the flowid space in order to balance work + * effectively. + * + * Some possible sources of flow identifiers for packets: + * - Hardware-generated hash from RSS + * - Software-generated hash from addresses and ports identifying the flow + * - Interface identifier the packet came from + */ + +#include "opt_ddb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DDB +#include +#endif + +#include +#include + +#ifdef NETISR_LOCKING +/*- + * Synchronize use and modification of the registered netisr data structures; + * acquire a read lock while modifying the set of registered protocols to + * prevent partially registered or unregistered protocols from being run. + * + * We make this optional so that we can measure the performance impact of + * providing consistency against run-time registration and deregristration, + * which is a very uncommon event. + * + * The following data structures and fields are protected by this lock: + * + * - The np array, including all fields of struct netisr_proto. + * - The nws array, including all fields of struct netisr_worker. + * - The nws_array array. + */ +static struct rwlock netisr_rwlock; +#define NETISR_LOCK_INIT() rw_init(&netisr_rwlock, "netisr") +#define NETISR_LOCK_ASSERT() rw_assert(&netisr_rwlock, RW_LOCKED) +#define NETISR_RLOCK() rw_rlock(&netisr_rwlock) +#define NETISR_RUNLOCK() rw_runlock(&netisr_rwlock) +#define NETISR_WLOCK() rw_wlock(&netisr_rwlock) +#define NETISR_WUNLOCK() rw_wunlock(&netisr_rwlock) +#else +#define NETISR_LOCK_INIT() +#define NETISR_LOCK_ASSERT() +#define NETISR_RLOCK() +#define NETISR_RUNLOCK() +#define NETISR_WLOCK() +#define NETISR_WUNLOCK() +#endif + +SYSCTL_NODE(_net, OID_AUTO, isr2, CTLFLAG_RW, 0, "netisr2"); + +static int netisr_direct = 1; /* Enable direct dispatch. */ +SYSCTL_INT(_net_isr2, OID_AUTO, direct, CTLFLAG_RW, &netisr_direct, 0, + "Direct dispatch"); + +/* + * Allow the administrator to limit the number of threads (CPUs) to use for + * netisr2. Notice that we don't check netisr_maxthreads before creating the + * thread for CPU 0, so in practice we ignore values <= 1. + */ +static int netisr_maxthreads = MAXCPU; /* Bound number of threads. */ +TUNABLE_INT("net.isr2.maxthreads", &netisr_maxthreads); +SYSCTL_INT(_net_isr2, OID_AUTO, maxthreads, CTLFLAG_RD, &netisr_maxthreads, + 0, "Use at most this many CPUs for netisr2 processing"); + +/* + * Each protocol is described by an instance of netisr_proto, which holds all + * global per-protocol information. This data structure is set up by + * netisr_register(). Currently, no flags are required, as all handlers are + * MPSAFE in the netisr2 system. Protocols provide zero or one of the two + * lookup interfaces, but not both. + */ +struct netisr_proto { + netisr_t *np_func; /* Protocol handler. */ + netisr_lookup_flow_t *np_lookup_flow; /* Flow generation. */ + netisr_lookup_cpu_t *np_lookup_cpu; /* CPU affinity. */ + const char *np_name; /* Protocol name. */ +}; + +#define NETISR_MAXPROT 32 /* Compile-time limit. */ +#define NETISR_ALLPROT 0xffffffff /* Run all protocols. */ + +/* + * The np array describes all registered protocols, indexed by protocol + * number. + */ +static struct netisr_proto np[NETISR_MAXPROT]; + +/* + * Protocol-specific work for each workstream is described by struct + * netisr_work. Each work descriptor consists of an mbuf queue and + * statistics. + * + * XXXRW: Using a lock-free linked list here might be useful. + */ +struct netisr_work { + /* + * Packet queue, linked by m_nextpkt. + */ + struct mbuf *nw_head; + struct mbuf *nw_tail; + u_int nw_len; + u_int nw_max; + u_int nw_watermark; + + /* + * Statistics. + */ + u_int nw_dispatched; /* Number of direct dispatches. */ + u_int nw_dropped; /* Number of drops. */ + u_int nw_queued; /* Number of enqueues. */ + u_int nw_handled; /* Number passed into handler. */ +}; + +/* + * Workstreams hold a set of ordered work across each protocol, and are + * described by netisr_workstream. Each workstream is associated with a + * worker thread, which in turn is pinned to a CPU. Work associated with a + * workstream can be processd in other threads during direct dispatch; + * concurrent processing is prevented by the NWS_RUNNING flag, which + * indicates that a thread is already processing the work queue. + * + * Currently, #workstreams must equal #CPUs. + */ +struct netisr_workstream { + struct thread *nws_thread; /* Thread serving stream. */ + struct mtx nws_mtx; /* Synchronize work. */ + struct cv nws_cv; /* Wake up worker. */ + u_int nws_cpu; /* CPU pinning. */ + u_int nws_flags; /* Wakeup flags. */ + + u_int nws_pendingwork; /* Across all protos. */ + /* + * Each protocol has per-workstream data. + */ + struct netisr_work nws_work[NETISR_MAXPROT]; +}; + +/* + * Kernel process associated with worker threads. + */ +static struct proc *netisr2_proc; + +/* + * Per-CPU workstream data, indexed by CPU ID. + */ +static struct netisr_workstream nws[MAXCPU]; + +/* + * Map contiguous values between 0 and nws_count into CPU IDs appropriate for + * indexing the nws[] array. This allows constructions of the form + * nws[nws_array(arbitraryvalue % nws_count)]. + */ +static u_int nws_array[MAXCPU]; + +/* + * Number of registered workstreams. Should be the number of running CPUs + * once fully started. + */ +static u_int nws_count; + +/* + * Per-workstream flags. + */ +#define NWS_RUNNING 0x00000001 /* Currently running in a thread. */ +#define NWS_SIGNALED 0x00000002 /* Signal issued. */ + +/* + * Synchronization for each workstream: a mutex protects all mutable fields + * in each stream, including per-protocol state (mbuf queues). The CV will + * be used to wake up the worker if asynchronous dispatch is required. + */ +#define NWS_LOCK(s) mtx_lock(&(s)->nws_mtx) +#define NWS_LOCK_ASSERT(s) mtx_assert(&(s)->nws_mtx, MA_OWNED) +#define NWS_UNLOCK(s) mtx_unlock(&(s)->nws_mtx) +#define NWS_SIGNAL(s) cv_signal(&(s)->nws_cv) +#define NWS_WAIT(s) cv_wait(&(s)->nws_cv, &(s)->nws_mtx) + +/* + * Register a new netisr handler, which requires initializing per-protocol + * fields for each workstream. All netisr2 work is briefly suspended while + * the protocol is installed. + */ +void +netisr2_register(u_int proto, netisr_t func, netisr_lookup_cpu_t lookup_cpu, + netisr_lookup_flow_t lookup_flow, const char *name, u_int max) +{ + struct netisr_work *npwp; + int i; + + NETISR_WLOCK(); + KASSERT(proto < NETISR_MAXPROT, + ("netisr2_register(%d, %s): too many protocols", proto, name)); + KASSERT(np[proto].np_func == NULL, + ("netisr2_register(%d, %s): func present", proto, name)); + KASSERT(np[proto].np_lookup_cpu == NULL, + ("netisr2_register(%d, %s): lookup_cpu present", proto, name)); + KASSERT(np[proto].np_lookup_flow == NULL, + ("netisr2_register(%d, %s): lookup_flow present", proto, name)); + KASSERT(np[proto].np_name == NULL, + ("netisr2_register(%d, %s): name present", proto, name)); + + KASSERT(func != NULL, ("netisr2_register: func NULL")); + KASSERT((lookup_flow == NULL && lookup_cpu == NULL) || + (lookup_flow != NULL && lookup_cpu == NULL) || + (lookup_flow == NULL && lookup_cpu != NULL), + ("netisr2_register(%d, %s): flow and cpu set", proto, name)); + + /* + * Initialize global and per-workstream protocol state. + */ + np[proto].np_func = func; + np[proto].np_lookup_cpu = lookup_cpu; + np[proto].np_lookup_flow = lookup_flow; + np[proto].np_name = name; + for (i = 0; i < MAXCPU; i++) { + npwp = &nws[i].nws_work[proto]; + bzero(npwp, sizeof(*npwp)); + npwp->nw_max = max; + } + NETISR_WUNLOCK(); +} + +/* + * Drain all packets currently held in a particular protocol work queue. + */ +static void +netisr2_drain_proto(struct netisr_work *npwp) +{ + struct mbuf *m; + + while ((m = npwp->nw_head) != NULL) { + npwp->nw_head = m->m_nextpkt; + m->m_nextpkt = NULL; + if (npwp->nw_head == NULL) + npwp->nw_tail = NULL; + npwp->nw_len--; + m_freem(m); + } + KASSERT(npwp->nw_tail == NULL, ("netisr_drain_proto: tail")); + KASSERT(npwp->nw_len == 0, ("netisr_drain_proto: len")); +} + +/* + * Remove the registration of a network protocol, which requires clearing + * per-protocol fields across all workstreams, including freeing all mbufs in + * the queues at time of deregister. All work in netisr2 is briefly + * suspended while this takes place. + */ +void +netisr2_deregister(u_int proto) +{ + struct netisr_work *npwp; + int i; + + NETISR_WLOCK(); + KASSERT(proto < NETISR_MAXPROT, + ("netisr_deregister(%d): protocol too big", proto)); + KASSERT(np[proto].np_func != NULL, + ("netisr_deregister(%d): protocol not registered", proto)); + + np[proto].np_func = NULL; + np[proto].np_name = NULL; + np[proto].np_lookup_cpu = NULL; + np[proto].np_lookup_flow = NULL; + for (i = 0; i < MAXCPU; i++) { + npwp = &nws[i].nws_work[proto]; + netisr2_drain_proto(npwp); + bzero(npwp, sizeof(*npwp)); + } + NETISR_WUNLOCK(); +} + +/* + * Naively map a flow ID into a CPU ID. For now we use a rather poor hash to + * reduce 32 bits down to a much smaller number of bits. We should attempt + * to be much more adaptive to the actual CPU count. + * + * XXXRW: This needs to be entirely rewritten. + */ +u_int +netisr2_flowid2cpuid(u_int flowid) +{ + + NETISR_LOCK_ASSERT(); + + /* + * Most systems have less than 256 CPUs, so combine the various bytes + * in the flowid so that we get all the entropy down to a single + * byte. We could be doing a much better job here. On systems with + * fewer CPUs, we slide the top nibble into the bottom nibble. + */ + flowid = ((flowid & 0xff000000) >> 24) ^ + ((flowid & 0x00ff0000) >> 16) ^ ((flowid & 0x0000ff00) >> 8) ^ + (flowid & 0x000000ff); +#if MAXCPU <= 16 + flowid = ((flowid & 0xf0) >> 4) ^ (flowid & 0x0f); +#endif + return (nws_array[flowid % nws_count]); +} + +/* + * Look up the correct stream for a requested flowid. There are two cases: + * one in which the caller has requested execution on the current CPU (i.e., + * source ordering is sufficient, perhaps because the underlying hardware has + * generated multiple input queues with sufficient order), or the case in + * which we ask the protocol to generate a flowid. In the latter case, we + * rely on the protocol generating a reasonable distribution across the + * flowid space, and hence use a very simple mapping from flowids to workers. + * + * Because protocols may need to call m_pullup(), they may rewrite parts of + * the mbuf chain. As a result, we must return an mbuf chain that is either + * the old chain (if there is no update) or the new chain (if there is). NULL + * is returned if there is a failure in the protocol portion of the lookup + * (i.e., out of mbufs and a rewrite is required). + */ +static struct mbuf * +netisr2_selectcpu(u_int proto, struct mbuf *m, u_int *cpuidp, + u_int *strengthp) +{ + u_int flowid; + + NETISR_LOCK_ASSERT(); + + KASSERT(nws_count > 0, ("netisr2_workstream_lookup: nws_count")); + + *cpuidp = 0; + *strengthp = 0; + if (np[proto].np_lookup_cpu != NULL) + return (np[proto].np_lookup_cpu(m, cpuidp, strengthp)); + else if (np[proto].np_lookup_flow != NULL) { + m = np[proto].np_lookup_flow(m, &flowid, strengthp); + if (m == NULL) + return (NULL); + *cpuidp = netisr2_flowid2cpuid(flowid); + return (m); + } else { + /* + * XXXRW: Pin protocols without a CPU or flow assignment + * preference to an arbitrary CPU. This needs refinement. + */ + *cpuidp = netisr2_flowid2cpuid(proto); + *strengthp = NETISR2_AFFINITY_WEAK; + return (m); + } +} + +/* + * Process packets associated with a workstream and protocol. For reasons of + * fairness, we process up to one complete netisr queue at a time, moving the + * queue to a stack-local queue for processing, but do not loop refreshing + * from the global queue. The caller is responsible for deciding whether to + * loop, and for setting the NWS_RUNNING flag. The passed workstream will be + * locked on entry and relocked before return, but will be released while + * processing. + */ +static void +netisr2_process_workstream_proto(struct netisr_workstream *nwsp, int proto) +{ + struct netisr_work local_npw, *npwp; + u_int handled; + struct mbuf *m; + + NWS_LOCK_ASSERT(nwsp); + + KASSERT(nwsp->nws_flags & NWS_RUNNING, + ("netisr_process_workstream_proto(%d): not running", proto)); + KASSERT(proto >= 0 && proto < NETISR_MAXPROT, + ("netisr_process_workstream_proto(%d): invalid proto\n", proto)); + + npwp = &nwsp->nws_work[proto]; + if (npwp->nw_len == 0) + return; + + /* + * Create a local copy of the work queue, and clear the global queue. + * + * Notice that this means the effective maximum length of the queue + * is actually twice that of the maximum queue length specified in + * the protocol registration call. + */ + handled = npwp->nw_len; + local_npw = *npwp; + npwp->nw_head = NULL; + npwp->nw_tail = NULL; + npwp->nw_len = 0; + nwsp->nws_pendingwork -= handled; + NWS_UNLOCK(nwsp); + while ((m = local_npw.nw_head) != NULL) { + local_npw.nw_head = m->m_nextpkt; + m->m_nextpkt = NULL; + if (local_npw.nw_head == NULL) + local_npw.nw_tail = NULL; + local_npw.nw_len--; + np[proto].np_func(m); + } + KASSERT(local_npw.nw_len == 0, + ("netisr_process_proto(%d): len %d", proto, local_npw.nw_len)); + NWS_LOCK(nwsp); + npwp->nw_handled += handled; +} + +/* + * Process either one or all protocols associated with a specific workstream. + * Handle only existing work for each protocol processed, not new work that + * may arrive while processing. Set the running flag so that other threads + * don't also try to process work in the queue; however, the lock on the + * workstream will be released by netisr_process_workstream_proto() while + * entering the protocol so that producers can continue to queue new work. + * + * The consumer is responsible for making sure that either all available work + * is performed until there is no more work to perform, or that the worker is + * scheduled to pick up where the consumer left off. They are also + * responsible for checking the running flag before entering this function. + */ +static void +netisr2_process_workstream(struct netisr_workstream *nwsp, int proto) +{ + u_int i; + + NETISR_LOCK_ASSERT(); + NWS_LOCK_ASSERT(nwsp); + + KASSERT(nwsp->nws_flags & NWS_RUNNING, + ("netisr2_process_workstream: not running")); + if (proto == NETISR_ALLPROT) { + for (i = 0; i < NETISR_MAXPROT; i++) + netisr2_process_workstream_proto(nwsp, i); + } else + netisr2_process_workstream_proto(nwsp, proto); +} + +/* + * Worker thread that waits for and processes packets in a set of workstreams + * that it owns. Each thread has one cv, which is uses for all workstreams + * it handles. + */ +static void +netisr2_worker(void *arg) +{ + struct netisr_workstream *nwsp; + + nwsp = arg; + + thread_lock(curthread); + sched_prio(curthread, SWI_NET * RQ_PPQ + PI_SOFT); + sched_bind(curthread, nwsp->nws_cpu); + thread_unlock(curthread); + + /* + * Main work loop. In the future we will want to support stopping + * workers, as well as re-balancing work, in which case we'll need to + * also handle state transitions. + * + * XXXRW: netisr_rwlock. + */ + NWS_LOCK(nwsp); + while (1) { + while (nwsp->nws_pendingwork == 0) { + nwsp->nws_flags &= ~(NWS_SIGNALED | NWS_RUNNING); + NWS_WAIT(nwsp); + nwsp->nws_flags |= NWS_RUNNING; + } + netisr2_process_workstream(nwsp, NETISR_ALLPROT); + } +} + +/* + * Internal routines for dispatch and queue. + */ +static void +netisr2_dispatch_internal(u_int proto, struct mbuf *m, u_int cpuid) +{ + struct netisr_workstream *nwsp; + struct netisr_work *npwp; + + KASSERT(cpuid == curcpu, ("netisr2_dispatch_internal: wrong CPU")); + + NETISR_LOCK_ASSERT(); + + nwsp = &nws[cpuid]; + npwp = &nwsp->nws_work[proto]; + NWS_LOCK(nwsp); + npwp->nw_dispatched++; + npwp->nw_handled++; + NWS_UNLOCK(nwsp); + np[proto].np_func(m); +} + +static int +netisr2_queue_internal(u_int proto, struct mbuf *m, u_int cpuid) +{ + struct netisr_workstream *nwsp; + struct netisr_work *npwp; + int dosignal, error; + + NETISR_LOCK_ASSERT(); + + dosignal = 0; + nwsp = &nws[cpuid]; + npwp = &nwsp->nws_work[proto]; + NWS_LOCK(nwsp); + if (npwp->nw_len < npwp->nw_max) { + error = 0; + m->m_nextpkt = NULL; + if (npwp->nw_head == NULL) { + npwp->nw_head = m; + npwp->nw_tail = m; + } else { + npwp->nw_tail->m_nextpkt = m; + npwp->nw_tail = m; + } + npwp->nw_len++; + if (npwp->nw_len > npwp->nw_watermark) + npwp->nw_watermark = npwp->nw_len; + npwp->nw_queued++; + nwsp->nws_pendingwork++; + if (!(nwsp->nws_flags & NWS_SIGNALED)) { + nwsp->nws_flags |= NWS_SIGNALED; + dosignal = 1; /* Defer until unlocked. */ + } + } else { + error = ENOBUFS; + npwp->nw_dropped++; + } + NWS_UNLOCK(nwsp); + if (dosignal) + NWS_SIGNAL(nwsp); + return (error); +} + +/* + * Variations on dispatch and queue in which the protocol determines where + * work is placed. + * + * XXXRW: The fact that the strength of affinity is only available by making + * a call to determine affinity means that we always pay the price of hashing + * the headers. If the protocol declared ahead of time the strength of the + * affinity it required, such as at netisr2 registration time, we could skip + * the hash generation when we knew we wanted to direct dispatch. + */ +int +netisr2_dispatch(u_int proto, struct mbuf *m) +{ + u_int cpuid, strength; + int error; + + error = 0; + sched_pin(); + NETISR_RLOCK(); + m = netisr2_selectcpu(proto, m, &cpuid, &strength); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + switch (strength) { + case NETISR2_AFFINITY_STRONG: + if (curcpu != cpuid) { + error = netisr2_queue_internal(proto, m, cpuid); + break; + } + /* FALLSTHROUGH */ + + case NETISR2_AFFINITY_WEAK: + if (netisr_direct) { + cpuid = curcpu; + netisr2_dispatch_internal(proto, m, cpuid); + } else + error = netisr2_queue_internal(proto, m, cpuid); + break; + } +out: + NETISR_RUNLOCK(); + sched_unpin(); + if (error && m != NULL) + m_freem(m); + return (error); +} + +int +netisr2_queue(u_int proto, struct mbuf *m) +{ + u_int cpuid, strength; + int error; + + NETISR_RLOCK(); + m = netisr2_selectcpu(proto, m, &cpuid, &strength); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + error = netisr2_queue_internal(proto, m, cpuid); +out: + NETISR_RUNLOCK(); + if (error && m != NULL) + m_freem(m); + return (error); +} + +/* + * Variations on dispatch and queue in which the caller specifies an explicit + * CPU affinity. + */ +int +netisr2_dispatch_cpu(u_int proto, struct mbuf *m, u_int cpuid) +{ + int error; + + sched_pin(); + NETISR_RLOCK(); + if (cpuid == curcpu) { + netisr2_dispatch_internal(proto, m, cpuid); + error = 0; + } else + error = netisr2_queue_internal(proto, m, cpuid); + NETISR_RUNLOCK(); + sched_unpin(); + return (error); +} + +int +netisr2_queue_cpu(u_int proto, struct mbuf *m, u_int cpuid) +{ + int error; + + NETISR_RLOCK(); + error = netisr2_queue_internal(proto, m, cpuid); + NETISR_RUNLOCK(); + return (error); +} + +/* + * Variations on dispatch and queue in which the caller specifies an explicit + * flow identifier. + */ +int +netisr2_dispatch_flow(u_int proto, struct mbuf *m, u_int flowid) +{ + u_int cpuid; + int error; + + sched_pin(); + NETISR_RLOCK(); + cpuid = netisr2_flowid2cpuid(flowid); + if (cpuid == curcpu) { + netisr2_dispatch_internal(proto, m, cpuid); + error = 0; + } else + error = netisr2_queue_internal(proto, m, cpuid); + NETISR_RUNLOCK(); + sched_unpin(); + return (error); +} + +int +netisr2_queue_flow(u_int proto, struct mbuf *m, u_int flowid) +{ + u_int cpuid; + int error; + + NETISR_RLOCK(); + cpuid = netisr2_flowid2cpuid(flowid); + error = netisr2_queue_internal(proto, m, cpuid); + NETISR_RUNLOCK(); + return (error); +} + +/* + * Initialize the netisr subsystem. We rely on BSS and static initialization + * of most fields in global data structures. Start a worker thread for the + * boot CPU. + */ +static void +netisr2_init(void *arg) +{ + struct netisr_workstream *nwsp; + int cpuid, error; + + KASSERT(curcpu == 0, ("netisr2_init: not on CPU 0")); + + NETISR_LOCK_INIT(); + + KASSERT(PCPU_GET(netisr2) == NULL, ("netisr2_init: pc_netisr2")); + + cpuid = curcpu; + nwsp = &nws[cpuid]; + mtx_init(&nwsp->nws_mtx, "netisr2_mtx", NULL, MTX_DEF); + cv_init(&nwsp->nws_cv, "netisr2_cv"); + nwsp->nws_cpu = cpuid; + error = kproc_kthread_add(netisr2_worker, nwsp, &netisr2_proc, + &nwsp->nws_thread, 0, 0, "netisr2", "netisr2: cpu%d", cpuid); + PCPU_SET(netisr2, nwsp->nws_thread); + if (error) + panic("netisr2_init: kproc_kthread_add %d", error); + nws_array[nws_count] = nwsp->nws_cpu; + nws_count++; + if (netisr_maxthreads < 1) + netisr_maxthreads = 1; +} +SYSINIT(netisr2_init, SI_SUB_SOFTINTR, SI_ORDER_FIRST, netisr2_init, NULL); + +/* + * Start worker threads for additional CPUs. No attempt to gracefully handle + * work reassignment, we don't yet support dynamic reconfiguration. + */ +static void +netisr2_start(void *arg) +{ + struct netisr_workstream *nwsp; + struct pcpu *pc; + int error; + + SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { + if (nws_count >= netisr_maxthreads) + break; + /* XXXRW: Is skipping absent CPUs still required here? */ + if (CPU_ABSENT(pc->pc_cpuid)) + continue; + /* Worker will already be present for boot CPU. */ + if (pc->pc_netisr2 != NULL) + continue; + nwsp = &nws[pc->pc_cpuid]; + mtx_init(&nwsp->nws_mtx, "netisr2_mtx", NULL, MTX_DEF); + cv_init(&nwsp->nws_cv, "netisr2_cv"); + nwsp->nws_cpu = pc->pc_cpuid; + error = kproc_kthread_add(netisr2_worker, nwsp, + &netisr2_proc, &nwsp->nws_thread, 0, 0, "netisr2", + "netisr2: cpu%d", pc->pc_cpuid); + pc->pc_netisr2 = nwsp->nws_thread; + if (error) + panic("netisr2_start: kproc_kthread_add %d", error); + nws_array[nws_count] = pc->pc_cpuid; + nws_count++; + } +} +SYSINIT(netisr2_start, SI_SUB_SMP, SI_ORDER_MIDDLE, netisr2_start, NULL); + +#ifdef DDB +DB_SHOW_COMMAND(netisr2, db_show_netisr2) +{ + struct netisr_workstream *nwsp; + struct netisr_work *nwp; + int cpu, first, proto; + + db_printf("%6s %6s %6s %6s %6s %6s %8s %8s %8s %8s\n", "CPU", "Pend", + "Proto", "Len", "WMark", "Max", "Disp", "Drop", "Queue", "Handle"); + for (cpu = 0; cpu < MAXCPU; cpu++) { + nwsp = &nws[cpu]; + if (nwsp->nws_thread == NULL) + continue; + first = 1; + for (proto = 0; proto < NETISR_MAXPROT; proto++) { + if (np[proto].np_func == NULL) + continue; + nwp = &nwsp->nws_work[proto]; + if (first) { + db_printf("%6d %6d ", cpu, + nwsp->nws_pendingwork); + first = 0; + } else + db_printf("%6s %6s ", "", ""); + db_printf("%6s %6d %6d %6d %8d %8d %8d %8d\n", + np[proto].np_name, nwp->nw_len, + nwp->nw_watermark, nwp->nw_max, + nwp->nw_dispatched, nwp->nw_dropped, + nwp->nw_queued, nwp->nw_handled); + } + } +} +#endif Added: projects/pnet/sys/net/netisr2.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/pnet/sys/net/netisr2.h Fri Jan 2 13:48:02 2009 (r186701) @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2007-2008 Robert N. M. Watson + * 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 _NET_NETISR2_H_ +#define _NET_NETISR2_H_ + +#ifndef _KERNEL +#error "no user-serviceable parts inside" +#endif + +/*- + * Protocols may express flow affinities or CPU affinities using lookup + * functions: + * + * netisr_lookup_cpu_t - Given a packet for the protocol handler, return a + * CPU affinity that will be used, and an indication of + * the affinity strength. All packets with the same + * CPU affinity and strength must be processed in order + * with respect to a single source. + * + * netisr_lookup_flow_t - Given a packet for the protocol handler, return a + * flow identifier that can be used to identify + * ordering requirements with respect to other + * packets, and likewise an affinity strength to use + * with the flowid-derived affinity. All packets + * with the same flowid and affinity strength must be + * processed in order with respect to a single source. + * + * Protocols that implement direct CPU assignment of work, rather than + * returning a flowid, must not return invalid (i.e., absent or otherwise + * inappropriate) CPU identifiers. The dispatch routines will panic if that + * occurs. + * + * XXXRW: If we eventually support dynamic reconfiguration, there should be + * protocol handlers to notify them of CPU configuration changes so that they + * can rebalance work. + */ +typedef struct mbuf *netisr_lookup_flow_t(struct mbuf *m, u_int *flowid, + u_int *strength); +typedef struct mbuf *netisr_lookup_cpu_t(struct mbuf *m, u_int *cpuid, + u_int *strength); + +/* + * Possibly values for the 'strength' returned by netisr_lookup_cpu_t. + * Protocols should consistently return the same strength for packets in the + * same flow, or misordering may occur due to varying dispatch decisions. + */ +#define NETISR2_AFFINITY_STRONG 1 /* Never direct dispatch off-CPU. */ +#define NETISR2_AFFINITY_WEAK 2 /* Direct dispatch even if off-CPU. */ + +/*- + * Register a new netisr2 handler for a given protocol. No previous + * registration may exist. At most one of lookup_cpu and lookup_flow may be + * defined. If no lookup routine is defined, the protocol's work will be + * assigned to a CPU arbitrarily. + * + * proto - Integer protocol identifier. + * func - Protocol handler. + * lookup_cpu - CPU affinity lookup. + * lookup_flow - Flow lookup. + * max - Maximum queue depth. + */ +void netisr2_register(u_int proto, netisr_t func, + netisr_lookup_cpu_t lookup_cpu, netisr_lookup_flow_t lookup_flow, + const char *name, u_int max); + +/* + * Deregister a protocol handler. + */ +void netisr2_deregister(u_int proto); + +/* + * Packet processing routines -- each accepts a protocol identifier and a + * packet. Some also force the use of a particular CPU affinity or flow + * identifier rather than having the dispatcher query the protocol. + * + * _dispatch variants will attempt do directly dispatch the handler if + * globally enabled and permitted by the protocol. + * + * _queue variants will enqueue the packet for later processing by the + * handler in a deferred context. + * + * Direct dispatch decisions are made based on a combination of global + * properties (is direct dispatch enabled), caller properties (is direct + * dispatch allowed in this context) and protocol properties (strong affinity + * will prevent direct dispatch on the wrong CPU, even if it maintains source + * ordering). Callers should use only one of the direct and queued dispatch + * modes for each source, or ordering constraints with respect to the source *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-projects@FreeBSD.ORG Sat Jan 3 05:32:38 2009 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 4D7841065675; Sat, 3 Jan 2009 05:32:38 +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 3DF1C8FC08; Sat, 3 Jan 2009 05:32:38 +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 n035WcDW017378; Sat, 3 Jan 2009 05:32:38 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n035WcXQ017377; Sat, 3 Jan 2009 05:32:38 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200901030532.n035WcXQ017377@svn.freebsd.org> From: Kip Macy Date: Sat, 3 Jan 2009 05:32: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: r186712 - projects/release_6_3_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, 03 Jan 2009 05:32:38 -0000 Author: kmacy Date: Sat Jan 3 05:32:37 2009 New Revision: 186712 URL: http://svn.freebsd.org/changeset/base/186712 Log: make 2 separate cases for memory layout Modified: projects/release_6_3_xen/sys/i386/xen/xen_machdep.c Modified: projects/release_6_3_xen/sys/i386/xen/xen_machdep.c ============================================================================== --- projects/release_6_3_xen/sys/i386/xen/xen_machdep.c Sat Jan 3 02:31:57 2009 (r186711) +++ projects/release_6_3_xen/sys/i386/xen/xen_machdep.c Sat Jan 3 05:32:37 2009 (r186712) @@ -831,6 +831,8 @@ initvalues(start_info_t *startinfo) #endif unsigned long i; int ncpus = MAXCPU; + uint32_t kidx_start = ((KERNBASE&0x3fffffff) >> PDRSHIFT); + uint32_t hvidx_start = ((VM_MAX_KERNEL_ADDRESS&0x3fffffff)>>PDRSHIFT); nkpt = min( min( @@ -855,30 +857,36 @@ initvalues(start_info_t *startinfo) l2_pages = 0; IdlePDPT = (pd_entry_t *)startinfo->pt_base; IdlePDPTma = xpmap_ptom(VTOP(startinfo->pt_base)); - for (i = (KERNBASE >> 30); - (i < 4) && (IdlePDPT[i] != 0); i++) + if (KERNBASE >= 0xC0000000) { + l2_pages = 1; + + for (i = kidx_start; i < hvidx_start; i++) + if (IdlePTD[i] != 0) + l1_pages++; + + } else { + /* + * XXX this will currently only work if l2 pages == 1 + * + */ + for (i = (KERNBASE >> 30); + (i < 3) && (IdlePDPT[i] != 0); i++) l2_pages++; + for (i = 0; i < 512; i++) + if (IdlePTD[i] != 0) + l1_pages++; + } + /* * Note that only one page directory has been allocated at this point. * Thus, if KERNBASE */ -#if 0 - for (i = 0; i < l2_pages; i++) - IdlePTDma[i] = xpmap_ptom(VTOP(IdlePTD + i*PAGE_SIZE)); -#endif - l2_pages = (l2_pages == 0) ? 1 : l2_pages; #else l3_pages = 0; l2_pages = 1; #endif - for (i = (((KERNBASE>>18) & PAGE_MASK)>>PAGE_SHIFT); - (i>PDRSHIFT)); i++) { - - if (IdlePTD[i] == 0) - break; - l1_pages++; - } + /* number of pages allocated after the pts + 1*/; cur_space = xen_start_info->pt_base + From owner-svn-src-projects@FreeBSD.ORG Sat Jan 3 12:09:18 2009 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 D66A4106567E; Sat, 3 Jan 2009 12:09:18 +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 C34478FC1B; Sat, 3 Jan 2009 12:09:18 +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 n03C9IQb027427; Sat, 3 Jan 2009 12:09:18 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n03C9IMr027426; Sat, 3 Jan 2009 12:09:18 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901031209.n03C9IMr027426@svn.freebsd.org> From: Ulf Lilleengen Date: Sat, 3 Jan 2009 12:09:18 +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: r186718 - 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, 03 Jan 2009 12:09:20 -0000 Author: lulf Date: Sat Jan 3 12:09:18 2009 New Revision: 186718 URL: http://svn.freebsd.org/changeset/base/186718 Log: - A bit missing from the previous commit. The '@'s from the string token must be stripped before encoding the expansion mode. Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsfile.c Sat Jan 3 11:35:31 2009 (r186717) +++ projects/csup_cvsmode/contrib/csup/rcsfile.c Sat Jan 3 12:09:18 2009 (r186718) @@ -921,6 +921,7 @@ rcsfile_getdelta(struct rcsfile *rf, cha void rcsfile_setval(struct rcsfile *rf, int field, char *val) { + size_t len; switch (field) { case RCSFILE_HEAD: @@ -943,6 +944,9 @@ rcsfile_setval(struct rcsfile *rf, int f rf->comment = xstrdup(val); break; case RCSFILE_EXPAND: + len = strlen(val) - 1; + val++; + val[len - 1] = '\0'; rf->expand = keyword_decode_expand(val); break; case RCSFILE_DESC: From owner-svn-src-projects@FreeBSD.ORG Sat Jan 3 15:17:20 2009 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 D4106106566B; Sat, 3 Jan 2009 15:17:20 +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 C2E458FC13; Sat, 3 Jan 2009 15:17:20 +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 n03FHK5Z031197; Sat, 3 Jan 2009 15:17:20 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n03FHK9Q031196; Sat, 3 Jan 2009 15:17:20 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901031517.n03FHK9Q031196@svn.freebsd.org> From: Ulf Lilleengen Date: Sat, 3 Jan 2009 15:17:20 +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: r186724 - 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, 03 Jan 2009 15:17:21 -0000 Author: lulf Date: Sat Jan 3 15:17:20 2009 New Revision: 186724 URL: http://svn.freebsd.org/changeset/base/186724 Log: - Write out branches with the highest revision number first if they have the same date. Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsfile.c Sat Jan 3 14:51:49 2009 (r186723) +++ projects/csup_cvsmode/contrib/csup/rcsfile.c Sat Jan 3 15:17:20 2009 (r186724) @@ -490,7 +490,7 @@ rcsfile_write_deltatext(struct rcsfile * } d_tmp2 = LIST_FIRST(&branchlist_datesorted); - if (rcsnum_cmp(d_tmp->revdate, d_tmp2->revdate) < 0) { + if (rcsnum_cmp(d_tmp->revdate, d_tmp2->revdate) <= 0) { LIST_INSERT_BEFORE(d_tmp2, d_tmp, branch_next_date); continue; @@ -498,7 +498,7 @@ rcsfile_write_deltatext(struct rcsfile * while ((d_tmp3 = LIST_NEXT(d_tmp2, branch_next_date)) != NULL) { if (rcsnum_cmp(d_tmp->revdate, d_tmp3->revdate) - < 0) + <= 0) break; d_tmp2 = d_tmp3; } From owner-svn-src-projects@FreeBSD.ORG Sat Jan 3 18:51:50 2009 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 33015106564A; Sat, 3 Jan 2009 18:51:50 +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 218D18FC13; Sat, 3 Jan 2009 18:51:50 +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 n03IpoJ5035169; Sat, 3 Jan 2009 18:51:50 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n03IpoIp035168; Sat, 3 Jan 2009 18:51:50 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200901031851.n03IpoIp035168@svn.freebsd.org> From: Ulf Lilleengen Date: Sat, 3 Jan 2009 18:51:50 +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: r186727 - 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, 03 Jan 2009 18:51:50 -0000 Author: lulf Date: Sat Jan 3 18:51:49 2009 New Revision: 186727 URL: http://svn.freebsd.org/changeset/base/186727 Log: - Use a LIST to hold branches instead of a STAILQ. - Sort branches when inserting them. Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c Modified: projects/csup_cvsmode/contrib/csup/rcsfile.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/rcsfile.c Sat Jan 3 17:22:05 2009 (r186726) +++ projects/csup_cvsmode/contrib/csup/rcsfile.c Sat Jan 3 18:51:49 2009 (r186727) @@ -89,7 +89,7 @@ struct delta { STAILQ_ENTRY(delta) delta_prev; LIST_ENTRY(delta) table_next; STAILQ_ENTRY(delta) stack_next; - STAILQ_HEAD(, branch) branchlist; + LIST_HEAD(, branch) branchlist; LIST_ENTRY(delta) branch_next_date; }; @@ -100,7 +100,7 @@ struct delta { struct branch { char *revnum; LIST_HEAD(, delta) deltalist; /* Next delta in our branch. */ - STAILQ_ENTRY(branch) branch_next; + LIST_ENTRY(branch) branch_next; }; /* @@ -142,6 +142,7 @@ static void rcsfile_insertsorteddelta( static struct stream *rcsfile_getdeltatext(struct rcsfile *, struct delta *, struct buf **); static void rcsdelta_writestring(char *, size_t, struct stream *); +static void rcsdelta_insertbranch(struct delta *, struct branch *); /* Space formatting of RCS file. */ @@ -378,7 +379,7 @@ rcsfile_write(struct rcsfile *rf, struct * later when we write out the text. */ STAILQ_INIT(&deltalist_inverted); - STAILQ_FOREACH(b, &d->branchlist, branch_next) { + LIST_FOREACH(b, &d->branchlist, branch_next) { d_tmp = LIST_FIRST(&b->deltalist); STAILQ_INSERT_HEAD(&deltalist_inverted, d_tmp, delta_prev); STAILQ_INSERT_HEAD(&deltastack, d_tmp, stack_next); @@ -481,7 +482,7 @@ rcsfile_write_deltatext(struct rcsfile * * First, we need to sort our branches based on their date to * take into account some self-hacked RCS files. */ - STAILQ_FOREACH(b, &d->branchlist, branch_next) { + LIST_FOREACH(b, &d->branchlist, branch_next) { d_tmp = LIST_FIRST(&b->deltalist); if (LIST_EMPTY(&branchlist_datesorted)) { LIST_INSERT_HEAD(&branchlist_datesorted, d_tmp, @@ -818,9 +819,9 @@ rcsfile_freedelta(struct delta *d) * reason for the branch to exists, but we might still have deltas in * these branches. */ - while (!STAILQ_EMPTY(&d->branchlist)) { - b = STAILQ_FIRST(&d->branchlist); - STAILQ_REMOVE_HEAD(&d->branchlist, branch_next); + while (!LIST_EMPTY(&d->branchlist)) { + b = LIST_FIRST(&d->branchlist); + LIST_REMOVE(b, branch_next); free(b->revnum); free(b); } @@ -975,7 +976,7 @@ rcsfile_createdelta(char *revnum) d->text = buf_new(BUF_SIZE_DEFAULT); d->diffbase = NULL; - STAILQ_INIT(&d->branchlist); + LIST_INIT(&d->branchlist); return (d); } @@ -1025,7 +1026,7 @@ rcsfile_addelta(struct rcsfile *rf, char b = xmalloc(sizeof(struct branch)); b->revnum = brev; LIST_INIT(&b->deltalist); - STAILQ_INSERT_TAIL(&d_bp->branchlist, b, branch_next); + rcsdelta_insertbranch(d_bp, b); } /* Insert both into the tree, and into the lookup list. */ @@ -1112,7 +1113,7 @@ rcsfile_importdelta(struct rcsfile *rf, b = xmalloc(sizeof(struct branch)); b->revnum = brev; LIST_INIT(&b->deltalist); - STAILQ_INSERT_HEAD(&d_bp->branchlist, b, branch_next); + rcsdelta_insertbranch(d_bp, b); } /* Insert if not a placeholder. */ @@ -1165,7 +1166,7 @@ rcsfile_getbranch(struct rcsfile *rf, ch bprev = rcsrev_prefix(branchrev); d = rcsfile_getdelta(rf, bprev); free(bprev); - STAILQ_FOREACH(b, &d->branchlist, branch_next) { + LIST_FOREACH(b, &d->branchlist, branch_next) { if(rcsnum_cmp(b->revnum, branchrev) == 0) { free(branchrev); return (b); @@ -1175,6 +1176,31 @@ rcsfile_getbranch(struct rcsfile *rf, ch return (NULL); } +/* Insert a branch into a delta, sorted by branch revision date. */ +static void +rcsdelta_insertbranch(struct delta *d, struct branch *b) +{ + struct branch *b_iter; + + /* If it's empty, insert into head. */ + if (LIST_EMPTY(&d->branchlist)) { + LIST_INSERT_HEAD(&d->branchlist, b, branch_next); + return; + } + + /* Just put it in before the revdate that is lower. */ + LIST_FOREACH(b_iter, &d->branchlist, branch_next) { + if (rcsnum_cmp(b->revnum, b_iter->revnum) > 0) { + LIST_INSERT_BEFORE(b_iter, b, branch_next); + return; + } + if (LIST_NEXT(b_iter, branch_next) == NULL) + break; + } + /* Insert after last element. */ + LIST_INSERT_AFTER(b_iter, b, branch_next); +} + /* Insert a delta into the correct place in the table of the rcsfile. */ static void rcsfile_insertsorteddelta(struct rcsfile *rf, struct delta *d)