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

[ns] Solution to Broadcast to all neighbors



This took me much longer than expected, but here is a
solution that I'm happy with.

The problem is for an agent to broadcast a packet to all its
peer agents on neighboring nodes.  A few people sent
suggestions from the mailing list, but none of them worked
out.  Many others contacted me and said they needed a
solution also, so I thought I'd pass my solution on and
recommend that something similar be incorporated into NS.

Before outlining the solution I used, I should point out
that I developed this specifically for Mobile Ad Hoc
networking, and have only tested it there.  I'm pretty sure
it will work with non-mobile nodes as well though.  Please
reference Figure 15.1 on page 118 of NS Notes and
Documentation also.

The problem was that if I sent a packet to the IP_BROADCAST
address with a known destination port, none of the
neighboring agents would get it.  The packet would be
forwarded to the routing agent on the neighboring nodes, and
then dropped because the routing agents are "down stream"
from the port demux.  I finally figured out that when the
address demux gets a packet and it doesn't recognize the
address as it's own, it just gives it to the default target,
which is the routing agent on a mobile node.  The
IP_BROADCAST address is currently -1, and this cannot be the
IP address of any node in the network as they are all
positive, so the address demux will never pass the packet to
the port demux to be handed off to the correct agent.

My solution approach modifies the link layer, so that if a
packet is addressed to the broadcast address and is going
"up" the stack, I change the address to the current node and
pass it to the address demux.  This has the result of
forwarding it to the port demux, and it arrives at the
correct agent.

One caution is in order:  It may be necessary to duplicate
the packet and still let the one addressed to the
IP_BROADCAST address continue through so it can be
re-broadcast by the routing agent, and then re-address the
copy.

As a result, this simple change to the file ll.cc will allow
the address demux to pass on the packet:

//******************************************************************
// I've included the entire LL::recv function so you'll
// know where to make the changes

void LL::recv(Packet* p, Handler* /*h*/)
{
	hdr_cmn *ch = HDR_CMN(p);
	//char *mh = (char*) HDR_MAC(p);
	//struct hdr_sr *hsr = HDR_SR(p);

	/*
	 * Sanity Check
	 */
	assert(initialized());

	if(p->incoming) {
                p->incoming = 0;
	}

	// If direction = UP, then pass it up the stack
	// Otherwise, set direction to DOWN and pass it down the
stack
	if(ch->direction() == hdr_cmn::UP) {
		//if(mac_->hdr_type(mh) == ETHERTYPE_ARP)
		if(ch->ptype_ == PT_ARP)
                {
			arptable_->arpinput(p, this);
		} else {
//*****************************************************************************
// this is put in order to make IP_BROADCAST packet
// be handled by the port demux, and not automatically go to
the
// default target
// It may be necessary to make a duplicate packet and send
them both up, so
// the routing agent gets a copy also in case it needs to be
re-broadcast

hdr_ip *iphdr = HDR_IP(p);
if (iphdr->daddr() == IP_BROADCAST)
{
  //fprintf(stderr, "\nResetting daddr and next_hop to
%d\n", mac_->addr());
  iphdr->daddr() = mac_->addr();
  ch->next_hop() = mac_->addr();
}

//*****************************************************************************
			uptarget_ ? sendUp(p) : drop(p);
                }
		return;
	}

	ch->direction() = hdr_cmn::DOWN;
	sendDown(p);
}

//******************************************************************

That's it.  In order to send the broadcast packet just do
this...

      // Create a new packet
      Packet* pkt = allocpkt();

      // Access the common header for the new packet:
      hdr_cmn* cmnhdr = (hdr_cmn*)pkt->access(off_cmn_);

      // Access the IP header for the new packet:
      hdr_ip* iphdr = (hdr_ip*)pkt->access(off_ip_);

      // set all the necessary things for the common header
      cmnhdr->next_hop_ = IP_BROADCAST;  // broadcast

      // now the ip header stuff
      iphdr->saddr() = myAddress;
      iphdr->sport() = myPort;
      iphdr->daddr() = IP_BROADCAST;
      iphdr->dport() = desiredDestinationPort;
      // I do this just to be sure that it isn't forwarded 
      // beyond the neighbors
      iphdr->ttl() = 1;

      // this is taken from dsragent::sendOutBCastPkt
      Scheduler::instance().schedule(ll, pkt, 0.0);

      // return TCL_OK, so the calling function knows that
the
      // command has been processed
      return (TCL_OK);

The only trick here is that you need a reference to the link
layer.
The variable above, ll, is declared in my header as

      NsObject *ll

and I set it through the tcl script with a set-ll command
like this:

  set g [new Agent/myAgent]
  $node attach $g <portNumber>

  # need to tell the agent about their link layers
  set ll [$node set ll_(0)]
  $ns at 0.0 "$g set-ll $ll"


The C++ is put in the command function and is:

    if (strcmp(argv[1], "set-ll") == 0)
    {
      if( (obj = TclObject::lookup(argv[2])) == 0)
      {
        fprintf(stderr, "GeocastAgent(set-ll): %s lookup of
%s failed\n", 
                        argv[1], argv[2]);
        return (TCL_ERROR);
      }
      ll = (NsObject*) obj;
      return (TCL_OK);

Email me if you try this and have problems.

Jeff Boleng