Beispiel #1
0
static inline void initialize_block_info(paper_input_databuf_t *paper_input_databuf_p, block_info_t * binfo, uint64_t pkt_mcnt) {

    int i;

    // We might be restarting so mark all currently active blocks, with the exception
    // of block_i, as filled. We will restart at block_i.  On program startup, this loop 
    // as no functional effect as no blocks are active and all block_active elements are 0. 
    for(i = 0; i < N_INPUT_BLOCKS; i++) {
	if(i == binfo->block_i) {
		binfo->block_active[i] = 0;	
	} else {
    		if(binfo->block_active[i]) {
			paper_input_databuf_p->block[i].header.good_data = 0;   // all data are bad at this point
			set_block_filled(paper_input_databuf_p, binfo, i);
		}
	}
    }		

    // On program startup block_i will be zero.  If we are restarting,  this will set 
    // us up to restart at the beginning of block_i. 
    binfo->mcnt_start = pkt_mcnt - binfo->block_i * N_SUB_BLOCKS_PER_INPUT_BLOCK;

    binfo->mcnt_prior = pkt_mcnt;
    binfo->out_of_seq_cnt = 0;
    binfo->initialized = 1;
}
Beispiel #2
0
// Method to process a received packet
// Processing involves the following
// (1) header extraction
// (2) block population (output buffer data type is a block)
// (3) buffer population (if block is filled)
static inline uint64_t process_packet(flag_input_databuf_t * db, struct hashpipe_udp_packet *p) {
    static block_info_t binfo;
    packet_header_t     pkt_header;
    
    // Parse packet header
    get_header(p, &pkt_header);
    uint64_t pkt_mcnt = pkt_header.mcnt;
    uint64_t cur_mcnt = binfo.mcnt_start;
    int dest_block_idx = get_block_idx(pkt_mcnt);
    // fprintf(stdout, "Block idx = %d\n", dest_block_idx);

    // Check mcnt to see if packet belongs in current block, next, or the one after
    uint64_t pkt_mcnt_dist = pkt_mcnt - cur_mcnt;
    
    if (pkt_mcnt_dist >= 2*Nm) { // 2nd next block (Current block + 2)
        set_block_filled(db, &binfo);

        // Advance mcnt_start to next block
        cur_mcnt += Nm;
        binfo.mcnt_start += Nm;
        binfo.block_i = (binfo.block_i + 1) % N_INPUT_BLOCKS;

        // Initialize next block
        flag_input_databuf_wait_free(db, dest_block_idx);
        initialize_block(db, pkt_mcnt);

        // Reset packet counter for this block
        binfo.packet_count[dest_block_idx] = 0;
    }
    // Increment packet count for block
    binfo.packet_count[dest_block_idx]++;

    // Validate FID and XID
    // Calculate "m" and "f" which index the buffer for writing packet payload
    if (calc_block_indices(&binfo, &pkt_header) == -1) {
        hashpipe_error(__FUNCTION__, "invalid FID and XID in header");
        return -1;
    }

    // Calculate starting points for writing packet payload into buffer
    // POSSIBLE RACE CONDITION!!!! Need to lock db->block access with semaphore
    uint64_t * dest_p  = db->block[dest_block_idx].data + flag_input_databuf_idx(binfo.m, binfo.f, 0, 0);
    const uint64_t * payload_p = (uint64_t *)(p->data+8);
    
    // Copy data into buffer
    memcpy(dest_p, payload_p, N_BYTES_PER_PACKET);

    // print_pkt_header(&pkt_header);

    return pkt_mcnt;
}
Beispiel #3
0
// This function returns -1 unless the given packet causes a block to be marked
// as filled in which case this function returns the marked block's first mcnt.
// Any return value other than -1 will be stored in the status memory as
// NETMCNT, so it is important that values other than -1 are returned rarely
// (i.e. when marking a block as filled)!!!
static inline uint64_t write_paper_packet_to_blocks(paper_input_databuf_t *paper_input_databuf_p, struct guppi_udp_packet *p) {

    static block_info_t binfo;
    packet_header_t pkt_header;
    const uint64_t *payload_p;
    int rv;
    int i;
    uint64_t *dest_p;
    uint64_t netmcnt = -1; // Value to store in status memory
#if N_DEBUG_INPUT_BLOCKS == 1
    static uint64_t debug_remaining = -1ULL;
    static off_t debug_offset = 0;
    uint64_t * debug_ptr;
#endif

    // housekeeping for each packet
    get_header(p, &pkt_header);

#if N_DEBUG_INPUT_BLOCKS == 1
    debug_ptr = (uint64_t *)&paper_input_databuf_p->block[N_INPUT_BLOCKS];
    debug_ptr[debug_offset++] = be64toh(*(uint64_t *)(p->data));
    if(--debug_remaining == 0) {
	exit(1);
    }
    if(debug_offset >= sizeof(paper_input_block_t)/sizeof(uint64_t)) {
	debug_offset = 0;
    }
#endif

    if(! binfo.initialized) {
	// insist that we start on a multiple of sub_blocks/block
    	if(pkt_header.mcnt % N_SUB_BLOCKS_PER_INPUT_BLOCK != 0) {
		return -1;
    	}
	initialize_block_info(paper_input_databuf_p, &binfo, pkt_header.mcnt);
    }
    if(out_of_seq_mcnt(&binfo, pkt_header.mcnt)) {
    	return(handle_out_of_seq_mcnt(&binfo));
    }
    if((rv = calc_block_indexes(&binfo, &pkt_header))) {
	return rv;
    }
    if(! binfo.block_active[binfo.block_i]) {
	// new block, pass along the block for N_INPUT_BLOCKS/2 blocks ago
	i = subtract_block_i(binfo.block_i, N_INPUT_BLOCKS/2);
#if N_DEBUG_INPUT_BLOCKS == 1
#define DEBUG_EXTRA (0x10000)
	if(set_block_filled(paper_input_databuf_p, &binfo, i) && debug_remaining > DEBUG_EXTRA) {
	    debug_remaining = DEBUG_EXTRA;
	}
#else
	set_block_filled(paper_input_databuf_p, &binfo, i);
#endif
	netmcnt = paper_input_databuf_p->block[i].header.mcnt;
	// Wait (hopefully not long!) for free block for this packet
	if((rv = paper_input_databuf_busywait_free(paper_input_databuf_p, binfo.block_i)) != GUPPI_OK) {    
	    if (rv==GUPPI_TIMEOUT) {
		// run_threads is 0 (i.e. shutting down)
	        return -1;
	    } else {
	        guppi_error(__FUNCTION__, "error waiting for free databuf");
	        run_threads=0;
	        pthread_exit(NULL);
	        return -1;
	    }
	}

	initialize_block(paper_input_databuf_p, &binfo, pkt_header.mcnt); 
    }
    binfo.block_active[binfo.block_i]++;	// increment packet count for block
    // end housekeeping

    // Calculate starting points for unpacking this packet into block's data buffer.
    dest_p = paper_input_databuf_p->block[binfo.block_i].data
	+ paper_input_databuf_data_idx(binfo.m, binfo.x, binfo.q, binfo.f, 0, 0);
    payload_p        = (uint64_t *)(p->data+8);

    // Copy data into buffer
    memcpy(dest_p, payload_p, N_BYTES_PER_PACKET);


    return netmcnt;
}