/* * net/l3mdev/l3mdev.c - L3 master device implementation * Copyright (c) 2015 Cumulus Networks * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com> * * 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. */ #include <linux/netdevice.h> #include <net/fib_rules.h> #include <net/l3mdev.h> /** * l3mdev_master_ifindex - get index of L3 master device * @dev: targeted interface */ int l3mdev_master_ifindex_rcu(const struct net_device *dev) { int ifindex = 0; if (!dev) return 0; if (netif_is_l3_master(dev)) { ifindex = dev->ifindex; } else if (netif_is_l3_slave(dev)) { struct net_device *master; struct net_device *_dev = (struct net_device *)dev; /* netdev_master_upper_dev_get_rcu calls * list_first_or_null_rcu to walk the upper dev list. * list_first_or_null_rcu does not handle a const arg. We aren't * making changes, just want the master device from that list so * typecast to remove the const */ master = netdev_master_upper_dev_get_rcu(_dev); if (master) ifindex = master->ifindex; } return ifindex; } EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu); /** * l3mdev_fib_table - get FIB table id associated with an L3 * master interface * @dev: targeted interface */ u32 l3mdev_fib_table_rcu(const struct net_device *dev) { u32 tb_id = 0; if (!dev) return 0; if (netif_is_l3_master(dev)) { if (dev->l3mdev_ops->l3mdev_fib_table) tb_id = dev->l3mdev_ops->l3mdev_fib_table(dev); } else if (netif_is_l3_slave(dev)) { /* Users of netdev_master_upper_dev_get_rcu need non-const, * but current inet_*type functions take a const */ struct net_device *_dev = (struct net_device *) dev; const struct net_device *master; master = netdev_master_upper_dev_get_rcu(_dev); if (master && master->l3mdev_ops->l3mdev_fib_table) tb_id = master->l3mdev_ops->l3mdev_fib_table(master); } return tb_id; } EXPORT_SYMBOL_GPL(l3mdev_fib_table_rcu); u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) { struct net_device *dev; u32 tb_id = 0; if (!ifindex) return 0; rcu_read_lock(); dev = dev_get_by_index_rcu(net, ifindex); if (dev) tb_id = l3mdev_fib_table_rcu(dev); rcu_read_unlock(); return tb_id; } EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index); /** * l3mdev_link_scope_lookup - IPv6 route lookup based on flow for link * local and multicast addresses * @net: network namespace for device index lookup * @fl6: IPv6 flow struct for lookup */ struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6) { struct dst_entry *dst = NULL; struct net_device *dev; if (fl6->flowi6_oif) { rcu_read_lock(); dev = dev_get_by_index_rcu(net, fl6->flowi6_oif); if (dev && netif_is_l3_slave(dev)) dev = netdev_master_upper_dev_get_rcu(dev); if (dev && netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_link_scope_lookup) dst = dev->l3mdev_ops->l3mdev_link_scope_lookup(dev, fl6); rcu_read_unlock(); } return dst; } EXPORT_SYMBOL_GPL(l3mdev_link_scope_lookup); /** * l3mdev_fib_rule_match - Determine if flowi references an * L3 master device * @net: network namespace for device index lookup * @fl: flow struct */ int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, struct fib_lookup_arg *arg) { struct net_device *dev; int rc = 0; rcu_read_lock(); dev = dev_get_by_index_rcu(net, fl->flowi_oif); if (dev && netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_fib_table) { arg->table = dev->l3mdev_ops->l3mdev_fib_table(dev); rc = 1; goto out; } dev = dev_get_by_index_rcu(net, fl->flowi_iif); if (dev && netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_fib_table) { arg->table = dev->l3mdev_ops->l3mdev_fib_table(dev); rc = 1; goto out; } out: rcu_read_unlock(); return rc; } void l3mdev_update_flow(struct net *net, struct flowi *fl) { struct net_device *dev; int ifindex; rcu_read_lock(); if (fl->flowi_oif) { dev = dev_get_by_index_rcu(net, fl->flowi_oif); if (dev) { ifindex = l3mdev_master_ifindex_rcu(dev); if (ifindex) { fl->flowi_oif = ifindex; fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF; goto out; } } } if (fl->flowi_iif) { dev = dev_get_by_index_rcu(net, fl->flowi_iif); if (dev) { ifindex = l3mdev_master_ifindex_rcu(dev); if (ifindex) { fl->flowi_iif = ifindex; fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF; } } } out: rcu_read_unlock(); } EXPORT_SYMBOL_GPL(l3mdev_update_flow); /tr></table></form></div><table summary='commit info' class='commit-info'> <tr><th>author</th><td>Peter Zijlstra <peterz@infradead.org></td><td class='right'>2017-01-26 23:15:08 +0100</td></tr> <tr><th>committer</th><td>Ingo Molnar <mingo@kernel.org></td><td class='right'>2017-01-30 11:41:26 +0100</td></tr> <tr><th>commit</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/commit/tools/build/feature/test-backtrace.c?id=0b3589be9b98994ce3d5aeca52445d1f5627c4ba'>0b3589be9b98994ce3d5aeca52445d1f5627c4ba</a> (<a href='/cgit.cgi/linux/net-next.git/patch/tools/build/feature/test-backtrace.c?id=0b3589be9b98994ce3d5aeca52445d1f5627c4ba'>patch</a>)</td></tr> <tr><th>tree</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/tree/?id=0b3589be9b98994ce3d5aeca52445d1f5627c4ba'>85d0d9b3ac902af2c938b19a566884caf8d00323</a> /<a href='/cgit.cgi/linux/net-next.git/tree/tools/build/feature/test-backtrace.c?id=0b3589be9b98994ce3d5aeca52445d1f5627c4ba'>tools/build/feature/test-backtrace.c</a></td></tr> <tr><th>parent</th><td colspan='2' class='oid'><a href='/cgit.cgi/linux/net-next.git/commit/tools/build/feature/test-backtrace.c?id=a76a82a3e38c8d3fb6499e3dfaeb0949241ab588'>a76a82a3e38c8d3fb6499e3dfaeb0949241ab588</a> (<a href='/cgit.cgi/linux/net-next.git/diff/tools/build/feature/test-backtrace.c?id=0b3589be9b98994ce3d5aeca52445d1f5627c4ba&id2=a76a82a3e38c8d3fb6499e3dfaeb0949241ab588'>diff</a>)</td></tr></table> <div class='commit-subject'>perf/core: Fix PERF_RECORD_MMAP2 prot/flags for anonymous memory</div><div class='commit-msg'>Andres reported that MMAP2 records for anonymous memory always have their protection field 0. Turns out, someone daft put the prot/flags generation code in the file branch, leaving them unset for anonymous memory. Reported-by: Andres Freund <andres@anarazel.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Don Zickus <dzickus@redhat.com Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@gmail.com> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: acme@kernel.org Cc: anton@ozlabs.org Cc: namhyung@kernel.org Cc: stable@vger.kernel.org # v3.16+ Fixes: f972eb63b100 ("perf: Pass protection and flags bits through mmap2 interface") Link: http://lkml.kernel.org/r/20170126221508.GF6536@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org> </div><div class='diffstat-header'><a href='/cgit.cgi/linux/net-next.git/diff/?id=0b3589be9b98994ce3d5aeca52445d1f5627c4ba'>Diffstat</a> (limited to 'tools/build/feature/test-backtrace.c')</div><table summary='diffstat' class='diffstat'>