new file mode 100644
@@ -0,0 +1,237 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM fib6
+
+#if !defined(_TRACE_FIB6_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_FIB6_H
+
+#include <linux/in6.h>
+#include <net/flow.h>
+#include <net/ip6_fib.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(fib6_table_lookup,
+
+ TP_PROTO(const struct net *net, const struct rt6_info *rt,
+ u32 tb_id, const struct flowi6 *flp),
+
+ TP_ARGS(net, rt, tb_id, flp),
+
+ TP_STRUCT__entry(
+ __field( u32, tb_id )
+
+ __field( int, oif )
+ __field( int, iif )
+ __field( __u8, tos )
+ __field( __u8, scope )
+ __field( __u8, flags )
+ __array( __u8, src, 16 )
+ __array( __u8, dst, 16 )
+
+ __dynamic_array( char, name, IFNAMSIZ )
+ __array( __u8, gw, 16 )
+ ),
+
+ TP_fast_assign(
+ struct in6_addr *in6;
+
+ __entry->tb_id = tb_id;
+ __entry->oif = flp->flowi6_oif;
+ __entry->iif = flp->flowi6_iif;
+ __entry->tos = flp->flowi6_tos;
+ __entry->scope = flp->flowi6_scope;
+ __entry->flags = flp->flowi6_flags;
+
+ in6 = (struct in6_addr *)__entry->src;
+ *in6 = flp->saddr;
+
+ in6 = (struct in6_addr *)__entry->dst;
+ *in6 = flp->daddr;
+
+ if (rt->rt6i_idev) {
+ __assign_str(name, rt->rt6i_idev->dev->name);
+ } else {
+ __assign_str(name, "");
+ }
+ if (rt == net->ipv6.ip6_null_entry) {
+ struct in6_addr in6_zero = {};
+
+ in6 = (struct in6_addr *)__entry->gw;
+ *in6 = in6_zero;
+
+ } else if (rt) {
+ in6 = (struct in6_addr *)__entry->gw;
+ *in6 = rt->rt6i_gateway;
+ }
+ ),
+
+ TP_printk("table %3u oif %d iif %d src %pI6c dst %pI6c tos %d scope %d flags %x ==> dev %s gw %pI6c",
+ __entry->tb_id, __entry->oif, __entry->iif,
+ __entry->src, __entry->dst, __entry->tos, __entry->scope,
+ __entry->flags, __get_str(name), __entry->gw)
+);
+
+TRACE_EVENT(ip6_route_del,
+
+ TP_PROTO(const struct fib6_config *cfg),
+
+ TP_ARGS(cfg),
+
+ TP_STRUCT__entry(
+ __field( u32, tb_id )
+ __field( int, iif )
+ __field( int, src_len )
+ __field( int, dst_len )
+ __array( __u8, src, 16 )
+ __array( __u8, dst, 16 )
+ __array( __u8, prefsrc, 16 )
+ __array( __u8, gw, 16 )
+ ),
+
+ TP_fast_assign(
+ struct in6_addr *in6;
+
+ __entry->tb_id = cfg->fc_table;
+ __entry->iif = cfg->fc_ifindex;
+
+ in6 = (struct in6_addr *)__entry->src;
+ *in6 = cfg->fc_src;
+ __entry->src_len = cfg->fc_src_len;
+
+ in6 = (struct in6_addr *)__entry->dst;
+ *in6 = cfg->fc_dst;
+ __entry->dst_len = cfg->fc_dst_len;
+
+ in6 = (struct in6_addr *)__entry->prefsrc;
+ *in6 = cfg->fc_prefsrc;
+
+ in6 = (struct in6_addr *)__entry->gw;
+ *in6 = cfg->fc_gateway;
+ ),
+
+ TP_printk("table %u ifindex %d src %pI6c/%d dst %pI6c/%d prefsrc %pI6c gw %pI6c",
+ __entry->tb_id, __entry->iif, __entry->src, __entry->src_len,
+ __entry->dst, __entry->dst_len, __entry->prefsrc, __entry->gw)
+);
+
+TRACE_EVENT(ipv6_alloc_dst,
+
+ TP_PROTO(const struct rt6_info *rt),
+
+ TP_ARGS(rt),
+
+ TP_STRUCT__entry(
+ __field( const void *, dst )
+ __field( void *, input )
+ __field( void *, output )
+ __field( __u32, flags )
+ __field( __u32, tb_id )
+ __dynamic_array( char, name, IFNAMSIZ )
+ __array( __u8, gw, 16 )
+ __array( __u8, addr, 16 )
+ __field( __u32, plen )
+ ),
+
+ TP_fast_assign(
+ struct in6_addr *in6;
+
+ __entry->dst = &rt->dst;
+ __entry->input = rt->dst.input;
+ __entry->output = rt->dst.output;
+ __entry->flags = rt->rt6i_flags;
+ if (rt->rt6i_table) {
+ __entry->tb_id = rt->rt6i_table->tb6_id;
+ } else {
+ __entry->tb_id = 0;
+ }
+ in6 = (struct in6_addr *)__entry->gw;
+ *in6 = rt->rt6i_gateway;
+
+ in6 = (struct in6_addr *)__entry->addr;
+ *in6 = rt->rt6i_dst.addr;
+ __entry->plen = rt->rt6i_dst.plen;
+
+ if (rt->rt6i_idev) {
+ __assign_str(name, rt->rt6i_idev->dev->name);
+ } else {
+ __assign_str(name, "<null>");
+ }
+ ),
+
+ TP_printk("table %3u flags %x dev %s gw %pI6c addr %pI6c/%d dst %p input %p output %p",
+ __entry->tb_id, __entry->flags, __get_str(name),
+ __entry->gw, __entry->addr, __entry->plen,
+ __entry->dst, __entry->input, __entry->output)
+);
+
+TRACE_EVENT(ipv6_alloc_pcpu_dst,
+
+ TP_PROTO(const struct rt6_info *rt, const struct rt6_info *rt_orig),
+
+ TP_ARGS(rt, rt_orig),
+
+ TP_STRUCT__entry(
+ __field( const void *, dst_orig )
+ __field( const void *, dst )
+ ),
+
+ TP_fast_assign(
+ __entry->dst_orig = &rt_orig->dst;
+ __entry->dst = &rt->dst;
+ ),
+
+ TP_printk("dst %p dst orig %p",
+ __entry->dst, __entry->dst_orig)
+);
+
+TRACE_EVENT(fib6_ifdown,
+
+ TP_PROTO(const struct net_device *dev, const struct rt6_info *rt),
+
+ TP_ARGS(dev, rt),
+
+ TP_STRUCT__entry(
+ __field( const void *, dst )
+ __field( __u32, flags )
+ __field( __u32, tb_id )
+ __dynamic_array( char, dev, IFNAMSIZ )
+ __dynamic_array( char, rt_dev, IFNAMSIZ )
+ __array( __u8, gw, 16 )
+ __array( __u8, addr, 16 )
+ __field( __u32, plen )
+ ),
+
+ TP_fast_assign(
+ struct in6_addr *in6;
+
+ __entry->dst = &rt->dst;
+ __entry->flags = rt->rt6i_flags;
+ if (rt->rt6i_table) {
+ __entry->tb_id = rt->rt6i_table->tb6_id;
+ } else {
+ __entry->tb_id = 0;
+ }
+ in6 = (struct in6_addr *)__entry->gw;
+ *in6 = rt->rt6i_gateway;
+
+ in6 = (struct in6_addr *)__entry->addr;
+ *in6 = rt->rt6i_dst.addr;
+ __entry->plen = rt->rt6i_dst.plen;
+
+ __assign_str(dev, dev->name);
+ if (rt->rt6i_idev) {
+ __assign_str(rt_dev, rt->rt6i_idev->dev->name);
+ } else {
+ __assign_str(rt_dev, "<null>");
+ }
+ ),
+
+ TP_printk("dev %s table %3u flags %x rt_dev %s gw %pI6c addr %pI6c/%d dst %p",
+ __get_str(dev), __entry->tb_id, __entry->flags, __get_str(rt_dev),
+ __entry->gw, __entry->addr, __entry->plen, __entry->dst)
+
+);
+
+#endif /* _TRACE_FIB6_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
@@ -32,6 +32,13 @@
#include <trace/events/sock.h>
#include <trace/events/udp.h>
#include <trace/events/fib.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <trace/events/fib6.h>
+EXPORT_TRACEPOINT_SYMBOL_GPL(fib6_table_lookup);
+EXPORT_TRACEPOINT_SYMBOL_GPL(ipv6_alloc_pcpu_dst);
+EXPORT_TRACEPOINT_SYMBOL_GPL(ipv6_alloc_dst);
+EXPORT_TRACEPOINT_SYMBOL_GPL(ip6_route_del);
+#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
@@ -62,6 +62,7 @@
#include <net/lwtunnel.h>
#include <net/ip_tunnels.h>
#include <net/l3mdev.h>
+#include <trace/events/fib6.h>
#include <asm/uaccess.h>
@@ -857,6 +858,9 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
}
dst_use(&rt->dst, jiffies);
read_unlock_bh(&table->tb6_lock);
+
+ trace_fib6_table_lookup(net, rt, table->tb6_id, fl6);
+
return rt;
}
@@ -958,6 +962,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
#endif
}
+ trace_ipv6_alloc_dst(rt);
return rt;
}
@@ -973,6 +978,8 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
ip6_rt_copy_init(pcpu_rt, rt);
pcpu_rt->rt6i_protocol = rt->rt6i_protocol;
pcpu_rt->rt6i_flags |= RTF_PCPU;
+
+ trace_ipv6_alloc_pcpu_dst(pcpu_rt, rt);
return pcpu_rt;
}
@@ -1070,6 +1077,8 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
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))) {
@@ -1093,6 +1102,8 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
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 {
@@ -1117,6 +1128,7 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
dst_release(&rt->dst);
}
+ trace_fib6_table_lookup(net, pcpu_rt, table->tb6_id, fl6);
return pcpu_rt;
}
@@ -1460,6 +1472,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
read_unlock_bh(&table->tb6_lock);
+ trace_fib6_table_lookup(net, rt, table->tb6_id, fl6);
return rt;
};
@@ -1600,6 +1613,8 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
rt->rt6i_idev = idev;
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
+ trace_ipv6_alloc_dst(rt);
+
spin_lock_bh(&icmp6_dst_lock);
rt->dst.next = icmp6_dst_gc_list;
icmp6_dst_gc_list = &rt->dst;
@@ -1967,6 +1982,8 @@ int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret)
cfg->fc_nlinfo.nl_net = dev_net(dev);
+ trace_ipv6_alloc_dst(rt);
+
*rt_ret = rt;
return 0;
@@ -2046,6 +2063,8 @@ static int ip6_route_del(struct fib6_config *cfg)
struct rt6_info *rt;
int err = -ESRCH;
+ trace_ip6_route_del(cfg);
+
table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
if (!table)
return err;
@@ -2510,6 +2529,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
atomic_set(&rt->dst.__refcnt, 1);
+ trace_ipv6_alloc_dst(rt);
return rt;
}
@@ -2595,8 +2615,10 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg)
const struct net_device *dev = adn->dev;
if ((rt->dst.dev == dev || !dev) &&
- rt != adn->net->ipv6.ip6_null_entry)
+ rt != adn->net->ipv6.ip6_null_entry) {
+ trace_fib6_ifdown(dev, rt);
return -1;
+ }
return 0;
}