)
 );
 
+TRACE_EVENT(bpf_xdp_link_attach_failed,
+
+       TP_PROTO(const char *msg),
+
+       TP_ARGS(msg),
+
+       TP_STRUCT__entry(
+               __string(msg, msg)
+       ),
+
+       TP_fast_assign(
+               __assign_str(msg, msg);
+       ),
+
+       TP_printk("errmsg=%s", __get_str(msg))
+);
+
 #endif /* _TRACE_XDP_H */
 
 #include <trace/define_trace.h>
 
 #include <trace/events/net.h>
 #include <trace/events/skb.h>
 #include <trace/events/qdisc.h>
+#include <trace/events/xdp.h>
 #include <linux/inetdevice.h>
 #include <linux/cpu_rmap.h>
 #include <linux/static_key.h>
 {
        struct net *net = current->nsproxy->net_ns;
        struct bpf_link_primer link_primer;
+       struct netlink_ext_ack extack = {};
        struct bpf_xdp_link *link;
        struct net_device *dev;
        int err, fd;
                goto unlock;
        }
 
-       err = dev_xdp_attach_link(dev, NULL, link);
+       err = dev_xdp_attach_link(dev, &extack, link);
        rtnl_unlock();
 
        if (err) {
                link->dev = NULL;
                bpf_link_cleanup(&link_primer);
+               trace_bpf_xdp_link_attach_failed(extack._msg);
                goto out_put_dev;
        }