/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ /* * Copyright (c) 2001 University of Mannheim, Praktische Informatik IV * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Praktische Informatik IV, * University of Mannheim and ACIRI. * 4. Neither the name of the University of Mannheim nor of ACIRI * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY U. MANNHEIM AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL U. MANNHEIM OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "agent.h" #include "packet.h" #include "ip.h" #include "timer-handler.h" #include "random.h" #define SMALLFLOAT 0.0000001 /* modes of rate change */ #define INIT_RATE 0 #define SLOW_START 1 #define CONG_AVOID 2 /* cut sending rate after DEC_NO_REPORT rtts without receiver report */ #define DEC_NO_REPORT 10 #define G_FACTOR 0.1 #define MAX_ROUND_ID 1000000 // just for logging, in real world 16 is enough #define MAX_RTT_DECAY 0.9 enum {PRIO_FORCE = 4, PRIO_NO_RTT = 3, PRIO_RECV = 2, PRIO_CLR = 1}; struct hdr_tfmcc { int seqno; // data sequence number double supp_rate; // suppression rate double timestamp; // time this message was sent double timestamp_echo; // echo timestamp from last receiver report double timestamp_offset; // offset since sender received report double max_rtt; // maximum RTT of all receivers int psize; // packet size int round_id; // round id. int is_clr; // current representative receiver int rtt_recv_id; // id of receiver whose timestamp is sent back static int offset_; //offset for this header inline static int& offset() { return offset_; } inline static hdr_tfmcc* access(Packet* p) { return (hdr_tfmcc*) p->access(offset_); } }; struct hdr_tfmcc_ack { int recv_id; // ID of receiver giving feedback double timestamp; // time this report was sent double timestamp_echo; // echo timestamp from last data packet double timestamp_offset; // offset since receiver got last packet double rate; // expected sending rate (eqn) int round_id; // round id echo int have_rtt; // receiver has at least one RTT measurement int have_loss; // receiver exprienced at least one loss event int receiver_leave; // receiver will leave session static int offset_; // offset for this header inline static int& offset() { return offset_; } inline static hdr_tfmcc_ack* access(Packet* p) { return (hdr_tfmcc_ack*) p->access(offset_); } }; class TfmccAgent; class TfmccSendTimer : public TimerHandler { public: TfmccSendTimer(TfmccAgent *a) : TimerHandler() { a_ = a; } virtual void expire(Event *e); protected: TfmccAgent *a_; }; class TfmccNoFeedbackTimer : public TimerHandler { public: TfmccNoFeedbackTimer(TfmccAgent *a) : TimerHandler() { a_ = a; } virtual void expire(Event *e); protected: TfmccAgent *a_; }; class TfmccAgent : public Agent { friend TfmccSendTimer; friend TfmccNoFeedbackTimer; public: TfmccAgent(); void recv(Packet*, Handler*); void sendpkt(); void nextpkt(); int command(int argc, const char*const* argv); void start(); void stop(); void increase_rate(); void decrease_rate(); void slowstart(); void reduce_rate_on_no_feedback(); protected: TfmccSendTimer send_timer_; TfmccNoFeedbackTimer NoFeedbacktimer_; int seqno_; int psize_; // packet size of TFMCC flow int fairsize_; // packet size of competing flow double rate_; // send rate double oldrate_; // allows rate to be changed gradually double delta_; // allows rate to be changed gradually int rate_change_; // slow start, cong avoid, decrease ... double expected_rate; // TCP friendly rate based on current RTT // and recever-provded loss estimate double maxrate_; // maximum rate during slowstart (prevents // sending at more than 2 times the // rate at which the receiver is _receiving_) int printStatus_; // to print status reports int sndr_id; // only needed for status reports double inter_packet; // inter packet gap double max_rtt_; // (assumed) maximum RTT of all receivers double Initial_RTT_; // safe initial value for max RTT double t_factor_; // T = t_factor_ * max_rtt_ double round_begin_; // time when fb round started int InitRate_; // initial send rate double last_change_; // time last change in rate was made double ssmult_; // during slow start, increase rate by this // factor every rtt int bval_; // value of B for the formula double overhead_; // if > 0, dither outgoing packets TracedInt ndatapack_; // number of packets sent int active_; // have we shut down? int round_id; // round id double min_rate_; double supp_rate_; // extensions for multicast int rtt_recv_id; int rtt_prio; double rtt_recv_timestamp; double rtt_recv_last_feedback; double rtt_rate; // CLR int clr_id; double clr_timestamp; double clr_last_feedback; };