cregit-Linux how code gets into the kernel

Release 4.16 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/xfrm.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->dev = dev; if (dev) dev_hold(dev); dst->ops = ops; dst_init_metrics(dst, dst_default_metrics.metrics, true); dst->expires = 0UL; #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; if (!(flags & DST_NOCOUNT)) dst_entries_add(ops, 1); }

Contributors

PersonTokensPropCommitsCommitProp
Wei Wang11565.34%110.00%
Linus Torvalds (pre-git)1810.23%220.00%
Eric Dumazet1810.23%220.00%
Alexey Kuznetsov158.52%220.00%
Arjan van de Ven52.84%110.00%
Denis V. Lunev42.27%110.00%
David S. Miller10.57%110.00%
Total176100.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 = NULL; smp_rmb(); #ifdef CONFIG_XFRM if (dst->xfrm) { struct xfrm_dst *xdst = (struct xfrm_dst *) dst; child = xdst->child; } #endif 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 Wang8554.14%17.69%
David S. Miller5736.31%646.15%
Linus Torvalds (pre-git)106.37%215.38%
Jiri Benc21.27%17.69%
Alexey Kuznetsov10.64%17.69%
Hideaki Yoshifuji / 吉藤英明10.64%17.69%
Thomas Graf10.64%17.69%
Total157100.00%13100.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 Graf1751.52%133.33%
Wei Wang1545.45%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%
Eric W. Biedermann11.20%116.67%
Alexey Kuznetsov11.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%
Thomas Graf42.14%110.00%
Paolo Abeni42.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
David S. Miller4573.77%120.00%
Wei Wang1118.03%240.00%
Eric Dumazet58.20%240.00%
Total61100.00%5100.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
Thomas Graf3083.33%150.00%
Eric W. Biedermann616.67%150.00%
Total36100.00%2100.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
Thomas Graf26100.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
Thomas Graf7179.78%125.00%
Jakub Kiciński1011.24%125.00%
Alexei Starovoitov77.87%125.00%
Eric W. Biedermann11.12%125.00%
Total89100.00%4100.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
Alexei Starovoitov2950.88%116.67%
Wei Wang1424.56%116.67%
Herbert Xu712.28%233.33%
Jakub Kiciński610.53%116.67%
Linus Torvalds (pre-git)11.75%116.67%
Total57100.00%6100.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 Wang2460.00%120.00%
David Lamparter820.00%120.00%
Linus Torvalds (pre-git)410.00%120.00%
Hideaki Yoshifuji / 吉藤英明37.50%120.00%
Daniel Lezcano12.50%120.00%
Total40100.00%5100.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 Wang4254.55%114.29%
Eric Dumazet810.39%114.29%
Herbert Xu810.39%114.29%
Linus Torvalds (pre-git)67.79%114.29%
Jakub Kiciński67.79%114.29%
Krister Johansen56.49%114.29%
Hideaki Yoshifuji / 吉藤英明22.60%114.29%
Total77100.00%7100.00%

EXPORT_SYMBOL_GPL(metadata_dst_alloc_percpu);
void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst) { #ifdef CONFIG_DST_CACHE int cpu; for_each_possible_cpu(cpu) { struct metadata_dst *one_md_dst = per_cpu_ptr(md_dst, cpu); if (one_md_dst->type == METADATA_IP_TUNNEL) dst_cache_destroy(&one_md_dst->u.tun_info.dst_cache); } #endif free_percpu(md_dst); }

Contributors

PersonTokensPropCommitsCommitProp
Jakub Kiciński62100.00%2100.00%
Total62100.00%2100.00%

EXPORT_SYMBOL_GPL(metadata_dst_free_percpu);

Overall Contributors

PersonTokensPropCommitsCommitProp
Wei Wang69346.76%34.69%
Thomas Graf17011.47%11.56%
Linus Torvalds (pre-git)15310.32%914.06%
David S. Miller1399.38%1117.19%
Jakub Kiciński896.01%34.69%
Eric Dumazet543.64%710.94%
Alexey Kuznetsov432.90%34.69%
Alexei Starovoitov362.43%11.56%
Herbert Xu191.28%34.69%
Eric W. Biedermann110.74%23.12%
Arnaldo Carvalho de Melo90.61%11.56%
Hideaki Yoshifuji / 吉藤英明80.54%34.69%
David Lamparter80.54%11.56%
Américo Wang50.34%11.56%
Jiri Benc50.34%11.56%
Krister Johansen50.34%11.56%
Arjan van de Ven50.34%11.56%
Laurent Chavey40.27%11.56%
Nicolas Dichtel40.27%11.56%
Tejun Heo40.27%23.12%
Denis V. Lunev40.27%11.56%
Paolo Abeni40.27%11.56%
Linus Torvalds30.20%11.56%
Vinay K. Nallamothu20.13%11.56%
Andrew Morton20.13%11.56%
Ingo Molnar10.07%11.56%
Christoph Hellwig10.07%11.56%
Daniel Lezcano10.07%11.56%
Total1482100.00%64100.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.