Commit 3d34635b authored by Jon Grimm's avatar Jon Grimm

[SCTP] Minor cleanup on tsnmap.

Move duplicate TSN tracking into tsnmap.  Remove typdefs for 
sctp_tsnmap_t and sctp_tsnamp_iter_t. 
parent def47680
......@@ -1291,19 +1291,11 @@ struct sctp_association {
* used in the bulk of the text. This value is hidden
* in tsn_map--we get it by calling sctp_tsnmap_get_ctsn().
*/
sctp_tsnmap_t tsn_map;
struct sctp_tsnmap tsn_map;
__u8 _map[sctp_tsnmap_storage_size(SCTP_TSN_MAP_SIZE)];
/* We record duplicate TSNs here. We clear this after
* every SACK.
* FIXME: We should move this into the tsnmap? --jgrimm
*/
sctp_dup_tsn_t dup_tsns[SCTP_MAX_DUP_TSNS];
int next_dup_tsn;
/* Do we need to sack the peer? */
uint8_t sack_needed;
__u8 sack_needed;
/* These are capabilities which our peer advertised. */
__u8 ecn_capable; /* Can peer do ECN? */
__u8 ipv4_address; /* Peer understands IPv4 addresses? */
......
......@@ -38,8 +38,6 @@
#ifndef __sctp_tsnmap_h__
#define __sctp_tsnmap_h__
/* RFC 2960 12.2 Parameters necessary per association (i.e. the TCB)
* Mapping An array of bits or bytes indicating which out of
* Array order TSN's have been received (relative to the
......@@ -48,9 +46,7 @@
* will be set to all zero. This structure may be
* in the form of a circular buffer or bit array.
*/
typedef struct sctp_tsnmap {
struct sctp_tsnmap {
/* This array counts the number of chunks with each TSN.
* It points at one of the two buffers with which we will
* ping-pong between.
......@@ -93,25 +89,30 @@ typedef struct sctp_tsnmap {
/* This is the highest TSN we've marked. */
__u32 max_tsn_seen;
/* No. of data chunks pending receipt. used by SCTP_STATUS sockopt */
/* Data chunks pending receipt. used by SCTP_STATUS sockopt */
__u16 pending_data;
/* We record duplicate TSNs here. We clear this after
* every SACK. Store up to SCTP_MAX_DUP_TSNS worth of
* information.
*/
__u32 dup_tsns[SCTP_MAX_DUP_TSNS];
__u16 num_dup_tsns;
int malloced;
__u8 raw_map[0];
} sctp_tsnmap_t;
};
typedef struct sctp_tsnmap_iter {
struct sctp_tsnmap_iter {
__u32 start;
} sctp_tsnmap_iter_t;
};
/* Create a new tsnmap. */
sctp_tsnmap_t *sctp_tsnmap_new(__u16 len, __u32 initial_tsn,
int priority);
struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 init_tsn, int priority);
/* Dispose of a tsnmap. */
void sctp_tsnmap_free(sctp_tsnmap_t *map);
void sctp_tsnmap_free(struct sctp_tsnmap *);
/* This macro assists in creation of external storage for variable length
* internal buffers. We double allocate so the overflow map works.
......@@ -119,9 +120,8 @@ void sctp_tsnmap_free(sctp_tsnmap_t *map);
#define sctp_tsnmap_storage_size(count) (sizeof(__u8) * (count) * 2)
/* Initialize a block of memory as a tsnmap. */
sctp_tsnmap_t *sctp_tsnmap_init(sctp_tsnmap_t *map, __u16 len, __u32 initial_tsn);
struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *, __u16 len,
__u32 initial_tsn);
/* Test the tracking state of this TSN.
* Returns:
......@@ -129,29 +129,51 @@ sctp_tsnmap_t *sctp_tsnmap_init(sctp_tsnmap_t *map, __u16 len, __u32 initial_tsn
* >0 if the TSN has been seen (duplicate)
* <0 if the TSN is invalid (too large to track)
*/
int sctp_tsnmap_check(const sctp_tsnmap_t *map, __u32 tsn);
int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
/* Mark this TSN as seen. */
void sctp_tsnmap_mark(sctp_tsnmap_t *map, __u32 tsn);
void sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
/* Retrieve the Cumulative TSN ACK Point. */
__u32 sctp_tsnmap_get_ctsn(const sctp_tsnmap_t *map);
__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *);
/* Retrieve the highest TSN we've seen. */
__u32 sctp_tsnmap_get_max_tsn_seen(const sctp_tsnmap_t *map);
__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *);
/* How many Duplicate TSNs are stored? */
static inline __u16 sctp_tsnmap_num_dups(struct sctp_tsnmap *map)
{
return map->num_dup_tsns;
}
/* Return pointer to duplicate tsn array as needed by SACK. */
static inline __u32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
{
map->num_dup_tsns = 0;
return map->dup_tsns;
}
/* Mark a duplicate TSN. Note: we limit how many we are willing to
* store and consequently report.
*/
static inline void sctp_tsnmap_mark_dup(struct sctp_tsnmap *map, __u32 tsn)
{
if (map->num_dup_tsns < SCTP_MAX_DUP_TSNS)
map->dup_tsns[map->num_dup_tsns++] = tsn;
}
/* Is there a gap in the TSN map? */
int sctp_tsnmap_has_gap(const sctp_tsnmap_t *map);
int sctp_tsnmap_has_gap(const struct sctp_tsnmap *);
/* Initialize a gap ack block interator from user-provided memory. */
void sctp_tsnmap_iter_init(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter);
void sctp_tsnmap_iter_init(const struct sctp_tsnmap *,
struct sctp_tsnmap_iter *);
/* Get the next gap ack blocks. We return 0 if there are no more
* gap ack blocks.
*/
int sctp_tsnmap_next_gap_ack(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter,
__u16 *start, __u16 *end);
int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *,
struct sctp_tsnmap_iter *,__u16 *start, __u16 *end);
#endif /* __sctp_tsnmap_h__ */
......
......@@ -260,7 +260,6 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
/* Set up the tsn tracking. */
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, 0);
asoc->peer.next_dup_tsn = 0;
skb_queue_head_init(&asoc->addip_chunks);
......@@ -848,7 +847,6 @@ void sctp_assoc_update(sctp_association_t *asoc, sctp_association_t *new)
/* Copy in new parameters of peer. */
asoc->c = new->c;
asoc->peer.rwnd = new->peer.rwnd;
asoc->peer.next_dup_tsn = new->peer.next_dup_tsn;
asoc->peer.sack_needed = new->peer.sack_needed;
asoc->peer.i = new->peer.i;
sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE,
......@@ -990,9 +988,9 @@ void sctp_assoc_rwnd_increase(sctp_association_t *asoc, int len)
asoc->rwnd += len;
}
SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) - %u\n",
__FUNCTION__, asoc, len, asoc->rwnd, asoc->rwnd_over,
asoc->a_rwnd);
SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) "
"- %u\n", __FUNCTION__, asoc, len, asoc->rwnd,
asoc->rwnd_over, asoc->a_rwnd);
/* Send a window update SACK if the rwnd has increased by at least the
* minimum of the association's PMTU and half of the receive buffer.
......@@ -1014,7 +1012,6 @@ void sctp_assoc_rwnd_increase(sctp_association_t *asoc, int len)
asoc->a_rwnd = asoc->rwnd;
asoc->peer.sack_needed = 0;
asoc->peer.next_dup_tsn = 0;
sctp_outq_tail(&asoc->outqueue, sack);
......
......@@ -222,9 +222,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &sat_param);
sctp_addto_chunk(retval, sizeof(sat_addr_types), sat_addr_types);
sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
nodata:
if (addrs.v)
kfree(addrs.v);
......@@ -587,14 +585,12 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
sctp_gap_ack_block_t gab;
int length;
__u32 ctsn;
sctp_tsnmap_iter_t iter;
__u16 num_gabs;
__u16 num_dup_tsns = asoc->peer.next_dup_tsn;
const sctp_tsnmap_t *map = &asoc->peer.tsn_map;
struct sctp_tsnmap_iter iter;
__u16 num_gabs, num_dup_tsns;
struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
ctsn = sctp_tsnmap_get_ctsn(map);
SCTP_DEBUG_PRINTK("make_sack: sackCTSNAck sent is 0x%x.\n",
ctsn);
SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn);
/* Count the number of Gap Ack Blocks. */
sctp_tsnmap_iter_init(map, &iter);
......@@ -604,6 +600,8 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
/* Do nothing. */
}
num_dup_tsns = sctp_tsnmap_num_dups(map);
/* Initialize the SACK header. */
sack.cum_tsn_ack = htonl(ctsn);
sack.a_rwnd = htonl(asoc->rwnd);
......@@ -612,7 +610,7 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
length = sizeof(sack)
+ sizeof(sctp_gap_ack_block_t) * num_gabs
+ sizeof(sctp_dup_tsn_t) * num_dup_tsns;
+ sizeof(__u32) * num_dup_tsns;
/* Create the chunk. */
retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, length);
......@@ -659,21 +657,18 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
while(sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end)) {
gab.start = htons(gab.start);
gab.end = htons(gab.end);
sctp_addto_chunk(retval,
sizeof(sctp_gap_ack_block_t),
&gab);
sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t), &gab);
}
/* Register the duplicates. */
sctp_addto_chunk(retval,
sizeof(sctp_dup_tsn_t) * num_dup_tsns,
&asoc->peer.dup_tsns);
sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
sctp_tsnmap_get_dups(map));
nodata:
return retval;
}
/* FIXME: Comments. */
/* Make a SHUTDOWN chunk. */
sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc)
{
sctp_chunk_t *retval;
......@@ -690,7 +685,6 @@ sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc)
retval->subh.shutdown_hdr =
sctp_addto_chunk(retval, sizeof(shut), &shut);
nodata:
return retval;
}
......
......@@ -527,10 +527,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break;
case SCTP_CMD_REPORT_DUP:
if (asoc->peer.next_dup_tsn < SCTP_MAX_DUP_TSNS) {
asoc->peer.dup_tsns[asoc->peer.next_dup_tsn++] =
ntohl(command->obj.u32);
}
sctp_tsnmap_mark_dup(&asoc->peer.tsn_map,
ntohl(command->obj.u32));
break;
case SCTP_CMD_REPORT_BIGGAP:
......@@ -744,7 +742,6 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands)
asoc->a_rwnd = asoc->rwnd;
asoc->peer.sack_needed = 0;
asoc->peer.next_dup_tsn = 0;
error = sctp_outq_tail(&asoc->outqueue, sack);
......
......@@ -4295,6 +4295,9 @@ sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *chunk)
__u16 num_blocks;
__u16 num_dup_tsns;
/* FIXME: Protect ourselves from reading too far into
* the skb from a bogus sender.
*/
sack = (sctp_sackhdr_t *) chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_sackhdr_t));
......
......@@ -45,9 +45,9 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static void _sctp_tsnmap_update(sctp_tsnmap_t *map);
static void _sctp_tsnmap_update_pending_data(sctp_tsnmap_t *map);
static void _sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
static void sctp_tsnmap_update(struct sctp_tsnmap *map);
static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map);
static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
__u16 len, __u16 base,
int *started, __u16 *start,
int *ended, __u16 *end);
......@@ -55,11 +55,11 @@ static void _sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
/* Create a new sctp_tsnmap.
* Allocate room to store at least 'len' contiguous TSNs.
*/
sctp_tsnmap_t *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int priority)
struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int priority)
{
sctp_tsnmap_t *retval;
struct sctp_tsnmap *retval;
retval = kmalloc(sizeof(sctp_tsnmap_t) +
retval = kmalloc(sizeof(struct sctp_tsnmap) +
sctp_tsnmap_storage_size(len),
priority);
if (!retval)
......@@ -72,13 +72,13 @@ sctp_tsnmap_t *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int priority)
fail_map:
kfree(retval);
fail:
return NULL;
}
/* Initialize a block of memory as a tsnmap. */
sctp_tsnmap_t *sctp_tsnmap_init(sctp_tsnmap_t *map, __u16 len, __u32 initial_tsn)
struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len,
__u32 initial_tsn)
{
map->tsn_map = map->raw_map;
map->overflow_map = map->tsn_map + len;
......@@ -94,6 +94,7 @@ sctp_tsnmap_t *sctp_tsnmap_init(sctp_tsnmap_t *map, __u16 len, __u32 initial_tsn
map->max_tsn_seen = map->cumulative_tsn_ack_point;
map->malloced = 0;
map->pending_data = 0;
map->num_dup_tsns = 0;
return map;
}
......@@ -104,7 +105,7 @@ sctp_tsnmap_t *sctp_tsnmap_init(sctp_tsnmap_t *map, __u16 len, __u32 initial_tsn
* >0 if the TSN has been seen (duplicate)
* <0 if the TSN is invalid (too large to track)
*/
int sctp_tsnmap_check(const sctp_tsnmap_t *map, __u32 tsn)
int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
{
__s32 gap;
int dup;
......@@ -136,7 +137,7 @@ int sctp_tsnmap_check(const sctp_tsnmap_t *map, __u32 tsn)
}
/* Is there a gap in the TSN map? */
int sctp_tsnmap_has_gap(const sctp_tsnmap_t *map)
int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
{
int has_gap;
......@@ -145,7 +146,7 @@ int sctp_tsnmap_has_gap(const sctp_tsnmap_t *map)
}
/* Mark this TSN as seen. */
void sctp_tsnmap_mark(sctp_tsnmap_t *map, __u32 tsn)
void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
{
__s32 gap;
......@@ -173,40 +174,45 @@ void sctp_tsnmap_mark(sctp_tsnmap_t *map, __u32 tsn)
/* Go fixup any internal TSN mapping variables including
* cumulative_tsn_ack_point.
*/
_sctp_tsnmap_update(map);
sctp_tsnmap_update(map);
}
void sctp_tsnmap_report_dup(struct sctp_tsnmap *map, __u32 tsn)
{
}
/* Retrieve the Cumulative TSN Ack Point. */
__u32 sctp_tsnmap_get_ctsn(const sctp_tsnmap_t *map)
__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map)
{
return map->cumulative_tsn_ack_point;
}
/* Retrieve the highest TSN we've seen. */
__u32 sctp_tsnmap_get_max_tsn_seen(const sctp_tsnmap_t *map)
__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map)
{
return map->max_tsn_seen;
}
/* Dispose of a tsnmap. */
void sctp_tsnmap_free(sctp_tsnmap_t *map)
void sctp_tsnmap_free(struct sctp_tsnmap *map)
{
if (map->malloced)
kfree(map);
}
/* Initialize a Gap Ack Block iterator from memory being provided. */
void sctp_tsnmap_iter_init(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter)
void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
struct sctp_tsnmap_iter *iter)
{
/* Only start looking one past the Cumulative TSN Ack Point. */
iter->start = map->cumulative_tsn_ack_point + 1;
}
/* Get the next Gap Ack Blocks. Returns 0 if there was not
* another block to get.
/* Get the next Gap Ack Blocks. Returns 0 if there was not another block
* to get.
*/
int sctp_tsnmap_next_gap_ack(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter,
__u16 *start, __u16 *end)
int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
struct sctp_tsnmap_iter *iter, __u16 *start, __u16 *end)
{
int started, ended;
__u16 _start, _end, offset;
......@@ -216,12 +222,10 @@ int sctp_tsnmap_next_gap_ack(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter,
/* Search the first mapping array. */
if (iter->start - map->base_tsn < map->len) {
offset = iter->start - map->base_tsn;
_sctp_tsnmap_find_gap_ack(map->tsn_map,
offset,
map->len, 0,
&started, &_start,
&ended, &_end);
sctp_tsnmap_find_gap_ack(map->tsn_map, offset, map->len, 0,
&started, &_start, &ended, &_end);
}
/* Do we need to check the overflow map? */
......@@ -235,7 +239,7 @@ int sctp_tsnmap_next_gap_ack(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter,
offset = iter->start - map->base_tsn - map->len;
/* Search the overflow map. */
_sctp_tsnmap_find_gap_ack(map->overflow_map,
sctp_tsnmap_find_gap_ack(map->overflow_map,
offset,
map->len,
map->len,
......@@ -278,7 +282,7 @@ int sctp_tsnmap_next_gap_ack(const sctp_tsnmap_t *map, sctp_tsnmap_iter_t *iter,
/* This private helper function updates the tsnmap buffers and
* the Cumulative TSN Ack Point.
*/
static void _sctp_tsnmap_update(sctp_tsnmap_t *map)
static void sctp_tsnmap_update(struct sctp_tsnmap *map)
{
__u32 ctsn;
......@@ -301,10 +305,10 @@ static void _sctp_tsnmap_update(sctp_tsnmap_t *map)
} while (map->tsn_map[ctsn - map->base_tsn]);
map->cumulative_tsn_ack_point = ctsn - 1; /* Back up one. */
_sctp_tsnmap_update_pending_data(map);
sctp_tsnmap_update_pending_data(map);
}
static void _sctp_tsnmap_update_pending_data(sctp_tsnmap_t *map)
static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map)
{
__u32 cum_tsn = map->cumulative_tsn_ack_point;
__u32 max_tsn = map->max_tsn_seen;
......@@ -345,14 +349,14 @@ static void _sctp_tsnmap_update_pending_data(sctp_tsnmap_t *map)
* The flags "started" and "ended" tell is if we found the beginning
* or (respectively) the end of a Gap Ack Block.
*/
static void _sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
__u16 len, __u16 base,
int *started, __u16 *start,
int *ended, __u16 *end)
{
int i = off;
/* Let's look through the entire array, but break out
/* Look through the entire array, but break out
* early if we have found the end of the Gap Ack Block.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment