aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2016-07-13 14:08:58 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-13 21:10:14 -0400
commite7487c86dc5c4a528a7dbd9dc14f453a0de61a84 (patch)
treefee52720c9c4621d165294c8d48dff6326468c36
parent1f45f78f8e511203f03138f2ccde3d2cf90d2cbf (diff)
sctp: avoid identifying address family many times for a chunk
Identifying address family operations during rx path is not something expensive but it's ugly to the eye to have it done multiple times, specially when we already validated it during initial rx processing. This patch takes advantage of the now shared sctp_input_cb and make the pointer to the operations readily available. Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--net/sctp/input.c1
-rw-r--r--net/sctp/inqueue.c1
-rw-r--r--net/sctp/sm_make_chunk.c20
-rw-r--r--net/sctp/sm_statefuns.c7
5 files changed, 9 insertions, 21 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index f6f201de6fa4..ce93c4b10d26 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1104,6 +1104,7 @@ struct sctp_input_cb {
1104#endif 1104#endif
1105 } header; 1105 } header;
1106 struct sctp_chunk *chunk; 1106 struct sctp_chunk *chunk;
1107 struct sctp_af *af;
1107}; 1108};
1108#define SCTP_INPUT_CB(__skb) ((struct sctp_input_cb *)&((__skb)->cb[0])) 1109#define SCTP_INPUT_CB(__skb) ((struct sctp_input_cb *)&((__skb)->cb[0]))
1109 1110
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 7a327ff71f08..30d72f7707b6 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -140,6 +140,7 @@ int sctp_rcv(struct sk_buff *skb)
140 af = sctp_get_af_specific(family); 140 af = sctp_get_af_specific(family);
141 if (unlikely(!af)) 141 if (unlikely(!af))
142 goto discard_it; 142 goto discard_it;
143 SCTP_INPUT_CB(skb)->af = af;
143 144
144 /* Initialize local addresses for lookups. */ 145 /* Initialize local addresses for lookups. */
145 af->from_skb(&src, skb, 1); 146 af->from_skb(&src, skb, 1);
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 147d975b0455..8fc773f9b59a 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -224,6 +224,7 @@ new_skb:
224 *head_cb = SCTP_INPUT_CB(chunk->head_skb); 224 *head_cb = SCTP_INPUT_CB(chunk->head_skb);
225 225
226 cb->chunk = head_cb->chunk; 226 cb->chunk = head_cb->chunk;
227 cb->af = head_cb->af;
227 } 228 }
228 } 229 }
229 230
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 1c96f4740e67..8c77b87a8565 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -108,14 +108,9 @@ static void sctp_control_set_owner_w(struct sctp_chunk *chunk)
108/* What was the inbound interface for this chunk? */ 108/* What was the inbound interface for this chunk? */
109int sctp_chunk_iif(const struct sctp_chunk *chunk) 109int sctp_chunk_iif(const struct sctp_chunk *chunk)
110{ 110{
111 struct sctp_af *af; 111 struct sk_buff *skb = chunk->skb;
112 int iif = 0;
113
114 af = sctp_get_af_specific(ipver2af(ip_hdr(chunk->skb)->version));
115 if (af)
116 iif = af->skb_iif(chunk->skb);
117 112
118 return iif; 113 return SCTP_INPUT_CB(skb)->af->skb_iif(skb);
119} 114}
120 115
121/* RFC 2960 3.3.2 Initiation (INIT) (1) 116/* RFC 2960 3.3.2 Initiation (INIT) (1)
@@ -1600,7 +1595,6 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
1600 struct sctp_association *asoc; 1595 struct sctp_association *asoc;
1601 struct sk_buff *skb; 1596 struct sk_buff *skb;
1602 sctp_scope_t scope; 1597 sctp_scope_t scope;
1603 struct sctp_af *af;
1604 1598
1605 /* Create the bare association. */ 1599 /* Create the bare association. */
1606 scope = sctp_scope(sctp_source(chunk)); 1600 scope = sctp_scope(sctp_source(chunk));
@@ -1610,16 +1604,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
1610 asoc->temp = 1; 1604 asoc->temp = 1;
1611 skb = chunk->skb; 1605 skb = chunk->skb;
1612 /* Create an entry for the source address of the packet. */ 1606 /* Create an entry for the source address of the packet. */
1613 af = sctp_get_af_specific(ipver2af(ip_hdr(skb)->version)); 1607 SCTP_INPUT_CB(skb)->af->from_skb(&asoc->c.peer_addr, skb, 1);
1614 if (unlikely(!af)) 1608
1615 goto fail;
1616 af->from_skb(&asoc->c.peer_addr, skb, 1);
1617nodata: 1609nodata:
1618 return asoc; 1610 return asoc;
1619
1620fail:
1621 sctp_association_free(asoc);
1622 return NULL;
1623} 1611}
1624 1612
1625/* Build a cookie representing asoc. 1613/* Build a cookie representing asoc.
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 5aabf42065e2..b7c1f7f3c838 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -6119,13 +6119,10 @@ static int sctp_eat_data(const struct sctp_association *asoc,
6119 */ 6119 */
6120 6120
6121 if (!chunk->ecn_ce_done) { 6121 if (!chunk->ecn_ce_done) {
6122 struct sctp_af *af; 6122 struct sctp_af *af = SCTP_INPUT_CB(chunk->skb)->af;
6123 chunk->ecn_ce_done = 1; 6123 chunk->ecn_ce_done = 1;
6124 6124
6125 af = sctp_get_af_specific( 6125 if (af->is_ce(sctp_gso_headskb(chunk->skb)) &&
6126 ipver2af(ip_hdr(chunk->skb)->version));
6127
6128 if (af && af->is_ce(sctp_gso_headskb(chunk->skb)) &&
6129 asoc->peer.ecn_capable) { 6126 asoc->peer.ecn_capable) {
6130 /* Do real work as sideffect. */ 6127 /* Do real work as sideffect. */
6131 sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, 6128 sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,