[Sumover-dev] [svn commit] r4518 - in vic/branches/cc: rtp
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Thu Oct 15 18:00:48 BST 2009
Author: soohyunc
Date: Thu Oct 15 18:00:48 2009
New Revision: 4518
Modified:
vic/branches/cc/cc/bitmap.h
vic/branches/cc/cc/tfwc_rcvr.cpp
vic/branches/cc/cc/tfwc_rcvr.h
vic/branches/cc/cc/tfwc_sndr.cpp
vic/branches/cc/cc/tfwc_sndr.h
vic/branches/cc/rtp/session.cpp
Log:
Re-written the TFWC receiver's AckVec build-up mechanisms. Previously, we have used a bit
operation in building up AckVec, but this was too error prone if it is not handled
carefully. For this version, instead, we have used C++ standard library, <vector> and
<algorithm>, to build AckVec in TFWC receiver module.
This way the TFWC receiver code became much easier to read and much
straight-forward to understand. A TFWC receiver can now handle the packet
re-ordering in a simpler and smarter way, too, by using C++ <algorithm> library.
Accordingly, rtp/session.cpp has been slightly modified.
Modified: vic/branches/cc/cc/bitmap.h
==============================================================================
--- vic/branches/cc/cc/bitmap.h (original)
+++ vic/branches/cc/cc/bitmap.h Thu Oct 15 18:00:48 2009
@@ -51,13 +51,13 @@
// bitmap tail search
#define GET_TAIL_VEC(bitmap, i) ( bitmap & (CTB << i) )
-// check bit at i-th location
+// check bit at i-th location, where (i >= 1)
#define CHECK_BIT_AT(bitmap, i) ( bitmap & (1 << (i-1)) )
-// set bit at i-th location
+// set bit at i-th location, where (i >= 1)
#define SET_BIT_AT(bitmap, i) ( bitmap |= 1 << (i-1) )
-// clear bit at i-th location
+// clear bit at i-th location, where (i >= 1)
#define CLR_BIT_AT(bitmap, i) ( bitmap &= ~(1 << (i-1)) )
#endif /* vic_cc_bitmap_h */
Modified: vic/branches/cc/cc/tfwc_rcvr.cpp
==============================================================================
--- vic/branches/cc/cc/tfwc_rcvr.cpp (original)
+++ vic/branches/cc/cc/tfwc_rcvr.cpp Thu Oct 15 18:00:48 2009
@@ -45,23 +45,21 @@
#include "tfwc_rcvr.h"
TfwcRcvr::TfwcRcvr() :
- currseq_(0),
- prevseq_(0),
ackofack_(0),
- begins_(0),
- ends_(0),
- currNumElm_(1),
- prevNumElm_(1),
- currNumVec_(1),
- prevNumVec_(1)
+ begins_(1),
+ ends_(1),
+ numElm_(1),
+ numVec_(1)
{
- // declare/initialize tfwcAV
- tfwcAV = (u_int16_t *) malloc(AVSZ * sizeof(u_int16_t));
- bzero(tfwcAV, AVSZ);
+ // tfwcAV (bit vector)
+ tfwcAV = (u_int16_t *) malloc(sizeof(u_int16_t *));
+ bzero(tfwcAV, numVec_);
}
-void TfwcRcvr::tfwc_rcvr_recv_aoa(u_int16_t type, u_int16_t *chunk, int num_chunks)
+// retrive ackofack from RTCP control channel
+void TfwcRcvr::tfwc_rcvr_recv_aoa(u_int16_t type, u_int16_t *chunk)
{
+ int num_chunks = 1;
if (type == XR_BT_1) {
// received ackofack
ackofack_ = ntohs(chunk[num_chunks-1]);
@@ -72,165 +70,99 @@
}
}
+// retrieve data packet sequence number from RTP data channel
void TfwcRcvr::tfwc_rcvr_recv_seqno(u_int16_t seqno)
{
- // variables
- int numLoss = 0; // number of packet loss count
- int diffNumElm = 0; // difference of AckVec elements (curr vs. prev)
- int diffNumVec = 0; // difference of AckVec array (curr vs. prev)
- int addiNumVec = 0; // additional AckVec array required
-
- // received data packet seqno
- currseq_ = seqno;
-
- // number of AckVec element
- currNumElm_ = currseq_ - ackofack();
- diffNumElm = currNumElm_ - prevNumElm_;
- int x = currNumElm_%BITLEN;
- int y = prevNumElm_%BITLEN;
-
- // number of chunks for building tfwcAV
- currNumVec_ = getNumVec(currNumElm_);
- diffNumVec = currNumVec_ - prevNumVec_;
-
- // for debugging purpose
- printf(" [%s +%d] seqno:%d, ackofack:%d\n",
- __FILE__,__LINE__,currseq_,ackofack());
- printf(" [%s +%d] currNumElm:%d, prevNumElm:%d\n",
- __FILE__,__LINE__,currNumElm_,prevNumElm_);
- printf(" [%s +%d] currNumVec:%d, prevNumVec:%d\n",
- __FILE__,__LINE__,currNumVec_,prevNumVec_);
-
- // there is no packet loss (or reordering)
- if (currseq_ == prevseq_ + 1) {
- // we just need the same number of AckVec elements,
- // hence just left shift by one and clear the top bit
- if (diffNumElm == 0) {
- // set next bit to 1
- SET_BIT_VEC(tfwcAV[currNumVec_-1], 1);
-
- // and clear the top bit which we don't need it anymore
- if (x != 0)
- CLR_BIT_AT(tfwcAV[currNumVec_-1], x+1);
- }
- // we just need less number of AckVec elements,
- // hence first free unnecessary AckVec chunk(s) and set bit.
- else if (diffNumElm < 0) {
- // firstly, freeing unnecessary AcvVec chunk(s)
- if (currNumVec_ < prevNumVec_) {
- for (int i = prevNumVec_; i > currNumVec_; i--) {
- for (int j = 1; j <= BITLEN; j++)
- SET_BIT_VEC(tfwcAV[i-1], 0);
- }
- }
- // set next bit to 1
- SET_BIT_VEC(tfwcAV[currNumVec_-1], 1);
- // and clear the bit(s) that we don't need it anymore
- int k = (x == 0) ? BITLEN: x;
- for (int i = BITLEN; i > k; i--)
- CLR_BIT_AT(tfwcAV[currNumVec_-1], i);
- }
- // otherwise, just set next bit to 1
- // (i.e., we need more AckVec elements)
- else
- SET_BIT_VEC(tfwcAV[currNumVec_-1], 1);
- }
- // we have one or more packet losses (or reordering)
- else {
- // number of packet loss
- numLoss = currseq_ - prevseq_ - 1;
- int z = numLoss%BITLEN;
-
- // we need more AckVec chunks (maybe one or more)
- if (currNumVec_ > prevNumVec_) {
- // currently available spaces in the previous tfwcAV array
- int numAvail = BITLEN - y;
-
- // first, fill up zeros into those available spaces
- for (int i = 0; i < numAvail; i++) {
- SET_BIT_VEC(tfwcAV[prevNumVec_-1], 0);
- numLoss--;
- }
+ // reset necessary variables before start
+ reset();
- // then, calculate "additional" AckVec chunks required
- addiNumVec = getNumVec(numLoss);
+ // required number of AckVec elements
+ numElm_ = seqno - ackofack();
- // fill up zeros accordingly if addiNumVec is greater than 1
- for (int i = 0; i < (addiNumVec - 1); i++) {
- for (int j = 0; j < BITLEN; j++) {
- SET_BIT_VEC(tfwcAV[prevNumVec_+i], 0);
- numLoss--;
- }
- }
+ // reference vector
+ for (int i = 1; i <= numElm_; i++)
+ rvec_.push_back(ackofack_ + i);
+
+ // push back the current seqno
+ avec_.push_back(seqno);
+ sort(avec_.begin(), avec_.end());
+
+ // then, trim upto ackofack (inclusive)
+ avit_ = find(avec_.begin(), avec_.end(), ackofack_);
+ if (avit_ != avec_.end())
+ avec_.erase(avec_.begin(), ++avit_);
+
+ // required number of AckVec chunks
+ numVec_ = numElm_/BITLEN + (numElm_%BITLEN > 0);
+
+ // now, build tfwcAV chunks
+ tfwc_ackvec();
+
+ // set 'start seqno' that this AckVec reports
+ begins_ = ackofack_ + 1;
+ // set 'end seqno plus one' that this AckVec report
+ ends_ = seqno + 1;
+
+ // print refvec, actual vec, and bitvec
+ //print_vec(rvec_);
+ //print_vec(avec_);
+ //print_tfwcAV();
+}
- // we need to update 'z' accordingly
- // (at this point, 'z' should be equal to 'numLoss')
- z = numLoss%BITLEN;
-
- // finally, fill up zeros at the latest AckVec chunk
- for (int i = 0; i < z; i++) {
- SET_BIT_VEC(tfwcAV[prevNumVec_+addiNumVec-1], 0);
+// build tfwcAV chunks
+void TfwcRcvr::tfwc_ackvec() {
+ int cv = 0; // vector counter
+ int cb = 0; // bit counter
+
+ // find reference vector elements from the actual sequence vector
+ for (rvit_ = rvec_.begin(); rvit_ != rvec_.end(); rvit_++) {
+ // find rvec_ elements in avec_
+ avit_ = find(avec_.begin(), avec_.end(), *rvit_);
+
+ // found
+ if (avit_ != avec_.end()) {
+ if (cb < BITLEN) {
+ tfwcAV[cv] = (tfwcAV[cv] << 1) | 1;
+ cb++;
+ }
+ else {
+ cb = 0;
+ cv++;
}
}
- // current AckVeck chunk can cope with the elements
+ // not found
else {
- // set next bit 0 into AckVec (# of packet loss)
- for (int i = 0; i < numLoss; i++)
- SET_BIT_VEC(tfwcAV[currNumVec_-1], 0);
- }
-
- // then, set this packet as received (this is important)
- SET_BIT_VEC(tfwcAV[currNumVec_-1], 1);
-
- // and clear the top two bits which we don't need
- // (because we have pushed '0' and '1' at the end of this AckVec)
- // it doesn't really matter if diffNumElm is greater than 0.
- if ( (diffNumElm <= 0) && (x != 0) ) {
- int b = abs(diffNumElm) + x + z;
- for (int i = x + 1; i <= b; i++)
- CLR_BIT_AT(tfwcAV[currNumVec_-1], i);
+ if (cb < BITLEN) {
+ tfwcAV[cv] = (tfwcAV[cv] << 1) | 0;
+ cb++;
+ }
+ else {
+ cb = 0;
+ cv++;
+ }
}
- }
+ } // end for(;;)
+}
- // print ackvec
- print_ackvec(tfwcAV);
+// print vector elements
+void TfwcRcvr::print_vec(std::vector<int> v) {
+ std::vector<int>::iterator iter;
+ printf("\t>> vec: ");
+ for (iter = v.begin(); iter != v.end(); iter++)
+ printf("%d ", *iter);
+ printf("\n");
+}
- // start seqno that this AckVec is reporting
- if (ackofack() != 0)
- begins_ = ackofack() + 1;
- else
- begins_ = 1;
-
- // end seqno is current seqno plus one (according to RFC 3611)
- ends_ = currseq_ + 1;
-
- // store seqno, num of AckVec elem, and num of AckVec array
- prevseq_ = currseq_;
- prevNumElm_ = currNumElm_;
- prevNumVec_ = currNumVec_;
-}
-
-void TfwcRcvr::print_ackvec(u_int16_t *ackv) {
- // start sequence number
- int seqno = ackofack()+1;
- int x = currNumElm_%BITLEN;
-
- // printing...
- printf("\t>> AckVec: ");
- for (int i = 0; i < currNumVec_-1; i++) {
- printf("[%d] ( ", ackv[i]);
- for (int j = 0; j < BITLEN; j++) {
- if ( CHECK_BIT_AT(ackv[i], (j+1)) )
- printf("%d ", seqno);
- seqno++;
- }
- } printf (") ");
+// print bit vectors (in decimal format)
+void TfwcRcvr::print_tfwcAV() {
+ printf("\t>> tfwcAV: ");
+ for (int i = 0; i < numVec_; i++)
+ printf("[%d:%d] ", i, tfwcAV[i]);
+ printf("\n");
+}
- int k = (x == 0) ? BITLEN: x;
- printf("[%d] ( ", ackv[currNumVec_-1]);
- for (int i = k; i > 0; i--) {
- if (CHECK_BIT_AT(ackv[currNumVec_-1], i))
- printf("%d ", seqno);
- seqno++;
- } printf(")...... %s +%d\n",__FILE__,__LINE__);
+// reset
+void TfwcRcvr::reset() {
+ bzero(tfwcAV, numVec_);
+ rvec_.clear();
}
Modified: vic/branches/cc/cc/tfwc_rcvr.h
==============================================================================
--- vic/branches/cc/cc/tfwc_rcvr.h (original)
+++ vic/branches/cc/cc/tfwc_rcvr.h Thu Oct 15 18:00:48 2009
@@ -36,16 +36,14 @@
#ifndef vic_tfwc_rcvr_h
#define vic_tfwc_rcvr_h
+#include <vector>
+#include <algorithm>
#include "tfwc_sndr.h"
-// AckVec Size (AVSZ)
-// - AckVec can manage "16 * AVSZ" outstanding packets
-#define AVSZ 256 // tfwcAV size
-
class TfwcRcvr {
public:
TfwcRcvr();
- void tfwc_rcvr_recv_aoa(u_int16_t type, u_int16_t *chunk, int num_chunks);
+ void tfwc_rcvr_recv_aoa(u_int16_t type, u_int16_t *chunk);
void tfwc_rcvr_recv_seqno(u_int16_t seqno);
protected:
@@ -59,23 +57,22 @@
// AckVec end seqno plus one
inline u_int16_t tfwc_rcvr_ends() { return ends_; }
// number of AckVec array
- inline u_int16_t tfwc_rcvr_numvec() { return currNumVec_; }
+ inline u_int16_t tfwc_rcvr_numvec() { return numVec_; }
/*
* Variables
*/
u_int16_t *tfwcAV; // AckVec array (bit vector array)
- u_int16_t currseq_; // current sequence number
- u_int16_t prevseq_; // previous sequence number
u_int16_t ackofack_; // ackofack
- u_int16_t begins_; // begin seqno that XR chunk is reporting
- u_int16_t ends_; // end seqno + 1 that XR chunk is reporting
- u_int16_t currNumElm_; // number of current AckVec elements
- u_int16_t prevNumElm_; // number of previous AckVec elements
- int currNumVec_; // numver of current AckVec array
- int prevNumVec_; // numver of previous AckVec array
-
+ u_int16_t begins_; // begin seqno that XR chunk is reporting
+ u_int16_t ends_; // end seqno + 1 that XR chunk is reporting
+ int numElm_; // number of tfwcAV elements
+ int numVec_; // number of tfwcAV chunks
private:
+ // TFWC sender's AckVec Routine
+ void tfwc_ackvec();
+ void reset();
+
// calculate the number of AckVec chunks
// (based on the number of given elements, i.e, numelm)
inline int getNumVec (int numelm) {
@@ -88,12 +85,20 @@
inline u_int16_t ackofack() { return ackofack_; }
// print built AckVec
- void print_ackvec(u_int16_t *ackv);
+ void print_tfwcAV();
+ void print_vec(std::vector<int> v);
/*
* Variables (private)
*/
u_int32_t ts_echo_; // for time stamp echoing
+
+ // actual AckVec and its iterator
+ std::vector<int> avec_;
+ std::vector<int>::iterator avit_;
+ // reference vector and its iterator
+ std::vector<int> rvec_;
+ std::vector<int>::iterator rvit_;
};
#endif
Modified: vic/branches/cc/cc/tfwc_sndr.cpp
==============================================================================
--- vic/branches/cc/cc/tfwc_sndr.cpp (original)
+++ vic/branches/cc/cc/tfwc_sndr.cpp Thu Oct 15 18:00:48 2009
@@ -64,8 +64,11 @@
{
// allocate tsvec_ in memory
tsvec_ = (double *)malloc(sizeof(double) * TSZ);
+ bzero(tsvec_, TSZ);
+
// allocate seqvec in memory
seqvec_ = (u_int32_t *)malloc(sizeof(u_int32_t) * SSZ);
+ bzero(seqvec_, SSZ);
// is TFWC running?
is_running_ = false;
@@ -139,32 +142,40 @@
* main TFWC reception path
*/
void TfwcSndr::tfwc_sndr_recv(u_int16_t type, u_int16_t begin, u_int16_t end,
- u_int16_t *chunk, int num_chunks)
+ u_int16_t *chunk)
{
- // retrieve ackvec
- if (type == XR_BT_1) {
- nakp_++; // number of ack packet received
+ // number of ack received
+ nakp_++;
- // get start/end seqno that this XR chunk reports
- begins_ = begin;
- ends_ = end;
+ // get start/end seqno that this XR chunk reports
+ begins_ = begin; // lowest packet seqno
+ ends_ = end; // highest packet seqno
+
+ // get the number of AckVec chunks
+ // use seqno space to work out the num chunks
+ // (add one to num unless exactly divisible by BITLEN
+ // - so it is large enough to accomodate all the bits
+ int num_chunks = (ends_-begins_)/BITLEN + ((ends_-begins_)%BITLEN > 0);
- // just acked seqno (head seqno of this ackvec)
+ // retrieve ackvec
+ if (type == XR_BT_1) {
+ // just acked seqno
+ // i.e.,) head seqno(= highest seqno) of this ackvec
jacked_ = ends_ - 1;
// declared AckVec
ackv_ = (u_int16_t *) malloc (sizeof(u_int16_t) * num_chunks);
+ bzero(ackv_, num_chunks);
- // clone AckVec from Vic application
- for (int i = 0; i < num_chunks; i++) {
- ackv_[i] = ntohs(chunk[i]);
- }
+ // clone AckVec from Vic
+ for (int i = 0; i < num_chunks; i++)
+ ackv_[i] = ntohs(chunk[i]);
- // XXX generate seqno vec
printf(" [%s +%d] begins:%d, ends:%d, jacked:%d\n",
__FILE__, __LINE__, begins_, ends_, jacked_);
- gen_seqvec(num_chunks, ackv_);
- free(ackv_);
+
+ // generate seqno vector
+ gen_seqvec(ackv_);
// generate margin vector
marginvec(jacked_);
@@ -199,6 +210,7 @@
update_rtt(tao_);
// initialize variables for the next pkt reception
+ free(ackv_);
init_loss_var();
}
// retrieve ts echo
@@ -221,35 +233,40 @@
* @num_chunks: number of AckVec chunks
* @ackvec: received AckVec
*/
-void TfwcSndr::gen_seqvec (u_int16_t num_chunks, u_int16_t *ackvec) {
+void TfwcSndr::gen_seqvec (u_int16_t *ackvec) {
// number of seqvec elements
- // (i.e., number of packets in AckVec)
+ // (i.e., number of packets that this AckVec is representing)
int numElm = ends_ - begins_;
+
+ // number of AckVec chunks
int x = numElm%BITLEN;
+ int num_chunks = numElm/BITLEN + (x > 0);
+ int i, j, k = 0;
// start of seqvec
- int start = jacked_;
+ //int start = jacked_;
+ int start = begins_; // lowest seqno
- int i, j, k = 0;
for (i = 0; i < num_chunks-1; i++) {
- for (j = 0; j < BITLEN; j++) {
- if ( CHECK_BIT_AT(ackvec[i], (j+1)) )
+ for (j = BITLEN; j > 0; j--) {
+ if( CHECK_BIT_AT(ackvec[i], j) )
seqvec_[k%SSZ] = start;
- else num_loss_++;
- k++; start--;
+ else num_loss_++;
+ k++; start++;
}
}
-
int a = (x == 0) ? BITLEN : x;
- for (i = 0; i < a; i++) {
- if ( CHECK_BIT_AT(ackvec[num_chunks-1], i+1 ))
+ for (i = a; i > 0; i--) {
+ if( CHECK_BIT_AT(ackvec[num_chunks-1], i) )
seqvec_[k++%SSZ] = start;
else num_loss_++;
- start--;
+ start++;
}
+ // therefore, the number of seqvec is:
+ int num_seqvec = numElm - num_loss_;
// printing retrieved sequence numbers from received AckVec
- print_seqvec(numElm - num_loss_);
+ print_seqvec(num_seqvec);
}
/*
Modified: vic/branches/cc/cc/tfwc_sndr.h
==============================================================================
--- vic/branches/cc/cc/tfwc_sndr.h (original)
+++ vic/branches/cc/cc/tfwc_sndr.h Thu Oct 15 18:00:48 2009
@@ -62,7 +62,7 @@
// main reception path (XR packet)
void tfwc_sndr_recv(u_int16_t type, u_int16_t begin, u_int16_t end,
- u_int16_t *chunk, int num_chunks);
+ u_int16_t *chunk);
// return current data packet's seqno
inline u_int16_t tfwc_sndr_get_seqno() { return seqno_; }
@@ -102,7 +102,7 @@
protected:
// generate sequence numbers
- void gen_seqvec(u_int16_t num_chunks, u_int16_t *ackvec);
+ void gen_seqvec(u_int16_t *ackvec);
// init loss related variables
inline void init_loss_var() {
Modified: vic/branches/cc/rtp/session.cpp
==============================================================================
--- vic/branches/cc/rtp/session.cpp (original)
+++ vic/branches/cc/rtp/session.cpp Thu Oct 15 18:00:48 2009
@@ -1283,41 +1283,30 @@
// i am an RTP data sender, so do the sender stuffs (AoA)
if (am_i_sender()) {
printf(">>> parse_xr - i_am_sender\n");
- // num_chunks = xrlen - sizeof(xr_BT_1_hr)[=3*32bit] +
- // 1 (counteracting -1 in hdr calc)
- //int num_chunks = (xrlen + 1 - 3) * 2;
- //printf("\tnum_chunks:%d, beg:%d, end:%d\n", num_chunks, begin, end);
-
-
- // use seqno space to work out length
- // (add one to num unless exactly divisible by 16
- // - so it is large enough to accommodate all the bits )
- int num_chunks = (end - begin)/16 + ((end - begin)%16 > 0);
-
- // this is just a double check - it should be the same as
- // the above num_chunks calculation
- printf(" [%s +%d] num_chunks:%d, beg:%d, end:%d, xr1len:%d (xrlen:%d)\n",
- __FILE__,__LINE__, num_chunks, begin, end, ntohs(xr1->xr_len), xrlen);
-
// parse XR chunks
u_int16_t *chunk = (u_int16_t *) ++xr1;
- tfwc_sndr_recv(xr->BT, begin, end, chunk, num_chunks);
+
+ printf(" [%s +%d] beg:%d, end:%d, xr1len:%d (xrlen:%d)\n",
+ __FILE__,__LINE__,begin, end, ntohs(xr1->xr_len), xrlen);
+
+ // TFWC sender
+ tfwc_sndr_recv(xr->BT, begin, end, chunk);
// we need to call Transmitter::output(pb) to make Ack driven
cc_output();
}
// i am an RTP data receiver, so receive ackofack
else {
- int num_chunks = 1;
printf(">>> parse_xr - i_am_receiver\n");
- printf(" [%s +%d] num_chunks:%d, beg:%d, end:%d\n",
- __FILE__,__LINE__,num_chunks, begin, end);
+ printf(" [%s +%d] beg:%d, end:%d\n",
+ __FILE__,__LINE__, begin, end);
// parse XR chunks
u_int16_t *chunk = (u_int16_t *) ++xr1;
printf(" [%s +%d] begin:%d, chunk[0]:%d\n",
__FILE__,__LINE__, begin, ntohs(chunk[0]));
- tfwc_rcvr_recv_aoa(xr->BT, chunk, num_chunks);
+ // TFWC receiver
+ tfwc_rcvr_recv_aoa(xr->BT, chunk);
} // end of XR block type 1
} else {
// XXX
More information about the Sumover-dev
mailing list