2018-04-02 18:19:28 +02:00
|
|
|
#include <string.h>
|
2018-04-02 10:11:25 +02:00
|
|
|
|
2018-04-02 18:19:28 +02:00
|
|
|
#include "cw/sock.h"
|
2018-04-02 10:11:25 +02:00
|
|
|
#include "cw/mlist.h"
|
|
|
|
#include "cw/mavl.h"
|
2018-04-02 21:00:37 +02:00
|
|
|
#include "cw/mod.h"
|
2018-04-02 10:11:25 +02:00
|
|
|
|
2018-04-02 18:19:28 +02:00
|
|
|
#include "discovery_cache.h"
|
2018-04-02 21:00:37 +02:00
|
|
|
struct cw_DiscoveryCacheElem{
|
|
|
|
struct sockaddr_storage addr;
|
|
|
|
struct cw_Mod *cmod, *bmod;
|
|
|
|
uint32_t ctrlo, ctrhi;
|
|
|
|
};
|
2018-04-02 18:19:28 +02:00
|
|
|
|
2018-04-02 10:11:25 +02:00
|
|
|
struct cw_DiscoveryCache{
|
|
|
|
int len;
|
2018-04-02 18:19:28 +02:00
|
|
|
int qpos;
|
|
|
|
int qdel;
|
|
|
|
mavl_t byaddrp;
|
|
|
|
mavl_t byaddr;
|
|
|
|
struct cw_DiscoveryCacheElem * queue;
|
|
|
|
uint32_t ctrlo, ctrhi;
|
2018-04-02 10:11:25 +02:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void discovery_cache_destroy(struct cw_DiscoveryCache * c)
|
|
|
|
{
|
2018-04-02 18:19:28 +02:00
|
|
|
if (c->byaddr)
|
|
|
|
mavl_destroy(c->byaddr);
|
|
|
|
|
|
|
|
if (c->byaddrp)
|
|
|
|
mavl_destroy(c->byaddrp);
|
|
|
|
|
|
|
|
free(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int cmpaddrp ( const void * d1, const void *d2 )
|
|
|
|
{
|
|
|
|
struct cw_DiscoveryCacheElem * c1 = * ( void ** ) d1 ;
|
|
|
|
struct cw_DiscoveryCacheElem * c2 = * ( void ** ) d2 ;
|
|
|
|
return sock_cmpaddr ( ( struct sockaddr* ) &c1->addr, ( struct sockaddr* ) &c2->addr, 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int cmpaddr ( const void * d1, const void *d2 )
|
|
|
|
{
|
|
|
|
struct cw_DiscoveryCacheElem * c1 = * ( void ** ) d1 ;
|
|
|
|
struct cw_DiscoveryCacheElem * c2 = * ( void ** ) d2 ;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = sock_cmpaddr ( ( struct sockaddr* ) &c1->addr, ( struct sockaddr* ) &c2->addr, 0 );
|
|
|
|
if (rc != 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
if (c1->ctrhi != c2->ctrhi)
|
|
|
|
return c1->ctrhi-c2->ctrhi;
|
|
|
|
|
|
|
|
return c1->ctrlo-c2->ctrlo;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct cw_DiscoveryCache * discovery_cache_create(int len)
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
struct cw_DiscoveryCache * cache;
|
|
|
|
|
|
|
|
cache = malloc (sizeof(struct cw_DiscoveryCache));
|
|
|
|
if (cache==NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(cache,0,sizeof(struct cw_DiscoveryCache));
|
|
|
|
cache->queue = malloc(sizeof(struct cw_DiscoveryCacheElem)*len);
|
|
|
|
if (cache->queue==NULL)
|
|
|
|
goto errX;
|
|
|
|
|
|
|
|
for (i=0; i<len; i++){
|
2018-04-02 21:00:37 +02:00
|
|
|
cache->queue[i].cmod=NULL;
|
2018-04-02 18:19:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cache->byaddr = mavl_create_ptr(cmpaddr,NULL);
|
|
|
|
if (cache->byaddr == NULL)
|
|
|
|
goto errX;
|
|
|
|
|
|
|
|
|
|
|
|
cache->byaddrp = mavl_create_ptr(cmpaddrp,NULL);
|
|
|
|
if (cache->byaddrp == NULL)
|
|
|
|
goto errX;
|
|
|
|
|
|
|
|
cache->len=len;
|
|
|
|
cache->qpos=0;
|
|
|
|
|
|
|
|
|
|
|
|
return cache;
|
|
|
|
errX:
|
|
|
|
discovery_cache_destroy(cache);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void discovery_cache_add(struct cw_DiscoveryCache *cache,
|
2018-04-02 21:00:37 +02:00
|
|
|
struct sockaddr * addr, struct cw_Mod * mod_capwap, struct cw_Mod * mod_bindings)
|
2018-04-02 18:19:28 +02:00
|
|
|
{
|
|
|
|
struct cw_DiscoveryCacheElem * cur = cache->queue+cache->qpos;
|
2018-04-02 21:00:37 +02:00
|
|
|
if (cur->cmod!=NULL){
|
2018-04-02 18:19:28 +02:00
|
|
|
/* delete here */
|
2018-04-02 21:00:37 +02:00
|
|
|
void * ptr = &cur;
|
|
|
|
mavl_del(cache->byaddr,ptr);
|
|
|
|
mavl_del(cache->byaddr,ptr);
|
2018-04-02 18:19:28 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-04-02 21:00:37 +02:00
|
|
|
cur->cmod=mod_capwap;
|
|
|
|
cur->bmod=mod_bindings;
|
2018-04-02 18:19:28 +02:00
|
|
|
sock_copyaddr(&cur->addr,addr);
|
|
|
|
|
|
|
|
cur->ctrhi=cache->ctrhi;
|
|
|
|
cur->ctrlo=cache->ctrlo;
|
|
|
|
|
|
|
|
if ((++cache->ctrlo)==0){
|
|
|
|
cache->ctrhi++;
|
|
|
|
}
|
|
|
|
|
|
|
|
mavl_add_ptr(cache->byaddr,cur);
|
|
|
|
mavl_add_ptr(cache->byaddrp,cur);
|
|
|
|
|
|
|
|
cache->qpos++;
|
|
|
|
if (cache->qpos>=cache->len)
|
|
|
|
cache->qpos=0;
|
2018-04-02 10:11:25 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-04-02 21:00:37 +02:00
|
|
|
int discovery_cache_get(struct cw_DiscoveryCache * cache,struct sockaddr *addr,
|
|
|
|
struct cw_Mod ** modcapwap, struct cw_Mod **modbindings)
|
2018-04-02 18:19:28 +02:00
|
|
|
{
|
|
|
|
struct cw_DiscoveryCacheElem * elem, ** result, *search_ptr, search;
|
|
|
|
sock_copyaddr(&search.addr,addr);
|
|
|
|
search.ctrhi=search.ctrlo=0;
|
|
|
|
|
2018-04-02 21:00:37 +02:00
|
|
|
search_ptr = &search;
|
|
|
|
result = mavl_get(cache->byaddrp ,&search_ptr);
|
|
|
|
if (result != NULL){
|
|
|
|
elem = *result;
|
|
|
|
if (elem != NULL){
|
|
|
|
mavl_del(cache->byaddr,result);
|
|
|
|
mavl_del(cache->byaddrp,result);
|
|
|
|
*modcapwap=elem->cmod;
|
|
|
|
*modbindings=elem->bmod;
|
|
|
|
|
|
|
|
elem->cmod=NULL;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2018-04-02 18:19:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
search_ptr = &search;
|
|
|
|
/*elem = *((struct cw_DiscoveryCacheElem **)
|
|
|
|
*/
|
|
|
|
result = mavl_get_first(cache->byaddr, &search_ptr);
|
|
|
|
if (result == NULL)
|
2018-04-02 21:00:37 +02:00
|
|
|
return 0;
|
|
|
|
|
2018-04-02 18:19:28 +02:00
|
|
|
elem = *result;
|
|
|
|
if (elem != NULL){
|
|
|
|
if (sock_cmpaddr((struct sockaddr*)&elem->addr,addr,0)!=0)
|
2018-04-02 21:00:37 +02:00
|
|
|
return 0;
|
2018-04-02 18:19:28 +02:00
|
|
|
|
|
|
|
mavl_del(cache->byaddr,result);
|
|
|
|
mavl_del(cache->byaddrp,result);
|
2018-04-02 21:00:37 +02:00
|
|
|
|
|
|
|
*modcapwap=elem->cmod;
|
|
|
|
*modbindings=elem->bmod;
|
|
|
|
|
|
|
|
elem->cmod=NULL;
|
2018-04-02 18:19:28 +02:00
|
|
|
}
|
2018-04-02 10:11:25 +02:00
|
|
|
|
2018-04-02 21:00:37 +02:00
|
|
|
return 1;
|
2018-04-02 18:19:28 +02:00
|
|
|
|
|
|
|
}
|