Commit 494337c9 authored by David Howells's avatar David Howells

rxrpc: Add a tracepoint to log ICMP/ICMP6 and error messages

Add a tracepoint to log received ICMP/ICMP6 events and other error
messages.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 93864fc3
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define _TRACE_RXRPC_H #define _TRACE_RXRPC_H
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/errqueue.h>
/* /*
* Define enums for tracing information. * Define enums for tracing information.
...@@ -1374,6 +1375,35 @@ TRACE_EVENT(rxrpc_resend, ...@@ -1374,6 +1375,35 @@ TRACE_EVENT(rxrpc_resend,
__entry->anno) __entry->anno)
); );
TRACE_EVENT(rxrpc_rx_icmp,
TP_PROTO(struct rxrpc_peer *peer, struct sock_extended_err *ee,
struct sockaddr_rxrpc *srx),
TP_ARGS(peer, ee, srx),
TP_STRUCT__entry(
__field(unsigned int, peer )
__field_struct(struct sock_extended_err, ee )
__field_struct(struct sockaddr_rxrpc, srx )
),
TP_fast_assign(
__entry->peer = peer->debug_id;
memcpy(&__entry->ee, ee, sizeof(__entry->ee));
memcpy(&__entry->srx, srx, sizeof(__entry->srx));
),
TP_printk("P=%08x o=%u t=%u c=%u i=%u d=%u e=%d %pISp",
__entry->peer,
__entry->ee.ee_origin,
__entry->ee.ee_type,
__entry->ee.ee_code,
__entry->ee.ee_info,
__entry->ee.ee_data,
__entry->ee.ee_errno,
&__entry->srx.transport)
);
#endif /* _TRACE_RXRPC_H */ #endif /* _TRACE_RXRPC_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
...@@ -28,39 +28,39 @@ static void rxrpc_store_error(struct rxrpc_peer *, struct sock_exterr_skb *); ...@@ -28,39 +28,39 @@ static void rxrpc_store_error(struct rxrpc_peer *, struct sock_exterr_skb *);
* Find the peer associated with an ICMP packet. * Find the peer associated with an ICMP packet.
*/ */
static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
const struct sk_buff *skb) const struct sk_buff *skb,
struct sockaddr_rxrpc *srx)
{ {
struct sock_exterr_skb *serr = SKB_EXT_ERR(skb); struct sock_exterr_skb *serr = SKB_EXT_ERR(skb);
struct sockaddr_rxrpc srx;
_enter(""); _enter("");
memset(&srx, 0, sizeof(srx)); memset(srx, 0, sizeof(*srx));
srx.transport_type = local->srx.transport_type; srx->transport_type = local->srx.transport_type;
srx.transport_len = local->srx.transport_len; srx->transport_len = local->srx.transport_len;
srx.transport.family = local->srx.transport.family; srx->transport.family = local->srx.transport.family;
/* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice /* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice
* versa? * versa?
*/ */
switch (srx.transport.family) { switch (srx->transport.family) {
case AF_INET: case AF_INET:
srx.transport.sin.sin_port = serr->port; srx->transport.sin.sin_port = serr->port;
switch (serr->ee.ee_origin) { switch (serr->ee.ee_origin) {
case SO_EE_ORIGIN_ICMP: case SO_EE_ORIGIN_ICMP:
_net("Rx ICMP"); _net("Rx ICMP");
memcpy(&srx.transport.sin.sin_addr, memcpy(&srx->transport.sin.sin_addr,
skb_network_header(skb) + serr->addr_offset, skb_network_header(skb) + serr->addr_offset,
sizeof(struct in_addr)); sizeof(struct in_addr));
break; break;
case SO_EE_ORIGIN_ICMP6: case SO_EE_ORIGIN_ICMP6:
_net("Rx ICMP6 on v4 sock"); _net("Rx ICMP6 on v4 sock");
memcpy(&srx.transport.sin.sin_addr, memcpy(&srx->transport.sin.sin_addr,
skb_network_header(skb) + serr->addr_offset + 12, skb_network_header(skb) + serr->addr_offset + 12,
sizeof(struct in_addr)); sizeof(struct in_addr));
break; break;
default: default:
memcpy(&srx.transport.sin.sin_addr, &ip_hdr(skb)->saddr, memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr,
sizeof(struct in_addr)); sizeof(struct in_addr));
break; break;
} }
...@@ -68,25 +68,25 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, ...@@ -68,25 +68,25 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
#ifdef CONFIG_AF_RXRPC_IPV6 #ifdef CONFIG_AF_RXRPC_IPV6
case AF_INET6: case AF_INET6:
srx.transport.sin6.sin6_port = serr->port; srx->transport.sin6.sin6_port = serr->port;
switch (serr->ee.ee_origin) { switch (serr->ee.ee_origin) {
case SO_EE_ORIGIN_ICMP6: case SO_EE_ORIGIN_ICMP6:
_net("Rx ICMP6"); _net("Rx ICMP6");
memcpy(&srx.transport.sin6.sin6_addr, memcpy(&srx->transport.sin6.sin6_addr,
skb_network_header(skb) + serr->addr_offset, skb_network_header(skb) + serr->addr_offset,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
break; break;
case SO_EE_ORIGIN_ICMP: case SO_EE_ORIGIN_ICMP:
_net("Rx ICMP on v6 sock"); _net("Rx ICMP on v6 sock");
srx.transport.sin6.sin6_addr.s6_addr32[0] = 0; srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
srx.transport.sin6.sin6_addr.s6_addr32[1] = 0; srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
srx.transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
memcpy(srx.transport.sin6.sin6_addr.s6_addr + 12, memcpy(srx->transport.sin6.sin6_addr.s6_addr + 12,
skb_network_header(skb) + serr->addr_offset, skb_network_header(skb) + serr->addr_offset,
sizeof(struct in_addr)); sizeof(struct in_addr));
break; break;
default: default:
memcpy(&srx.transport.sin6.sin6_addr, memcpy(&srx->transport.sin6.sin6_addr,
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->saddr,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
break; break;
...@@ -98,7 +98,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, ...@@ -98,7 +98,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
BUG(); BUG();
} }
return rxrpc_lookup_peer_rcu(local, &srx); return rxrpc_lookup_peer_rcu(local, srx);
} }
/* /*
...@@ -146,6 +146,7 @@ static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, struct sock_exterr_skb *se ...@@ -146,6 +146,7 @@ static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, struct sock_exterr_skb *se
void rxrpc_error_report(struct sock *sk) void rxrpc_error_report(struct sock *sk)
{ {
struct sock_exterr_skb *serr; struct sock_exterr_skb *serr;
struct sockaddr_rxrpc srx;
struct rxrpc_local *local = sk->sk_user_data; struct rxrpc_local *local = sk->sk_user_data;
struct rxrpc_peer *peer; struct rxrpc_peer *peer;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -166,7 +167,7 @@ void rxrpc_error_report(struct sock *sk) ...@@ -166,7 +167,7 @@ void rxrpc_error_report(struct sock *sk)
} }
rcu_read_lock(); rcu_read_lock();
peer = rxrpc_lookup_peer_icmp_rcu(local, skb); peer = rxrpc_lookup_peer_icmp_rcu(local, skb, &srx);
if (peer && !rxrpc_get_peer_maybe(peer)) if (peer && !rxrpc_get_peer_maybe(peer))
peer = NULL; peer = NULL;
if (!peer) { if (!peer) {
...@@ -176,6 +177,8 @@ void rxrpc_error_report(struct sock *sk) ...@@ -176,6 +177,8 @@ void rxrpc_error_report(struct sock *sk)
return; return;
} }
trace_rxrpc_rx_icmp(peer, &serr->ee, &srx);
if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP && if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP &&
serr->ee.ee_type == ICMP_DEST_UNREACH && serr->ee.ee_type == ICMP_DEST_UNREACH &&
serr->ee.ee_code == ICMP_FRAG_NEEDED)) { serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
...@@ -209,9 +212,6 @@ static void rxrpc_store_error(struct rxrpc_peer *peer, ...@@ -209,9 +212,6 @@ static void rxrpc_store_error(struct rxrpc_peer *peer,
ee = &serr->ee; ee = &serr->ee;
_net("Rx Error o=%d t=%d c=%d e=%d",
ee->ee_origin, ee->ee_type, ee->ee_code, ee->ee_errno);
err = ee->ee_errno; err = ee->ee_errno;
switch (ee->ee_origin) { switch (ee->ee_origin) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment