Release 4.7 net/ipv6/route.c
/*
* Linux INET6 implementation
* FIB front-end.
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/* Changes:
*
* YOSHIFUJI Hideaki @USAGI
* reworked default router selection.
* - respect outgoing interface
* - select from (probably) reachable routers (i.e.
* routers in REACHABLE, STALE, DELAY or PROBE states).
* - always select the same router if it is (probably)
* reachable. otherwise, round-robin the list.
* Ville Nuorvala
* Fixed routing subtrees.
*/
#define pr_fmt(fmt) "IPv6: " fmt
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/times.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/route.h>
#include <linux/netdevice.h>
#include <linux/in6.h>
#include <linux/mroute6.h>
#include <linux/init.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/nsproxy.h>
#include <linux/slab.h>
#include <net/net_namespace.h>
#include <net/snmp.h>
#include <net/ipv6.h>
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/tcp.h>
#include <linux/rtnetlink.h>
#include <net/dst.h>
#include <net/dst_metadata.h>
#include <net/xfrm.h>
#include <net/netevent.h>
#include <net/netlink.h>
#include <net/nexthop.h>
#include <net/lwtunnel.h>
#include <net/ip_tunnels.h>
#include <net/l3mdev.h>
#include <trace/events/fib6.h>
#include <asm/uaccess.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
enum rt6_nud_state {
RT6_NUD_FAIL_HARD = -3,
RT6_NUD_FAIL_PROBE = -2,
RT6_NUD_FAIL_DO_RR = -1,
RT6_NUD_SUCCEED = 1
};
static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ip6_default_advmss(const struct dst_entry *dst);
static unsigned int ip6_mtu(const struct dst_entry *dst);
static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static void ip6_dst_destroy(struct dst_entry *);
static void ip6_dst_ifdown(struct dst_entry *,
struct net_device *dev, int how);
static int ip6_dst_gc(struct dst_ops *ops);
static int ip6_pkt_discard(struct sk_buff *skb);
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static int ip6_pkt_prohibit(struct sk_buff *skb);
static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu);
static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb);
static void rt6_dst_from_metrics_check(struct rt6_info *rt);
static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr, int ifindex,
unsigned int pref);
static struct rt6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr, int ifindex);
#endif
struct uncached_list {
spinlock_t lock;
struct list_head head;
};
static DEFINE_PER_CPU_ALIGNED(struct uncached_list, rt6_uncached_list);
static void rt6_uncached_list_add(struct rt6_info *rt)
{
struct uncached_list *ul = raw_cpu_ptr(&rt6_uncached_list);
rt->dst.flags |= DST_NOCACHE;
rt->rt6i_uncached_list = ul;
spin_lock_bh(&ul->lock);
list_add_tail(&rt->rt6i_uncached, &ul->head);
spin_unlock_bh(&ul->lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 65 | 100.00% | 1 | 100.00% |
| Total | 65 | 100.00% | 1 | 100.00% |
static void rt6_uncached_list_del(struct rt6_info *rt)
{
if (!list_empty(&rt->rt6i_uncached)) {
struct uncached_list *ul = rt->rt6i_uncached_list;
spin_lock_bh(&ul->lock);
list_del(&rt->rt6i_uncached);
spin_unlock_bh(&ul->lock);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 57 | 100.00% | 1 | 100.00% |
| Total | 57 | 100.00% | 1 | 100.00% |
static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
{
struct net_device *loopback_dev = net->loopback_dev;
int cpu;
if (dev == loopback_dev)
return;
for_each_possible_cpu(cpu) {
struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
struct rt6_info *rt;
spin_lock_bh(&ul->lock);
list_for_each_entry(rt, &ul->head, rt6i_uncached) {
struct inet6_dev *rt_idev = rt->rt6i_idev;
struct net_device *rt_dev = rt->dst.dev;
if (rt_idev->dev == dev) {
rt->rt6i_idev = in6_dev_get(loopback_dev);
in6_dev_put(rt_idev);
}
if (rt_dev == dev) {
rt->dst.dev = loopback_dev;
dev_hold(rt->dst.dev);
dev_put(rt_dev);
}
}
spin_unlock_bh(&ul->lock);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 152 | 95.60% | 1 | 50.00% |
eric w. biederman | eric w. biederman | 7 | 4.40% | 1 | 50.00% |
| Total | 159 | 100.00% | 2 | 100.00% |
static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt)
{
return dst_metrics_write_ptr(rt->dst.from);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 22 | 100.00% | 1 | 100.00% |
| Total | 22 | 100.00% | 1 | 100.00% |
static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
{
struct rt6_info *rt = (struct rt6_info *)dst;
if (rt->rt6i_flags & RTF_PCPU)
return rt6_pcpu_cow_metrics(rt);
else if (rt->rt6i_flags & RTF_CACHE)
return NULL;
else
return dst_cow_metrics_generic(dst, old);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 30 | 47.62% | 1 | 20.00% |
martin kafai lau | martin kafai lau | 27 | 42.86% | 3 | 60.00% |
zheng yan | zheng yan | 6 | 9.52% | 1 | 20.00% |
| Total | 63 | 100.00% | 5 | 100.00% |
static inline const void *choose_neigh_daddr(struct rt6_info *rt,
struct sk_buff *skb,
const void *daddr)
{
struct in6_addr *p = &rt->rt6i_gateway;
if (!ipv6_addr_any(p))
return (const void *) p;
else if (skb)
return &ipv6_hdr(skb)->daddr;
return daddr;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 67 | 100.00% | 3 | 100.00% |
| Total | 67 | 100.00% | 3 | 100.00% |
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
struct rt6_info *rt = (struct rt6_info *) dst;
struct neighbour *n;
daddr = choose_neigh_daddr(rt, skb, daddr);
n = __ipv6_neigh_lookup(dst->dev, daddr);
if (n)
return n;
return neigh_create(&nd_tbl, daddr, dst->dev);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 83 | 100.00% | 4 | 100.00% |
| Total | 83 | 100.00% | 4 | 100.00% |
static struct dst_ops ip6_dst_ops_template = {
.family = AF_INET6,
.gc = ip6_dst_gc,
.gc_thresh = 1024,
.check = ip6_dst_check,
.default_advmss = ip6_default_advmss,
.mtu = ip6_mtu,
.cow_metrics = ipv6_cow_metrics,
.destroy = ip6_dst_destroy,
.ifdown = ip6_dst_ifdown,
.negative_advice = ip6_negative_advice,
.link_failure = ip6_link_failure,
.update_pmtu = ip6_rt_update_pmtu,
.redirect = rt6_do_redirect,
.local_out = __ip6_local_out,
.neigh_lookup = ip6_neigh_lookup,
};
static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst)
{
unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
return mtu ? : dst->dev->mtu;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
steffen klassert | steffen klassert | 20 | 58.82% | 3 | 75.00% |
roland dreier | roland dreier | 14 | 41.18% | 1 | 25.00% |
| Total | 34 | 100.00% | 4 | 100.00% |
static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu)
{
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 23 | 100.00% | 2 | 100.00% |
| Total | 23 | 100.00% | 2 | 100.00% |
static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb)
{
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 20 | 100.00% | 2 | 100.00% |
| Total | 20 | 100.00% | 2 | 100.00% |
static struct dst_ops ip6_dst_blackhole_ops = {
.family = AF_INET6,
.destroy = ip6_dst_destroy,
.check = ip6_dst_check,
.mtu = ip6_blackhole_mtu,
.default_advmss = ip6_default_advmss,
.update_pmtu = ip6_rt_blackhole_update_pmtu,
.redirect = ip6_rt_blackhole_redirect,
.cow_metrics = dst_cow_metrics_generic,
.neigh_lookup = ip6_neigh_lookup,
};
static const u32 ip6_template_metrics[RTAX_MAX] = {
[RTAX_HOPLIMIT - 1] = 0,
};
static const struct rt6_info ip6_null_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
.obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -ENETUNREACH,
.input = ip6_pkt_discard,
.output = ip6_pkt_discard_out,
},
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
.rt6i_protocol = RTPROT_KERNEL,
.rt6i_metric = ~(u32) 0,
.rt6i_ref = ATOMIC_INIT(1),
};
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
static const struct rt6_info ip6_prohibit_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
.obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -EACCES,
.input = ip6_pkt_prohibit,
.output = ip6_pkt_prohibit_out,
},
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
.rt6i_protocol = RTPROT_KERNEL,
.rt6i_metric = ~(u32) 0,
.rt6i_ref = ATOMIC_INIT(1),
};
static const struct rt6_info ip6_blk_hole_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
.obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -EINVAL,
.input = dst_discard,
.output = dst_discard_out,
},
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
.rt6i_protocol = RTPROT_KERNEL,
.rt6i_metric = ~(u32) 0,
.rt6i_ref = ATOMIC_INIT(1),
};
#endif
static void rt6_info_init(struct rt6_info *rt)
{
struct dst_entry *dst = &rt->dst;
memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
INIT_LIST_HEAD(&rt->rt6i_siblings);
INIT_LIST_HEAD(&rt->rt6i_uncached);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 21 | 36.21% | 2 | 22.22% |
steffen klassert | steffen klassert | 14 | 24.14% | 1 | 11.11% |
martin kafai lau | martin kafai lau | 11 | 18.97% | 2 | 22.22% |
nicolas dichtel | nicolas dichtel | 8 | 13.79% | 1 | 11.11% |
benjamin thery | benjamin thery | 2 | 3.45% | 1 | 11.11% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 3.45% | 2 | 22.22% |
| Total | 58 | 100.00% | 9 | 100.00% |
/* allocate dst with ip6_dst_ops */
static struct rt6_info *__ip6_dst_alloc(struct net *net,
struct net_device *dev,
int flags)
{
struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
0, DST_OBSOLETE_FORCE_CHK, flags);
if (rt)
rt6_info_init(rt);
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 52 | 92.86% | 1 | 33.33% |
david s. miller | david s. miller | 2 | 3.57% | 1 | 33.33% |
kazunori miyazawa | kazunori miyazawa | 2 | 3.57% | 1 | 33.33% |
| Total | 56 | 100.00% | 3 | 100.00% |
struct rt6_info *ip6_dst_alloc(struct net *net,
struct net_device *dev,
int flags)
{
struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags);
if (rt) {
rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC);
if (rt->rt6i_pcpu) {
int cpu;
for_each_possible_cpu(cpu) {
struct rt6_info **p;
p = per_cpu_ptr(rt->rt6i_pcpu, cpu);
/* no one shares rt */
*p = NULL;
}
} else {
dst_destroy((struct dst_entry *)rt);
return NULL;
}
}
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 112 | 100.00% | 1 | 100.00% |
| Total | 112 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(ip6_dst_alloc);
static void ip6_dst_destroy(struct dst_entry *dst)
{
struct rt6_info *rt = (struct rt6_info *)dst;
struct dst_entry *from = dst->from;
struct inet6_dev *idev;
dst_destroy_metrics_generic(dst);
free_percpu(rt->rt6i_pcpu);
rt6_uncached_list_del(rt);
idev = rt->rt6i_idev;
if (idev) {
rt->rt6i_idev = NULL;
in6_dev_put(idev);
}
dst->from = NULL;
dst_release(from);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 49 | 55.68% | 3 | 37.50% |
martin kafai lau | martin kafai lau | 23 | 26.14% | 2 | 25.00% |
gao feng | gao feng | 8 | 9.09% | 1 | 12.50% |
zheng yan | zheng yan | 7 | 7.95% | 1 | 12.50% |
david s. miller | david s. miller | 1 | 1.14% | 1 | 12.50% |
| Total | 88 | 100.00% | 8 | 100.00% |
static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int how)
{
struct rt6_info *rt = (struct rt6_info *)dst;
struct inet6_dev *idev = rt->rt6i_idev;
struct net_device *loopback_dev =
dev_net(dev)->loopback_dev;
if (dev != loopback_dev) {
if (idev && idev->dev == dev) {
struct inet6_dev *loopback_idev =
in6_dev_get(loopback_dev);
if (loopback_idev) {
rt->rt6i_idev = loopback_idev;
in6_dev_put(idev);
}
}
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 75 | 75.76% | 4 | 57.14% |
herbert xu | herbert xu | 10 | 10.10% | 1 | 14.29% |
denis v. lunev | denis v. lunev | 9 | 9.09% | 1 | 14.29% |
david s. miller | david s. miller | 5 | 5.05% | 1 | 14.29% |
| Total | 99 | 100.00% | 7 | 100.00% |
static bool __rt6_check_expired(const struct rt6_info *rt)
{
if (rt->rt6i_flags & RTF_EXPIRES)
return time_after(jiffies, rt->dst.expires);
else
return false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 36 | 100.00% | 1 | 100.00% |
| Total | 36 | 100.00% | 1 | 100.00% |
static bool rt6_check_expired(const struct rt6_info *rt)
{
if (rt->rt6i_flags & RTF_EXPIRES) {
if (time_after(jiffies, rt->dst.expires))
return true;
} else if (rt->dst.from) {
return rt6_check_expired((struct rt6_info *) rt->dst.from);
}
return false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
gao feng | gao feng | 44 | 65.67% | 1 | 25.00% |
hideaki yoshifuji | hideaki yoshifuji | 17 | 25.37% | 1 | 25.00% |
eric dumazet | eric dumazet | 3 | 4.48% | 1 | 25.00% |
li rongqing | li rongqing | 3 | 4.48% | 1 | 25.00% |
| Total | 67 | 100.00% | 4 | 100.00% |
/* Multipath route selection:
* Hash based function using packet header and flowlabel.
* Adapted from fib_info_hashfn()
*/
static int rt6_info_hash_nhsfn(unsigned int candidate_count,
const struct flowi6 *fl6)
{
return get_hash_from_flowi6(fl6) % candidate_count;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
nicolas dichtel | nicolas dichtel | 20 | 83.33% | 1 | 33.33% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 8.33% | 1 | 33.33% |
tom herbert | tom herbert | 2 | 8.33% | 1 | 33.33% |
| Total | 24 | 100.00% | 3 | 100.00% |
static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
struct flowi6 *fl6, int oif,
int strict)
{
struct rt6_info *sibling, *next_sibling;
int route_choosen;
route_choosen = rt6_info_hash_nhsfn(match->rt6i_nsiblings + 1, fl6);
/* Don't change the route, if route_choosen == 0
* (siblings does not include ourself)
*/
if (route_choosen)
list_for_each_entry_safe(sibling, next_sibling,
&match->rt6i_siblings, rt6i_siblings) {
route_choosen--;
if (route_choosen == 0) {
if (rt6_score_route(sibling, oif, strict) < 0)
break;
match = sibling;
break;
}
}
return match;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
nicolas dichtel | nicolas dichtel | 98 | 100.00% | 2 | 100.00% |
| Total | 98 | 100.00% | 2 | 100.00% |
/*
* Route lookup. Any table->tb6_lock is implied.
*/
static inline struct rt6_info *rt6_device_match(struct net *net,
struct rt6_info *rt,
const struct in6_addr *saddr,
int oif,
int flags)
{
struct rt6_info *local = NULL;
struct rt6_info *sprt;
if (!oif && ipv6_addr_any(saddr))
goto out;
for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) {
struct net_device *dev = sprt->dst.dev;
if (oif) {
if (dev->ifindex == oif)
return sprt;
if (dev->flags & IFF_LOOPBACK) {
if (!sprt->rt6i_idev ||
sprt->rt6i_idev->dev->ifindex != oif) {
if (flags & RT6_LOOKUP_F_IFACE)
continue;
if (local &&
local->rt6i_idev->dev->ifindex == oif)
continue;
}
local = sprt;
}
} else {
if (ipv6_chk_addr(net, saddr, dev,
flags & RT6_LOOKUP_F_IFACE))
return sprt;
}
}
if (oif) {
if (local)
return local;
if (flags & RT6_LOOKUP_F_IFACE)
return net->ipv6.ip6_null_entry;
}
out:
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 93 | 44.50% | 4 | 33.33% |
pre-git | pre-git | 71 | 33.97% | 3 | 25.00% |
daniel lezcano | daniel lezcano | 37 | 17.70% | 1 | 8.33% |
david s. miller | david s. miller | 4 | 1.91% | 2 | 16.67% |
eric dumazet | eric dumazet | 4 | 1.91% | 2 | 16.67% |
| Total | 209 | 100.00% | 12 | 100.00% |
#ifdef CONFIG_IPV6_ROUTER_PREF
struct __rt6_probe_work {
struct work_struct work;
struct in6_addr target;
struct net_device *dev;
};
static void rt6_probe_deferred(struct work_struct *w)
{
struct in6_addr mcaddr;
struct __rt6_probe_work *work =
container_of(w, struct __rt6_probe_work, work);
addrconf_addr_solict_mult(&work->target, &mcaddr);
ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL);
dev_put(work->dev);
kfree(work);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hannes frederic sowa | hannes frederic sowa | 69 | 98.57% | 1 | 50.00% |
michael busch | michael busch | 1 | 1.43% | 1 | 50.00% |
| Total | 70 | 100.00% | 2 | 100.00% |
static void rt6_probe(struct rt6_info *rt)
{
struct __rt6_probe_work *work;
struct neighbour *neigh;
/*
* Okay, this does not seem to be appropriate
* for now, however, we need to check if it
* is really so; aka Router Reachability Probing.
*
* Router Reachability Probe MUST be rate-limited
* to no more than one per minute.
*/
if (!rt || !(rt->rt6i_flags & RTF_GATEWAY))
return;
rcu_read_lock_bh();
neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
if (neigh) {
if (neigh->nud_state & NUD_VALID)
goto out;
work = NULL;
write_lock(&neigh->lock);
if (!(neigh->nud_state & NUD_VALID) &&
time_after(jiffies,
neigh->updated +
rt->rt6i_idev->cnf.rtr_probe_interval)) {
work = kmalloc(sizeof(*work), GFP_ATOMIC);
if (work)
__neigh_set_probe_once(neigh);
}
write_unlock(&neigh->lock);
} else {
work = kmalloc(sizeof(*work), GFP_ATOMIC);
}
if (work) {
INIT_WORK(&work->work, rt6_probe_deferred);
work->target = rt->rt6i_gateway;
dev_hold(rt->dst.dev);
work->dev = rt->dst.dev;
schedule_work(&work->work);
}
out:
rcu_read_unlock_bh();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 113 | 52.07% | 5 | 41.67% |
hannes frederic sowa | hannes frederic sowa | 47 | 21.66% | 1 | 8.33% |
martin kafai lau | martin kafai lau | 44 | 20.28% | 2 | 16.67% |
eric dumazet | eric dumazet | 6 | 2.76% | 1 | 8.33% |
david s. miller | david s. miller | 3 | 1.38% | 1 | 8.33% |
jiri benc | jiri benc | 3 | 1.38% | 1 | 8.33% |
daniel lezcano | daniel lezcano | 1 | 0.46% | 1 | 8.33% |
| Total | 217 | 100.00% | 12 | 100.00% |
#else
static inline void rt6_probe(struct rt6_info *rt)
{
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 10 | 90.91% | 1 | 50.00% |
joe perches | joe perches | 1 | 9.09% | 1 | 50.00% |
| Total | 11 | 100.00% | 2 | 100.00% |
#endif
/*
* Default Router Selection (RFC 2461 6.3.6)
*/
static inline int rt6_check_dev(struct rt6_info *rt, int oif)
{
struct net_device *dev = rt->dst.dev;
if (!oif || dev->ifindex == oif)
return 2;
if ((dev->flags & IFF_LOOPBACK) &&
rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif)
return 1;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 55 | 78.57% | 4 | 57.14% |
david s. miller | david s. miller | 14 | 20.00% | 2 | 28.57% |
dave jones | dave jones | 1 | 1.43% | 1 | 14.29% |
| Total | 70 | 100.00% | 7 | 100.00% |
static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt)
{
struct neighbour *neigh;
enum rt6_nud_state ret = RT6_NUD_FAIL_HARD;
if (rt->rt6i_flags & RTF_NONEXTHOP ||
!(rt->rt6i_flags & RTF_GATEWAY))
return RT6_NUD_SUCCEED;
rcu_read_lock_bh();
neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
if (neigh) {
read_lock(&neigh->lock);
if (neigh->nud_state & NUD_VALID)
ret = RT6_NUD_SUCCEED;
#ifdef CONFIG_IPV6_ROUTER_PREF
else if (!(neigh->nud_state & NUD_FAILED))
ret = RT6_NUD_SUCCEED;
else
ret = RT6_NUD_FAIL_PROBE;
#endif
read_unlock(&neigh->lock);
} else {
ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ?
RT6_NUD_SUCCEED : RT6_NUD_FAIL_DO_RR;
}
rcu_read_unlock_bh();
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 85 | 59.44% | 6 | 42.86% |
hannes frederic sowa | hannes frederic sowa | 21 | 14.69% | 2 | 14.29% |
pre-git | pre-git | 21 | 14.69% | 3 | 21.43% |
paul marks | paul marks | 8 | 5.59% | 1 | 7.14% |
jiri benc | jiri benc | 6 | 4.20% | 1 | 7.14% |
eric dumazet | eric dumazet | 2 | 1.40% | 1 | 7.14% |
| Total | 143 | 100.00% | 14 | 100.00% |
static int rt6_score_route(struct rt6_info *rt, int oif,
int strict)
{
int m;
m = rt6_check_dev(rt, oif);
if (!m && (strict & RT6_LOOKUP_F_IFACE))
return RT6_NUD_FAIL_HARD;
#ifdef CONFIG_IPV6_ROUTER_PREF
m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
#endif
if (strict & RT6_LOOKUP_F_REACHABLE) {
int n = rt6_check_neigh(rt);
if (n < 0)
return n;
}
return m;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 65 | 72.22% | 5 | 62.50% |
hannes frederic sowa | hannes frederic sowa | 17 | 18.89% | 1 | 12.50% |
pre-git | pre-git | 6 | 6.67% | 1 | 12.50% |
paul marks | paul marks | 2 | 2.22% | 1 | 12.50% |
| Total | 90 | 100.00% | 8 | 100.00% |
static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
int *mpri, struct rt6_info *match,
bool *do_rr)
{
int m;
bool match_do_rr = false;
struct inet6_dev *idev = rt->rt6i_idev;
struct net_device *dev = rt->dst.dev;
if (dev && !netif_carrier_ok(dev) &&
idev->cnf.ignore_routes_with_linkdown)
goto out;
if (rt6_check_expired(rt))
goto out;
m = rt6_score_route(rt, oif, strict);
if (m == RT6_NUD_FAIL_DO_RR) {
match_do_rr = true;
m = 0; /* lowest valid score */
} else if (m == RT6_NUD_FAIL_HARD) {
goto out;
}
if (strict & RT6_LOOKUP_F_REACHABLE)
rt6_probe(rt);
/* note that m can be RT6_NUD_FAIL_PROBE at this point */
if (m > *mpri) {
*do_rr = match_do_rr;
*mpri = m;
match = rt;
}
out:
return match;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 62 | 36.69% | 6 | 54.55% |
hannes frederic sowa | hannes frederic sowa | 40 | 23.67% | 1 | 9.09% |
andy gospodarek | andy gospodarek | 39 | 23.08% | 1 | 9.09% |
david s. miller | david s. miller | 21 | 12.43% | 1 | 9.09% |
jiri benc | jiri benc | 4 | 2.37% | 1 | 9.09% |
pre-git | pre-git | 3 | 1.78% | 1 | 9.09% |
| Total | 169 | 100.00% | 11 | 100.00% |
static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
struct rt6_info *rr_head,
u32 metric, int oif, int strict,
bool *do_rr)
{
struct rt6_info *rt, *match, *cont;
int mpri = -1;
match = NULL;
cont = NULL;
for (rt = rr_head; rt; rt = rt->dst.rt6_next) {
if (rt->rt6i_metric != metric) {
cont = rt;
break;
}
match = find_match(rt, oif, strict, &mpri, match, do_rr);
}
for (rt = fn->leaf; rt && rt != rr_head; rt = rt->dst.rt6_next) {
if (rt->rt6i_metric != metric) {
cont = rt;
break;
}
match = find_match(rt, oif, strict, &mpri, match, do_rr);
}
if (match || !cont)
return match;
for (rt = cont; rt; rt = rt->dst.rt6_next)
match = find_match(rt, oif, strict, &mpri, match, do_rr);
return match;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 106 | 50.24% | 1 | 14.29% |
steffen klassert | steffen klassert | 81 | 38.39% | 1 | 14.29% |
hideaki yoshifuji | hideaki yoshifuji | 10 | 4.74% | 3 | 42.86% |
hannes frederic sowa | hannes frederic sowa | 8 | 3.79% | 1 | 14.29% |
eric dumazet | eric dumazet | 6 | 2.84% | 1 | 14.29% |
| Total | 211 | 100.00% | 7 | 100.00% |
static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
{
struct rt6_info *match, *rt0;
struct net *net;
bool do_rr = false;
rt0 = fn->rr_ptr;
if (!rt0)
fn->rr_ptr = rt0 = fn->leaf;
match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict,
&do_rr);
if (do_rr) {
struct rt6_info *next = rt0->dst.rt6_next;
/* no entries matched; do round-robin */
if (!next || next->rt6i_metric != rt0->rt6i_metric)
next = fn->leaf;
if (next != rt0)
fn->rr_ptr = next;
}
net = dev_net(rt0->dst.dev);
return match ? match : net->ipv6.ip6_null_entry;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 107 | 71.81% | 2 | 20.00% |
daniel lezcano | daniel lezcano | 14 | 9.40% | 1 | 10.00% |
hideaki yoshifuji | hideaki yoshifuji | 13 | 8.72% | 4 | 40.00% |
hannes frederic sowa | hannes frederic sowa | 9 | 6.04% | 1 | 10.00% |
eric dumazet | eric dumazet | 3 | 2.01% | 1 | 10.00% |
pre-git | pre-git | 3 | 2.01% | 1 | 10.00% |
| Total | 149 | 100.00% | 10 | 100.00% |
static bool rt6_is_gw_or_nonexthop(const struct rt6_info *rt)
{
return (rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 25 | 100.00% | 1 | 100.00% |
| Total | 25 | 100.00% | 1 | 100.00% |
#ifdef CONFIG_IPV6_ROUTE_INFO
int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
const struct in6_addr *gwaddr)
{
struct net *net = dev_net(dev);
struct route_info *rinfo = (struct route_info *) opt;
struct in6_addr prefix_buf, *prefix;
unsigned int pref;
unsigned long lifetime;
struct rt6_info *rt;
if (len < sizeof(struct route_info)) {
return -EINVAL;
}
/* Sanity check for prefix_len and length */
if (rinfo->length > 3) {
return -EINVAL;
} else if (rinfo->prefix_len > 128) {
return -EINVAL;
} else if (rinfo->prefix_len > 64) {
if (rinfo->length < 2) {
return -EINVAL;
}
} else if (rinfo->prefix_len > 0) {
if (rinfo->length < 1) {
return -EINVAL;
}
}
pref = rinfo->route_pref;
if (pref == ICMPV6_ROUTER_PREF_INVALID)
return -EINVAL;
lifetime = addrconf_timeout_fixup(ntohl(rinfo->lifetime), HZ);
if (rinfo->length == 3)
prefix = (struct in6_addr *)rinfo->prefix;
else {
/* this function is safe */
ipv6_addr_prefix(&prefix_buf,
(struct in6_addr *)rinfo->prefix,
rinfo->prefix_len);
prefix = &prefix_buf;
}
if (rinfo->prefix_len == 0)
rt = rt6_get_dflt_router(gwaddr, dev);
else
rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
gwaddr, dev->ifindex);
if (rt && !lifetime) {
ip6_del_rt(rt);
rt = NULL;
}
if (!rt && lifetime)
rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
pref);
else if (rt)
rt->rt6i_flags = RTF_ROUTEINFO |
(rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
if (rt) {
if (!addrconf_finite_timeout(lifetime))
rt6_clean_expires(rt);
else
rt6_set_expires(rt, jiffies + HZ * lifetime);
ip6_rt_put(rt);
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 307 | 79.74% | 3 | 20.00% |
pre-git | pre-git | 35 | 9.09% | 5 | 33.33% |
duan jiong | duan jiong | 18 | 4.68% | 1 | 6.67% |
daniel lezcano | daniel lezcano | 11 | 2.86% | 1 | 6.67% |
gao feng | gao feng | 7 | 1.82% | 1 | 6.67% |
jens rosenboom | jens rosenboom | 4 | 1.04% | 1 | 6.67% |
eric dumazet | eric dumazet | 1 | 0.26% | 1 | 6.67% |
americo wang | americo wang | 1 | 0.26% | 1 | 6.67% |
al viro | al viro | 1 | 0.26% | 1 | 6.67% |
| Total | 385 | 100.00% | 15 | 100.00% |
#endif
static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
struct in6_addr *saddr)
{
struct fib6_node *pn;
while (1) {
if (fn->fn_flags & RTN_TL_ROOT)
return NULL;
pn = fn->parent;
if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn)
fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr);
else
fn = pn;
if (fn->fn_flags & RTN_RTINFO)
return fn;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 86 | 95.56% | 1 | 33.33% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 3.33% | 1 | 33.33% |
daniel lezcano | daniel lezcano | 1 | 1.11% | 1 | 33.33% |
| Total | 90 | 100.00% | 3 | 100.00% |
static struct rt6_info *ip6_pol_route_lookup(struct net *net,
struct fib6_table *table,
struct flowi6 *fl6, int flags)
{
struct fib6_node *fn;
struct rt6_info *rt;
read_lock_bh(&table->tb6_lock);
fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart:
rt = fn->leaf;
rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags);
if (rt == net->ipv6.ip6_null_entry) {
fn = fib6_backtrack(fn, &fl6->saddr);
if (fn)
goto restart;
}
dst_use(&rt->dst, jiffies);
read_unlock_bh(&table->tb6_lock);
trace_fib6_table_lookup(net, rt, table->tb6_id, fl6);
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 56 | 30.43% | 3 | 21.43% |
thomas graf | thomas graf | 33 | 17.93% | 1 | 7.14% |
nicolas dichtel | nicolas dichtel | 27 | 14.67% | 2 | 14.29% |
martin kafai lau | martin kafai lau | 23 | 12.50% | 1 | 7.14% |
david ahern | david ahern | 13 | 7.07% | 1 | 7.14% |
david s. miller | david s. miller | 12 | 6.52% | 1 | 7.14% |
daniel lezcano | daniel lezcano | 9 | 4.89% | 1 | 7.14% |
pre-git | pre-git | 8 | 4.35% | 3 | 21.43% |
pavel emelianov | pavel emelianov | 3 | 1.63% | 1 | 7.14% |
| Total | 184 | 100.00% | 14 | 100.00% |
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
int flags)
{
return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
florian westphal | florian westphal | 32 | 100.00% | 1 | 100.00% |
| Total | 32 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL_GPL(ip6_route_lookup);
struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
const struct in6_addr *saddr, int oif, int strict)
{
struct flowi6 fl6 = {
.flowi6_oif = oif,
.daddr = *daddr,
};
struct dst_entry *dst;
int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
if (saddr) {
memcpy(&fl6.saddr, saddr, sizeof(*saddr));
flags |= RT6_LOOKUP_F_HAS_SADDR;
}
dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup);
if (dst->error == 0)
return (struct rt6_info *) dst;
dst_release(dst);
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 92 | 73.60% | 2 | 22.22% |
pre-git | pre-git | 15 | 12.00% | 2 | 22.22% |
daniel lezcano | daniel lezcano | 8 | 6.40% | 2 | 22.22% |
david s. miller | david s. miller | 7 | 5.60% | 1 | 11.11% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 2.40% | 2 | 22.22% |
| Total | 125 | 100.00% | 9 | 100.00% |
EXPORT_SYMBOL(rt6_lookup);
/* ip6_ins_rt is called with FREE table->tb6_lock.
It takes new route entry, the addition fails by any reason the
route is freed. In any case, if caller does not hold it, it may
be destroyed.
*/
static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info,
struct mx6_config *mxc)
{
int err;
struct fib6_table *table;
table = rt->rt6i_table;
write_lock_bh(&table->tb6_lock);
err = fib6_add(&table->tb6_root, rt, info, mxc);
write_unlock_bh(&table->tb6_lock);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 34 | 48.57% | 3 | 30.00% |
thomas graf | thomas graf | 25 | 35.71% | 3 | 30.00% |
michal kubecek | michal kubecek | 4 | 5.71% | 1 | 10.00% |
mathew richardson | mathew richardson | 3 | 4.29% | 1 | 10.00% |
florian westphal | florian westphal | 3 | 4.29% | 1 | 10.00% |
jamal hadi salim | jamal hadi salim | 1 | 1.43% | 1 | 10.00% |
| Total | 70 | 100.00% | 10 | 100.00% |
int ip6_ins_rt(struct rt6_info *rt)
{
struct nl_info info = { .nl_net = dev_net(rt->dst.dev), };
struct mx6_config mxc = { .mx = NULL, };
return __ip6_ins_rt(rt, &info, &mxc);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 17 | 33.33% | 1 | 12.50% |
florian westphal | florian westphal | 14 | 27.45% | 1 | 12.50% |
denis v. lunev | denis v. lunev | 11 | 21.57% | 2 | 25.00% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 5.88% | 1 | 12.50% |
david s. miller | david s. miller | 3 | 5.88% | 1 | 12.50% |
daniel lezcano | daniel lezcano | 2 | 3.92% | 1 | 12.50% |
michal kubecek | michal kubecek | 1 | 1.96% | 1 | 12.50% |
| Total | 51 | 100.00% | 8 | 100.00% |
static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{
struct rt6_info *rt;
/*
* Clone the route.
*/
if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
ort = (struct rt6_info *)ort->dst.from;
rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0);
if (!rt)
return NULL;
ip6_rt_copy_init(rt, ort);
rt->rt6i_flags |= RTF_CACHE;
rt->rt6i_metric = 0;
rt->dst.flags |= DST_HOST;
rt->rt6i_dst.addr = *daddr;
rt->rt6i_dst.plen = 128;
if (!rt6_is_gw_or_nonexthop(ort)) {
if (ort->rt6i_dst.plen != 128 &&
ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
rt->rt6i_flags |= RTF_ANYCAST;
#ifdef CONFIG_IPV6_SUBTREES
if (rt->rt6i_src.plen && saddr) {
rt->rt6i_src.addr = *saddr;
rt->rt6i_src.plen = 128;
}
#endif
}
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 98 | 47.80% | 3 | 20.00% |
pre-git | pre-git | 81 | 39.51% | 5 | 33.33% |
hideaki yoshifuji | hideaki yoshifuji | 19 | 9.27% | 3 | 20.00% |
eric dumazet | eric dumazet | 4 | 1.95% | 2 | 13.33% |
alexey dobriyan | alexey dobriyan | 2 | 0.98% | 1 | 6.67% |
david s. miller | david s. miller | 1 | 0.49% | 1 | 6.67% |
| Total | 205 | 100.00% | 15 | 100.00% |
static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
{
struct rt6_info *pcpu_rt;
pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev),
rt->dst.dev, rt->dst.flags);
if (!pcpu_rt)
return NULL;
ip6_rt_copy_init(pcpu_rt, rt);
pcpu_rt->rt6i_protocol = rt->rt6i_protocol;
pcpu_rt->rt6i_flags |= RTF_PCPU;
return pcpu_rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 76 | 100.00% | 1 | 100.00% |
| Total | 76 | 100.00% | 1 | 100.00% |
/* It should be called with read_lock_bh(&tb6_lock) acquired */
static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt)
{
struct rt6_info *pcpu_rt, **p;
p = this_cpu_ptr(rt->rt6i_pcpu);
pcpu_rt = *p;
if (pcpu_rt) {
dst_hold(&pcpu_rt->dst);
rt6_dst_from_metrics_check(pcpu_rt);
}
return pcpu_rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 58 | 100.00% | 2 | 100.00% |
| Total | 58 | 100.00% | 2 | 100.00% |
static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt)
{
struct fib6_table *table = rt->rt6i_table;
struct rt6_info *pcpu_rt, *prev, **p;
pcpu_rt = ip6_rt_pcpu_alloc(rt);
if (!pcpu_rt) {
struct net *net = dev_net(rt->dst.dev);
dst_hold(&net->ipv6.ip6_null_entry->dst);
return net->ipv6.ip6_null_entry;
}
read_lock_bh(&table->tb6_lock);
if (rt->rt6i_pcpu) {
p = this_cpu_ptr(rt->rt6i_pcpu);
prev = cmpxchg(p, NULL, pcpu_rt);
if (prev) {
/* If someone did it before us, return prev instead */
dst_destroy(&pcpu_rt->dst);
pcpu_rt = prev;
}
} else {
/* rt has been removed from the fib6 tree
* before we have a chance to acquire the read_lock.
* In this case, don't brother to create a pcpu rt
* since rt is going away anyway. The next
* dst_check() will trigger a re-lookup.
*/
dst_destroy(&pcpu_rt->dst);
pcpu_rt = rt;
}
dst_hold(&pcpu_rt->dst);
rt6_dst_from_metrics_check(pcpu_rt);
read_unlock_bh(&table->tb6_lock);
return pcpu_rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 176 | 100.00% | 3 | 100.00% |
| Total | 176 | 100.00% | 3 | 100.00% |
static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
struct flowi6 *fl6, int flags)
{
struct fib6_node *fn, *saved_fn;
struct rt6_info *rt;
int strict = 0;
strict |= flags & RT6_LOOKUP_F_IFACE;
if (net->ipv6.devconf_all->forwarding == 0)
strict |= RT6_LOOKUP_F_REACHABLE;
read_lock_bh(&table->tb6_lock);
fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
saved_fn = fn;
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
oif = 0;
redo_rt6_select:
rt = rt6_select(fn, oif, strict);
if (rt->rt6i_nsiblings)
rt = rt6_multipath_select(rt, fl6, oif, strict);
if (rt == net->ipv6.ip6_null_entry) {
fn = fib6_backtrack(fn, &fl6->saddr);
if (fn)
goto redo_rt6_select;
else if (strict & RT6_LOOKUP_F_REACHABLE) {
/* also consider unreachable route */
strict &= ~RT6_LOOKUP_F_REACHABLE;
fn = saved_fn;
goto redo_rt6_select;
}
}
if (rt == net->ipv6.ip6_null_entry || (rt->rt6i_flags & RTF_CACHE)) {
dst_use(&rt->dst, jiffies);
read_unlock_bh(&table->tb6_lock);
rt6_dst_from_metrics_check(rt);
trace_fib6_table_lookup(net, rt, table->tb6_id, fl6);
return rt;
} else if (unlikely((fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH) &&
!(rt->rt6i_flags & RTF_GATEWAY))) {
/* Create a RTF_CACHE clone which will not be
* owned by the fib6 tree. It is for the special case where
* the daddr in the skb during the neighbor look-up is different
* from the fl6->daddr used to look-up route here.
*/
struct rt6_info *uncached_rt;
dst_use(&rt->dst, jiffies);
read_unlock_bh(&table->tb6_lock);
uncached_rt = ip6_rt_cache_alloc(rt, &fl6->daddr, NULL);
dst_release(&rt->dst);
if (uncached_rt)
rt6_uncached_list_add(uncached_rt);
else
uncached_rt = net->ipv6.ip6_null_entry;
dst_hold(&uncached_rt->dst);
trace_fib6_table_lookup(net, uncached_rt, table->tb6_id, fl6);
return uncached_rt;
} else {
/* Get a percpu copy */
struct rt6_info *pcpu_rt;
rt->dst.lastuse = jiffies;
rt->dst.__use++;
pcpu_rt = rt6_get_pcpu_route(rt);
if (pcpu_rt) {
read_unlock_bh(&table->tb6_lock);
} else {
/* We have to do the read_unlock first
* because rt6_make_pcpu_route() may trigger
* ip6_dst_gc() which will take the write_lock.
*/
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
pcpu_rt = rt6_make_pcpu_route(rt);
dst_release(&rt->dst);
}
trace_fib6_table_lookup(net, pcpu_rt, table->tb6_id, fl6);
return pcpu_rt;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 266 | 57.08% | 8 | 27.59% |
david ahern | david ahern | 51 | 10.94% | 2 | 6.90% |
pre-git | pre-git | 38 | 8.15% | 4 | 13.79% |
hideaki yoshifuji | hideaki yoshifuji | 35 | 7.51% | 7 | 24.14% |
thomas graf | thomas graf | 25 | 5.36% | 1 | 3.45% |
nicolas dichtel | nicolas dichtel | 19 | 4.08% | 2 | 6.90% |
david s. miller | david s. miller | 19 | 4.08% | 2 | 6.90% |
daniel lezcano | daniel lezcano | 7 | 1.50% | 1 | 3.45% |
pavel emelianov | pavel emelianov | 5 | 1.07% | 1 | 3.45% |
adrian bunk | adrian bunk | 1 | 0.21% | 1 | 3.45% |
| Total | 466 | 100.00% | 29 | 100.00% |
static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
struct flowi6 *fl6, int flags)
{
return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pavel emelianov | pavel emelianov | 30 | 71.43% | 1 | 33.33% |
daniel lezcano | daniel lezcano | 7 | 16.67% | 1 | 33.33% |
david s. miller | david s. miller | 5 | 11.90% | 1 | 33.33% |
| Total | 42 | 100.00% | 3 | 100.00% |
static struct dst_entry *ip6_route_input_lookup(struct net *net,
struct net_device *dev,
struct flowi6 *fl6, int flags)
{
if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
flags |= RT6_LOOKUP_F_IFACE;
return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
shmulik ladkani | shmulik ladkani | 58 | 100.00% | 1 | 100.00% |
| Total | 58 | 100.00% | 1 | 100.00% |
void ip6_route_input(struct sk_buff *skb)
{
const struct ipv6hdr *iph = ipv6_hdr(skb);
struct net *net = dev_net(skb->dev);
int flags = RT6_LOOKUP_F_HAS_SADDR;
struct ip_tunnel_info *tun_info;
struct flowi6 fl6 = {
.flowi6_iif = l3mdev_fib_oif(skb->dev),
.daddr = iph->daddr,
.saddr = iph->saddr,
.flowlabel = ip6_flowinfo(iph),
.flowi6_mark = skb->mark,
.flowi6_proto = iph->nexthdr,
};
tun_info = skb_tunnel_info(skb);
if (tun_info && !(tun_info->mode & IP_TUNNEL_INFO_TX))
fl6.flowi6_tun_key.tun_id = tun_info->key.tun_id;
skb_dst_drop(skb);
skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 61 | 40.40% | 3 | 15.79% |
jiri benc | jiri benc | 42 | 27.81% | 3 | 15.79% |
daniel lezcano | daniel lezcano | 12 | 7.95% | 2 | 10.53% |
david s. miller | david s. miller | 9 | 5.96% | 1 | 5.26% |
hideaki yoshifuji | hideaki yoshifuji | 7 | 4.64% | 3 | 15.79% |
eric dumazet | eric dumazet | 5 | 3.31% | 2 | 10.53% |
shmulik ladkani | shmulik ladkani | 5 | 3.31% | 1 | 5.26% |
pre-git | pre-git | 4 | 2.65% | 2 | 10.53% |
david ahern | david ahern | 3 | 1.99% | 1 | 5.26% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 3 | 1.99% | 1 | 5.26% |
| Total | 151 | 100.00% | 19 | 100.00% |
static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
struct flowi6 *fl6, int flags)
{
return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 12 | 28.57% | 2 | 25.00% |
thomas graf | thomas graf | 11 | 26.19% | 1 | 12.50% |
daniel lezcano | daniel lezcano | 7 | 16.67% | 1 | 12.50% |
david s. miller | david s. miller | 5 | 11.90% | 1 | 12.50% |
hideaki yoshifuji | hideaki yoshifuji | 4 | 9.52% | 2 | 25.00% |
pavel emelianov | pavel emelianov | 3 | 7.14% | 1 | 12.50% |
| Total | 42 | 100.00% | 8 | 100.00% |
struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
struct flowi6 *fl6, int flags)
{
struct dst_entry *dst;
bool any_src;
dst = l3mdev_get_rt6_dst(net, fl6);
if (dst)
return dst;
fl6->flowi6_iif = LOOPBACK_IFINDEX;
any_src = ipv6_addr_any(&fl6->saddr);
if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) ||
(fl6->flowi6_oif && any_src))
flags |= RT6_LOOKUP_F_IFACE;
if (!any_src)
flags |= RT6_LOOKUP_F_HAS_SADDR;
else if (sk)
flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david ahern | david ahern | 43 | 32.09% | 4 | 20.00% |
thomas graf | thomas graf | 39 | 29.10% | 2 | 10.00% |
hideaki yoshifuji | hideaki yoshifuji | 18 | 13.43% | 3 | 15.00% |
daniel lezcano | daniel lezcano | 7 | 5.22% | 2 | 10.00% |
brian haley | brian haley | 6 | 4.48% | 1 | 5.00% |
david s. miller | david s. miller | 5 | 3.73% | 1 | 5.00% |
david mccullough | david mccullough | 5 | 3.73% | 1 | 5.00% |
paolo abeni | paolo abeni | 4 | 2.99% | 1 | 5.00% |
pre-git | pre-git | 3 | 2.24% | 2 | 10.00% |
jiri olsa | jiri olsa | 2 | 1.49% | 1 | 5.00% |
florian westphal | florian westphal | 1 | 0.75% | 1 | 5.00% |
pavel emelianov | pavel emelianov | 1 | 0.75% | 1 | 5.00% |
| Total | 134 | 100.00% | 20 | 100.00% |
EXPORT_SYMBOL_GPL(ip6_route_output_flags);
struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
{
struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig;
struct dst_entry *new = NULL;
rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
if (rt) {
rt6_info_init(rt);
new = &rt->dst;
new->__use = 1;
new->input = dst_discard;
new->output = dst_discard_out;
dst_copy_metrics(new, &ort->dst);
rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
rt->rt6i_gateway = ort->rt6i_gateway;
rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU;
rt->rt6i_metric = 0;
memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
#ifdef CONFIG_IPV6_SUBTREES
memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
#endif
dst_free(new);
}
dst_release(dst_orig);
return new ? new : ERR_PTR(-ENOMEM);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 199 | 92.56% | 7 | 53.85% |
martin kafai lau | martin kafai lau | 8 | 3.72% | 1 | 7.69% |
steffen klassert | steffen klassert | 4 | 1.86% | 1 | 7.69% |
gao feng | gao feng | 1 | 0.47% | 1 | 7.69% |
eric w. biederman | eric w. biederman | 1 | 0.47% | 1 | 7.69% |
herbert xu | herbert xu | 1 | 0.47% | 1 | 7.69% |
alexey dobriyan | alexey dobriyan | 1 | 0.47% | 1 | 7.69% |
| Total | 215 | 100.00% | 13 | 100.00% |
/*
* Destination cache support functions
*/
static void rt6_dst_from_metrics_check(struct rt6_info *rt)
{
if (rt->dst.from &&
dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(rt->dst.from))
dst_init_metrics(&rt->dst, dst_metrics_ptr(rt->dst.from), true);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 55 | 100.00% | 1 | 100.00% |
| Total | 55 | 100.00% | 1 | 100.00% |
static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
{
if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
return NULL;
if (rt6_check_expired(rt))
return NULL;
return &rt->dst;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 29 | 55.77% | 3 | 50.00% |
hannes frederic sowa | hannes frederic sowa | 11 | 21.15% | 1 | 16.67% |
martin kafai lau | martin kafai lau | 10 | 19.23% | 1 | 16.67% |
nicolas dichtel | nicolas dichtel | 2 | 3.85% | 1 | 16.67% |
| Total | 52 | 100.00% | 6 | 100.00% |
static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie)
{
if (!__rt6_check_expired(rt) &&
rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
rt6_check((struct rt6_info *)(rt->dst.from), cookie))
return &rt->dst;
else
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 60 | 100.00% | 2 | 100.00% |
| Total | 60 | 100.00% | 2 | 100.00% |
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
{
struct rt6_info *rt;
rt = (struct rt6_info *) dst;
/* All IPV6 dsts are created with ->obsolete set to the value
* DST_OBSOLETE_FORCE_CHK which forces validation calls down
* into this function always.
*/
rt6_dst_from_metrics_check(rt);
if (rt->rt6i_flags & RTF_PCPU ||
(unlikely(dst->flags & DST_NOCACHE) && rt->dst.from))
return rt6_dst_from_check(rt, cookie);
else
return rt6_check(rt, cookie);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 75 | 96.15% | 4 | 66.67% |
hannes frederic sowa | hannes frederic sowa | 2 | 2.56% | 1 | 16.67% |
pre-git | pre-git | 1 | 1.28% | 1 | 16.67% |
| Total | 78 | 100.00% | 6 | 100.00% |
static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
{
struct rt6_info *rt = (struct rt6_info *) dst;
if (rt) {
if (rt->rt6i_flags & RTF_CACHE) {
if (rt6_check_expired(rt)) {
ip6_del_rt(rt);
dst = NULL;
}
} else {
dst_release(dst);
dst = NULL;
}
}
return dst;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 52 | 70.27% | 3 | 75.00% |
hideaki yoshifuji | hideaki yoshifuji | 22 | 29.73% | 1 | 25.00% |
| Total | 74 | 100.00% | 4 | 100.00% |
static void ip6_link_failure(struct sk_buff *skb)
{
struct rt6_info *rt;
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
rt = (struct rt6_info *) skb_dst(skb);
if (rt) {
if (rt->rt6i_flags & RTF_CACHE) {
dst_hold(&rt->dst);
ip6_del_rt(rt);
} else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {
rt->rt6i_node->fn_sernum = -1;
}
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 78 | 82.98% | 2 | 50.00% |
hannes frederic sowa | hannes frederic sowa | 13 | 13.83% | 1 | 25.00% |
eric dumazet | eric dumazet | 3 | 3.19% | 1 | 25.00% |
| Total | 94 | 100.00% | 4 | 100.00% |
static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu)
{
struct net *net = dev_net(rt->dst.dev);
rt->rt6i_flags |= RTF_MODIFIED;
rt->rt6i_pmtu = mtu;
rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 51 | 96.23% | 1 | 50.00% |
alexey kuznetsov | alexey kuznetsov | 2 | 3.77% | 1 | 50.00% |
| Total | 53 | 100.00% | 2 | 100.00% |
static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
{
return !(rt->rt6i_flags & RTF_CACHE) &&
(rt->rt6i_flags & RTF_PCPU || rt->rt6i_node);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 34 | 100.00% | 1 | 100.00% |
| Total | 34 | 100.00% | 1 | 100.00% |
static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
const struct ipv6hdr *iph, u32 mtu)
{
struct rt6_info *rt6 = (struct rt6_info *)dst;
if (rt6->rt6i_flags & RTF_LOCAL)
return;
dst_confirm(dst);
mtu = max_t(u32, mtu, IPV6_MIN_MTU);
if (mtu >= dst_mtu(dst))
return;
if (!rt6_cache_allowed_for_pmtu(rt6)) {
rt6_do_update_pmtu(rt6, mtu);
} else {
const struct in6_addr *daddr, *saddr;
struct rt6_info *nrt6;
if (iph) {
daddr = &iph->daddr;
saddr = &iph->saddr;
} else if (sk) {
daddr = &sk->sk_v6_daddr;
saddr = &inet6_sk(sk)->saddr;
} else {
return;
}
nrt6 = ip6_rt_cache_alloc(rt6, daddr, saddr);
if (nrt6) {
rt6_do_update_pmtu(nrt6, mtu);
/* ip6_ins_rt(nrt6) will bump the
* rt6->rt6i_node->fn_sernum
* which will fail the next rt6_check() and
* invalidate the sk->sk_dst_cache.
*/
ip6_ins_rt(nrt6);
}
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 123 | 66.49% | 3 | 37.50% |
alexey kuznetsov | alexey kuznetsov | 34 | 18.38% | 1 | 12.50% |
david s. miller | david s. miller | 23 | 12.43% | 2 | 25.00% |
shirley ma | shirley ma | 4 | 2.16% | 1 | 12.50% |
herbert xu | herbert xu | 1 | 0.54% | 1 | 12.50% |
| Total | 185 | 100.00% | 8 | 100.00% |
static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu)
{
__ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 42 | 100.00% | 1 | 100.00% |
| Total | 42 | 100.00% | 1 | 100.00% |
void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
int oif, u32 mark)
{
const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
struct dst_entry *dst;
struct flowi6 fl6;
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_oif = oif;
fl6.flowi6_mark = mark ? mark : IP6_REPLY_MARK(net, skb->mark);
fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph);
dst = ip6_route_output(net, NULL, &fl6);
if (!dst->error)
__ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu));
dst_release(dst);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 130 | 88.44% | 3 | 42.86% |
lorenzo colitti | lorenzo colitti | 11 | 7.48% | 1 | 14.29% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 2.04% | 1 | 14.29% |
martin kafai lau | martin kafai lau | 2 | 1.36% | 1 | 14.29% |
alexey kuznetsov | alexey kuznetsov | 1 | 0.68% | 1 | 14.29% |
| Total | 147 | 100.00% | 7 | 100.00% |
EXPORT_SYMBOL_GPL(ip6_update_pmtu);
void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
{
struct dst_entry *dst;
ip6_update_pmtu(skb, sock_net(sk), mtu,
sk->sk_bound_dev_if, sk->sk_mark);
dst = __sk_dst_get(sk);
if (!dst || !dst->obsolete ||
dst->ops->check(dst, inet6_sk(sk)->dst_cookie))
return;
bh_lock_sock(sk);
if (!sock_owned_by_user(sk) && !ipv6_addr_v4mapped(&sk->sk_v6_daddr))
ip6_datagram_dst_update(sk, false);
bh_unlock_sock(sk);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 73 | 65.77% | 1 | 33.33% |
david s. miller | david s. miller | 37 | 33.33% | 1 | 33.33% |
alexey kuznetsov | alexey kuznetsov | 1 | 0.90% | 1 | 33.33% |
| Total | 111 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
/* Handle redirects */
struct ip6rd_flowi {
struct flowi6 fl6;
struct in6_addr gateway;
};
static struct rt6_info *__ip6_route_redirect(struct net *net,
struct fib6_table *table,
struct flowi6 *fl6,
int flags)
{
struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
struct rt6_info *rt;
struct fib6_node *fn;
/* Get the "current" route for this destination and
* check if the redirect has come from approriate router.
*
* RFC 4861 specifies that redirects should only be
* accepted if they come from the nexthop to the target.
* Due to the way the routes are chosen, this notion
* is a bit fuzzy and one might need to check all possible
* routes.
*/
read_lock_bh(&table->tb6_lock);
fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart:
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
if (rt6_check_expired(rt))
continue;
if (rt->dst.error)
break;
if (!(rt->rt6i_flags & RTF_GATEWAY))
continue;
if (fl6->flowi6_oif != rt->dst.dev->ifindex)
continue;
if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
continue;
break;
}
if (!rt)
rt = net->ipv6.ip6_null_entry;
else if (rt->dst.error) {
rt = net->ipv6.ip6_null_entry;
goto out;
}
if (rt == net->ipv6.ip6_null_entry) {
fn = fib6_backtrack(fn, &fl6->saddr);
if (fn)
goto restart;
}
out:
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
trace_fib6_table_lookup(net, rt, table->tb6_id, fl6);
return rt;
}Contributors
| Person | Tokens | Prop | Commits | CommitProp |
duan jiong | duan jiong | 220 | 84.29% | 1 | 25.00% |
martin kafai lau | martin kafai lau | 28 | 10.73% | 2 | 50.00% |
david ahern | david ahern | 13 | 4.98% | 1 | 25.00% |
| Total | 261 | 100.00% | 4 | 100.00% |
;
static struct dst_entry *ip6_route_redirect(struct net *net,
const struct flowi6 *fl6,
const struct in6_addr *gateway)
{
int flags = RT6_LOOKUP_F_HAS_SADDR;
struct ip6rd_flowi rdfl;
rdfl.fl6 = *fl6;
rdfl.gateway = *gateway;
return fib6_rule_lookup(net, &rdfl.fl6,
flags, __ip6_route_redirect);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
duan jiong | duan jiong | 63 | 100.00% | 1 | 100.00% |
| Total | 63 | 100.00% | 1 | 100.00% |
void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
{
const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
struct dst_entry *dst;
struct flowi6 fl6;
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_iif = LOOPBACK_IFINDEX;
fl6.flowi6_oif = oif;
fl6.flowi6_mark = mark;
fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph);
dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
rt6_do_redirect(dst, NULL, skb);
dst_release(dst);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 115 | 86.47% | 2 | 40.00% |
duan jiong | duan jiong | 9 | 6.77% | 1 | 20.00% |
julian anastasov | julian anastasov | 6 | 4.51% | 1 | 20.00% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 2.26% | 1 | 20.00% |
| Total | 133 | 100.00% | 5 | 100.00% |
EXPORT_SYMBOL_GPL(ip6_redirect);
void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
u32 mark)
{
const struct ipv6hdr *iph = ipv6_hdr(skb);
const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb);
struct dst_entry *dst;
struct flowi6 fl6;
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_iif = LOOPBACK_IFINDEX;
fl6.flowi6_oif = oif;
fl6.flowi6_mark = mark;
fl6.daddr = msg->dest;
fl6.saddr = iph->daddr;
dst = ip6_route_redirect(net, &fl6, &iph->saddr);
rt6_do_redirect(dst, NULL, skb);
dst_release(dst);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
duan jiong | duan jiong | 127 | 95.49% | 2 | 66.67% |
julian anastasov | julian anastasov | 6 | 4.51% | 1 | 33.33% |
| Total | 133 | 100.00% | 3 | 100.00% |
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
{
ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 33 | 100.00% | 1 | 100.00% |
| Total | 33 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL_GPL(ip6_sk_redirect);
static unsigned int ip6_default_advmss(const struct dst_entry *dst)
{
struct net_device *dev = dst->dev;
unsigned int mtu = dst_mtu(dst);
struct net *net = dev_net(dev);
mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
/*
* Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
* corresponding MSS is IPV6_MAXPLEN - tcp_header_size.
* IPV6_MAXPLEN is also valid and means: "any MSS,
* rely only on pmtu discovery"
*/
if (mtu > IPV6_MAXPLEN - sizeof(struct tcphdr))
mtu = IPV6_MAXPLEN;
return mtu;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
al viro | al viro | 44 | 45.36% | 1 | 16.67% |
david s. miller | david s. miller | 31 | 31.96% | 1 | 16.67% |
daniel lezcano | daniel lezcano | 14 | 14.43% | 2 | 33.33% |
shirley ma | shirley ma | 7 | 7.22% | 1 | 16.67% |
hideaki yoshifuji | hideaki yoshifuji | 1 | 1.03% | 1 | 16.67% |
| Total | 97 | 100.00% | 6 | 100.00% |
static unsigned int ip6_mtu(const struct dst_entry *dst)
{
const struct rt6_info *rt = (const struct rt6_info *)dst;
unsigned int mtu = rt->rt6i_pmtu;
struct inet6_dev *idev;
if (mtu)
goto out;
mtu = dst_metric_raw(dst, RTAX_MTU);
if (mtu)
goto out;
mtu = IPV6_MIN_MTU;
rcu_read_lock();
idev = __in6_dev_get(dst->dev);
if (idev)
mtu = idev->cnf.mtu6;
rcu_read_unlock();
out:
return min_t(unsigned int, mtu, IP6_MAX_MTU);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 44 | 41.51% | 1 | 20.00% |
martin kafai lau | martin kafai lau | 30 | 28.30% | 1 | 20.00% |
steffen klassert | steffen klassert | 19 | 17.92% | 2 | 40.00% |
eric dumazet | eric dumazet | 13 | 12.26% | 1 | 20.00% |
| Total | 106 | 100.00% | 5 | 100.00% |
static struct dst_entry *icmp6_dst_gc_list;
static DEFINE_SPINLOCK(icmp6_dst_lock);
struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
struct flowi6 *fl6)
{
struct dst_entry *dst;
struct rt6_info *rt;
struct inet6_dev *idev = in6_dev_get(dev);
struct net *net = dev_net(dev);
if (unlikely(!idev))
return ERR_PTR(-ENODEV);
rt = ip6_dst_alloc(net, dev, 0);
if (unlikely(!rt)) {
in6_dev_put(idev);
dst = ERR_PTR(-ENOMEM);
goto out;
}
rt->dst.flags |= DST_HOST;
rt->dst.output = ip6_output;
atomic_set(&rt->dst.__refcnt, 1);
rt->rt6i_gateway = fl6->daddr;
rt->rt6i_dst.addr = fl6->daddr;
rt->rt6i_dst.plen = 128;
rt->rt6i_idev = idev;
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
spin_lock_bh(&icmp6_dst_lock);
rt->dst.next = icmp6_dst_gc_list;
icmp6_dst_gc_list = &rt->dst;
spin_unlock_bh(&icmp6_dst_lock);
fib6_force_start_gc(net);
dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0);
out:
return dst;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 118 | 51.53% | 5 | 21.74% |
hideaki yoshifuji | hideaki yoshifuji | 35 | 15.28% | 5 | 21.74% |
zheng yan | zheng yan | 24 | 10.48% | 1 | 4.35% |
gao feng | gao feng | 11 | 4.80% | 1 | 4.35% |
daniel lezcano | daniel lezcano | 10 | 4.37% | 2 | 8.70% |
julian anastasov | julian anastasov | 8 | 3.49% | 1 | 4.35% |
patrick mchardy | patrick mchardy | 7 | 3.06% | 1 | 4.35% |
eric dumazet | eric dumazet | 5 | 2.18% | 1 | 4.35% |
shirley ma | shirley ma | 3 | 1.31% | 1 | 4.35% |
benjamin thery | benjamin thery | 3 | 1.31% | 1 | 4.35% |
thomas graf | thomas graf | 2 | 0.87% | 1 | 4.35% |
li rongqing | li rongqing | 1 | 0.44% | 1 | 4.35% |
kazunori miyazawa | kazunori miyazawa | 1 | 0.44% | 1 | 4.35% |
alexey dobriyan | alexey dobriyan | 1 | 0.44% | 1 | 4.35% |
| Total | 229 | 100.00% | 23 | 100.00% |
int icmp6_dst_gc(void)
{
struct dst_entry *dst, **pprev;
int more = 0;
spin_lock_bh(&icmp6_dst_lock);
pprev = &icmp6_dst_gc_list;
while ((dst = *pprev) != NULL) {
if (!atomic_read(&dst->__refcnt)) {
*pprev = dst->next;
dst_free(dst);
} else {
pprev = &dst->next;
++more;
}
}
spin_unlock_bh(&icmp6_dst_lock);
return more;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 72 | 78.26% | 1 | 25.00% |
thomas graf | thomas graf | 10 | 10.87% | 1 | 25.00% |
stephen hemminger | stephen hemminger | 6 | 6.52% | 1 | 25.00% |
hideaki yoshifuji | hideaki yoshifuji | 4 | 4.35% | 1 | 25.00% |
| Total | 92 | 100.00% | 4 | 100.00% |
static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
void *arg)
{
struct dst_entry *dst, **pprev;
spin_lock_bh(&icmp6_dst_lock);
pprev = &icmp6_dst_gc_list;
while ((dst = *pprev) != NULL) {
struct rt6_info *rt = (struct rt6_info *) dst;
if (func(rt, arg)) {
*pprev = dst->next;
dst_free(dst);
} else {
pprev = &dst->next;
}
}
spin_unlock_bh(&icmp6_dst_lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 110 | 100.00% | 1 | 100.00% |
| Total | 110 | 100.00% | 1 | 100.00% |
static int ip6_dst_gc(struct dst_ops *ops)
{
struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
int entries;
entries = dst_entries_get_fast(ops);
if (time_after(rt_last_gc + rt_min_interval, jiffies) &&
entries <= rt_max_size)
goto out;
net->ipv6.ip6_rt_gc_expire++;
fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, true);
entries = dst_entries_get_slow(ops);
if (entries < ops->gc_thresh)
net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
out:
net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
return entries > rt_max_size;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel lezcano | daniel lezcano | 68 | 38.64% | 5 | 31.25% |
pre-git | pre-git | 38 | 21.59% | 3 | 18.75% |
benjamin thery | benjamin thery | 36 | 20.45% | 1 | 6.25% |
eric dumazet | eric dumazet | 17 | 9.66% | 1 | 6.25% |
alexey dobriyan | alexey dobriyan | 10 | 5.68% | 1 | 6.25% |
michal kubecek | michal kubecek | 2 | 1.14% | 2 | 12.50% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 2 | 1.14% | 1 | 6.25% |
randy dunlap | randy dunlap | 2 | 1.14% | 1 | 6.25% |
li rongqing | li rongqing | 1 | 0.57% | 1 | 6.25% |
| Total | 176 | 100.00% | 16 | 100.00% |
static int ip6_convert_metrics(struct mx6_config *mxc,
const struct fib6_config *cfg)
{
bool ecn_ca = false;
struct nlattr *nla;
int remaining;
u32 *mp;
if (!cfg->fc_mx)
return 0;
mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
if (unlikely(!mp))
return -ENOMEM;
nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
int type = nla_type(nla);
u32 val;
if (!type)
continue;
if (unlikely(type > RTAX_MAX))
goto err;
if (type == RTAX_CC_ALGO) {
char tmp[TCP_CA_NAME_MAX];
nla_strlcpy(tmp, nla, sizeof(tmp));
val = tcp_ca_get_key_by_name(tmp, &ecn_ca);
if (val == TCP_CA_UNSPEC)
goto err;
} else {
val = nla_get_u32(nla);
}
if (type == RTAX_HOPLIMIT && val > 255)
val = 255;
if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
goto err;
mp[type - 1] = val;
__set_bit(type - 1, mxc->mx_valid);
}
if (ecn_ca) {
__set_bit(RTAX_FEATURES - 1, mxc->mx_valid);
mp[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
}
mxc->mx = mp;
return 0;
err:
kfree(mp);
return -EINVAL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
florian westphal | florian westphal | 139 | 53.05% | 1 | 14.29% |
daniel borkmann | daniel borkmann | 108 | 41.22% | 4 | 57.14% |
paolo abeni | paolo abeni | 14 | 5.34% | 1 | 14.29% |
ian morris | ian morris | 1 | 0.38% | 1 | 14.29% |
| Total | 262 | 100.00% | 7 | 100.00% |
static struct rt6_info *ip6_nh_lookup_table(struct net *net,
struct fib6_config *cfg,
const struct in6_addr *gw_addr)
{
struct flowi6 fl6 = {
.flowi6_oif = cfg->fc_ifindex,
.daddr = *gw_addr,
.saddr = cfg->fc_prefsrc,
};
struct fib6_table *table;
struct rt6_info *rt;
int flags = RT6_LOOKUP_F_IFACE;
table = fib6_get_table(net, cfg->fc_table);
if (!table)
return NULL;
if (!ipv6_addr_any(&cfg->fc_prefsrc))
flags |= RT6_LOOKUP_F_HAS_SADDR;
rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags);
/* if table lookup failed, fall back to full lookup */
if (rt == net->ipv6.ip6_null_entry) {
ip6_rt_put(rt);
rt = NULL;
}
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david ahern | david ahern | 141 | 99.30% | 1 | 50.00% |
paolo abeni | paolo abeni | 1 | 0.70% | 1 | 50.00% |
| Total | 142 | 100.00% | 2 | 100.00% |
static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg)
{
struct net *net = cfg->fc_nlinfo.nl_net;
struct rt6_info *rt = NULL;
struct net_device *dev = NULL;
struct inet6_dev *idev = NULL;
struct fib6_table *table;
int addr_type;
int err = -EINVAL;
if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
goto out;
#ifndef CONFIG_IPV6_SUBTREES
if (cfg->fc_src_len)
goto out;
#endif
if (cfg->fc_ifindex) {
err = -ENODEV;
dev = dev_get_by_index(net, cfg->fc_ifindex);
if (!dev)
goto out;
idev = in6_dev_get(dev);
if (!idev)
goto out;
}
if (cfg->fc_metric == 0)
cfg->fc_metric = IP6_RT_PRIO_USER;
err = -ENOBUFS;
if (cfg->fc_nlinfo.nlh &&
!(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
table = fib6_get_table(net, cfg->fc_table);
if (!table) {
pr_warn("NLM_F_CREATE should be specified when creating new route\n");
table = fib6_new_table(net, cfg->fc_table);
}
} else {
table = fib6_new_table(net, cfg->fc_table);
}
if (!table)
goto out;
rt = ip6_dst_alloc(net, NULL,
(cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT);
if (!rt) {
err = -ENOMEM;
goto out;
}
if (cfg->fc_flags & RTF_EXPIRES)
rt6_set_expires(rt, jiffies +
clock_t_to_jiffies(cfg->fc_expires));
else
rt6_clean_expires(rt);
if (cfg->fc_protocol == RTPROT_UNSPEC)
cfg->fc_protocol = RTPROT_BOOT;
rt->rt6i_protocol = cfg->fc_protocol;
addr_type = ipv6_addr_type(&cfg->fc_dst);
if (addr_type & IPV6_ADDR_MULTICAST)
rt->dst.input = ip6_mc_input;
else if (cfg->fc_flags & RTF_LOCAL)
rt->dst.input = ip6_input;
else
rt->dst.input = ip6_forward;
rt->dst.output = ip6_output;
if (cfg->fc_encap) {
struct lwtunnel_state *lwtstate;
err = lwtunnel_build_state(dev, cfg->fc_encap_type,
cfg->fc_encap, AF_INET6, cfg,
&lwtstate);
if (err)
goto out;
rt->dst.lwtstate = lwtstate_get(lwtstate);
if (lwtunnel_output_redirect(rt->dst.lwtstate)) {
rt->dst.lwtstate->orig_output = rt->dst.output;
rt->dst.output = lwtunnel_output;
}
if (lwtunnel_input_redirect(rt->dst.lwtstate)) {
rt->dst.lwtstate->orig_input = rt->dst.input;
rt->dst.input = lwtunnel_input;
}
}
ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
rt->rt6i_dst.plen = cfg->fc_dst_len;
if (rt->rt6i_dst.plen == 128)
rt->dst.flags |= DST_HOST;
#ifdef CONFIG_IPV6_SUBTREES
ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
rt->rt6i_src.plen = cfg->fc_src_len;
#endif
rt->rt6i_metric = cfg->fc_metric;
/* We cannot add true routes via loopback here,
they would result in kernel looping; promote them to reject routes
*/
if ((cfg->fc_flags & RTF_REJECT) ||
(dev && (dev->flags & IFF_LOOPBACK) &&
!(addr_type & IPV6_ADDR_LOOPBACK) &&
!(cfg->fc_flags & RTF_LOCAL))) {
/* hold loopback dev/idev if we haven't done so. */
if (dev != net->loopback_dev) {
if (dev) {
dev_put(dev);
in6_dev_put(idev);
}
dev = net->loopback_dev;
dev_hold(dev);
idev = in6_dev_get(dev);
if (!idev) {
err = -ENODEV;
goto out;
}
}
rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
switch (cfg->fc_type) {
case RTN_BLACKHOLE:
rt->dst.error = -EINVAL;
rt->dst.output = dst_discard_out;
rt->dst.input = dst_discard;
break;
case RTN_PROHIBIT:
rt->dst.error = -EACCES;
rt->dst.output = ip6_pkt_prohibit_out;
rt->dst.input = ip6_pkt_prohibit;
break;
case RTN_THROW:
case RTN_UNREACHABLE:
default:
rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
: (cfg->fc_type == RTN_UNREACHABLE)
? -EHOSTUNREACH : -ENETUNREACH;
rt->dst.output = ip6_pkt_discard_out;
rt->dst.input = ip6_pkt_discard;
break;
}
goto install_route;
}
if (cfg->fc_flags & RTF_GATEWAY) {
const struct in6_addr *gw_addr;
int gwa_type;
gw_addr = &cfg->fc_gateway;
gwa_type = ipv6_addr_type(gw_addr);
/* if gw_addr is local we will fail to detect this in case
* address is still TENTATIVE (DAD in progress). rt6_lookup()
* will return already-added prefix route via interface that
* prefix route was assigned to, which might be non-loopback.
*/
err = -EINVAL;
if (ipv6_chk_addr_and_flags(net, gw_addr,
gwa_type & IPV6_ADDR_LINKLOCAL ?
dev : NULL, 0, 0))
goto out;
rt->rt6i_gateway = *gw_addr;
if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
struct rt6_info *grt = NULL;
/* IPv6 strictly inhibits using not link-local
addresses as nexthop address.
Otherwise, router will not able to send redirects.
It is very good, but in some (rare!) circumstances
(SIT, PtP, NBMA NOARP links) it is handy to allow
some exceptions. --ANK
*/
if (!(gwa_type & IPV6_ADDR_UNICAST))
goto out;
if (cfg->fc_table)
grt = ip6_nh_lookup_table(net, cfg, gw_addr);
if (!grt)
grt = rt6_lookup(net, gw_addr, NULL,
cfg->fc_ifindex, 1);
err = -EHOSTUNREACH;
if (!grt)
goto out;
if (dev) {
if (dev != grt->dst.dev) {
ip6_rt_put(grt);
goto out;
}
} else {
dev = grt->dst.dev;
idev = grt->rt6i_idev;
dev_hold(dev);
in6_dev_hold(grt->rt6i_idev);
}
if (!(grt->rt6i_flags & RTF_GATEWAY))
err = 0;
ip6_rt_put(grt);
if (err)
goto out;
}
err = -EINVAL;
if (!dev || (dev->flags & IFF_LOOPBACK))
goto out;
}
err = -ENODEV;
if (!dev)
goto out;
if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) {
err = -EINVAL;
goto out;
}
rt->rt6i_prefsrc.addr = cfg->fc_prefsrc;
rt->rt6i_prefsrc.plen = 128;
} else
rt->rt6i_prefsrc.plen = 0;
rt->rt6i_flags = cfg->fc_flags;
install_route:
rt->dst.dev = dev;
rt->rt6i_idev = idev;
rt->rt6i_table = table;
cfg->fc_nlinfo.nl_net = dev_net(dev);
return rt;
out:
if (dev)
dev_put(dev);
if (idev)
in6_dev_put(idev);
if (rt)
dst_free(&rt->dst);
return ERR_PTR(err);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 419 | 33.71% | 12 | 18.75% |
hideaki yoshifuji | hideaki yoshifuji | 127 | 10.22% | 9 | 14.06% |
roopa prabhu | roopa prabhu | 109 | 8.77% | 4 | 6.25% |
thomas graf | thomas graf | 85 | 6.84% | 2 | 3.12% |
daniel walter | daniel walter | 64 | 5.15% | 1 | 1.56% |
nicolas dichtel | nicolas dichtel | 60 | 4.83% | 4 | 6.25% |
matti vaittinen | matti vaittinen | 60 | 4.83% | 1 | 1.56% |
kamala r | kamala r | 53 | 4.26% | 1 | 1.56% |
tom herbert | tom herbert | 45 | 3.62% | 2 | 3.12% |
florian westphal | florian westphal | 37 | 2.98% | 2 | 3.12% |
daniel lezcano | daniel lezcano | 28 | 2.25% | 4 | 6.25% |
maciej zenczykowski | maciej zenczykowski | 26 | 2.09% | 1 | 1.56% |
david ahern | david ahern | 24 | 1.93% | 1 | 1.56% |
david s. miller | david s. miller | 18 | 1.45% | 6 | 9.38% |
jiri benc | jiri benc | 17 | 1.37% | 1 | 1.56% |
nikola forro | nikola forro | 14 | 1.13% | 1 | 1.56% |
gao feng | gao feng | 14 | 1.13% | 1 | 1.56% |
mathew richardson | mathew richardson | 11 | 0.88% | 1 | 1.56% |
sabrina dubroca | sabrina dubroca | 10 | 0.80% | 1 | 1.56% |
patrick mchardy | patrick mchardy | 8 | 0.64% | 1 | 1.56% |
benjamin thery | benjamin thery | 3 | 0.24% | 1 | 1.56% |
alexey dobriyan | alexey dobriyan | 3 | 0.24% | 1 | 1.56% |
eric w. biederman | eric w. biederman | 2 | 0.16% | 2 | 3.12% |
joe perches | joe perches | 2 | 0.16% | 1 | 1.56% |
americo wang | americo wang | 2 | 0.16% | 1 | 1.56% |
jamal hadi salim | jamal hadi salim | 1 | 0.08% | 1 | 1.56% |
eric dumazet | eric dumazet | 1 | 0.08% | 1 | 1.56% |
| Total | 1243 | 100.00% | 64 | 100.00% |
int ip6_route_add(struct fib6_config *cfg)
{
struct mx6_config mxc = { .mx = NULL, };
struct rt6_info *rt;
int err;
rt = ip6_route_info_create(cfg);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
rt = NULL;
goto out;
}
err = ip6_convert_metrics(&mxc, cfg);
if (err)
goto out;
err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, &mxc);
kfree(mxc.mx);
return err;
out:
if (rt)
dst_free(&rt->dst);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roopa prabhu | roopa prabhu | 58 | 49.15% | 2 | 14.29% |
florian westphal | florian westphal | 31 | 26.27% | 1 | 7.14% |
pre-git | pre-git | 17 | 14.41% | 5 | 35.71% |
thomas graf | thomas graf | 5 | 4.24% | 2 | 14.29% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 2.54% | 1 | 7.14% |
patrick mchardy | patrick mchardy | 2 | 1.69% | 1 | 7.14% |
mathew richardson | mathew richardson | 1 | 0.85% | 1 | 7.14% |
michal kubecek | michal kubecek | 1 | 0.85% | 1 | 7.14% |
| Total | 118 | 100.00% | 14 | 100.00% |
static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
{
int err;
struct fib6_table *table;
struct net *net = dev_net(rt->dst.dev);
if (rt == net->ipv6.ip6_null_entry ||
rt->dst.flags & DST_NOCACHE) {
err = -ENOENT;
goto out;
}
table = rt->rt6i_table;
write_lock_bh(&table->tb6_lock);
err = fib6_del(rt, info);
write_unlock_bh(&table->tb6_lock);
out:
ip6_rt_put(rt);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 30 | 28.04% | 4 | 23.53% |
thomas graf | thomas graf | 19 | 17.76% | 3 | 17.65% |
gao feng | gao feng | 14 | 13.08% | 1 | 5.88% |
daniel lezcano | daniel lezcano | 12 | 11.21% | 1 | 5.88% |
martin kafai lau | martin kafai lau | 8 | 7.48% | 1 | 5.88% |
patrick mchardy | patrick mchardy | 8 | 7.48% | 1 | 5.88% |
herbert xu | herbert xu | 5 | 4.67% | 1 | 5.88% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 2.80% | 1 | 5.88% |
mathew richardson | mathew richardson | 3 | 2.80% | 1 | 5.88% |
david s. miller | david s. miller | 3 | 2.80% | 1 | 5.88% |
jamal hadi salim | jamal hadi salim | 1 | 0.93% | 1 | 5.88% |
americo wang | americo wang | 1 | 0.93% | 1 | 5.88% |
| Total | 107 | 100.00% | 17 | 100.00% |
int ip6_del_rt(struct rt6_info *rt)
{
struct nl_info info = {
.nl_net = dev_net(rt->dst.dev),
};
return __ip6_del_rt(rt, &info);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 17 | 45.95% | 1 | 16.67% |
denis v. lunev | denis v. lunev | 12 | 32.43% | 2 | 33.33% |
david s. miller | david s. miller | 3 | 8.11% | 1 | 16.67% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 8.11% | 1 | 16.67% |
daniel lezcano | daniel lezcano | 2 | 5.41% | 1 | 16.67% |
| Total | 37 | 100.00% | 6 | 100.00% |
static int ip6_route_del(struct fib6_config *cfg)
{
struct fib6_table *table;
struct fib6_node *fn;
struct rt6_info *rt;
int err = -ESRCH;
table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
if (!table)
return err;
read_lock_bh(&table->tb6_lock);
fn = fib6_locate(&table->tb6_root,
&cfg->fc_dst, cfg->fc_dst_len,
&cfg->fc_src, cfg->fc_src_len);
if (fn) {
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
if ((rt->rt6i_flags & RTF_CACHE) &&
!(cfg->fc_flags & RTF_CACHE))
continue;
if (cfg->fc_ifindex &&
(!rt->dst.dev ||
rt->dst.dev->ifindex != cfg->fc_ifindex))
continue;
if (cfg->fc_flags & RTF_GATEWAY &&
!ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway))
continue;
if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
continue;
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
return __ip6_del_rt(rt, &cfg->fc_nlinfo);
}
}
read_unlock_bh(&table->tb6_lock);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 138 | 57.26% | 9 | 39.13% |
thomas graf | thomas graf | 60 | 24.90% | 3 | 13.04% |
martin kafai lau | martin kafai lau | 20 | 8.30% | 1 | 4.35% |
david s. miller | david s. miller | 8 | 3.32% | 2 | 8.70% |
daniel lezcano | daniel lezcano | 6 | 2.49% | 2 | 8.70% |
eric dumazet | eric dumazet | 3 | 1.24% | 1 | 4.35% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 0.83% | 1 | 4.35% |
jamal hadi salim | jamal hadi salim | 1 | 0.41% | 1 | 4.35% |
stephen rothwell | stephen rothwell | 1 | 0.41% | 1 | 4.35% |
james morris | james morris | 1 | 0.41% | 1 | 4.35% |
mathew richardson | mathew richardson | 1 | 0.41% | 1 | 4.35% |
| Total | 241 | 100.00% | 23 | 100.00% |
static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb)
{
struct netevent_redirect netevent;
struct rt6_info *rt, *nrt = NULL;
struct ndisc_options ndopts;
struct inet6_dev *in6_dev;
struct neighbour *neigh;
struct rd_msg *msg;
int optlen, on_link;
u8 *lladdr;
optlen = skb_tail_pointer(skb) - skb_transport_header(skb);
optlen -= sizeof(*msg);
if (optlen < 0) {
net_dbg_ratelimited("rt6_do_redirect: packet too short\n");
return;
}
msg = (struct rd_msg *)icmp6_hdr(skb);
if (ipv6_addr_is_multicast(&msg->dest)) {
net_dbg_ratelimited("rt6_do_redirect: destination address is multicast\n");
return;
}
on_link = 0;
if (ipv6_addr_equal(&msg->dest, &msg->target)) {
on_link = 1;
} else if (ipv6_addr_type(&msg->target) !=
(IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
net_dbg_ratelimited("rt6_do_redirect: target address is not link-local unicast\n");
return;
}
in6_dev = __in6_dev_get(skb->dev);
if (!in6_dev)
return;
if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects)
return;
/* RFC2461 8.1:
* The IP source address of the Redirect MUST be the same as the current
* first-hop router for the specified ICMP Destination Address.
*/
if (!ndisc_parse_options(msg->opt, optlen, &ndopts)) {
net_dbg_ratelimited("rt6_redirect: invalid ND options\n");
return;
}
lladdr = NULL;
if (ndopts.nd_opts_tgt_lladdr) {
lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
skb->dev);
if (!lladdr) {
net_dbg_ratelimited("rt6_redirect: invalid link-layer address length\n");
return;
}
}
rt = (struct rt6_info *) dst;
if (rt->rt6i_flags & RTF_REJECT) {
net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n");
return;
}
/* Redirect received -> path was valid.
* Look, redirects are sent only in response to data packets,
* so that this nexthop apparently is reachable. --ANK
*/
dst_confirm(&rt->dst);
neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1);
if (!neigh)
return;
/*
* We have finally decided to accept it.
*/
neigh_update(neigh, lladdr, NUD_STALE,
NEIGH_UPDATE_F_WEAK_OVERRIDE|
NEIGH_UPDATE_F_OVERRIDE|
(on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
NEIGH_UPDATE_F_ISROUTER))
);
nrt = ip6_rt_cache_alloc(rt, &msg->dest, NULL);
if (!nrt)
goto out;
nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
if (on_link)
nrt->rt6i_flags &= ~RTF_GATEWAY;
nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
if (ip6_ins_rt(nrt))
goto out;
netevent.old = &rt->dst;
netevent.new = &nrt->dst;
netevent.daddr = &msg->dest;
netevent.neigh = neigh;
call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
if (rt->rt6i_flags & RTF_CACHE) {
rt = (struct rt6_info *) dst_clone(&rt->dst);
ip6_del_rt(rt);
}
out:
neigh_release(neigh);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 304 | 60.56% | 5 | 21.74% |
hideaki yoshifuji | hideaki yoshifuji | 78 | 15.54% | 6 | 26.09% |
pre-git | pre-git | 75 | 14.94% | 5 | 21.74% |
tom tucker | tom tucker | 26 | 5.18% | 1 | 4.35% |
simon horman | simon horman | 6 | 1.20% | 1 | 4.35% |
martin kafai lau | martin kafai lau | 3 | 0.60% | 1 | 4.35% |
daniel lezcano | daniel lezcano | 3 | 0.60% | 1 | 4.35% |
matthias schiffer | matthias schiffer | 3 | 0.60% | 1 | 4.35% |
eric dumazet | eric dumazet | 2 | 0.40% | 1 | 4.35% |
alexey dobriyan | alexey dobriyan | 2 | 0.40% | 1 | 4.35% |
| Total | 502 | 100.00% | 23 | 100.00% |
/*
* Misc support functions
*/
static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
{
BUG_ON(from->dst.from);
rt->rt6i_flags &= ~RTF_EXPIRES;
dst_hold(&from->dst);
rt->dst.from = &from->dst;
dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
martin kafai lau | martin kafai lau | 69 | 100.00% | 1 | 100.00% |
| Total | 69 | 100.00% | 1 | 100.00% |
static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
{
rt->dst.input = ort->dst.input;
rt->dst.output = ort->dst.output;
rt->rt6i_dst = ort->rt6i_dst;
rt->dst.error = ort->dst.error;
rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
rt->dst.lastuse = jiffies;
rt->rt6i_gateway = ort->rt6i_gateway;
rt->rt6i_flags = ort->rt6i_flags;
rt6_set_from(rt, ort);
rt->rt6i_metric = ort->rt6i_metric;
#ifdef CONFIG_IPV6_SUBTREES
rt->rt6i_src = ort->rt6i_src;
#endif
rt->rt6i_prefsrc = ort->rt6i_prefsrc;
rt->rt6i_table = ort->rt6i_table;
rt->dst.lwtstate = lwtstate_get(ort->dst.lwtstate);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 73 | 44.51% | 5 | 26.32% |
hideaki yoshifuji | hideaki yoshifuji | 21 | 12.80% | 1 | 5.26% |
ville nuorvala | ville nuorvala | 10 | 6.10% | 1 | 5.26% |
nicolas dichtel | nicolas dichtel | 10 | 6.10% | 2 | 10.53% |
martin kafai lau | martin kafai lau | 10 | 6.10% | 1 | 5.26% |
thomas graf | thomas graf | 8 | 4.88% | 1 | 5.26% |
gao feng | gao feng | 8 | 4.88% | 1 | 5.26% |
florian westphal | florian westphal | 7 | 4.27% | 1 | 5.26% |
jiri benc | jiri benc | 6 | 3.66% | 1 | 5.26% |
eric dumazet | eric dumazet | 5 | 3.05% | 1 | 5.26% |
zheng yan | zheng yan | 2 | 1.22% | 1 | 5.26% |
alexey dobriyan | alexey dobriyan | 2 | 1.22% | 1 | 5.26% |
benjamin thery | benjamin thery | 1 | 0.61% | 1 | 5.26% |
david s. miller | david s. miller | 1 | 0.61% | 1 | 5.26% |
| Total | 164 | 100.00% | 19 | 100.00% |
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct rt6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr, int ifindex)
{
struct fib6_node *fn;
struct rt6_info *rt = NULL;
struct fib6_table *table;
table = fib6_get_table(net, RT6_TABLE_INFO);
if (!table)
return NULL;
read_lock_bh(&table->tb6_lock);
fn = fib6_locate(&table->tb6_root, prefix, prefixlen, NULL, 0);
if (!fn)
goto out;
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
if (rt->dst.dev->ifindex != ifindex)
continue;
if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
continue;
if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr))
continue;
dst_hold(&rt->dst);
break;
}
out:
read_unlock_bh(&table->tb6_lock);
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 143 | 75.66% | 1 | 11.11% |
thomas graf | thomas graf | 28 | 14.81% | 1 | 11.11% |
daniel lezcano | daniel lezcano | 7 | 3.70% | 2 | 22.22% |
eric dumazet | eric dumazet | 5 | 2.65% | 2 | 22.22% |
david s. miller | david s. miller | 4 | 2.12% | 2 | 22.22% |
li rongqing | li rongqing | 2 | 1.06% | 1 | 11.11% |
| Total | 189 | 100.00% | 9 | 100.00% |
static struct rt6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr, int ifindex,
unsigned int pref)
{
struct fib6_config cfg = {
.fc_metric = IP6_RT_PRIO_USER,
.fc_ifindex = ifindex,
.fc_dst_len = prefixlen,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
RTF_UP | RTF_PREF(pref),
.fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = net,
};
cfg.fc_table = l3mdev_fib_table_by_index(net, ifindex) ? : RT6_TABLE_INFO;
cfg.fc_dst = *prefix;
cfg.fc_gateway = *gwaddr;
/* We should treat it as a default route if prefix length is 0. */
if (!prefixlen)
cfg.fc_flags |= RTF_DEFAULT;
ip6_route_add(&cfg);
return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 75 | 49.02% | 2 | 20.00% |
thomas graf | thomas graf | 28 | 18.30% | 1 | 10.00% |
daniel lezcano | daniel lezcano | 27 | 17.65% | 1 | 10.00% |
david ahern | david ahern | 14 | 9.15% | 1 | 10.00% |
alexey dobriyan | alexey dobriyan | 4 | 2.61% | 1 | 10.00% |
eric dumazet | eric dumazet | 3 | 1.96% | 2 | 20.00% |
rami rosen | rami rosen | 1 | 0.65% | 1 | 10.00% |
eric w. biederman | eric w. biederman | 1 | 0.65% | 1 | 10.00% |
| Total | 153 | 100.00% | 10 | 100.00% |
#endif
struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev)
{
struct rt6_info *rt;
struct fib6_table *table;
table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
if (!table)
return NULL;
read_lock_bh(&table->tb6_lock);
for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
if (dev == rt->dst.dev &&
((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
ipv6_addr_equal(&rt->rt6i_gateway, addr))
break;
}
if (rt)
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 82 | 57.75% | 6 | 33.33% |
hideaki yoshifuji | hideaki yoshifuji | 24 | 16.90% | 3 | 16.67% |
thomas graf | thomas graf | 23 | 16.20% | 1 | 5.56% |
david s. miller | david s. miller | 4 | 2.82% | 2 | 11.11% |
eric dumazet | eric dumazet | 4 | 2.82% | 2 | 11.11% |
daniel lezcano | daniel lezcano | 2 | 1.41% | 2 | 11.11% |
li rongqing | li rongqing | 2 | 1.41% | 1 | 5.56% |
james morris | james morris | 1 | 0.70% | 1 | 5.56% |
| Total | 142 | 100.00% | 18 | 100.00% |
struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
struct net_device *dev,
unsigned int pref)
{
struct fib6_config cfg = {
.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT,
.fc_metric = IP6_RT_PRIO_USER,
.fc_ifindex = dev->ifindex,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
.fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = dev_net(dev),
};
cfg.fc_gateway = *gwaddr;
ip6_route_add(&cfg);
return rt6_get_dflt_router(gwaddr, dev);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 46 | 40.35% | 4 | 28.57% |
thomas graf | thomas graf | 23 | 20.18% | 1 | 7.14% |
daniel lezcano | daniel lezcano | 20 | 17.54% | 1 | 7.14% |
hideaki yoshifuji | hideaki yoshifuji | 14 | 12.28% | 3 | 21.43% |
david ahern | david ahern | 6 | 5.26% | 1 | 7.14% |
alexey dobriyan | alexey dobriyan | 2 | 1.75% | 1 | 7.14% |
eric w. biederman | eric w. biederman | 1 | 0.88% | 1 | 7.14% |
eric dumazet | eric dumazet | 1 | 0.88% | 1 | 7.14% |
rami rosen | rami rosen | 1 | 0.88% | 1 | 7.14% |
| Total | 114 | 100.00% | 14 | 100.00% |
void rt6_purge_dflt_routers(struct net *net)
{
struct rt6_info *rt;
struct fib6_table *table;
/* NOTE: Keep consistent with rt6_get_dflt_router */
table = fib6_get_table(net, RT6_TABLE_DFLT);
if (!table)
return;
restart:
read_lock_bh(&table->tb6_lock);
for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
(!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
ip6_del_rt(rt);
goto restart;
}
}
read_unlock_bh(&table->tb6_lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 69 | 52.67% | 4 | 36.36% |
thomas graf | thomas graf | 30 | 22.90% | 1 | 9.09% |
lorenzo colitti | lorenzo colitti | 17 | 12.98% | 1 | 9.09% |
daniel lezcano | daniel lezcano | 6 | 4.58% | 2 | 18.18% |
hideaki yoshifuji | hideaki yoshifuji | 5 | 3.82% | 1 | 9.09% |
eric dumazet | eric dumazet | 3 | 2.29% | 1 | 9.09% |
david s. miller | david s. miller | 1 | 0.76% | 1 | 9.09% |
| Total | 131 | 100.00% | 11 | 100.00% |
static void rtmsg_to_fib6_config(struct net *net,
struct in6_rtmsg *rtmsg,
struct fib6_config *cfg)
{
memset(cfg, 0, sizeof(*cfg));
cfg->fc_table = l3mdev_fib_table_by_index(net, rtmsg->rtmsg_ifindex) ?
: RT6_TABLE_MAIN;
cfg->fc_ifindex = rtmsg->rtmsg_ifindex;
cfg->fc_metric = rtmsg->rtmsg_metric;
cfg->fc_expires = rtmsg->rtmsg_info;
cfg->fc_dst_len = rtmsg->rtmsg_dst_len;
cfg->fc_src_len = rtmsg->rtmsg_src_len;
cfg->fc_flags = rtmsg->rtmsg_flags;
cfg->fc_nlinfo.nl_net = net;
cfg->fc_dst = rtmsg->rtmsg_dst;
cfg->fc_src = rtmsg->rtmsg_src;
cfg->fc_gateway = rtmsg->rtmsg_gateway;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 104 | 80.00% | 1 | 20.00% |
david ahern | david ahern | 10 | 7.69% | 1 | 20.00% |
benjamin thery | benjamin thery | 7 | 5.38% | 1 | 20.00% |
daniel lezcano | daniel lezcano | 6 | 4.62% | 1 | 20.00% |
alexey dobriyan | alexey dobriyan | 3 | 2.31% | 1 | 20.00% |
| Total | 130 | 100.00% | 5 | 100.00% |
int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
{
struct fib6_config cfg;
struct in6_rtmsg rtmsg;
int err;
switch (cmd) {
case SIOCADDRT: /* Add a route */
case SIOCDELRT: /* Delete a route */
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
err = copy_from_user(&rtmsg, arg,
sizeof(struct in6_rtmsg));
if (err)
return -EFAULT;
rtmsg_to_fib6_config(net, &rtmsg, &cfg);
rtnl_lock();
switch (cmd) {
case SIOCADDRT:
err = ip6_route_add(&cfg);
break;
case SIOCDELRT:
err = ip6_route_del(&cfg);
break;
default:
err = -EINVAL;
}
rtnl_unlock();
return err;
}
return -EINVAL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 115 | 79.86% | 5 | 50.00% |
thomas graf | thomas graf | 15 | 10.42% | 1 | 10.00% |
daniel lezcano | daniel lezcano | 7 | 4.86% | 1 | 10.00% |
eric w. biederman | eric w. biederman | 5 | 3.47% | 1 | 10.00% |
david s. miller | david s. miller | 1 | 0.69% | 1 | 10.00% |
al viro | al viro | 1 | 0.69% | 1 | 10.00% |
| Total | 144 | 100.00% | 10 | 100.00% |
/*
* Drop the packet on the floor
*/
static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes)
{
int type;
struct dst_entry *dst = skb_dst(skb);
switch (ipstats_mib_noroutes) {
case IPSTATS_MIB_INNOROUTES:
type = ipv6_addr_type(&ipv6_hdr(skb)->daddr);
if (type == IPV6_ADDR_ANY) {
IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
IPSTATS_MIB_INADDRERRORS);
break;
}
/* FALLTHROUGH */
case IPSTATS_MIB_OUTNOROUTES:
IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
ipstats_mib_noroutes);
break;
}
icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0);
kfree_skb(skb);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 35 | 29.41% | 2 | 14.29% |
pre-git | pre-git | 31 | 26.05% | 5 | 35.71% |
denis v. lunev | denis v. lunev | 21 | 17.65% | 1 | 7.14% |
lv liangying | lv liangying | 20 | 16.81% | 1 | 7.14% |
thomas graf | thomas graf | 4 | 3.36% | 1 | 7.14% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 4 | 3.36% | 2 | 14.29% |
eric dumazet | eric dumazet | 3 | 2.52% | 1 | 7.14% |
brian haley | brian haley | 1 | 0.84% | 1 | 7.14% |
| Total | 119 | 100.00% | 14 | 100.00% |
static int ip6_pkt_discard(struct sk_buff *skb)
{
return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 19 | 90.48% | 1 | 50.00% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 9.52% | 1 | 50.00% |
| Total | 21 | 100.00% | 2 | 100.00% |
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
skb->dev = skb_dst(skb)->dev;
return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
james morris | james morris | 13 | 30.95% | 1 | 12.50% |
eric dumazet | eric dumazet | 8 | 19.05% | 2 | 25.00% |
dave craig | dave craig | 6 | 14.29% | 1 | 12.50% |
eric w. biederman | eric w. biederman | 5 | 11.90% | 1 | 12.50% |
hideaki yoshifuji | hideaki yoshifuji | 5 | 11.90% | 1 | 12.50% |
herbert xu | herbert xu | 4 | 9.52% | 1 | 12.50% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 1 | 2.38% | 1 | 12.50% |
| Total | 42 | 100.00% | 8 | 100.00% |
static int ip6_pkt_prohibit(struct sk_buff *skb)
{
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 19 | 90.48% | 1 | 50.00% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 9.52% | 1 | 50.00% |
| Total | 21 | 100.00% | 2 | 100.00% |
static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
skb->dev = skb_dst(skb)->dev;
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 24 | 57.14% | 1 | 20.00% |
eric dumazet | eric dumazet | 8 | 19.05% | 2 | 40.00% |
eric w. biederman | eric w. biederman | 5 | 11.90% | 1 | 20.00% |
hideaki yoshifuji | hideaki yoshifuji | 5 | 11.90% | 1 | 20.00% |
| Total | 42 | 100.00% | 5 | 100.00% |
/*
* Allocate a dst for local (unicast / anycast) address.
*/
struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
const struct in6_addr *addr,
bool anycast)
{
u32 tb_id;
struct net *net = dev_net(idev->dev);
struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
DST_NOCOUNT);
if (!rt)
return ERR_PTR(-ENOMEM);
in6_dev_hold(idev);
rt->dst.flags |= DST_HOST;
rt->dst.input = ip6_input;
rt->dst.output = ip6_output;
rt->rt6i_idev = idev;
rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
if (anycast)
rt->rt6i_flags |= RTF_ANYCAST;
else
rt->rt6i_flags |= RTF_LOCAL;
rt->rt6i_gateway = *addr;
rt->rt6i_dst.addr = *addr;
rt->rt6i_dst.plen = 128;
tb_id = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL;
rt->rt6i_table = fib6_get_table(net, tb_id);
rt->dst.flags |= DST_NOCACHE;
atomic_set(&rt->dst.__refcnt, 1);
return rt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 79 | 40.72% | 5 | 18.52% |
hideaki yoshifuji | hideaki yoshifuji | 38 | 19.59% | 6 | 22.22% |
david ahern | david ahern | 16 | 8.25% | 1 | 3.70% |
alexey kuznetsov | alexey kuznetsov | 12 | 6.19% | 1 | 3.70% |
daniel lezcano | daniel lezcano | 11 | 5.67% | 2 | 7.41% |
david s. miller | david s. miller | 9 | 4.64% | 6 | 22.22% |
thomas graf | thomas graf | 8 | 4.12% | 1 | 3.70% |
martin kafai lau | martin kafai lau | 8 | 4.12% | 1 | 3.70% |
julian anastasov | julian anastasov | 7 | 3.61% | 1 | 3.70% |
benjamin thery | benjamin thery | 3 | 1.55% | 1 | 3.70% |
alexey dobriyan | alexey dobriyan | 2 | 1.03% | 1 | 3.70% |
hannes frederic sowa | hannes frederic sowa | 1 | 0.52% | 1 | 3.70% |
| Total | 194 | 100.00% | 27 | 100.00% |
int ip6_route_get_saddr(struct net *net,
struct rt6_info *rt,
const struct in6_addr *daddr,
unsigned int prefs,
struct in6_addr *saddr)
{
struct inet6_dev *idev =
rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL;
int err = 0;
if (rt && rt->rt6i_prefsrc.plen)
*saddr = rt->rt6i_prefsrc.addr;
else
err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
daddr, prefs, saddr);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel walter | daniel walter | 89 | 90.82% | 1 | 25.00% |
markus stenberg | markus stenberg | 6 | 6.12% | 1 | 25.00% |
alexey dobriyan | alexey dobriyan | 2 | 2.04% | 1 | 25.00% |
eric dumazet | eric dumazet | 1 | 1.02% | 1 | 25.00% |
| Total | 98 | 100.00% | 4 | 100.00% |
/* remove deleted ip from prefsrc entries */
struct arg_dev_net_ip {
struct net_device *dev;
struct net *net;
struct in6_addr *addr;
};
static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
{
struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
struct net *net = ((struct arg_dev_net_ip *)arg)->net;
struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
if (((void *)rt->dst.dev == dev || !dev) &&
rt != net->ipv6.ip6_null_entry &&
ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
/* remove prefsrc entry */
rt->rt6i_prefsrc.plen = 0;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel walter | daniel walter | 112 | 96.55% | 1 | 33.33% |
david s. miller | david s. miller | 4 | 3.45% | 2 | 66.67% |
| Total | 116 | 100.00% | 3 | 100.00% |
void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
{
struct net *net = dev_net(ifp->idev->dev);
struct arg_dev_net_ip adni = {
.dev = ifp->idev->dev,
.net = net,
.addr = &ifp->addr,
};
fib6_clean_all(net, fib6_remove_prefsrc, &adni);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel walter | daniel walter | 62 | 100.00% | 1 | 100.00% |
| Total | 62 | 100.00% | 1 | 100.00% |
#define RTF_RA_ROUTER (RTF_ADDRCONF | RTF_DEFAULT | RTF_GATEWAY)
#define RTF_CACHE_GATEWAY (RTF_GATEWAY | RTF_CACHE)
/* Remove routers and update dst entries when gateway turn into host. */
static int fib6_clean_tohost(struct rt6_info *rt, void *arg)
{
struct in6_addr *gateway = (struct in6_addr *)arg;
if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) ||
((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) &&
ipv6_addr_equal(gateway, &rt->rt6i_gateway)) {
return -1;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
duan jiong | duan jiong | 74 | 100.00% | 1 | 100.00% |
| Total | 74 | 100.00% | 1 | 100.00% |
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
{
fib6_clean_all(net, fib6_clean_tohost, gateway);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
duan jiong | duan jiong | 24 | 100.00% | 1 | 100.00% |
| Total | 24 | 100.00% | 1 | 100.00% |
struct arg_dev_net {
struct net_device *dev;
struct net *net;
};
static int fib6_ifdown(struct rt6_info *rt, void *arg)
{
const struct arg_dev_net *adn = arg;
const struct net_device *dev = adn->dev;
if ((rt->dst.dev == dev || !dev) &&
rt != adn->net->ipv6.ip6_null_entry)
return -1;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 35 | 53.85% | 2 | 33.33% |
daniel lezcano | daniel lezcano | 16 | 24.62% | 1 | 16.67% |
stephen hemminger | stephen hemminger | 10 | 15.38% | 1 | 16.67% |
david s. miller | david s. miller | 4 | 6.15% | 2 | 33.33% |
| Total | 65 | 100.00% | 6 | 100.00% |
void rt6_ifdown(struct net *net, struct net_device *dev)
{
struct arg_dev_net adn = {
.dev = dev,
.net = net,
};
fib6_clean_all(net, fib6_ifdown, &adn);
icmp6_clean_all(fib6_ifdown, &adn);
if (dev)
rt6_uncached_list_flush_dev(net, dev);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel lezcano | daniel lezcano | 25 | 41.67% | 2 | 22.22% |
pre-git | pre-git | 15 | 25.00% | 3 | 33.33% |
david s. miller | david s. miller | 8 | 13.33% | 1 | 11.11% |
martin kafai lau | martin kafai lau | 7 | 11.67% | 1 | 11.11% |
eric w. biederman | eric w. biederman | 4 | 6.67% | 1 | 11.11% |
thomas graf | thomas graf | 1 | 1.67% | 1 | 11.11% |
| Total | 60 | 100.00% | 9 | 100.00% |
struct rt6_mtu_change_arg {
struct net_device *dev;
unsigned int mtu;
};
static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
{
struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;
struct inet6_dev *idev;
/* In IPv6 pmtu discovery is not optional,
so that RTAX_MTU lock cannot disable it.
We still use this lock to block changes
caused by addrconf/ndisc.
*/
idev = __in6_dev_get(arg->dev);
if (!idev)
return 0;
/* For administrative MTU increase, there is no way to discover
IPv6 PMTU increase, so PMTU increase should be updated here.
Since RFC 1981 doesn't include administrative MTU increase
update PMTU increase is a MUST. (i.e. jumbo frame)
*/
/*
If new MTU is less than route PMTU, this new MTU will be the
lowest MTU in the path, update the route PMTU to reflect PMTU
decreases; if new MTU is greater than route PMTU, and the
old MTU is the lowest MTU in the path, update the route PMTU
to reflect the increase. In this case if the other nodes' MTU
also have the lowest MTU, TOO BIG MESSAGE will be lead to
PMTU discouvery.
*/
if (rt->dst.dev == arg->dev &&
!dst_metric_locked(&rt->dst, RTAX_MTU)) {
if (rt->rt6i_flags & RTF_CACHE) {
/* For RTF_CACHE with rt6i_pmtu == 0
* (i.e. a redirected route),
* the metrics of its rt->dst.from has already
* been updated.
*/
if (rt->rt6i_pmtu && rt->rt6i_pmtu > arg->mtu)
rt->rt6i_pmtu = arg->mtu;
} else if (dst_mtu(&rt->dst) >= arg->mtu ||
(dst_mtu(&rt->dst) < arg->mtu &&
dst_mtu(&rt->dst) == idev->cnf.mtu6)) {
dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu);
}
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 51 | 29.65% | 3 | 20.00% |
shirley ma | shirley ma | 47 | 27.33% | 1 | 6.67% |
martin kafai lau | martin kafai lau | 38 | 22.09% | 1 | 6.67% |
alexey kuznetsov | alexey kuznetsov | 12 | 6.98% | 2 | 13.33% |
david s. miller | david s. miller | 10 | 5.81% | 3 | 20.00% |
linus torvalds | linus torvalds | 7 | 4.07% | 1 | 6.67% |
herbert xu | herbert xu | 3 | 1.74% | 1 | 6.67% |
simon arlott | simon arlott | 2 | 1.16% | 1 | 6.67% |
jim paris | jim paris | 1 | 0.58% | 1 | 6.67% |
hideaki yoshifuji | hideaki yoshifuji | 1 | 0.58% | 1 | 6.67% |
| Total | 172 | 100.00% | 15 | 100.00% |
void rt6_mtu_change(struct net_device *dev, unsigned int mtu)
{
struct rt6_mtu_change_arg arg = {
.dev = dev,
.mtu = mtu,
};
fib6_clean_all(dev_net(dev), rt6_mtu_change_route, &arg);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 31 | 72.09% | 3 | 42.86% |
thomas graf | thomas graf | 6 | 13.95% | 1 | 14.29% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 6.98% | 1 | 14.29% |
daniel lezcano | daniel lezcano | 2 | 4.65% | 1 | 14.29% |
eric dumazet | eric dumazet | 1 | 2.33% | 1 | 14.29% |
| Total | 43 | 100.00% | 7 | 100.00% |
static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
[RTA_OIF] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
[RTA_PRIORITY] = { .type = NLA_U32 },
[RTA_METRICS] = { .type = NLA_NESTED },
[RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
[RTA_PREF] = { .type = NLA_U8 },
[RTA_ENCAP_TYPE] = { .type = NLA_U16 },
[RTA_ENCAP] = { .type = NLA_NESTED },
[RTA_EXPIRES] = { .type = NLA_U32 },
};
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
struct fib6_config *cfg)
{
struct rtmsg *rtm;
struct nlattr *tb[RTA_MAX+1];
unsigned int pref;
int err;
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
if (err < 0)
goto errout;
err = -EINVAL;
rtm = nlmsg_data(nlh);
memset(cfg, 0, sizeof(*cfg));
cfg->fc_table = rtm->rtm_table;
cfg->fc_dst_len = rtm->rtm_dst_len;
cfg->fc_src_len = rtm->rtm_src_len;
cfg->fc_flags = RTF_UP;
cfg->fc_protocol = rtm->rtm_protocol;
cfg->fc_type = rtm->rtm_type;
if (rtm->rtm_type == RTN_UNREACHABLE ||
rtm->rtm_type == RTN_BLACKHOLE ||
rtm->rtm_type == RTN_PROHIBIT ||
rtm->rtm_type == RTN_THROW)
cfg->fc_flags |= RTF_REJECT;
if (rtm->rtm_type == RTN_LOCAL)
cfg->fc_flags |= RTF_LOCAL;
if (rtm->rtm_flags & RTM_F_CLONED)
cfg->fc_flags |= RTF_CACHE;
cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
cfg->fc_nlinfo.nlh = nlh;
cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
if (tb[RTA_GATEWAY]) {
cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]);
cfg->fc_flags |= RTF_GATEWAY;
}
if (tb[RTA_DST]) {
int plen = (rtm->rtm_dst_len + 7) >> 3;
if (nla_len(tb[RTA_DST]) < plen)
goto errout;
nla_memcpy(&cfg->fc_dst, tb[RTA_DST], plen);
}
if (tb[RTA_SRC]) {
int plen = (rtm->rtm_src_len + 7) >> 3;
if (nla_len(tb[RTA_SRC]) < plen)
goto errout;
nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
}
if (tb[RTA_PREFSRC])
cfg->fc_prefsrc = nla_get_in6_addr(tb[RTA_PREFSRC]);
if (tb[RTA_OIF])
cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
if (tb[RTA_PRIORITY])
cfg->fc_metric = nla_get_u32(tb[RTA_PRIORITY]);
if (tb[RTA_METRICS]) {
cfg->fc_mx = nla_data(tb[RTA_METRICS]);
cfg->fc_mx_len = nla_len(tb[RTA_METRICS]);
}
if (tb[RTA_TABLE])
cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
if (tb[RTA_MULTIPATH]) {
cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
}
if (tb[RTA_PREF]) {
pref = nla_get_u8(tb[RTA_PREF]);
if (pref != ICMPV6_ROUTER_PREF_LOW &&
pref != ICMPV6_ROUTER_PREF_HIGH)
pref = ICMPV6_ROUTER_PREF_MEDIUM;
cfg->fc_flags |= RTF_PREF(pref);
}
if (tb[RTA_ENCAP])
cfg->fc_encap = tb[RTA_ENCAP];
if (tb[RTA_ENCAP_TYPE])
cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]);
if (tb[RTA_EXPIRES]) {
unsigned long timeout = addrconf_timeout_fixup(nla_get_u32(tb[RTA_EXPIRES]), HZ);
if (addrconf_finite_timeout(timeout)) {
cfg->fc_expires = jiffies_to_clock_t(timeout * HZ);
cfg->fc_flags |= RTF_EXPIRES;
}
}
err = 0;
errout:
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 234 | 36.17% | 1 | 5.88% |
pre-git | pre-git | 156 | 24.11% | 3 | 17.65% |
nicolas dichtel | nicolas dichtel | 59 | 9.12% | 3 | 17.65% |
lucien xin | lucien xin | 52 | 8.04% | 1 | 5.88% |
lubomir rintel | lubomir rintel | 46 | 7.11% | 1 | 5.88% |
roopa prabhu | roopa prabhu | 35 | 5.41% | 1 | 5.88% |
daniel walter | daniel walter | 16 | 2.47% | 1 | 5.88% |
maciej zenczykowski | maciej zenczykowski | 14 | 2.16% | 1 | 5.88% |
martin kafai lau | martin kafai lau | 14 | 2.16% | 1 | 5.88% |
benjamin thery | benjamin thery | 10 | 1.55% | 1 | 5.88% |
jiri benc | jiri benc | 6 | 0.93% | 1 | 5.88% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 0.46% | 1 | 5.88% |
eric w. biederman | eric w. biederman | 2 | 0.31% | 1 | 5.88% |
| Total | 647 | 100.00% | 17 | 100.00% |
struct rt6_nh {
struct rt6_info *rt6_info;
struct fib6_config r_cfg;
struct mx6_config mxc;
struct list_head next;
};
static void ip6_print_replace_route_err(struct list_head *rt6_nh_list)
{
struct rt6_nh *nh;
list_for_each_entry(nh, rt6_nh_list, next) {
pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6 nexthop %pI6 ifi %d\n",
&nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway,
nh->r_cfg.fc_ifindex);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roopa prabhu | roopa prabhu | 35 | 68.63% | 1 | 50.00% |
nicolas dichtel | nicolas dichtel | 16 | 31.37% | 1 | 50.00% |
| Total | 51 | 100.00% | 2 | 100.00% |
static int ip6_route_info_append(struct list_head *rt6_nh_list,
struct rt6_info *rt, struct fib6_config *r_cfg)
{
struct rt6_nh *nh;
struct rt6_info *rtnh;
int err = -EEXIST;
list_for_each_entry(nh, rt6_nh_list, next) {
/* check if rt6_info already exists */
rtnh = nh->rt6_info;
if (rtnh->dst.dev == rt->dst.dev &&
rtnh->rt6i_idev == rt->rt6i_idev &&
ipv6_addr_equal(&rtnh->rt6i_gateway,
&rt->rt6i_gateway))
return err;
}
nh = kzalloc(sizeof(*nh), GFP_KERNEL);
if (!nh)
return -ENOMEM;
nh->rt6_info = rt;
err = ip6_convert_metrics(&nh->mxc, r_cfg);
if (err) {
kfree(nh);
return err;
}
memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg));
list_add_tail(&nh->next, rt6_nh_list);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roopa prabhu | roopa prabhu | 175 | 100.00% | 1 | 100.00% |
| Total | 175 | 100.00% | 1 | 100.00% |
static int ip6_route_multipath_add(struct fib6_config *cfg)
{
struct fib6_config r_cfg;
struct rtnexthop *rtnh;
struct rt6_info *rt;
struct rt6_nh *err_nh;
struct rt6_nh *nh, *nh_safe;
int remaining;
int attrlen;
int err = 1;
int nhn = 0;
int replace = (cfg->fc_nlinfo.nlh &&
(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE));
LIST_HEAD(rt6_nh_list);
remaining = cfg->fc_mp_len;
rtnh = (struct rtnexthop *)cfg->fc_mp;
/* Parse a Multipath Entry and build a list (rt6_nh_list) of
* rt6_info structs per nexthop
*/
while (rtnh_ok(rtnh, remaining)) {
memcpy(&r_cfg, cfg, sizeof(*cfg));
if (rtnh->rtnh_ifindex)
r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
attrlen = rtnh_attrlen(rtnh);
if (attrlen > 0) {
struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
if (nla) {
r_cfg.fc_gateway = nla_get_in6_addr(nla);
r_cfg.fc_flags |= RTF_GATEWAY;
}
r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
if (nla)
r_cfg.fc_encap_type = nla_get_u16(nla);
}
rt = ip6_route_info_create(&r_cfg);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
rt = NULL;
goto cleanup;
}
err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
if (err) {
dst_free(&rt->dst);
goto cleanup;
}
rtnh = rtnh_next(rtnh, &remaining);
}
err_nh = NULL;
list_for_each_entry(nh, &rt6_nh_list, next) {
err = __ip6_ins_rt(nh->rt6_info, &cfg->fc_nlinfo, &nh->mxc);
/* nh->rt6_info is used or freed at this point, reset to NULL*/
nh->rt6_info = NULL;
if (err) {
if (replace && nhn)
ip6_print_replace_route_err(&rt6_nh_list);
err_nh = nh;
goto add_errout;
}
/* Because each route is added like a single route we remove
* these flags after the first nexthop: if there is a collision,
* we have already failed to add the first nexthop:
* fib6_add_rt2node() has rejected it; when replacing, old
* nexthops have been replaced by first new, the rest should
* be added to it.
*/
cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL |
NLM_F_REPLACE);
nhn++;
}
goto cleanup;
add_errout:
/* Delete routes that were already added */
list_for_each_entry(nh, &rt6_nh_list, next) {
if (err_nh == nh)
break;
ip6_route_del(&nh->r_cfg);
}
cleanup:
list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) {
if (nh->rt6_info)
dst_free(&nh->rt6_info->dst);
kfree(nh->mxc.mx);
list_del(&nh->next);
kfree(nh);
}
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roopa prabhu | roopa prabhu | 460 | 96.44% | 2 | 50.00% |
nicolas dichtel | nicolas dichtel | 16 | 3.35% | 1 | 25.00% |
jiri benc | jiri benc | 1 | 0.21% | 1 | 25.00% |
| Total | 477 | 100.00% | 4 | 100.00% |
static int ip6_route_multipath_del(struct fib6_config *cfg)
{
struct fib6_config r_cfg;
struct rtnexthop *rtnh;
int remaining;
int attrlen;
int err = 1, last_err = 0;
remaining = cfg->fc_mp_len;
rtnh = (struct rtnexthop *)cfg->fc_mp;
/* Parse a Multipath Entry */
while (rtnh_ok(rtnh, remaining)) {
memcpy(&r_cfg, cfg, sizeof(*cfg));
if (rtnh->rtnh_ifindex)
r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
attrlen = rtnh_attrlen(rtnh);
if (attrlen > 0) {
struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
if (nla) {
nla_memcpy(&r_cfg.fc_gateway, nla, 16);
r_cfg.fc_flags |= RTF_GATEWAY;
}
}
err = ip6_route_del(&r_cfg);
if (err)
last_err = err;
rtnh = rtnh_next(rtnh, &remaining);
}
return last_err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roopa prabhu | roopa prabhu | 152 | 82.61% | 2 | 66.67% |
nicolas dichtel | nicolas dichtel | 32 | 17.39% | 1 | 33.33% |
| Total | 184 | 100.00% | 3 | 100.00% |
static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
{
struct fib6_config cfg;
int err;
err = rtm_to_fib6_config(skb, nlh, &cfg);
if (err < 0)
return err;
if (cfg.fc_mp)
return ip6_route_multipath_del(&cfg);
else
return ip6_route_del(&cfg);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 31 | 47.69% | 2 | 28.57% |
thomas graf | thomas graf | 19 | 29.23% | 2 | 28.57% |
nicolas dichtel | nicolas dichtel | 13 | 20.00% | 1 | 14.29% |
roopa prabhu | roopa prabhu | 1 | 1.54% | 1 | 14.29% |
patrick mchardy | patrick mchardy | 1 | 1.54% | 1 | 14.29% |
| Total | 65 | 100.00% | 7 | 100.00% |
static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
{
struct fib6_config cfg;
int err;
err = rtm_to_fib6_config(skb, nlh, &cfg);
if (err < 0)
return err;
if (cfg.fc_mp)
return ip6_route_multipath_add(&cfg);
else
return ip6_route_add(&cfg);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 31 | 47.69% | 3 | 37.50% |
thomas graf | thomas graf | 19 | 29.23% | 2 | 25.00% |
nicolas dichtel | nicolas dichtel | 13 | 20.00% | 1 | 12.50% |
patrick mchardy | patrick mchardy | 1 | 1.54% | 1 | 12.50% |
roopa prabhu | roopa prabhu | 1 | 1.54% | 1 | 12.50% |
| Total | 65 | 100.00% | 8 | 100.00% |
static inline size_t rt6_nlmsg_size(struct rt6_info *rt)
{
return NLMSG_ALIGN(sizeof(struct rtmsg))
+ nla_total_size(16) /* RTA_SRC */
+ nla_total_size(16) /* RTA_DST */
+ nla_total_size(16) /* RTA_GATEWAY */
+ nla_total_size(16) /* RTA_PREFSRC */
+ nla_total_size(4) /* RTA_TABLE */
+ nla_total_size(4) /* RTA_IIF */
+ nla_total_size(4) /* RTA_OIF */
+ nla_total_size(4) /* RTA_PRIORITY */
+ RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
+ nla_total_size(sizeof(struct rta_cacheinfo))
+ nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
+ nla_total_size(1) /* RTA_PREF */
+ lwtunnel_get_encap_size(rt->dst.lwtstate);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 74 | 68.52% | 1 | 16.67% |
roopa prabhu | roopa prabhu | 11 | 10.19% | 1 | 16.67% |
noriaki takamiya | noriaki takamiya | 8 | 7.41% | 1 | 16.67% |
lubomir rintel | lubomir rintel | 6 | 5.56% | 1 | 16.67% |
daniel borkmann | daniel borkmann | 6 | 5.56% | 1 | 16.67% |
jiri benc | jiri benc | 3 | 2.78% | 1 | 16.67% |
| Total | 108 | 100.00% | 6 | 100.00% |
static int rt6_fill_node(struct net *net,
struct sk_buff *skb, struct rt6_info *rt,
struct in6_addr *dst, struct in6_addr *src,
int iif, int type, u32 portid, u32 seq,
int prefix, int nowait, unsigned int flags)
{
u32 metrics[RTAX_MAX];
struct rtmsg *rtm;
struct nlmsghdr *nlh;
long expires;
u32 table;
if (prefix) { /* user wants prefix routes only */
if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
/* success since this is not a prefix route */
return 1;
}
}
nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags);
if (!nlh)
return -EMSGSIZE;
rtm = nlmsg_data(nlh);
rtm->rtm_family = AF_INET6;
rtm->rtm_dst_len = rt->rt6i_dst.plen;
rtm->rtm_src_len = rt->rt6i_src.plen;
rtm->rtm_tos = 0;
if (rt->rt6i_table)
table = rt->rt6i_table->tb6_id;
else
table = RT6_TABLE_UNSPEC;
rtm->rtm_table = table;
if (nla_put_u32(skb, RTA_TABLE, table))
goto nla_put_failure;
if (rt->rt6i_flags & RTF_REJECT) {
switch (rt->dst.error) {
case -EINVAL:
rtm->rtm_type = RTN_BLACKHOLE;
break;
case -EACCES:
rtm->rtm_type = RTN_PROHIBIT;
break;
case -EAGAIN:
rtm->rtm_type = RTN_THROW;
break;
default:
rtm->rtm_type = RTN_UNREACHABLE;
break;
}
}
else if (rt->rt6i_flags & RTF_LOCAL)
rtm->rtm_type = RTN_LOCAL;
else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
rtm->rtm_type = RTN_LOCAL;
else
rtm->rtm_type = RTN_UNICAST;
rtm->rtm_flags = 0;
if (!netif_carrier_ok(rt->dst.dev)) {
rtm->rtm_flags |= RTNH_F_LINKDOWN;
if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
rtm->rtm_flags |= RTNH_F_DEAD;
}
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
rtm->rtm_protocol = rt->rt6i_protocol;
if (rt->rt6i_flags & RTF_DYNAMIC)
rtm->rtm_protocol = RTPROT_REDIRECT;
else if (rt->rt6i_flags & RTF_ADDRCONF) {
if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
rtm->rtm_protocol = RTPROT_RA;
else
rtm->rtm_protocol = RTPROT_KERNEL;
}
if (rt->rt6i_flags & RTF_CACHE)
rtm->rtm_flags |= RTM_F_CLONED;
if (dst) {
if (nla_put_in6_addr(skb, RTA_DST, dst))
goto nla_put_failure;
rtm->rtm_dst_len = 128;
} else if (rtm->rtm_dst_len)
if (nla_put_in6_addr(skb, RTA_DST, &rt->rt6i_dst.addr))
goto nla_put_failure;
#ifdef CONFIG_IPV6_SUBTREES
if (src) {
if (nla_put_in6_addr(skb, RTA_SRC, src))
goto nla_put_failure;
rtm->rtm_src_len = 128;
} else if (rtm->rtm_src_len &&
nla_put_in6_addr(skb, RTA_SRC, &rt->rt6i_src.addr))
goto nla_put_failure;
#endif
if (iif) {
#ifdef CONFIG_IPV6_MROUTE
if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
int err = ip6mr_get_route(net, skb, rtm, nowait);
if (err <= 0) {
if (!nowait) {
if (err == 0)
return 0;
goto nla_put_failure;
} else {
if (err == -EMSGSIZE)
goto nla_put_failure;
}
}
} else
#endif
if (nla_put_u32(skb, RTA_IIF, iif))
goto nla_put_failure;
} else if (dst) {
struct in6_addr saddr_buf;
if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0 &&
nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf))
goto nla_put_failure;
}
if (rt->rt6i_prefsrc.plen) {
struct in6_addr saddr_buf;
saddr_buf = rt->rt6i_prefsrc.addr;
if (nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf))
goto nla_put_failure;
}
memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics));
if (rt->rt6i_pmtu)
metrics[RTAX_MTU - 1] = rt->rt6i_pmtu;
if (rtnetlink_put_metrics(skb, metrics) < 0)
goto nla_put_failure;
if (rt->rt6i_flags & RTF_GATEWAY) {
if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0)
goto nla_put_failure;
}
if (rt->dst.dev &&
nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
goto nla_put_failure;
if (nla_put_u32(skb, RTA_PRIORITY, rt->rt6i_metric))
goto nla_put_failure;
expires = (rt->rt6i_flags & RTF_EXPIRES) ? rt->dst.expires - jiffies : 0;
if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0)
goto nla_put_failure;
if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
goto nla_put_failure;
lwtunnel_fill_encap(skb, rt->dst.lwtstate);
nlmsg_end(skb, nlh);
return 0;
nla_put_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 398 | 42.48% | 6 | 13.64% |
hideaki yoshifuji | hideaki yoshifuji | 94 | 10.03% | 5 | 11.36% |
david s. miller | david s. miller | 79 | 8.43% | 4 | 9.09% |
thomas graf | thomas graf | 54 | 5.76% | 3 | 6.82% |
nicolas dichtel | nicolas dichtel | 47 | 5.02% | 2 | 4.55% |
martin kafai lau | martin kafai lau | 39 | 4.16% | 1 | 2.27% |
andy gospodarek | andy gospodarek | 36 | 3.84% | 2 | 4.55% |
daniel walter | daniel walter | 29 | 3.09% | 1 | 2.27% |
krishna kumar | krishna kumar | 24 | 2.56% | 1 | 2.27% |
patrick mchardy | patrick mchardy | 22 | 2.35% | 2 | 4.55% |
lubomir rintel | lubomir rintel | 19 | 2.03% | 1 | 2.27% |
maciej zenczykowski | maciej zenczykowski | 15 | 1.60% | 1 | 2.27% |
denis ovsienko | denis ovsienko | 13 | 1.39% | 1 | 2.27% |
brian haley | brian haley | 13 | 1.39% | 2 | 4.55% |
eric dumazet | eric dumazet | 12 | 1.28% | 2 | 4.55% |
jiri benc | jiri benc | 10 | 1.07% | 2 | 4.55% |
roopa prabhu | roopa prabhu | 8 | 0.85% | 1 | 2.27% |
jamal hadi salim | jamal hadi salim | 6 | 0.64% | 1 | 2.27% |
mathew richardson | mathew richardson | 6 | 0.64% | 1 | 2.27% |
li wei | li wei | 5 | 0.53% | 1 | 2.27% |
johannes berg | johannes berg | 3 | 0.32% | 1 | 2.27% |
benjamin thery | benjamin thery | 2 | 0.21% | 1 | 2.27% |
eric w. biederman | eric w. biederman | 2 | 0.21% | 1 | 2.27% |
alexey dobriyan | alexey dobriyan | 1 | 0.11% | 1 | 2.27% |
| Total | 937 | 100.00% | 44 | 100.00% |
int rt6_dump_route(struct rt6_info *rt, void *p_arg)
{
struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
int prefix;
if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) {
struct rtmsg *rtm = nlmsg_data(arg->cb->nlh);
prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
} else
prefix = 0;
return rt6_fill_node(arg->net,
arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
NETLINK_CB(arg->cb->skb).portid, arg->cb->nlh->nlmsg_seq,
prefix, 0, NLM_F_MULTI);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 62 | 49.21% | 3 | 27.27% |
krishna kumar | krishna kumar | 29 | 23.02% | 1 | 9.09% |
ville nuorvala | ville nuorvala | 21 | 16.67% | 1 | 9.09% |
thomas graf | thomas graf | 4 | 3.17% | 1 | 9.09% |
brian haley | brian haley | 4 | 3.17% | 1 | 9.09% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 1.59% | 1 | 9.09% |
jamal hadi salim | jamal hadi salim | 2 | 1.59% | 1 | 9.09% |
eric w. biederman | eric w. biederman | 1 | 0.79% | 1 | 9.09% |
mathew richardson | mathew richardson | 1 | 0.79% | 1 | 9.09% |
| Total | 126 | 100.00% | 11 | 100.00% |
static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
{
struct net *net = sock_net(in_skb->sk);
struct nlattr *tb[RTA_MAX+1];
struct rt6_info *rt;
struct sk_buff *skb;
struct rtmsg *rtm;
struct flowi6 fl6;
int err, iif = 0, oif = 0;
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
if (err < 0)
goto errout;
err = -EINVAL;
memset(&fl6, 0, sizeof(fl6));
if (tb[RTA_SRC]) {
if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
goto errout;
fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]);
}
if (tb[RTA_DST]) {
if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
goto errout;
fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]);
}
if (tb[RTA_IIF])
iif = nla_get_u32(tb[RTA_IIF]);
if (tb[RTA_OIF])
oif = nla_get_u32(tb[RTA_OIF]);
if (tb[RTA_MARK])
fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]);
if (iif) {
struct net_device *dev;
int flags = 0;
dev = __dev_get_by_index(net, iif);
if (!dev) {
err = -ENODEV;
goto errout;
}
fl6.flowi6_iif = iif;
if (!ipv6_addr_any(&fl6.saddr))
flags |= RT6_LOOKUP_F_HAS_SADDR;
rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
flags);
} else {
fl6.flowi6_oif = oif;
if (netif_index_is_l3_master(net, oif)) {
fl6.flowi6_flags = FLOWI_FLAG_L3MDEV_SRC |
FLOWI_FLAG_SKIP_NH_OIF;
}
rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
}
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb) {
ip6_rt_put(rt);
err = -ENOBUFS;
goto errout;
}
/* Reserve room for dummy headers, this skb can pass
through good chunk of routing engine.
*/
skb_reset_mac_header(skb);
skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
skb_dst_set(skb, &rt->dst);
err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, 0, 0, 0);
if (err < 0) {
kfree_skb(skb);
goto errout;
}
err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
errout:
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 169 | 32.44% | 4 | 12.90% |
thomas graf | thomas graf | 145 | 27.83% | 3 | 9.68% |
shmulik ladkani | shmulik ladkani | 80 | 15.36% | 2 | 6.45% |
david s. miller | david s. miller | 24 | 4.61% | 4 | 12.90% |
lorenzo colitti | lorenzo colitti | 19 | 3.65% | 1 | 3.23% |
david ahern | david ahern | 19 | 3.65% | 1 | 3.23% |
james morris | james morris | 17 | 3.26% | 1 | 3.23% |
alexey dobriyan | alexey dobriyan | 14 | 2.69% | 1 | 3.23% |
denis v. lunev | denis v. lunev | 10 | 1.92% | 2 | 6.45% |
hideaki yoshifuji | hideaki yoshifuji | 5 | 0.96% | 2 | 6.45% |
eric dumazet | eric dumazet | 4 | 0.77% | 1 | 3.23% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 3 | 0.58% | 1 | 3.23% |
eric w. biederman | eric w. biederman | 3 | 0.58% | 2 | 6.45% |
jamal hadi salim | jamal hadi salim | 2 | 0.38% | 1 | 3.23% |
daniel lezcano | daniel lezcano | 2 | 0.38% | 1 | 3.23% |
brian haley | brian haley | 2 | 0.38% | 1 | 3.23% |
mathew richardson | mathew richardson | 1 | 0.19% | 1 | 3.23% |
krishna kumar | krishna kumar | 1 | 0.19% | 1 | 3.23% |
americo wang | americo wang | 1 | 0.19% | 1 | 3.23% |
| Total | 521 | 100.00% | 31 | 100.00% |
void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info,
unsigned int nlm_flags)
{
struct sk_buff *skb;
struct net *net = info->nl_net;
u32 seq;
int err;
err = -ENOBUFS;
seq = info->nlh ? info->nlh->nlmsg_seq : 0;
skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
if (!skb)
goto errout;
err = rt6_fill_node(net, skb, rt, NULL, NULL, 0,
event, info->portid, seq, 0, 0, nlm_flags);
if (err < 0) {
/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
WARN_ON(err == -EMSGSIZE);
kfree_skb(skb);
goto errout;
}
rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
info->nlh, gfp_any());
return;
errout:
if (err < 0)
rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 57 | 32.39% | 5 | 20.83% |
thomas graf | thomas graf | 45 | 25.57% | 3 | 12.50% |
patrick mchardy | patrick mchardy | 21 | 11.93% | 2 | 8.33% |
denis v. lunev | denis v. lunev | 16 | 9.09% | 2 | 8.33% |
daniel lezcano | daniel lezcano | 11 | 6.25% | 1 | 4.17% |
roopa prabhu | roopa prabhu | 8 | 4.55% | 2 | 8.33% |
jamal hadi salim | jamal hadi salim | 6 | 3.41% | 2 | 8.33% |
mathew richardson | mathew richardson | 3 | 1.70% | 1 | 4.17% |
brian haley | brian haley | 2 | 1.14% | 1 | 4.17% |
eric w. biederman | eric w. biederman | 2 | 1.14% | 1 | 4.17% |
krishna kumar | krishna kumar | 2 | 1.14% | 1 | 4.17% |
david s. miller | david s. miller | 1 | 0.57% | 1 | 4.17% |
hideaki yoshifuji | hideaki yoshifuji | 1 | 0.57% | 1 | 4.17% |
pablo neira ayuso | pablo neira ayuso | 1 | 0.57% | 1 | 4.17% |
| Total | 176 | 100.00% | 24 | 100.00% |
static int ip6_route_dev_notify(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct net *net = dev_net(dev);
if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
net->ipv6.ip6_null_entry->dst.dev = dev;
net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
net->ipv6.ip6_prohibit_entry->dst.dev = dev;
net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
#endif
}
return NOTIFY_OK;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel lezcano | daniel lezcano | 130 | 94.20% | 1 | 33.33% |
jiri pirko | jiri pirko | 5 | 3.62% | 1 | 33.33% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 2.17% | 1 | 33.33% |
| Total | 138 | 100.00% | 3 | 100.00% |
/*
* /proc
*/
#ifdef CONFIG_PROC_FS
static const struct file_operations ipv6_route_proc_fops = {
.owner = THIS_MODULE,
.open = ipv6_route_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_net,
};
static int rt6_stats_seq_show(struct seq_file *seq, void *v)
{
struct net *net = (struct net *)seq->private;
seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
net->ipv6.rt6_stats->fib_nodes,
net->ipv6.rt6_stats->fib_route_nodes,
net->ipv6.rt6_stats->fib_rt_alloc,
net->ipv6.rt6_stats->fib_rt_entries,
net->ipv6.rt6_stats->fib_rt_cache,
dst_entries_get_slow(&net->ipv6.ip6_dst_ops),
net->ipv6.rt6_stats->fib_discarded_routes);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 33 | 34.02% | 3 | 30.00% |
daniel lezcano | daniel lezcano | 32 | 32.99% | 2 | 20.00% |
benjamin thery | benjamin thery | 16 | 16.49% | 2 | 20.00% |
randy dunlap | randy dunlap | 15 | 15.46% | 2 | 20.00% |
eric dumazet | eric dumazet | 1 | 1.03% | 1 | 10.00% |
| Total | 97 | 100.00% | 10 | 100.00% |
static int rt6_stats_seq_open(struct inode *inode, struct file *file)
{
return single_open_net(inode, file, rt6_stats_seq_show);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
randy dunlap | randy dunlap | 19 | 73.08% | 1 | 20.00% |
pavel emelianov | pavel emelianov | 4 | 15.38% | 2 | 40.00% |
daniel lezcano | daniel lezcano | 2 | 7.69% | 1 | 20.00% |
pre-git | pre-git | 1 | 3.85% | 1 | 20.00% |
| Total | 26 | 100.00% | 5 | 100.00% |
static const struct file_operations rt6_stats_seq_fops = {
.owner = THIS_MODULE,
.open = rt6_stats_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release_net,
};
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSCTL
static
int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net;
int delay;
if (!write)
return -EINVAL;
net = (struct net *)ctl->extra1;
delay = net->ipv6.sysctl.flush_delay;
proc_dointvec(ctl, write, buffer, lenp, ppos);
fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 43 | 42.16% | 1 | 11.11% |
lucian adrian grijincu | lucian adrian grijincu | 24 | 23.53% | 1 | 11.11% |
daniel lezcano | daniel lezcano | 18 | 17.65% | 2 | 22.22% |
linus torvalds | linus torvalds | 6 | 5.88% | 1 | 11.11% |
michal kubecek | michal kubecek | 5 | 4.90% | 1 | 11.11% |
hideaki yoshifuji | hideaki yoshifuji | 4 | 3.92% | 1 | 11.11% |
joe perches | joe perches | 1 | 0.98% | 1 | 11.11% |
al viro | al viro | 1 | 0.98% | 1 | 11.11% |
| Total | 102 | 100.00% | 9 | 100.00% |
struct ctl_table ipv6_route_table_template[] = {
{
.procname = "flush",
.data = &init_net.ipv6.sysctl.flush_delay,
.maxlen = sizeof(int),
.mode = 0200,
.proc_handler = ipv6_sysctl_rtcache_flush
},
{
.procname = "gc_thresh",
.data = &ip6_dst_ops_template.gc_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "max_size",
.data = &init_net.ipv6.sysctl.ip6_rt_max_size,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "gc_min_interval",
.data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "gc_timeout",
.data = &init_net.ipv6.sysctl.ip6_rt_gc_timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "gc_interval",
.data = &init_net.ipv6.sysctl.ip6_rt_gc_interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "gc_elasticity",
.data = &init_net.ipv6.sysctl.ip6_rt_gc_elasticity,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "mtu_expires",
.data = &init_net.ipv6.sysctl.ip6_rt_mtu_expires,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "min_adv_mss",
.data = &init_net.ipv6.sysctl.ip6_rt_min_advmss,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "gc_min_interval_ms",
.data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_ms_jiffies,
},
{ }
};
struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
{
struct ctl_table *table;
table = kmemdup(ipv6_route_table_template,
sizeof(ipv6_route_table_template),
GFP_KERNEL);
if (table) {
table[0].data = &net->ipv6.sysctl.flush_delay;
table[0].extra1 = net;
table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh;
table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
table[0].procname = NULL;
}
return table;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
hideaki yoshifuji | hideaki yoshifuji | 134 | 58.52% | 1 | 11.11% |
daniel lezcano | daniel lezcano | 45 | 19.65% | 2 | 22.22% |
eric w. biederman | eric w. biederman | 19 | 8.30% | 1 | 11.11% |
alexey dobriyan | alexey dobriyan | 18 | 7.86% | 3 | 33.33% |
lucian adrian grijincu | lucian adrian grijincu | 9 | 3.93% | 1 | 11.11% |
benjamin thery | benjamin thery | 4 | 1.75% | 1 | 11.11% |
| Total | 229 | 100.00% | 9 | 100.00% |
#endif
static int __net_init ip6_route_net_init(struct net *net)
{
int ret = -ENOMEM;
memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template,
sizeof(net->ipv6.ip6_dst_ops));
if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
goto out_ip6_dst_ops;
net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
sizeof(*net->ipv6.ip6_null_entry),
GFP_KERNEL);
if (!net->ipv6.ip6_null_entry)
goto out_ip6_dst_entries;
net->ipv6.ip6_null_entry->dst.path =
(struct dst_entry *)net->ipv6.ip6_null_entry;
net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
ip6_template_metrics, true);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
sizeof(*net->ipv6.ip6_prohibit_entry),
GFP_KERNEL);
if (!net->ipv6.ip6_prohibit_entry)
goto out_ip6_null_entry;
net->ipv6.ip6_prohibit_entry->dst.path =
(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
ip6_template_metrics, true);
net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
sizeof(*net->ipv6.ip6_blk_hole_entry),
GFP_KERNEL);
if (!net->ipv6.ip6_blk_hole_entry)
goto out_ip6_prohibit_entry;
net->ipv6.ip6_blk_hole_entry->dst.path =
(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
ip6_template_metrics, true);
#endif
net->ipv6.sysctl.flush_delay = 0;
net->ipv6.sysctl.ip6_rt_max_size = 4096;
net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;
net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ;
net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ;
net->ipv6.sysctl.ip6_rt_gc_elasticity = 9;
net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
net->ipv6.ip6_rt_gc_expire = 30*HZ;
ret = 0;
out:
return ret;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
out_ip6_prohibit_entry:
kfree(net->ipv6.ip6_prohibit_entry);
out_ip6_null_entry:
kfree(net->ipv6.ip6_null_entry);
#endif
out_ip6_dst_entries:
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
out_ip6_dst_ops:
goto out;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel lezcano | daniel lezcano | 234 | 47.85% | 4 | 26.67% |
peter zijlstra | peter zijlstra | 123 | 25.15% | 2 | 13.33% |
david s. miller | david s. miller | 48 | 9.82% | 2 | 13.33% |
benjamin thery | benjamin thery | 44 | 9.00% | 2 | 13.33% |
eric dumazet | eric dumazet | 30 | 6.13% | 1 | 6.67% |
alexey dobriyan | alexey dobriyan | 8 | 1.64% | 2 | 13.33% |
denis v. lunev | denis v. lunev | 1 | 0.20% | 1 | 6.67% |
pavel emelianov | pavel emelianov | 1 | 0.20% | 1 | 6.67% |
| Total | 489 | 100.00% | 15 | 100.00% |
static void __net_exit ip6_route_net_exit(struct net *net)
{
kfree(net->ipv6.ip6_null_entry);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.ip6_prohibit_entry);
kfree(net->ipv6.ip6_blk_hole_entry);
#endif
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel lezcano | daniel lezcano | 43 | 79.63% | 1 | 33.33% |
xiaotian feng | xiaotian feng | 10 | 18.52% | 1 | 33.33% |
alexey dobriyan | alexey dobriyan | 1 | 1.85% | 1 | 33.33% |
| Total | 54 | 100.00% | 3 | 100.00% |
static int __net_init ip6_route_net_init_late(struct net *net)
{
#ifdef CONFIG_PROC_FS
proc_create("ipv6_route", 0, net->proc_net, &ipv6_route_proc_fops);
proc_create("rt6_stats", S_IRUGO, net->proc_net, &rt6_stats_seq_fops);
#endif
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 38 | 79.17% | 1 | 50.00% |
gao feng | gao feng | 10 | 20.83% | 1 | 50.00% |
| Total | 48 | 100.00% | 2 | 100.00% |
static void __net_exit ip6_route_net_exit_late(struct net *net)
{
#ifdef CONFIG_PROC_FS
remove_proc_entry("ipv6_route", net->proc_net);
remove_proc_entry("rt6_stats", net->proc_net);
#endif
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
thomas graf | thomas graf | 25 | 71.43% | 1 | 50.00% |
gao feng | gao feng | 10 | 28.57% | 1 | 50.00% |
| Total | 35 | 100.00% | 2 | 100.00% |
static struct pernet_operations ip6_route_net_ops = {
.init = ip6_route_net_init,
.exit = ip6_route_net_exit,
};
static int __net_init ipv6_inetpeer_init(struct net *net)
{
struct inet_peer_base *bp = kmalloc(sizeof(*bp), GFP_KERNEL);
if (!bp)
return -ENOMEM;
inet_peer_base_init(bp);
net->ipv6.peers = bp;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 53 | 100.00% | 1 | 100.00% |
| Total | 53 | 100.00% | 1 | 100.00% |
static void __net_exit ipv6_inetpeer_exit(struct net *net)
{
struct inet_peer_base *bp = net->ipv6.peers;
net->ipv6.peers = NULL;
inetpeer_invalidate_tree(bp);
kfree(bp);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david s. miller | david s. miller | 41 | 100.00% | 2 | 100.00% |
| Total | 41 | 100.00% | 2 | 100.00% |
static struct pernet_operations ipv6_inetpeer_ops = {
.init = ipv6_inetpeer_init,
.exit = ipv6_inetpeer_exit,
};
static struct pernet_operations ip6_route_net_late_ops = {
.init = ip6_route_net_init_late,
.exit = ip6_route_net_exit_late,
};
static struct notifier_block ip6_route_dev_notifier = {
.notifier_call = ip6_route_dev_notify,
.priority = 0,
};
int __init ip6_route_init(void)
{
int ret;
int cpu;
ret = -ENOMEM;
ip6_dst_ops_template.kmem_cachep =
kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
SLAB_HWCACHE_ALIGN, NULL);
if (!ip6_dst_ops_template.kmem_cachep)
goto out;
ret = dst_entries_init(&ip6_dst_blackhole_ops);
if (ret)
goto out_kmem_cache;
ret = register_pernet_subsys(&ipv6_inetpeer_ops);
if (ret)
goto out_dst_entries;
ret = register_pernet_subsys(&ip6_route_net_ops);
if (ret)
goto out_register_inetpeer;
ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
/* Registering of the loopback is done before this portion of code,
* the loopback reference in rt6_info will not be taken, do it
* manually for init_net */
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
#endif
ret = fib6_init();
if (ret)
goto out_register_subsys;
ret = xfrm6_init();
if (ret)
goto out_fib6_init;
ret = fib6_rules_init();
if (ret)
goto xfrm6_init;
ret = register_pernet_subsys(&ip6_route_net_late_ops);
if (ret)
goto fib6_rules_init;
ret = -ENOBUFS;
if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
__rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
__rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
goto out_register_late_subsys;
ret = register_netdevice_notifier(&ip6_route_dev_notifier);
if (ret)
goto out_register_late_subsys;
for_each_possible_cpu(cpu) {
struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
INIT_LIST_HEAD(&ul->head);
spin_lock_init(&ul->lock);
}
out:
return ret;
out_register_late_subsys:
unregister_pernet_subsys(&ip6_route_net_late_ops);
fib6_rules_init:
fib6_rules_cleanup();
xfrm6_init:
xfrm6_fini();
out_fib6_init:
fib6_gc_cleanup();
out_register_subsys:
unregister_pernet_subsys(&ip6_route_net_ops);
out_register_inetpeer:
unregister_pernet_subsys(&ipv6_inetpeer_ops);
out_dst_entries:
dst_entries_destroy(&ip6_dst_blackhole_ops);
out_kmem_cache:
kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
goto out;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
daniel lezcano | daniel lezcano | 212 | 51.71% | 6 | 27.27% |
thomas graf | thomas graf | 59 | 14.39% | 3 | 13.64% |
martin kafai lau | martin kafai lau | 38 | 9.27% | 1 | 4.55% |
david s. miller | david s. miller | 29 | 7.07% | 3 | 13.64% |
pre-git | pre-git | 29 | 7.07% | 4 | 18.18% |
eric dumazet | eric dumazet | 23 | 5.61% | 1 | 4.55% |
arnaud ebalard | arnaud ebalard | 8 | 1.95% | 1 | 4.55% |
greg rose | greg rose | 6 | 1.46% | 1 | 4.55% |
benjamin thery | benjamin thery | 3 | 0.73% | 1 | 4.55% |
hideaki yoshifuji | hideaki yoshifuji | 3 | 0.73% | 1 | 4.55% |
| Total | 410 | 100.00% | 22 | 100.00% |
void ip6_route_cleanup(void)
{
unregister_netdevice_notifier(&ip6_route_dev_notifier);
unregister_pernet_subsys(&ip6_route_net_late_ops);
fib6_rules_cleanup();
xfrm6_fini();
fib6_gc_cleanup();
unregister_pernet_subsys(&ipv6_inetpeer_ops);
unregister_pernet_subsys(&ip6_route_net_ops);
dst_entries_destroy(&ip6_dst_blackhole_ops);
kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 13 | 24.53% | 4 | 28.57% |
daniel lezcano | daniel lezcano | 11 | 20.75% | 2 | 14.29% |
thomas graf | thomas graf | 6 | 11.32% | 1 | 7.14% |
david s. miller | david s. miller | 6 | 11.32% | 1 | 7.14% |
xiaotian feng | xiaotian feng | 6 | 11.32% | 1 | 7.14% |
daniel mcneil | daniel mcneil | 5 | 9.43% | 1 | 7.14% |
benjamin thery | benjamin thery | 2 | 3.77% | 1 | 7.14% |
hideaki yoshifuji | hideaki yoshifuji | 2 | 3.77% | 1 | 7.14% |
kazunori miyazawa | kazunori miyazawa | 1 | 1.89% | 1 | 7.14% |
eric w. biederman | eric w. biederman | 1 | 1.89% | 1 | 7.14% |
| Total | 53 | 100.00% | 14 | 100.00% |
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 3205 | 16.32% | 26 | 5.70% |
david s. miller | david s. miller | 2354 | 11.99% | 50 | 10.96% |
hideaki yoshifuji | hideaki yoshifuji | 2312 | 11.77% | 84 | 18.42% |
martin kafai lau | martin kafai lau | 2293 | 11.67% | 23 | 5.04% |
thomas graf | thomas graf | 1806 | 9.20% | 18 | 3.95% |
daniel lezcano | daniel lezcano | 1269 | 6.46% | 21 | 4.61% |
roopa prabhu | roopa prabhu | 1091 | 5.55% | 5 | 1.10% |
duan jiong | duan jiong | 559 | 2.85% | 4 | 0.88% |
nicolas dichtel | nicolas dichtel | 487 | 2.48% | 9 | 1.97% |
daniel walter | daniel walter | 393 | 2.00% | 1 | 0.22% |
david ahern | david ahern | 364 | 1.85% | 7 | 1.54% |
hannes frederic sowa | hannes frederic sowa | 274 | 1.40% | 7 | 1.54% |
florian westphal | florian westphal | 269 | 1.37% | 6 | 1.32% |
eric dumazet | eric dumazet | 217 | 1.10% | 14 | 3.07% |
shmulik ladkani | shmulik ladkani | 143 | 0.73% | 2 | 0.44% |
steffen klassert | steffen klassert | 143 | 0.73% | 5 | 1.10% |
benjamin thery | benjamin thery | 136 | 0.69% | 6 | 1.32% |
gao feng | gao feng | 127 | 0.65% | 5 | 1.10% |
peter zijlstra | peter zijlstra | 123 | 0.63% | 2 | 0.44% |
daniel borkmann | daniel borkmann | 114 | 0.58% | 4 | 0.88% |
jiri benc | jiri benc | 110 | 0.56% | 7 | 1.54% |
alexey kuznetsov | alexey kuznetsov | 101 | 0.51% | 3 | 0.66% |
alexey dobriyan | alexey dobriyan | 93 | 0.47% | 5 | 1.10% |
lubomir rintel | lubomir rintel | 82 | 0.42% | 1 | 0.22% |
denis v. lunev | denis v. lunev | 80 | 0.41% | 7 | 1.54% |
eric w. biederman | eric w. biederman | 77 | 0.39% | 9 | 1.97% |
andy gospodarek | andy gospodarek | 75 | 0.38% | 2 | 0.44% |
kamala r | kamala r | 73 | 0.37% | 1 | 0.22% |
patrick mchardy | patrick mchardy | 71 | 0.36% | 7 | 1.54% |
randy dunlap | randy dunlap | 68 | 0.35% | 4 | 0.88% |
lucien xin | lucien xin | 63 | 0.32% | 1 | 0.22% |
shirley ma | shirley ma | 61 | 0.31% | 3 | 0.66% |
matti vaittinen | matti vaittinen | 60 | 0.31% | 1 | 0.22% |
krishna kumar | krishna kumar | 60 | 0.31% | 2 | 0.44% |
maciej zenczykowski | maciej zenczykowski | 55 | 0.28% | 1 | 0.22% |
pavel emelianov | pavel emelianov | 48 | 0.24% | 7 | 1.54% |
al viro | al viro | 47 | 0.24% | 3 | 0.66% |
lorenzo colitti | lorenzo colitti | 47 | 0.24% | 3 | 0.66% |
tom herbert | tom herbert | 47 | 0.24% | 3 | 0.66% |
james morris | james morris | 42 | 0.21% | 3 | 0.66% |
zheng yan | zheng yan | 39 | 0.20% | 1 | 0.22% |
lucian adrian grijincu | lucian adrian grijincu | 33 | 0.17% | 1 | 0.22% |
herbert xu | herbert xu | 33 | 0.17% | 6 | 1.32% |
ville nuorvala | ville nuorvala | 31 | 0.16% | 2 | 0.44% |
mathew richardson | mathew richardson | 30 | 0.15% | 1 | 0.22% |
tom tucker | tom tucker | 29 | 0.15% | 1 | 0.22% |
brian haley | brian haley | 28 | 0.14% | 4 | 0.88% |
julian anastasov | julian anastasov | 27 | 0.14% | 2 | 0.44% |
paolo abeni | paolo abeni | 21 | 0.11% | 3 | 0.66% |
lv liangying | lv liangying | 20 | 0.10% | 1 | 0.22% |
jamal hadi salim | jamal hadi salim | 20 | 0.10% | 2 | 0.44% |
roland dreier | roland dreier | 17 | 0.09% | 1 | 0.22% |
xiaotian feng | xiaotian feng | 16 | 0.08% | 1 | 0.22% |
stephen hemminger | stephen hemminger | 16 | 0.08% | 2 | 0.44% |
jean-mickael guerin | jean-mickael guerin | 15 | 0.08% | 1 | 0.22% |
nikola forro | nikola forro | 14 | 0.07% | 1 | 0.22% |
michal kubecek | michal kubecek | 13 | 0.07% | 3 | 0.66% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 13 | 0.07% | 4 | 0.88% |
linus torvalds | linus torvalds | 13 | 0.07% | 2 | 0.44% |
denis ovsienko | denis ovsienko | 13 | 0.07% | 1 | 0.22% |
joe perches | joe perches | 12 | 0.06% | 3 | 0.66% |
kazunori miyazawa | kazunori miyazawa | 10 | 0.05% | 2 | 0.44% |
li rongqing | li rongqing | 10 | 0.05% | 4 | 0.88% |
sabrina dubroca | sabrina dubroca | 10 | 0.05% | 1 | 0.22% |
paul marks | paul marks | 10 | 0.05% | 1 | 0.22% |
noriaki takamiya | noriaki takamiya | 8 | 0.04% | 1 | 0.22% |
arnaud ebalard | arnaud ebalard | 8 | 0.04% | 1 | 0.22% |
simon horman | simon horman | 6 | 0.03% | 1 | 0.22% |
markus stenberg | markus stenberg | 6 | 0.03% | 1 | 0.22% |
dave craig | dave craig | 6 | 0.03% | 1 | 0.22% |
greg rose | greg rose | 6 | 0.03% | 1 | 0.22% |
li wei | li wei | 5 | 0.03% | 1 | 0.22% |
daniel mcneil | daniel mcneil | 5 | 0.03% | 1 | 0.22% |
jiri pirko | jiri pirko | 5 | 0.03% | 1 | 0.22% |
david mccullough | david mccullough | 5 | 0.03% | 1 | 0.22% |
americo wang | americo wang | 5 | 0.03% | 1 | 0.22% |
jens rosenboom | jens rosenboom | 4 | 0.02% | 1 | 0.22% |
adrian bunk | adrian bunk | 4 | 0.02% | 3 | 0.66% |
held bernhard | held bernhard | 4 | 0.02% | 1 | 0.22% |
tejun heo | tejun heo | 3 | 0.02% | 1 | 0.22% |
changli gao | changli gao | 3 | 0.02% | 1 | 0.22% |
paul gortmaker | paul gortmaker | 3 | 0.02% | 1 | 0.22% |
matthias schiffer | matthias schiffer | 3 | 0.02% | 1 | 0.22% |
johannes berg | johannes berg | 3 | 0.02% | 1 | 0.22% |
stephen rothwell | stephen rothwell | 2 | 0.01% | 1 | 0.22% |
min zhang | min zhang | 2 | 0.01% | 1 | 0.22% |
jiri olsa | jiri olsa | 2 | 0.01% | 1 | 0.22% |
simon arlott | simon arlott | 2 | 0.01% | 1 | 0.22% |
dave jones | dave jones | 2 | 0.01% | 2 | 0.44% |
rami rosen | rami rosen | 2 | 0.01% | 1 | 0.22% |
ian morris | ian morris | 1 | 0.01% | 1 | 0.22% |
jim paris | jim paris | 1 | 0.01% | 1 | 0.22% |
arjan van de ven | arjan van de ven | 1 | 0.01% | 1 | 0.22% |
pablo neira ayuso | pablo neira ayuso | 1 | 0.01% | 1 | 0.22% |
michael busch | michael busch | 1 | 0.01% | 1 | 0.22% |
| Total | 19641 | 100.00% | 456 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.