lms-sender.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * lms-sender.cc
  3.  * Copyright (C) 2001 by the University of Southern California
  4.  * $Id: lms-sender.cc,v 1.5 2006/02/21 15:20:19 mahrenho Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. /*
  46.  * Light-Weight Multicast Services (LMS), Reliable Multicast
  47.  *
  48.  * lms-sender.cc
  49.  *
  50.  * This implements the Sending LMS agent, "Agent/LMS/Sender".
  51.  *
  52.  * Christos Papadopoulos. 
  53.  * christos@isi.edu
  54.  */
  55. #include "agent.h"
  56. #include "tclcl.h"
  57. #include "packet.h"
  58. #include "ip.h"
  59. #include "rtp.h"
  60. #include "config.h"
  61. #include "random.h"
  62. #include "trafgen.h"
  63. #include "lms.h"
  64. static int snd_uid_ = 0;
  65. class LmsSender;
  66. class LmsSender: public Agent {
  67.  public:
  68. LmsSender();
  69. LmsSender *next_;
  70. int  command (int argc, const char*const* argv);
  71. void recv (Packet* pkt, Handler*);
  72.  protected:
  73. void handle_lms_pkt (Packet* pkt);
  74. virtual void sendmsg(int nbytes, const char *flags = 0);
  75. void send_lms_pkt (int, int);
  76. void send_dmcast (hdr_lms* lh, int seqno, int fid);
  77. int  add_req (Packet *rq);
  78. void send_spm ();
  79. void solicit_naks ();
  80. void print_stats ();
  81.         void print_all_stats (int drops);
  82.     
  83. char uname_[16]; // unique name in the form r#
  84. int spm_seqno_; // spm sequence number
  85. int lms_cost_; // for sender this is usually zero
  86. int lms_ttl_; // solicit nacks this many hops away
  87. int     packetSize_;    // remember pkt size for retransmissions
  88. int lmsPacketSize_; // packet size for lms packets
  89. Packet *req_list_; // request list to detect duplicate requests
  90. int req_list_sz_; // current size of above list
  91. // Stats
  92. int req_rcvd_; // number of requests received
  93. int dup_reqs_; // number of duplicate requests received
  94. int dmcasts_sent_; // number of dmcasts sent
  95.  static int     max_dup_naks_;  // max num of duplicate naks    
  96.     
  97. // int  maxpkts_;
  98. int  seqno_; // XXX: RTP should handle this
  99. //LmsSenderTimer lms_sender_timer_;
  100. // int off_lms_;
  101. // int off_ip_;
  102. // int  off_rtp_;
  103. // int  off_cmn_;
  104. };
  105. static class LmsSenderClass : public TclClass {
  106. public:
  107. LmsSenderClass() : TclClass("Agent/LMS/Sender") {}
  108. TclObject* create(int, const char*const*) {
  109. return (new LmsSender());
  110. }
  111. } class_lms_sender;
  112. // Obligatory definition of the class static
  113. int LmsSender::max_dup_naks_ = 0;
  114. LmsSender::LmsSender(): Agent(PT_LMS), seqno_(-1)
  115. {
  116. sprintf (uname_, "sender%d", snd_uid_++);
  117. lms_cost_ = 0;
  118. spm_seqno_ = 0;
  119. req_list_ = NULL;
  120. req_rcvd_ = dup_reqs_ = max_dup_naks_ = 0;
  121. dmcasts_sent_ = 0;
  122. bind("lmsPacketSize_", &lmsPacketSize_);
  123. bind("packetSize_", &packetSize_);
  124. // bind("off_ip_", &off_ip_);
  125. // bind("off_lms_", &off_lms_);
  126. // bind("off_rtp_", &off_rtp_);
  127. // bind("off_cmn_", &off_cmn_);
  128. // bind("maxpkts_", &maxpkts_);
  129. }
  130. //
  131. // Send a data packet
  132. //
  133. void LmsSender::sendmsg(int nbytes, const char* flags)
  134. {
  135. Packet*   p = allocpkt ();
  136. hdr_ip* ih = HDR_IP(p);
  137. hdr_cmn* th = HDR_CMN(p);
  138. hdr_rtp* rh = HDR_RTP(p); // XXX
  139. bzero (HDR_LMS(p), sizeof (struct hdr_lms));
  140. packetSize_ = nbytes;
  141. th->size_ = packetSize_;   
  142. rh->seqno() = ++seqno_; // XXX
  143. ih->flowid() = 1; //for coloring in NAM
  144. #ifdef LMS_DEBUG
  145. packet_t t = th->ptype();
  146. const char* nname = packet_info.name(t);
  147. double now = Scheduler::instance().clock();
  148. printf("SNDR: at %f %s sendmsg pkt %d type is %s, size is %dnn",
  149.   now, uname_, seqno_, nname, th->size_);
  150. #endif
  151. target_->recv(p);
  152. }
  153. //
  154. // Send an LMS packet
  155. // set LMS header and adjust size_
  156. //
  157. void LmsSender::send_lms_pkt (int type, int cost)
  158. {
  159. Packet* p = allocpkt();
  160. (HDR_CMN(p))->ptype_ = PT_LMS;
  161. (HDR_IP(p))->flowid() = 7; //Coloring in NAM
  162. if (type != LMS_SETUP)
  163. (HDR_CMN(p))->size_ = lmsPacketSize_; 
  164. //(HDR_CMN(p))->size_ = sizeof(hdr_lms); 
  165. else 
  166. (HDR_CMN(p))->size_ = packetSize_; 
  167. //(HDR_CMN(p))->size_ = sizeof(hdr_lms); 
  168. hdr_lms* lh = HDR_LMS(p);
  169. lh->type_ = type;
  170. lh->cost_ = cost;
  171. lh->from_ = addr();
  172. // lh->from_ = port();
  173. lh->src_ = addr();
  174. lh->group_ = daddr();
  175. lh->tp_addr_  = LMS_NOADDR;
  176. lh->tp_port_ = -1;
  177. lh->tp_iface_ = LMS_NOIFACE;
  178. lh->lo_ = lh->hi_ = -1;
  179. lh->ts_ = Scheduler::instance().clock();
  180. #ifdef LMS_DEBUG
  181. printf ("SNDR: %s send_lms_pkt from %d src %d dst %x type %d cost %d size %d at %fnn",
  182.   uname_, lh->from_, lh->src_, lh->group_, lh->type_, lh->cost_,
  183.   (HDR_CMN(p))->size_, lh->ts_);
  184. #endif 
  185. target_->recv(p);
  186. }
  187. //
  188. // Receive a packet
  189. //
  190. void LmsSender::recv(Packet* pkt, Handler*)
  191. {
  192. hdr_cmn* h = HDR_CMN(pkt);
  193. if (h->ptype_ == PT_LMS)
  194. handle_lms_pkt (pkt);
  195. else {
  196. printf ("ERROR: %s received non LMS pkt type %dn", uname_, h->ptype_);
  197. Packet::free(pkt);
  198. }
  199. }
  200. /*
  201.  * Handle LMS packets
  202.  */
  203. void LmsSender::handle_lms_pkt (Packet* pkt)
  204. {
  205. int st = 0;
  206. hdr_lms* lh = HDR_LMS(pkt);
  207. //hdr_ip* iph = HDR_IP(pkt);
  208. #ifdef LMS_DEBUG
  209. int a1, a2;
  210. #endif
  211. switch (lh->type())
  212. {
  213. case LMS_REQ:
  214. req_rcvd_++;
  215. if (lh->src_ != addr())
  216. {
  217. printf ("ERROR: %s REQ with wrong source addr %d:%dn",
  218. uname_, lh->src_>>8, lh->src_&0xff);
  219. abort ();
  220. }
  221. #ifdef LMS_DEBUG
  222. a1 = lh->from(); a2 = lh->src();
  223. printf ("SNDR: %s got LMS_REQ from %d:%d src %d:%d group 0x%xnn",
  224.   uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group());
  225. printf ("SNDR: TP: (%d, %d)nn", lh->tp_addr_, lh->tp_iface_);
  226. #endif
  227. if ((st = add_req (pkt)) != 0)
  228. for (int i = lh->lo_; i <= lh->hi_; i++)
  229. send_dmcast (lh, i, 3);
  230. else dup_reqs_++;
  231. break;
  232. case LMS_REFRESH:
  233. break;
  234. default:
  235. printf ("***ERROR: %s Unexpected LMS packet type: %dnn", uname_, lh->type());
  236. abort ();
  237. }
  238. if (!st)
  239. Packet::free(pkt);
  240. }
  241. int LmsSender::command(int argc, const char*const* argv)
  242. {
  243.     if (argc == 2) {
  244.         if (strcmp(argv[1], "lms-setup") == 0) {
  245.             send_lms_pkt (LMS_SETUP, packetSize_); // XXX
  246.             return (TCL_OK);
  247.         }
  248.         if (strcmp(argv[1], "gather-links") == 0) {
  249.             send_lms_pkt (LMS_LINKS, 0);
  250.             return (TCL_OK);
  251.         }
  252.         if (strcmp(argv[1], "print-stats") == 0) {
  253.             print_stats ();
  254.             return (TCL_OK);
  255.         }
  256.     }
  257.     if (argc == 3)
  258.     {
  259.         if (strcmp(argv[1], "solicit-naks") == 0) {
  260.             lms_ttl_ = atoi (argv[2]);
  261.             solicit_naks ();
  262.             return (TCL_OK);
  263.         }
  264.         if (strcmp(argv[1], "set-replier-cost") == 0)
  265.         {
  266.             lms_cost_  = atoi (argv[2]);
  267.             send_lms_pkt (LMS_REFRESH, lms_cost_);
  268.             return (TCL_OK);
  269.         }
  270.         if (strcmp(argv[1], "print-all-stats") == 0) {
  271.             print_all_stats ( atoi(argv[2]) );
  272.             return (TCL_OK);
  273.         }         
  274.         if (strcmp(argv[1], "send") == 0) {
  275.             sendmsg( atoi (argv[2]), 0);
  276.             return (TCL_OK);
  277.         }
  278.     }
  279.     return (Agent::command(argc, argv));
  280. }
  281. /*
  282.  * Send a LMS_DMCAST in response to LMS_REQ packet
  283.  */
  284. void LmsSender::send_dmcast (hdr_lms* lh, int seqno, int fid)
  285. {
  286. Packet *p = allocpkt();
  287. hdr_rtp *rh = HDR_RTP(p);
  288. hdr_ip *piph = HDR_IP(p);
  289. hdr_cmn *ch = HDR_CMN(p);
  290. hdr_lms *plh = HDR_LMS(p);
  291. dmcasts_sent_++;
  292. rh->seqno() = seqno;
  293. piph->daddr() = lh->tp_addr_;
  294. piph->dport() = lh->tp_port_;
  295. ch->size_= packetSize_;
  296. piph->flowid() = fid; // Green for repair; to color packets in NAM
  297. plh->type_ = LMS_DMCAST;
  298. plh->from_ = addr();
  299. // plh->from_ = port();
  300. plh->src_ = addr();
  301. plh->group_ = daddr();
  302. plh->tp_addr_ = lh->tp_addr_;
  303. plh->tp_port_ = lh->tp_port_;
  304. plh->tp_iface_ = lh->tp_iface_;
  305.         //const char* nname = packet_info.name(t);
  306. target_->recv(p);
  307. }
  308. // Add a new request to the request list.
  309. // Return 1 if the request was added,
  310. // 0 if this was a duplicate request and was not added.
  311. // Requests are added to the head of the list
  312. // and the list size is limited to 10 (XXX: should have time limit instead)
  313. //
  314. int LmsSender::add_req (Packet *rq)
  315. {
  316. hdr_lms *lh = HDR_LMS(rq);
  317.         Packet  *p = req_list_;
  318.         int     i = 0;
  319.         if (!p)
  320.         {
  321.             req_list_ = rq;
  322.             rq->next_ = 0;
  323.             req_list_sz_ = 1;
  324.             return 1;
  325.         }
  326.         while (p)
  327.         {
  328.             if (i++ > 10)
  329.                 break;
  330.             hdr_lms *plh = HDR_LMS(p);
  331.             if ((plh->lo_ == lh->lo_) &&
  332.                 (plh->hi_ == lh->hi_) &&
  333.                 (plh->tp_addr_ == lh->tp_addr_) &&
  334.                 (plh->tp_iface_ == lh->tp_iface_))
  335.             {
  336.                 struct lms_nak *nh = (struct lms_nak *)p->accessdata();
  337.                 // increments the dup_cnt_ for this NAK, and updates
  338.                 // max_dup_naks_ if appropriate
  339.                 ++nh->dup_cnt_;
  340. #ifdef LMS_DEBUG
  341.    printf ("SNDR: %s got %d dup reqs, max is %dn", uname_, nh->dup_cnt_, max_dup_naks_);
  342. #endif                
  343.                 
  344.                 if( nh->dup_cnt_ > max_dup_naks_)
  345.                     max_dup_naks_ = nh->dup_cnt_;
  346.                                 
  347.                 return 0;                
  348.             }
  349.             
  350.             p = p->next_;
  351.         }
  352.         if (i > 10 && p && p->next_)
  353.         {
  354.             Packet::free (p->next_);
  355.             p->next_ = 0;
  356.             req_list_sz_--;
  357.         }
  358.         rq->next_ = req_list_;
  359.         req_list_ = rq;
  360.         req_list_sz_++;
  361.         return 1;
  362. }
  363. void LmsSender::send_spm ()
  364. {
  365.         Packet* p = allocpkt (sizeof (struct lms_spm));
  366.         (HDR_CMN(p))->ptype_ = PT_LMS;
  367. (HDR_CMN(p))->size_ = sizeof(struct lms_spm) + sizeof(hdr_lms);
  368.         (HDR_IP(p))->flowid() = 7;
  369.         hdr_lms* lh = HDR_LMS(p);
  370.         
  371.         lh->type_ = LMS_SPM;
  372.         struct lms_spm *spm = (struct lms_spm *)p->accessdata();
  373.         spm->spm_seqno_ = spm_seqno_++;
  374.         spm->spm_path_ = addr();
  375.         spm->spm_ts_ = Scheduler::instance().clock();
  376.         target_->recv(p);
  377. }
  378. void LmsSender::solicit_naks ()
  379. {
  380. Packet* p = allocpkt(sizeof (struct lms_ctl));
  381. struct lms_ctl  *ctl = (struct lms_ctl*)p->accessdata ();
  382. (HDR_CMN(p))->size_ = sizeof(struct lms_ctl) + sizeof(hdr_lms); 
  383. (HDR_CMN(p))->ptype_ = PT_LMS;
  384.     (HDR_IP(p))->flowid() = 7;
  385. hdr_lms* lh = HDR_LMS(p);
  386. lh->type_ = LMS_SRC_REFRESH;
  387. lh->ttl_  = lms_ttl_;
  388. lh->from_ = addr();
  389. lh->src_  = addr();
  390. lh->group_ = daddr();
  391. ctl->cost_ = lms_cost_;
  392. ctl->hop_cnt_ = 0;
  393. target_->recv(p);
  394. }
  395. void LmsSender::print_stats ()
  396. {
  397.         printf ("%s:n", uname_);
  398.         printf ("tPackets sent:tt%dn", seqno_);
  399.         printf ("tRequests received:t%dn", req_rcvd_);
  400.         printf ("tDuplicate Requests:t%dn", dup_reqs_);
  401.         printf ("tDMCASTs sent:tt%dn", dmcasts_sent_);
  402.         printf ("n");
  403. }
  404. void LmsSender::print_all_stats (int drops)
  405. {
  406.     if (drops) 
  407.         printf ("t%.5ft  %d", float(dup_reqs_)/float(drops), max_dup_naks_);
  408.     else 
  409.         printf ("t0.0t  0");
  410. }