Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Arne Øslebø
mapi
Commits
f33e5498
Commit
f33e5498
authored
Sep 19, 2006
by
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
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/
drivers
/cbuf.c
→
src/
common
/cbuf.c
View file @
f33e5498
File moved
src/
drivers
/cbuf.h
→
src/
common
/cbuf.h
View file @
f33e5498
File moved
src/drivers/mapinicdrv_buf.c
deleted
100644 → 0
View file @
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__
));
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment