diff --git a/src/Linux/hsflowd.h b/src/Linux/hsflowd.h index 21cb433..c61e3b9 100644 --- a/src/Linux/hsflowd.h +++ b/src/Linux/hsflowd.h @@ -417,6 +417,7 @@ extern "C" { #define HSPEVENT_INTF_COUNTER_SAMPLE "icsample" // (csample *) building intf counter-sample #define HSPEVENT_VM_COUNTER_SAMPLE "vcsample" // (csample *) building vm counter-sample #define HSPEVENT_FLOW_SAMPLE "flow_sample" // (HSPPendingSample *) building flow-sample +#define HSPEVENT_INTF_EVENT_SAMPLE "evsample" // (discard *) building event-sample #define HSPEVENT_FLOW_SAMPLE_RELEASED "flow_sample_released" // (HSPPendingSample *) flow-sample after lookups completed #define HSPEVENT_XDR_SAMPLE "xdr_sample" // fully-encoded SFDBuf #define HSPEVENT_CONFIG_START "config_start" // begin config lines @@ -491,6 +492,12 @@ extern "C" { bool suppress:1; } HSPPendingCSample; + typedef struct _HSPPendingEvtSample { + SFLEvent_discarded_packet *discard; + SFLNotifier *notifier; + bool suppress:1; + } HSPPendingEvtSample; + typedef enum { HSP_TELEMETRY_FLOW_SAMPLES=0, HSP_TELEMETRY_COUNTER_SAMPLES, diff --git a/src/Linux/mod_dropmon.c b/src/Linux/mod_dropmon.c index 2c5f5ce..86db2ce 100644 --- a/src/Linux/mod_dropmon.c +++ b/src/Linux/mod_dropmon.c @@ -137,6 +137,7 @@ extern "C" { uint32_t ignoredDrops_rn; uint32_t totalDrops_thisTick; // for threshold bool dropmon_disabled; + EVEvent *evt_intf_es; } HSP_mod_DROPMON; @@ -942,8 +943,16 @@ That would allow everything to stay on the stack as it does here, which has nice SFLADD_ELEMENT(&discard, &rnElem); } - sfl_notifier_writeEventSample(notifier, &discard); - sp->telemetry[HSP_TELEMETRY_EVENT_SAMPLES]++; + HSPPendingEvtSample es = { .notifier = notifier, .discard = &discard }; + if(mdata->evt_intf_es) + EVEventTx(mod, mdata->evt_intf_es, &es, sizeof(es)); + if(es.suppress) { + sp->telemetry[HSP_TELEMETRY_EVENT_SAMPLES_SUPPRESSED]++; + } + else { + sfl_notifier_writeEventSample(notifier, &discard); + sp->telemetry[HSP_TELEMETRY_EVENT_SAMPLES]++; + } // first successful event confirms we are up and running if(mdata->state == HSP_DROPMON_STATE_START) @@ -1234,6 +1243,7 @@ That would allow everything to stay on the stack as it does here, which has nice EVEventRx(mod, EVGetEvent(mdata->packetBus, EVEVENT_TICK), evt_tick); EVEventRx(mod, EVGetEvent(mdata->packetBus, EVEVENT_DECI), evt_deci); EVEventRx(mod, EVGetEvent(mdata->packetBus, EVEVENT_FINAL), evt_final); + mdata->evt_intf_es = EVGetEvent(mdata->packetBus, HSPEVENT_INTF_EVENT_SAMPLE); } #if defined(__cplusplus) diff --git a/src/Linux/mod_sonic.c b/src/Linux/mod_sonic.c index 3c75d31..32dbb56 100644 --- a/src/Linux/mod_sonic.c +++ b/src/Linux/mod_sonic.c @@ -2322,6 +2322,58 @@ extern "C" { } } + /*_________________---------------------------__________________ + _________________ evt_flow_sample __________________ + -----------------___________________________------------------ + packet bus + */ + + static void evt_discard_sample(EVMod *mod, EVEvent *evt, void *data, size_t dataLen) { + HSP *sp = (HSP *)EVROOTDATA(mod); + HSPPendingEvtSample *ps = (HSPPendingEvtSample *)data; + // find and translate all ifIndex fields from the OS (Linux) ifIndex namespace to + // the SONiC ifIndex namespace. + HSPSonicPort *prt = NULL; + uint32_t dsClass = ps->discard->ds_class; + uint32_t osIndex = ps->discard->ds_index; + if(ps->discard->ds_class == SFL_DSCLASS_IFINDEX) + prt = getPortByOsIndex(mod, osIndex); + if(prt == NULL + || prt->ifIndex == HSP_SONIC_IFINDEX_UNDEFINED) { + // for troubleshooting we can allow this through (untranslated) with: + // "sonic{suppressOther=off}" + if(!sp->sonic.suppressOther) + return; + // Unfortunately we might suppress useful discard events that were associated with, + // say, VLAN interfaces or the docker bridge here. So rather than suppress them + // altogether, translate them as coming from dataSource 0:0x3FFFFFFF, meaning "internal" + EVDebug(mod, 2, "discard sample from non-sonic port (class=%u, osIndex=%u)", dsClass, osIndex); + // ps->suppress = YES; + } + + uint32_t dsIndexAlias = prt ? prt->ifIndex : SFL_INTERNAL_INTERFACE; + // fix datasource + sfl_notifier_set_dsAlias(ps->notifier, dsIndexAlias); + // fix in/out + if(ps->discard->input + && ps->discard->input != SFL_INTERNAL_INTERFACE) { + // translate, or mark unknown + HSPSonicPort *in = getPortByOsIndex(mod, ps->discard->input); + ps->discard->input = (in && in->ifIndex != HSP_SONIC_IFINDEX_UNDEFINED) + ? in->ifIndex + : 0; + } + if(ps->discard->output + && ps->discard->output != SFL_INTERNAL_INTERFACE + && (ps->discard->output & 0x80000000) == 0) { + // translate, or mark unknown + HSPSonicPort *out = getPortByOsIndex(mod, ps->discard->output); + ps->discard->output = (out && out->ifIndex != HSP_SONIC_IFINDEX_UNDEFINED) + ? out->ifIndex + : 0; + } + } + /*_________________---------------------------__________________ _________________ evt_cntr_sample __________________ -----------------___________________________------------------ @@ -2454,6 +2506,7 @@ extern "C" { // intercept samples before they go out so we can rewrite ifindex numbers EVEventRx(mod, EVGetEvent(mdata->packetBus, HSPEVENT_FLOW_SAMPLE), evt_flow_sample); + EVEventRx(mod, EVGetEvent(mdata->packetBus, HSPEVENT_INTF_EVENT_SAMPLE), evt_discard_sample); EVEventRx(mod, EVGetEvent(mdata->pollBus, HSPEVENT_INTF_COUNTER_SAMPLE), evt_cntr_sample); }