From 300b739b1fdc579ef05d265ed9fce0d52c1786ab Mon Sep 17 00:00:00 2001 From: Ken Steele Date: Fri, 22 Nov 2013 15:53:12 -0500 Subject: [PATCH] Add more suricata.yaml configuration options for mPIPE. Add two new mPIPE load-balancing configuration options in suricata.yaml. 1) "sticky" which keep sending flows to one CPU, but if that queue is full, don't drop the packet, move the flow to the least loaded queue. 2) Round-robin, which always picks the least full input queue for each packet. Allow configuring the number of packets in the input queue (iqueue) in suricata.yaml. For the mPipe.buckets configuration, which must be a power of 2, round up to the next power of two, rather than report an error. Added mpipe.min-buckets, which defaults to 256, so if the requested number of buckets can't be allocated, Suricata will keep dividing by 2 until either it succeeds in allocating buckets, or reaches the minimum number of buckets and fails. --- src/source-mpipe.c | 68 +++++++++++++++++++++++++++++++++++++--------- suricata.yaml.in | 5 +++- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/source-mpipe.c b/src/source-mpipe.c index 7276c29971..231f4d0bb1 100644 --- a/src/source-mpipe.c +++ b/src/source-mpipe.c @@ -637,6 +637,7 @@ static TmEcode ReceiveMpipeCreateBuckets(int ring, int num_workers, { SCEnter(); int result; + int min_buckets = 256; /* Allocate a NotifGroup. */ int group = gxio_mpipe_alloc_notif_groups(context, 1, 0, 0); @@ -646,19 +647,42 @@ static TmEcode ReceiveMpipeCreateBuckets(int ring, int num_workers, if (ConfGetInt("mpipe.buckets", &value) == 1) { /* range check */ if ((value >= 1) && (value <= 4096)) { - *num_buckets = (int) value; + /* Must be a power of 2, so round up to next power of 2. */ + int ceiling_log2 = 64 - __builtin_clz((int64_t)value - 1); + *num_buckets = 1 << (ceiling_log2); } else { - SCLogError(SC_ERR_INVALID_ARGUMENT, "Illegal mpipe.buckets value."); + SCLogError(SC_ERR_INVALID_ARGUMENT, + "Illegal mpipe.buckets value (%ld). must be between 1 and 4096.", value); + } + } + if (ConfGetInt("mpipe.min-buckets", &value) == 1) { + /* range check */ + if ((value >= 1) && (value <= 4096)) { + /* Must be a power of 2, so round up to next power of 2. */ + int ceiling_log2 = 64 - __builtin_clz((int64_t)value - 1); + min_buckets = 1 << (ceiling_log2); + } else { + SCLogError(SC_ERR_INVALID_ARGUMENT, + "Illegal min-mpipe.buckets value (%ld). must be between 1 and 4096.", value); } } - /* Allocate buckets. */ - *first_bucket = gxio_mpipe_alloc_buckets(context, *num_buckets, 0, 0); - if (*first_bucket == GXIO_MPIPE_ERR_NO_BUCKET) { + /* Allocate buckets. Keep trying half the number of requested buckets until min-bucket is reached. */ + while (1) { + *first_bucket = gxio_mpipe_alloc_buckets(context, *num_buckets, 0, 0); + if (*first_bucket != GXIO_MPIPE_ERR_NO_BUCKET) + break; + /* Failed to allocate the requested number of buckets. Keep + * trying less buckets until min-buckets is reached. + */ + if (*num_buckets <= min_buckets) { SCLogError(SC_ERR_INVALID_ARGUMENT, - "Could not allocate mpipe buckets. " - "Try a smaller mpipe.buckets value in suricata.yaml"); + "Could not allocate (%d) mpipe buckets. " + "Try a smaller mpipe.buckets value in suricata.yaml", *num_buckets); SCReturnInt(TM_ECODE_FAILED); + } + /* Cut the number of requested buckets in half and try again. */ + *num_buckets /= 2; } /* Init group and buckets, preserving packet order among flows. */ @@ -668,17 +692,26 @@ static TmEcode ReceiveMpipeCreateBuckets(int ring, int num_workers, if (balance) { if (strcmp(balance, "static") == 0) { mode = GXIO_MPIPE_BUCKET_STATIC_FLOW_AFFINITY; - SCLogInfo("Using \"static\" flow affinity."); + SCLogInfo("Using \"static\" flow affinity load balancing with %d buckets.", *num_buckets); } else if (strcmp(balance, "dynamic") == 0) { mode = GXIO_MPIPE_BUCKET_DYNAMIC_FLOW_AFFINITY; - SCLogInfo("Using \"dynamic\" flow affinity."); + SCLogInfo("Using \"dynamic\" flow affinity load balancing with %d buckets.", *num_buckets); + } else if (strcmp(balance, "sticky") == 0) { + mode = GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY; + SCLogInfo("Using \"sticky\" load balancing with %d buckets.", *num_buckets); + } else if (strcmp(balance, "round-robin") == 0) { + mode = GXIO_MPIPE_BUCKET_ROUND_ROBIN; } else { SCLogWarning(SC_ERR_INVALID_ARGUMENT, - "Illegal load balancing mode %s using \"static\"", - balance); + "Illegal load balancing mode \"%s\"", balance); + balance = "static"; } } + } else { + balance = "static"; } + SCLogInfo("Using \"%s\" load balancing with %d buckets.", balance, *num_buckets); + result = gxio_mpipe_init_notif_group_and_buckets(context, group, ring, num_workers, *first_bucket, @@ -716,8 +749,17 @@ static int ReceiveMpipeRegisterRules(int bucket, int num_buckets) */ static int MpipeReceiveOpenIqueue(int rank) { - /* Init the NotifRings. */ - const size_t notif_ring_entries = 2048; + /* Initialize the NotifRings. */ + size_t notif_ring_entries = 2048; + intmax_t value = 0; + if (ConfGetInt("mpipe.iqueue-packets", &value) == 1) { + /* range check */ + if (value == 128 || value == 512 || value == 2048 || value == (64 * 1024)) { + notif_ring_entries = value; + } else { + SCLogError(SC_ERR_INVALID_ARGUMENT, "Illegal mpipe.iqueue_packets value. must be 128, 512, 2048 or 65536."); + } + } size_t notif_ring_size = notif_ring_entries * sizeof(gxio_mpipe_idesc_t); diff --git a/suricata.yaml.in b/suricata.yaml.in index 26dbb2a284..d18ceb77b6 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -721,9 +721,12 @@ logging: # Tilera mpipe configuration. for use on Tilera TILE-Gx. mpipe: - # Load balancing mode "static" or "dynamic". + # Load balancing modes: "static", "dynamic", "sticky", or "round-robin". load-balance: dynamic + # Number of Packets in each ingress packet queue. Must be 128, 512, 2028 or 65536 + iqueue-packets: 2048 + # List of interfaces we will listen on. inputs: - interface: xgbe2