From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
To: netdev@vger.kernel.org
Cc: linux-sctp@vger.kernel.org, Neil Horman <nhorman@tuxdriver.com>,
Vlad Yasevich <vyasevich@gmail.com>,
Xin Long <lucien.xin@gmail.com>
Subject: [PATCH net-next 2/8] sctp: factor out sctp_outq_select_transport
Date: Fri, 11 May 2018 20:28:37 -0300 [thread overview]
Message-ID: <4b7935c08dea4610292965ad1c002843c9f98831.1526077476.git.marcelo.leitner@gmail.com> (raw)
In-Reply-To: <cover.1526077476.git.marcelo.leitner@gmail.com>
We had two spots doing such complex operation and they were very close to
each other, a bit more tailored to here or there.
This patch unifies these under the same function,
sctp_outq_select_transport, which knows how to handle control chunks and
original transmissions (but not retransmissions).
Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
net/sctp/outqueue.c | 187 +++++++++++++++++++++++++---------------------------
1 file changed, 90 insertions(+), 97 deletions(-)
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 300bd0dfc7c14c9df579dbe2f9e78dd8356ae1a3..bda50596d4bfebeac03966c5a161473df1c1986a 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -791,6 +791,90 @@ static int sctp_packet_singleton(struct sctp_transport *transport,
return sctp_packet_transmit(&singleton, gfp);
}
+static bool sctp_outq_select_transport(struct sctp_chunk *chunk,
+ struct sctp_association *asoc,
+ struct sctp_transport **transport,
+ struct list_head *transport_list)
+{
+ struct sctp_transport *new_transport = chunk->transport;
+ struct sctp_transport *curr = *transport;
+ bool changed = false;
+
+ if (!new_transport) {
+ if (!sctp_chunk_is_data(chunk)) {
+ /*
+ * If we have a prior transport pointer, see if
+ * the destination address of the chunk
+ * matches the destination address of the
+ * current transport. If not a match, then
+ * try to look up the transport with a given
+ * destination address. We do this because
+ * after processing ASCONFs, we may have new
+ * transports created.
+ */
+ if (curr && sctp_cmp_addr_exact(&chunk->dest,
+ &curr->ipaddr))
+ new_transport = curr;
+ else
+ new_transport = sctp_assoc_lookup_paddr(asoc,
+ &chunk->dest);
+ }
+
+ /* if we still don't have a new transport, then
+ * use the current active path.
+ */
+ if (!new_transport)
+ new_transport = asoc->peer.active_path;
+ } else {
+ __u8 type;
+
+ switch (new_transport->state) {
+ case SCTP_INACTIVE:
+ case SCTP_UNCONFIRMED:
+ case SCTP_PF:
+ /* If the chunk is Heartbeat or Heartbeat Ack,
+ * send it to chunk->transport, even if it's
+ * inactive.
+ *
+ * 3.3.6 Heartbeat Acknowledgement:
+ * ...
+ * A HEARTBEAT ACK is always sent to the source IP
+ * address of the IP datagram containing the
+ * HEARTBEAT chunk to which this ack is responding.
+ * ...
+ *
+ * ASCONF_ACKs also must be sent to the source.
+ */
+ type = chunk->chunk_hdr->type;
+ if (type != SCTP_CID_HEARTBEAT &&
+ type != SCTP_CID_HEARTBEAT_ACK &&
+ type != SCTP_CID_ASCONF_ACK)
+ new_transport = asoc->peer.active_path;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Are we switching transports? Take care of transport locks. */
+ if (new_transport != curr) {
+ changed = true;
+ curr = new_transport;
+ *transport = curr;
+ if (list_empty(&curr->send_ready))
+ list_add_tail(&curr->send_ready, transport_list);
+
+ sctp_packet_config(&curr->packet, asoc->peer.i.init_tag,
+ asoc->peer.ecn_capable);
+ /* We've switched transports, so apply the
+ * Burst limit to the new transport.
+ */
+ sctp_transport_burst_limited(curr);
+ }
+
+ return changed;
+}
+
/*
* Try to flush an outqueue.
*
@@ -806,7 +890,6 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
struct sctp_association *asoc = q->asoc;
__u32 vtag = asoc->peer.i.init_tag;
struct sctp_transport *transport = NULL;
- struct sctp_transport *new_transport;
struct sctp_chunk *chunk, *tmp;
enum sctp_xmit status;
int error = 0;
@@ -843,68 +926,12 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
list_del_init(&chunk->list);
- /* Pick the right transport to use. */
- new_transport = chunk->transport;
-
- if (!new_transport) {
- /*
- * If we have a prior transport pointer, see if
- * the destination address of the chunk
- * matches the destination address of the
- * current transport. If not a match, then
- * try to look up the transport with a given
- * destination address. We do this because
- * after processing ASCONFs, we may have new
- * transports created.
- */
- if (transport &&
- sctp_cmp_addr_exact(&chunk->dest,
- &transport->ipaddr))
- new_transport = transport;
- else
- new_transport = sctp_assoc_lookup_paddr(asoc,
- &chunk->dest);
-
- /* if we still don't have a new transport, then
- * use the current active path.
- */
- if (!new_transport)
- new_transport = asoc->peer.active_path;
- } else if ((new_transport->state == SCTP_INACTIVE) ||
- (new_transport->state == SCTP_UNCONFIRMED) ||
- (new_transport->state == SCTP_PF)) {
- /* If the chunk is Heartbeat or Heartbeat Ack,
- * send it to chunk->transport, even if it's
- * inactive.
- *
- * 3.3.6 Heartbeat Acknowledgement:
- * ...
- * A HEARTBEAT ACK is always sent to the source IP
- * address of the IP datagram containing the
- * HEARTBEAT chunk to which this ack is responding.
- * ...
- *
- * ASCONF_ACKs also must be sent to the source.
- */
- if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT &&
- chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT_ACK &&
- chunk->chunk_hdr->type != SCTP_CID_ASCONF_ACK)
- new_transport = asoc->peer.active_path;
- }
-
- /* Are we switching transports?
- * Take care of transport locks.
+ /* Pick the right transport to use. Should always be true for
+ * the first chunk as we don't have a transport by then.
*/
- if (new_transport != transport) {
- transport = new_transport;
- if (list_empty(&transport->send_ready)) {
- list_add_tail(&transport->send_ready,
- &transport_list);
- }
+ if (sctp_outq_select_transport(chunk, asoc, &transport,
+ &transport_list))
packet = &transport->packet;
- sctp_packet_config(packet, vtag,
- asoc->peer.ecn_capable);
- }
switch (chunk->chunk_hdr->type) {
/*
@@ -1072,43 +1099,9 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
goto sctp_flush_out;
}
- /* If there is a specified transport, use it.
- * Otherwise, we want to use the active path.
- */
- new_transport = chunk->transport;
- if (!new_transport ||
- ((new_transport->state == SCTP_INACTIVE) ||
- (new_transport->state == SCTP_UNCONFIRMED) ||
- (new_transport->state == SCTP_PF)))
- new_transport = asoc->peer.active_path;
- if (new_transport->state == SCTP_UNCONFIRMED) {
- WARN_ONCE(1, "Attempt to send packet on unconfirmed path.");
- sctp_sched_dequeue_done(q, chunk);
- sctp_chunk_fail(chunk, 0);
- sctp_chunk_free(chunk);
- continue;
- }
-
- /* Change packets if necessary. */
- if (new_transport != transport) {
- transport = new_transport;
-
- /* Schedule to have this transport's
- * packet flushed.
- */
- if (list_empty(&transport->send_ready)) {
- list_add_tail(&transport->send_ready,
- &transport_list);
- }
-
+ if (sctp_outq_select_transport(chunk, asoc, &transport,
+ &transport_list))
packet = &transport->packet;
- sctp_packet_config(packet, vtag,
- asoc->peer.ecn_capable);
- /* We've switched transports, so apply the
- * Burst limit to the new transport.
- */
- sctp_transport_burst_limited(transport);
- }
pr_debug("%s: outq:%p, chunk:%p[%s], tx-tsn:0x%x skb->head:%p "
"skb->users:%d\n",
--
2.14.3
next prev parent reply other threads:[~2018-05-11 23:28 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-11 23:28 [PATCH net-next 0/8] sctp: refactor sctp_outq_flush Marcelo Ricardo Leitner
2018-05-11 23:28 ` [PATCH net-next 1/8] sctp: add sctp_packet_singleton Marcelo Ricardo Leitner
2018-05-11 23:28 ` Marcelo Ricardo Leitner [this message]
2018-05-11 23:28 ` [PATCH net-next 3/8] sctp: move the flush of ctrl chunks into its own function Marcelo Ricardo Leitner
2018-05-12 13:29 ` Marcelo Ricardo Leitner
2018-05-11 23:28 ` [PATCH net-next 4/8] sctp: move outq data rtx code out of sctp_outq_flush Marcelo Ricardo Leitner
2018-05-11 23:28 ` [PATCH net-next 5/8] sctp: move flushing of data chunks " Marcelo Ricardo Leitner
2018-05-11 23:29 ` [PATCH net-next 6/8] sctp: move transport flush code " Marcelo Ricardo Leitner
2018-05-11 23:29 ` [PATCH net-next 7/8] sctp: make use of gfp on retransmissions Marcelo Ricardo Leitner
2018-05-11 23:29 ` [PATCH net-next 8/8] sctp: rework switch cases in sctp_outq_flush_data Marcelo Ricardo Leitner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4b7935c08dea4610292965ad1c002843c9f98831.1526077476.git.marcelo.leitner@gmail.com \
--to=marcelo.leitner@gmail.com \
--cc=linux-sctp@vger.kernel.org \
--cc=lucien.xin@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=nhorman@tuxdriver.com \
--cc=vyasevich@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).