Commit bf0032f6 authored by 's avatar
Browse files

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().
......@@ -16,12 +16,11 @@ MAPI dagflib \- Endace DAG Function Library
.fi
.SH DESCRIPTION
This library provides functions intended to better use the capabilities of
the DAG capturing card hardware (produced by Endace), thus to alleviate the
main CPU burden. Once applied to DAG bound flow, the function from dagflib
is tried first. In case it cannot be used for whatever reason, the
correspondingly named software function from stdflib is used instead
(if exists). See
This library provides functions intended for better use the capabilities of
the DAG capturing hardware (produced by Endace), thus to alleviate the main
CPU burden. Once applied to DAG bound MAPI flow, the function from dagflib
is tried first. In case of failure, the correspondingly named software
function from stdflib is used instead (if exists). See also
.BR mapi_stdflib (3).
.BR INTERFACE ,
......@@ -34,7 +33,7 @@ have where to fallback.
For IPF filtering, the DAG version 4.3GE (with coprocessor) is currently
supported. DSM filtering is enabled for all DAG cards claiming DSM support
(e.g. DAG 6.2). The number of hardware filters is hardwired to 8. For more
information about DSM, see the
information on DSM, see the
.BR bpf2dagdsm (1)
manpage from this package or Endace documentation.
......@@ -44,7 +43,7 @@ internals.
.SH FUNCTIONS
.TP
.BI "INTERFACE (int " ifnumber ")"
Software function (not touching the hardware) to pass only frames originating
Software function (not touching the hardware) to pass only packets originating
from the DAG interface (AKA port) identified by
.IR ifnumber .
......@@ -58,27 +57,46 @@ Type of results: \fBnone\fP.
.\"--------------------------------------------------------
.TP
.BI "BPF_FILTER (char *" expression ")"
Programs the DAG card's hardware DSM filter so in result, only packets matching the
filtering \fIexpression\fR (which is in the syntax used by \fBtcpdump\fR(8))
will pass over this func in the flow.
Programs the DAG card's hardware DSM filter so in result, only packets
matching the filtering \fIexpression\fR (which uses the syntax used by
\fBtcpdump\fR(8)) will pass over this func in the flow.
The \fIexpression\fR is compiled into a XML format and fed to Endace's utility
The \fIexpression\fR is compiled into the XML format and fed to Endace's utility
.BR dsm_loader (1)
executed on the background by mapid. The path to this binary is expected in the variable
.I dsm_loader_bin
in the section
executed on the background by mapid. The section
.I [dag]
of the MAPI configuration file
.BR mapi.conf .
.BR mapi.conf
holds the following variables pertaining to the DSM:
.I dsm_loader_bin
-- The path to the \fBdsm_loader\fR binary.
The \fBBPF_FILTER\fR implementation is rather tricky and is described below
under \fBDSM IMPLEMENTATION\fR.
.I dsm_load_balancing
-- There are four possible values: \fInone\fR (turned off), \fIcrc32\fR,
\fIparity\fR or \fIinterface\fR. When it is turned on, the bpfcompiler
library (see below) adds the appropriate construct to the XML file
describing the DSM configuration. As result, the frames are steered
between the logical streams 0 and 2 according to the output of the chosen
internal variable.
.I disable_dsm
-- This debugging boolean variable disables the DSM code in mapid (value 1).
The code from stdflib will be used for BPF_FILTER. The default is 0.
.I disable_dsm_xml_remove
-- This debugging boolean variable instruct mapid to \fBnot\fR remote the XML
definition file created in the /tmp directory after the successful run
of dsm_loader. The default is 0.
The \fBBPF_FILTER\fR implementation is NEW & EXPERIMENTAL and more
described below under \fBDSM IMPLEMENTATION\fR.
Type of results: \fBnone\fP.
.\"--------------------------------------------------------
.TP
.BI "DAGIPF_BPF_FILTER (char *" expression ")"
Programs the DAG card's hardware IPF filter to drop all frames that do not
Programs the DAG card's hardware IPF filter to drop all packets that do not
match the filtering
.IR expression ,
which is in the syntax used by
......@@ -107,13 +125,19 @@ Type of results: \fBnone\fP.
.TP
.B PKT_COUNTER
Returns the number of frames seen by the DAG capturing card so far on its
one or all interfaces (selected by the presence of previous
Returns the number of packets seen by the DAG capturing card so far on
one or all its interfaces (selected by the presence of previous
.B INTERFACE
function). See also
.B STATUS API
below.
When this function is applied \fBafter\fR the BPF_FILTER that use the DSM
filtering/classification, the implementation is different to fully utilize
the hardware DSM counters measuring the packets matched the DSM filters. See
also the \fBDSM IMPLEMENTATION\fR section below. Beware that this application
of PKT_COUNTER is still NEW & EXPERIMENTAL.
Type of results: \fBunsigned long long\fP.
.\"--------------------------------------------------------
.TP
......@@ -127,12 +151,14 @@ below.
.B Please note:
There is a difference in results returned by this function for dagflib and
stdflib. DAG also counts the link layer for each frame. Even when taking
stdflib. DAG also counts the link layer of each frame. Even when taking
this into account, the results are not completely same, but close. To be
able to "correct" the value by the number of frames captured, use atomic
.B PKTBYTE_COUNTER
function.
This function cannot use the DSM counters.
Type of results: \fBunsigned long long\fP.
.\"--------------------------------------------------------
.TP
......@@ -146,46 +172,66 @@ latched at once, thus the values match the same time periods exactly. See also
.B STATUS API
below.
This function cannot use the DSM counters.
Type of results: 2 * \fBunsigned long long\fP.
.fi
.\"--------------------------------------------------------
.SH DSM IMPLEMENTATION
BPF expression compiler is needed, so MAPI carries one. For more details see
\fBbpf2dagdsm\fR(1) describing a program using the bpfcompiler library as well
as some notable language restrictions.
Data Stream Management (DSM) is a hardware filtering/classification feature
provided by certain models of DAG capturing cards made by Endace. The DSM
module provides 8 independent bitmasking filters; they match first 64 bytes
of captured network frames in parallel. Every filter yields the boolean
value that can be further processed by the hardware lookup table forming
trivial or complex logical expressions.
Logical expressions can be formed from additional variables: 1) outputs of
two steering (load balancing) algorithms: parity and crc32 (both should
generate true/false with approximately 50:50 split), 2) variable describing
the port (interface) the current frame was captured on.
The output of the logical expressions indicates, to which logical input
stream the frame should be sent or whether it should be silently dropped.
The hardware increments a special counters for every filter that matched the
frame. The DSM version of function \fBPKT_COUNTER\fR utilizes reading filter
counters.
Each of the \fBBPF_FILTER\fR functions occupies one or more OR-ed hardware
filters in the DAG capturing card. There are 8 filters available.
Being in the DSM mode, the DAG card sends special "colored" ERF records
containing the bit-array describing which filters matched the packet.
To utilize the \fBBPF_FILTER\fR functions we need to transform the BPF
expression to DSM configuration just described. The suitable bpfcompiler
library comes with MAPI. For additional details see \fBbpf2dagdsm\fR(1)
describing a command line program using this library as well as some notable
language restrictions.
Each of the \fBBPF_FILTER\fR functions occupies one or more DSM bitmasking
filters. Being in the DSM mode, DAG card sends special "colored" ERF data
records containing the bit-array indicating which filters matched the packet.
Main reason to implement DSM in MAPI was to alleviate the load of the CPU
running mapid when monitoring thick pipes. The DAG filtering hardware should
always be instructed to pass only interesting packets to the software.
Interesting means that any active MAPI flow expressed the interest.
This requires special handling:
In simple case, when the sum of all successfully initialized dagflib
\fBBPF_FILTER\fR functions in all flows fit to 8 hardware filters, the DAG
capturing card is in the \fIfiltering\fR mode, providing only packets matching
any of the \fBBPF_FILTER\fR's \fIexpression\fR. Every function then decides
the matching condition according to ERF \fIcolor\fR (see above), because
it knows its filtering mask.
In other case (\fBBPF_FILTER\fR init error, incompatible leading software
function requesting all packets captured, etc.) the DSM filter is turned
into the \fIpreclassification\fR (AKA always-match) mode. Now the coloring
masking still works for successfully initialized dagflib \fBBPF_FILTER\fR
functions, but also packets not matching any filter are provided.
The complete filter inspecting all active flows is rebuilt in each
\fImapi_connect\fR() and \fImapi_close_flow\fR(). Also read-only building of
the entire filter is made upon the instantiation of dagflib's
\fBBPF_FILTER\fR when it is needed to decide whether the new function will
overflow the number of available hardware filters and therefore stdflib's
version should be used instead (of course, this leads to
\fIpreclassification\fR mode).
running MAPI daemon when monitoring thick pipes. The DAG filtering hardware
should always be instructed to pass only interesting packets to the
software. Interesting means that at least one active MAPI flow expressed the
interest. This requires special handling:
Case one: The sum of all successfully initialized dagflib \fBBPF_FILTER\fR
functions in all flows fit to 8 hardware filters as well as no flow
begins with a function requiring \fIentire\fR traffic. Then the DAG
capturing card is in the \fIfiltering\fR mode, providing only packets
matching any of the \fBBPF_FILTER\fR's \fIexpression\fR. Every function then
distinguishes the matching condition according to ERF \fIcolor\fR (see
above), because it knows its own filtering mask.
Case two (opposite): The DSM card is turned into the \fIpreclassification\fR
(AKA always-match) mode. Now the coloring masking still works for
successfully initialized dagflib \fBBPF_FILTER\fR functions, but also
the rest of the packets (not matching any filter) are provided to the software.
The complete DSM configuration inspecting all active flows is fully rebuilt
in each \fImapi_connect\fR() and \fImapi_close_flow\fR(). The bpfcompiler
library generates the XML file to /tmp. It is suitable for the
\fBdsm_loader\fR command line program create by Endace, which is then called
by mapid to actually activate the DSM configuration.
.\"--------------------------------------------------------
.SH STATUS API
......
......@@ -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;