mapinicdrv.c 11.3 KB
Newer Older
Arne Øslebø's avatar
Arne Øslebø committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#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 <netinet/in.h>
#include <pcap.h>
#include "mapi.h"
#include "mapidrv.h"
#include "mapidlib.h"

#include "mapidevices.h"
#include "flist.h"
#include "debug.h"

#define ETHSTR     "eth"
#define LOSTR      "lo"

#define BUFSIZE 32768

#define NIC_PKTCAP_LEN 1500

__attribute__ ((constructor)) void init ();
__attribute__ ((destructor))  void fini ();

typedef struct nic_instance {
  pthread_attr_t th_attr;
  pthread_t th_proc;
  pcap_t *pcap;
  int eventset;
  void *buf;
  int file;
  char *name;
  int id;
's avatar
committed
42
  mapi_offline_device_status_t *offline_status;
Arne Øslebø's avatar
Arne Øslebø committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  mapid_hw_info_t hwinfo;
  mapidlib_instance_t mapidlib;
} nic_instance_t;

flist_t *devlist;

/* for mapidlib errorcode */
int 
mapidrv_get_errno(int devid,int fd)
{
  nic_instance_t *i=flist_get(devlist,devid);
  return mapid_get_errno(&i->mapidlib,fd);
}

int
58
mapidrv_apply_function (int devid,int fd, char* function, mapiFunctArg *fargs)
Arne Øslebø's avatar
Arne Øslebø committed
59
60
{
  nic_instance_t *i=flist_get(devlist,devid);
61
  return mapid_apply_function(&i->mapidlib,fd, function, fargs);
Arne Øslebø's avatar
Arne Øslebø committed
62
63
}

64
int mapidrv_add_device(mapi_offline_device_status_t* olstatus,char *devname, int file,int devid, global_function_list_t *gflist)
Arne Øslebø's avatar
Arne Øslebø committed
65
66
67
68
69
70
71
72
{
  nic_instance_t *i=malloc(sizeof(nic_instance_t));
  i->name=strdup(devname);
  i->id=devid;
  i->pcap=NULL;
  i->file=file;
  i->th_proc=0;
  i->hwinfo.offline=0;
73
  i->hwinfo.gflist=gflist;
's avatar
committed
74
75
76
  i->offline_status = olstatus;
  if(devid<0)
    i->hwinfo.offline=1;
Arne Øslebø's avatar
Arne Øslebø committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  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_delete_device(int devid)
{
  nic_instance_t *i=flist_remove(devlist,devid,FLIST_LEAVE_DATA);
  
  if (i!=NULL) {
    int err=0;

91
92
    //    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__));
Arne Øslebø's avatar
Arne Øslebø committed
93
94
      fflush(stdout);
      
95
96
      if(i->th_proc) {

Arne Øslebø's avatar
Arne Øslebø committed
97
      if ((err=pthread_cancel(i->th_proc))!=0) {
's avatar
committed
98
        if (!(i->hwinfo.offline>2 && err==ESRCH)) {
Arne Øslebø's avatar
Arne Øslebø committed
99
100
101
102
103
104
105
106
107
108
109
          WARNING_CMD(printf("Could not cancel 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==1 && err==ESRCH)) {
          WARNING_CMD(printf("Could not join thread for devid %d (%s) [%s:%d]\n",devid,strerror(err),__FILE__,__LINE__));
          fflush(stdout);
        }
      }
110
111
112
113

      if ((err=pthread_attr_destroy(&i->th_attr))!=0)
	WARNING_CMD(printf("Could not destroy threads attribute object for devid %d (%s) [%s:%d]\n",devid,strerror(err),__FILE__,__LINE__));      
    
Arne Øslebø's avatar
Arne Øslebø committed
114
115
116
117
118
119
120
121
122
123
124
125
126
    }
   
    if (i->hwinfo.offline==0) {
      if (i->pcap != NULL) {
	pcap_close(i->pcap);
        DEBUG_CMD(printf("Closed pcap handle [%s:%d]\n",__FILE__,__LINE__));
      }
    } else {
      if (i->file) {
        close(i->file);
        DEBUG_CMD(printf("Closed file [%s:%d]\n",__FILE__,__LINE__));
      }
    }
127

Arne Øslebø's avatar
Arne Øslebø committed
128
129
    mapid_destroy(&i->mapidlib);
    free(i->name);
's avatar
committed
130
131
    if(i->offline_status!=NULL)
      *(i->offline_status) = DEVICE_DELETED;
Arne Øslebø's avatar
Arne Øslebø committed
132
    free(i);
's avatar
committed
133
134
  } 

Arne Øslebø's avatar
Arne Øslebø committed
135
136
137
138
  return 0;
}

static unsigned 
139
process_pkts(void *buf,unsigned len, nic_instance_t *i,MAPI_UNUSED int devid, int last)
Arne Øslebø's avatar
Arne Øslebø committed
140
141
142
143
{
    unsigned c = 0;
  int rlen = 0;
  struct pcap_pkthdr *rec;
's avatar
committed
144
  unsigned char *packet;
Arne Øslebø's avatar
Arne Øslebø committed
145
146
147
148
149
150
151
152
153
154
155
156
157
  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;
158
      mhdr.ts = (((unsigned long long)rec->ts.tv_sec)<<32)+((rec->ts.tv_usec*4295) & 0xffffffff);
Arne Øslebø's avatar
Arne Øslebø committed
159
160
161
162
163
164
165
166
      //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)
's avatar
committed
167
		i->hwinfo.offline=3;
Arne Øslebø's avatar
Arne Øslebø committed
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
      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)
{
  char buf[BUFSIZE];
  char *b=buf;
  int left=0,c;
  nic_instance_t *i=flist_get(devlist,devid);
  int err;
  struct pcap_file_header head;
's avatar
committed
189
  *(i->offline_status) = DEVICE_READING;
Arne Øslebø's avatar
Arne Øslebø committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

  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;
  }

  //Read pcap header
  c=read(i->file,&head,sizeof(struct pcap_file_header));

  c=read(i->file,b,BUFSIZE);
205
  while(c>0) {    
Arne Øslebø's avatar
Arne Øslebø committed
206
207
208
209
210
211
212
213
    left=process_pkts(buf,c+left,i,devid,c);
    //Copy last bytes to beginning of buffer
    memcpy(buf,b+c-left,left);
    b=buf+left;

    c=read(i->file,b,BUFSIZE-left);
  }
  mapid_finished(&i->mapidlib);
's avatar
committed
214
  *(i->offline_status) = DEVICE_FINISHED;
Arne Øslebø's avatar
Arne Øslebø committed
215
216
217
218
219
220
  DEBUG_CMD(printf("Finished reading file, pkts %lld [%s:%d]\n",i->hwinfo.pkts,__FILE__,__LINE__));
}

static void
mapidrv_proc_loop (int devid)
{
's avatar
committed
221
  u_char *packet;
Arne Øslebø's avatar
Arne Øslebø committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  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;
  }

  while (1)
    {
's avatar
committed
239
      while( (packet = (u_char *)pcap_next(i->pcap,&phdr)) == NULL );
Arne Øslebø's avatar
Arne Øslebø committed
240
241
242
243
244
      
      // Transform header
      // This is only for backward compatibility
      mhdr.caplen = phdr.caplen;
      mhdr.wlen = phdr.len;
245
      mhdr.ts = (((unsigned long long)phdr.ts.tv_sec)<<32)+((phdr.ts.tv_usec*4295) & 0xffffffff);
Arne Øslebø's avatar
Arne Øslebø committed
246
247
248
249
250
251
      
      // increase counter for packets seen so far
      i->hwinfo.pkts++;
      
      // Process packet
      mapid_process_pkt(&i->mapidlib,packet,packet,&mhdr);
's avatar
committed
252
      
Arne Øslebø's avatar
Arne Øslebø committed
253
254
255
256
    }
 }

int
257
mapidrv_read_results (int devid,int fd, int fid, mapid_result_t** result)
Arne Øslebø's avatar
Arne Øslebø committed
258
259
{
  nic_instance_t *i=flist_get(devlist,devid);
260
  return mapid_read_results(&i->mapidlib,fd,fid,result);
Arne Øslebø's avatar
Arne Øslebø committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
}

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_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);
}

int
mapidrv_create_offline_flow (int devid, int format,int fd,char **devtype)
{
  nic_instance_t *i=flist_get(devlist,devid);

  *devtype=MAPI_DEVICE_NIC;
's avatar
committed
280
  i->hwinfo.offline=4;
Arne Øslebø's avatar
Arne Øslebø committed
281
282
283
284

  if(format==MFF_PCAP) {
    //This should be read from the file
    i->hwinfo.link_type=DLT_EN10MB;
285
    i->hwinfo.cap_length=1514;
Arne Øslebø's avatar
Arne Øslebø committed
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    i->hwinfo.devtype=MAPI_DEVICE_NIC;
    i->hwinfo.devid=i->id;
    i->hwinfo.pkts=0;

    DEBUG_CMD(printf("Reading from trace file: %s [%s:%d]\n",i->name,__FILE__,__LINE__));

    return mapid_add_flow(&i->mapidlib,fd,&i->hwinfo,NULL);
  }

  return 0;
}

int
mapidrv_create_flow (int devid, int fd, char **devtype)
{
  nic_instance_t *i=flist_get(devlist,devid);
  char errbuf[PCAP_ERRBUF_SIZE];

's avatar
committed
304
  //i->hwinfo.offline=0;
Arne Øslebø's avatar
Arne Øslebø committed
305
306

  *devtype=MAPI_DEVICE_NIC;
's avatar
committed
307
308
309
310
311
312
313
314
315
316
  if(i->hwinfo.offline > 0)
  {
    //This should be read from the file
    i->hwinfo.link_type=DLT_EN10MB;
    i->hwinfo.cap_length=1500;
    i->hwinfo.devtype=MAPI_DEVICE_NIC;
    i->hwinfo.devid=i->id;
    i->hwinfo.pkts=0;

    DEBUG_CMD(printf("Reading from trace file: %s [%s:%d]\n",i->name,__FILE__,__LINE__));
Arne Øslebø's avatar
Arne Øslebø committed
317

's avatar
committed
318
319
320
    return mapid_add_flow(&i->mapidlib,fd,&i->hwinfo,NULL);
  }
  	
Arne Øslebø's avatar
Arne Øslebø committed
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  //Open device if it is not already open
  if (i->pcap==NULL)
  {
    if( (i->pcap = pcap_open_live(i->name,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;
      }
          
      i->hwinfo.link_type = pcap_datalink(i->pcap);
      i->hwinfo.cap_length = pcap_snapshot(i->pcap);
      i->hwinfo.devid=i->id;
      i->hwinfo.pkts=0;
      i->hwinfo.devtype=MAPI_DEVICE_NIC;

      //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 (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 DAGDRV_PTHR_ERR;
    	}    
    }
  return   mapid_add_flow(&i->mapidlib,fd,&i->hwinfo,NULL);
}

int
mapidrv_connect (int devid,int fd)
{
  nic_instance_t *i=flist_get(devlist,devid);
's avatar
committed
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  int ret = mapid_connect(&i->mapidlib,fd);
  if(i->hwinfo.offline==4) {
    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 (pthread_create
		(&i->th_proc, &i->th_attr, (void *) mapidrv_offline_proc_loop, (void *)i->id) != 0)
      {
		ERROR_CMD(fprintf (stderr, "pthread_create failed [%s:%d]\n",__FILE__,__LINE__));
		return NICDRV_PTHR_ERR;
      }    
  }
  return ret;
}
Arne Øslebø's avatar
Arne Øslebø committed
373

's avatar
committed
374
375
376
377
378
int 
mapidrv_start_offline_device( int devid)
{
  nic_instance_t *i = flist_get(devlist,devid);
  
Arne Øslebø's avatar
Arne Øslebø committed
379
380
381
  if(i->hwinfo.offline==1) {
    if (pthread_attr_init (&i->th_attr) != 0)
      {
's avatar
committed
382
383
		ERROR_CMD(fprintf (stderr, "pthread_attr_init failed [%s:%d]\n",__FILE__,__LINE__));
		return NICDRV_PTHR_ERR;
Arne Øslebø's avatar
Arne Øslebø committed
384
385
      }
    if (pthread_create
's avatar
committed
386
		(&i->th_proc, &i->th_attr, (void *) mapidrv_offline_proc_loop, (void *)i->id) != 0)
Arne Øslebø's avatar
Arne Øslebø committed
387
      {
's avatar
committed
388
389
		ERROR_CMD(fprintf (stderr, "pthread_create failed [%s:%d]\n",__FILE__,__LINE__));
		return NICDRV_PTHR_ERR;
Arne Øslebø's avatar
Arne Øslebø committed
390
391
      }    
  }
's avatar
committed
392
393
  return 0;
}
Arne Øslebø's avatar
Arne Øslebø committed
394

's avatar
committed
395
396
397
398




's avatar
committed
399
mapi_function_def_mini_t*
's avatar
committed
400
401
402
403
404
mapidrv_get_function_info(int libnumber,int functionnumber)
{
	return mapid_get_function_info(libnumber, functionnumber);
}

405
unsigned char*
's avatar
committed
406
407
mapidrv_get_lib_name(int libnumber)
{
408
	return (unsigned char*)mapid_get_lib_name(libnumber);
Arne Øslebø's avatar
Arne Øslebø committed
409
410
411
412
}



's avatar
committed
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471



























































Arne Øslebø's avatar
Arne Øslebø committed
472
473
474
475
int
mapidrv_close_flow (int devid,int fd)
{
  nic_instance_t *i=flist_get(devlist,devid);
Arne Øslebø's avatar
Arne Øslebø committed
476
  if(i==NULL)
Arne Øslebø's avatar
Arne Øslebø committed
477
  	return -1;
Arne Øslebø's avatar
Arne Øslebø committed
478
479
480
481
  return mapid_close_flow(&i->mapidlib,fd);
}

int 
482
mapidrv_load_library(MAPI_UNUSED int devid,char* lib)
Arne Øslebø's avatar
Arne Øslebø committed
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
{
  return mapid_load_library(lib);
}


__attribute__ ((constructor))
     void init ()
{
  devlist=malloc(sizeof(flist_t));
  flist_init(devlist);
  DEBUG_CMD(printf ("NIC driver loaded [%s:%d]\n",__FILE__,__LINE__));
}

__attribute__ ((destructor))
     void fini ()
{
's avatar
committed
499

Arne Øslebø's avatar
Arne Øslebø committed
500
501
502
503
  free(devlist);
  DEBUG_CMD(printf ("NIC driver unloaded [%s:%d]\n",__FILE__,__LINE__));
}