normStreamer example feature additions, code cleanup

pull/18/head
Brian Adamson 2020-06-14 11:21:19 -04:00
parent ad31a1a32a
commit 0ff199fc3c
3 changed files with 63 additions and 45 deletions

View File

@ -122,6 +122,7 @@ class NormStreamer
{
assert(NORM_SESSION_INVALID != norm_session);
NormAddAckingNode(norm_session, ackId);
acking_node_count++;
norm_acking = true; // invoke ack-based flow control
}
void SetAutoAck(bool enable)
@ -293,7 +294,7 @@ class NormStreamer
private:
NormSessionHandle norm_session;
bool is_multicast;
bool probe_tos;
UINT8 probe_tos;
bool loopback;
bool is_running;
@ -316,6 +317,7 @@ class NormStreamer
bool tx_watermark_pending;
bool norm_acking;
bool auto_ack;
unsigned int acking_node_count;
bool tx_ack_pending;
NormFlushMode flush_mode; // TBD - allow for "none", "passive", "active" options
bool fti_info;
@ -367,8 +369,8 @@ NormStreamer::NormStreamer()
input_socket(ProtoSocket::UDP), input_file(stdin), input_fd(fileno(stdin)), input_ready(true),
input_needed(false), input_msg_length(0), input_index(0),
tx_stream (NORM_OBJECT_INVALID), tx_ready(true),
tx_stream_buffer_max(0), tx_stream_buffer_count(0), tx_stream_bytes_remain(0),
tx_watermark_pending(false), norm_acking(false), auto_ack(false), tx_ack_pending(false), flush_mode(NORM_FLUSH_ACTIVE),
tx_stream_buffer_max(0), tx_stream_buffer_count(0), tx_stream_bytes_remain(0), tx_watermark_pending(false),
norm_acking(false), auto_ack(false), acking_node_count(0), tx_ack_pending(false), flush_mode(NORM_FLUSH_ACTIVE),
fti_info(false), ack_ex(false), rx_stream(NORM_OBJECT_INVALID), rx_ready(false), rx_needed(false), msg_sync(false),
output_bucket_rate(0.0), output_bucket_interval(0.0), output_bucket_depth(0), output_bucket_count(0),
output_socket(ProtoSocket::UDP), output_file(stdout), output_fd(fileno(stdout)), output_ready(true),
@ -645,6 +647,13 @@ bool NormStreamer::Start(bool sender, bool receiver)
NormSetFlowControl(norm_session, 0.0);
NormTrackingStatus trackingMode = auto_ack? NORM_TRACK_RECEIVERS : NORM_TRACK_NONE;
NormSetAutoAckingNodes(norm_session, trackingMode);
if (auto_ack && (0 == acking_node_count))
{
// This allows for the receivrer(s) to start after the sender
// as the sender will persistently send ack requests until
// a receiver responds.
NormAddAckingNode(norm_session, NORM_NODE_NONE);
}
}
// Pick a random instance id for now
struct timeval currentTime;
@ -1160,12 +1169,23 @@ void NormStreamer::HandleNormEvent(const NormEvent& event)
//fprintf(stderr, "new GRTT = %lf\n", NormGetGrttEstimate(norm_session));
break;
case NORM_ACKING_NODE_NEW:
if (0 == acking_node_count)
NormRemoveAckingNode(event.session, NORM_NODE_NONE);
acking_node_count++;
break;
case NORM_TX_WATERMARK_COMPLETED:
TRACE("NORM_TX_WATERMARK_COMPLETED ...\n");
if (NORM_ACK_SUCCESS == NormGetAckingStatus(norm_session))
{
//fprintf(stderr, "WATERMARK COMPLETED\n");
if (tx_watermark_pending)
if (0 == acking_node_count)
{
// Keep probing until some receiver shows up
NormResetWatermark(norm_session);
}
else if (tx_watermark_pending)
{
// Flow control ack request was pending.
tx_watermark_pending = false;
@ -1473,7 +1493,7 @@ int main(int argc, char* argv[])
return -1;
}
i++;
normStreamer.SetProbeTOS(tos);
normStreamer.SetProbeTOS((UINT8)tos);
}
else if (0 == strncmp(cmd, "info", len))
{

View File

@ -762,7 +762,7 @@ void NormSenderNode::HandleCommand(const struct timeval& currentTime,
backoffTime = 0.25 * r * maxBackoff + 0.75 * backoffTime;
cc_timer.SetInterval(backoffTime);
PLOG(PL_TRACE, "NormSenderNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
PLOG(PL_DEBUG, "NormSenderNode::HandleCommand() node>%lu begin CC back-off: %lf sec)...\n",
(unsigned long)LocalNodeId(), backoffTime);
session.ActivateTimer(cc_timer);
break;
@ -2393,6 +2393,8 @@ bool NormSenderNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
(unsigned long)LocalNodeId(), 8.0e-03*NormUnquantizeRate(ext.GetCCRate()),
rtt_estimate, ccLoss, (UINT16)nominal_packet_size, slow_start);
ext.SetCCSequence(cc_sequence);
if (0 == session.GetProbeTOS()) // always send NormAck(CC) for special TOS case
{
// Cancel potential pending NORM_ACK(CC) since we are NACKing
if (cc_timer.IsActive())
{
@ -2401,6 +2403,7 @@ bool NormSenderNode::OnRepairTimeout(ProtoTimer& /*theTimer*/)
cc_timer.Reschedule();
cc_timer.DecrementRepeatCount();
}
}
} // end if (cc_enable)
// Iterate through rx pending object list,
@ -2990,6 +2993,8 @@ bool NormSenderNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
{
// Build and send NORM_ACK(CC)
if (ack_pending && !ack_ex_pending && (1 == cc_timer.GetRepeatCount()))
{
if (0 == session.GetProbeTOS()) // always send NormAck(CC) in special TOS case
{
// Send ACK flush right away (CC feedback is included)
if (ack_timer.IsActive()) ack_timer.Deactivate();
@ -2997,6 +3002,7 @@ bool NormSenderNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
OnAckTimeout(ack_timer);
return false;
}
}
switch (cc_timer.GetRepeatCount())
{
case 0:
@ -3005,7 +3011,7 @@ bool NormSenderNode::OnCCTimeout(ProtoTimer& /*theTimer*/)
case 1:
{
// We weren't suppressed, so build an ACK(RTT) and send
// We weren't suppressed, so build an ACK(CC) and send
NormAckMsg* ack = (NormAckMsg*)session.GetMessageFromPool();
if (!ack)
{
@ -3105,6 +3111,8 @@ bool NormSenderNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
if (session.SendMessage(*ack))
{
ack_pending = false;
if (0 == session.GetProbeTOS()) // Always send NormAck(CC) for special TOS case
{
cc_feedback_needed = false;
if (cc_enable && !is_clr && !is_plr && session.Address().IsMulticast())
{
@ -3121,6 +3129,7 @@ bool NormSenderNode::OnAckTimeout(ProtoTimer& /*theTimer*/)
cc_timer.Deactivate();
}
}
}
else
{
// TBD - should we queue the message so it can get a send retry?
@ -3726,8 +3735,6 @@ bool NormLossEstimator2::Update(const struct timeval& currentTime,
event_time = event_time_orig = currentTime;
newLossEvent = true;
//TRACE("time>%lf new loss event fraction = %lf\n", ProtoTime(currentTime).GetValue(), LossFraction());
}
}
else

View File

@ -426,8 +426,6 @@ bool NormSession::OpenProtoCap()
PLOG(PL_WARN, "NormSession::OpenProtoCap() warning: unable to get interface source address\n");
}
TRACE("got source address: %s\n", src_addr.GetHostString());
if (dst_addr_list.IsEmpty())
{
PLOG(PL_FATAL, "NormSession::OpenProtoCap() error: unable to add any addresses to dst_addr_list!!\n");
@ -2059,7 +2057,7 @@ bool NormSession::QueueTxObject(NormObject *obj)
NormObject *oldest = tx_table.Find(tx_table.RangeLo());
if (oldest->IsRepairPending() || oldest->IsPending())
{
PLOG(PL_ALWAYS, "NormSession::QueueTxObject() all held objects repair pending:%d (repair active:%d) pending:%d\n",
PLOG(PL_DEBUG, "NormSession::QueueTxObject() all held objects repair pending:%d (repair active:%d) pending:%d\n",
oldest->IsRepairPending(), repair_timer.IsActive(), oldest->IsPending());
posted_tx_queue_empty = false;
return false;
@ -2075,7 +2073,7 @@ bool NormSession::QueueTxObject(NormObject *obj)
}
else
{
PLOG(PL_ALWAYS, "NormSession::QueueTxObject() asserting flow control for object delay:%lf sec\n", delay);
PLOG(PL_DEBUG, "NormSession::QueueTxObject() asserting flow control for object delay:%lf sec\n", delay);
// TBD - flow control as should allow for TX_QUEUE_VACANCY posting for session
ActivateFlowControl(delay, oldest->GetId(), NormController::TX_QUEUE_EMPTY);
posted_tx_queue_empty = false;
@ -2390,7 +2388,6 @@ void NormSession::RxSocketRecvHandler(ProtoSocket &theSocket,
bool ecnStatus = false;
#ifdef SIMULATE
ecnStatus = theSocket.GetEcnStatus();
//if (ecnStatus) TRACE("NORM RECEIVED PACKET W/ ECN BIT SET!!!!!\n");
#endif // SIMULATE
bool wasUnicast;
if (destAddr.IsValid())
@ -3042,7 +3039,6 @@ void NormSession::ReceiverHandleObjectMessage(const struct timeval &currentTime,
Notify(NormController::REMOTE_SENDER_ADDRESS, theSender, NULL);
}
theSender->UpdateRecvRate(currentTime, msg.GetLength());
//if (ecnStatus) TRACE("UPDATING LOSS EST w/ ECN pkt\n");
theSender->UpdateLossEstimate(currentTime, msg.GetSequence(), ecnStatus);
theSender->IncrementRecvTotal(msg.GetLength()); // for statistics only (TBD) #ifdef NORM_DEBUG
theSender->HandleObjectMessage(msg);
@ -4830,14 +4826,12 @@ bool NormSession::OnTxTimeout(ProtoTimer & /*theTimer*/)
message_queue.Prepend(msg);
if (tx_timer.IsActive())
tx_timer.Deactivate();
//TRACE("starting output notification ...\n");
tx_socket->StartOutputNotification();
return false; // since timer was deactivated
case MSG_SEND_FAILED:
// Message was not sent due to socket error (no route, etc), so so just timeout and try again
// (TBD - is there something smarter we should do)
//TRACE("MSG_SEND_FAILED\n");
if (!advertise_repairs)
message_queue.Prepend(msg);
if (tx_rate > 0.0)
@ -4874,7 +4868,6 @@ bool NormSession::OnTxTimeout(ProtoTimer & /*theTimer*/)
NormSession::MessageStatus NormSession::SendMessage(NormMsg &msg)
{
//TRACE("sending message length %hu\n", msg.GetLength());
bool isReceiverMsg = false;
bool isProbe = false;
bool sendRaw = false;
@ -4967,13 +4960,13 @@ NormSession::MessageStatus NormSession::SendMessage(NormMsg &msg)
struct timeval currentTime;
ProtoSystemTime(currentTime);
theSender->CalculateGrttResponse(currentTime, grttResponse);
ack.SetGrttResponse(grttResponse);
if (0 != probe_tos) sendRaw = true;
}
else
{
grttResponse.tv_sec = grttResponse.tv_usec = 0;
}
ack.SetGrttResponse(grttResponse);
break;
}
default:
@ -5118,7 +5111,6 @@ bool NormSession::RawSendTo(const char* buffer, unsigned int& numBytes, const Pr
trafficClass &= ~((UINT8)ProtoSocket::ECN_ECT1); // clear ECT1 bit
}
//TRACE("sending RAW with tos 0x%02x (probe_tos 0x%02x\n", trafficClass, probe_tos);
switch (dstAddr.GetType())
{
case ProtoAddress::IPv4:
@ -5570,7 +5562,6 @@ void NormSession::AdjustRate(bool onResponse)
{
// reduce rate if no active data transmission
// (TBD) Perhaps we want to be less aggressive here someday
//TRACE("DATA INACTIVITY!\n");
txRate *= 0.5;
}
else if (clr && clr->IsActive())