summaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-10-08 14:18:39 -0700
committerDavid S. Miller <davem@davemloft.net>2008-10-08 14:18:39 -0700
commit8e1ee18c332e08bee9d8bd66e63cd564fbf17fc2 (patch)
tree8dace1db660d555eb6e020f301fdfe6cf6c05b80 /include/net
parent3c689b7320ae6f20dba6a8b71806a6c6fd604ee8 (diff)
downloadlinux-8e1ee18c332e08bee9d8bd66e63cd564fbf17fc2.tar.gz
linux-8e1ee18c332e08bee9d8bd66e63cd564fbf17fc2.tar.xz
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 <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/sctp/constants.h4
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--include/net/sctp/tsnmap.h39
3 files changed, 12 insertions, 32 deletions
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index c32ddf0279c8..b05b0557211f 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -261,7 +261,9 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 };
* must be less than 65535 (2^16 - 1), or we will have overflow
* problems creating SACK's.
*/
-#define SCTP_TSN_MAP_SIZE 2048
+#define SCTP_TSN_MAP_INITIAL BITS_PER_LONG
+#define SCTP_TSN_MAP_INCREMENT SCTP_TSN_MAP_INITIAL
+#define SCTP_TSN_MAP_SIZE 4096
#define SCTP_TSN_MAX_GAP 65535
/* We will not record more than this many duplicate TSNs between two
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 94c62e4ddea9..9661d7b765f0 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1545,7 +1545,6 @@ struct sctp_association {
* in tsn_map--we get it by calling sctp_tsnmap_get_ctsn().
*/
struct sctp_tsnmap tsn_map;
- __u8 _map[sctp_tsnmap_storage_size(SCTP_TSN_MAP_SIZE)];
/* Ack State : This flag indicates if the next received
* : packet is to be responded to with a
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index 099211bf998d..6dabbee8bbd3 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -60,18 +60,7 @@ struct sctp_tsnmap {
* It points at one of the two buffers with which we will
* ping-pong between.
*/
- __u8 *tsn_map;
-
- /* This marks the tsn which overflows the tsn_map, when the
- * cumulative ack point reaches this point we know we can switch
- * maps (tsn_map and overflow_map swap).
- */
- __u32 overflow_tsn;
-
- /* This is the overflow array for tsn_map.
- * It points at one of the other ping-pong buffers.
- */
- __u8 *overflow_map;
+ unsigned long *tsn_map;
/* This is the TSN at tsn_map[0]. */
__u32 base_tsn;
@@ -89,15 +78,15 @@ struct sctp_tsnmap {
*/
__u32 cumulative_tsn_ack_point;
+ /* This is the highest TSN we've marked. */
+ __u32 max_tsn_seen;
+
/* This is the minimum number of TSNs we can track. This corresponds
* to the size of tsn_map. Note: the overflow_map allows us to
* potentially track more than this quantity.
*/
__u16 len;
- /* This is the highest TSN we've marked. */
- __u32 max_tsn_seen;
-
/* Data chunks pending receipt. used by SCTP_STATUS sockopt */
__u16 pending_data;
@@ -110,24 +99,17 @@ struct sctp_tsnmap {
/* Record gap ack block information here. */
struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
-
- int malloced;
-
- __u8 raw_map[0];
};
struct sctp_tsnmap_iter {
__u32 start;
};
-/* This macro assists in creation of external storage for variable length
- * internal buffers. We double allocate so the overflow map works.
- */
-#define sctp_tsnmap_storage_size(count) (sizeof(__u8) * (count) * 2)
-
/* Initialize a block of memory as a tsnmap. */
struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *, __u16 len,
- __u32 initial_tsn);
+ __u32 initial_tsn, gfp_t gfp);
+
+void sctp_tsnmap_free(struct sctp_tsnmap *map);
/* Test the tracking state of this TSN.
* Returns:
@@ -138,7 +120,7 @@ struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *, __u16 len,
int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
/* Mark this TSN as seen. */
-void sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
+int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
/* Mark this TSN and all lower as seen. */
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
/* Is there a gap in the TSN map? */
static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
{
- int has_gap;
-
- has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen);
- return has_gap;
+ return (map->cumulative_tsn_ack_point != map->max_tsn_seen);
}
/* Mark a duplicate TSN. Note: limit the storage of duplicate TSN