[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fragmentation/reassembly functions at link layer



I'm forwarding Nguyen's modifications as an FYI to the original
authors and ns-users, since it's text.

Archive of the latest original code I could find is at:
http://www.ee.surrey.ac.uk/Personal/L.Wood/ns/sar_dist_oct2298.tar.gz
since it's not currently available at ftp://cc-lab.u-aizu.ac.jp/pub/

(Nguyen - that is later than what I previously found and sent you,
 mostly with some minimal trace additions. You might want to stick
 some comments in your code identifying your modifications, too...)

Comments, anyone?

cheers,

L.

<[email protected]>PGP<http://www.ee.surrey.ac.uk/Personal/L.Wood/>

---------- Forwarded message ----------
Date: Tue, 29 Jun 1999 13:08:56 +0100
From: Nguyen Huu Thanh <[email protected]>
To: Lloyd Wood <[email protected]>
Subject: Re: fragmentation/reassembly functions  at link layer

Dear Lloyd,

Thank you very much for the code you shiped me. I find it very useful
and decided to use this model. However, I think that this code has some
following disadvantages:

- All header informations of original packets except hdr_cmn, hdr_ip and
hdr_rtp are lost due to the fact that the Agent/Pass and Agent/Sar must
allocate new packets each time they receive an original packet.

- Such performance as end-to-end delay cannot be traced, also due to the
above-mentioned matter.

- Agent/Pass can only classify CBR traffic.

I have modified the code to overcome these problems. At the segmentation
node, I send the original packet at the end of the cell period and
simply change the packet size and packet type. These informations are
restored at the reassembly node. The packet is then directed to the sink
by modifying its destination address in the ip header. I attache here
the modified code. Let me know if you have any comment (you can make a
test by running the original example.tcl).

Best regards,

Nguyen Huu Thanh

Lloyd Wood wrote:
 
> I thought fragmentation and reassembly was a done thing in third-party
> code - although this does it via an agent rather than at link level.
> Let me know if the attached code is of any use.
> 
> ns2.1b2, segmentation and reassembly at link layer - may need to email
> Behcet Sarikaya
>       ([email protected]) or Yukio Hashimoto ([email protected])
> previously available from ftp://cc-lab.u-aizu.ac.jp/pub/
> 
> And then there's the ATM work you'll find mentioned on:
> http://www.ee.surrey.ac.uk/Personal/L.Wood/ns/
> for ns 1 though.

-- 
------------------------------------------------
    Nguyen Huu Thanh                      

    Universitaet der Bundeswehr Muenchen  
    Institut fuer informationstechnische Systeme
    Werner-Heisenberg-Weg 39
    85577 Neubiberg                        
    Tel.: +49 89 6004-2279                   
    Email: [email protected]  
-------------------------------------------------
/*
 * File: pass.cc
 *  date: July, 1998
 * Author: Yukio Hashimoto
   Thanks to Marc Greis ([email protected])
 *
 */

#include "agent.h"
#include "tclcl.h"
#include "packet.h"
#include "ip.h"
#include "sar.h"
#include "rtp.h"

#include <iostream.h>
 
class PassAgent : public Agent {
 public:
  PassAgent();
  int command(int argc, const char*const* argv);
  void recv(Packet*, Handler*);
protected:
  int off_sar_;
  NsObject* dst;
  int off_rtp_;

};
 



static class PassClass : public TclClass {
public:
  PassClass() : TclClass("Agent/Pass") {}
  TclObject* create(int, const char*const*) {
    return (new PassAgent());
  }
} class_pass;


PassAgent::PassAgent() : Agent(PT_PASS)
{
  bind("off_sar_", &off_sar_); // important to access sar packets
  bind("off_rtp_", &off_rtp_);
}


int PassAgent::command(int argc, const char*const* argv)
{
  if (argc == 3) {
    if (strcmp(argv[1], "dst") == 0) {
      Agent* a = (Agent*)TclObject::lookup(argv[2]);
      dst=a;

      // command has been processed */
      return (TCL_OK);
    }
  }
  // If the command hasn't been processed by PassAgent()::command,
  // call the command() function for the base class
  return (Agent::command(argc, argv));
}


void PassAgent::recv(Packet* pkt, Handler*)
{
  // Access the IP header for the received packet:
  hdr_cmn* hdrcmn = (hdr_cmn*)pkt->access(off_cmn_);
  
  if(hdrcmn->ptype() != PT_SAR){  // to lower layer
    dst->recv(pkt,(Handler*)0);
  }  else {                       // from lower layer

    // Access the Pass header for the received packet:
    hdr_sar* hdra = (hdr_sar*)pkt->access(off_sar_);
 
    hdr_cmn* header_common_ = (hdr_cmn*)pkt->access(off_cmn_);
    header_common_->ptype() = hdra->packet_type_; // return the original type

    //Packet* p = allocpkt();  
    //hdr_cmn* hdrcmn2 = (hdr_cmn*)p->access(off_cmn_);
    
    //hdrcmn2->size()=hdra->pkt_size;
    //hdrcmn2->ptype() = hdra->packet_type_;

    hdr_ip* hdrip = (hdr_ip*)pkt->access(off_ip_);
    //*hdrip= hdra->IP;
    //hdrip->src() = addr_;
    hdrip->dst() = dst_;  // modification of the ip destination
    //hdrip->ttl() = defttl_;

    //hdr_rtp* rh = (hdr_rtp*)p->access(off_rtp_);
    //hdr_rtp* rh_from = (hdr_rtp*)pkt->access(off_rtp_);
    //*rh = *rh_from;  // copy rtp info

    

    send(pkt,0);
    
     

    //Packet::free(pkt);  
  }

}


/*
 * File: Code for a 'Sar' Agent Class
 * date: July, 1998
 * Author: Yukio Hashimoto
 * Thanks to Marc Greis ([email protected])
 *
 */

#include <stdio.h>
#include <math.h>
#include "sar.h"
#include "rtp.h"
#include "tcp.h"
#include <iostream.h>

static class SarClass : public TclClass {
public:
  SarClass() : TclClass("Agent/Sar") {}
  TclObject* create(int, const char*const*) {
    return (new SarAgent());
  }
} class_sar;


SarAgent::SarAgent() : Agent(PT_SAR), sar_timer_(this), finish_seg(1)
 {
   bind("packetSize_", &size_);
   bind("off_sar_", &off_sar_); 
   bind("off_rtp_", &off_rtp_);
   bind("off_tcp_", &off_tcp_);
   finish_seg=1;

 }


 int SarAgent::command(int argc, const char*const* argv)
 {
   if (argc == 3) {
	if (strcmp(argv[1], "dst") == 0) {
       Agent* a = (Agent*)TclObject::lookup(argv[2]);
       dst=a;
       /*
       // Create a new packet
       Packet* pkt = allocpkt();
       // Access the Sar header for the new packet:
       hdr_sar* hdr = (hdr_sar*)pkt->access(off_sar_);
       // Set the 'ret' field to 0, so the receiving node knows
       // that it has to generate an echo packet
       hdr->ret = 0;
       // Store the current time in the 'send_time' field
       hdr->send_time = Scheduler::instance().clock();
       // Send the packet
       send(pkt, 0);
       // return TCL_OK, so the calling function knows that the
       // command has been processed
       */
       return (TCL_OK);
     }
   }
   // If the command hasn't been processed by SarAgent()::command,
   // call the command() function for the base class
   return (Agent::command(argc, argv));
 }


 void SarAgent::recv(Packet* pkt, Handler*)
 {
   // Access the IP header for the received packet:
   hdr_cmn* hdrcmn = (hdr_cmn*)pkt->access(off_cmn_);
   hdr_ip* hdrip = (hdr_ip*)pkt->access(off_ip_);
   hdr_rtp* rh_from = (hdr_rtp*)pkt->access(off_rtp_);



   if(hdrcmn->ptype() == PT_SAR){// to upper layer 
   // reassembly

     // Access the Sar header for the received packet:
     hdr_sar* hdr = (hdr_sar*)pkt->access(off_sar_);

     if(hdr->total_cell_num == hdr->cell_num) {
       //Packet* p = allocpkt();
       //hdr_sar* hdr3 = (hdr_sar*)p->access(off_sar_);
       //hdr_cmn* header_common_ = (hdr_cmn*)p->access(off_cmn_);
       //header_common_->size() = hdr->pkt_size; // restore the original size

       hdrcmn->size() = hdr->pkt_size;  // restore the original size

       //hdr3->pkt_size=hdr->pkt_size;
       //hdr3->packet_type_ = hdr->packet_type_;

       // kokowa test
       //hdr_rtp* rh = (hdr_rtp*)p->access(off_rtp_);
       //*rh= *rh_from;

       //dst->recv(p,(Handler*)0);       

       dst->recv(pkt,(Handler*)0);

     }else {
       //cout << "discard";
       Packet::free(pkt);

     }


     //Packet::free(pkt);

   } else { // from upper layer  
     // segmentation

     sar_timer_.resched(0.2);
     
     while (finish_seg == 0) {
       cout << "wait "<< endl ;
     } // do nothing

    int psize=hdrcmn->size(); // read packet size
    packet_t org_ptype_=hdrcmn->ptype();
    int cell_num =(int)ceil((double)psize/58.0);  // required num of 58 byte S cells (total 64 bytes)


    for(int i=0; i< cell_num-1; i++) {    
      Packet* c = allocpkt();

      
      hdr_sar* hdr_sar1 = (hdr_sar*)c->access(off_sar_);

      hdr_sar1->total_cell_num=cell_num;
      hdr_sar1->cell_num=i+1;

      //cout << i << "th iteration" << endl;
      send(c,0);
      
      
    }


    // last cell

    //Packet* c=allocpkt();

    hdr_sar* hdr2 = (hdr_sar*)pkt->access(off_sar_);
    hdr2->total_cell_num=cell_num;
    hdr2->cell_num=cell_num;
    hdr2->IP = *hdrip;


    //hdr_sar* hdr2 = (hdr_sar*)c->access(off_sar_);
    //hdr2->total_cell_num=cell_num;
    //hdr2->cell_num=cell_num;
    //hdr2->IP = *hdrip;

    // save the original size and type in sar header
    hdr2->pkt_size=psize; 
    hdr2->packet_type_=org_ptype_;


    //hdr2->pkt_size=psize; // put IP size info
    //hdr2->packet_type_=org_ptype_; // save the original packet type 
    //hdr_rtp* rh = (hdr_rtp*)c->access(off_rtp_);
    //*rh = *rh_from;  // copy rtp info

    // modify the packet size and type
    hdrcmn->ptype() = type_;
    hdrcmn->size() = size_;

    // modify the ip destination
    hdrip->dst() = dst_;

    //send(c,0);
    
    send(pkt,0);
    
    //Packet::free(pkt);
  }

}


void Sar_Timer::expire(Event *e) {
  a_->timeout(0);
}


void SarAgent::timeout(int)
{
  finish_seg=1;
}

	
/*
 * File: sar.h
 * date: July 1998
 * Author: Yukio Hashimoto
   Thanks to Marc Greis ([email protected])
 *
 */


#ifndef ns_sar_h
#define ns_sar_h

#include "agent.h"
#include "tclcl.h"
#include "packet.h"
#include "ip.h"


class SarAgent;

class Sar_Timer : public TimerHandler {
public:
	Sar_Timer(SarAgent *a) : TimerHandler() { a_ = a; }
	virtual void expire(Event *e);
protected:
	SarAgent *a_;

	
};



struct hdr_sar {
  char ret;
  double send_time;
  int total_cell_num;
  int cell_num;
  int pkt_num; 
  int pkt_size;
  struct hdr_ip IP;
  int seqno_;
  packet_t packet_type_;
  int& seqno() {
		return (seqno_);
	}
};


class SarAgent : public Agent {
 public:
  SarAgent();
  int command(int argc, const char*const* argv);
  void recv(Packet*, Handler*);
  void timeout(int);
 protected:
  Sar_Timer sar_timer_;
  int off_sar_;
  NsObject* dst;
  int off_rtp_;
  int off_tcp_;
  int finish_seg;
};



static class SarHeaderClass : public PacketHeaderClass {
public:
  SarHeaderClass() : PacketHeaderClass("PacketHeader/Sar", 
					sizeof(hdr_sar)) {}
} class_sarhdr;


#endif