Skip to content

Commit

Permalink
rxrpc: Add a tracepoint to log ICMP/ICMP6 and error messages
Browse files Browse the repository at this point in the history
Add a tracepoint to log received ICMP/ICMP6 events and other error
messages.

Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
David Howells committed May 10, 2018
1 parent 93864fc commit 494337c
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 23 deletions.
30 changes: 30 additions & 0 deletions include/trace/events/rxrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define _TRACE_RXRPC_H

#include <linux/tracepoint.h>
#include <linux/errqueue.h>

/*
* Define enums for tracing information.
Expand Down Expand Up @@ -1374,6 +1375,35 @@ TRACE_EVENT(rxrpc_resend,
__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 */

/* This part must be outside protection */
Expand Down
46 changes: 23 additions & 23 deletions net/rxrpc/peer_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,65 +28,65 @@ static void rxrpc_store_error(struct rxrpc_peer *, struct sock_exterr_skb *);
* Find the peer associated with an ICMP packet.
*/
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 sockaddr_rxrpc srx;

_enter("");

memset(&srx, 0, sizeof(srx));
srx.transport_type = local->srx.transport_type;
srx.transport_len = local->srx.transport_len;
srx.transport.family = local->srx.transport.family;
memset(srx, 0, sizeof(*srx));
srx->transport_type = local->srx.transport_type;
srx->transport_len = local->srx.transport_len;
srx->transport.family = local->srx.transport.family;

/* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice
* versa?
*/
switch (srx.transport.family) {
switch (srx->transport.family) {
case AF_INET:
srx.transport.sin.sin_port = serr->port;
srx->transport.sin.sin_port = serr->port;
switch (serr->ee.ee_origin) {
case SO_EE_ORIGIN_ICMP:
_net("Rx ICMP");
memcpy(&srx.transport.sin.sin_addr,
memcpy(&srx->transport.sin.sin_addr,
skb_network_header(skb) + serr->addr_offset,
sizeof(struct in_addr));
break;
case SO_EE_ORIGIN_ICMP6:
_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,
sizeof(struct in_addr));
break;
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));
break;
}
break;

#ifdef CONFIG_AF_RXRPC_IPV6
case AF_INET6:
srx.transport.sin6.sin6_port = serr->port;
srx->transport.sin6.sin6_port = serr->port;
switch (serr->ee.ee_origin) {
case SO_EE_ORIGIN_ICMP6:
_net("Rx ICMP6");
memcpy(&srx.transport.sin6.sin6_addr,
memcpy(&srx->transport.sin6.sin6_addr,
skb_network_header(skb) + serr->addr_offset,
sizeof(struct in6_addr));
break;
case SO_EE_ORIGIN_ICMP:
_net("Rx ICMP on v6 sock");
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[2] = htonl(0xffff);
memcpy(srx.transport.sin6.sin6_addr.s6_addr + 12,
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[2] = htonl(0xffff);
memcpy(srx->transport.sin6.sin6_addr.s6_addr + 12,
skb_network_header(skb) + serr->addr_offset,
sizeof(struct in_addr));
break;
default:
memcpy(&srx.transport.sin6.sin6_addr,
memcpy(&srx->transport.sin6.sin6_addr,
&ipv6_hdr(skb)->saddr,
sizeof(struct in6_addr));
break;
Expand All @@ -98,7 +98,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
BUG();
}

return rxrpc_lookup_peer_rcu(local, &srx);
return rxrpc_lookup_peer_rcu(local, srx);
}

/*
Expand Down Expand Up @@ -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)
{
struct sock_exterr_skb *serr;
struct sockaddr_rxrpc srx;
struct rxrpc_local *local = sk->sk_user_data;
struct rxrpc_peer *peer;
struct sk_buff *skb;
Expand All @@ -166,7 +167,7 @@ void rxrpc_error_report(struct sock *sk)
}

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))
peer = NULL;
if (!peer) {
Expand All @@ -176,6 +177,8 @@ void rxrpc_error_report(struct sock *sk)
return;
}

trace_rxrpc_rx_icmp(peer, &serr->ee, &srx);

if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP &&
serr->ee.ee_type == ICMP_DEST_UNREACH &&
serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
Expand Down Expand Up @@ -209,9 +212,6 @@ static void rxrpc_store_error(struct rxrpc_peer *peer,

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;

switch (ee->ee_origin) {
Expand Down

0 comments on commit 494337c

Please sign in to comment.