Commit bf0032f6 authored by 's avatar

The dagflib's PKT_COUNTER extended to use the DSM hardware counters in the

DAG cards. Function must be applied after DSM BPF_FILTER.
 
Load balacing parameter dsm_load_balancing of mapi.conf for DSM (based on
crc32, parity and interface), influences the generated XML configuration.

New disable_dsm_xml_remove=0|1 debugging parameter to mapi.conf. Generated
XML config in /tmp will not be removed.                                   

Some bugfixes.

Update of appropriate manpages, see details there.



git-svn-id: file:///home/svn/mapi/trunk@1266 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent c6fe1d34
......@@ -11,4 +11,6 @@ description=Offline dag-capture
[dag]
ipf_loader_bin=dag_ipf_loader.sh
dsm_loader_bin=/path/to/dsm_loader
dsm_load_balancing=none
disable_dsm=0
disable_dsm_xml_remove=0
.TH "BPF2DAGDSM" 1 "April 2007"
.SH NAME
bpf2dagdsm \- convert multiple BPF expressions to Endace DSM filter XML specification
bpf2dagdsm \- convert the set of BPF expressions to Endace DSM filter XML specification
.SH "SYNOPSIS"
.ad l
.hy 0
......@@ -11,47 +11,46 @@ bpf2dagdsm \- convert multiple BPF expressions to Endace DSM filter XML specific
.SH "DESCRIPTION"
Note: For complete understanding this text you should read the DAG card
documents first, particularly the one about \fBData Stream Management\fR
(DSM).
Note: To fully understand this manual page please read the DAG card documents
first, particularly the one referring to \fBData Stream Management\fR (DSM).
This program converts the Berkeley Packet Filter (\fBBPF\fR) expressions
(well-known as used by \fItcpdump\fR(8)) to \fBXML\fR filter configuration for
Endace \fBDAG\fR cards that are using the \fBDSM\fR classification. The
resulting XML file can be used as the input for Endace's
\fIdsm_loader\fR executable to program the hardware filter.
(well-known as the expressions of \fItcpdump\fR(8)) to \fBXML\fR filter
configuration for Endace \fBDAG\fR cards with the \fBDSM\fR classification.
The resulting XML file can be used as the input for Endace's \fIdsm_loader\fR
executable to set up the hardware filter.
The input is expected on stdin; one complete BPF expression per line (empty
lines are ignored, but counted). Each expression is parsed, compiled into
internal node tree, transformed to Disjunctive Normal Form (DNF, that is
OR-of-ANDs) and broken down to atomic filters.
The input is expected on stdin with one complete BPF expression per line
(empty lines are ignored, but counted). Each expression is parsed, compiled
into internal node tree, transformed to Disjunctive Normal Form (DNF, that
is OR-of-ANDs) and broken down to atomic filters.
For each atomic filter one DAG hardware filter is used. The resulting single
XML configuration file (printed on stdout) describes all analyzed BPF
expressions.
For each atomic filter one DAG hardware filter is occupied. The resulting
single XML configuration file is printed on stdout and describes all
parsed BPF expressions.
After each group of <filter> elements is followed by the XML <!--comment-->
block. It contains lines like this one (started with special text tag):
Each group of <filter> elements is followed by the XML <!--comment--> block
containing lines like this one (started with special text tag):
$DAG-DSM-TAG$ bpf-index:3 filters-used:00110000
The `\fBbpf-line-number\fR' value is the number of the input line the BPF
expression was on. The `\fBfilters-used\fR' is the bit array describing the
association between the BPF expression and hardware filters. The filters are
indexed from zero on the left side. The line above says that the hardware
filters #2 and #3 was allocated for BPF expression on input line 3.
On the next comment line the originating BPF expression is copied (not
shown here).
The `\fBbpf-index\fR' value is the number of the physical input line
contained the BPF expression. The `\fBfilters-used\fR' is the bit array
describing the association between the BPF expression and hardware filters.
The filters are indexed from zero on the left side. The line above says that
the hardware filters #2 and #3 was allocated for BPF expression on input
line 3. On the next comment line the originating BPF expression is copied
(not shown here).
The line tagged with $DAG-DSM-TAG$ helps the caller to quickly re-analyze the
XML output, construct the filter bitmasks and match triggered filters back with
BPF expressions. For easy parsing, both values on tagged line are preceded
by the colon (:) and followed by a tab character.
The line tagged with $DAG-DSM-TAG$ helps the caller to quickly re-analyze
the XML output, construct the filter bitmasks and match triggered filters
back with BPF expressions. To ease the parsing, both values on tagged line
are preceded by the colon (:) and followed by the tab character.
The entire XML configuration is finalized in the way that all packets matching
at least one hardware filter are passed to DAG stream 0 (first input stream).
Other packets are dropped, but see the option --always-match below for
exception.
The definition at the bottom of the XML configuration instructs the filter
to pass all packets matching at least one hardware filter to DAG stream 0
(first input stream). Other packets are dropped, but see the option
\fB--always-match\fR below for exception.
.SH "OPTIONS"
......@@ -60,29 +59,28 @@ exception.
When the caller knows the number of hardware filters supported by the DAG card
before calling the \fIbpf2dagdsm\fR, that number can be passed using this option.
When the total number of filters needed by analyzed configuration exceeds the
max-filters value, no XML output is printed. Instead the appropriate error
message is sent do stderr and return code is nonzero.
When the analyzed configuration exceeds this number, no XML output is printed.
Instead the error message is sent do stderr and return code is nonzero.
This is the safety measure, because the \fIdsm_loader\fR blindly loads
everything until all hardware filters are filled and omits the rest.
Then this damaged DAG card configuration is activated. This option allows for
detection of such error and skipping the call of \fIdsm_loader\fR.
detection of such error and skipping the bogus call of \fIdsm_loader\fR.
.TP
\fB--always-match\fR
This options merely adds one final OR-able condition to the partials hardware
This options merely adds one final OR-ed condition to the partials hardware
lookup table: the negation of the first defined filter.
The result is, that all packets (even those not matching the previous filters)
are also accepted (not filtered out by the DAG card). The triggered filters
can still be recognized by analyzing the ERF header. Using this option, the
As result, all packets (even those not matching the previous filters) are
also accepted (not filtered out by the DAG card). The triggered filters can
still be distinguished by analyzing the ERF header. Using this option, the
DAG card stops filtering and becomes the packet classification machine.
.SH "RESTRICTIONS"
Unfortunately, only a subset of BPF expression features is implemented. This
is mainly due to the fact that the original BPF is a machine language,
is mainly due to the fact that the original BPF is fed to a machine,
processing the true algorithm for each examined packet. On the other hand,
DSM-driven hardware can only match static bitmasked filters. So all BPF
constructs that require "runtime" computation must have been omited.
......@@ -106,6 +104,6 @@ Error occured or help text printed. The problem is described on stderr.
.SH TODO
The program should be able to re-use duplicate filters, probably by comparing
The program should be able to re-use duplicated filters, probably by comparing
their string representation generated by function print_node().
This diff is collapsed.
......@@ -121,7 +121,7 @@ int main(int argc, char **argv)
fatal("%s: The number of filters needed (%d) exceeds the given limit (%d).\n", argv[0], filter_count, max_filters);
/* Write the filter to DAGDSM configuration output file. */
output = dagdsm_bpf_xprintf(filter, always_match);
output = dagdsm_bpf_xprintf(filter, always_match, BALANCE_NONE);
/* Free resources allocated for the filter. */
if (filter != NULL)
......
......@@ -372,7 +372,7 @@ dagdsm_bpf_filter_t *dagdsm_bpf_compile(dagdsm_bpf_filter_t *bpf_filter, char *b
/*
* Write filter to FILE
*/
char *dagdsm_bpf_xprintf(dagdsm_bpf_filter_t *bpf_filter, int always_match)
char *dagdsm_bpf_xprintf(dagdsm_bpf_filter_t *bpf_filter, int always_match, bal_t load_balancing)
{
dstring_t s;
char *retval;
......@@ -430,12 +430,68 @@ char *dagdsm_bpf_xprintf(dagdsm_bpf_filter_t *bpf_filter, int always_match)
}
}
dsprintf(&s, " </partial>\n"
" <stream>\n"
" <number>0</number>\n"
" <stream-component>all-filters</stream-component>\n"
" </stream>\n");
dsprintf(&s, " </partial>\n");
if (load_balancing == BALANCE_NONE) {
dsprintf(&s, " <stream>\n"
" <number>0</number>\n"
" <stream-component>all-filters</stream-component>\n"
" </stream>\n");
} else if ((load_balancing == BALANCE_CRC32) || (load_balancing == BALANCE_PARITY)) {
char *baltype = (load_balancing == BALANCE_CRC32) ? "crc32" : "parity";
dsprintf(&s, " <steering>\n"
" <name>steer-%s</name>\n"
" <algorithm>%s</algorithm>\n"
" </steering>\n"
" <partial>\n"
" <name>balancer</name>\n"
" <partial-component>steer-%s</partial-component>\n"
" </partial>\n"
" <stream>\n"
" <number>0</number>\n"
" <stream-component>all-filters</stream-component>\n"
" <stream-component>balancer</stream-component>\n"
" </stream>\n"
" <stream>\n"
" <number>2</number>\n"
" <stream-component>all-filters</stream-component>\n"
" <stream-component invert=\"true\">balancer</stream-component>\n"
" </stream>\n", baltype, baltype, baltype);
} else { /* BALANCE_INTERFACE */
dsprintf(&s, " <interface>\n"
" <name>iface0</name>\n"
" <number>0</number>\n"
" </interface>\n"
" <interface>\n"
" <name>iface1</name>\n"
" <number>1</number>\n"
" </interface>\n"
" <partial>\n"
" <name>partial-iface0</name>\n"
" <partial-component>iface0</partial-component>\n"
" </partial>\n"
" <partial>\n"
" <name>partial-iface1</name>\n"
" <partial-component>iface1</partial-component>\n"
" </partial>\n"
" <stream>\n"
" <number>0</number>\n"
" <stream-component>all-filters</stream-component>\n"
" <stream-component>partial-iface0</stream-component>\n"
" </stream>\n"
" <stream>\n"
" <number>2</number>\n"
" <stream-component>all-filters</stream-component>\n"
" <stream-component>partial-iface1</stream-component>\n"
" </stream>\n");
}
dsprintf(&s, "</dsm-config>\n");
retval = dsstrdup(&s);
......
......@@ -49,6 +49,8 @@
typedef struct combo6_bpf_filter combo6_bpf_filter_t;
typedef struct dagdsm_bpf_filter dagdsm_bpf_filter_t;
typedef enum { BALANCE_NONE, BALANCE_CRC32, BALANCE_PARITY, BALANCE_INTERFACE } bal_t;
/*
* Compile bpf filter functions
*/
......@@ -59,7 +61,7 @@ dagdsm_bpf_filter_t *dagdsm_bpf_compile(dagdsm_bpf_filter_t *filter, char *buf,
* Write filter to the text format
*/
char *combo6_bpf_xprintf(combo6_bpf_filter_t *filter);
char *dagdsm_bpf_xprintf(dagdsm_bpf_filter_t *filter, int always_match);
char *dagdsm_bpf_xprintf(dagdsm_bpf_filter_t *filter, int always_match, bal_t load_balancing);
/*
* Other functions
......
......@@ -108,7 +108,7 @@ void test_dagdsm(char *bpf, int always_match)
fprintf(stderr, "DAG DSM filter:\n");
/* Translate filter to DAGDSM configuration. */
output = dagdsm_bpf_xprintf(filter, always_match);
output = dagdsm_bpf_xprintf(filter, always_match, BALANCE_NONE);
/* Free resources allocated for the filter */
dagdsm_bpf_free(filter);
......
......@@ -17,7 +17,7 @@ static int bytecounter_get_result(mapidflib_function_instance_t* instance,
dagstat_instance_t *i = instance->internal_data;
dag_counter_t cnt[2];
dag_get_stats(instance->hwinfo->adapterinfo, i->which_port, cnt);
dag_get_port_counts(instance->hwinfo->adapterinfo, i->which_port, cnt);
*(dag_counter_t *)instance->result.data = cnt[1] - i->initial_counts[1];
*res = &instance->result; // must point to actual value
......
......@@ -19,6 +19,7 @@
#include "dagnew.h"
#include "dagapi.h"
#include "dagutil.h"
#include "dagdsm.h"
#include "dag_config.h"
#include "dag_component.h"
#include "mapidagdrv.h"
......
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
......@@ -17,8 +20,11 @@
*
* 1) the DAG card returns just the increment from the last reading,
* 2) we want to provide these functions to multiple concurrent flows.
*
* This function is suitable for BEFORE_MODIFILTER kind of counting
* functions, because it measures early counts (before DSM filtering).
*/
int dag_get_stats(dag_adapterinfo_t *di,
int dag_get_port_counts(dag_adapterinfo_t *di,
int which_port,
dag_counter_t *result)
{
......@@ -51,13 +57,13 @@ int dag_get_stats(dag_adapterinfo_t *di,
uuid = dag_component_get_attribute_uuid(port, rxpkt_attr);
d = di->counters + 2*portidx + 0;
d = di->port_counters + 2*portidx + 0;
*d += dag_config_get_uint64_attribute(di->card, uuid);
*(result+0) += *d;
uuid = dag_component_get_attribute_uuid(port, kUint64AttributeRxBytes);
d = di->counters + 2*portidx + 1;
d = di->port_counters + 2*portidx + 1;
*d += dag_config_get_uint64_attribute(di->card, uuid);
*(result+1) += *d;
// }
......@@ -66,6 +72,43 @@ int dag_get_stats(dag_adapterinfo_t *di,
return 0;
}
#ifdef PRECLASSIFICATION
/* Returns the sum of numbers of packets that were counted by hardware DSM
* filter counters described by the bitmap which_filters.
* The counters are global in the environment, the reasons are:
*
* 1) the DAG card returns just the increment from the last reading,
* 2) we want to provide these functions to multiple concurrent flows.
*/
int dag_get_dsm_counts(dag_adapterinfo_t *di,
u_int32_t which_filters,
dag_counter_t *result)
{
int i;
uint32_t v;
DsmFilterH filter_h;
*result = 0;
if (dagdsm_latch_and_clear_counters(di->dsm_config) != -1) {
for (i=0; i<7; i++) {
filter_h = dagdsm_get_filter(di->dsm_config, i);
if (dagdsm_read_filter_counter(di->dsm_config, filter_h, &v) != -1) {
di->dsm_counters[i] += v;
if (which_filters & (1 << i))
*result += di->dsm_counters[i];
}
}
}
return 0;
}
#endif
/* When there is a function in the flow that MODIFIES packets, its instance is returned. */
mapidflib_function_instance_t* fhlp_modifying_funct_is_in_list(global_function_list_t *gfl, int fd)
{
......@@ -147,6 +190,46 @@ mapidflib_function_instance_t* fhlp_filtering_funct_is_in_list_but_INTERFACE(
return NULL;
}
#ifdef PRECLASSIFICATION
/* There _must_ be dagflib:BPF_FILTER function in the given flow, but not
* another modifying/filtering function. If ok, TRUE is returned and
* the DAG counting function based on hardware DSM counter can be applied. */
boolean_t fhlp_can_apply_dsm_counter(global_function_list_t *gfl, int fd)
{
mapid_flow_info_t *flowfuncs;
mapidflib_function_t *func;
flist_node_t *n;
boolean_t ok = FALSE;
pthread_spin_lock(&gfl->lock);
flowfuncs = flist_get(gfl->fflist, fd);
if (flowfuncs != NULL) {
n = flist_head(flowfuncs->flist);
while (n) {
func = flist_data(n);
if (!strcmp(func->instance->def->name, "BPF_FILTER")
&& (!strcmp(func->instance->def->devtype, MAPI_DEVICE_DAG))) {
ok = TRUE;
} else {
if (func->instance->def->modifies_pkts
|| func->instance->def->filters_pkts) {
ok = FALSE;
break;
}
}
n = flist_next(n);
}
}
pthread_spin_unlock(&gfl->lock);
return ok;
}
#endif
/****************************************************************************/
int dagstat_instance(mapidflib_function_instance_t *instance,
......@@ -157,49 +240,84 @@ int dagstat_instance(mapidflib_function_instance_t *instance,
* PKT_COUNTER and BYTE_COUNTER return just one value. */
int data_num = (!strcmp(instance->def->name, "PKTBYTE_COUNTER")) ? 2 : 1;
dag_adapterinfo_t *di = instance->hwinfo->adapterinfo;
dagstat_instance_t *i = NULL;
int which_port;
/* FIRST TEST THE PLACEMENT _BEFORE_ MODIFYING/FILTERING FUNCTIONS */
/* Refuses to install itself in case there is some modifying or filtering
* function already in the flow.
/* Install itself only in case there is no modifying or filtering
* function already in the flow. The second call also finds possibly
* preceding INTERFACE and harvests its argument.
*/
if (fhlp_modifying_funct_is_in_list(instance->hwinfo->gflist, fd)
|| fhlp_filtering_funct_is_in_list_but_INTERFACE(instance->hwinfo->gflist, fd, NULL))
return MFUNCT_COULD_NOT_APPLY_FUNCT;
/* These functions are only tested on DAG 4.3GE or DAG 6.2. */
switch (((dag_adapterinfo_t *)instance->hwinfo->adapterinfo)->device_code) {
case PCI_DEVICE_ID_DAG4_30E:
case PCI_DEVICE_ID_DAG6_20:
break;
default:
return MFUNCT_COULD_NOT_APPLY_FUNCT;
if (!fhlp_modifying_funct_is_in_list(instance->hwinfo->gflist, fd)
&& !fhlp_filtering_funct_is_in_list_but_INTERFACE(instance->hwinfo->gflist, fd, &which_port)) {
/* These functions are only tested on DAG 4.3GE and DAG 6.2. */
switch (((dag_adapterinfo_t *)instance->hwinfo->adapterinfo)->device_code) {
case PCI_DEVICE_ID_DAG4_30E:
case PCI_DEVICE_ID_DAG6_20: break;
default: return MFUNCT_COULD_NOT_APPLY_FUNCT;
}
/* Install itself only in case the card initialization
* recognized required measuring components.
*/
if ((di->portcnt != 0) && (di->port_counters != NULL)) {
i = malloc(sizeof(dagstat_instance_t));
i->placement = BEFORE_MODIFILTER;
i->which_port = which_port;
}
}
#ifdef PRECLASSIFICATION
/* IF FAILED, TEST PLACEMENT SOMEWHERE _AFTER_ HARDWARE BPF_FILTER,
* BECAUSE DAG SUPPORTS HARDWARE COUNTING OF MATCHED DSM FILTERS.
* THEREFORE: THIS IS FOR PKT_COUNTER ONLY. */
if ((i == NULL)
&& !strcmp(instance->def->name, "PKT_COUNTER")
&& (di->dsm_config != NULL)
&& (fhlp_can_apply_dsm_counter(instance->hwinfo->gflist, fd) != 0)) {
i = malloc(sizeof(dagstat_instance_t));
i->placement = AFTER_MODIFILTER;
}
/* Refuses to install itself in case the card initialization did not
* recognized required measuring components.
*/
if ((di->portcnt == 0) || (di->counters == NULL))
return MFUNCT_COULD_NOT_APPLY_FUNCT;
#endif
/* Failure, use software function. */
if (i == NULL) return MFUNCT_COULD_NOT_APPLY_FUNCT;
/* Setting data_size is a must for MAPIRES_IPC! */
instance->result.data_size = data_num * sizeof(dag_counter_t);
instance->internal_data = (void *)i;
return 0;
}
int dagstat_init(MAPI_UNUSED mapidflib_function_instance_t* instance,
MAPI_UNUSED int fd)
{
dagstat_instance_t *i = malloc(sizeof(dagstat_instance_t));
/* Find the possibly preceding INTERFACE and harvest its argument. */
fhlp_filtering_funct_is_in_list_but_INTERFACE(instance->hwinfo->gflist, fd, &i->which_port);
dagstat_instance_t *i = instance->internal_data;
if (i->placement == BEFORE_MODIFILTER) {
/* Since we maintain global (i.e. independent from flows) pkt/byte counters,
* we artifically shift each counter so it reads zero in the first function
* value reading. So we need the initial values to subtract.
*/
dag_get_port_counts(instance->hwinfo->adapterinfo, i->which_port, i->initial_counts);
}
/* Since we maintain global (i.e. independent from flows) pkt/byte counters,
* we artifically shift each counter so it reads zero in the first function
* value reading. So we need the initial values to subtract.
*/
dag_get_stats(instance->hwinfo->adapterinfo, i->which_port, i->initial_counts);
#ifdef PRECLASSIFICATION
else {
/* For this case we need to postpone setting initial_counts to first call
* of *_get_result function, because of still unknown preclassification_mask.
*/
memset(i->initial_counts, 0, sizeof(i->initial_counts));
i->first_call = TRUE;
}
#endif
instance->internal_data=i;
return 0;
}
......
......@@ -4,6 +4,7 @@
#include "dagnew.h"
#include "dagapi.h"
#include "dagutil.h"
#include "dagdsm.h"
#include "dag_config.h"
#include "dag_component.h"
......@@ -14,8 +15,10 @@ typedef struct {
} interface_instance_t;
typedef struct {
int which_port;
enum { BEFORE_MODIFILTER, AFTER_MODIFILTER } placement;
dag_counter_t initial_counts[2];
int which_port; /* for BEFORE_MODIFILTER */
boolean_t first_call; /* for AFTER_MODIFILTER */
} dagstat_instance_t;
#define INTERFACE_FUNCT_EXISTS (-2)
......@@ -26,9 +29,15 @@ mapidflib_function_instance_t* fhlp_filtering_funct_is_in_list_but_INTERFACE(
int fd,
int *interface);
int dag_get_stats(dag_adapterinfo_t *di,
int which_port,
dag_counter_t *result);
int dag_get_port_counts(dag_adapterinfo_t *di,
int which_port,
dag_counter_t *result);
#ifdef PRECLASSIFICATION
int dag_get_dsm_counts(dag_adapterinfo_t *di,
u_int32_t which_filters,
dag_counter_t *result);
#endif
int dagstat_instance(mapidflib_function_instance_t *instance,
int fd,
......
......@@ -17,6 +17,7 @@
#include "dagnew.h"
#include "dagapi.h"
#include "dagutil.h"
#include "dagdsm.h"
#include "dag_config.h"
#include "dag_component.h"
......
......@@ -17,7 +17,7 @@ static int pktbytecounter_get_result(mapidflib_function_instance_t* instance,
dagstat_instance_t *i = instance->internal_data;
dag_counter_t cnt[2];
dag_get_stats(instance->hwinfo->adapterinfo, i->which_port, cnt);
dag_get_port_counts(instance->hwinfo->adapterinfo, i->which_port, cnt);
*((dag_counter_t *)instance->result.data + 0) = cnt[0] - i->initial_counts[0];
*((dag_counter_t *)instance->result.data + 1) = cnt[1] - i->initial_counts[1];
......
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
......@@ -17,10 +20,22 @@ static int pktcounter_get_result(mapidflib_function_instance_t* instance,
dagstat_instance_t *i = instance->internal_data;
dag_counter_t cnt[2];
dag_get_stats(instance->hwinfo->adapterinfo, i->which_port, cnt);
if (i->placement == BEFORE_MODIFILTER) {
dag_get_port_counts(instance->hwinfo->adapterinfo, i->which_port, cnt);
}
#ifdef PRECLASSIFICATION
else { /* i->placement == AFTER_MODIFILTER */
dag_get_dsm_counts(instance->hwinfo->adapterinfo, instance->preclassification_mask, cnt);
if (i->first_call) {
i->initial_counts[0] = cnt[0];
i->first_call = FALSE;
}
}
#endif
*(dag_counter_t *)instance->result.data = cnt[0] - i->initial_counts[0];
*res = &instance->result; // must point to actual value
return 0;
}
......
This diff is collapsed.
......@@ -15,9 +15,13 @@ typedef struct dag_adapterinfo {
int is_dsm_filtering; /* DSM filtering available */
int dsm_filter_count; /* Number of DSM hardware filters (usually 8) */
DsmConfigH dsm_config; /* handle to DAG DSM configuration */
/* allocated array of counters for ports and kinds (bytes, packets) */
dag_counter_t *counters;
dag_counter_t *port_counters;
/* array for hardware DSM filter counters */
dag_counter_t dsm_counters[8];
} dag_adapterinfo_t;
#endif /*MAPIDAGDRV_H_*/
......@@ -1004,7 +1004,7 @@ mapid_close_flow(mapidlib_instance_t *i,int fd)
pthread_mutex_lock(&i->lock);
DEBUG_CMD(printf ("Added flow to delete list, fd=%d [%s:%d]\n", fd, __FILE__,__LINE__));
flist_append(&i->close,fd,NULL);
flist_append(&i->close,fd, (void *)0x1); /* 0x1 ... so flist_get works as exist operator */
pthread_mutex_unlock(&i->lock);
......@@ -1285,7 +1285,7 @@ mapid_apply_function(mapidlib_instance_t *i,
//TODO: Add support for optimization
error=0;
//Try software function
DEBUG_CMD(printf("Trying MAPI_DEVICE_ALL devtype because of failure to instance function [%s:%d]\n",__FILE__,__LINE__));
DEBUG_CMD(printf("Trying MAPI_DEVICE_ALL devtype because of failure to instance function %s [%s:%d]\n",function,__FILE__,__LINE__));
f2=mapilh_get_function_def(function,MAPI_DEVICE_ALL);
if(f2==NULL) {
......
......@@ -119,7 +119,7 @@ void mapid_process_pkt(mapidlib_instance_t *i,
unsigned char* link_pkt,
mapid_pkthdr_t* pkt_head);
int mapid_get_errno(mapidlib_instance_t *i,int fid);
//void mapid_delete_flows(mapidlib_instance_t *i);
void mapid_delete_flows(mapidlib_instance_t *i);
int mapid_get_devid(mapidlib_instance_t *i,int fd);
int mapid_load_library(char *lib);
int mapid_get_flow_info(mapidlib_instance_t *i,int fd,mapi_flow_info_t *info);
......