RxRPC fixes
-----BEGIN PGP SIGNATURE----- iQIVAwUAWvTI3fu3V2unywtrAQJhsRAAoO801foYD0QvcePS7kygwY3xgEnhWfI2 gTKX7yzYHsoZT+0wesMZ2wjFplTt5pH351H/ytcRiXZ+VIQu+6rWaNTwuUvAISYy 6hsYST3Exl3P/ZW2GZNZIHyht3Qmpj6O8DYbJvJiJF5MVApb2zQKsuOa+ZBywgD2 eeahiHZ4wOMgY4YLQkBl1WKEh78AaWkkBljLyvFNC6v1GkvBGJ2AAZZNt+Ye65i7 AvCMqXD1hmqqfWBK12dz9HIPJCPRv2uoDGehS1EsfCdqQmE0Cw9k54tVPbAOBKzb 1ys2dgRc87/UYjXX4e+OS7u+pmoxE3MRiWxT+hFfHFa0PSYu/R2aM2Jbh2VxtdfS PeeK8BKMqB6W2MFTU1ZUG0viw7LVTxN0oiLQ+eEbhs+ew+czbZSIsqcO6BUTIoNZ M1KqR17PHYjjKGtUp12/8iAO2x6ejNhmWRZvxlyp5TviF5Txub0a9/IfuV1t18ut N7i+L0jLsjUsPdQlBJUNuTb5TrMdMof18sISZtf4wSMa6llrrOl3CTxO7LSnJjw/ shhs3MBqt3geSp0b0OzT8imPjGZRxHF7hWfhn4SeRqsmPFyLVW+je64P1+De0iP9 o9IQjVFX6WJP9NdRygai9gcWw7CJpmFo8ODPzBBU6O64lHk0NKE2Ihs3i7wdM9h0 SFRxfOl+ma0= =jobL -----END PGP SIGNATURE----- Merge tag 'rxrpc-fixes-20180510' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs David Howells says: ==================== rxrpc: Fixes Here are three fixes for AF_RXRPC and two tracepoints that were useful for finding them: (1) Fix missing start of expect-Rx-by timeout on initial packet transmission so that calls will time out if the peer doesn't respond. (2) Fix error reception on AF_INET6 sockets by using the correct family of sockopts on the UDP transport socket. (3) Fix setting the minimum security level on kernel calls so that they can be encrypted. (4) Add a tracepoint to log ICMP/ICMP6 and other error reports from the transport socket. (5) Add a tracepoint to log UDP sendmsg failure so that we can find out if transmission failure occurred on the UDP socket. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
f01008916f
|
@ -15,6 +15,7 @@
|
|||
#define _TRACE_RXRPC_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/errqueue.h>
|
||||
|
||||
/*
|
||||
* Define enums for tracing information.
|
||||
|
@ -210,6 +211,20 @@ enum rxrpc_congest_change {
|
|||
rxrpc_cong_saw_nack,
|
||||
};
|
||||
|
||||
enum rxrpc_tx_fail_trace {
|
||||
rxrpc_tx_fail_call_abort,
|
||||
rxrpc_tx_fail_call_ack,
|
||||
rxrpc_tx_fail_call_data_frag,
|
||||
rxrpc_tx_fail_call_data_nofrag,
|
||||
rxrpc_tx_fail_call_final_resend,
|
||||
rxrpc_tx_fail_conn_abort,
|
||||
rxrpc_tx_fail_conn_challenge,
|
||||
rxrpc_tx_fail_conn_response,
|
||||
rxrpc_tx_fail_reject,
|
||||
rxrpc_tx_fail_version_keepalive,
|
||||
rxrpc_tx_fail_version_reply,
|
||||
};
|
||||
|
||||
#endif /* end __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY */
|
||||
|
||||
/*
|
||||
|
@ -437,6 +452,19 @@ enum rxrpc_congest_change {
|
|||
EM(RXRPC_CALL_LOCAL_ERROR, "LocalError") \
|
||||
E_(RXRPC_CALL_NETWORK_ERROR, "NetError")
|
||||
|
||||
#define rxrpc_tx_fail_traces \
|
||||
EM(rxrpc_tx_fail_call_abort, "CallAbort") \
|
||||
EM(rxrpc_tx_fail_call_ack, "CallAck") \
|
||||
EM(rxrpc_tx_fail_call_data_frag, "CallDataFrag") \
|
||||
EM(rxrpc_tx_fail_call_data_nofrag, "CallDataNofrag") \
|
||||
EM(rxrpc_tx_fail_call_final_resend, "CallFinalResend") \
|
||||
EM(rxrpc_tx_fail_conn_abort, "ConnAbort") \
|
||||
EM(rxrpc_tx_fail_conn_challenge, "ConnChall") \
|
||||
EM(rxrpc_tx_fail_conn_response, "ConnResp") \
|
||||
EM(rxrpc_tx_fail_reject, "Reject") \
|
||||
EM(rxrpc_tx_fail_version_keepalive, "VerKeepalive") \
|
||||
E_(rxrpc_tx_fail_version_reply, "VerReply")
|
||||
|
||||
/*
|
||||
* Export enum symbols via userspace.
|
||||
*/
|
||||
|
@ -460,6 +488,7 @@ rxrpc_propose_ack_traces;
|
|||
rxrpc_propose_ack_outcomes;
|
||||
rxrpc_congest_modes;
|
||||
rxrpc_congest_changes;
|
||||
rxrpc_tx_fail_traces;
|
||||
|
||||
/*
|
||||
* Now redefine the EM() and E_() macros to map the enums to the strings that
|
||||
|
@ -1374,6 +1403,62 @@ 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)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rxrpc_tx_fail,
|
||||
TP_PROTO(unsigned int debug_id, rxrpc_serial_t serial, int ret,
|
||||
enum rxrpc_tx_fail_trace what),
|
||||
|
||||
TP_ARGS(debug_id, serial, ret, what),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, debug_id )
|
||||
__field(rxrpc_serial_t, serial )
|
||||
__field(int, ret )
|
||||
__field(enum rxrpc_tx_fail_trace, what )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = debug_id;
|
||||
__entry->serial = serial;
|
||||
__entry->ret = ret;
|
||||
__entry->what = what;
|
||||
),
|
||||
|
||||
TP_printk("c=%08x r=%x ret=%d %s",
|
||||
__entry->debug_id,
|
||||
__entry->serial,
|
||||
__entry->ret,
|
||||
__print_symbolic(__entry->what, rxrpc_tx_fail_traces))
|
||||
);
|
||||
|
||||
#endif /* _TRACE_RXRPC_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
|
@ -313,7 +313,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
|
|||
memset(&cp, 0, sizeof(cp));
|
||||
cp.local = rx->local;
|
||||
cp.key = key;
|
||||
cp.security_level = 0;
|
||||
cp.security_level = rx->min_sec_level;
|
||||
cp.exclusive = false;
|
||||
cp.upgrade = upgrade;
|
||||
cp.service_id = srx->srx_service;
|
||||
|
|
|
@ -476,6 +476,7 @@ enum rxrpc_call_flag {
|
|||
RXRPC_CALL_SEND_PING, /* A ping will need to be sent */
|
||||
RXRPC_CALL_PINGING, /* Ping in process */
|
||||
RXRPC_CALL_RETRANS_TIMEOUT, /* Retransmission due to timeout occurred */
|
||||
RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -40,7 +40,7 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
|
|||
} __attribute__((packed)) pkt;
|
||||
struct rxrpc_ackinfo ack_info;
|
||||
size_t len;
|
||||
int ioc;
|
||||
int ret, ioc;
|
||||
u32 serial, mtu, call_id, padding;
|
||||
|
||||
_enter("%d", conn->debug_id);
|
||||
|
@ -135,10 +135,13 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
|
|||
break;
|
||||
}
|
||||
|
||||
kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
|
||||
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
|
||||
conn->params.peer->last_tx_at = ktime_get_real();
|
||||
if (ret < 0)
|
||||
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_call_final_resend);
|
||||
|
||||
_leave("");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -236,6 +239,8 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
|
|||
|
||||
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
|
||||
if (ret < 0) {
|
||||
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_conn_abort);
|
||||
_debug("sendmsg failed: %d", ret);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
|
@ -971,7 +971,7 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
|
|||
if (timo) {
|
||||
unsigned long now = jiffies, expect_rx_by;
|
||||
|
||||
expect_rx_by = jiffies + timo;
|
||||
expect_rx_by = now + timo;
|
||||
WRITE_ONCE(call->expect_rx_by, expect_rx_by);
|
||||
rxrpc_reduce_call_timer(call, expect_rx_by, now,
|
||||
rxrpc_timer_set_for_normal);
|
||||
|
|
|
@ -71,7 +71,8 @@ static void rxrpc_send_version_request(struct rxrpc_local *local,
|
|||
|
||||
ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
|
||||
if (ret < 0)
|
||||
_debug("sendmsg failed: %d", ret);
|
||||
trace_rxrpc_tx_fail(local->debug_id, 0, ret,
|
||||
rxrpc_tx_fail_version_reply);
|
||||
|
||||
_leave("");
|
||||
}
|
||||
|
|
|
@ -134,6 +134,8 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
|
|||
}
|
||||
}
|
||||
|
||||
switch (local->srx.transport.family) {
|
||||
case AF_INET:
|
||||
/* we want to receive ICMP errors */
|
||||
opt = 1;
|
||||
ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
|
||||
|
@ -151,6 +153,31 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
|
|||
_debug("setsockopt failed");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
/* we want to receive ICMP errors */
|
||||
opt = 1;
|
||||
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR,
|
||||
(char *) &opt, sizeof(opt));
|
||||
if (ret < 0) {
|
||||
_debug("setsockopt failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* we want to set the don't fragment bit */
|
||||
opt = IPV6_PMTUDISC_DO;
|
||||
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER,
|
||||
(char *) &opt, sizeof(opt));
|
||||
if (ret < 0) {
|
||||
_debug("setsockopt failed");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* set the socket up */
|
||||
sock = local->socket->sk;
|
||||
|
|
|
@ -210,6 +210,9 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
|
|||
if (ping)
|
||||
call->ping_time = now;
|
||||
conn->params.peer->last_tx_at = ktime_get_real();
|
||||
if (ret < 0)
|
||||
trace_rxrpc_tx_fail(call->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_call_ack);
|
||||
|
||||
if (call->state < RXRPC_CALL_COMPLETE) {
|
||||
if (ret < 0) {
|
||||
|
@ -294,6 +297,10 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
|
|||
ret = kernel_sendmsg(conn->params.local->socket,
|
||||
&msg, iov, 1, sizeof(pkt));
|
||||
conn->params.peer->last_tx_at = ktime_get_real();
|
||||
if (ret < 0)
|
||||
trace_rxrpc_tx_fail(call->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_call_abort);
|
||||
|
||||
|
||||
rxrpc_put_connection(conn);
|
||||
return ret;
|
||||
|
@ -387,6 +394,9 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
|
|||
conn->params.peer->last_tx_at = ktime_get_real();
|
||||
|
||||
up_read(&conn->params.local->defrag_sem);
|
||||
if (ret < 0)
|
||||
trace_rxrpc_tx_fail(call->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_call_data_nofrag);
|
||||
if (ret == -EMSGSIZE)
|
||||
goto send_fragmentable;
|
||||
|
||||
|
@ -414,6 +424,17 @@ done:
|
|||
rxrpc_timer_set_for_lost_ack);
|
||||
}
|
||||
}
|
||||
|
||||
if (sp->hdr.seq == 1 &&
|
||||
!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER,
|
||||
&call->flags)) {
|
||||
unsigned long nowj = jiffies, expect_rx_by;
|
||||
|
||||
expect_rx_by = nowj + call->next_rx_timo;
|
||||
WRITE_ONCE(call->expect_rx_by, expect_rx_by);
|
||||
rxrpc_reduce_call_timer(call, expect_rx_by, nowj,
|
||||
rxrpc_timer_set_for_normal);
|
||||
}
|
||||
}
|
||||
|
||||
rxrpc_set_keepalive(call);
|
||||
|
@ -465,6 +486,10 @@ send_fragmentable:
|
|||
#endif
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
trace_rxrpc_tx_fail(call->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_call_data_frag);
|
||||
|
||||
up_write(&conn->params.local->defrag_sem);
|
||||
goto done;
|
||||
}
|
||||
|
@ -482,6 +507,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
|
|||
struct kvec iov[2];
|
||||
size_t size;
|
||||
__be32 code;
|
||||
int ret;
|
||||
|
||||
_enter("%d", local->debug_id);
|
||||
|
||||
|
@ -516,7 +542,10 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
|
|||
whdr.flags ^= RXRPC_CLIENT_INITIATED;
|
||||
whdr.flags &= RXRPC_CLIENT_INITIATED;
|
||||
|
||||
kernel_sendmsg(local->socket, &msg, iov, 2, size);
|
||||
ret = kernel_sendmsg(local->socket, &msg, iov, 2, size);
|
||||
if (ret < 0)
|
||||
trace_rxrpc_tx_fail(local->debug_id, 0, ret,
|
||||
rxrpc_tx_fail_reject);
|
||||
}
|
||||
|
||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
||||
|
@ -567,7 +596,8 @@ void rxrpc_send_keepalive(struct rxrpc_peer *peer)
|
|||
|
||||
ret = kernel_sendmsg(peer->local->socket, &msg, iov, 2, len);
|
||||
if (ret < 0)
|
||||
_debug("sendmsg failed: %d", ret);
|
||||
trace_rxrpc_tx_fail(peer->debug_id, 0, ret,
|
||||
rxrpc_tx_fail_version_keepalive);
|
||||
|
||||
peer->last_tx_at = ktime_get_real();
|
||||
_leave("");
|
||||
|
|
|
@ -28,39 +28,39 @@ 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;
|
||||
}
|
||||
|
@ -68,25 +68,25 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
|
|||
|
||||
#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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
|
|
@ -664,7 +664,8 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
|
|||
|
||||
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
|
||||
if (ret < 0) {
|
||||
_debug("sendmsg failed: %d", ret);
|
||||
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_conn_challenge);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
@ -719,7 +720,8 @@ static int rxkad_send_response(struct rxrpc_connection *conn,
|
|||
|
||||
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 3, len);
|
||||
if (ret < 0) {
|
||||
_debug("sendmsg failed: %d", ret);
|
||||
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
|
||||
rxrpc_tx_fail_conn_response);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
|
|
@ -223,6 +223,15 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
|
|||
|
||||
ret = rxrpc_send_data_packet(call, skb, false);
|
||||
if (ret < 0) {
|
||||
switch (ret) {
|
||||
case -ENETUNREACH:
|
||||
case -EHOSTUNREACH:
|
||||
case -ECONNREFUSED:
|
||||
rxrpc_set_call_completion(call,
|
||||
RXRPC_CALL_LOCAL_ERROR,
|
||||
0, ret);
|
||||
goto out;
|
||||
}
|
||||
_debug("need instant resend %d", ret);
|
||||
rxrpc_instant_resend(call, ix);
|
||||
} else {
|
||||
|
@ -241,6 +250,7 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
|
|||
rxrpc_timer_set_for_send);
|
||||
}
|
||||
|
||||
out:
|
||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
||||
_leave("");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue