Skip to content

Commit 8e1ee18

Browse files
Vlad Yasevichdavem330
authored andcommitted
sctp: Rework the tsn map to use generic bitmap.
The tsn map currently use is 4K large and is stuck inside the sctp_association structure making memory references REALLY expensive. What we really need is at most 4K worth of bits so the biggest map we would have is 512 bytes. Also, the map is only really usefull when we have gaps to store and report. As such, starting with minimal map of say 32 TSNs (bits) should be enough for normal low-loss operations. We can grow the map by some multiple of 32 along with some extra room any time we receive the TSN which would put us outside of the map boundry. As we close gaps, we can shift the map to rebase it on the latest TSN we've seen. This saves 4088 bytes per association just in the map alone along savings from the now unnecessary structure members. Signed-off-by: Vlad Yasevich <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3c689b7 commit 8e1ee18

File tree

8 files changed

+178
-224
lines changed

8 files changed

+178
-224
lines changed

include/net/sctp/constants.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,9 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 };
261261
* must be less than 65535 (2^16 - 1), or we will have overflow
262262
* problems creating SACK's.
263263
*/
264-
#define SCTP_TSN_MAP_SIZE 2048
264+
#define SCTP_TSN_MAP_INITIAL BITS_PER_LONG
265+
#define SCTP_TSN_MAP_INCREMENT SCTP_TSN_MAP_INITIAL
266+
#define SCTP_TSN_MAP_SIZE 4096
265267
#define SCTP_TSN_MAX_GAP 65535
266268

267269
/* We will not record more than this many duplicate TSNs between two

include/net/sctp/structs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,6 @@ struct sctp_association {
15451545
* in tsn_map--we get it by calling sctp_tsnmap_get_ctsn().
15461546
*/
15471547
struct sctp_tsnmap tsn_map;
1548-
__u8 _map[sctp_tsnmap_storage_size(SCTP_TSN_MAP_SIZE)];
15491548

15501549
/* Ack State : This flag indicates if the next received
15511550
* : packet is to be responded to with a

include/net/sctp/tsnmap.h

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,7 @@ struct sctp_tsnmap {
6060
* It points at one of the two buffers with which we will
6161
* ping-pong between.
6262
*/
63-
__u8 *tsn_map;
64-
65-
/* This marks the tsn which overflows the tsn_map, when the
66-
* cumulative ack point reaches this point we know we can switch
67-
* maps (tsn_map and overflow_map swap).
68-
*/
69-
__u32 overflow_tsn;
70-
71-
/* This is the overflow array for tsn_map.
72-
* It points at one of the other ping-pong buffers.
73-
*/
74-
__u8 *overflow_map;
63+
unsigned long *tsn_map;
7564

7665
/* This is the TSN at tsn_map[0]. */
7766
__u32 base_tsn;
@@ -89,15 +78,15 @@ struct sctp_tsnmap {
8978
*/
9079
__u32 cumulative_tsn_ack_point;
9180

81+
/* This is the highest TSN we've marked. */
82+
__u32 max_tsn_seen;
83+
9284
/* This is the minimum number of TSNs we can track. This corresponds
9385
* to the size of tsn_map. Note: the overflow_map allows us to
9486
* potentially track more than this quantity.
9587
*/
9688
__u16 len;
9789

98-
/* This is the highest TSN we've marked. */
99-
__u32 max_tsn_seen;
100-
10190
/* Data chunks pending receipt. used by SCTP_STATUS sockopt */
10291
__u16 pending_data;
10392

@@ -110,24 +99,17 @@ struct sctp_tsnmap {
11099

111100
/* Record gap ack block information here. */
112101
struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
113-
114-
int malloced;
115-
116-
__u8 raw_map[0];
117102
};
118103

119104
struct sctp_tsnmap_iter {
120105
__u32 start;
121106
};
122107

123-
/* This macro assists in creation of external storage for variable length
124-
* internal buffers. We double allocate so the overflow map works.
125-
*/
126-
#define sctp_tsnmap_storage_size(count) (sizeof(__u8) * (count) * 2)
127-
128108
/* Initialize a block of memory as a tsnmap. */
129109
struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *, __u16 len,
130-
__u32 initial_tsn);
110+
__u32 initial_tsn, gfp_t gfp);
111+
112+
void sctp_tsnmap_free(struct sctp_tsnmap *map);
131113

132114
/* Test the tracking state of this TSN.
133115
* Returns:
@@ -138,7 +120,7 @@ struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *, __u16 len,
138120
int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
139121

140122
/* Mark this TSN as seen. */
141-
void sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
123+
int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
142124

143125
/* Mark this TSN and all lower as seen. */
144126
void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn);
@@ -183,10 +165,7 @@ static inline struct sctp_gap_ack_block *sctp_tsnmap_get_gabs(struct sctp_tsnmap
183165
/* Is there a gap in the TSN map? */
184166
static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
185167
{
186-
int has_gap;
187-
188-
has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen);
189-
return has_gap;
168+
return (map->cumulative_tsn_ack_point != map->max_tsn_seen);
190169
}
191170

192171
/* Mark a duplicate TSN. Note: limit the storage of duplicate TSN

net/sctp/associola.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
283283
if (!sctp_ulpq_init(&asoc->ulpq, asoc))
284284
goto fail_init;
285285

286-
/* Set up the tsn tracking. */
287-
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, 0);
286+
memset(&asoc->peer.tsn_map, 0, sizeof(struct sctp_tsnmap));
288287

289288
asoc->need_ecne = 0;
290289

@@ -402,6 +401,8 @@ void sctp_association_free(struct sctp_association *asoc)
402401
/* Dispose of any pending chunks on the inqueue. */
403402
sctp_inq_free(&asoc->base.inqueue);
404403

404+
sctp_tsnmap_free(&asoc->peer.tsn_map);
405+
405406
/* Free ssnmap storage. */
406407
sctp_ssnmap_free(asoc->ssnmap);
407408

@@ -1122,8 +1123,8 @@ void sctp_assoc_update(struct sctp_association *asoc,
11221123
asoc->peer.rwnd = new->peer.rwnd;
11231124
asoc->peer.sack_needed = new->peer.sack_needed;
11241125
asoc->peer.i = new->peer.i;
1125-
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE,
1126-
asoc->peer.i.initial_tsn);
1126+
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
1127+
asoc->peer.i.initial_tsn, GFP_ATOMIC);
11271128

11281129
/* Remove any peer addresses not present in the new association. */
11291130
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {

net/sctp/sm_make_chunk.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,8 +2288,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
22882288
}
22892289

22902290
/* Set up the TSN tracking pieces. */
2291-
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE,
2292-
asoc->peer.i.initial_tsn);
2291+
if (!sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
2292+
asoc->peer.i.initial_tsn, gfp))
2293+
goto clean_up;
22932294

22942295
/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
22952296
*

net/sctp/sm_sideeffect.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
11521152

11531153
case SCTP_CMD_REPORT_TSN:
11541154
/* Record the arrival of a TSN. */
1155-
sctp_tsnmap_mark(&asoc->peer.tsn_map, cmd->obj.u32);
1155+
error = sctp_tsnmap_mark(&asoc->peer.tsn_map,
1156+
cmd->obj.u32);
11561157
break;
11571158

11581159
case SCTP_CMD_REPORT_FWDTSN:

0 commit comments

Comments
 (0)