/** * @brief Start CCA. * * @param parameter Pointer to trx_id */ static void cca_start(void *parameter) { trx_id_t trx_id = *(trx_id_t *)parameter; /* Check if trx is currently detecting a frame ota */ if (trx_state[trx_id] == RF_RX) { uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id; uint8_t agc_freeze = trx_bit_read(reg_offset + SR_RF09_AGCC_FRZS); if (agc_freeze) { csma_continue(trx_id); } else { #ifdef SUPPORT_MODE_SWITCH if (tal_pib[trx_id].ModeSwitchEnabled) { trigger_cca_meaurement(trx_id); } else #endif { transmit_frame(trx_id, WITH_CCA); } } } else { #ifdef SUPPORT_MODE_SWITCH if (tal_pib[trx_id].ModeSwitchEnabled) { trigger_cca_meaurement(trx_id); } else #endif { transmit_frame(trx_id, WITH_CCA); } } }
static EVENT_HANDLER(physical_ready) { FRAME f; size_t len; int link, checksum; len = sizeof(FRAME); CHECK(CNET_read_physical(&link, (char *)&f, &len)); checksum = f.checksum; f.checksum = 0; if(CNET_ccitt((unsigned char *)&f, len) != checksum) { return; // bad checksum, ignore frame } switch (f.kind) { case ACK : if(f.seq == ackexpected) { CNET_stop_timer(lasttimer); ackexpected = 1-ackexpected; CNET_enable_application(ALLNODES); } break; case DATA : if(f.seq == frameexpected) { len = f.len; CHECK(CNET_write_application((char *)&f.msg, &len)); frameexpected = 1-frameexpected; } transmit_frame(NULL, ACK, 0, f.seq); break; } }
/** * \brief Send the peer confirmation confirming the node which has been connected * This frame is sent as a unicast to peer node. All other nodes which * took part in the peer search process times out and resets peer search */ static retval_t send_peer_conf(void) { uint8_t payload_length; app_payload_t msg; peer_conf_t *data; msg.cmd_id = PEER_CONFIRM; seq_num++; msg.seq_num = seq_num; data = (peer_conf_t *)&msg.payload; /* The payload is this nodes address. The receptor of frame compares the address to the address it has issued and if it matches then declares itself as peer found */ data->nwk_addr = tal_pib.ShortAddress; payload_length = ((sizeof(app_payload_t) - sizeof(general_pkt_t)) + sizeof(peer_conf_t)); return( transmit_frame(FCF_SHORT_ADDR, (uint8_t *)(&node_info.peer_short_addr), FCF_SHORT_ADDR, seq_num, /* seq_num used as msdu handle */ (uint8_t *)&msg, payload_length, 1)); }
/** * \brief Send peer response. This is a unicast send to the node which * had earlier send the peer request * * \param src_addr The address which had been sent as payload of peer request * it becomes the source address of node which sent peer rsp * \param seq_num Sequence number of the Peer request frame */ static int send_peer_rsp(uint64_t *dst_addr) { uint8_t payload_length; app_payload_t msg; peer_rsp_t *data; /* Fill the payload */ msg.cmd_id = PEER_RESPONSE; seq_num++; msg.seq_num = seq_num; data = (peer_rsp_t *)&msg.payload; /* Issues an address for the peer. If tis node gets connected then * peer node changes its short address to this value */ data->nwk_addr = node_info.peer_short_addr; payload_length = ((sizeof(app_payload_t) - sizeof(general_pkt_t)) + sizeof(peer_rsp_t)); return(transmit_frame(FCF_LONG_ADDR, (uint8_t *)(dst_addr), FCF_SHORT_ADDR, seq_num, /* seq_num used as msdu handle **/ (uint8_t *)&msg, payload_length, 1)); }
/** * \brief Send Range Measurement mode test frames to the peer device. * * This is a unicast with source address and destination addreses which were set * during peer search process */ static int range_test_frame_tx(void) { uint8_t payload_length; app_payload_t msg; data_pkt_range_test_t *data; /* Form the payload for the test frames */ msg.cmd_id = DATA_PKT; seq_num++; msg.seq_num = seq_num; data = (data_pkt_range_test_t *)&msg.payload; data->pkt_count = num_of_frames_send; payload_length = ((sizeof(app_payload_t) - sizeof(general_pkt_t)) + sizeof(data_pkt_range_test_t)); return( transmit_frame(FCF_SHORT_ADDR, (uint8_t *)(&node_info.peer_short_addr), FCF_SHORT_ADDR, seq_num, /* seq_num used as msdu handle */ (uint8_t *)&msg, payload_length, 1)); }
static EVENT_HANDLER(application_ready) { CnetAddr destaddr; lastlength = sizeof(MSG); CHECK(CNET_read_application(&destaddr, (char *)lastmsg, &lastlength)); CNET_disable_application(ALLNODES); transmit_frame(lastmsg, DATA, lastlength, nextframetosend); nextframetosend = 1-nextframetosend; }
static void transmit_ack(int link, int seqNum) { // CREATE EMPTY ACK FRAME FRAME frame; frame.kind = DL_ACK; frame.len = 0; frame.seq = seqNum; frame.link = link; // CALL STANDARD TRANSMIT FRAME FUNCTION TO WRITE TO PHYSICAL transmit_frame(frame); }
static void timeout_link_4(CnetEvent ev, CnetTimerID timer, CnetData data) { FRAME frame; frame.link = 4; // GET FRAME THAT TIMED OUT FROM WINDOW + RESEND FRAME ON LINK 4 int seqNum = (int)data; printf("TIMEOUT:\nOUT LINK: %d\nSEQ NO: %d\n\n", frame.link, seqNum); frame = window[frame.link - 1][seqNum]; transmit_frame(frame); print_buffers(frame.link); }
static void frame_arrived(CnetEvent ev, CnetTimerID timer, CnetData data) { if(strcmp(nodeinfo.nodename,"Dehradun")==0 ){ char *ack=(char *)malloc(48*sizeof(char)); int link; int seq_check; size_t length=48; CNET_stop_timer(id); CHECK(CNET_read_physical(&link, ack, &length)); seq_check = ((int)(ack[0]))-48; if(seq_check == ((SN+1)%2)){ printf("\n Acknowledgement received "); flag_sen=1; count++; SN= count%2; } } else if(strcmp(nodeinfo.nodename,"KGP")==0 ){ char *frame=(char *)malloc(64*sizeof(char)); char *tobchecked=(char *)calloc(9,sizeof(char)); size_t length=64; int link; int i=0; printf("\n Receiving....."); CHECK(CNET_read_physical(&link, frame, &length)); for(i=1;i<9;i++){ tobchecked[i]=frame[i]; } if((strcmp(check,tobchecked))==0){ flag_rec = 1; if(RN==((int)frame[0])-48){ printf("\nSUCCESSFULLY RECEIVED %u bytes", length); RN=(RN+1)%2; flag_sen=1; } else{ printf("\n The SN mismatches !"); } transmit_frame(); //for the acknowledgement printf("\n The frame is valid"); } else { printf("\n The frame is either lost or error"); } } }
/** * @brief Starts software-controlled CSMA. * * @param trx_id Transceiver identifier */ void csma_start(trx_id_t trx_id) { /* Initialize CSMA variables */ NB[trx_id] = 0; BE[trx_id] = tal_pib[trx_id].MinBE; if (BE[trx_id] == 0) { /* Collision avoidance is disabled during first iteration */ #ifdef SUPPORT_MODE_SWITCH if (tal_pib[trx_id].ModeSwitchEnabled) { tx_ms_ppdu(trx_id); } else #endif { transmit_frame(trx_id, NO_CCA); } } else { /* Start backoff timer to trigger CCA */ start_backoff(trx_id); } }
/** * \brief Send peer search request. */ static retval_t send_peer_req(void) { app_payload_t msg; peer_req_t *data; uint8_t payload_length; uint16_t dst_addr = BROADCAST; /* Fill the payload */ msg.cmd_id = PEER_REQUEST; seq_num++; msg.seq_num = seq_num; data = (peer_req_t *)&msg.payload; /* Fill the Mode of Peer search */ switch (node_info.main_state) { case PEER_SEARCH_RANGE_TX: data->op_mode = RANGE_MEASURE_MODE; break; case PEER_SEARCH_PER_TX: data->op_mode = PER_TEST_MODE; break; /* To keep the GCC compiler happy */ case INIT: case WAIT_FOR_EVENT: case PEER_SEARCH_RANGE_RX: case PEER_SEARCH_PER_RX: case RANGE_TEST_TX_ON: case RANGE_TEST_TX_OFF: case SINGLE_NODE_TESTS: case PER_TEST_INITIATOR: case PER_TEST_RECEPTOR: case NUM_MAIN_STATES: break; default: /* Do nothing */ break; } /* Issues an address for the peer. If this node gets connected then * peer node changes its short address to this value */ data->nwk_addr = node_info.peer_short_addr; /* payload flag for config mode */ data->config_mode = node_info.configure_mode; payload_length = ((sizeof(app_payload_t) - sizeof(general_pkt_t)) + sizeof(peer_req_t)); return( transmit_frame(FCF_SHORT_ADDR, (uint8_t *)(&dst_addr),/* dst_addr is braodcast */ FCF_LONG_ADDR, /* src_addr_mode use IEEE addr */ seq_num, /* seq_num used as msdu handle */ (uint8_t *)&msg, payload_length, 0)); }
static EVENT_HANDLER(timeouts) { if(timer == lasttimer) { transmit_frame(lastmsg, DATA, lastlength, ackexpected); } }
static void ack_received(FRAME frame, int link) { FRAME tempFrame; int first, second, third, fourth; // PRINT ACKOWLEDGEMENT MESSAGE printf("\n\t\t\t\t\tACK RECEIVED\n"); printf("\t\t\t\t\tIN LINK:%d\n", link); printf("\t\t\t\t\tSEQ NO:\t%d\n", frame.seq); // ENSURE ACK NUMBER IS BETWEEN ACK EXPECTED AND NEXT FRAME TO SEND if (between(ackExpected[link - 1], frame.seq, nextFrameToSend[link - 1])) { // LOOP UNTIL ACKEXPECTED IS ONE MORE THAN THE SEQNUM OF THE ACK while (between(ackExpected[link - 1], frame.seq, nextFrameToSend[link - 1])) { // STOP THE TIMER FOR THAT FRAME TO PREVENT A TIMEOUT CNET_stop_timer(timers[link - 1][ackExpected[link - 1]]); // INCREMENT ACKEXPECTED AND DECREASE NUMBER IN WINDOW inc(&ackExpected[link - 1]); numInWindow[link - 1] -= 1; } } else { // ERRORS SHOULD ALL BE CAUGHT BEFORE THIS // STILL CHECK REGARDLESS, AS A FAILSAFE printf("\n\t\t\t\t\tERROR: OUTSIDE WINDOW BOUNDS\n"); } // ENSURE WINDOW SIZE IS VALID AND BUFFER IS NOT EMPTY while (numInWindow[link - 1] < MAX_SEQ && numInBuffer[link - 1] > 0) { // ADD FRAMES FROM THE BUFFER TO THE WINDOW printf("\t\t\t\t\tSENDING FRAME FROM BUFFER\n"); // REMOVE FRAME FROM THE FRONT OF THE BUFFER tempFrame = buffer[link - 1][bufferBounds[link - 1][0]]; inc(&bufferBounds[link - 1][0]); numInBuffer[link - 1] -= 1; // STORE THE FRAME FROM THE BUFFER IN THE WINDOW tempFrame.seq = nextFrameToSend[link - 1]; window[link - 1][nextFrameToSend[link - 1]] = tempFrame; numInWindow[link - 1] += 1; // TRANSMIT THE FRAME FROM THE BUFFER (NOW IN THE WINDOW) tempFrame.link = get_route(tempFrame.destNode); transmit_frame(tempFrame); inc(&nextFrameToSend[link - 1]); } // IF ALL LINK WINDOWS NOT FULL AND ALL BUFFER'S EMPTY // THIS KEEPS EFFICIECNY AS HIGH AS POSSIBLE first = ( numInBuffer[0] == 0 ) && ( numInWindow[0] < MAX_SEQ ); second = ( numInBuffer[1] == 0 ) && ( numInWindow[1] < MAX_SEQ ); third = ( numInBuffer[2] == 0 ) && ( numInWindow[2] < MAX_SEQ ); fourth = ( numInBuffer[3] == 0 ) && ( numInWindow[3] < MAX_SEQ ); // REENABLE APPLICATION LAYER TO GENERATE MESSAGES AGAIN if ( first && second && third && fourth ) { CHECK(CNET_enable_application(ALLNODES)); for ( int ii = 0; ii < nodeinfo.nlinks; ii++ ) CNET_set_LED(ii, "green" ); } print_buffers(link); }
static void datalink_down(FRAME frame, int inLink, int outLink) { // FRAME IS BEING FORWARDED if ( outLink != 0 ) { // MORE ROOM TO SEND SO TRANSMIT FRAME if (numInWindow[outLink - 1] < MAX_SEQ) { transmit_ack(inLink, frame.seq); inc(&frameExpected[inLink - 1]); frame.seq = nextFrameToSend[outLink - 1]; // STORE FRAME IN THE OUTGOING WINDOW window[outLink - 1][nextFrameToSend[outLink - 1]] = frame; numInWindow[outLink - 1] += 1; // TRANSMIT THE FRAME OUT frame.link = outLink; transmit_frame(frame); inc(&nextFrameToSend[outLink - 1]); } // NOT ENOUGH ROOM IN WINDOW TO SEND else { if (numInBuffer[outLink - 1] < MAX_SEQ + 1) { transmit_ack(inLink, frame.seq); inc(&frameExpected[inLink - 1]); // STORE FRAME IN THE BUFFER buffer[outLink - 1][bufferBounds[outLink - 1][1]] = frame; numInBuffer[outLink - 1] += 1; inc(&bufferBounds[outLink - 1][1]); printf("\t\t\t\t\tADDED TO BUFFER\n"); } else { // IF WINDOW AND BUFFER BOTH FULL, CAN'T DO ANYTHING. DROP printf("\t\t\t\t\tBUFFER FULL, FRAME DROPPED\n"); } } // IF THE WINDOW IS CURRENTLY FULL if (numInWindow[outLink - 1] >= MAX_SEQ) { // DISABLE GENERATION OF NEW MESSAGES WHILE WINDOW IS FULL for ( int ii = 0; ii < NUM_NODES; ii++ ) { // ONLY DISABLE MESSAGES FOR DESTINATION ROUTED THROUGH outLink if ( routingTable[nodeinfo.nodenumber][ii] == outLink ) { CNET_disable_application( ii ); printf("\t\t\t\t\tDISABLED APPLICATION\n"); CNET_set_LED( outLink-1, "red" ); } } } } else { // MORE ROOM TO SEND SO TRANSMIT FRAME if (numInWindow[inLink - 1] < MAX_SEQ) { // GET SEQUENCE NUMBER, STORE FRAME IN WINDOW, INC WINDOW NUMBER frame.seq = nextFrameToSend[inLink - 1]; window[inLink - 1][nextFrameToSend[inLink - 1]] = frame; numInWindow[inLink - 1] += 1; // CALL DLL TO TRANSMIT FRAME frame.link = inLink; transmit_frame(frame); inc(&nextFrameToSend[inLink - 1]); } // NOT ENOUGH ROOM IN WINDOW TO SEND else { // ADD FRAME TO THE BUFFER WAITING TO SEND OUT buffer[inLink - 1][bufferBounds[inLink - 1][1]] = frame; numInBuffer[inLink - 1] += 1; inc(&bufferBounds[inLink - 1][1]); // PRINT DESTINATION OF MESSAGE, LINK, INDEX IN BUFFER printf("\nADDED TO BUFFER\n"); printf("DEST:\t%s\n", nodenames[frame.destNode]); printf("LINK:\t%d\n", inLink); printf("INDEX:\t%d\n", bufferBounds[inLink - 1][1] - 1); } // IF THE WINDOW IS CURRENTLY FULL if (numInWindow[inLink - 1] >= MAX_SEQ) { // ONLY DISABLE MESSAGES FOR DESTINATION ROUTED THROUGH outLink for ( int ii = 0; ii < NUM_NODES; ii++ ) { if ( routingTable[nodeinfo.nodenumber][ii] == inLink ) { CNET_disable_application( ii ); printf("DISABLE APPLICATION FOR %s\n", nodenames[ii] ); CNET_set_LED( inLink-1 , "red" ); } } } } }
/** * link_ready() event-handler. * * It is called whenever a timeout indicating complete transmission of * a message occurs, which means the link is not busy any more. * It calls <code>transmit()</code>. */ static EVENT_HANDLER(link_ready) { transmit_frame(data); // data = link (to send over) }
static EVENT_HANDLER(resend_frame){ flag_sen=1; printf("Timer expired"); transmit_frame(); }
static EVENT_HANDLER(application_ready) { transmit_frame(); }