Commit 4c99ee7f authored by ikumar's avatar ikumar

This version has my algorithm implemented and works correctly with all kinds...

This version has my algorithm implemented and works correctly with all kinds of topology. It generates the nam file with LAN topology too !!
                  - Indrajeet
parent 945c0520
pc1 0 00d0b713f399
pc1 1 00d0b713f6c9
pc1 2 00d0b713f273
pc1 3 00d0b713f443
pc1 4 00d0b713f639
pc2 0 00d0b713f28e
pc2 1 00d0b713f5d5
pc2 2 00d0b713f5e8
pc2 3 00d0b713f35c
pc2 4 00d0b713f56c
pc3 0 00d0b713f5ad
pc3 1 00d0b713f425
pc3 2 00d0b713f419
pc3 3 00d0b713f290
pc3 4 00d0b713f57d
pc4 0 00d0b713f4f0
pc4 1 00d0b713f644
pc4 2 00d0b713f492
pc4 3 00d0b713f65a
pc4 4 00d0b713f470
pc5 0 00d0b713f473
pc5 1 00d0b713f178
pc5 2 00d0b713f5a5
pc5 3 00d0b713f524
pc5 4 00d0b713f686
pc6 0 00d0b713f607
pc6 1 00d0b713f41c
pc6 2 00d0b713f603
pc6 3 00d0b7254638
pc6 4 00d0b713f467
pc7 0 00d0b713f636
pc7 1 00d0b713f277
pc7 2 00d0b726c1ca
pc7 3 00d0b713f44f
pc7 4 00d0b713f66c
pc8 0 00d0b713f6cd
pc8 1 00d0b713f465
pc8 2 00d0b713f5d7
pc8 3 00d0b713f605
pc8 4 00d0b713f5ab
pc9 0 009027ca71a6
pc9 1 009027ca5cff
pc9 2 009027ca9835
pc9 3 009027c7e056
pc9 4 009027ca983e
pc10 0 00d0b713f398
pc10 1 00d0b713f288
pc10 2 00d0b713f515
pc10 3 00d0b713f56e
pc10 4 00d0b713f3db
pc11 0 00d0b714100c
pc11 1 00d0b71416ac
pc11 2 00d0b7141778
pc11 3 00d0b7141055
pc11 4 00d0b7141118
pc12 0 00d0b7102501
pc12 1 00d0b70ee068
pc12 2 00d0b7102cef
pc12 3 00d0b7102dc4
pc12 4 00d0b7102be3
pc13 0 00d0b713f689
pc13 1 00d0b713f893
pc13 2 00d0b713f895
pc13 3 00d0b713f91b
pc13 4 00d0b713fadf
pc14 0 00d0b713f91c
pc14 1 00d0b713f669
pc14 2 00d0b713f5e4
pc14 3 00d0b713f48e
pc14 4 00d0b713f656
pc15 0 00d0b713f6b1
pc15 1 00d0b713f527
pc15 2 00d0b713f68a
pc15 3 00d0b713f61c
pc15 4 00d0b713f668
pc16 0 00d0b713f88e
pc16 1 00d0b713f763
pc16 2 00d0b713f3e7
pc16 3 00d0b713f471
pc16 4 00d0b713fa35
pc17 0 00d0b713f733
pc17 1 00d0b713f8a3
pc17 2 00d0b713f884
pc17 3 00d0b713f88d
pc17 4 00d0b713fa2a
pc18 0 00d0b713fa56
pc18 1 00d0b713fa54
pc18 2 00d0b713f676
pc18 3 00d0b713f6b5
pc18 4 00d0b713ecfa
pc19 0 00d0b713f892
pc19 1 00d0b713f716
pc19 2 00d0b713f6b3
pc19 3 00d0b713f64d
pc19 4 00d0b713f0c5
pc20 0 00d0b713f66b
pc20 1 00d0b713f66d
pc20 2 00d0b713f3df
pc20 3 00d0b713f382
pc20 4 00d0b713f5dc
pc21 0 00d0b7102dc1
pc21 1 00d0b7102cf8
pc21 2 00d0b70f70c9
pc21 3 00d0b71008ce
pc21 4 00d0b7102dfd
pc22 0 00d0b7102d9e
pc22 1 00d0b7102dd5
pc22 2 00d0b71007dd
pc22 3 00d0b7141ea9
pc22 4 00d0b71008a2
pc23 0 00d0b7140f51
pc23 1 00d0b7140efa
pc23 2 00d0b71410d4
pc23 3 00d0b7141056
pc23 4 00d0b7140f4f
pc24 0 00d0b71007d6
pc24 1 00d0b7100846
pc24 2 00d0b71420d6
pc24 3 00d0b71007de
pc24 4 00d0b710065d
pc25 0 00d0b71410e5
pc25 1 00d0b7140f1b
pc25 2 00d0b71410e7
pc25 3 00d0b71410e4
pc25 4 00d0b7141052
pc26 0 00d0b71417b7
pc26 1 00d0b71416a8
pc26 2 00d0b71417d3
pc26 3 00d0b71410e8
pc26 4 00d0b71417bd
pc27 0 00d0b70ef58b
pc27 1 00d0b7100818
pc27 2 00d0b7100884
pc27 3 00d0b70efae0
pc27 4 00d0b7100645
pc28 0 00d0b71029ce
pc28 1 00d0b70ee067
pc28 2 00d0b71029ba
pc28 3 00d0b70efaa4
pc28 4 00d0b7100887
pc29 0 00d0b7141108
pc29 1 00d0b7140f4d
pc29 2 00d0b7141002
pc29 3 00d0b7141003
pc29 4 00d0b71410da
pc30 0 00d0b71420d5
pc30 1 00d0b70ee069
pc30 2 00d0b70f70cb
pc30 3 00d0b7141f9a
pc30 4 00d0b7102dd3
pc31 0 00d0b713fa28
pc31 1 00d0b713fadd
pc31 2 00d0b713f928
pc31 3 00d0b713f9cb
pc31 4 00d0b713ecdc
pc32 0 00d0b713fad7
pc32 1 00d0b713f387
pc32 2 00d0b713f88b
pc32 3 00d0b713f886
pc32 4 00d0b713f658
pc33 0 00d0b7140d4f
pc33 1 00d0b71410be
pc33 2 00d0b7140f55
pc33 3 00d0b71410d6
pc33 4 00d0b7140f12
pc34 0 00d0b7141005
pc34 1 00d0b7141000
pc34 2 00d0b714104e
pc34 3 00d0b7141050
pc34 4 00d0b7141057
pc35 0 00d0b7140f53
pc35 1 00d0b714110c
pc35 2 00d0b7140f17
pc35 3 00d0b7140f57
pc35 4 00d0b7141084
pc36 0 00d0b71410e6
pc36 1 00d0b7140d46
pc36 2 00d0b7140d4e
pc36 3 00d0b71410db
pc36 4 00d0b7140fe2
pc37 0 00d0b713fa36
pc37 1 00d0b713f634
pc37 2 00d0b713f7ba
pc37 3 00d0b713f44d
pc37 4 00d0b713f3ea
pc38 0 00d0b71007dc
pc38 1 00d0b70f70cf
pc38 2 00d0b7141f96
pc38 3 00d0b7102dc2
pc38 4 00d0b7141eac
pc39 0 00d0b71416a5
pc39 1 00d0b713b4ed
pc39 2 00d0b7141114
pc39 3 00d0b7141782
pc39 4 00d0b7141505
pc40 0 00d0b71006e0
pc40 1 00d0b71006d1
pc40 2 00d0b7100852
pc40 3 00d0b71006e3
pc40 4 00d0b71007d7
......@@ -18,13 +18,17 @@
* ---------------------------
* $Id: cli.c,v 1.5 2001-07-19 19:55:57 ikumar Exp $
* $Id: cli.c,v 1.7 2001-08-02 21:21:05 ikumar Exp $
#include "discvr.h"
#include "packet.h"
#include "util.h"
extern u_char *mac_list[MAX_NODES];
extern int num_nodes;
u_char *
......@@ -63,7 +67,6 @@ find_nodeID(void)
* compiled out eventually. -lkw
// Why max is being talken ?! -ik
if ( ifi->ifi_hlen > 0) {
myNodeIDtmp = max_haddr(myNodeIDtmp, ifi->ifi_haddr);
......@@ -119,11 +122,13 @@ cli(int sockfd, const struct sockaddr *pservaddr, socklen_t servlen,
printf("sending query to server:\n");
sendto(sockfd, &ti, TOPD_INQ_SIZ, 0, pservaddr, servlen);
//print_tdinq((char *)&ti);
print_tdinq((char *)&ti);
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
//printf("Receiving in client:==>\n");
//print_tdreply(recvline, n);
printf("Receiving in client:==>\n");
print_tdreply(recvline, n);
gen_nam_file(recvline, n,"td1.nam");
......@@ -149,7 +154,7 @@ main(int argc, char **argv)
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
printf("calling client\n");
//printf("calling client\n");
cli(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr), atoi(argv[2]), atoi(argv[3]));
Initiate Topology Discovery by sending Query to the server on
the same machine. The Query packet format is:
1) Unique ID: Basically its the value returned by "gettimeofday()"
which serves two purpose:
a) Query initiated by different clients running simulatenously
b) Identifying that its the query packet which was already
seen earlier and processed.
2) TTL: In a sense its the estimate of the diameter of the network.
3) Factor: "TTL * Factor" is the time till any node waits for its
neighbors to respond.
4) SourceNodeID: The greatest of the MAC Addresses of the machine
from where the query was initiated.
5) ImmediateSenderID: Its the ID of the immediate sender of the query.
After sending this query the client waits for the server to respond.
In an "infinite loop" the server does the following:
1. Listen to any query packet on the SERV_PORT
2. We can determine if the latest query packet was already processed earlier
or not based on a list of query that we maintain. We keep adding every new
query that we encounter in this "Query List".
(a)If the "query packet" was already processed (as by above) and it is now sent
by this server then we discard the packet. We can determine who has sent this
packet by the information returned by "recvfrom" function for UDP receive.
(b)If the "query packet" was already processed earlier and it is now sent
by some other node (neighbors) then the server replies them with its interface
list. (No neighbor information was supplied in the reply). The fact that the
packet has come back again tells the possibility of a cycle in the network so
just telling this node's information is enough to make the cycle complete.
3. If the "query packet is a NEW packet then the server needs to gather its
neighbors' information and will have to send this back to the node which has
sent the query.
To gather this neighbors' information the server broadcasts this query to all
its interfaces after decrementing the TTL using the broadcast addresses.
Then the server goes in "select mode" to listen for all replies. It opens sockets
corresponding to each interface and binds to temperory ports.
Based on the replies from all the different interfaces the server makes a list
of replies (ReplyList).
The server cann't wait for replies for ever! So, it has a time limit
after that it stops listening to any reply and sends the current ReplyList back
to the node which as sent the Query. The "time limit" is determined by "ttl *
factor" in the query packet. From this it can be understood that TTL is in
sense corresponds to the diameter of the network. Factor helps in getting a
reasonable time out value.
4. After the ReplyList was formed send this to the node which had sent the query.
5. Jump to step 1.
Problems removed from Kristine's Code to follow the above algorithm:
1. TTL was not decremented before forwarding the Query
2. Duplicate Query was not checked in the code correctly
- TTL was also compared to be equal
3. Before doing select "fd_set" was not saved so it was
modified after select
4. ResponseList was not returned by the forw_requests funstion
5. It was forwarding the Query on one interface and was blocking
till it receives the response. Because of this
(i) Timeout was occuring by listening on just one
(ii) It resulted in deadlock in case of cycles.
6. Caculation of the size of reply list was wrong
(i) There were memory problems because size of Query
structure was not decremented from the received
response before forming the ResponseList
7. Other small small problems like server was not listening on
the specific ports where neighbors were sending the response
But apart from this, the algo has an inherent problem:
The server listens to query only after it has received all the replies from the
neighbors. Because of this the algorithm results in a lock when two nodes are each
waiting for the other to reply and they both time out simulatenously resulting in
missing links. This situation occurs in a cycle of 5 nodes as was discovered while
New Server Algo:
This algorithm is slight modification of the above server algorithm. The main
difference is in the fact that we listen to the query as well as the replies
at the same point in the algorithm. We do the select on Query socket as well as
the Response socket and process each of them depending on which socket the packet
was received.
After receiving a new query the server sets a timeout for the select. After
the timeout occurs server stops waiting for response and then it sends its own
response back to the node which sent the query.
The algorithm is very similar to the above except the fact that we are doing
select on the query socket too.
Set timeout= 0. This blocks the select to listen for the queries.
Run the following steps infinitely:
1. select on socket corresponding to SERV_PORT for listening to any query as well
as any socket open for listening to responses from the neighbors.
2. If there is any query packet on the query socket then process it as done in
step 2 of the above algorithm. In case of a new query set "timeout" to
"ttl*factor" and goto select statement again.
3. If there are any response packets then make a list of it. Goto select again.
4. If there is "timeout" in select then send the response back and set "timeout"
to 0 again so that it can wait infinitely for any query.
So, as clear from the algorithm the server can respond to any query also while
waiting for replies. This was the drawback in the above algorithm which went in
lock in this scenario.
PS: I have avoided minute details in the algorithm for high level understanding of
the algorithm. Feel free to raise any problem in the above algorithm.
......@@ -8,7 +8,7 @@ error_exit(char *fmt, ...)
char *msg;
va_start(ap, fmt);
perror("Unable to get time-of-day.");
/*$Id: discvr.h,v 1.6 2001-07-19 19:55:57 ikumar Exp $*/
/*$Id: discvr.h,v 1.8 2001-08-02 21:21:05 ikumar Exp $*/
#ifndef _TOPD_DISCVR_H_
#define _TOPD_DISCVR_H_
......@@ -29,6 +29,10 @@
* needed until true packets are generated. -lkw
#define Q_LISTEN 1
#define QR_LISTEN 2
#define print_nodeID(x) println_haddr((x), ETHADDRSIZ)
#define INCR_ALIGN(x,y) ((x) += (y); ALIGN(x);)
......@@ -57,14 +61,25 @@ struct ifi_info {
int sock; /* socket associated with this interface */
#define MAC_ADDR_LEN 20
typedef struct db_elem
char *hostname;
#define MAX_NODES 100
/* Prototypes */
serv_listen(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen);
struct ifi_info *
int *
forward_request(struct ifi_info *ifi, const struct in_pktinfo *pktinfo,
const char *mesg, const int mesglen);
const char *mesg, const int mesglen, int *ptrSockNum);
struct ifi_info *
get_ifi_info(int, int);
......@@ -88,7 +103,8 @@ void
get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
compose_reply(struct ifi_info *ifi, char *mesg, const int mesglen, int sendnbors);
compose_reply(struct ifi_info *ifi, char *mesg, const int mesglen, int sendnbors,
u_char [], u_char []);
is_my_packet(struct sockaddr *pcliaddr, struct ifi_info *ifihead) ;
......@@ -100,7 +116,13 @@ void
addMyID(char* mesg, int size);
get_recvIFADDR(char *name,struct ifi_info * ifihead);
get_recvIFADDR(u_char* recvIF,char *name,struct ifi_info * ifihead);
gen_nam_file(const char *mesg, size_t nbytes, char *);
#endif /* _TOPD_DISCVR_H_ */
......@@ -18,7 +18,7 @@
* ---------------------------
* $Id: forw_requests.c,v 1.8 2001-07-19 19:55:57 ikumar Exp $
* $Id: forw_requests.c,v 1.9 2001-07-19 20:02:37 ikumar Exp $
#include <math.h>
......@@ -73,271 +73,87 @@ addMyID(char* mesg, int size)
struct ifi_info *
forward_request(struct ifi_info *ifi, const struct in_pktinfo *pktinfo,
const char *mesg, int mesglen)
int *
forward_request(struct ifi_info *ifihead, const struct in_pktinfo *pktinfo,
const char *mesg, int mesglen, int *ptrSockNum)
int s, n;
int more_time = 1;
fd_set rset,temp_rset;
const int on = 1;
char ifname[IFNAMSIZ];
struct topd_inqid *tdi;
struct topd_nborlist *save;
struct sockaddr_in sin,tempAddr;
struct ifi_info *ifihead;
struct timeval tv;
int selectReturn;
struct sockaddr name;
int namelen=sizeof(name);
struct ifi_info *ifi;
int *sock_list=NULL, *temp_sock_list=NULL;
int sock_num = 0,i=0;
struct topd_inqid *temp_mesg;
int t_int;
printf("The interface on which I received: \"%s\"\n",if_indextoname(pktinfo->ipi_ifindex, ifname));
int t_int=0,i=0;
bzero(&tempAddr, sizeof(tempAddr));
tempAddr.sin_family = AF_INET;
tempAddr.sin_addr.s_addr = htonl(INADDR_ANY);
tempAddr.sin_port = htons(0);
tempAddr.sin_port = htons(0);
// Setting the deadline for select -ik
tdi = (struct topd_inqid *)mesg;
tv.tv_sec = ntohs(tdi->tdi_ttl) * ntohs(tdi->tdi_factor);
tv.tv_usec = 0;
temp_mesg = (struct topd_inqid *)mesg;
t_int = ntohs(temp_mesg->tdi_ttl);
temp_mesg->tdi_ttl = htons(t_int);
for (ifihead = ifi = get_ifi_info(AF_INET, 0);
ifi != NULL; ifi = ifi->ifi_next) {
* Don't send a message if the interface is down,
* a loopback interface, or it's the receiving
* interface.
* Add check for control net? -lkw
(*ptrSockNum) = 0;
for (ifi = ifihead; ifi != NULL; ifi = ifi->ifi_next)
// Skip all the interfaces which are not useful
if( (ifi->ifi_flags & !IFF_UP) || (ifi->ifi_flags & IFF_LOOPBACK) ||
(strcmp(ifi->ifi_name, if_indextoname(pktinfo->ipi_ifindex, ifname)) == 0) ||
(strcmp(ifi->ifi_name,"fxp4")==0) )
if ((ifi->ifi_flags & !IFF_UP) ||
(ifi->ifi_flags & IFF_LOOPBACK) ||
(strcmp(ifi->ifi_name, if_indextoname(pktinfo->ipi_ifindex, ifname)) == 0)) {
ifi->ifi_myflags |= MY_IFF_RECVIF; /* may be unnec. -lkw */
// Adding check for control net... -ik
if(strcmp(ifi->ifi_name,"fxp4")==0) continue;
printf("Forwarding the query to interface: \"%s\"\n",ifi->ifi_name);
temp_sock_list = sock_list;
sock_list = (int *)malloc(sizeof(int)*(sock_num+1));
sock_list = (int *)malloc(sizeof(int)*((*ptrSockNum)+1));
//printf("copying: %d\n",temp_sock_list[i]);
sock_list[i] = temp_sock_list[i];
sock_list[sock_num] = s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
perror("Unable to get socket");
sock_list[(*ptrSockNum)] = s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1)
perror("Unable to get socket");
if(bind(s, (struct sockaddr *) &tempAddr, sizeof(tempAddr))<0)
perror("Problem in bind call");
ifi->sock = s;
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0) {
perror("setsockopt died.");
/* Do something intelligent. -lkw */
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0)
perror("setsockopt died.");
// Do something intelligent. -lkw
bzero(&sin, sizeof(sin));
sin.sin_len = htons(sizeof sin);
sin.sin_family = PF_INET;
sin.sin_port = htons(SERV_PORT);
/* sin.sin_addr.s_addr = inet_addr(BROADCAST_IP); */
* struct sockaddr_in sin
* -> struct in_addr sin_addr
* -> u_int32_t s_addr
* struct sockaddr *ifi_brdaddr
* -> ifi_brdaddr->sa_data
/*sin.sin_addr.s_addr = inet_addr(ifi->ifi_brdaddr->sa_data); */
sin.sin_addr = ((struct sockaddr_in *)(ifi->ifi_brdaddr))->sin_addr;
printf("The dest. address: %s\n", inet_ntoa(sin.sin_addr));
* though sendto() returns the correct number of bytes,
* tcpdump is showing two packets for this one line. -lkw
* 60 eureka:testbed/discvr> tcpdump port 9877
* tcpdump: listening on fxp0
* 15:04:59.357514 > udp 15
* 15:04:59.357528 > udp 15
* 15:20:02.075858 > udp 15
printf("$$$forwarding the enquiry: ");
sin.sin_addr = ((struct sockaddr_in *)(ifi->ifi_brdaddr))->sin_addr;
printf("The dest. address: %s\n", inet_ntoa(sin.sin_addr));
printf("Forwarding the enquiry: ");
n = sendto(s, mesg, mesglen, 0,
(struct sockaddr *)&sin, sizeof(struct sockaddr_in));
//printf("$$$after forwarding the enquiry: ");
if(getsockname(s, (struct sockaddr *)&name, &namelen)<0)
//printf("The address from where i am sending: %s\n",sock_ntop(&name,name.sa_len));
if (n != mesglen) {
perror("Didn't send all of packet");
if (n != mesglen)
perror("Didn't send all of packet");
FD_SET(s, &rset);
* Can't wait forever because
* there may be either no nodes on this interface or
* the nodes that are there may not be responding.
* Our wait delay is equal to the "factor times the ttl".
* The packet size *might* exceed our buffer size.
* Put in some mechanism to check. -lkw
n = 0;
start = tod();
//while ( more_time ) {
while (1) {
double begin, end, elapsed;
double dea