lms-sender.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * lms-sender.cc
00004  * Copyright (C) 2001 by the University of Southern California
00005  * $Id: lms-sender.cc,v 1.4 2005/08/25 18:58:07 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 /*
00048  * Light-Weight Multicast Services (LMS), Reliable Multicast
00049  *
00050  * lms-sender.cc
00051  *
00052  * This implements the Sending LMS agent, "Agent/LMS/Sender".
00053  *
00054  * Christos Papadopoulos. 
00055  * christos@isi.edu
00056  */
00057 
00058 #include "agent.h"
00059 #include "tclcl.h"
00060 #include "packet.h"
00061 #include "ip.h"
00062 #include "rtp.h"
00063 #include "config.h"
00064 #include "random.h"
00065 #include "trafgen.h"
00066 #include "lms.h"
00067 
00068 static int snd_uid_ = 0;
00069 
00070 class LmsSender;
00071 
00072 class LmsSender: public Agent {
00073  public:
00074     LmsSender();
00075     LmsSender *next_;
00076     int  command (int argc, const char*const* argv);
00077     void recv (Packet* pkt, Handler*);
00078 
00079  protected:
00080     void handle_lms_pkt (Packet* pkt);
00081     virtual void sendmsg(int nbytes, const char *flags = 0);
00082     void send_lms_pkt (int, int);
00083     void send_dmcast (hdr_lms* lh, int seqno, int fid);
00084     int  add_req (Packet *rq);
00085     void send_spm ();
00086     void solicit_naks ();
00087     void print_stats ();
00088         void print_all_stats (int drops);
00089     
00090     char    uname_[16]; // unique name in the form r#
00091     int spm_seqno_; // spm sequence number
00092     int lms_cost_;  // for sender this is usually zero
00093     int lms_ttl_;   // solicit nacks this many hops away
00094     int     packetSize_;    // remember pkt size for retransmissions
00095     int lmsPacketSize_; // packet size for lms packets
00096     Packet  *req_list_; // request list to detect duplicate requests
00097     int req_list_sz_;   // current size of above list
00098 
00099     // Stats
00100     int req_rcvd_;  // number of requests received
00101     int dup_reqs_;  // number of duplicate requests received
00102     int dmcasts_sent_;  // number of dmcasts sent
00103 
00104  static int     max_dup_naks_;  // max num of duplicate naks    
00105     
00106     // int  maxpkts_;
00107     int     seqno_;     // XXX: RTP should handle this
00108 
00109     //LmsSenderTimer lms_sender_timer_;
00110     
00111     // int  off_lms_;
00112     // int  off_ip_;
00113     // int  off_rtp_;
00114     // int  off_cmn_;
00115 };
00116 
00117 static class LmsSenderClass : public TclClass {
00118 public:
00119     LmsSenderClass() : TclClass("Agent/LMS/Sender") {}
00120     TclObject* create(int, const char*const*) {
00121         return (new LmsSender());
00122     }
00123 } class_lms_sender;
00124 
00125 
00126 // Obligatory definition of the class static
00127 int LmsSender::max_dup_naks_ = 0;
00128 
00129 LmsSender::LmsSender(): Agent(PT_LMS), seqno_(-1)
00130 {
00131     sprintf (uname_, "sender%d", snd_uid_++);
00132     
00133     lms_cost_ = 0;
00134     spm_seqno_ = 0;
00135     req_list_ = NULL;
00136     req_rcvd_ = dup_reqs_ = max_dup_naks_ = 0;
00137     dmcasts_sent_ = 0;
00138     bind("lmsPacketSize_", &lmsPacketSize_);
00139     bind("packetSize_", &packetSize_);
00140     // bind("off_ip_", &off_ip_);
00141     // bind("off_lms_", &off_lms_);
00142     // bind("off_rtp_", &off_rtp_);
00143     // bind("off_cmn_", &off_cmn_);
00144     // bind("maxpkts_", &maxpkts_);
00145 }
00146 
00147 //
00148 // Send a data packet
00149 //
00150 void LmsSender::sendmsg(int nbytes, const char* flags)
00151 {
00152     Packet*   p = allocpkt ();
00153     hdr_ip* ih = HDR_IP(p);
00154     hdr_cmn* th = HDR_CMN(p);
00155     hdr_rtp* rh = HDR_RTP(p); // XXX
00156 
00157     bzero (HDR_LMS(p), sizeof (struct hdr_lms));
00158     packetSize_ = nbytes;   
00159     th->size_ = packetSize_;   
00160     rh->seqno() = ++seqno_; // XXX
00161 
00162     ih->flowid() = 1; //for coloring in NAM
00163 
00164 #ifdef LMS_DEBUG
00165 packet_t t = th->ptype();
00166 const char* nname = packet_info.name(t);
00167 double now = Scheduler::instance().clock();
00168 printf("SNDR: at %f %s sendmsg pkt %d type is %s, size is %d\n\n",
00169   now, uname_, seqno_, nname, th->size_);
00170 #endif
00171 
00172     target_->recv(p);
00173 }
00174 
00175 //
00176 // Send an LMS packet
00177 // set LMS header and adjust size_
00178 //
00179 void LmsSender::send_lms_pkt (int type, int cost)
00180 {
00181     Packet* p = allocpkt();
00182 
00183     (HDR_CMN(p))->ptype_ = PT_LMS;
00184     (HDR_IP(p))->flowid() = 7; //Coloring in NAM
00185 
00186     if (type != LMS_SETUP)
00187         (HDR_CMN(p))->size_ = lmsPacketSize_; 
00188         //(HDR_CMN(p))->size_ = sizeof(hdr_lms); 
00189     else 
00190         (HDR_CMN(p))->size_ = packetSize_; 
00191         //(HDR_CMN(p))->size_ = sizeof(hdr_lms); 
00192 
00193     hdr_lms* lh = HDR_LMS(p);
00194     lh->type_ = type;
00195     lh->cost_ = cost;
00196     lh->from_ = addr();
00197 //  lh->from_ = port();
00198     lh->src_ = addr();
00199     lh->group_ = daddr();
00200     lh->tp_addr_  = LMS_NOADDR;
00201     lh->tp_port_ = -1;
00202     lh->tp_iface_ = LMS_NOIFACE;
00203     lh->lo_ = lh->hi_ = -1;
00204     lh->ts_ = Scheduler::instance().clock();
00205 
00206 #ifdef LMS_DEBUG
00207 printf ("SNDR: %s send_lms_pkt from %d src %d dst %x type %d cost %d size %d at %f\n\n",
00208   uname_, lh->from_, lh->src_, lh->group_, lh->type_, lh->cost_,
00209   (HDR_CMN(p))->size_, lh->ts_);
00210 #endif 
00211     target_->recv(p);
00212 }
00213 
00214 //
00215 // Receive a packet
00216 //
00217 void LmsSender::recv(Packet* pkt, Handler*)
00218 {
00219     hdr_cmn* h = HDR_CMN(pkt);
00220 
00221     if (h->ptype_ == PT_LMS)
00222         handle_lms_pkt (pkt);
00223     else    {
00224         printf ("ERROR: %s received non LMS pkt type %d\n", uname_, h->ptype_);
00225         Packet::free(pkt);
00226         }
00227 }
00228 
00229 /*
00230  * Handle LMS packets
00231  */
00232 void LmsSender::handle_lms_pkt (Packet* pkt)
00233 {
00234     int st = 0;
00235 
00236     hdr_lms* lh = HDR_LMS(pkt);
00237     //hdr_ip* iph = HDR_IP(pkt);
00238 #ifdef LMS_DEBUG
00239 int a1, a2;
00240 #endif
00241     switch (lh->type())
00242         {
00243         case LMS_REQ:
00244             req_rcvd_++;
00245             if (lh->src_ != addr())
00246                 {
00247                 printf ("ERROR: %s REQ with wrong source addr %d:%d\n",
00248                     uname_, lh->src_>>8, lh->src_&0xff);
00249                 abort ();
00250                 }
00251 #ifdef LMS_DEBUG
00252 a1 = lh->from(); a2 = lh->src();
00253 printf ("SNDR: %s got LMS_REQ from %d:%d src %d:%d group 0x%x\n\n",
00254   uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group());
00255 printf ("SNDR: TP: (%d, %d)\n\n", lh->tp_addr_, lh->tp_iface_);
00256 #endif
00257             if ((st = add_req (pkt)) != 0)
00258                 for (int i = lh->lo_; i <= lh->hi_; i++)
00259                     send_dmcast (lh, i, 3);
00260             else dup_reqs_++;
00261 
00262             break;
00263         case LMS_REFRESH:
00264             break;
00265         default:
00266             printf ("***ERROR: %s Unexpected LMS packet type: %d\n\n", uname_, lh->type());
00267             abort ();
00268         }
00269     if (!st)
00270         Packet::free(pkt);
00271 }
00272 
00273 int LmsSender::command(int argc, const char*const* argv)
00274 {
00275     if (argc == 2) {
00276         if (strcmp(argv[1], "lms-setup") == 0) {
00277             send_lms_pkt (LMS_SETUP, packetSize_);  // XXX
00278             return (TCL_OK);
00279         }
00280         if (strcmp(argv[1], "gather-links") == 0) {
00281             send_lms_pkt (LMS_LINKS, 0);
00282             return (TCL_OK);
00283         }
00284         if (strcmp(argv[1], "print-stats") == 0) {
00285             print_stats ();
00286             return (TCL_OK);
00287         }
00288     }
00289     if (argc == 3)
00290     {
00291         if (strcmp(argv[1], "solicit-naks") == 0) {
00292             lms_ttl_ = atoi (argv[2]);
00293             solicit_naks ();
00294             return (TCL_OK);
00295         }
00296         if (strcmp(argv[1], "set-replier-cost") == 0)
00297         {
00298             lms_cost_  = atoi (argv[2]);
00299             send_lms_pkt (LMS_REFRESH, lms_cost_);
00300             return (TCL_OK);
00301         }
00302         if (strcmp(argv[1], "print-all-stats") == 0) {
00303             print_all_stats ( atoi(argv[2]) );
00304             return (TCL_OK);
00305         }         
00306         if (strcmp(argv[1], "send") == 0) {
00307             sendmsg( atoi (argv[2]), 0);
00308             return (TCL_OK);
00309         }
00310     }
00311     return (Agent::command(argc, argv));
00312 }
00313 
00314 /*
00315  * Send a LMS_DMCAST in response to LMS_REQ packet
00316  */
00317 void LmsSender::send_dmcast (hdr_lms* lh, int seqno, int fid)
00318 {
00319     Packet      *p = allocpkt();
00320     hdr_rtp     *rh = HDR_RTP(p);
00321     hdr_ip      *piph = HDR_IP(p);
00322     hdr_cmn     *ch = HDR_CMN(p);
00323     hdr_lms     *plh = HDR_LMS(p);
00324 
00325     dmcasts_sent_++;
00326     rh->seqno() = seqno;
00327     piph->daddr() = lh->tp_addr_;
00328     piph->dport() = lh->tp_port_;
00329     ch->size_= packetSize_;
00330     piph->flowid() = fid;       // Green for repair; to color packets in NAM
00331 
00332     plh->type_ = LMS_DMCAST;
00333     plh->from_ = addr();
00334 //  plh->from_ = port();
00335     plh->src_ = addr();
00336     plh->group_ = daddr();
00337     plh->tp_addr_ = lh->tp_addr_;
00338     plh->tp_port_ = lh->tp_port_;
00339     plh->tp_iface_ = lh->tp_iface_;
00340         //const char* nname = packet_info.name(t);
00341     
00342     target_->recv(p);
00343 }
00344 
00345 // Add a new request to the request list.
00346 // Return 1 if the request was added,
00347 // 0 if this was a duplicate request and was not added.
00348 // Requests are added to the head of the list
00349 // and the list size is limited to 10 (XXX: should have time limit instead)
00350 //
00351 int LmsSender::add_req (Packet *rq)
00352 {
00353     hdr_lms *lh = HDR_LMS(rq);
00354         Packet  *p = req_list_;
00355         int     i = 0;
00356 
00357         if (!p)
00358         {
00359             req_list_ = rq;
00360             rq->next_ = 0;
00361             req_list_sz_ = 1;
00362             return 1;
00363         }
00364         while (p)
00365         {
00366             if (i++ > 10)
00367                 break;
00368             hdr_lms *plh = HDR_LMS(p);
00369             if ((plh->lo_ == lh->lo_) &&
00370                 (plh->hi_ == lh->hi_) &&
00371                 (plh->tp_addr_ == lh->tp_addr_) &&
00372                 (plh->tp_iface_ == lh->tp_iface_))
00373             {
00374                 struct lms_nak *nh = (struct lms_nak *)p->accessdata();
00375                 // increments the dup_cnt_ for this NAK, and updates
00376                 // max_dup_naks_ if appropriate
00377                 ++nh->dup_cnt_;
00378 
00379 #ifdef LMS_DEBUG
00380    printf ("SNDR: %s got %d dup reqs, max is %d\n", uname_, nh->dup_cnt_, max_dup_naks_);
00381 #endif                
00382                 
00383                 if( nh->dup_cnt_ > max_dup_naks_)
00384                     max_dup_naks_ = nh->dup_cnt_;
00385                                 
00386                 return 0;                
00387             }
00388             
00389             p = p->next_;
00390         }
00391         if (i > 10 && p && p->next_)
00392         {
00393             Packet::free (p->next_);
00394             p->next_ = 0;
00395             req_list_sz_--;
00396         }
00397         rq->next_ = req_list_;
00398         req_list_ = rq;
00399         req_list_sz_++;
00400         return 1;
00401 }
00402 
00403 
00404 void LmsSender::send_spm ()
00405 {
00406         Packet* p = allocpkt (sizeof (struct lms_spm));
00407         (HDR_CMN(p))->ptype_ = PT_LMS;
00408         (HDR_CMN(p))->size_ = sizeof(struct lms_spm) + sizeof(hdr_lms);
00409         (HDR_IP(p))->flowid() = 7;
00410 
00411         hdr_lms* lh = HDR_LMS(p);
00412         
00413         lh->type_ = LMS_SPM;
00414 
00415         struct lms_spm *spm = (struct lms_spm *)p->accessdata();
00416         spm->spm_seqno_ = spm_seqno_++;
00417         spm->spm_path_ = addr();
00418         spm->spm_ts_ = Scheduler::instance().clock();
00419 
00420         target_->recv(p);
00421 }
00422 
00423 void LmsSender::solicit_naks ()
00424 {
00425     Packet* p = allocpkt(sizeof (struct lms_ctl));
00426     struct lms_ctl  *ctl = (struct lms_ctl*)p->accessdata ();
00427     (HDR_CMN(p))->size_ = sizeof(struct lms_ctl) + sizeof(hdr_lms); 
00428     (HDR_CMN(p))->ptype_ = PT_LMS;
00429     (HDR_IP(p))->flowid() = 7;
00430 
00431     hdr_lms* lh = HDR_LMS(p);
00432     lh->type_ = LMS_SRC_REFRESH;
00433     lh->ttl_  = lms_ttl_;
00434     lh->from_ = addr();
00435     lh->src_  = addr();
00436     lh->group_ = daddr();
00437 
00438     ctl->cost_ = lms_cost_;
00439     ctl->hop_cnt_ = 0;
00440 
00441     target_->recv(p);
00442 }
00443 
00444 void LmsSender::print_stats ()
00445 {
00446         printf ("%s:\n", uname_);
00447         printf ("\tPackets sent:\t\t%d\n", seqno_);
00448         printf ("\tRequests received:\t%d\n", req_rcvd_);
00449         printf ("\tDuplicate Requests:\t%d\n", dup_reqs_);
00450         printf ("\tDMCASTs sent:\t\t%d\n", dmcasts_sent_);
00451         printf ("\n");
00452 }
00453 
00454 void LmsSender::print_all_stats (int drops)
00455 {
00456     if (drops) 
00457         printf ("\t%.5lf\t  %d", float(dup_reqs_)/float(drops), max_dup_naks_);
00458     else 
00459         printf ("\t0.0\t  0");
00460 }

Generated on Tue Mar 6 16:47:46 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6