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; ...@@ -555,6 +555,7 @@ SHUTDOWN_COMPLETE return SHUTDOWN_COMPLETE;
I-DATA return I_DATA; I-DATA return I_DATA;
PAD return PAD; PAD return PAD;
RECONFIG return RECONFIG; RECONFIG return RECONFIG;
FORWARD_TSN return FORWARD_TSN;
type return TYPE; type return TYPE;
flgs return FLAGS; flgs return FLAGS;
len return LEN; len return LEN;
......
...@@ -472,6 +472,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, ...@@ -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_u16_list_item *u16_item;
struct sctp_sack_block_list_item *sack_block_list_item; struct sctp_sack_block_list_item *sack_block_list_item;
struct sctp_sack_block_list *sack_block_list; 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_item *address_type_list_item;
struct sctp_address_type_list *address_type_list; struct sctp_address_type_list *address_type_list;
struct sctp_parameter_type_list_item *parameter_type_list_item; 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, ...@@ -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> SPINFO_MTU GAUTH_ASSOC_ID GAUTH_NUMBER_OF_CHUNKS GAUTH_CHUNKS
%token <reserved> CHUNK DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT %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 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> TYPE FLAGS LEN
%token <reserved> TAG A_RWND OS IS TSN SID SSN MID PPID FSN CUM_TSN GAPS DUPS %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 %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, ...@@ -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_shutdown_complete_chunk_spec
%type <chunk_list_item> sctp_i_data_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_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> opt_parameter_list_spec sctp_parameter_list_spec
%type <parameter_list_item> sctp_parameter_spec %type <parameter_list_item> sctp_parameter_spec
%type <parameter_list_item> sctp_generic_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, ...@@ -722,6 +725,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%type <u16_item> u16_item %type <u16_item> u16_item
%type <sack_block_list> opt_gaps gap_list opt_dups dup_list %type <sack_block_list> opt_gaps gap_list opt_dups dup_list
%type <sack_block_list_item> gap dup %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> address_types_list
%type <address_type_list_item> address_type %type <address_type_list_item> address_type
%type <parameter_type_list> parameter_types_list %type <parameter_type_list> parameter_types_list
...@@ -1053,6 +1058,7 @@ sctp_chunk_spec ...@@ -1053,6 +1058,7 @@ sctp_chunk_spec
| sctp_i_data_chunk_spec { $$ = $1; } | sctp_i_data_chunk_spec { $$ = $1; }
| sctp_pad_chunk_spec { $$ = $1; } | sctp_pad_chunk_spec { $$ = $1; }
| sctp_reconfig_chunk_spec { $$ = $1; } | sctp_reconfig_chunk_spec { $$ = $1; }
| sctp_forward_tsn_spec { $$ = $1; }
; ;
chunk_type chunk_type
...@@ -1122,6 +1128,9 @@ chunk_type ...@@ -1122,6 +1128,9 @@ chunk_type
| RECONFIG { | RECONFIG {
$$ = SCTP_RECONFIG_CHUNK_TYPE; $$ = SCTP_RECONFIG_CHUNK_TYPE;
} }
| FORWARD_TSN {
$$ = SCTP_FORWARD_TSN_CHUNK_TYPE;
}
; ;
opt_chunk_type opt_chunk_type
...@@ -1564,6 +1573,31 @@ dup ...@@ -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 sctp_generic_chunk_spec
: CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_len ',' opt_val ']' { : CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_len ',' opt_val ']' {
if (($7 != -1) && if (($7 != -1) &&
...@@ -1695,6 +1729,11 @@ sctp_pad_chunk_spec ...@@ -1695,6 +1729,11 @@ sctp_pad_chunk_spec
$$ = sctp_pad_chunk_new($3, $5, NULL); $$ = 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 opt_req_sn
: REQ_SN '=' INTEGER { : REQ_SN '=' INTEGER {
if (!is_valid_u32($3)) { if (!is_valid_u32($3)) {
......
...@@ -55,6 +55,7 @@ struct sctp_common_header { ...@@ -55,6 +55,7 @@ struct sctp_common_header {
#define SCTP_I_DATA_CHUNK_TYPE 0x40 #define SCTP_I_DATA_CHUNK_TYPE 0x40
#define SCTP_RECONFIG_CHUNK_TYPE 0x82 #define SCTP_RECONFIG_CHUNK_TYPE 0x82
#define SCTP_PAD_CHUNK_TYPE 0x84 #define SCTP_PAD_CHUNK_TYPE 0x84
#define SCTP_FORWARD_TSN_CHUNK_TYPE 0xc0
#define MAX_SCTP_CHUNK_BYTES 0xffff #define MAX_SCTP_CHUNK_BYTES 0xffff
...@@ -241,6 +242,19 @@ struct sctp_reconfig_chunk { ...@@ -241,6 +242,19 @@ struct sctp_reconfig_chunk {
__u8 parameter[]; __u8 parameter[];
} __packed; } __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_HEARTBEAT_INFORMATION_PARAMETER_TYPE 0x0001
#define SCTP_IPV4_ADDRESS_PARAMETER_TYPE 0x0005 #define SCTP_IPV4_ADDRESS_PARAMETER_TYPE 0x0005
#define SCTP_IPV6_ADDRESS_PARAMETER_TYPE 0x0006 #define SCTP_IPV6_ADDRESS_PARAMETER_TYPE 0x0006
......
...@@ -234,6 +234,65 @@ sctp_sack_block_list_item_dup_new(u32 tsn) ...@@ -234,6 +234,65 @@ sctp_sack_block_list_item_dup_new(u32 tsn)
return item; 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 * struct sctp_address_type_list *
sctp_address_type_list_new(void) sctp_address_type_list_new(void)
{ {
...@@ -1283,6 +1342,62 @@ sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding) ...@@ -1283,6 +1342,62 @@ sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding)
sctp_cause_list_new()); 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 * struct sctp_chunk_list_item *
sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters) sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters)
{ {
...@@ -2966,6 +3081,19 @@ new_sctp_packet(int address_family, ...@@ -2966,6 +3081,19 @@ new_sctp_packet(int address_family,
break; break;
case SCTP_RECONFIG_CHUNK_TYPE: case SCTP_RECONFIG_CHUNK_TYPE:
break; 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: default:
if (chunk_item->flags & FLAG_CHUNK_TYPE_NOCHECK) { if (chunk_item->flags & FLAG_CHUNK_TYPE_NOCHECK) {
asprintf(error, asprintf(error,
......
...@@ -104,6 +104,31 @@ sctp_sack_block_list_item_gap_new(u16 start, u16 end); ...@@ -104,6 +104,31 @@ sctp_sack_block_list_item_gap_new(u16 start, u16 end);
struct sctp_sack_block_list_item * struct sctp_sack_block_list_item *
sctp_sack_block_list_item_dup_new(u32 tsn); 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 {
struct sctp_address_type_list_item *next; struct sctp_address_type_list_item *next;
u16 address_type; u16 address_type;
...@@ -313,6 +338,12 @@ sctp_i_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 res, s64 mid, ...@@ -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 * struct sctp_chunk_list_item *
sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding); 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 * struct sctp_chunk_list_item *
sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters); 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