Release 4.11 net/core/flow.c
/* flow.c: Generic flow cache.
*
* Copyright (C) 2003 Alexey N. Kuznetsov (kuznet@ms2.inr.ac.ru)
* Copyright (C) 2003 David S. Miller (davem@redhat.com)
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/jhash.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/completion.h>
#include <linux/percpu.h>
#include <linux/bitops.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/mutex.h>
#include <net/flow.h>
#include <linux/atomic.h>
#include <linux/security.h>
#include <net/net_namespace.h>
struct flow_cache_entry {
union {
struct hlist_node hlist;
struct list_head gc_list;
}
u;
struct net *net;
u16 family;
u8 dir;
u32 genid;
struct flowi key;
struct flow_cache_object *object;
};
struct flow_flush_info {
struct flow_cache *cache;
atomic_t cpuleft;
struct completion completion;
};
static struct kmem_cache *flow_cachep __read_mostly;
#define flow_cache_hash_size(cache) (1 << (cache)->hash_shift)
#define FLOW_HASH_RND_PERIOD (10 * 60 * HZ)
static void flow_cache_new_hashrnd(unsigned long arg)
{
struct flow_cache *fc = (void *) arg;
int i;
for_each_possible_cpu(i)
per_cpu_ptr(fc->percpu, i)->hash_rnd_recalc = 1;
fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
add_timer(&fc->rnd_timer);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David S. Miller | 31 | 52.54% | 2 | 33.33% |
Timo Teräs | 24 | 40.68% | 1 | 16.67% |
Herbert Xu | 2 | 3.39% | 1 | 16.67% |
Kamezawa Hiroyuki | 1 | 1.69% | 1 | 16.67% |
Rusty Russell | 1 | 1.69% | 1 | 16.67% |
Total | 59 | 100.00% | 6 | 100.00% |
static int flow_entry_valid(struct flow_cache_entry *fle,
struct netns_xfrm *xfrm)
{
if (atomic_read(&xfrm->flow_cache_genid) != fle->genid)
return 0;
if (fle->object && !fle->object->ops->check(fle->object))
return 0;
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 52 | 88.14% | 1 | 50.00% |
Fan Du | 7 | 11.86% | 1 | 50.00% |
Total | 59 | 100.00% | 2 | 100.00% |
static void flow_entry_kill(struct flow_cache_entry *fle,
struct netns_xfrm *xfrm)
{
if (fle->object)
fle->object->ops->delete(fle->object);
kmem_cache_free(flow_cachep, fle);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Morris | 27 | 64.29% | 1 | 20.00% |
Timo Teräs | 10 | 23.81% | 3 | 60.00% |
Fan Du | 5 | 11.90% | 1 | 20.00% |
Total | 42 | 100.00% | 5 | 100.00% |
static void flow_cache_gc_task(struct work_struct *work)
{
struct list_head gc_list;
struct flow_cache_entry *fce, *n;
struct netns_xfrm *xfrm = container_of(work, struct netns_xfrm,
flow_cache_gc_work);
INIT_LIST_HEAD(&gc_list);
spin_lock_bh(&xfrm->flow_cache_gc_lock);
list_splice_tail_init(&xfrm->flow_cache_gc_list, &gc_list);
spin_unlock_bh(&xfrm->flow_cache_gc_lock);
list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) {
flow_entry_kill(fce, xfrm);
atomic_dec(&xfrm->flow_cache_gc_count);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 65 | 66.33% | 1 | 33.33% |
Fan Du | 23 | 23.47% | 1 | 33.33% |
Steffen Klassert | 10 | 10.20% | 1 | 33.33% |
Total | 98 | 100.00% | 3 | 100.00% |
static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp,
int deleted, struct list_head *gc_list,
struct netns_xfrm *xfrm)
{
if (deleted) {
atomic_add(deleted, &xfrm->flow_cache_gc_count);
fcp->hash_count -= deleted;
spin_lock_bh(&xfrm->flow_cache_gc_lock);
list_splice_tail(gc_list, &xfrm->flow_cache_gc_list);
spin_unlock_bh(&xfrm->flow_cache_gc_lock);
schedule_work(&xfrm->flow_cache_gc_work);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 55 | 68.75% | 2 | 40.00% |
Fan Du | 13 | 16.25% | 1 | 20.00% |
Steffen Klassert | 10 | 12.50% | 1 | 20.00% |
James Morris | 2 | 2.50% | 1 | 20.00% |
Total | 80 | 100.00% | 5 | 100.00% |
static void __flow_cache_shrink(struct flow_cache *fc,
struct flow_cache_percpu *fcp,
int shrink_to)
{
struct flow_cache_entry *fle;
struct hlist_node *tmp;
LIST_HEAD(gc_list);
int i, deleted = 0;
struct netns_xfrm *xfrm = container_of(fc, struct netns_xfrm,
flow_cache_global);
for (i = 0; i < flow_cache_hash_size(fc); i++) {
int saved = 0;
hlist_for_each_entry_safe(fle, tmp,
&fcp->hash_table[i], u.hlist) {
if (saved < shrink_to &&
flow_entry_valid(fle, xfrm)) {
saved++;
} else {
deleted++;
hlist_del(&fle->u.hlist);
list_add_tail(&fle->u.gc_list, &gc_list);
}
}
}
flow_cache_queue_garbage(fcp, deleted, &gc_list, xfrm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 78 | 52.00% | 3 | 50.00% |
David S. Miller | 53 | 35.33% | 2 | 33.33% |
Fan Du | 19 | 12.67% | 1 | 16.67% |
Total | 150 | 100.00% | 6 | 100.00% |
static void flow_cache_shrink(struct flow_cache *fc,
struct flow_cache_percpu *fcp)
{
int shrink_to = fc->low_watermark / flow_cache_hash_size(fc);
__flow_cache_shrink(fc, fcp, shrink_to);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 19 | 51.35% | 1 | 50.00% |
David S. Miller | 18 | 48.65% | 1 | 50.00% |
Total | 37 | 100.00% | 2 | 100.00% |
static void flow_new_hash_rnd(struct flow_cache *fc,
struct flow_cache_percpu *fcp)
{
get_random_bytes(&fcp->hash_rnd, sizeof(u32));
fcp->hash_rnd_recalc = 0;
__flow_cache_shrink(fc, fcp, 0);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David S. Miller | 26 | 59.09% | 1 | 50.00% |
Timo Teräs | 18 | 40.91% | 1 | 50.00% |
Total | 44 | 100.00% | 2 | 100.00% |
static u32 flow_hash_code(struct flow_cache *fc,
struct flow_cache_percpu *fcp,
const struct flowi *key,
size_t keysize)
{
const u32 *k = (const u32 *) key;
const u32 length = keysize * sizeof(flow_compare_t) / sizeof(u32);
return jhash2(k, length, fcp->hash_rnd)
& (flow_cache_hash_size(fc) - 1);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David S. Miller | 40 | 54.05% | 2 | 50.00% |
Timo Teräs | 17 | 22.97% | 1 | 25.00% |
David Ward | 17 | 22.97% | 1 | 25.00% |
Total | 74 | 100.00% | 4 | 100.00% |
/* I hear what you're saying, use memcmp. But memcmp cannot make
* important assumptions that we can here, such as alignment.
*/
static int flow_key_compare(const struct flowi *key1, const struct flowi *key2,
size_t keysize)
{
const flow_compare_t *k1, *k1_lim, *k2;
k1 = (const flow_compare_t *) key1;
k1_lim = k1 + keysize;
k2 = (const flow_compare_t *) key2;
do {
if (*k1++ != *k2++)
return 1;
} while (k1 < k1_lim);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David S. Miller | 78 | 95.12% | 2 | 66.67% |
David Ward | 4 | 4.88% | 1 | 33.33% |
Total | 82 | 100.00% | 3 | 100.00% |
struct flow_cache_object *
flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
flow_resolve_t resolver, void *ctx)
{
struct flow_cache *fc = &net->xfrm.flow_cache_global;
struct flow_cache_percpu *fcp;
struct flow_cache_entry *fle, *tfle;
struct flow_cache_object *flo;
size_t keysize;
unsigned int hash;
local_bh_disable();
fcp = this_cpu_ptr(fc->percpu);
fle = NULL;
flo = NULL;
keysize = flow_key_size(family);
if (!keysize)
goto nocache;
/* Packet really early in init? Making flow_cache_init a
* pre-smp initcall would solve this. --RR */
if (!fcp->hash_table)
goto nocache;
if (fcp->hash_rnd_recalc)
flow_new_hash_rnd(fc, fcp);
hash = flow_hash_code(fc, fcp, key, keysize);
hlist_for_each_entry(tfle, &fcp->hash_table[hash], u.hlist) {
if (tfle->net == net &&
tfle->family == family &&
tfle->dir == dir &&
flow_key_compare(key, &tfle->key, keysize) == 0) {
fle = tfle;
break;
}
}
if (unlikely(!fle)) {
if (fcp->hash_count > fc->high_watermark)
flow_cache_shrink(fc, fcp);
if (atomic_read(&net->xfrm.flow_cache_gc_count) >
2 * num_online_cpus() * fc->high_watermark) {
flo = ERR_PTR(-ENOBUFS);
goto ret_object;
}
fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
if (fle) {
fle->net = net;
fle->family = family;
fle->dir = dir;
memcpy(&fle->key, key, keysize * sizeof(flow_compare_t));
fle->object = NULL;
hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);
fcp->hash_count++;
}
} else if (likely(fle->genid == atomic_read(&net->xfrm.flow_cache_genid))) {
flo = fle->object;
if (!flo)
goto ret_object;
flo = flo->ops->get(flo);
if (flo)
goto ret_object;
} else if (fle->object) {
flo = fle->object;
flo->ops->delete(flo);
fle->object = NULL;
}
nocache:
flo = NULL;
if (fle) {
flo = fle->object;
fle->object = NULL;
}
flo = resolver(net, key, family, dir, flo, ctx);
if (fle) {
fle->genid = atomic_read(&net->xfrm.flow_cache_genid);
if (!IS_ERR(flo))
fle->object = flo;
else
fle->genid--;
} else {
if (!IS_ERR_OR_NULL(flo))
flo->ops->delete(flo);
}
ret_object:
local_bh_enable();
return flo;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 227 | 43.32% | 3 | 15.79% |
David S. Miller | 118 | 22.52% | 3 | 15.79% |
Herbert Xu | 82 | 15.65% | 2 | 10.53% |
David Ward | 37 | 7.06% | 2 | 10.53% |
Steffen Klassert | 29 | 5.53% | 1 | 5.26% |
Fan Du | 12 | 2.29% | 1 | 5.26% |
Alexey Dobriyan | 7 | 1.34% | 1 | 5.26% |
Miroslav Urbanek | 5 | 0.95% | 1 | 5.26% |
James Morris | 3 | 0.57% | 1 | 5.26% |
Eric Dumazet | 1 | 0.19% | 1 | 5.26% |
Christoph Lameter | 1 | 0.19% | 1 | 5.26% |
Rusty Russell | 1 | 0.19% | 1 | 5.26% |
Hideaki Yoshifuji / 吉藤英明 | 1 | 0.19% | 1 | 5.26% |
Total | 524 | 100.00% | 19 | 100.00% |
EXPORT_SYMBOL(flow_cache_lookup);
static void flow_cache_flush_tasklet(unsigned long data)
{
struct flow_flush_info *info = (void *)data;
struct flow_cache *fc = info->cache;
struct flow_cache_percpu *fcp;
struct flow_cache_entry *fle;
struct hlist_node *tmp;
LIST_HEAD(gc_list);
int i, deleted = 0;
struct netns_xfrm *xfrm = container_of(fc, struct netns_xfrm,
flow_cache_global);
fcp = this_cpu_ptr(fc->percpu);
for (i = 0; i < flow_cache_hash_size(fc); i++) {
hlist_for_each_entry_safe(fle, tmp,
&fcp->hash_table[i], u.hlist) {
if (flow_entry_valid(fle, xfrm))
continue;
deleted++;
hlist_del(&fle->u.hlist);
list_add_tail(&fle->u.gc_list, &gc_list);
}
}
flow_cache_queue_garbage(fcp, deleted, &gc_list, xfrm);
if (atomic_dec_and_test(&info->cpuleft))
complete(&info->completion);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 92 | 51.98% | 3 | 37.50% |
Herbert Xu | 60 | 33.90% | 2 | 25.00% |
Fan Du | 19 | 10.73% | 1 | 12.50% |
David S. Miller | 5 | 2.82% | 1 | 12.50% |
Eric Dumazet | 1 | 0.56% | 1 | 12.50% |
Total | 177 | 100.00% | 8 | 100.00% |
/*
* Return whether a cpu needs flushing. Conservatively, we assume
* the presence of any entries means the core may require flushing,
* since the flow_cache_ops.check() function may assume it's running
* on the same core as the per-cpu cache component.
*/
static int flow_cache_percpu_empty(struct flow_cache *fc, int cpu)
{
struct flow_cache_percpu *fcp;
int i;
fcp = per_cpu_ptr(fc->percpu, cpu);
for (i = 0; i < flow_cache_hash_size(fc); i++)
if (!hlist_empty(&fcp->hash_table[i]))
return 0;
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Chris Metcalf | 68 | 98.55% | 1 | 50.00% |
Li RongQing | 1 | 1.45% | 1 | 50.00% |
Total | 69 | 100.00% | 2 | 100.00% |
static void flow_cache_flush_per_cpu(void *data)
{
struct flow_flush_info *info = data;
struct tasklet_struct *tasklet;
tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet;
tasklet->data = (unsigned long)info;
tasklet_schedule(tasklet);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Herbert Xu | 37 | 72.55% | 2 | 33.33% |
Timo Teräs | 7 | 13.73% | 1 | 16.67% |
David S. Miller | 4 | 7.84% | 1 | 16.67% |
Li RongQing | 2 | 3.92% | 1 | 16.67% |
Shan Wei | 1 | 1.96% | 1 | 16.67% |
Total | 51 | 100.00% | 6 | 100.00% |
void flow_cache_flush(struct net *net)
{
struct flow_flush_info info;
cpumask_var_t mask;
int i, self;
/* Track which cpus need flushing to avoid disturbing all cores. */
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return;
cpumask_clear(mask);
/* Don't want cpus going down or up during this. */
get_online_cpus();
mutex_lock(&net->xfrm.flow_flush_sem);
info.cache = &net->xfrm.flow_cache_global;
for_each_online_cpu(i)
if (!flow_cache_percpu_empty(info.cache, i))
cpumask_set_cpu(i, mask);
atomic_set(&info.cpuleft, cpumask_weight(mask));
if (atomic_read(&info.cpuleft) == 0)
goto done;
init_completion(&info.completion);
local_bh_disable();
self = cpumask_test_and_clear_cpu(smp_processor_id(), mask);
on_each_cpu_mask(mask, flow_cache_flush_per_cpu, &info, 0);
if (self)
flow_cache_flush_tasklet((unsigned long)&info);
local_bh_enable();
wait_for_completion(&info.completion);
done:
mutex_unlock(&net->xfrm.flow_flush_sem);
put_online_cpus();
free_cpumask_var(mask);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Chris Metcalf | 92 | 47.42% | 1 | 8.33% |
Herbert Xu | 50 | 25.77% | 4 | 33.33% |
Fan Du | 16 | 8.25% | 1 | 8.33% |
Andrew Morton | 13 | 6.70% | 2 | 16.67% |
David S. Miller | 12 | 6.19% | 1 | 8.33% |
Timo Teräs | 7 | 3.61% | 1 | 8.33% |
Gautham R. Shenoy | 2 | 1.03% | 1 | 8.33% |
Arjan van de Ven | 2 | 1.03% | 1 | 8.33% |
Total | 194 | 100.00% | 12 | 100.00% |
static void flow_cache_flush_task(struct work_struct *work)
{
struct netns_xfrm *xfrm = container_of(work, struct netns_xfrm,
flow_cache_flush_work);
struct net *net = container_of(xfrm, struct net, xfrm);
flow_cache_flush(net);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Fan Du | 31 | 67.39% | 1 | 33.33% |
Steffen Klassert | 14 | 30.43% | 1 | 33.33% |
Miroslav Urbanek | 1 | 2.17% | 1 | 33.33% |
Total | 46 | 100.00% | 3 | 100.00% |
void flow_cache_flush_deferred(struct net *net)
{
schedule_work(&net->xfrm.flow_cache_flush_work);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Steffen Klassert | 12 | 60.00% | 1 | 50.00% |
Fan Du | 8 | 40.00% | 1 | 50.00% |
Total | 20 | 100.00% | 2 | 100.00% |
static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu)
{
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
size_t sz = sizeof(struct hlist_head) * flow_cache_hash_size(fc);
if (!fcp->hash_table) {
fcp->hash_table = kzalloc_node(sz, GFP_KERNEL, cpu_to_node(cpu));
if (!fcp->hash_table) {
pr_err("NET: failed to allocate flow cache sz %zu\n", sz);
return -ENOMEM;
}
fcp->hash_rnd_recalc = 1;
fcp->hash_count = 0;
tasklet_init(&fcp->flush_tasklet, flow_cache_flush_tasklet, 0);
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Eric Dumazet | 56 | 49.12% | 1 | 14.29% |
Timo Teräs | 24 | 21.05% | 1 | 14.29% |
Herbert Xu | 19 | 16.67% | 2 | 28.57% |
David S. Miller | 11 | 9.65% | 2 | 28.57% |
Rusty Russell | 4 | 3.51% | 1 | 14.29% |
Total | 114 | 100.00% | 7 | 100.00% |
static int flow_cache_cpu_up_prep(unsigned int cpu, struct hlist_node *node)
{
struct flow_cache *fc = hlist_entry_safe(node, struct flow_cache, node);
return flow_cache_cpu_prepare(fc, cpu);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sebastian Andrzej Siewior | 18 | 47.37% | 1 | 33.33% |
Timo Teräs | 12 | 31.58% | 1 | 33.33% |
Rusty Russell | 8 | 21.05% | 1 | 33.33% |
Total | 38 | 100.00% | 3 | 100.00% |
static int flow_cache_cpu_dead(unsigned int cpu, struct hlist_node *node)
{
struct flow_cache *fc = hlist_entry_safe(node, struct flow_cache, node);
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
__flow_cache_shrink(fc, fcp, 0);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sebastian Andrzej Siewior | 26 | 46.43% | 1 | 33.33% |
Timo Teräs | 21 | 37.50% | 1 | 33.33% |
Rusty Russell | 9 | 16.07% | 1 | 33.33% |
Total | 56 | 100.00% | 3 | 100.00% |
int flow_cache_init(struct net *net)
{
int i;
struct flow_cache *fc = &net->xfrm.flow_cache_global;
if (!flow_cachep)
flow_cachep = kmem_cache_create("flow_cache",
sizeof(struct flow_cache_entry),
0, SLAB_PANIC, NULL);
spin_lock_init(&net->xfrm.flow_cache_gc_lock);
INIT_LIST_HEAD(&net->xfrm.flow_cache_gc_list);
INIT_WORK(&net->xfrm.flow_cache_gc_work, flow_cache_gc_task);
INIT_WORK(&net->xfrm.flow_cache_flush_work, flow_cache_flush_task);
mutex_init(&net->xfrm.flow_flush_sem);
atomic_set(&net->xfrm.flow_cache_gc_count, 0);
fc->hash_shift = 10;
fc->low_watermark = 2 * flow_cache_hash_size(fc);
fc->high_watermark = 4 * flow_cache_hash_size(fc);
fc->percpu = alloc_percpu(struct flow_cache_percpu);
if (!fc->percpu)
return -ENOMEM;
if (cpuhp_state_add_instance(CPUHP_NET_FLOW_PREPARE, &fc->node))
goto err;
setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
(unsigned long) fc);
fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
add_timer(&fc->rnd_timer);
return 0;
err:
for_each_possible_cpu(i) {
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
kfree(fcp->hash_table);
fcp->hash_table = NULL;
}
free_percpu(fc->percpu);
fc->percpu = NULL;
return -ENOMEM;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Fan Du | 87 | 32.46% | 1 | 9.09% |
Huajun Li | 55 | 20.52% | 1 | 9.09% |
Timo Teräs | 48 | 17.91% | 1 | 9.09% |
Eric Dumazet | 26 | 9.70% | 2 | 18.18% |
David S. Miller | 22 | 8.21% | 1 | 9.09% |
Steffen Klassert | 12 | 4.48% | 1 | 9.09% |
Herbert Xu | 8 | 2.99% | 2 | 18.18% |
Sebastian Andrzej Siewior | 6 | 2.24% | 1 | 9.09% |
Pavel Emelyanov | 4 | 1.49% | 1 | 9.09% |
Total | 268 | 100.00% | 11 | 100.00% |
EXPORT_SYMBOL(flow_cache_init);
void flow_cache_fini(struct net *net)
{
int i;
struct flow_cache *fc = &net->xfrm.flow_cache_global;
del_timer_sync(&fc->rnd_timer);
cpuhp_state_remove_instance_nocalls(CPUHP_NET_FLOW_PREPARE, &fc->node);
for_each_possible_cpu(i) {
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
kfree(fcp->hash_table);
fcp->hash_table = NULL;
}
free_percpu(fc->percpu);
fc->percpu = NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Steffen Klassert | 85 | 95.51% | 1 | 50.00% |
Sebastian Andrzej Siewior | 4 | 4.49% | 1 | 50.00% |
Total | 89 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(flow_cache_fini);
void __init flow_cache_hp_init(void)
{
int ret;
ret = cpuhp_setup_state_multi(CPUHP_NET_FLOW_PREPARE,
"net/flow:prepare",
flow_cache_cpu_up_prep,
flow_cache_cpu_dead);
WARN_ON(ret < 0);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sebastian Andrzej Siewior | 31 | 100.00% | 1 | 100.00% |
Total | 31 | 100.00% | 1 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Timo Teräs | 801 | 31.30% | 3 | 6.00% |
David S. Miller | 468 | 18.29% | 4 | 8.00% |
Herbert Xu | 297 | 11.61% | 8 | 16.00% |
Fan Du | 245 | 9.57% | 1 | 2.00% |
Steffen Klassert | 177 | 6.92% | 3 | 6.00% |
Chris Metcalf | 161 | 6.29% | 1 | 2.00% |
Eric Dumazet | 99 | 3.87% | 5 | 10.00% |
Sebastian Andrzej Siewior | 85 | 3.32% | 1 | 2.00% |
David Ward | 64 | 2.50% | 2 | 4.00% |
Huajun Li | 55 | 2.15% | 1 | 2.00% |
James Morris | 32 | 1.25% | 1 | 2.00% |
Rusty Russell | 23 | 0.90% | 2 | 4.00% |
Andrew Morton | 13 | 0.51% | 2 | 4.00% |
Alexey Dobriyan | 7 | 0.27% | 1 | 2.00% |
Miroslav Urbanek | 6 | 0.23% | 2 | 4.00% |
Arjan van de Ven | 5 | 0.20% | 1 | 2.00% |
Pavel Emelyanov | 4 | 0.16% | 1 | 2.00% |
Arnaldo Carvalho de Melo | 3 | 0.12% | 1 | 2.00% |
Linus Torvalds | 3 | 0.12% | 1 | 2.00% |
Li RongQing | 3 | 0.12% | 2 | 4.00% |
Gautham R. Shenoy | 2 | 0.08% | 1 | 2.00% |
Kamezawa Hiroyuki | 1 | 0.04% | 1 | 2.00% |
Trent Jaeger | 1 | 0.04% | 1 | 2.00% |
Hideaki Yoshifuji / 吉藤英明 | 1 | 0.04% | 1 | 2.00% |
Shan Wei | 1 | 0.04% | 1 | 2.00% |
Christoph Lameter | 1 | 0.04% | 1 | 2.00% |
Arun Sharma | 1 | 0.04% | 1 | 2.00% |
Total | 2559 | 100.00% | 50 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.