/*--------------------------------------------------------------------------------
 * Function:	wban_up0_traffic_generate
 *
 * Description:	creates a MSDU requiring acknowledge based on the MSDU generation		
 *				 specifications of the source model and sends it to the lower layer.
 *
 * No parameters
 *--------------------------------------------------------------------------------*/
static void wban_up0_traffic_generate() {
	Packet*	msdu_ptr;
	Packet*	app_traffic_ptr;

	int	msdu_size; /* size in bits */
	double next_intarr_time;	/*  interarrival time of next MSDU */
	double abs_next_intarr_time; /* absolute interarrival time of next MSDU */

	/* Stack tracing enrty point */
	FIN (wban_up0_traffic_generate);
	
	/* Generate a MSDU size outcome.		*/
	msdu_size = (int) ceil (oms_dist_outcome (up0_msdu_size_dist_ptr));
		
	/* 0 <= MAC frame body <= pMaxFrameBodyLength_Bits */
	if (msdu_size > pMaxFrameBodyLength_Bits)
		msdu_size = pMaxFrameBodyLength_Bits;	/* The size of generated MSDU is bigger than the maximum - the size is set to the maximum. */
		
	if (msdu_size < 0)
		msdu_size = 0;
	
	/* We produce unformatted packets. Create one.	*/
	msdu_ptr = op_pk_create (msdu_size);
	/* create a App traffic frame that encapsulates the msdu packet */
	app_traffic_ptr = op_pk_create_fmt ("wban_app_traffic_format");
	/* increment the data sequence number by 1 at a time */
	dataSN = (dataSN + 1) % 32768;
	op_pk_nfd_set (app_traffic_ptr, "App Sequence Number", dataSN);
	op_pk_nfd_set (app_traffic_ptr, "User Priority", 0);
	op_pk_nfd_set_pkt (app_traffic_ptr, "MSDU Payload", msdu_ptr); // wrap msdu in app traffic

	/* schedule next MSDU generation */
	next_intarr_time = oms_dist_outcome (up0_msdu_interarrival_dist_ptr);

	/* Make sure that interarrival time is not negative. In that case it will be set to 0. */
	if (next_intarr_time <0)
		next_intarr_time = 0.0;

	abs_next_intarr_time = op_sim_time () + next_intarr_time;
	
	// printf(" [Node %s] t = %f, msdu_create_time = %f, app_pkt_create_time = %f\n", \
	// 	node_name, op_sim_time(), op_pk_creation_time_get(msdu_ptr), op_pk_creation_time_get(app_traffic_ptr));
	/* send the App traffic via the stream to the lower layer.	*/
	op_pk_send (app_traffic_ptr, STRM_FROM_UP_TO_MAC);
	// printf (" [Node %s] t= %f -> UP7 MSDU (size = %d bits) \
		// was generated and sent to MAC layer.\n", node_name, op_sim_time(), msdu_size);
	
	if ((abs_next_intarr_time <= up0_stop_time) || (up0_stop_time == SC_INFINITE_TIME)) {
		up0_next_msdu_evh = op_intrpt_schedule_self (abs_next_intarr_time, SC_GENERATE_UP0);
		// printf ("\t Next UP0 MSDU will be generated at %f\n\n", abs_next_intarr_time);
	}

	/* Stack tracing exit point */
	FOUT;
}
示例#2
0
void ra_aloha_ss_intrpt_strm_handler(void)
{
    Packet* sduptr;
    Packet* pduptr;
    int istrm;
    int ss_id;
    char pk_fmt_str[64];
    static Boolean wait_ack_flag = OPC_FALSE;
    static Evhandle tr_ack;

    FIN(ra_aloha_ss_intrpt_strm_handler());

    istrm = op_intrpt_strm();

    if (istrm == svptr->istrm_hl) {
	sduptr = op_pk_get(istrm);
	if (wait_ack_flag) {
	    //What will happen if the subq overflows?
	    op_subq_pk_insert(0, sduptr, OPC_QPOS_TAIL);

	    if (op_prg_odb_ltrace_active("aloha")) {
		op_prg_odb_print_major("Queueing a data packet.", OPC_NIL);
	    }

	    FOUT ;
	}
	buf_pkptr = op_pk_copy(sduptr);
	pduptr = op_pk_create_fmt(Ra_Aloha_Data_Pk_Name );

	op_stat_write(svptr->sh_load_bits, op_pk_total_size_get(sduptr));
	op_stat_write(svptr->sh_load_bits, 0.0);
	op_stat_write(svptr->gsh_load_bits, op_pk_total_size_get(sduptr));
	op_stat_write(svptr->gsh_load_bits, 0.0);

	op_pk_nfd_set_pkt(pduptr, "Data", sduptr);
	op_pk_send(pduptr, svptr->ostrm_ll);

	tr_ack = op_intrpt_schedule_self(Cur_Time + tr_len_ack, TR_ACK_TO);
	wait_ack_flag = OPC_TRUE;

	if (op_prg_odb_ltrace_active("aloha")) {
	    op_prg_odb_print_major("Sending a data packet.", OPC_NIL);
	}
    } else if (istrm == svptr->istrm_ll) {
	pduptr = op_pk_get(istrm);
	op_pk_format(pduptr, pk_fmt_str);

	if (strcmp(pk_fmt_str, Ra_Aloha_Ack_Pk_Name)==0) {

	    op_pk_nfd_get_int32(pduptr, "SS ID", & ss_id);

	    if (ss_id != svptr->ss_id) {
		op_pk_destroy(pduptr);
		FOUT;
	    }

	    wait_ack_flag = OPC_FALSE;
	    //TODO: check whether the timer event is valid
	    op_ev_cancel(tr_ack);
	    //op_ev_cancel(svptr->tr_ack);

	    op_stat_write(svptr->sh_goodput_bits, op_pk_total_size_get(buf_pkptr));
	    op_stat_write(svptr->sh_goodput_bits, 0.0);

	    op_pk_destroy(buf_pkptr);

	    //the waiting queue is not empty, scheduing next tx
	    if (!op_subq_empty(0)) {
		sduptr = ra_aloha_ss_dequeue();
		buf_pkptr = op_pk_copy(sduptr);
		pduptr = op_pk_create_fmt(Ra_Aloha_Data_Pk_Name );
		op_pk_nfd_set(pduptr, "Data", sduptr);
		op_pk_send(pduptr, svptr->ostrm_ll);
		op_pk_send(pduptr, svptr->ostrm_ll);
		tr_ack = op_intrpt_schedule_self(Cur_Time + tr_len_ack, TR_ACK_TO);
	    }
	}

	//op_pk_send(pduptr, svptr->ostrm_hl);
    } //istrm_ll

    FOUT;
}