// Copyright (c) 2001-2009, Scalable Network Technologies, Inc. All Rights Reserved.
// 6100 Center Drive
// Suite 1250
// Los Angeles, CA 90045
// sales@scalable-networks.com
//
// This source code is licensed, not sold, and is subject to a written
// license agreement. Among other things, no portion of this source
// code may be copied, transmitted, disclosed, displayed, distributed,
// translated, used as the basis for a derivative work, or used, in
// whole or in part, for any program or purpose other than its intended
// use in compliance with the license agreement as part of the QualNet
// software. This source code and certain of the algorithms contained
// within it are confidential trade secrets of Scalable Network
// Technologies, Inc. and may not be used as the basis for any other
// software, hardware, product or service.
// Reference: The implementation is according to dsr draft 7
// http://www.ietf.org/internet-drafts/draft-ietf-manet-dsr-07.txt
// Future works:
// 1. FIFO strategy for immature packet drop from
// packet buffer for buffer overflowing.
// 2. Only option implemented is propagating and non
// propagating broadcast of RREQ. Expanding ring
// search can be implemented.
// 3. Optimization for preventing route reply storm
// 4. Gratuitous route reply table
// 5. Blacklist table
// 6. Network layer acknowledgement
// 7. Automatic route shortening.
// 8. Multiple interface support
// 9. Route cache has been implemented a path cache, other
// available option is link cache
// 10. Initiating Route discovery to send Reply back to source
// with Piggybacking the Reply option.
// Assumptions:
// 1. Physical link needs bidirectional communication
// to send unicast packets.
// 2. Route reply will be reversed back to the source
// 3. Route request will be sent as a separate packet
// 4. This protocol is only applicable for wireless scenario
// 5. MAC layer has packet transmission acknowledgement method
// Note: #1
// According to the Draft
// "decrement the value of the Segments Left field by 1. Let i equal n minus
// Segments Left. This is the index of the next address to be visited in the
// Address vector."
// If a path list contains addr[1] .....addr[i]..........addr[n], and
// i = (n - segsleft) then addr[i + 1] should give the next hop not i. In C
// programming the equation is correct as index actually starts from 0 not 1
//
// According to the Draft
// "Specifically, the node copies the hop addresses of the source route into
// sequential Address[i] fields in the DSR Source Route option, for i = 1,
// 2, ..., n.Address[1] here is the address of the salvaging node itself (the
// first address in the source route found from this node to the IP
// Destination Address of the packet). The value n here is the number of hop
// addresses in this source route, excluding the destination of the packet
// (which is instead already represented in the Destination Address field in
// the packet's IP header)."
// "Initialize the Segments Left field in the DSR Source Route option to n as
// defined above"
//
// With this specification above rule for calculating next hop is not going to
// work
// If a path list contains addr[1] .....addr[i]..........addr[n], and
// i = (n - segsleft) consider the 1st hop in the path, there i will be equal
// to 1 which is the previous hop not next Hop. So the equation should be
// next hop = addr[i + 2]. We took a different approach. We have set segsleft
// to n - 1 instead of n. Then processing will be same as above.
// Note: #2
// The draft says, if the destination is one hop away, then a node don't need
// to add source route option with the packet and should send the packet
// directly to the destination, without adding a DSR header.
// To make the work of DSR symmetric while receiving a packet, in the
// implementation, even when a node adds a source route option with a packet,
// that source route only travels up to the previous hop of the destination.
// The previous hop to the destination strips out DSR source route option
// and DSR header iff the packet contains only data, and sends the only data
// portion to the destination.
// This might result in a Routing Loop in some special cases. If the topology is
// prone to change , then number of salvaging a packet might be higher. In
// those cases salvage information (like Salvage Count) might be lost at the
// previous hop to the destination as DSR header, at least the source route,
// will be stripped out there. So there might be no way to check
// MAX_SALVAGE_COUNT to stop a packet to be salvaged. This might cause a loop of
// salvaging the packet continiously.
//
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include "api.h"
#include "network_ip.h"
#include "routing_dsr.h"
#define DEBUG_TRACE 0
#define DEBUG_ROUTE_CACHE 0
#define DEBUG_ROUTING_TABLE 0
#define DEBUG_ERROR 0
#define DEBUG_MAINTENANCE_BUFFER 0
#define DEBUG_SEND_BUFFER 0
#define DEBUG_RREQ_BUFFER 0
#define DEBUG_DISCOVERY 0
//------------------------------------------
// Dsr Memory Manager
//------------------------------------------
//-------------------------------------------------------------------------
// FUNCTION: DsrMemoryChunkAlloc
// PURPOSE: Function to allocate a chunk of memory
// ARGUMENTS: Pointer to Dsr main data structure
// RETURN: void
//-------------------------------------------------------------------------
static
void DsrMemoryChunkAlloc(DsrData* dsr)
{
int i = 0;
DsrMemPollEntry* freeList = NULL;
dsr->freeList = (DsrMemPollEntry *) MEM_malloc(
DSR_MEM_UNIT * sizeof(DsrMemPollEntry));
ERROR_Assert(dsr->freeList != NULL, " No available Memory");
freeList = dsr->freeList;
for (i = 0; i < DSR_MEM_UNIT - 1; i++)
{
freeList[i].next = &freeList[i+1];
}
freeList[DSR_MEM_UNIT - 1].next = NULL;
}
//-------------------------------------------------------------------------
// FUNCTION: DsrMemoryMalloc
// PURPOSE: Function to allocate a single cell of memory from the memory
// chunk
// ARGUMENTS: Pointer to Dsr main data structure
// RETURN: Address of free memory cell
//-------------------------------------------------------------------------
static
DsrRouteEntry* DsrMemoryMalloc(DsrData* dsr)
{
DsrRouteEntry* temp = NULL;
if (!dsr->freeList)
{
DsrMemoryChunkAlloc(dsr);
}
temp = (DsrRouteEntry*)dsr->freeList;
dsr->freeList = dsr->freeList->next;
return temp;
}
//-------------------------------------------------------------------------
// FUNCTION: DsrMemoryFree
// PURPOSE: Function to return a memory cell to the memory pool
// ARGUMENTS: Pointer to Dsr main data structure,
// pointer to route entry
// RETURN: void
//-------------------------------------------------------------------------
static
void DsrMemoryFree(DsrData* dsr,DsrRouteEntry* ptr)
{
DsrMemPollEntry* temp = (DsrMemPollEntry*)ptr;
temp->next = dsr->freeList;
dsr->freeList = temp;
}
//-------------------------------------------------------------------------
// Dsr Utility functions
//-------------------------------------------------------------------------
// FUNCTION: DsrCheckIfAddressExists
// PURPOSE: Function to check whether a particular address exists in a path
// ARGUMENTS: Pointer to path, path length and the address to check
// RETURN: TRUE if the address exists in the path, FALSE otherwise
//-------------------------------------------------------------------------
static
BOOL DsrCheckIfAddressExists(
unsigned char* path,
int hopCount,
NodeAddress a