1 /* Copyright 2002 Yon Uriarte and Jeff Dike
2 * Licensed under the GPL
3 * This file is part of the original uml_switch code
4 * Modified 2003 Renzo Davoli
14 #include <sys/types.h>
16 #include <sys/signal.h>
24 struct hash_entry
*next
;
25 struct hash_entry
*prev
;
28 unsigned char dst
[ETH_ALEN
];
31 static struct hash_entry
*h
[HASH_SIZE
];
33 static int calc_hash(char *src
)
35 return ((*(u_int32_t
*) &src
[0] % HASH_MOD
) ^ src
[4] ^ src
[5] ) % HASH_SIZE
;
38 static struct hash_entry
*find_entry(char *dst
)
41 int k
= calc_hash(dst
);
43 for(e
= h
[k
]; e
; e
= e
->next
){
44 if(!memcmp(&e
->dst
, dst
, ETH_ALEN
)) return(e
);
49 void *find_in_hash(char *dst
)
51 struct hash_entry
*e
= find_entry(dst
);
52 if(e
== NULL
) return(NULL
);
56 void insert_into_hash(char *src
, void *port
)
58 struct hash_entry
*new;
59 int k
= calc_hash(src
);
61 new = find_in_hash(src
);
62 if(new != NULL
) return;
64 new = malloc(sizeof(*new));
66 perror("Failed to malloc hash entry");
70 memcpy(&new->dst
, src
, ETH_ALEN
);
71 if(h
[k
] != NULL
) h
[k
]->prev
= new;
79 void update_entry_time(char *src
)
85 e
->last_seen
= time(NULL
);
88 static void delete_hash_entry(struct hash_entry
*old
)
90 int k
= calc_hash(old
->dst
);
92 if(old
->prev
!= NULL
) old
->prev
->next
= old
->next
;
93 if(old
->next
!= NULL
) old
->next
->prev
= old
->prev
;
94 if(h
[k
] == old
) h
[k
] = old
->next
;
98 void delete_hash(char *dst
)
100 struct hash_entry
*old
= find_entry(dst
);
102 if(old
== NULL
) return;
103 delete_hash_entry(old
);
106 static void for_all_hash(void (*f
)(struct hash_entry
*, void *), void *arg
)
109 struct hash_entry
*e
, *next
;
111 for(i
= 0; i
< HASH_SIZE
; i
++){
112 for(e
= h
[i
]; e
; e
= next
){
121 char *(*port_id
)(void *);
124 static void print_hash_entry(struct hash_entry
*e
, void *arg
)
126 struct printer
*p
= arg
;
128 printf("Hash: %d Addr: %02x:%02x:%02x:%02x:%02x:%02x to port: %s "
129 "age %ld secs\n", calc_hash(e
->dst
),
130 e
->dst
[0], e
->dst
[1], e
->dst
[2], e
->dst
[3], e
->dst
[4], e
->dst
[5],
131 (*p
->port_id
)(e
->port
), (int) p
->now
- e
->last_seen
);
134 void print_hash(char *(*port_id
)(void *))
136 struct printer p
= ((struct printer
) { now
: time(NULL
),
137 port_id
: port_id
});
139 for_all_hash(print_hash_entry
, &p
);
142 struct reassign_data
{
147 static void reassing_iterator (struct hash_entry
*e
, void *arg
)
149 struct reassign_data
*p
=arg
;
151 if (e
->port
== p
->port
)
152 e
->port
= p
->newport
;
155 void hash_reassign (void *port
, void *newport
)
157 struct reassign_data p
=((struct reassign_data
) { port
: port
,
158 newport
: newport
});
159 for_all_hash(reassing_iterator
, &p
);
162 static void delete_port_iterator (struct hash_entry
*e
, void *arg
)
165 delete_hash_entry(e
);
168 void hash_delete_port (void *port
)
170 for_all_hash(delete_port_iterator
,port
);
174 #define GC_INTERVAL 2
175 #define GC_EXPIRE 100
177 static void gc(struct hash_entry
*e
, void *now
)
179 time_t t
= *(time_t *) now
;
181 if(e
->last_seen
+ GC_EXPIRE
< t
)
182 delete_hash_entry(e
);
185 static void sig_alarm(int sig
)
188 time_t t
= time(NULL
);
189 for_all_hash(&gc
, &t
);
191 it
.it_value
.tv_sec
= GC_INTERVAL
;
192 it
.it_value
.tv_usec
= 0 ;
193 it
.it_interval
.tv_sec
= 0;
194 it
.it_interval
.tv_usec
= 0 ;
195 setitimer(ITIMER_REAL
, &it
, NULL
);
202 sa
.sa_handler
= sig_alarm
;
203 sa
.sa_flags
= SA_RESTART
;
204 if(sigaction(SIGALRM
, &sa
, NULL
) < 0){
205 perror("Setting handler for SIGALRM");
208 kill(getpid(), SIGALRM
);