2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-19 14:37:21 +00:00
Files
openvswitch/datapath/loop_counter.c
Ben Pfaff cdee00fd63 datapath: Replace "struct odp_action" by Netlink attributes.
In the medium term, we plan to migrate the datapath to use Netlink as its
communication channel.  In the short term, we need to be able to have
actions with 64-bit arguments but "struct odp_action" only has room for
48 bits.  So this patch shifts to variable-length arguments using Netlink
attributes, which starts in on the Netlink transition and makes 64-bit
arguments possible at the same time.

Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
2010-12-10 11:13:32 -08:00

72 lines
1.7 KiB
C

/*
* Distributed under the terms of the GNU GPL version 2.
* Copyright (c) 2010 Nicira Networks.
*
* Significant portions of this file may be copied from parts of the Linux
* kernel, by Linus Torvalds and others.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/percpu.h>
#include <linux/sched.h>
#include "loop_counter.h"
void loop_suppress(struct datapath *dp, struct sw_flow_actions *actions)
{
if (net_ratelimit())
pr_warn("%s: flow looped %d times, dropping\n",
dp_name(dp), MAX_LOOPS);
actions->actions_len = 0;
}
#ifndef CONFIG_PREEMPT_RT
/* We use a separate counter for each CPU for both interrupt and non-interrupt
* context in order to keep the limit deterministic for a given packet.
*/
struct percpu_loop_counters {
struct loop_counter counters[2];
};
static DEFINE_PER_CPU(struct percpu_loop_counters, loop_counters);
struct loop_counter *loop_get_counter(void)
{
return &get_cpu_var(loop_counters).counters[!!in_interrupt()];
}
void loop_put_counter(void)
{
put_cpu_var(loop_counters);
}
#else /* !CONFIG_PREEMPT_RT */
struct loop_counter *loop_get_counter(void)
{
WARN_ON(in_interrupt());
/* Only two bits of the extra_flags field in struct task_struct are
* used and it's an unsigned int. We hijack the most significant bits
* to be our counter structure. On RT kernels softirqs always run in
* process context so we are guaranteed to have a valid task_struct.
*/
#ifdef __LITTLE_ENDIAN
return (void *)(&current->extra_flags + 1) -
sizeof(struct loop_counter);
#elif __BIG_ENDIAN
return (struct loop_counter *)&current->extra_flags;
#else
#error "Please fix <asm/byteorder.h>."
#endif
}
void loop_put_counter(void) { }
#endif /* CONFIG_PREEMPT_RT */