Skip to content
Snippets Groups Projects
Commit de587f3f authored by Aomx's avatar Aomx
Browse files

first commit regarding support of forward-tsn-chunk

parent 0ce7bc43
No related branches found
No related tags found
No related merge requests found
......@@ -555,6 +555,7 @@ SHUTDOWN_COMPLETE return SHUTDOWN_COMPLETE;
I-DATA return I_DATA;
PAD return PAD;
RECONFIG return RECONFIG;
FORWARD_TSN return FORWARD_TSN;
type return TYPE;
flgs return FLAGS;
len return LEN;
......
......@@ -472,6 +472,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
struct sctp_u16_list_item *u16_item;
struct sctp_sack_block_list_item *sack_block_list_item;
struct sctp_sack_block_list *sack_block_list;
struct sctp_forward_tsn_sids_list *forward_tsn_sids_list;
struct sctp_forward_tsn_sids_list_item *forward_tsn_sids_list_item;
struct sctp_address_type_list_item *address_type_list_item;
struct sctp_address_type_list *address_type_list;
struct sctp_parameter_type_list_item *parameter_type_list_item;
......@@ -519,7 +521,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%token <reserved> SPINFO_MTU GAUTH_ASSOC_ID GAUTH_NUMBER_OF_CHUNKS GAUTH_CHUNKS
%token <reserved> CHUNK DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT
%token <reserved> SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECNE CWR
%token <reserved> SHUTDOWN_COMPLETE I_DATA PAD RECONFIG
%token <reserved> SHUTDOWN_COMPLETE I_DATA PAD RECONFIG FORWARD_TSN
%token <reserved> TYPE FLAGS LEN
%token <reserved> TAG A_RWND OS IS TSN SID SSN MID PPID FSN CUM_TSN GAPS DUPS
%token <reserved> PARAMETER HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS
......@@ -675,6 +677,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%type <chunk_list_item> sctp_shutdown_complete_chunk_spec
%type <chunk_list_item> sctp_i_data_chunk_spec
%type <chunk_list_item> sctp_pad_chunk_spec sctp_reconfig_chunk_spec
%type <chunk_list_item> sctp_forward_tsn_spec
%type <parameter_list> opt_parameter_list_spec sctp_parameter_list_spec
%type <parameter_list_item> sctp_parameter_spec
%type <parameter_list_item> sctp_generic_parameter_spec
......@@ -722,6 +725,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%type <u16_item> u16_item
%type <sack_block_list> opt_gaps gap_list opt_dups dup_list
%type <sack_block_list_item> gap dup
%type <forward_tsn_sids_list> opt_stream_identifier sids_list
%type <forward_tsn_sids_list_item> sid
%type <address_type_list> address_types_list
%type <address_type_list_item> address_type
%type <parameter_type_list> parameter_types_list
......@@ -1053,6 +1058,7 @@ sctp_chunk_spec
| sctp_i_data_chunk_spec { $$ = $1; }
| sctp_pad_chunk_spec { $$ = $1; }
| sctp_reconfig_chunk_spec { $$ = $1; }
| sctp_forward_tsn_spec { $$ = $1; }
;
chunk_type
......@@ -1122,6 +1128,9 @@ chunk_type
| RECONFIG {
$$ = SCTP_RECONFIG_CHUNK_TYPE;
}
| FORWARD_TSN {
$$ = SCTP_FORWARD_TSN_CHUNK_TYPE;
}
;
opt_chunk_type
......@@ -1564,6 +1573,31 @@ dup
}
;
opt_stream_identifier
: SIDS '=' ELLIPSIS { $$ = NULL; }
| SIDS '=' '[' ELLIPSIS ']' { $$ = NULL; }
| SIDS '=' '[' sids_list ']' { $$ = $4; }
;
sids_list
: { $$ = sctp_forward_tsn_sids_list_new(); }
| sid { $$ =sctp_forward_tsn_sids_list_new();
sctp_forward_tsn_sids_list_append($$, $1); }
| sids_list ',' sid { $$ = $1;
sctp_forward_tsn_sids_list_append($1, $3); }
;
sid: INTEGER ':' INTEGER {
if (!is_valid_u16($1)) {
semantic_error("stream identifier out of range");
}
if (!is_valid_u16($3)) {
semantic_error("stream sequence number out of range");
}
$$ = sctp_forward_tsn_sids_list_item_new($1, $3);
}
;
sctp_generic_chunk_spec
: CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_len ',' opt_val ']' {
if (($7 != -1) &&
......@@ -1695,6 +1729,11 @@ sctp_pad_chunk_spec
$$ = sctp_pad_chunk_new($3, $5, NULL);
}
sctp_forward_tsn_spec
: FORWARD_TSN '[' opt_cum_tsn ',' opt_stream_identifier']' {
$$ = sctp_forward_tsn_chunk_new($3, $5);
}
opt_req_sn
: REQ_SN '=' INTEGER {
if (!is_valid_u32($3)) {
......
......@@ -55,6 +55,7 @@ struct sctp_common_header {
#define SCTP_I_DATA_CHUNK_TYPE 0x40
#define SCTP_RECONFIG_CHUNK_TYPE 0x82
#define SCTP_PAD_CHUNK_TYPE 0x84
#define SCTP_FORWARD_TSN_CHUNK_TYPE 0xc0
#define MAX_SCTP_CHUNK_BYTES 0xffff
......@@ -241,6 +242,19 @@ struct sctp_reconfig_chunk {
__u8 parameter[];
} __packed;
struct sctp_stream_identifier_block {
__u16 stream;
__u16 stream_sequence;
} __packed;
struct sctp_forward_tsn_chunk {
__u8 type;
__u8 flags;
__be16 length;
__be32 cum_tsn;
struct sctp_stream_identifier_block stream_identifier_blocks[];
} __packed;
#define SCTP_HEARTBEAT_INFORMATION_PARAMETER_TYPE 0x0001
#define SCTP_IPV4_ADDRESS_PARAMETER_TYPE 0x0005
#define SCTP_IPV6_ADDRESS_PARAMETER_TYPE 0x0006
......
......@@ -234,6 +234,65 @@ sctp_sack_block_list_item_dup_new(u32 tsn)
return item;
}
struct sctp_forward_tsn_sids_list *
sctp_forward_tsn_sids_list_new () {
struct sctp_forward_tsn_sids_list *list;
list = malloc(sizeof(struct sctp_forward_tsn_sids_list));
assert(list != NULL);
list->first = NULL;
list->last = NULL;
list->nr_entries = 0;
return list;
}
void
sctp_forward_tsn_sids_list_append(struct sctp_forward_tsn_sids_list *list,
struct sctp_forward_tsn_sids_list_item *item) {
assert(item->next == NULL);
if (list->last == NULL) {
assert(list->first == NULL);
assert(list->nr_entries == 0);
list->first = item;
} else {
assert(list->first != NULL);
list->last->next = item;
}
list->last = item;
list->nr_entries++;
}
void sctp_forward_tsn_sids_list_free (struct sctp_forward_tsn_sids_list *list) {
struct sctp_forward_tsn_sids_list_item *current_item, *next_item;
if (list == NULL) {
return;
}
current_item = list->first;
while (current_item != NULL) {
assert(list->nr_entries > 0);
next_item = current_item->next;
assert(next_item != NULL || current_item == list->last);
free(current_item);
current_item = next_item;
list->nr_entries--;
}
assert(list->nr_entries == 0);
free(list);
}
struct sctp_forward_tsn_sids_list_item *
sctp_forward_tsn_sids_list_item_new(u16 stream_identifier, u16 stream_sequence_number) {
struct sctp_forward_tsn_sids_list_item *item;
item = malloc(sizeof(struct sctp_forward_tsn_sids_list_item));
assert(item != NULL);
item->next = NULL;
item->stream_identifier = stream_identifier;
item->stream_sequence_number= stream_sequence_number;
return item;
}
struct sctp_address_type_list *
sctp_address_type_list_new(void)
{
......@@ -1283,6 +1342,62 @@ sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding)
sctp_cause_list_new());
}
struct sctp_chunk_list_item *
sctp_forward_tsn_chunk_new(u32 cum_tsn, struct sctp_forward_tsn_sids_list *sids) {
struct sctp_forward_tsn_chunk *chunk;
struct sctp_forward_tsn_sids_list_item *item;
DEBUGP("sctp_forward_tsn_chunk_new called with cum_tsn = %d and sids_list = %p", cum_tsn, sids);
u32 flags;
u32 length;
u16 i, nr_sids;
flags = 0;
length = sizeof(struct sctp_forward_tsn_chunk);
if (sids == NULL) {
nr_sids = 0;
flags |= FLAG_CHUNK_LENGTH_NOCHECK;
flags |= FLAG_FORWARD_TSN_CHUNK_SIDS_NOCHECK;
} else {
nr_sids = sids->nr_entries;
length += nr_sids * sizeof(struct sctp_stream_identifier_block);
}
assert(is_valid_u16(length));
assert(length % 4 == 0);
chunk = malloc(length);
assert(chunk != NULL);
chunk->type = SCTP_FORWARD_TSN_CHUNK_TYPE;
chunk->flags = 0;
chunk->length = htons(length);
if (cum_tsn == -1) {
chunk->cum_tsn = htonl(0);
flags |= FLAG_FORWARD_TSN_CHUNK_CUM_TSN_NOCHECK;
} else {
chunk->cum_tsn = htonl((u32)cum_tsn);
}
if (nr_sids == 0 || sids == NULL) {
flags |= FLAG_FORWARD_TSN_CHUNK_SIDS_NOCHECK;
}
if (sids != NULL) {
for (i = 0, item = sids->first;
(i < nr_sids) && (item != NULL);
i++, item = item->next) {
chunk->stream_identifier_blocks[i].stream= htons(item->stream_identifier);
chunk->stream_identifier_blocks[i].stream_sequence = htons(item->stream_sequence_number);
}
assert((i == nr_sids) && (item == NULL));
}
return sctp_chunk_list_item_new((struct sctp_chunk *)chunk,
length, flags,
sctp_parameter_list_new(),
sctp_cause_list_new());
}
struct sctp_chunk_list_item *
sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters)
{
......@@ -2966,6 +3081,19 @@ new_sctp_packet(int address_family,
break;
case SCTP_RECONFIG_CHUNK_TYPE:
break;
case SCTP_FORWARD_TSN_CHUNK_TYPE:
if (chunk_item->flags & FLAG_FORWARD_TSN_CHUNK_CUM_TSN_NOCHECK) {
asprintf(error,
"cum tsn must be specified for inbound packets");
return NULL;
}
if (chunk_item->flags & FLAG_FORWARD_TSN_CHUNK_SIDS_NOCHECK) {
// TODO: is this true or are FORWARD-TSN-Chunks that only contain the new cum tsn valid?
asprintf(error,
"at least one stream number and stream sequence number must be specified for inbound packets");
return NULL;
}
break;
default:
if (chunk_item->flags & FLAG_CHUNK_TYPE_NOCHECK) {
asprintf(error,
......
......@@ -104,6 +104,31 @@ sctp_sack_block_list_item_gap_new(u16 start, u16 end);
struct sctp_sack_block_list_item *
sctp_sack_block_list_item_dup_new(u32 tsn);
struct sctp_forward_tsn_sids_list_item {
struct sctp_forward_tsn_sids_list_item *next;
u16 stream_identifier;
u16 stream_sequence_number;
};
struct sctp_forward_tsn_sids_list {
struct sctp_forward_tsn_sids_list_item *first;
struct sctp_forward_tsn_sids_list_item *last;
u16 nr_entries;
};
struct sctp_forward_tsn_sids_list *
sctp_forward_tsn_sids_list_new ();
void
sctp_forward_tsn_sids_list_append(struct sctp_forward_tsn_sids_list *list,
struct sctp_forward_tsn_sids_list_item *item);
void sctp_forward_tsn_sids_list_free (struct sctp_forward_tsn_sids_list *list);
struct sctp_forward_tsn_sids_list_item *
sctp_forward_tsn_sids_list_item_new(u16 stream_identifier, u16 stream_sequence_number);
struct sctp_address_type_list_item {
struct sctp_address_type_list_item *next;
u16 address_type;
......@@ -313,6 +338,12 @@ sctp_i_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 res, s64 mid,
struct sctp_chunk_list_item *
sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding);
#define FLAG_FORWARD_TSN_CHUNK_CUM_TSN_NOCHECK 0x00000100
#define FLAG_FORWARD_TSN_CHUNK_SIDS_NOCHECK 0x00000200
struct sctp_chunk_list_item *
sctp_forward_tsn_chunk_new(u32 cum_tsn, struct sctp_forward_tsn_sids_list *sids_list);
struct sctp_chunk_list_item *
sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment