Commit f33e5498 authored by Arne Øslebø's avatar Arne Øslebø
Browse files

moved and deleted some files

git-svn-id: file:///home/svn/mapi/trunk@890 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent 65e86467
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <pcap.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include "mapi.h"
#include "mapidrv.h"
#include "mapidlib.h"
#include "mapid.h"
#include "mapidevices.h"
#include "flist.h"
#include "debug.h"
#include "cbuf.h"
#define ETHSTR "eth"
#define LOSTR "lo"
#define CBUF_PATH "/tmp/.mapinicdrv.cbuf-XXXXXX"
#define CBUF_ID 'C'
#define CBUF_SLOTS 256
#define NIC_PKTCAP_LEN 1500
#define BUFSIZE 32768
static pthread_spinlock_t devlist_lock;
typedef struct nic_instance {
int id;
char *device;
int file;
unsigned long long pkts;
int init;
pthread_attr_t th_attr;
pthread_t th_proc;
pcap_t *pcap;
int offline_format;
mapid_hw_info_t hwinfo;
cbuf_t *NIC_cbuf;
mapi_offline_device_status_t *offline_status;
kernel_memory_t NIC_cbuf_mem;
char shm_fname[MAPI_STR_LENGTH];
mapidlib_instance_t mapidlib;
} nic_instance_t;
static flist_t *devlist;
__attribute__ ((constructor)) void init ();
__attribute__ ((destructor)) void fini ();
static function_manipulation_t* manipulation;
static int
touch_file(const char *fn)
{
int fd;
umask(022);
if ( (fd = open(fn,O_CREAT|O_EXCL,CBUF_PERMS)) < 0 )
return - 1;
close(fd);
return 0;
}
/** \brief Allocates a shared memory segment
*
* Used with cbuf_new().
*
* \param size size of segment to allocate
* \param mem shared segment info
*
* \return Reference to attached/and newly allocated segment,
* or NULL on failure
*/
static void *
shm_alloc(size_t *size,kernel_memory_t *mem)
{
mem->type = KERNEL_MEMORY_SHM;
mem->addr = NULL;
mem->src.shm.id = - 1;
if ( (mem->src.shm.id = shmget(mem->src.shm.key,*size,CBUF_PERMS|IPC_CREAT)) < 0 )
{
ERROR_CMD(printf("shmget: %s [%s:%d]\n",strerror(errno),__FILE__,__LINE__));
DEBUG_CMD2(printf("CBUF size = %u\n",*size));
return NULL;
}
if ( (mem->addr = shmat(mem->src.shm.id,NULL,644)) == NULL )
{
ERROR_CMD(printf("shmat: %s [%s:%d]\n",strerror(errno),__FILE__,__LINE__));
shmctl(mem->src.shm.id,IPC_RMID,0);
mem->src.shm.id = - 1;
return NULL;
}
DEBUG_CMD(printf("cbuf shm id=%d, key=%d [%s:%d]\n",mem->src.shm.id,mem->src.shm.key,__FILE__,__LINE__));
return mem->addr;
}
/** \brief Frees a shared memory segment
*
* Used with cbuf_destroy().
*
* \param addr memory segment info
*/
static void
shm_free(kernel_memory_t *mem)
{
if ( shmdt(mem->addr) != 0 )
return;
shmctl(mem->src.shm.id,IPC_RMID,0);
}
int
mapidrv_get_errno(int devid,int fd)
{
nic_instance_t *i=flist_get(devlist,devid);
return mapid_get_errno(&i->mapidlib,fd);
}
int
mapidrv_apply_function (int devid,int fd, int pid, char* function, mapiFunctArg *fargs)
{
nic_instance_t *i=flist_get(devlist,devid);
return mapid_apply_function(&i->mapidlib,fd, pid, function, fargs, manipulation);
}
static void
mapidrv_proc_loop(int devid)
{
const u_char *packet;
struct pcap_pkthdr phdr;
mapid_pkthdr_t mhdr;
nic_instance_t *i=flist_get(devlist,devid);
int err;
if ((err=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0) {
ERROR_CMD(fprintf(stderr, "pthread_setcanceltype failed (%s) [%s:%d]\n",strerror(err),__FILE__,__LINE__));
return;
}
if ((err=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) != 0) {
ERROR_CMD(fprintf(stderr, "pthread_setcancelstate (%s) failed [%s:%d]\n",strerror(err),__FILE__,__LINE__));
return;
}
DEBUG_CMD2(printf("NIC: thread running, device %d [%s:%d]\n",devid,__FILE__,__LINE__));
while( 1 )
{
//what happens with the timestamp?
while( (packet = pcap_next(i->pcap,&phdr)) == NULL )
;
// Transform header
// This is only for backward compatibility
mhdr.caplen = phdr.caplen;
mhdr.wlen = phdr.len;
mhdr.ts = (((unsigned long long)phdr.ts.tv_sec)<<32)+
((phdr.ts.tv_usec*4295) & 0xffffffff);
// increase counter for packets seen so far
i->hwinfo.pkts++;
// Process packet
mapid_process_pkt(&i->mapidlib,packet,packet,&mhdr);
}
}
static unsigned
process_pkts(void *buf,unsigned len, nic_instance_t *i,MAPI_UNUSED int devid,int last)
{
unsigned c = 0;
int rlen = 0;
struct pcap_pkthdr *rec;
const unsigned char *packet;
mapid_pkthdr_t mhdr;
rec = (struct pcap_pkthdr *) buf;
rlen = rec->caplen+sizeof(struct pcap_pkthdr);
while (c + rlen <= len)
{
char *p = buf;
buf = p + rlen;
c += rlen;
mhdr.caplen = rec->caplen;
mhdr.ifindex = 0;
mhdr.wlen = rec->len;
mhdr.ts = (((unsigned long long)rec->ts.tv_sec)<<32)+
((rec->ts.tv_usec*4295) & 0xffffffff);
//TODO: Need to check accuracy of timestamp. Rounding errors?
// increase counter for packets seen so far
i->hwinfo.pkts++;
packet=(unsigned char*)rec+(sizeof(struct pcap_pkthdr));
if(last<BUFSIZE && c+rlen>len)
i->hwinfo.offline=3;
mapid_process_pkt(&i->mapidlib,(unsigned char*)rec,packet,&mhdr);
// if(c+sizeof(dag_record_t)>len-sizeof(dag_record_t)*2)
//break;
rec = (struct pcap_pkthdr *) buf;
rlen = rec->caplen+sizeof(struct pcap_pkthdr);
}
return len - c;
}
static void
mapidrv_offline_proc_loop(int devid)
{
int c,left=0;
nic_instance_t *i=flist_get(devlist,devid);
int err;
char buf[BUFSIZE];
struct pcap_file_header head;
char *b=buf;
if (i==NULL) {
ERROR_CMD(fprintf(stderr, "Could not get device with devid %d [%s:%d]\n",devid,__FILE__,__LINE__));
return;
}
if ((err=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0) {
ERROR_CMD(fprintf(stderr, "pthread_setcanceltype failed (%s) [%s:%d]\n",strerror(err),__FILE__,__LINE__));
return;
}
if ((err=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) != 0) {
ERROR_CMD(fprintf(stderr, "pthread_setcancelstate (%s) failed [%s:%d]\n",strerror(err),__FILE__,__LINE__));
return;
}
DEBUG_CMD(printf("NIC: offline thread running, device %d [%s:%d]\n",devid,__FILE__,__LINE__));
/////
//Read pcap header
c=read(i->file,&head,sizeof(struct pcap_file_header));
c=read(i->file,buf,BUFSIZE);
while(c>0)
{
left=process_pkts(buf,c+left,i,devid,c);
memcpy(buf,b+c-left,left);
b=buf+left;
c=read(i->file,b,BUFSIZE-left);
}
mapid_finished(&i->mapidlib);
DEBUG_CMD(printf("Finished reading file, pkts %lld [%s:%d]\n",(unsigned long long)i->hwinfo.pkts,__FILE__,__LINE__));
}
int
mapidrv_connect (int devid,int fd)
{
nic_instance_t *i=flist_get(devlist,devid);
int ret=mapid_connect(&i->mapidlib,fd);
DEBUG_CMD(printf("NIC: connecting flow %d [%s:%d]\n",fd,__FILE__,__LINE__));
if(i->hwinfo.offline>0)
{
pthread_create(&i->th_proc, &i->th_attr, (void *) mapidrv_offline_proc_loop, (void*)i->id);
}
return ret;
}
int
mapidrv_read_results(int devid,int fd, int fid, int pid, mapid_result_t** result)
{
nic_instance_t *i=flist_get(devlist,devid);
return mapid_read_results(&i->mapidlib,fd,fid,pid,result);
}
int mapidrv_load_library(MAPI_UNUSED int devid,char* lib)
{
return mapid_load_library(lib);
}
int
mapidrv_create_flow (int devid, int fd, char **devtype)
{
char errbuf[PCAP_ERRBUF_SIZE];
nic_instance_t *i=flist_get(devlist,devid);
char *dev=i->device;
char *path;
struct pcap_file_header head;
DEBUG_CMD(printf("NIC: creating flow [%s:%d]\n",__FILE__,__LINE__));
/**************************************************************/
/**** Initialise CBUF if it's the first time we get called ****/
/**************************************************************/
if ( i->NIC_cbuf == NULL && i->hwinfo.offline!=1)
{
path=strdup(CBUF_PATH);
mktemp(path);
DEBUG_CMD(printf("file: %s [%s:%d]\n",path,__FILE__,__LINE__));
if ( touch_file(path) != 0 )
{
ERROR_CMD(printf("cbuf shm pathname: %s [%s:%d]\n",strerror(errno),__FILE__,__LINE__));
return MAPI_SHM_ERR;
}
strncpy(i->shm_fname,path,MAPI_STR_LENGTH);
if ( (i->NIC_cbuf_mem.src.shm.key = ftok(path,CBUF_ID)) < 0 )
{
ERROR_CMD(printf("NIC create flow(ftok): %s [%s:%d]\n",strerror(errno),__FILE__,__LINE__));
return MAPI_SHM_ERR;
}
if ( (i->NIC_cbuf = cbuf_new(CBUF_SLOTS,NIC_PKTCAP_LEN+sizeof(struct mapid_pkthdr),shm_alloc,&i->NIC_cbuf_mem)) == NULL )
{
ERROR_CMD(printf("NIC create flow(cbuf_new) [%s:%d]",__FILE__,__LINE__));
return ENOMEM;
}
free(path);
DEBUG_CMD2(printf("NIC: CBUF created [%s:%d]\n",__FILE__,__LINE__));
}
// else changed by danton
//Open device if it is not already open
if ( i->pcap == NULL || i->hwinfo.offline==0)
{
// Offline flow
if(i->offline_format==MFF_PCAP)
{
i->hwinfo.offline = 1;
//Read pcap_header header from file
if(read(i->file,&head,sizeof(struct pcap_file_header))!=sizeof(struct pcap_file_header))
return MAPI_ERROR_FILE;
if(head.magic!=2712847316U || head.version_major!=2)
return MAPI_ERROR_FILE;
i->hwinfo.link_type=head.linktype;
}
// Online flow
else
{
DEBUG_CMD2(printf("NIC: pcap_open_live(%s) [%s:%d]\n",dev,__FILE__,__LINE__));
*devtype = i->hwinfo.devtype = MAPI_DEVICE_NIC;
if( (i->pcap = pcap_open_live(dev,NIC_PKTCAP_LEN,1,0,errbuf)) == NULL )
{
ERROR_CMD(fprintf(stderr,"pcap_open_live: %s [%s:%d]\n",errbuf,__FILE__,__LINE__));
return PCAP_OPEN_ERR;
}
if ( pcap_setnonblock(i->pcap,0,errbuf) != 0 )
{
ERROR_CMD(fprintf(stderr,"pcap_setnonblock: %s [%s:%d]\n",errbuf,__FILE__,__LINE__));
return PCAP_OPEN_ERR;
}
}
i->hwinfo.link_type = pcap_datalink(i->pcap);
i->hwinfo.cap_length = pcap_snapshot(i->pcap);
i->hwinfo.adapterinfo = i->NIC_cbuf;
i->hwinfo.devid=i->id;
i->hwinfo.pkts=0;
//Start processing thread
if (pthread_attr_init (&i->th_attr) != 0)
{
ERROR_CMD(fprintf (stderr, "pthread_attr_init failed [%s:%d]\n",__FILE__,__LINE__));
return NICDRV_PTHR_ERR;
}
if( i->hwinfo.offline == 0 )
{
//start fetchthread, if offline_flow, thread will be started on connect.
if (pthread_create
(&i->th_proc, &i->th_attr, (void *) mapidrv_proc_loop, (void*)devid) != 0)
{
ERROR_CMD(fprintf (stderr, "pthread_create failed [%s:%d]\n",__FILE__,__LINE__));
return NICDRV_PTHR_ERR;
}
}
}
else
*devtype = MAPI_DEVICE_NIC;
return mapid_add_flow(&i->mapidlib,fd,&i->hwinfo,NULL);
}
int
mapidrv_create_offline_flow (int devid, int format,int fd,char **devtype)
{
nic_instance_t *i=flist_get(devlist,devid);
i->hwinfo.offline=1;
if(format==MFF_PCAP) {
i->offline_format=format;
//This should be read from the file
i->hwinfo.link_type=DLT_EN10MB;
i->hwinfo.cap_length=1500;
*devtype = i->hwinfo.devtype = MAPI_DEVICE_ALL;
i->hwinfo.devid=i->id;
i->hwinfo.pkts=0;
DEBUG_CMD(printf("Reading from trace file: %s [%s:%d]\n",i->device,__FILE__,__LINE__));
return mapid_add_flow(&i->mapidlib,fd,&i->hwinfo,NULL);
}
return 0;
}
int mapidrv_add_device(mapi_offline_device_status_t *olstatus,char *devname, int file,int devid, function_manipulation_t* manip)
{
nic_instance_t *i=malloc(sizeof(nic_instance_t));
manipulation = manip;
i->device=strdup(devname);
i->id=devid;
i->init=0;
i->file=file;
i->pcap=NULL;
i->th_proc=0;
i->hwinfo.offline=0;
i->hwinfo.pkt_drop=0;
i->offline_format=-1;
i->NIC_cbuf = NULL;
i->pkts=0;
i->offline_status = olstatus;
i->hwinfo.ff_list=malloc(sizeof(flist_t));
flist_init(i->hwinfo.ff_list);
DEBUG_CMD(printf("Added device %d: %s [%s:%d]\n",devid,devname,__FILE__,__LINE__));
flist_append(devlist,devid,i);
mapid_init(&i->mapidlib);
return 0;
}
int
mapidrv_close_flow (int devid,int fd)
{
nic_instance_t *i=flist_get(devlist,devid);
return mapid_close_flow (&i->mapidlib,fd);
}
int mapidrv_get_flow_info(int devid,int fd,mapi_flow_info_t *info) {
nic_instance_t *i=flist_get(devlist,devid);
return mapid_get_flow_info(&i->mapidlib,fd,info);
}
mapid_funct_info_t* mapidrv_get_flow_functions(int devid,int fd)
{
nic_instance_t *i=flist_get(devlist,devid);
return mapid_get_flow_functions(&i->mapidlib,fd);
}
int mapidrv_delete_device(int devid)
{
nic_instance_t *i;
pthread_spin_lock(&devlist_lock);
i=flist_remove(devlist,devid);
pthread_spin_unlock(&devlist_lock);
if (i!=NULL) {
int err=0;
if (i->th_proc && pthread_equal(i->th_proc, pthread_self())==0) {
DEBUG_CMD(printf("Calling thread != th_proc (%lu != %lu), canceling [%s:%d]\n",i->th_proc,pthread_self(),__FILE__,__LINE__));
fflush(stdout);
if ((err=pthread_cancel(i->th_proc))!=0) {
if (!(i->hwinfo.offline!=0 && err==ESRCH)) {
WARNING_CMD(printf("Could not join thread for devid %d (%s) [%s:%d]\n",devid,strerror(err),__FILE__,__LINE__));
fflush(stdout);
}
}
if ((err=pthread_join(i->th_proc,NULL))!=0) {
if (!(i->hwinfo.offline!=0 && err==ESRCH)) {
WARNING_CMD(printf("Could not join thread for devid %d (%s) [%s:%d]\n",devid,strerror(err),__FILE__,__LINE__));
fflush(stdout);
}
}
}
// free: i->NIC_cbuf, i->pcap
if (i->pcap!=NULL) {
DEBUG_CMD(printf("pcap handle closed [%s:%d]\n",__FILE__,__LINE__));
pcap_close(i->pcap);
}
if (i->NIC_cbuf!=NULL) {
if (remove(i->shm_fname)<0) {
WARNING_CMD(printf("Could not remove semaphore file %s (%s) [%s:%d]",i->shm_fname,strerror(errno),__FILE__,__LINE__));
}
cbuf_destroy(i->NIC_cbuf,shm_free);
}
mapid_destroy(&i->mapidlib);
flist_destroy(i->hwinfo.ff_list);
free(i->hwinfo.ff_list);
free(i->device);
free(i);
} else {
ERROR_CMD(printf("Could not find and remove devid %d [%s:%d]\n",devid,__FILE__,__LINE__));
return -1;
}
return 0;
}
mapi_function_def_mini_t*
mapidrv_get_function_info(int libnumber,int functionnumber)
{
return mapid_get_function_info(libnumber, functionnumber);
}
char*
mapidrv_get_lib_name(int libnumber)
{
return mapid_get_lib_name(libnumber);
}
__attribute__ ((constructor))
void init ()
{
devlist=malloc(sizeof(flist_t));
flist_init(devlist);
pthread_spin_init(&devlist_lock,PTHREAD_PROCESS_SHARED);
DEBUG_CMD(printf ("NIC driver loaded [%s:%d]\n",__FILE__,__LINE__));
}
__attribute__ ((destructor))
void fini ()
{
unlink(CBUF_PATH);
free(devlist);
//TODO: Loop through all devices and free the NIC_cbuf
// if ( NIC_cbuf )
// cbuf_destroy(NIC_cbuf,shm_free);
DEBUG_CMD(printf ("NIC driver unloaded [%s:%d]\n",__FILE__,__LINE__));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment