cregit-Linux how code gets into the kernel

Release 4.14 net/core/dst.c

Directory: net/core
/*
 * net/core/dst.c       Protocol independent destination cache.
 *
 * Authors:             Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 *
 */

#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/types.h>
#include <net/net_namespace.h>
#include <linux/sched.h>
#include <linux/prefetch.h>
#include <net/lwtunnel.h>

#include <net/dst.h>
#include <net/dst_metadata.h>

/*
 * Theory of operations:
 * 1) We use a list, protected by a spinlock, to add
 *    new entries from both BH and non-BH context.
 * 2) In order to keep spinlock held for a small delay,
 *    we use a second list where are stored long lived
 *    entries, that are handled by the garbage collect thread
 *    fired by a workqueue.
 * 3) This list is guarded by a mutex,
 *    so that the gc_task and dst_dev_event() can be synchronized.
 */

/*
 * We want to keep lock & list close together
 * to dirty as few cache lines as possible in __dst_free().
 * As this is not a very strong hint, we dont force an alignment on SMP.
 */

int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb) { kfree_skb(skb); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang1864.29%120.00%
Eric Dumazet414.29%120.00%
Alexey Kuznetsov310.71%120.00%
Andrew Morton27.14%120.00%
Ingo Molnar13.57%120.00%
Total28100.00%5100.00%

EXPORT_SYMBOL(dst_discard_out); const struct dst_metrics dst_default_metrics = { /* This initializer is needed to force linker to place this variable * into const section. Otherwise it might end into bss section. * We really want to avoid false sharing on this variable, and catch * any writes on it. */ .refcnt = REFCOUNT_INIT(1), };
void dst_init(struct dst_entry *dst, struct dst_ops *ops, struct net_device *dev, int initial_ref, int initial_obsolete, unsigned short flags) { dst->child = NULL; dst->dev = dev; if (dev) dev_hold(dev); dst->ops = ops; dst_init_metrics(dst, dst_default_metrics.metrics, true); dst->expires = 0UL; dst->path = dst; dst->from = NULL; #ifdef CONFIG_XFRM dst->xfrm = NULL; #endif dst->input = dst_discard; dst->output = dst_discard_out; dst->error = 0; dst->obsolete = initial_obsolete; dst->header_len = 0; dst->trailer_len = 0; #ifdef CONFIG_IP_ROUTE_CLASSID dst->tclassid = 0; #endif dst->lwtstate = NULL; atomic_set(&dst->__refcnt, initial_ref); dst->__use = 0; dst->lastuse = jiffies; dst->flags = flags; dst->next = NULL; if (!(flags & DST_NOCOUNT)) dst_entries_add(ops, 1); }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang12964.50%110.00%
Eric Dumazet2311.50%220.00%
Linus Torvalds (pre-git)2211.00%220.00%
Alexey Kuznetsov157.50%220.00%
Denis V. Lunev52.50%110.00%
Arjan van de Ven52.50%110.00%
David S. Miller10.50%110.00%
Total200100.00%10100.00%

EXPORT_SYMBOL(dst_init);
void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, int initial_obsolete, unsigned short flags) { struct dst_entry *dst; if (ops->gc && dst_entries_get_fast(ops) > ops->gc_thresh) { if (ops->gc(ops)) return NULL; } dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC); if (!dst) return NULL; dst_init(dst, ops, dev, initial_ref, initial_obsolete, flags); return dst; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang5657.73%114.29%
David S. Miller2626.80%457.14%
Linus Torvalds (pre-git)1313.40%114.29%
Thomas Graf22.06%114.29%
Total97100.00%7100.00%

EXPORT_SYMBOL(dst_alloc);
struct dst_entry *dst_destroy(struct dst_entry * dst) { struct dst_entry *child; smp_rmb(); child = dst->child; if (!(dst->flags & DST_NOCOUNT)) dst_entries_add(dst->ops, -1); if (dst->ops->destroy) dst->ops->destroy(dst); if (dst->dev) dev_put(dst->dev); lwtstate_put(dst->lwtstate); if (dst->flags & DST_METADATA) metadata_dst_free((struct metadata_dst *)dst); else kmem_cache_free(dst->ops->kmem_cachep, dst); dst = child; if (dst) dst_release_immediate(dst); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang8565.38%19.09%
David S. Miller3023.08%436.36%
Linus Torvalds (pre-git)107.69%218.18%
Jiri Benc21.54%19.09%
Alexey Kuznetsov10.77%19.09%
Thomas Graf10.77%19.09%
Hideaki Yoshifuji / 吉藤英明10.77%19.09%
Total130100.00%11100.00%

EXPORT_SYMBOL(dst_destroy);
static void dst_destroy_rcu(struct rcu_head *head) { struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); dst = dst_destroy(dst); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf1854.55%133.33%
Wei Wang1442.42%133.33%
Linus Torvalds (pre-git)13.03%133.33%
Total33100.00%3100.00%

/* Operations to mark dst as DEAD and clean up the net device referenced * by dst: * 1. put the dst under loopback interface and discard all tx/rx packets * on this route. * 2. release the net_device * This function should be called when removing routes from the fib tree * in preparation for a NETDEV_DOWN/NETDEV_UNREGISTER event and also to * make the next dst_ops->check() fail. */
void dst_dev_put(struct dst_entry *dst) { struct net_device *dev = dst->dev; dst->obsolete = DST_OBSOLETE_DEAD; if (dst->ops->ifdown) dst->ops->ifdown(dst, dev, true); dst->input = dst_discard; dst->output = dst_discard_out; dst->dev = dev_net(dst->dev)->loopback_dev; dev_hold(dst->dev); dev_put(dev); }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang5161.45%116.67%
Linus Torvalds (pre-git)2833.73%233.33%
Eric Dumazet22.41%116.67%
Alexey Kuznetsov11.20%116.67%
Eric W. Biedermann11.20%116.67%
Total83100.00%6100.00%

EXPORT_SYMBOL(dst_dev_put);
void dst_release(struct dst_entry *dst) { if (dst) { int newrefcnt; newrefcnt = atomic_dec_return(&dst->__refcnt); if (unlikely(newrefcnt < 0)) net_warn_ratelimited("%s: dst:%p refcnt:%d\n", __func__, dst, newrefcnt); if (!newrefcnt) call_rcu(&dst->rcu_head, dst_destroy_rcu); } }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang3960.94%116.67%
Linus Torvalds (pre-git)1320.31%233.33%
Alexey Kuznetsov914.06%116.67%
Vinay K. Nallamothu23.12%116.67%
Tejun Heo11.56%116.67%
Total64100.00%6100.00%

EXPORT_SYMBOL(dst_release);
void dst_release_immediate(struct dst_entry *dst) { if (dst) { int newrefcnt; newrefcnt = atomic_dec_return(&dst->__refcnt); if (unlikely(newrefcnt < 0)) net_warn_ratelimited("%s: dst:%p refcnt:%d\n", __func__, dst, newrefcnt); if (!newrefcnt) dst_destroy(dst); } }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang3254.24%116.67%
Linus Torvalds (pre-git)2033.90%233.33%
Alexey Kuznetsov58.47%116.67%
Eric Dumazet11.69%116.67%
David S. Miller11.69%116.67%
Total59100.00%6100.00%

EXPORT_SYMBOL(dst_release_immediate);
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old) { struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC); if (p) { struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old); unsigned long prev, new; refcount_set(&p->refcnt, 1); memcpy(p->metrics, old_p->metrics, sizeof(p->metrics)); new = (unsigned long) p; prev = cmpxchg(&dst->_metrics, old, new); if (prev != old) { kfree(p); p = (struct dst_metrics *)__DST_METRICS_PTR(prev); if (prev & DST_METRICS_READ_ONLY) p = NULL; } else if (prev & DST_METRICS_REFCOUNTED) { if (refcount_dec_and_test(&old_p->refcnt)) kfree(old_p); } } BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0); return (u32 *)p; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang15281.28%220.00%
Linus Torvalds (pre-git)115.88%220.00%
Alexey Kuznetsov94.81%220.00%
Américo Wang52.67%110.00%
Paolo Abeni42.14%110.00%
Thomas Graf42.14%110.00%
Eric Dumazet21.07%110.00%
Total187100.00%10100.00%

EXPORT_SYMBOL(dst_cow_metrics_generic); /* Caller asserts that dst_metrics_read_only(dst) is false. */
void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old) { unsigned long prev, new; new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY; prev = cmpxchg(&dst->_metrics, old, new); if (prev == old) kfree(__DST_METRICS_PTR(old)); }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang4878.69%150.00%
Eric Dumazet1321.31%150.00%
Total61100.00%2100.00%

EXPORT_SYMBOL(__dst_destroy_metrics_generic); static struct dst_ops md_dst_ops = { .family = AF_UNSPEC, };
static int dst_md_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb) { WARN_ONCE(1, "Attempting to call output on metadata dst\n"); kfree_skb(skb); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang36100.00%1100.00%
Total36100.00%1100.00%


static int dst_md_discard(struct sk_buff *skb) { WARN_ONCE(1, "Attempting to call input on metadata dst\n"); kfree_skb(skb); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang26100.00%1100.00%
Total26100.00%1100.00%


static void __metadata_dst_init(struct metadata_dst *md_dst, enum metadata_type type, u8 optslen) { struct dst_entry *dst; dst = &md_dst->dst; dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, DST_METADATA | DST_NOCOUNT); dst->input = dst_md_discard; dst->output = dst_md_discard_out; memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst)); md_dst->type = type; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang7988.76%266.67%
Jakub Kiciński1011.24%133.33%
Total89100.00%3100.00%


struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t flags) { struct metadata_dst *md_dst; md_dst = kmalloc(sizeof(*md_dst) + optslen, flags); if (!md_dst) return NULL; __metadata_dst_init(md_dst, type, optslen); return md_dst; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang3052.63%112.50%
Eric Dumazet1322.81%450.00%
Jakub Kiciński610.53%112.50%
Ilpo Järvinen610.53%112.50%
Konstantin Khlebnikov23.51%112.50%
Total57100.00%8100.00%

EXPORT_SYMBOL_GPL(metadata_dst_alloc);
void metadata_dst_free(struct metadata_dst *md_dst) { #ifdef CONFIG_DST_CACHE if (md_dst->type == METADATA_IP_TUNNEL) dst_cache_destroy(&md_dst->u.tun_info.dst_cache); #endif kfree(md_dst); }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang3280.00%266.67%
David Lamparter820.00%133.33%
Total40100.00%3100.00%


struct metadata_dst __percpu * metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags) { int cpu; struct metadata_dst __percpu *md_dst; md_dst = __alloc_percpu_gfp(sizeof(struct metadata_dst) + optslen, __alignof__(struct metadata_dst), flags); if (!md_dst) return NULL; for_each_possible_cpu(cpu) __metadata_dst_init(per_cpu_ptr(md_dst, cpu), type, optslen); return md_dst; }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang4457.14%125.00%
David S. Miller2228.57%125.00%
Jakub Kiciński67.79%125.00%
Eric Dumazet56.49%125.00%
Total77100.00%4100.00%

EXPORT_SYMBOL_GPL(metadata_dst_alloc_percpu);

Overall Contributors

PersonTokensPropCommitsCommitProp
Wei Wang92765.79%46.90%
Linus Torvalds (pre-git)14210.08%813.79%
David S. Miller845.96%915.52%
Eric Dumazet775.46%1017.24%
Alexey Kuznetsov433.05%35.17%
Thomas Graf322.27%11.72%
Jakub Kiciński221.56%11.72%
Ilpo Järvinen90.64%11.72%
Arnaldo Carvalho de Melo90.64%11.72%
David Lamparter80.57%11.72%
Américo Wang50.35%11.72%
Denis V. Lunev50.35%11.72%
Jiri Benc50.35%11.72%
Arjan van de Ven50.35%11.72%
Nicolas Dichtel40.28%11.72%
Laurent Chavey40.28%11.72%
Tejun Heo40.28%23.45%
Paolo Abeni40.28%11.72%
Herbert Xu40.28%11.72%
Eric W. Biedermann40.28%23.45%
Linus Torvalds30.21%11.72%
Konstantin Khlebnikov20.14%11.72%
Vinay K. Nallamothu20.14%11.72%
Andrew Morton20.14%11.72%
Christoph Hellwig10.07%11.72%
Hideaki Yoshifuji / 吉藤英明10.07%11.72%
Ingo Molnar10.07%11.72%
Total1409100.00%58100.00%
Directory: net/core
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.