@@ -282,6 +282,12 @@ CONFIG_RTE_LIBRTE_HASH=y
CONFIG_RTE_LIBRTE_HASH_DEBUG=n
#
+# Compile librte_headroom
+#
+CONFIG_RTE_LIBRTE_HEADROOM=y
+CONFIG_RTE_HEADROOM_MAX_JOBS=32
+
+#
# Compile librte_lpm
#
CONFIG_RTE_LIBRTE_LPM=y
@@ -290,6 +290,12 @@ CONFIG_RTE_LIBRTE_HASH=y
CONFIG_RTE_LIBRTE_HASH_DEBUG=n
#
+# Compile librte_headroom
+#
+CONFIG_RTE_LIBRTE_HEADROOM=y
+CONFIG_RTE_HEADROOM_MAX_JOBS=32
+
+#
# Compile librte_lpm
#
CONFIG_RTE_LIBRTE_LPM=y
@@ -53,6 +53,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
+DIRS-$(CONFIG_RTE_LIBRTE_HEADROOM) += librte_headroom
DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net
new file mode 100644
@@ -0,0 +1,50 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_headroom.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_HEADROOM) := rte_headroom.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_HEADROOM)-include := rte_headroom.h
+
+# this lib needs eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_HEADROOM) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_HEADROOM) += lib/librte_mbuf
+
+include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,368 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include <rte_errno.h>
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_branch_prediction.h>
+#include <rte_debug.h>
+
+#include "rte_headroom.h"
+
+/* Those are steps used to adjust job period.
+ * Experiments show that for forwarding apps the up step must be less than down
+ * step to achieve optimal performance.
+ */
+#define JOB_UPDATE_STEP_UP 1
+#define JOB_UPDATE_STEP_DOWN 4
+
+/*
+ * Default update function that implements simple period adjustment.
+ */
+static void
+default_update_function(struct rte_headroom_job *job, int64_t result)
+{
+ int64_t err = job->job_target - result;
+
+ /* Job is happy. Nothing to do */
+ if (err == 0)
+ return;
+
+ if (err > 0) {
+ if (job->period + JOB_UPDATE_STEP_UP < job->max_period)
+ job->period += JOB_UPDATE_STEP_UP;
+ } else {
+ if (job->min_period + JOB_UPDATE_STEP_DOWN < job->period)
+ job->period -= JOB_UPDATE_STEP_DOWN;
+ }
+}
+
+static uint32_t
+select_next_job(struct rte_headroom *hdr)
+{
+ const uint64_t now = rte_get_timer_cycles();
+ const uint32_t count = hdr->job_count;
+ uint32_t idx = hdr->job_idx;
+
+ for (; idx < count; idx++) {
+ if (hdr->jobs[idx].next_exec_time <= now)
+ break;
+ }
+
+ hdr->job_idx = idx;
+ return idx;
+}
+
+static void
+default_loop_hook(__rte_unused struct rte_headroom *hdr)
+{
+ rte_pause();
+}
+
+static void
+default_idle_hook(__rte_unused struct rte_headroom *hdr)
+{
+ rte_pause();
+}
+
+int
+rte_headroom_init(struct rte_headroom *hdr)
+{
+ if (hdr == NULL)
+ return -EINVAL;
+
+ memset(hdr, 0, sizeof(*hdr));
+
+ /* Set some initial values */
+ hdr->idle_hook = &default_idle_hook;
+ hdr->loop_hook = &default_loop_hook;
+
+ hdr->user_data = NULL;
+
+ return 0;
+}
+
+void
+rte_headroom_deinit(struct rte_headroom *hdr)
+{
+ RTE_VERIFY(hdr != NULL);
+
+ hdr->job_count = 0;
+ hdr->job_idx = 0;
+}
+
+void
+rte_headroom_set_user_data(struct rte_headroom *hdr, void *user_data)
+{
+ hdr->user_data = user_data;
+}
+
+void
+rte_headroom_set_loop_hook(struct rte_headroom *hdr,
+ rte_headroom_idle_hook_t loop_end_hook)
+{
+ if (loop_end_hook == NULL)
+ loop_end_hook = default_loop_hook;
+
+ hdr->loop_hook = loop_end_hook;
+}
+
+void
+rte_headroom_set_idle_hook(struct rte_headroom *hdr,
+ rte_headroom_idle_hook_t idle_hook)
+{
+ if (idle_hook == NULL)
+ idle_hook = default_idle_hook;
+
+ hdr->idle_hook = idle_hook;
+}
+
+static void
+update_stats(struct rte_headroom_stats *stats, uint64_t idle, uint64_t runtime)
+{
+ stats->idle += idle;
+
+ if (idle < stats->idle_min)
+ stats->idle_min = idle;
+
+ if (idle > stats->idle_max)
+ stats->idle_max = idle;
+
+ stats->run_time += runtime;
+
+ if (runtime < stats->run_time_min)
+ stats->run_time_min = runtime;
+
+ if (runtime > stats->run_time_max)
+ stats->run_time_max = runtime;
+
+ stats->exec_cnt++;
+}
+
+int
+rte_headroom_next_job(struct rte_headroom *hdr)
+{
+ uint64_t start_time, run_time, idle_time = 0, now;
+ int64_t retval;
+ struct rte_headroom_job *job;
+
+ if (unlikely(hdr == NULL))
+ return -EINVAL;
+
+ if (unlikely(hdr->job_count == 0))
+ return -ENOENT;
+
+ /* Wait for any job to be ready. */
+ if (unlikely(select_next_job(hdr) == hdr->job_count)) {
+ /* All jobs done. Update statisctics and go next loop */
+ update_stats(&hdr->stats, hdr->loop_idle, hdr->loop_runtime);
+ hdr->loop_idle = 0;
+ hdr->loop_runtime = 0;
+ hdr->job_idx = 0;
+
+ /* Execute loop end hook. */
+ (*hdr->loop_hook)(hdr);
+
+ /* Get ready job or wait for first one to became ready */
+ while (select_next_job(hdr) == hdr->job_count) {
+ hdr->job_idx = 0;
+ (*hdr->idle_hook)(hdr);
+ }
+ }
+
+ /* Calculate idle time counter for this job. Idle time is a time from
+ * execution finish to next job became ready. */
+ start_time = rte_get_timer_cycles();
+ idle_time = start_time - hdr->loop_end_time;
+
+ job = &hdr->jobs[hdr->job_idx];
+ retval = (*job->job_cb)(job);
+
+ (*job->update_period_cb)(job, retval);
+ job->next_exec_time += job->period;
+
+ now = rte_get_timer_cycles();
+ if (job->next_exec_time < now)
+ job->next_exec_time = now;
+
+ run_time = now - start_time;
+
+ /* Update job stats. */
+ update_stats(&job->stats, idle_time, run_time);
+
+ /* Update this loop stats. */
+ hdr->loop_idle += idle_time;
+ hdr->loop_runtime += run_time;
+
+ /* Mark time when this iteration ended */
+ hdr->loop_end_time = rte_get_timer_cycles();
+
+ /* Try next job. */
+ hdr->job_idx++;
+
+ /* Job finished */
+ return 0;
+}
+
+struct rte_headroom_job *
+rte_headroom_find_job(struct rte_headroom *hdr,
+ rte_headroom_job_callbak_t job_cb, void *job_data)
+{
+ size_t i;
+
+ if (unlikely(job_cb == NULL)) {
+ rte_errno = EINVAL;
+ return NULL;
+ }
+
+ /* Search the array. */
+ for (i = 0; i < hdr->job_count; i++) {
+ if (hdr->jobs[i].job_cb == job_cb &&
+ hdr->jobs[i].job_data == job_data)
+ return &hdr->jobs[i];
+ }
+
+ if (hdr->job_count == 0)
+ rte_errno = ENOENT;
+
+ return NULL;
+}
+
+struct rte_headroom_job *
+rte_headroom_find_job_by_name(struct rte_headroom *hdr, const char *job_name)
+{
+ size_t i;
+
+ if (unlikely(job_name == NULL)) {
+ rte_errno = EINVAL;
+ return NULL;
+ }
+
+ /* Search the array. */
+ for (i = 0; i < hdr->job_count; i++) {
+ if (hdr->jobs[i].name[0] == '\0')
+ continue;
+
+ if (strcmp(hdr->jobs[i].name, job_name) == 0)
+ return &hdr->jobs[i];
+ }
+
+ if (hdr->job_count == 0)
+ rte_errno = ENOENT;
+
+ return NULL;
+}
+
+int
+rte_headroom_add_job(struct rte_headroom *hdr, const char *name,
+ rte_headroom_job_callbak_t job_cb, void *job_data, uint64_t min_period,
+ uint64_t max_period, uint64_t initial_period, int64_t target,
+ struct rte_headroom_job **job_handle)
+{
+ struct rte_headroom_job *job;
+
+ if (hdr == NULL || job_cb == NULL)
+ return -EINVAL;
+
+ /* Add job by finding free slot. */
+ if (hdr->job_count == RTE_DIM(hdr->jobs))
+ return -ENOBUFS;
+
+ job = &hdr->jobs[hdr->job_count];
+ hdr->job_count++;
+
+ memset(job, 0, sizeof(*job));
+ job->next_exec_time = rte_get_timer_cycles();
+ job->job_cb = job_cb;
+ job->job_data = job_data;
+
+ job->update_period_cb = default_update_function;
+
+ if (initial_period <= min_period)
+ job->period = min_period;
+ else if (initial_period >= max_period)
+ job->period = max_period;
+ else
+ job->period = initial_period;
+
+ job->min_period = min_period;
+ job->max_period = max_period;
+ job->job_target = target;
+
+ if (name != NULL)
+ strncpy(job->name, name, RTE_DIM(job->name));
+ else
+ memset(job->name, 0, sizeof(job->name));
+
+ job->headroom = hdr;
+
+ if (job_handle)
+ *job_handle = job;
+ return 0;
+}
+
+int
+rte_headroom_del_job(struct rte_headroom_job *job)
+{
+ struct rte_headroom *hdr;
+ size_t cnt, idx;
+
+ if (unlikely(job == NULL))
+ return -EINVAL;
+
+ hdr = job->headroom;
+ RTE_VERIFY(hdr->jobs < job &&
+ (size_t)(job - hdr->jobs) < RTE_DIM(hdr->jobs));
+
+ idx = job - hdr->jobs;
+ cnt = hdr->job_count - idx - 1;
+ hdr->job_count--;
+
+ if (cnt > 0)
+ memmove(&hdr->jobs[idx], &hdr->jobs[idx + 1], sizeof(*job) * cnt);
+
+ return hdr->job_count;
+}
+
+void
+rte_headroom_set_update_period_function(struct rte_headroom_job *job,
+ rte_headroom_update_fn_t update_pedriod_cb)
+{
+ if (update_pedriod_cb == NULL)
+ update_pedriod_cb = default_update_function;
+
+ job->update_period_cb = update_pedriod_cb;
+}
new file mode 100644
@@ -0,0 +1,481 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HEADROOM_H_
+#define HEADROOM_H_
+
+#include <stdint.h>
+
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if RTE_HEADROOM_MAX_JOBS < 1 || RTE_HEADROOM_MAX_JOBS >= 0xFFFF
+# error Define RTE_HEADROOM_MAX_JOBS to be greater 1 and less 65535
+#endif
+
+/* Forward declarations. */
+struct rte_headroom;
+struct rte_headroom_job;
+
+typedef void (*rte_headroom_idle_hook_t)(struct rte_headroom *hdr);
+typedef void (*rte_headroom_loop_hook_t)(struct rte_headroom *hdr);
+typedef int64_t (*rte_headroom_job_callbak_t)(struct rte_headroom_job *job);
+
+/**
+ * This function should calculate new period and set it using
+ * rte_headroom_set_period() function. Time spent in this function will be
+ * added to job's runtime.
+ *
+ * @param job
+ * The job data structure handler.
+ * @param job_result
+ * Result of calling job callback.
+ */
+typedef void (*rte_headroom_update_fn_t)(struct rte_headroom_job *job,
+ int64_t job_result);
+
+struct rte_headroom_stats {
+ uint64_t idle;
+ /**< Sum of idle time before this job became ready. */
+
+ uint64_t idle_min;
+ /**< Minimum idle time. */
+
+ uint64_t idle_max;
+ /**< Maximum idle time. */
+
+ uint64_t run_time;
+ /**< Total time that this job was executing. */
+
+ uint64_t run_time_min;
+ /**< Minimum execute time. */
+
+ uint64_t run_time_max;
+ /**< Minimum execute time. */
+
+ uint64_t exec_cnt;
+ /**< Task execute count. */
+};
+
+struct rte_headroom_job {
+ uint64_t next_exec_time;
+ /**< Next time when job should be executed. */
+
+ rte_headroom_job_callbak_t job_cb;
+ /**< Callback function for this job. */
+
+ void *job_data;
+ /**< Pointer to custom job's data. */
+
+ rte_headroom_update_fn_t update_period_cb;
+ /**< Period update callback. */
+
+ uint64_t period;
+ /**< Estitmated period of execution. */
+
+ uint64_t min_period;
+ /**< Minimum period. */
+
+ uint64_t max_period;
+ /**< Maximum period. */
+
+ struct rte_headroom_stats stats;
+
+ int64_t job_target;
+ /**< Desired value for this job. */
+
+#define RTE_HEADROOM_JOB_NAMESIZE 32
+ char name[RTE_HEADROOM_JOB_NAMESIZE];
+ /**< Name of this job */
+
+ struct rte_headroom *headroom;
+ /**< Hedroom object that this job belong to. */
+} __rte_cache_aligned;
+
+struct rte_headroom {
+ struct rte_headroom_job jobs[RTE_HEADROOM_MAX_JOBS];
+ /**< Array of job objects. */
+ uint32_t job_count;
+ /**< Job count. */
+ uint32_t job_idx;
+ /**< Index of job that is executing. */
+ struct rte_headroom_stats stats;
+
+ uint64_t loop_end_time;
+ /**< Time when last loop finished its execution. */
+
+ uint64_t loop_idle;
+ uint64_t loop_runtime;
+ /**< This loop idle time. */
+
+ rte_headroom_idle_hook_t idle_hook;
+ rte_headroom_loop_hook_t loop_hook;
+
+ void *user_data;
+ /**< User specified data for all user hooks. Not used by default hooks. */
+} __rte_cache_aligned;
+
+/**
+ * Allocate resource and initialize given headroom object with default
+ * values.
+ *
+ * @param hdr
+ * The headroom object to be initialized.
+ *
+ * @return
+ * 0 if successfull or negative error value:
+ * -EINVAL - if hdr is NULL
+ */
+int
+rte_headroom_init(struct rte_headroom *hdr);
+
+/**
+ * Deallocate any reserved resource make headroom object invalid.
+ *
+ * @pre All jobs from headroom object
+ *
+ * @param hdr The headroom object to be initialized.
+ */
+void
+rte_headroom_deinit(struct rte_headroom *hdr);
+
+/**
+ * Set new user data for headroom hooks.
+ *
+ * @param hdr
+ * Headroom object to change a hook.
+ * @param loop_hook
+ * New hook function. Can be NULL.
+ */
+void
+rte_headroom_set_user_data(struct rte_headroom *hdr, void *user_data);
+
+/**
+ * Set hook function executed when all jobs are executed in this loop turn.
+ *
+ * Time spent in this function is considered idle and counted as headroom. User
+ * application should not do any time consuming tasks in this hook as it can
+ * delay execution of job that became ready during time spent in this function.
+ *
+ * @param hdr
+ * Headroom object to change a hook.
+ * @param loop_hook
+ * New hook function. Can be NULL.
+ */
+void
+rte_headroom_set_loop_hook(struct rte_headroom *hdr,
+ rte_headroom_idle_hook_t loop_end_hook);
+
+/**
+ * Set hook function executed when no job is ready to execute (idle loop).
+ *
+ * Time spent in this function is considered idle and counted as headroom. User
+ * application should not do any time consuming tasks in this hook as it can
+ * delay execution of job that became ready during time spent in this function.
+ *
+ * @param hdr
+ * Headroom object to change a hook.
+ * @param idle_hook
+ * New hook function. Can be NULL.
+ */
+void
+rte_headroom_set_idle_hook(struct rte_headroom *hdr,
+ rte_headroom_idle_hook_t idle_hook);
+
+/**
+ * Wait for next job to be ready and execute it.
+ *
+ * @param headroom
+ * Headroom object that contains jobs.
+ *
+ * @return
+ * 0 on success or negative error code:
+ * -EINVAL if hdr is NULL.
+ * -ENOENT if there is no added jobs.
+ */
+int
+rte_headroom_next_job(struct rte_headroom *hdr);
+
+/**
+ * Return first job handle that match callback and data parameter.
+ *
+ * @param hdr
+ * Headroom obcjet to be searched.
+ * @param job_cb
+ * Job callback to find.
+ * @param job_data
+ * Job's private data pointer to find.
+ *
+ * @return
+ * Job object
+ * NULL if job is not found.
+ * NULL and set rte_errno:
+ * EINVAL if job_cb is NULL
+ * ENOENT if there is no jobs added to headroom object
+ */
+struct rte_headroom_job *
+rte_headroom_find_job(struct rte_headroom *hdr,
+ rte_headroom_job_callbak_t job_cb, void *job_data);
+
+/**
+ * Return first job handle that match given name. Jobs without name
+ * can't be found.
+ *
+ * @param hdr
+ * Headroom obcjet to be searched.
+ * @param job_name
+ * Name of job to be found.
+ *
+ * @return
+ * Job object
+ * NULL if job is not found.
+ * NULL and set rte_errno:
+ * EINVAL if job_name is NULL
+ * ENOENT if there is no jobs added to headroom object
+ */
+struct rte_headroom_job *
+rte_headroom_find_job_by_name(struct rte_headroom *hdr, const char *job_name);
+
+/**
+ * Return current number of jobs in headroom object.
+ * @param hdr
+ * Headroom object to interrogate.
+ * @return
+ * Number of jobs.
+ */
+static inline uint16_t
+rte_headroom_job_count(struct rte_headroom *hdr)
+{
+ return hdr->job_count;
+}
+
+/**
+ * Add new job to headroom object.
+ *
+ * @param hdr The headroom object to which job will be added.
+ * @param name Name of ne job. Can be NULL.
+ * @param job_cb Callback for this job.
+ * @param job_data Job's private data pointer.
+ * @param job_handle Output - added job handle. Can be NULL.
+ *
+ * @return 0 on success or negative error code:
+ * -EINVAL if hdr or job_cb is NULL.
+ * -ENOBUFS if there is no space in headroom object to add new job.
+ */
+int
+rte_headroom_add_job(struct rte_headroom *hdr, const char *name,
+ rte_headroom_job_callbak_t job_cb, void *job_data, uint64_t min_period,
+ uint64_t max_period, uint64_t initial_period, int64_t target,
+ struct rte_headroom_job **job_handle);
+
+/**
+ * Remove given job from headroom.
+ *
+ * @param job
+ * Job to be removed.
+ *
+ * @return
+ * Count of remaining jobs in headroom to which belong removed job or negative
+ * error value:
+ * -EINVAL job is NULL
+ */
+int
+rte_headroom_del_job(struct rte_headroom_job *job);
+
+/**
+ * Set job desired target value. Difference between target and job callback
+ * return value must be used to properly adjust job execute period value.
+ * @param job
+ * The job object.
+ * @param target
+ * New target.
+ */
+static inline void
+rte_headroom_set_target(struct rte_headroom_job *job, int64_t target)
+{
+ job->job_target = target;
+}
+
+/**
+ * Set execute period of given job.
+ *
+ * @param job
+ * The job ocbject.
+ * @param period
+ * New period value.
+ * @param saturate
+ * If zero, skip period saturatation to min, max range.
+ */
+static inline void
+rte_headroom_set_period(struct rte_headroom_job *job, uint64_t period,
+ uint8_t saturate)
+{
+ if (saturate != 0) {
+ if (period < job->min_period)
+ period = job->min_period;
+ else if (period > job->max_period)
+ period = job->max_period;
+ }
+
+ job->period = period;
+}
+
+/**
+ * Set minimum execute period of given job.
+ *
+ * @param job
+ * The job ocject.
+ * @param period
+ * New minimum period value.
+ */
+static inline void
+rte_headroom_set_min_period(struct rte_headroom_job *job, uint64_t period)
+{
+ job->min_period = period;
+ if (job->period < period)
+ job->period = period;
+}
+
+/**
+ * Set maximum execute period of given job.
+ *
+ * @param job
+ * The job ocject.
+ * @param period
+ * New maximum period value.
+ */
+static inline void
+rte_headroom_set_max_period(struct rte_headroom_job *job, uint64_t period)
+{
+ job->max_period = period;
+ if (job->period > period)
+ job->period = period;
+}
+
+/**
+ * Set update period callback that is invoked after task finish his job.
+ * If application want to
+ *
+ * @param job
+ * Job object.
+ * @param update_pedriod_cb
+ * Callback to set. If NULL restore default update function.
+ */
+void
+rte_headroom_set_update_period_function(struct rte_headroom_job *job,
+ rte_headroom_update_fn_t update_pedriod_cb);
+
+/**
+ * Retive job stats
+ *
+ * @param job
+ * Job which statistics will be copied.
+ * @param stats
+ * The output stats buffer.
+ *
+ */
+static inline void
+rte_headroom_get_job_stats(struct rte_headroom_job *job,
+ struct rte_headroom_stats *stats)
+{
+ rte_memcpy(stats, &job->stats, sizeof(job->stats));
+}
+
+/**
+ * Function resets job statistics.
+ *
+ * @param job
+ * Job which statistics will be reset.
+ */
+static inline void
+rte_headroom_reset_job_stats(struct rte_headroom_job *job)
+{
+ struct rte_headroom_stats *s = &job->stats;
+
+ s->idle = 0;
+ s->idle_min = UINT64_MAX;
+ s->idle_max = 0;
+
+ s->run_time = 0;
+ s->run_time_min = UINT64_MAX;
+ s->run_time_max = 0;
+
+ s->exec_cnt = 0;
+}
+
+/**
+ * Retive headroom stats
+ *
+ * @param hdr
+ * Headroom which statistics will be copied.
+ * @param stats
+ * The output stats buffer.
+ */
+static inline void
+rte_headroom_get_stats(struct rte_headroom *hdr,
+ struct rte_headroom_stats *stats)
+{
+ rte_memcpy(stats, &hdr->stats, sizeof(hdr->stats));
+}
+
+/**
+ * Function resets headroom statistics.
+ *
+ * @param hdr
+ * Headroom which statistics will be reset.
+ */
+static inline void
+rte_headroom_reset_stats(struct rte_headroom *hdr)
+{
+ struct rte_headroom_stats *s = &hdr->stats;
+
+ s->idle = 0;
+ s->idle_min = UINT64_MAX;
+ s->idle_max = 0;
+
+ s->run_time = 0;
+ s->run_time_min = UINT64_MAX;
+ s->run_time_max = 0;
+
+ s->exec_cnt = 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEADROOM_H_ */
@@ -103,6 +103,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_HASH),y)
LDLIBS += -lrte_hash
endif
+ifeq ($(CONFIG_RTE_LIBRTE_HEADROOM),y)
+LDLIBS += -lrte_headroom
+endif
+
ifeq ($(CONFIG_RTE_LIBRTE_LPM),y)
LDLIBS += -lrte_lpm
endif