Skip to content

Commit

Permalink
Merge tag 'rxrpc-rewrite-20160923' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/dhowells/linux-fs

David Howells says:

====================
rxrpc: Bug fixes and tracepoints

Here are a bunch of bug fixes:

 (1) Need to set the timestamp on a Tx packet before queueing it to avoid
     trouble with the retransmission function.

 (2) Don't send an ACK at the end of the service reply transmission; it's
     the responsibility of the client to send an ACK to close the call.
     The service can resend the last DATA packet or send a PING ACK.

 (3) Wake sendmsg() on abnormal call termination.

 (4) Use ktime_add_ms() not ktime_add_ns() to add millisecond offsets.

 (5) Use before_eq() & co. to compare serial numbers (which may wrap).

 (6) Start the resend timer on DATA packet transmission.

 (7) Don't accidentally cancel a retransmission upon receiving a NACK.

 (8) Fix the call timer setting function to deal with timeouts that are now
     or past.

 (9) Don't use a flag to communicate the presence of the last packet in the
     Tx buffer from sendmsg to the input routines where ACK and DATA
     reception is handled.  The problem is that there's a window between
     queueing the last packet for transmission and setting the flag in
     which ACKs or reply DATA packets can arrive, causing apparent state
     machine violation issues.

     Instead use the annotation buffer to mark the last packet and pick up
     and set the flag in the input routines.

(10) Don't call the tx_ack tracepoint and don't allocate a serial number if
     someone else nicked the ACK we were about to transmit.

There are also new tracepoints and one altered tracepoint used to track
down the above bugs:

(11) Call timer tracepoint.

(12) Data Tx tracepoint (and adjustments to ACK tracepoint).

(13) Injected Rx packet loss tracepoint.

(14) Ack proposal tracepoint.

(15) Retransmission selection tracepoint.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 24, 2016
2 parents 3eb193e + c6672e3 commit 2a9aa41
Show file tree
Hide file tree
Showing 11 changed files with 405 additions and 127 deletions.
1 change: 1 addition & 0 deletions include/rxrpc/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct rxrpc_ackpacket {
#define RXRPC_ACK_PING_RESPONSE 7 /* response to RXRPC_ACK_PING */
#define RXRPC_ACK_DELAY 8 /* nothing happened since received packet */
#define RXRPC_ACK_IDLE 9 /* ACK due to fully received ACK window */
#define RXRPC_ACK__INVALID 10 /* Representation of invalid ACK reason */

uint8_t nAcks; /* number of ACKs */
#define RXRPC_MAXACKS 255
Expand Down
174 changes: 165 additions & 9 deletions include/trace/events/rxrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,38 +251,72 @@ TRACE_EVENT(rxrpc_rx_ack,

TP_printk("c=%p %s f=%08x n=%u",
__entry->call,
rxrpc_acks(__entry->reason),
rxrpc_ack_names[__entry->reason],
__entry->first,
__entry->n_acks)
);

TRACE_EVENT(rxrpc_tx_data,
TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
rxrpc_serial_t serial, u8 flags, bool lose),

TP_ARGS(call, seq, serial, flags, lose),

TP_STRUCT__entry(
__field(struct rxrpc_call *, call )
__field(rxrpc_seq_t, seq )
__field(rxrpc_serial_t, serial )
__field(u8, flags )
__field(bool, lose )
),

TP_fast_assign(
__entry->call = call;
__entry->seq = seq;
__entry->serial = serial;
__entry->flags = flags;
__entry->lose = lose;
),

TP_printk("c=%p DATA %08x q=%08x fl=%02x%s",
__entry->call,
__entry->serial,
__entry->seq,
__entry->flags,
__entry->lose ? " *LOSE*" : "")
);

TRACE_EVENT(rxrpc_tx_ack,
TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t first,
rxrpc_serial_t serial, u8 reason, u8 n_acks),
TP_PROTO(struct rxrpc_call *call, rxrpc_serial_t serial,
rxrpc_seq_t ack_first, rxrpc_serial_t ack_serial,
u8 reason, u8 n_acks),

TP_ARGS(call, first, serial, reason, n_acks),
TP_ARGS(call, serial, ack_first, ack_serial, reason, n_acks),

TP_STRUCT__entry(
__field(struct rxrpc_call *, call )
__field(rxrpc_seq_t, first )
__field(rxrpc_serial_t, serial )
__field(rxrpc_seq_t, ack_first )
__field(rxrpc_serial_t, ack_serial )
__field(u8, reason )
__field(u8, n_acks )
),

TP_fast_assign(
__entry->call = call;
__entry->first = first;
__entry->serial = serial;
__entry->ack_first = ack_first;
__entry->ack_serial = ack_serial;
__entry->reason = reason;
__entry->n_acks = n_acks;
),

TP_printk("c=%p %s f=%08x r=%08x n=%u",
TP_printk(" c=%p ACK %08x %s f=%08x r=%08x n=%u",
__entry->call,
rxrpc_acks(__entry->reason),
__entry->first,
__entry->serial,
rxrpc_ack_names[__entry->reason],
__entry->ack_first,
__entry->ack_serial,
__entry->n_acks)
);

Expand Down Expand Up @@ -414,6 +448,128 @@ TRACE_EVENT(rxrpc_rtt_rx,
__entry->avg)
);

TRACE_EVENT(rxrpc_timer,
TP_PROTO(struct rxrpc_call *call, enum rxrpc_timer_trace why,
unsigned long now),

TP_ARGS(call, why, now),

TP_STRUCT__entry(
__field(struct rxrpc_call *, call )
__field(enum rxrpc_timer_trace, why )
__field(unsigned long, now )
__field(unsigned long, expire_at )
__field(unsigned long, ack_at )
__field(unsigned long, resend_at )
__field(unsigned long, timer )
),

TP_fast_assign(
__entry->call = call;
__entry->why = why;
__entry->now = now;
__entry->expire_at = call->expire_at;
__entry->ack_at = call->ack_at;
__entry->resend_at = call->resend_at;
__entry->timer = call->timer.expires;
),

TP_printk("c=%p %s now=%lx x=%ld a=%ld r=%ld t=%ld",
__entry->call,
rxrpc_timer_traces[__entry->why],
__entry->now,
__entry->expire_at - __entry->now,
__entry->ack_at - __entry->now,
__entry->resend_at - __entry->now,
__entry->timer - __entry->now)
);

TRACE_EVENT(rxrpc_rx_lose,
TP_PROTO(struct rxrpc_skb_priv *sp),

TP_ARGS(sp),

TP_STRUCT__entry(
__field_struct(struct rxrpc_host_header, hdr )
),

TP_fast_assign(
memcpy(&__entry->hdr, &sp->hdr, sizeof(__entry->hdr));
),

TP_printk("%08x:%08x:%08x:%04x %08x %08x %02x %02x %s *LOSE*",
__entry->hdr.epoch, __entry->hdr.cid,
__entry->hdr.callNumber, __entry->hdr.serviceId,
__entry->hdr.serial, __entry->hdr.seq,
__entry->hdr.type, __entry->hdr.flags,
__entry->hdr.type <= 15 ? rxrpc_pkts[__entry->hdr.type] : "?UNK")
);

TRACE_EVENT(rxrpc_propose_ack,
TP_PROTO(struct rxrpc_call *call, enum rxrpc_propose_ack_trace why,
u8 ack_reason, rxrpc_serial_t serial, bool immediate,
bool background, enum rxrpc_propose_ack_outcome outcome),

TP_ARGS(call, why, ack_reason, serial, immediate, background,
outcome),

TP_STRUCT__entry(
__field(struct rxrpc_call *, call )
__field(enum rxrpc_propose_ack_trace, why )
__field(rxrpc_serial_t, serial )
__field(u8, ack_reason )
__field(bool, immediate )
__field(bool, background )
__field(enum rxrpc_propose_ack_outcome, outcome )
),

TP_fast_assign(
__entry->call = call;
__entry->why = why;
__entry->serial = serial;
__entry->ack_reason = ack_reason;
__entry->immediate = immediate;
__entry->background = background;
__entry->outcome = outcome;
),

TP_printk("c=%p %s %s r=%08x i=%u b=%u%s",
__entry->call,
rxrpc_propose_ack_traces[__entry->why],
rxrpc_ack_names[__entry->ack_reason],
__entry->serial,
__entry->immediate,
__entry->background,
rxrpc_propose_ack_outcomes[__entry->outcome])
);

TRACE_EVENT(rxrpc_retransmit,
TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq, u8 annotation,
s64 expiry),

TP_ARGS(call, seq, annotation, expiry),

TP_STRUCT__entry(
__field(struct rxrpc_call *, call )
__field(rxrpc_seq_t, seq )
__field(u8, annotation )
__field(s64, expiry )
),

TP_fast_assign(
__entry->call = call;
__entry->seq = seq;
__entry->annotation = annotation;
__entry->expiry = expiry;
),

TP_printk("c=%p q=%x a=%02x xp=%lld",
__entry->call,
__entry->seq,
__entry->annotation,
__entry->expiry)
);

#endif /* _TRACE_RXRPC_H */

/* This part must be outside protection */
Expand Down
45 changes: 41 additions & 4 deletions net/rxrpc/ar-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,9 @@ struct rxrpc_call {
#define RXRPC_TX_ANNO_NAK 2
#define RXRPC_TX_ANNO_RETRANS 3
#define RXRPC_TX_ANNO_MASK 0x03
#define RXRPC_TX_ANNO_RESENT 0x04
#define RXRPC_TX_ANNO_LAST 0x04
#define RXRPC_TX_ANNO_RESENT 0x08

#define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */
#define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */
#define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */
Expand Down Expand Up @@ -621,9 +623,10 @@ extern const char rxrpc_call_traces[rxrpc_call__nr_trace][4];
enum rxrpc_transmit_trace {
rxrpc_transmit_wait,
rxrpc_transmit_queue,
rxrpc_transmit_queue_reqack,
rxrpc_transmit_queue_last,
rxrpc_transmit_rotate,
rxrpc_transmit_rotate_last,
rxrpc_transmit_await_reply,
rxrpc_transmit_end,
rxrpc_transmit__nr_trace
};
Expand Down Expand Up @@ -675,8 +678,39 @@ enum rxrpc_rtt_rx_trace {

extern const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5];

enum rxrpc_timer_trace {
rxrpc_timer_begin,
rxrpc_timer_expired,
rxrpc_timer_set_for_ack,
rxrpc_timer_set_for_resend,
rxrpc_timer_set_for_send,
rxrpc_timer__nr_trace
};

extern const char rxrpc_timer_traces[rxrpc_timer__nr_trace][8];

enum rxrpc_propose_ack_trace {
rxrpc_propose_ack_input_data,
rxrpc_propose_ack_ping_for_params,
rxrpc_propose_ack_respond_to_ack,
rxrpc_propose_ack_respond_to_ping,
rxrpc_propose_ack_retry_tx,
rxrpc_propose_ack_terminal_ack,
rxrpc_propose_ack__nr_trace
};

enum rxrpc_propose_ack_outcome {
rxrpc_propose_ack_use,
rxrpc_propose_ack_update,
rxrpc_propose_ack_subsume,
rxrpc_propose_ack__nr_outcomes
};

extern const char rxrpc_propose_ack_traces[rxrpc_propose_ack__nr_trace][8];
extern const char *const rxrpc_propose_ack_outcomes[rxrpc_propose_ack__nr_outcomes];

extern const char *const rxrpc_pkts[];
extern const char *rxrpc_acks(u8 reason);
extern const char const rxrpc_ack_names[RXRPC_ACK__INVALID + 1][4];

#include <trace/events/rxrpc.h>

Expand Down Expand Up @@ -704,7 +738,9 @@ int rxrpc_reject_call(struct rxrpc_sock *);
/*
* call_event.c
*/
void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool);
void rxrpc_set_timer(struct rxrpc_call *, enum rxrpc_timer_trace);
void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
enum rxrpc_propose_ack_trace);
void rxrpc_process_call(struct work_struct *);

/*
Expand Down Expand Up @@ -758,6 +794,7 @@ static inline bool __rxrpc_set_call_completion(struct rxrpc_call *call,
call->error = error;
call->completion = compl,
call->state = RXRPC_CALL_COMPLETE;
wake_up(&call->waitq);
return true;
}
return false;
Expand Down
Loading

0 comments on commit 2a9aa41

Please sign in to comment.