Skip to content

Commit

Permalink
net-test: packetdrill encap support: IPv6 support
Browse files Browse the repository at this point in the history
Add support for IPv6 in encapsulation layers, including: lexical
scanning of IPv6 addresses, parsing IPv6 encap in scripts, appending
and filling in IPv6 encapsulation.


Change-Id: I1349cd4056c168a4114a92324eb2a321f7db7697
  • Loading branch information
nealcardwell committed Nov 28, 2013
1 parent f023c1e commit 8eb75b5
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 7 deletions.
48 changes: 48 additions & 0 deletions gtests/net/packetdrill/ip_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,37 @@ int ipv4_header_append(struct packet *packet,
return STATUS_OK;
}

int ipv6_header_append(struct packet *packet,
const char *ip_src,
const char *ip_dst,
char **error)
{
struct header *header = NULL;
const int ipv6_bytes = sizeof(struct ipv6);
struct ipv6 *ipv6 = NULL;

header = packet_append_header(packet, HEADER_IPV6, ipv6_bytes);
if (header == NULL) {
asprintf(error, "too many headers");
return STATUS_ERR;
}

ipv6 = header->h.ipv6;
set_ip_header(ipv6, AF_INET6, sizeof(struct ipv6), ECN_NONE, 0);

if (inet_pton(AF_INET6, ip_src, &ipv6->src_ip) != 1) {
asprintf(error, "bad IPv6 src address: '%s'\n", ip_src);
return STATUS_ERR;
}

if (inet_pton(AF_INET6, ip_dst, &ipv6->dst_ip) != 1) {
asprintf(error, "bad IPv6 dst address: '%s'\n", ip_dst);
return STATUS_ERR;
}

return STATUS_OK;
}

int ipv4_header_finish(struct packet *packet,
struct header *header, struct header *next_inner)
{
Expand All @@ -170,3 +201,20 @@ int ipv4_header_finish(struct packet *packet,

return STATUS_OK;
}

int ipv6_header_finish(struct packet *packet,
struct header *header, struct header *next_inner)
{
struct ipv6 *ipv6 = header->h.ipv6;
int ip_bytes = sizeof(struct ipv6) + next_inner->total_bytes;

assert(next_inner->total_bytes <= 0xffff);
ipv6->payload_len = htons(next_inner->total_bytes);
ipv6->next_header = header_type_info(next_inner->type)->ip_proto;

/* IPv6 has no header checksum. */

header->total_bytes = ip_bytes;

return STATUS_OK;
}
17 changes: 16 additions & 1 deletion gtests/net/packetdrill/ip_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,25 @@ extern int ipv4_header_append(struct packet *packet,
const char *ip_dst,
char **error);

/* Finalize the IPV4 header by filling in all necessary fields that
/* Append an IPv6 header to the end of the given packet and fill in
* src/dst. On success, return STATUS_OK; on error return STATUS_ERR
* and fill in a malloc-allocated error message in *error.
*/
extern int ipv6_header_append(struct packet *packet,
const char *ip_src,
const char *ip_dst,
char **error);

/* Finalize the IPv4 header by filling in all necessary fields that
* were not filled in at parse time.
*/
extern int ipv4_header_finish(struct packet *packet,
struct header *header, struct header *next_inner);

/* Finalize the IPv6 header by filling in all necessary fields that
* were not filled in at parse time.
*/
extern int ipv6_header_finish(struct packet *packet,
struct header *header, struct header *next_inner);

#endif /* __IP_PACKET_H__ */
30 changes: 27 additions & 3 deletions gtests/net/packetdrill/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,33 @@ c_comment \/\*(([^*])|(\*[^\/]))*\*\/
*/
code \%\{(([^}])|(\}[^\%]))*\}\%

/* A regular experssion for an IP address
* TODO(ncardwell): IPv6
*/
/* IPv4: a regular experssion for an IPv4 address */
ipv4_addr [0-9]+[.][0-9]+[.][0-9]+[.][0-9]+

/* IPv6: a regular experssion for an IPv6 address. The complexity is
* unfortunate, but we can't use a super-simple approach because TCP
* sequence number ranges like 1:1001 can look like IPv6 addresses if
* we use a naive approach.
*/
seg [0-9a-fA-F]{1,4}
v0 [:][:]
v1 ({seg}[:]){7,7}{seg}
v2 ({seg}[:]){1,7}[:]
v3 ({seg}[:]){1,6}[:]{seg}
v4 ({seg}[:]){1,5}([:]{seg}){1,2}
v5 ({seg}[:]){1,4}([:]{seg}){1,3}
v6 ({seg}[:]){1,3}([:]{seg}){1,4}
v7 ({seg}[:]){1,2}([:]{seg}){1,5}
v8 {seg}[:](([:]{seg}){1,6})
v9 [:]([:]{seg}){1,7}
/* IPv4-mapped IPv6 address: */
v10 [:][:]ffff[:]{ipv4_addr}
/* IPv4-translated IPv6 address: */
v11 [:][:]ffff[:](0){1,4}[:]{ipv4_addr}
/* IPv4-embedded IPv6 addresses: */
v12 ({seg}[:]){1,4}[:]{ipv4_addr}
ipv6_addr ({v0}|{v1}|{v2}|{v3}|{v4}|{v5}|{v6}|{v7}|{v8}|{v9}|{v10}|{v11}|{v12})

%%
sa_family return SA_FAMILY;
sin_port return SIN_PORT;
Expand All @@ -150,6 +172,7 @@ onoff return ONOFF;
linger return LINGER;
htons return _HTONS_;
ipv4 return IPV4;
ipv6 return IPV6;
icmp return ICMP;
udp return UDP;
gre return GRE;
Expand Down Expand Up @@ -186,4 +209,5 @@ ce return CE;
{c_comment} /* ignore C-style comment */;
{code} yylval.string = code(yytext); return CODE;
{ipv4_addr} yylval.string = strdup(yytext); return IPV4_ADDR;
{ipv6_addr} yylval.string = strdup(yytext); return IPV6_ADDR;
%%
2 changes: 1 addition & 1 deletion gtests/net/packetdrill/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
struct header_type_info header_types[HEADER_NUM_TYPES] = {
{ "NONE", 0, 0, NULL },
{ "IPV4", IPPROTO_IPIP, ETHERTYPE_IP, ipv4_header_finish },
{ "IPV6", IPPROTO_IPV6, ETHERTYPE_IPV6, NULL },
{ "IPV6", IPPROTO_IPV6, ETHERTYPE_IPV6, ipv6_header_finish },
{ "GRE", IPPROTO_GRE, 0, gre_header_finish },
{ "TCP", IPPROTO_TCP, 0, NULL },
{ "UDP", IPPROTO_UDP, 0, NULL },
Expand Down
17 changes: 15 additions & 2 deletions gtests/net/packetdrill/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,11 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
%token <reserved> ACK ECR EOL MSS NOP SACK SACKOK TIMESTAMP VAL WIN WSCALE PRO
%token <reserved> FAST_OPEN
%token <reserved> ECT0 ECT1 CE ECT01 NO_ECN
%token <reserved> IPV4 ICMP UDP GRE MTU
%token <reserved> IPV4 IPV6 ICMP UDP GRE MTU
%token <reserved> OPTION
%token <floating> FLOAT
%token <integer> INTEGER HEX_INTEGER
%token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR
%token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
%type <direction> direction
%type <ip_ecn> opt_ip_info
%type <ip_ecn> ip_ecn
Expand Down Expand Up @@ -550,7 +550,9 @@ option_value
| WORD { $$ = $1; }
| STRING { $$ = $1; }
| IPV4_ADDR { $$ = $1; }
| IPV6_ADDR { $$ = $1; }
| IPV4 { $$ = strdup("ipv4"); }
| IPV6 { $$ = strdup("ipv6"); }
;

opt_init_command
Expand Down Expand Up @@ -751,6 +753,17 @@ packet_prefix
free(ip_dst);
$$ = packet;
}
| packet_prefix IPV6 IPV6_ADDR '>' IPV6_ADDR ':' {
char *error = NULL;
struct packet *packet = $1;
char *ip_src = $3;
char *ip_dst = $5;
if (ipv6_header_append(packet, ip_src, ip_dst, &error))
semantic_error(error);
free(ip_src);
free(ip_dst);
$$ = packet;
}
| packet_prefix GRE ':' {
char *error = NULL;
struct packet *packet = $1;
Expand Down

0 comments on commit 8eb75b5

Please sign in to comment.