#include <dg.h>
#include <dgrq.h>
#include <dgxq.h>
#ifdef RPC_DG_PLOG
#ifndef RPC_C_DG_PKT_LOG_SIZE
# define RPC_C_DG_PKT_LOG_SIZE 256
#endif
#define MAX_LOGGED_PKT_BODY_LEN 16
typedef struct {
rpc_clock_t timestamp;
unsigned32 lossy_action;
rpc_dg_raw_pkt_hdr_t hdr;
byte_t body[MAX_LOGGED_PKT_BODY_LEN];
} pktlog_elt_t, *pktlog_elt_p_t;
PRIVATE pktlog_elt_p_t rpc_g_dg_pkt_log;
PRIVATE unsigned32 rpc_g_dg_pkt_log_bytes;
#ifdef STATIC_DG_PKTLOG
INTERNAL pktlog_elt_t _pkt_log[RPC_C_DG_PKT_LOG_SIZE];
#endif
INTERNAL unsigned16 pkt_log_index;
#endif
#ifdef DEBUG
INTERNAL char act_seq_string_buff[64];
#ifndef NO_SPRINTF
# define RPC__DG_ACT_SEQ_SPRINTF sprintf
#else
# define RPC__DG_ACT_SEQ_SPRINTF rpc__dg_act_seq_sprintf
#endif
#endif
#ifdef RPC_DG_PLOG
PRIVATE void rpc__dg_plog_pkt
(
rpc_dg_raw_pkt_hdr_p_t hdrp,
rpc_dg_pkt_body_p_t bodyp,
boolean32 recv,
unsigned32 lossy_action
)
{
pktlog_elt_p_t pp;
if (rpc_g_dg_pkt_log == NULL)
{
rpc_g_dg_pkt_log_bytes = RPC_C_DG_PKT_LOG_SIZE * sizeof(pktlog_elt_t);
#ifdef STATIC_DG_PKTLOG
rpc_g_dg_pkt_log = _pkt_log;
#else
RPC_MEM_ALLOC(rpc_g_dg_pkt_log, pktlog_elt_p_t,
rpc_g_dg_pkt_log_bytes,
RPC_C_MEM_DG_PKTLOG, RPC_C_MEM_NOWAIT);
if (rpc_g_dg_pkt_log == NULL)
return;
memset(rpc_g_dg_pkt_log, 0, rpc_g_dg_pkt_log_bytes);
#endif
}
pp = &rpc_g_dg_pkt_log[pkt_log_index];
pkt_log_index = (pkt_log_index + 1) % RPC_C_DG_PKT_LOG_SIZE;
pp->timestamp = rpc__clock_stamp();
pp->lossy_action = lossy_action;
memmove( &pp->hdr, hdrp, sizeof(rpc_dg_raw_pkt_hdr_t));
#ifndef MISPACKED_HDR
memmove( pp->body, bodyp,
MIN(MAX_LOGGED_PKT_BODY_LEN, ((rpc_dg_pkt_hdr_p_t) hdrp)->len)) ;
#else
memmove( pp->body, bodyp,
MIN(MAX_LOGGED_PKT_BODY_LEN, ...extracted from raw hdr... hdrp->len));
#endif
if (recv)
#ifndef MISPACKED_HDR
((rpc_dg_pkt_hdr_p_t)(&pp->hdr))->_rpc_vers |= 0x80;
#else
set bit in raw hdr
#endif
}
void (*rpc__dg_plog_dump_addr)(void) = rpc__dg_plog_dump;
PRIVATE void rpc__dg_plog_dump(void)
{
unsigned16 i;
unsigned32 st;
static char *lossy_action = "d?r ";
RPC_LOCK_ASSERT(0);
if (rpc_g_dg_pkt_log == NULL)
{
RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1,
("rpc__dg_plog_dump called, but DG Pkt Logging never enabled\n") );
return;
}
RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1,
("tstamp ver ptyp f1 f2 seq/fnum/sn ihnt ahnt len interface/ver/op activity sboot object drep at\n") );
RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1,
("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n") );
for (i = 0; i < RPC_C_DG_PKT_LOG_SIZE; i++)
{
pktlog_elt_p_t p = &rpc_g_dg_pkt_log[i];
unsigned_char_p_t obj, iface, act;
rpc_dg_pkt_hdr_p_t hdrp;
#ifndef MISPACKED_HDR
hdrp = (rpc_dg_pkt_hdr_p_t) &p->hdr;
#else
hdrp = converted local rep of raw hdr
#endif
if (p->timestamp == 0)
break;
uuid_to_string(&hdrp->object, &obj, &st);
uuid_to_string(&hdrp->if_id, &iface, &st);
uuid_to_string(&hdrp->actuid, &act, &st);
RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1,
("%08x %c%c%1u %-4.4s %02x %02x %08x/%04x/%04x %04x %04x %4d %s/%02u/%03u %s %9u %s %02x%02x%02x %02x\n",
p->timestamp,
(hdrp->_rpc_vers & 0x80) ? 'R' : lossy_action[p->lossy_action],
((i + 1) % RPC_C_DG_PKT_LOG_SIZE == pkt_log_index) ? '*' : ' ',
hdrp->_rpc_vers & 0x7f,
rpc__dg_pkt_name(RPC_DG_HDR_INQ_PTYPE(hdrp)),
hdrp->flags, hdrp->flags2,
hdrp->seq, hdrp->fragnum,
hdrp->serial_hi << 8 | hdrp->serial_lo,
hdrp->ihint, hdrp->ahint,
hdrp->len,
iface, hdrp->if_vers, hdrp->opnum, act,
hdrp->server_boot, obj,
hdrp->drep[0], hdrp->drep[1], hdrp->drep[2],
hdrp->auth_proto) );
rpc_string_free(&obj, &st);
rpc_string_free(&act, &st);
rpc_string_free(&iface, &st);
}
}
#endif
PRIVATE const char *rpc__dg_act_seq_string
(
rpc_dg_pkt_hdr_p_t hdrp ATTRIBUTE_UNUSED
)
{
#ifndef DEBUG
return("");
#else
RPC__DG_ACT_SEQ_SPRINTF(act_seq_string_buff, "%s, %lu.%u",
rpc__uuid_string(&hdrp->actuid), (unsigned long) hdrp->seq, hdrp->fragnum);
return(act_seq_string_buff);
#endif
}
PRIVATE const char *rpc__dg_pkt_name
(
rpc_dg_ptype_t ptype ATTRIBUTE_UNUSED
)
{
#ifndef DEBUG
return("");
#else
static const char *names[RPC_C_DG_PT_MAX_TYPE + 1] = {
"request",
"ping",
"response",
"fault",
"working",
"nocall",
"reject",
"ack",
"quit",
"fack",
"quack"
};
return((int) ptype > RPC_C_DG_PT_MAX_TYPE ? "BOGUS PACKET TYPE" : names[(int) ptype]);
#endif
}
PRIVATE void rpc__dg_xmit_pkt
(
rpc_socket_t sock,
rpc_addr_p_t addr,
rpc_socket_iovec_p_t iov,
int iovlen,
boolean *b
)
{
#ifdef MISPACKED_HDR
rpc_dg_raw_pkt_hdr_t raw_hdr;
rpc_dg_pkt_hdr_p_t hdrp;
#endif
rpc_socket_error_t serr;
size_t sendcc = 0;
size_t sentcc;
int i;
#ifdef MISPACKED_HDR
if (iov[0].len != RPC_C_DG_RAW_PKT_HDR_SIZE)
{
hdrp = (iov)[0].base;
compress_hdr(hdrp, &raw_hdr);
(iov)[0].iov_base = (caddr_t) &raw_hdr;
}
#endif
for (i = 0; i < iovlen; i++)
sendcc += iov[i].iov_len;
*b = true;
RPC_DG_SOCKET_SENDMSG_OOL(sock, iov, iovlen, addr, &sentcc, &serr);
if (RPC_SOCKET_IS_ERR(serr) || sentcc != sendcc)
{
RPC_DBG_GPRINTF(("(rpc__dg_xmit_pkt) sendmsg failed, sendcc = %ld, sentcc = %ld, error = %d\n",
sendcc, sentcc, RPC_SOCKET_ETOI(serr)));
*b = false;
}
RPC_DG_STATS_INCR(pkts_sent);
RPC_DG_STATS_INCR(pstats[RPC_DG_HDR_INQ_PTYPE(((rpc_dg_pkt_hdr_p_t) iov[0].iov_base))].sent);
#ifdef MISPACKED_HDR
iov[0].iov_base = hdrp;
#endif
}
PRIVATE void rpc__dg_xmit_hdr_only_pkt
(
rpc_socket_t sock,
rpc_addr_p_t addr,
rpc_dg_pkt_hdr_p_t hdrp,
rpc_dg_ptype_t ptype
)
{
rpc_socket_iovec_t iov[1];
rpc_dg_pkt_hdr_t hdr;
boolean b;
hdr = *hdrp;
RPC_DG_HDR_SET_VERS(&hdr);
RPC_DG_HDR_SET_PTYPE(&hdr, ptype);
RPC_DG_HDR_SET_DREP(&hdr);
hdr.flags = 0;
hdr.flags2 = 0;
hdr.len = 0;
iov[0].iov_base = (byte_p_t) &hdr;
iov[0].iov_len = RPC_C_DG_RAW_PKT_HDR_SIZE;
rpc__dg_xmit_pkt(sock, addr, iov, 1, &b);
}
PRIVATE void rpc__dg_xmit_error_body_pkt
(
rpc_socket_t sock,
rpc_addr_p_t addr,
rpc_dg_pkt_hdr_p_t hdrp,
rpc_dg_ptype_t ptype,
unsigned32 errst
)
{
rpc_socket_iovec_t iov[2];
rpc_dg_pkt_hdr_t hdr;
#ifndef MISPACKED_HDR
rpc_dg_epkt_body_t body;
#else
rpc_dg_raw_epkt_body_t body;
#endif
boolean b;
hdr = *hdrp;
RPC_DG_HDR_SET_VERS(&hdr);
RPC_DG_HDR_SET_PTYPE(&hdr, ptype);
RPC_DG_HDR_SET_DREP(&hdr);
hdr.flags = 0;
hdr.flags2 = 0;
hdr.len = RPC_C_DG_RAW_EPKT_BODY_SIZE;
#ifndef MISPACKED_HDR
body.st = errst;
#else
#error "extract and pack the 32 bit status code into the body"
#endif
iov[0].iov_base = (byte_p_t) &hdr;
iov[0].iov_len = RPC_C_DG_RAW_PKT_HDR_SIZE;
iov[1].iov_base = (byte_p_t) &body;
iov[1].iov_len = hdr.len;
rpc__dg_xmit_pkt(sock, addr, iov, 2, &b);
RPC_DBG_GPRINTF(("(rpc__dg_xmit_call_error_body_pkt) \"%s\" - st 0x%x sent\n",
rpc__dg_pkt_name(ptype), errst));
}
PRIVATE unsigned32 rpc__dg_mgmt_inq_calls_sent(void)
{
return (rpc_g_dg_stats.calls_sent);
}
PRIVATE unsigned32 rpc__dg_mgmt_inq_calls_rcvd(void)
{
return (rpc_g_dg_stats.calls_rcvd);
}
PRIVATE unsigned32 rpc__dg_mgmt_inq_pkts_sent(void)
{
return (rpc_g_dg_stats.pkts_sent);
}
PRIVATE unsigned32 rpc__dg_mgmt_inq_pkts_rcvd(void)
{
return (rpc_g_dg_stats.pkts_rcvd);
}
PRIVATE void rpc__dg_stats_print(void)
{
unsigned16 i;
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("RPC DG Protocol Statistics\n") );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("--------------------------------------------------------\n") );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Calls sent: %9u\n", rpc_g_dg_stats.calls_sent) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Calls rcvd: %9u\n", rpc_g_dg_stats.calls_rcvd) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Pkts sent: %9u\n", rpc_g_dg_stats.pkts_sent) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Pkts rcvd: %9u\n", rpc_g_dg_stats.pkts_rcvd) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Broadcasts sent: %9u\n", rpc_g_dg_stats.brds_sent) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Dups sent: %9u\n", rpc_g_dg_stats.dups_sent) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Dups rcvd: %9u\n", rpc_g_dg_stats.dups_rcvd) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("Out of orders rcvd: %9u\n", rpc_g_dg_stats.oo_rcvd) );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("\nBreakdown by packet type sent rcvd\n") );
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("------------------------------------------------------------------\n") );
for (i = 0; i <= RPC_C_DG_PT_MAX_TYPE; i++)
{
RPC_DBG_PRINTF(rpc_e_dbg_stats, 1,
("(%02u) %-10s %9u %9u\n",
i, rpc__dg_pkt_name(i),
rpc_g_dg_stats.pstats[i].sent,
rpc_g_dg_stats.pstats[i].rcvd) );
}
}
PRIVATE unsigned16 rpc__dg_uuid_hash
(
uuid_p_t uuid
)
{
unsigned32 *lp = (unsigned32 *) uuid;
unsigned32 hash = lp[0] ^ lp[1] ^ lp[2] ^ lp[3];
return ((hash >> 16) ^ hash);
}