📄 svc_kudp.c
字号:
#ifndef lintstatic char *sccsid = "@(#)svc_kudp.c 4.4 (ULTRIX) 3/7/91";#endif lint/************************************************************************ * * * Copyright (c) 1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Portions of this software have been licensed to * Digital Equipment Company, Maynard, MA. * Copyright (c) 1986 Sun Microsystems, Inc. ALL RIGHTS RESERVED. *//* * * Modification history: * * 25 Aug 90 -- chet * Allow for Prestoserve in sizing of duplicate request cache. * Shrink dupreq struct and fix NOTDUP macro. * * 9 Mar 90 -- chet * Add dynamic allocation of duplicate request cache hash lists. * * 10 Dec 89 -- chet * Re-do duplicate request cache allocation and locking scheme. * * 30 May 89 -- U. Sinkewicz * Replaced smp_lock(&so->lk_socket, LK_RETRY) with SO_LOCK() * as part of an smp bug fix. Fix guarantees that socket doesn't * changed while unlocked during sleeps or for the lock hierarchy. * * 6 Mar 89 -- chet * Made duplicate request cache size a function of "system size". * * 19-Dec-88 condylis * Restructured some of dupreq cache code because of inability to call * kmem_alloc while holding a spin lock. * * 10-Jun-88 condylis * Added smp locking to dupreq hash list and dupreq event counters * and interaction with socket locks. Added SMP locking for * RPC server statistics. * * 12-11-87 Robin L. and Larry C. and Ricky P. * Added new kmalloc memory allocation to system. * * 11 May 87 -- chet * Changed/added new server duplicate * transaction cache interface routines. * *//* * svc_kudp.c, * Server side for UDP/IP based RPC in the kernel. * */#include "../h/param.h"#include "../h/systm.h"#include "../h/time.h"#include "../rpc/types.h"#include "../netinet/in.h"#include "../rpc/xdr.h"#include "../rpc/auth.h"#include "../rpc/clnt.h"#include "../rpc/rpc_msg.h"#include "../rpc/svc.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/mbuf.h"#include "../h/kernel.h"#include "../h/smp_lock.h"#include "../h/cpudata.h"extern struct timeval *timepick;#define rpc_buffer(xprt) ((xprt)->xp_p1)/* * Routines exported through ops vector. */bool_t svckudp_recv();bool_t svckudp_send();enum xprt_stat svckudp_stat();bool_t svckudp_getargs();bool_t svckudp_freeargs();void svckudp_destroy();/* * Server transport operations vector. */struct xp_ops svckudp_op = { svckudp_recv, /* Get requests */ svckudp_stat, /* Return status */ svckudp_getargs, /* Deserialize arguments */ svckudp_send, /* Send reply */ svckudp_freeargs, /* Free argument data space */ svckudp_destroy /* Destroy transport handle */};struct mbuf *ku_recvfrom();void xdrmbuf_init();/* * Transport private data. * Kept in xprt->xp_p2. */struct udp_data { int ud_flags; /* flag bits, see below */ u_long ud_xid; /* id */ struct mbuf *ud_inmbuf; /* input mbuf chain */ XDR ud_xdrin; /* input xdr stream */ XDR ud_xdrout; /* output xdr stream */ char ud_verfbody[MAX_AUTH_BYTES]; /* verifier */ struct lock_t u_lk_udpdata; /* smp lock for type 2*/ /* mbuf data */};/* * Flags */#define UD_BUSY 0x001 /* buffer is busy */#define UD_WANTED 0x002 /* buffer wanted *//* * Server statistics */struct { int rscalls; int rsbadcalls; int rsnullrecv; int rsbadlen; int rsxdrcall;} rsstat;extern struct lock_t lk_nfsstat;/* * Create a transport record. * The transport record, output buffer, and private data structure * are allocated. The output buffer is serialized into using xdrmem. * There is one transport record per user process which implements a * set of services. */SVCXPRT *svckudp_create(sock, port) struct socket *sock; u_short port;{ register SVCXPRT *xprt; register struct udp_data *ud;#ifdef RPCDEBUG rpc_debug(4, "svckudp_create so = %x, port = %d\n", sock, port);#endif kmem_alloc(xprt, SVCXPRT *, (u_int)sizeof(SVCXPRT), KM_RPC); kmem_alloc(rpc_buffer(xprt), caddr_t, (u_int)UDPMSGSIZE, KM_RPC); kmem_alloc(ud, struct udp_data *, (u_int)sizeof(struct udp_data), KM_RPC); /* Initialize smp lock for outgoing type 2 mbuf data */ lockinit(&ud->u_lk_udpdata, &lock_udpdata_d); xprt->xp_addrlen = 0; xprt->xp_p2 = (caddr_t)ud; xprt->xp_verf.oa_base = ud->ud_verfbody; xprt->xp_ops = &svckudp_op; xprt->xp_port = port; xprt->xp_sock = sock; xprt_register(xprt); return (xprt);} /* * Destroy a transport record. * Frees the space allocated for a transport record. */voidsvckudp_destroy(xprt) register SVCXPRT *xprt;{ register struct udp_data *ud = (struct udp_data *)xprt->xp_p2;#ifdef RPCDEBUG rpc_debug(4, "usr_destroy %x\n", xprt);#endif if (ud->ud_inmbuf) { m_freem(ud->ud_inmbuf); } kmem_free((caddr_t)ud, KM_RPC); kmem_free((caddr_t)rpc_buffer(xprt), KM_RPC); kmem_free((caddr_t)xprt, KM_RPC);}/* * Receive rpc requests. * Pulls a request in off the socket, checks if the packet is intact, * and deserializes the call packet. */bool_tsvckudp_recv(xprt, msg) register SVCXPRT *xprt; struct rpc_msg *msg;{ register struct udp_data *ud = (struct udp_data *)xprt->xp_p2; register XDR *xdrs = &(ud->ud_xdrin); register struct mbuf *m; int s;#ifdef RPCDEBUG rpc_debug(4, "svckudp_recv %x\n", xprt);#endif smp_lock(&lk_nfsstat, LK_RETRY); rsstat.rscalls++; smp_unlock(&lk_nfsstat); s = splnet(); /* smp lock socket during receive */ /* smp_lock(&xprt->xp_sock->lk_socket, LK_RETRY); */ SO_LOCK(xprt->xp_sock); m = ku_recvfrom(xprt->xp_sock, &(xprt->xp_raddr)); smp_unlock(&xprt->xp_sock->lk_socket); (void) splx(s); if (m == NULL) { /* * This looks silly, but this stat is useless * on an SMP machine by design. Leave it here * for non-SMP use only. */ if (!smp) { smp_lock(&lk_nfsstat, LK_RETRY); rsstat.rsnullrecv++; smp_unlock(&lk_nfsstat); } return (FALSE); } if (m->m_len < 4*sizeof(u_long)) { smp_lock(&lk_nfsstat, LK_RETRY); rsstat.rsbadlen++; smp_unlock(&lk_nfsstat); goto bad; } xdrmbuf_init(&ud->ud_xdrin, m, XDR_DECODE); if (! xdr_callmsg(xdrs, msg)) { smp_lock(&lk_nfsstat, LK_RETRY); rsstat.rsxdrcall++; smp_unlock(&lk_nfsstat); goto bad; } ud->ud_xid = msg->rm_xid; ud->ud_inmbuf = m;#ifdef RPCDEBUG rpc_debug(5, "svckudp_recv done\n");#endif return (TRUE);bad: m_freem(m); ud->ud_inmbuf = NULL; smp_lock(&lk_nfsstat, LK_RETRY); rsstat.rsbadcalls++; smp_unlock(&lk_nfsstat); return (FALSE);}staticnoop(){}staticbuffree(ud) register struct udp_data *ud;{ int s; s = splimp(); smp_lock(&ud->u_lk_udpdata, LK_RETRY); ud->ud_flags &= ~UD_BUSY; if (ud->ud_flags & UD_WANTED) { ud->ud_flags &= ~UD_WANTED; wakeup((caddr_t)ud); } smp_unlock(&ud->u_lk_udpdata); splx(s);}/* * Send rpc reply. * Serialize the reply packet into the output buffer then * call ku_sendto to make an mbuf out of it and send it. */bool_t/* ARGSUSED */svckudp_send(xprt, msg) register SVCXPRT *xprt; struct rpc_msg *msg; { register struct udp_data *ud = (struct udp_data *)xprt->xp_p2; register XDR *xdrs = &(ud->ud_xdrout); register int slen; register int stat = FALSE; int s; struct mbuf *m, *mclgetx();#ifdef RPCDEBUG rpc_debug(4, "svckudp_send %x\n", xprt);#endif s = splimp(); /* SMP lock mbuf data while setting up for sleep */ smp_lock(&ud->u_lk_udpdata, LK_RETRY); while (ud->ud_flags & UD_BUSY) { ud->ud_flags |= UD_WANTED; sleep_unlock((caddr_t)ud, PZERO-2, &ud->u_lk_udpdata); smp_lock(&ud->u_lk_udpdata, LK_RETRY); } ud->ud_flags |= UD_BUSY; smp_unlock(&ud->u_lk_udpdata); (void) splx(s); m = mclgetx(buffree, (caddr_t)ud, rpc_buffer(xprt), UDPMSGSIZE, M_WAIT); if (m == NULL) { buffree(ud); return (stat); } xdrmbuf_init(&ud->ud_xdrout, m, XDR_ENCODE); msg->rm_xid = ud->ud_xid; if (xdr_replymsg(xdrs, msg)) { slen = (int)XDR_GETPOS(xdrs); if (m->m_next == 0) { /* XXX */ m->m_len = slen; } if (!ku_sendto_mbuf(xprt->xp_sock, m, &xprt->xp_raddr)) stat = TRUE; } else { printf("svckudp_send: xdr_replymsg failed\n"); m_freem(m);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -