Skip to content

Commit

Permalink
Include ARQ scheme #10 (#37)
Browse files Browse the repository at this point in the history
* ARQ mode: change message definitions of dldata and uldata to contain
an Acknowledgement mode flag.

* add Unit Tests for some MAC messages

* fix linting

* ARQ: add constructor and parser for ACK messages

* ARQ: implement transmission window when sending fragments

* ARQ: include ACK transmissions

* ARQ: adapt reassembler to work with AM und UM mode

* ARQ: include handlers for ACK messages

* add Unit Tests for some MAC messages

* Bugfixes for ARQ:

- include packet inspection for UEs
- copy messages after adding them to the sender window. Otherwise
  messages get lost in window
- handle case in which there is data to send, but no fragment can be
  generated since the sender window is full

* ARQ: fix crash in mac fragmenter object

* ARQ: fix TCP/IP packet detection + add some logs

ethertype byte order was wrong
more log outputs to identify which ARQ scheme is currently used

* ARQ: bugfixes for fragmenter and reassembler

fragmenter_has_fragment returned true in some cases
were no fragment could be sent anymore

reassembler had a memory issue when reassembling a frame

* Mac messages: increase max sequence number for better flow with ARQ

we use 4 bits instead of 3 for seqNr

* ARQ: faster ACK transmission from Client to BS

BS will automatically assign UL slots when it transmits a frame that has
to be acked

* Fix mac uldata_ack and dldata_ack messages to 4Bit seqNr size

* Client scheduler: check if a fragment is available before calling get_fragment

* Adjust log levels for some PHY functions

* ARQ: clean up code

- include a maximum number of retransmits for the ARQ scheme
- check whether a fragment is available inside get_fragment
- Some doxygen documentation
- Verbose assignment of MacMessage types enum

* ARQ: refactor mac_frag_get_fragment for better readability

* ARQ: Bugfixes for mac_frag_get_fragment

* Add unit tests for packet inspection

* Fix linting

Co-authored-by: chris007de <[email protected]>
  • Loading branch information
lukasostendorf and chris007de authored Oct 11, 2020
1 parent df6a536 commit 7049f88
Show file tree
Hide file tree
Showing 14 changed files with 889 additions and 119 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ set(UTIL src/util/log.h src/util/log.c src/util/ringbuf.h src/util/ringbuf.c)

# Unit Tests
set(UNITY tests/unity/src/unity.c)
set(TESTS tests/test_mac_messages.c)
set(TESTS tests/test.c)

### Add different executables

Expand Down
45 changes: 33 additions & 12 deletions src/mac/mac_bs.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@

#include "mac_bs.h"
#include "../util/log.h"
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <unistd.h>

#ifdef MAC_TEST_DELAY
#include "../runtime/test.h"
#endif

user_s *ue_create(uint userid) {
user_s *ue_create(uint userid, long long unsigned int *subframe_ptr) {
// create user instance and association response
user_s *new_ue = calloc(sizeof(user_s), 1);
new_ue->msg_control_queue = ringbuf_create(MAC_CTRL_MSG_BUF_SIZE);
new_ue->fragmenter = mac_frag_init();
new_ue->fragmenter = mac_frag_init(subframe_ptr);
new_ue->reassembler = mac_assmbl_init();
new_ue->userid = userid;
new_ue->ul_queue = 0;
Expand Down Expand Up @@ -63,7 +65,7 @@ MacBS mac_bs_init() {
macinst->UE[i] = NULL;
}
macinst->broadcast_ctrl_queue = ringbuf_create(MAC_CTRL_MSG_BUF_SIZE);
macinst->broadcast_data_fragmenter = mac_frag_init();
macinst->broadcast_data_fragmenter = mac_frag_init(&macinst->subframe_cnt);

#ifdef MAC_ENABLE_TAP_DEV
macinst->tapdevice = tap_init("tap0");
Expand Down Expand Up @@ -137,7 +139,7 @@ void mac_bs_add_new_ue(MacBS mac, uint8_t rachuserid, uint8_t rach_try_cnt,
ringbuf_put(mac->broadcast_ctrl_queue, response);
} else {
// create new UE struct
mac->UE[userid] = ue_create(userid);
mac->UE[userid] = ue_create(userid, &mac->subframe_cnt);
mac->UE[userid]->fs = fs;
mac->UE[userid]->last_seen = mac->subframe_cnt;
mac->UE[userid]->timingadvance = timing_diff;
Expand Down Expand Up @@ -199,6 +201,8 @@ int mac_bs_add_txdata(MacBS mac, uint8_t destUserID, MacDataFrame frame) {
MacFrag fragmenter = NULL;
if (destUserID == USER_BROADCAST) {
fragmenter = mac->broadcast_data_fragmenter;
// force frames that are forwarded using broadcast frag to disable ARQ
frame->do_arq = 0;
} else if (mac->UE[destUserID] != NULL) {
fragmenter = mac->UE[destUserID]->fragmenter;
} else {
Expand Down Expand Up @@ -284,7 +288,15 @@ int mac_bs_handle_message(MacBS mac, MacMessage msg, uint8_t userID) {
INFO, "[MAC BS] mcs_change_request from user %d mcs: %d is_ul %d\n",
userID, msg->hdr.MCSChangeReq.mcs, msg->hdr.MCSChangeReq.ul_flag)
break;
case dl_data_ack:
mac_frag_ack_fragment(user->fragmenter, msg);
break;
case ul_data:
if (msg->hdr.ULdata.do_ack) {
MacMessage ack = mac_msg_create_ul_data_ack(ACK, msg->hdr.ULdata.seqNr,
msg->hdr.ULdata.fragNr);
ringbuf_put(user->msg_control_queue, ack);
}
frame = mac_assmbl_reassemble(user->reassembler, msg);
if (frame != NULL) {
user->stats.bytes_rx += frame->size;
Expand Down Expand Up @@ -379,11 +391,16 @@ void mac_bs_map_slot(MacBS mac, uint subframe, uint slot, user_s *ue) {
uint tbs = get_tbs_size(mac->phy->common, ue->dl_mcs);
LogicalChannel chan = lchan_create(tbs / 8, CRC16);
lchan_add_all_msgs(chan, ue->msg_control_queue);
if (mac_frag_has_fragment(ue->fragmenter)) {
uint payload_size = lchan_unused_bytes(chan);
MacMessage msg = mac_frag_get_fragment(ue->fragmenter, payload_size, 0);
uint payload_size = lchan_unused_bytes(chan);
MacMessage msg = mac_frag_get_fragment(ue->fragmenter, payload_size, 0);
if (msg != NULL) {
lchan_add_message(chan, msg);
ue->stats.bytes_tx += msg->payload_len;
if (msg->hdr.DLdata.do_ack) {
// if the user is expected to send an ack for this frame, indicate a
// pending transmission to the scheduler
ue->ul_queue++;
}
mac_msg_destroy(msg);
}
lchan_calc_crc(chan);
Expand Down Expand Up @@ -558,10 +575,10 @@ void mac_bs_run_scheduler(MacBS mac) {
uint tbs = get_tbs_size(mac->phy->common, 0);
LogicalChannel chan = lchan_create(tbs / 8, CRC16);
lchan_add_all_msgs(chan, mac->broadcast_ctrl_queue);
if (mac_frag_has_fragment(mac->broadcast_data_fragmenter)) {
uint payload_size = lchan_unused_bytes(chan);
MacMessage msg = mac_frag_get_fragment(mac->broadcast_data_fragmenter,
payload_size, 0);
uint payload_size = lchan_unused_bytes(chan);
MacMessage msg =
mac_frag_get_fragment(mac->broadcast_data_fragmenter, payload_size, 0);
if (msg != NULL) {
lchan_add_message(chan, msg);
mac_msg_destroy(msg);
}
Expand Down Expand Up @@ -691,7 +708,11 @@ void *mac_bs_tap_rx_th(void *arg) {
if (mac->tapdevice->bytes_rec > 0) {
MacDataFrame frame = dataframe_create(dev->bytes_rec);
memcpy(frame->data, dev->buffer, dev->bytes_rec);

if (packet_inspect_is_tcpip(frame->data, frame->size)) {
frame->do_arq = 1;
} else {
frame->do_arq = 0;
}
// find correct userid to forward EtherFrame to
// if no entry is found, broadcast channel is used
struct entry *np = NULL;
Expand Down
27 changes: 27 additions & 0 deletions src/mac/mac_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@
#include "mac_channels.h"
#include "mac_messages.h"

#include <net/ethernet.h>
#include <netinet/ip.h>

MacDataFrame dataframe_create(uint size) {
MacDataFrame frame = malloc(sizeof(MacDataFrame_s));
frame->data = malloc(size);
frame->size = size;
frame->do_arq = 0; // do not use ARQ mode by default
return frame;
}

Expand Down Expand Up @@ -86,3 +90,26 @@ int mac_stats_print(char *buf, int buflen, MACstat_s *stats) {
up_days, up_hours, up_min, up_secs, stats->chan_rx_succ,
stats->chan_rx_fail, stats->bytes_rx, stats->bytes_tx);
}

int packet_inspect_is_tcpip(uint8_t *buf, uint buflen) {
// Packet inspection: determine if this is TCP traffic
// then activate ARQ

if (buf == NULL)
return -1; // no buffer

if (buflen < 34)
return -1; // buffersize is shorter than Ethernet+IP header size

uint16_t ether_type = (buf[12] << 8) + buf[13];
struct iphdr *ip4hdr = (struct iphdr *)&buf[14];
LOG(DEBUG, "[MAC] Packet inspect: ethertype %04x, proto %d\n", ether_type,
ip4hdr->protocol);
if (ether_type == ETHERTYPE_IP) {
// is IPv4 packet, check if TCP
if (ip4hdr->protocol == 6) {
return 1; // This is a IPv4 header with TCP content
}
}
return 0; // this frame does not contain TCP/IP
}
13 changes: 13 additions & 0 deletions src/mac/mac_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
typedef struct {
uint size;
uint8_t *data;
uint do_arq;
} MacDataFrame_s;

// Store some MAC layer statistics
Expand All @@ -67,4 +68,16 @@ void lchan_add_all_msgs(LogicalChannel lchan, ringbuf ctrl_msg_buf);
void mac_stats_init(MACstat_s *stats);
int mac_stats_print(char *buf, int buflen, MACstat_s *stats);

/**
* Check whether an Ethernet frame contains a IPv4+TCP datagram
*
* This function inspects an Ethernet frame given as a uint8_t buffer
*
* @param buf Pointer to the start of the Ethernet frame
* @param buflen the length of the buffer
* @returns 1 if it is a TCP/IP datagram, -1 if no inspection is possible
* 0 in all other cases
*/
int packet_inspect_is_tcpip(uint8_t *buf, uint buflen);

#endif /* MAC_MAC_COMMON_H_ */
Loading

0 comments on commit 7049f88

Please sign in to comment.