From 9a2a4802f440ea8acf9c1a30180250433103a5b0 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 2 Jan 2012 17:51:21 +0100 Subject: [PATCH] pf-ring: add support for checksum verif mode This patch adds support for checksum verification mode. Supported mode are yes, no, auto and rx-only. --- src/runmode-pfring.c | 18 ++++++++++++++++++ src/source-pfring.c | 42 +++++++++++++++++++++++++++++++++++++----- src/source-pfring.h | 1 + 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/runmode-pfring.c b/src/runmode-pfring.c index 21f5e9333e..bc938c5049 100644 --- a/src/runmode-pfring.c +++ b/src/runmode-pfring.c @@ -128,6 +128,7 @@ void *OldParsePfringConfig(const char *iface) pfconf->ctype = default_ctype; #endif pfconf->DerefFunc = PfringDerefConfig; + pfconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; SC_ATOMIC_INIT(pfconf->ref); SC_ATOMIC_ADD(pfconf->ref, 1); @@ -315,6 +316,23 @@ void *ParsePfringConfig(const char *iface) } } + if (ConfGetChildValue(if_root, "checksum-checks", &tmpctype) != 1) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "Could not get checksum-checks from config"); + } else { + if (strcmp(tmpctype, "auto") == 0) { + pfconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; + } else if (strcmp(tmpctype, "yes") == 0) { + pfconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE; + } else if (strcmp(tmpctype, "no") == 0) { + pfconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE; + } else if (strcmp(tmpctype, "rx-only") == 0) { + pfconf->checksum_mode = CHECKSUM_VALIDATION_RXONLY; + } else { + SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", pfconf->iface); + } + } + + #endif return pfconf; diff --git a/src/source-pfring.c b/src/source-pfring.c index 7160aeec13..90248ed90a 100644 --- a/src/source-pfring.c +++ b/src/source-pfring.c @@ -43,6 +43,8 @@ #include "source-pfring.h" #include "util-debug.h" #include "util-privs.h" +#include "util-device.h" +#include "runmodes.h" TmEcode ReceivePfringLoop(ThreadVars *tv, void *data, void *slot); TmEcode ReceivePfringThreadInit(ThreadVars *, void *, void **); @@ -117,7 +119,7 @@ typedef struct PfringThreadVars_ ThreadVars *tv; TmSlot *slot; - + /* threads count */ int threads; @@ -126,9 +128,12 @@ typedef struct PfringThreadVars_ #endif /* HAVE_PFRING_CLUSTER_TYPE */ uint8_t cluster_id; char *interface; + LiveDevice *livedev; #ifdef HAVE_PFRING_SET_BPF_FILTER char *bpf_filter; #endif /* HAVE_PFRING_SET_BPF_FILTER */ + + ChecksumValidationMode checksum_mode; } PfringThreadVars; /** @@ -174,6 +179,8 @@ static inline void PfringProcessPacket(void *user, struct pfring_pkthdr *h, Pack ptv->bytes += h->caplen; ptv->pkts++; + SC_ATOMIC_ADD(ptv->livedev->pkts, 1); + p->livedev = ptv->livedev; p->ts.tv_sec = h->ts.tv_sec; p->ts.tv_usec = h->ts.tv_usec; @@ -182,10 +189,27 @@ static inline void PfringProcessPacket(void *user, struct pfring_pkthdr *h, Pack * so that is what we do here. */ p->datalink = LINKTYPE_ETHERNET; - /* Packet is being sent */ - if (h->extended_hdr.rx_direction == 0) { - /* Checksum can be offloaded */ - p->flags |= PKT_IGNORE_CHECKSUM; + switch (ptv->checksum_mode) { + case CHECKSUM_VALIDATION_RXONLY: + if (h->extended_hdr.rx_direction == 0) { + p->flags |= PKT_IGNORE_CHECKSUM; + } + break; + case CHECKSUM_VALIDATION_DISABLE: + p->flags |= PKT_IGNORE_CHECKSUM; + break; + case CHECKSUM_VALIDATION_AUTO: + if (ptv->livedev->ignore_checksum) { + p->flags |= PKT_IGNORE_CHECKSUM; + } else if (ChecksumAutoModeCheck(ptv->pkts, + SC_ATOMIC_GET(ptv->livedev->pkts), + SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) { + ptv->livedev->ignore_checksum = 1; + p->flags |= PKT_IGNORE_CHECKSUM; + } + break; + default: + break; } SET_PKT_LEN(p, h->caplen); @@ -303,6 +327,12 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { ptv->interface = SCStrdup(pfconf->iface); + ptv->livedev = LiveGetDevice(pfconf->iface); + if (ptv->livedev == NULL) { + SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); + SCReturnInt(TM_ECODE_FAILED); + } + ptv->pd = pfring_open(ptv->interface, LIBPFRING_PROMISC, (uint32_t)default_packet_size, LIBPFRING_REENTRANT); if (ptv->pd == NULL) { SCLogError(SC_ERR_PF_RING_OPEN,"opening %s failed: pfring_open error", @@ -314,6 +344,8 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { pfring_version(ptv->pd, &version); } + ptv->checksum_mode = pfconf->checksum_mode; + /* We only set cluster info if the number of pfring threads is greater than 1 */ ptv->threads = pfconf->threads; diff --git a/src/source-pfring.h b/src/source-pfring.h index ae7550f779..5e499bb59a 100644 --- a/src/source-pfring.h +++ b/src/source-pfring.h @@ -44,6 +44,7 @@ typedef struct PfringIfaceConfig_ #ifdef HAVE_PFRING_SET_BPF_FILTER char *bpf_filter; #endif /* HAVE_PFRING_SET_BPF_FILTER */ + ChecksumValidationMode checksum_mode; SC_ATOMIC_DECLARE(unsigned int, ref); void (*DerefFunc)(void *); } PfringIfaceConfig;