/** * ICmdQClearPort removes all outgoing packets for the current port * and all incoming packets, too. ACK packets are left alone. * * NOTE: * Make sure that this routine is only called when all communications * are finalized. * *<!-----------------------------------------------------------------------*/ static T_void ICmdQClearPort(T_void) { T_word16 i ; T_cmdQStruct *p_cmdQ ; T_cmdQPacketStruct *p_packet ; T_packetLong packet ; DebugRoutine("ICmdQClearPort") ; /* First, read in all the incoming packets (and ignore them). */ while (PacketGet(&packet) == 0) { } /* Catch all the outgoing packets. */ /* Go through all the queues looking for packets to remove. */ for (i=1; i<PACKET_COMMAND_MAX; i++) { for (;;) { p_cmdQ = &G_activeCmdQList[i] ; p_packet = p_cmdQ->last ; if (p_packet != NULL) { #ifndef NDEBUG /* Check for the tag. */ if (strcmp(p_packet->tag, "CmQ") != 0) { printf("Bad packet %p\n", p_packet) ; DebugCheck(FALSE) ; } #endif /* Found a packet, remove it. */ p_cmdQ->last = p_packet->prev ; if (p_cmdQ->last == NULL) p_cmdQ->first = NULL ; else { p_cmdQ->last->next = NULL ; } #ifndef NDEBUG /* Mark the packet as gone. */ strcpy(p_packet->tag, "c_q") ; G_packetsFree++ ; #endif /* Delete it. */ MemFree(p_packet) ; } else { /* No packet. Stop looping on this queue. */ break ; } } } DebugEnd() ; }
void I_NetCmd (void) { if (doomcom.command == CMD_SEND) { PacketSend (); } else if (doomcom.command == CMD_GET) { PacketGet (); } else I_Error ("Bad net cmd: %i\n",doomcom.command); }
static int IterateSummarizeSession( OWPDataRec *rec, void *cdata ) { OWPStats stats = cdata; OWPPacket node; double d; double derr; long int i; /* * Mark the first offset that has a seq greater than currently * interested in. This allows the caller to know what offset to * use for the "beginning" of the next summary. */ if(!stats->next_oset && (rec->seq_no >= stats->last)){ stats->next_oset = stats->begin_oset + stats->i * stats->hdr->rec_size; } /* increase file index */ stats->i++; /* * return (cont processing) if this record is not part of this sum-session * * XXX: This may not be completely correct with respect to reordering... * If the first packet of the "next" session takes place before the * last packet of the "previous" session - should reordering be counted? * */ if((rec->seq_no < stats->first) || (rec->seq_no >= stats->last)){ return 0; } /* * Flush OWPPacket buffer before dealing with this packet so the buffer * only holds as many records as is needed. * */ if(OWPIsLostRecord(rec)){ /* * if current rec is lost, then all seq nums less than this one * can be flushed. */ while(stats->pbegin->seq < rec->seq_no){ if(!PacketBeginFlush(stats)) return -1; } }else{ /* * If this packet is not lost, then compute recv-lossThresh * and flush all packets with "sent" before this time. */ OWPNum64 thresh = OWPNum64Sub(rec->recv.owptime, stats->hdr->test_spec.loss_timeout); while(OWPNum64Cmp(stats->pbegin->schedtime,thresh) < 0){ if(!PacketBeginFlush(stats)) return -1; } } /* * Fetch current packet record */ if( !(node = PacketGet(stats,rec->seq_no))){ OWPError(stats->ctx,OWPErrFATAL,EINVAL, "IterateSummarizeSession: Unable to fetch packet #%lu", rec->seq_no); return -1; } /* * Check if in "skip" range. If so, then skip aggregation information * for this record. */ i = stats->iskip; while(stats->skips && (i < (long int)stats->hdr->num_skiprecs)){ if((node->seq >= stats->skips[i].begin) && (node->seq <= stats->skips[i].end)){ return 0; } i++; } if( OWPIsLostRecord(rec)){ /* * If this has been seen before, then we have a problem. */ if(node->seen){ OWPError(stats->ctx,OWPErrFATAL,EINVAL, "IterateSummarizeSession: Unexpected lost packet record"); return -1; } node->lost = True; stats->sent++; /* sync */ if(!rec->recv.sync){ stats->sync = 0; } /* * Time error */ derr = OWPGetTimeStampError(&rec->recv); stats->maxerr = MAX(stats->maxerr,derr); if(stats->output){ fprintf(stats->output,"seq_no=%-10u *LOST*\n", rec->seq_no); } return 0; } else{ /* * If this has already been declared lost, we have a problem. */ if(node->lost){ OWPError(stats->ctx,OWPErrFATAL,EINVAL, "IterateSummarizeSession: Unexpected duplicate packet record (for lost one)"); return -1; } if(!node->seen){ stats->sent++; } node->seen++; } /* * j-reordering. See: * http://www.internet2.edu/~shalunov/ippm/\ * draft-shalunov-reordering-definition-02.txt */ #define rseqindex(x) ((x) >= 0? x: x + stats->rlistlen) for(i=0;i < MIN(stats->rnumseqno,stats->rlistlen) && rec->seq_no < stats->rseqno[rseqindex(stats->rindex-i-1)];i++){ stats->rn[i]++; } stats->rseqno[stats->rindex] = rec->seq_no; stats->rnumseqno++; stats->rindex++; stats->rindex %= stats->rlistlen; #undef rseqindex /* sync */ if(!rec->send.sync || !rec->recv.sync){ stats->sync = 0; } /* * compute delay for this packet */ d = OWPDelay(&rec->send, &rec->recv); /* * compute total error from send/recv */ derr = OWPGetTimeStampError(&rec->send) + OWPGetTimeStampError(&rec->recv); stats->maxerr = MAX(stats->maxerr,derr); /* * Print individual packet record */ if(stats->output){ if(rec->send.sync && rec->recv.sync){ if (stats->display_unix_ts == True) { /* print using unix timestamp */ double epochdiff = (OWPULongToNum64(OWPJAN_1970))>>32; fprintf(stats->output, "seq_no=%d delay=%e %s (sync, err=%.3g %s) sent=%f recv=%f\n", rec->seq_no, d*stats->scale_factor, stats->scale_abrv, derr*stats->scale_factor, stats->scale_abrv, OWPNum64ToDouble(rec->send.owptime) - epochdiff, OWPNum64ToDouble(rec->recv.owptime) - epochdiff ); } else { /* print the default */ fprintf(stats->output, "seq_no=%-10u delay=%.3g %s\t(sync, err=%.3g %s)\n", rec->seq_no, d*stats->scale_factor, stats->scale_abrv, derr*stats->scale_factor,stats->scale_abrv); } }
static OWPBoolean PacketBeginFlush( OWPStats stats ) { OWPPacket node = stats->pbegin; OWPBoolean keep_parsing = True; if(!node){ OWPError(stats->ctx,OWPErrFATAL,EINVAL, "PacketBeginFlush: begin node empty?"); return False; } /* * Move begin skip to next skip if needed (based on node->seq). */ while(stats->skips && (stats->iskip < (long int)stats->hdr->num_skiprecs) && (node->seq > stats->skips[stats->iskip].end)){ stats->iskip++; } /* * Check if in "skip" range. If so, then skip aggregation information * and flush the packet. (iskip has been forwarded to guarentee the * first skip range is the only possible match.) */ if(stats->skips && (stats->iskip < (long int)stats->hdr->num_skiprecs) && (node->seq >= stats->skips[stats->iskip].begin)){ goto flush; } /* * Loss and Dup Stats Happen Here */ if(node->lost){ /* count lost packets */ stats->lost++; } else if(node->seen){ /* count dups */ stats->dups += (node->seen - 1); } flush: /* Retain the last scheduled timestamp */ stats->end_time = node->schedtime; if(node->next){ stats->pbegin = node->next; } else if((node->seq+1) < stats->last){ stats->pbegin = PacketGet(stats,node->seq+1); } else{ keep_parsing = False; } PacketFree(stats,node); return keep_parsing; }
T_void CmdQUpdateAllReceives(T_void) { T_packetLong packet ; T_sword16 status ; T_byte8 command ; T_byte8 ackCommand ; T_word32 packetId ; T_packetShort ackPacket ; E_Boolean packetOkay; T_directTalkUniqueAddress uniqueID; DebugRoutine("CmdQUpdateAllReceives") ; INDICATOR_LIGHT(260, INDICATOR_GREEN) ; DebugCheck(G_init == TRUE) ; /* Let's see how many ports there are. */ DebugCheckValidStack() ; // numPorts = CommGetNumberPorts() ; DebugCheckValidStack() ; /* Set the active port (and any additional information). */ DebugCheckValidStack() ; /* Hunting for a bug... */ /* ... . */ DebugCheckValidStack() ; DirectTalkGetUniqueAddress(&uniqueID); /* Loop while there are packets to get. */ do { DebugCompare("CmdQUpdateAllReceives") ; DebugCheckValidStack() ; /* Try getting a packet. */ status = PacketGet(&packet) ; DebugCheckValidStack() ; /* Did we get a packet? */ if (status == 0) { /* Yes, we did. See what command is being issued. */ command = packet.data[0] ; /* Make sure it is a legal commands. Unfortunately, */ /* we'll have to ignore those illegal commands. */ if (command < PACKET_COMMAND_UNKNOWN) { /* Is it an ACK packet? */ //printf("R(%d) %2d %ld %ld\n", CmdQGetActivePortNum(), packet.data[0], packet.header.id, TickerGet()) ; fflush(stdout) ; #ifdef COMPILE_OPTION_CREATE_PACKET_DATA_FILE fprintf(G_packetFile, "R(%d) %2d %ld %ld\n", CmdQGetActivePortNum(), packet.data[0], packet.header.id, SyncTimeGet()) ; fflush(G_packetFile) ; #endif if (command == PACKET_COMMAND_ACK) { /* Yes, it is an ack. See what command it is */ /* acknowledging. */ ackCommand = packet.data[1] ; /* Is that a valid command? */ if (ackCommand < PACKET_COMMAND_UNKNOWN) { INDICATOR_LIGHT(264, INDICATOR_GREEN) ; /* Yes. But is it a lossless command? */ if (G_CmdQTypeCommand[ackCommand] == PACKET_COMMAND_TYPE_LOSSLESS) { /* Get the packet id. */ packetId = *((T_word32 *)(&(packet.data[2]))) ; /* Is there a list at that point? */ if (G_activeCmdQList[ackCommand].last != NULL) { /* Yes. Is there an ack for the same packet */ /* waiting? */ T_cmdQPacketStruct *p = G_activeCmdQList[ackCommand].first; while (p) { // Search for a matching packet id if (p->packet.header.id == packetId) { /* Yes. We can now discard it. */ DebugCheckValidStack() ; ICmdQDiscardPacket(ackCommand, p) ; DebugCheckValidStack() ; break; } // Walk the complete list of this type of packet p = p->next; } } } INDICATOR_LIGHT(264, INDICATOR_RED) ; } } else { /* No, do the normal action. */ /** If this is a lossy packet, always call the **/ /** callback routine. **/ packetOkay = TRUE; /* Is this a lossless command? */ if (G_CmdQTypeCommand[command] == PACKET_COMMAND_TYPE_LOSSLESS) { INDICATOR_LIGHT(268, INDICATOR_GREEN) ; memset(&ackPacket, 0xFF, sizeof(ackPacket)); /* Yes, it is. We need to send an ACK that */ /* we got it. */ /* Make an ack packet with the packet's */ /* command and id we received. */ ackPacket.data[0] = PACKET_COMMAND_ACK ; ackPacket.data[1] = command ; *((T_word32 *)(&ackPacket.data[2])) = packet.header.id ; /* Send it! Note that we go through our */ /* routines. */ INDICATOR_LIGHT(272, INDICATOR_GREEN) ; DebugCheckValidStack() ; CmdQSendShortPacket( &ackPacket, &packet.header.sender, 140, /* Once two seconds is plenty fast */ 0, /* No extra data since no callback. */ NULL) ; /* No callback. */ INDICATOR_LIGHT(272, INDICATOR_RED) ; DebugCheckValidStack() ; INDICATOR_LIGHT(268, INDICATOR_RED) ; } /* IF the packet is a new packet or a lossy one, */ /* we'll go ahead and do the appropriate action */ /* on this side. */ //printf("Considering %p [%d]\n", G_cmdQActionList[command], command) ; if ((G_cmdQActionList[command] != NULL) && (packetOkay == TRUE)) { /* Call the appropriate action item. */ INDICATOR_LIGHT(276, INDICATOR_GREEN) ; //printf("Did go: (%d) %d, %p\n", command, packetOkay, G_cmdQActionList[command]) ; fflush(stdout) ; DebugCheckValidStack() ; G_cmdQActionList[command] ((T_packetEitherShortOrLong *)&packet) ; DebugCheckValidStack() ; INDICATOR_LIGHT(276, INDICATOR_RED) ; DebugCompare("CmdQUpdateAllReceives") ; } else { //printf("Didn't go: (%d) %d, %p\n", command, packetOkay, G_cmdQActionList[command]) ; fflush(stdout) ; } } } } DebugCheckValidStack() ; } while (status == 0) ; DebugEnd() ; INDICATOR_LIGHT(260, INDICATOR_RED) ; }