diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index ecf60c4d6272ff7b49e9ee95a51c6acb6fbff3c1..f24e72929634e4e18970be74bdef7f32a5630891 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -243,6 +243,7 @@ ppid			return PPID;
 cum_tsn			return CUM_TSN;
 gaps			return GAPS;
 dups			return DUPS;
+PARAMETER		return PARAMETER;
 HEARTBEAT_INFORMATION	return HEARTBEAT_INFORMATION;
 IPV4_ADDRESS		return IPV4_ADDRESS;
 IPV6_ADDRESS		return IPV6_ADDRESS;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index f11d5410da6af35adf00d938233ba777bcabf68d..d70fa7202fa2350ffba327b4c5fa5b987171bab6 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -508,9 +508,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SHUTDOWN_COMPLETE PAD
 %token <reserved> TYPE FLAGS LEN
 %token <reserved> TAG A_RWND OS IS TSN SID SSN PPID CUM_TSN GAPS DUPS
-%token <reserved> HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS STATE_COOKIE
-%token <reserved> UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE HOSTNAME_ADDRESS
-%token <reserved> SUPPORTED_ADDRESS_TYPES ECN_CAPABLE
+%token <reserved> PARAMETER HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS
+%token <reserved> STATE_COOKIE UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE
+%token <reserved> HOSTNAME_ADDRESS SUPPORTED_ADDRESS_TYPES ECN_CAPABLE
 %token <reserved> ADDR INCR TYPES PARAMS
 %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE
 %token <floating> FLOAT
@@ -568,6 +568,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <chunk_list_item> sctp_pad_chunk_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
 %type <parameter_list_item> sctp_heartbeat_information_parameter_spec
 %type <parameter_list_item> sctp_ipv4_address_parameter_spec
 %type <parameter_list_item> sctp_ipv6_address_parameter_spec
@@ -578,8 +579,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <parameter_list_item> sctp_supported_address_types_parameter_spec
 %type <parameter_list_item> sctp_ecn_capable_parameter_spec
 %type <parameter_list_item> sctp_pad_parameter_spec
-%type <integer> opt_chunk_type opt_flags opt_data_flags opt_abort_flags
-%type <integer> opt_shutdown_complete_flags opt_chunk_len
+%type <integer> opt_chunk_type opt_parameter_type
+%type <integer> opt_flags opt_data_flags opt_abort_flags
+%type <integer> opt_shutdown_complete_flags opt_len
 %type <integer> opt_tag opt_a_rwnd opt_os opt_is opt_tsn opt_sid opt_ssn
 %type <integer> opt_cum_tsn opt_ppid
 %type <byte_list> opt_val byte_list
@@ -830,13 +832,13 @@ opt_flags
 }
 ;
 
-opt_chunk_len
+opt_len
 : LEN '=' ELLIPSIS { $$ = -1; }
 | LEN '=' INTEGER  {
 	if (!is_valid_u16($3)) {
 		semantic_error("length value out of range");
-        }
-        $$ = $3;
+	}
+	$$ = $3;
 }
 ;
 
@@ -1141,7 +1143,7 @@ dup
 ;
 
 sctp_generic_chunk_spec
-: CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_chunk_len ',' opt_val ']' {
+: CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_len ',' opt_val ']' {
 	if (($7 != -1) && ($7 < sizeof(struct sctp_chunk))) {
 		semantic_error("length value out of range");
 	}
@@ -1156,7 +1158,7 @@ sctp_generic_chunk_spec
 }
 
 sctp_data_chunk_spec
-: DATA '[' opt_data_flags ',' opt_chunk_len ',' opt_tsn ',' opt_sid ',' opt_ssn ',' opt_ppid ']' {
+: DATA '[' opt_data_flags ',' opt_len ',' opt_tsn ',' opt_sid ',' opt_ssn ',' opt_ppid ']' {
 	if (($5 != -1) && ($5 < sizeof(struct sctp_data_chunk))) {
 		semantic_error("length value out of range");
 	}
@@ -1215,7 +1217,7 @@ sctp_error_chunk_spec
 }
 
 sctp_cookie_echo_chunk_spec
-: COOKIE_ECHO '[' opt_flags ',' opt_chunk_len ',' VAL '=' ELLIPSIS ']' {
+: COOKIE_ECHO '[' opt_flags ',' opt_len ',' VAL '=' ELLIPSIS ']' {
 	$$ = sctp_cookie_echo_chunk_new($3, $5, NULL);
 }
 
@@ -1240,7 +1242,7 @@ sctp_shutdown_complete_chunk_spec
 }
 
 sctp_pad_chunk_spec
-: PAD '[' opt_flags ',' opt_chunk_len ',' VAL '=' ELLIPSIS ']' {
+: PAD '[' opt_flags ',' opt_len ',' VAL '=' ELLIPSIS ']' {
 	$$ = sctp_pad_chunk_new($3, $5, NULL);
 }
 
@@ -1258,7 +1260,8 @@ sctp_parameter_list_spec
 ;
 
 sctp_parameter_spec
-: sctp_heartbeat_information_parameter_spec   { $$ = $1; }
+: sctp_generic_parameter_spec                 { $$ = $1; }
+| sctp_heartbeat_information_parameter_spec   { $$ = $1; }
 | sctp_ipv4_address_parameter_spec            { $$ = $1; }
 | sctp_ipv6_address_parameter_spec            { $$ = $1; }
 | sctp_state_cookie_parameter_spec            { $$ = $1; }
@@ -1270,6 +1273,37 @@ sctp_parameter_spec
 | sctp_pad_parameter_spec                     { $$ = $1; }
 ;
 
+opt_parameter_type
+: TYPE '=' ELLIPSIS    { $$ = -1; }
+| TYPE '=' HEX_INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("type value out of range");
+        }
+	$$ = $3;
+}
+| TYPE '=' INTEGER     {
+	if (!is_valid_u16($3)) {
+		semantic_error("type value out of range");
+        }
+	$$ = $3;
+}
+;
+
+sctp_generic_parameter_spec
+: PARAMETER '[' opt_parameter_type ',' opt_len ',' opt_val ']' {
+	if (($5 != -1) && ($5 < sizeof(struct sctp_parameter))) {
+		semantic_error("length value out of range");
+	}
+	if (($5 != -1) && ($7 != NULL) &&
+	    ($5 != sizeof(struct sctp_parameter) + $7->nr_entries)) {
+		semantic_error("length value incompatible with val");
+	}
+	if (($5 == -1) && ($7 != NULL)) {
+		semantic_error("length needs to be specified");
+	}
+	$$ = sctp_generic_parameter_new($3, $5, $7);
+}
+
 sctp_heartbeat_information_parameter_spec
 : HEARTBEAT_INFORMATION '[' ELLIPSIS ']' {
 	$$ = sctp_heartbeat_information_parameter_new(-1, NULL);
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 4ca10243af80244cca5712b36db24c188e985a72..1571702fe92de3039e037e8785ff31ae5b984b15 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -261,10 +261,10 @@ sctp_generic_chunk_new(s64 type, s64 flgs, s64 len,
 
 	flags = 0;
 	if (bytes == NULL) {
-		flags |= FLAG_CHUNK_LENGTH_NOCHECK;
 		flags |= FLAG_CHUNK_VALUE_NOCHECK;
 	}
 	if (len == -1) {
+		flags |= FLAG_CHUNK_LENGTH_NOCHECK;
 		length = (u16)sizeof(struct sctp_chunk);
 	} else {
 		length = (u16)len;
@@ -288,10 +288,6 @@ sctp_generic_chunk_new(s64 type, s64 flgs, s64 len,
 		 chunk->flags = (u8)flgs;
 	}
 	chunk->length = htons(length);
-	if (len == -1) {
-		flags |= FLAG_CHUNK_LENGTH_NOCHECK;
-		flags |= FLAG_CHUNK_VALUE_NOCHECK;
-	}
 	if (bytes != NULL) {
 		for (i = 0, item = bytes->first;
 		     item != NULL;
@@ -1055,6 +1051,52 @@ sctp_parameter_list_item_new(struct sctp_parameter *parameter, u32 length, u32 f
 	return item;
 }
 
+struct sctp_parameter_list_item *
+sctp_generic_parameter_new(s64 type, s64 len, struct sctp_byte_list *bytes)
+{
+	struct sctp_parameter *parameter;
+	struct sctp_byte_list_item *item;
+	u32 flags;
+	u16 parameter_length, value_length, padding_length, i;
+
+	flags = 0;
+	if (bytes == NULL) {
+		flags |= FLAG_CHUNK_VALUE_NOCHECK;
+	}
+	if (len == -1) {
+		parameter_length = (u16)sizeof(struct sctp_chunk);
+		flags |= FLAG_CHUNK_LENGTH_NOCHECK;
+	} else {
+		parameter_length = (u16)len;
+	}
+	value_length = parameter_length - sizeof(struct sctp_parameter);
+	padding_length = parameter_length % 4;
+	if (padding_length > 0) {
+		padding_length = 4 - padding_length;
+	}
+	parameter = malloc(parameter_length + padding_length);
+	assert(parameter != NULL);
+	if (type == -1) {
+		parameter->type = 0;
+		flags |= FLAG_CHUNK_TYPE_NOCHECK;
+	} else {
+		parameter->type = htons((u16)type);
+	}
+	parameter->length = htons(parameter_length);
+	if (bytes != NULL) {
+		for (i = 0, item = bytes->first;
+		     item != NULL;
+		     i++, item = item->next) {
+			parameter->value[i] = item->byte;
+		}
+	} else {
+		memset(parameter->value, 0, value_length);
+	}
+	/* Clear the padding */
+	memset(parameter->value + value_length, 0, padding_length);
+	return sctp_parameter_list_item_new(parameter, parameter_length, flags);
+}
+
 struct sctp_parameter_list_item *
 sctp_heartbeat_information_parameter_new(s64 len, u8 *information)
 {
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index b8cc7ef1581ec2acf22866287c4b1f6ee3eb1e5e..85a3ea626240b93893f9b897fb132ff19a2504bf 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -250,6 +250,9 @@ struct sctp_parameter_list_item *
 sctp_parameter_list_item_new(struct sctp_parameter *parameter,
                              u32 length, u32 flags);
 
+struct sctp_parameter_list_item *
+sctp_generic_parameter_new(s64 type, s64 len, struct sctp_byte_list *bytes);
+
 struct sctp_parameter_list_item *
 sctp_heartbeat_information_parameter_new(s64 len, u8 *information);