#! /usr/bin/perl
-# Copyright (c) 2009, 2010 Nicira Networks.
+# Copyright (c) 2009, 2010, 2011 Nicira Networks.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
output(DL_HEADER => '802.2');
-for my $dl_header qw(802.2+SNAP Ethernet) {
+for my $dl_header (qw(802.2+SNAP Ethernet)) {
my %a = (DL_HEADER => $dl_header);
- for my $dl_vlan qw(none zero nonzero) {
+ for my $dl_vlan (qw(none zero nonzero)) {
my %b = (%a, DL_VLAN => $dl_vlan);
# Non-IP case.
output(%b, DL_TYPE => 'non-ip');
- for my $ip_options qw(no yes) {
+ for my $ip_options (qw(no yes)) {
my %c = (%b, DL_TYPE => 'ip', IP_OPTIONS => $ip_options);
- for my $ip_fragment qw(no first middle last) {
+ for my $ip_fragment (qw(no first middle last)) {
my %d = (%c, IP_FRAGMENT => $ip_fragment);
- for my $tp_proto qw(TCP TCP+options UDP ICMP other) {
+ for my $tp_proto (qw(TCP TCP+options UDP ICMP other)) {
output(%d, TP_PROTO => $tp_proto);
}
}
$flow{NW_PROTO} = 42;
} elsif ($attrs{TP_PROTO} eq 'TCP' ||
$attrs{TP_PROTO} eq 'TCP+options') {
- $flow{NW_PROTO} = 6; # IP_TYPE_TCP
+ $flow{NW_PROTO} = 6; # IPPROTO_TCP
$flow{TP_SRC} = 6667;
$flow{TP_DST} = 9998;
} elsif ($attrs{TP_PROTO} eq 'UDP') {
- $flow{NW_PROTO} = 17; # IP_TYPE_UDP
+ $flow{NW_PROTO} = 17; # IPPROTO_UDP
$flow{TP_SRC} = 1112;
$flow{TP_DST} = 2223;
} elsif ($attrs{TP_PROTO} eq 'ICMP') {
- $flow{NW_PROTO} = 1; # IP_TYPE_ICMP
+ $flow{NW_PROTO} = 1; # IPPROTO_ICMP
$flow{TP_SRC} = 8; # echo request
$flow{TP_DST} = 0; # code
} else {
die;
}
- if ($attrs{IP_FRAGMENT} ne 'no') {
+ if ($attrs{IP_FRAGMENT} ne 'no' && $attrs{IP_FRAGMENT} ne 'first') {
$flow{TP_SRC} = $flow{TP_DST} = 0;
}
} elsif ($attrs{DL_TYPE} eq 'non-ip') {
my $packet = '';
$packet .= pack_ethaddr($flow{DL_DST});
$packet .= pack_ethaddr($flow{DL_SRC});
+ if ($flow{DL_VLAN} != 0xffff) {
+ $packet .= pack('nn', 0x8100, $flow{DL_VLAN});
+ }
+ my $len_ofs = length($packet);
$packet .= pack('n', 0) if $attrs{DL_HEADER} =~ /^802.2/;
if ($attrs{DL_HEADER} eq '802.2') {
$packet .= pack('CCC', 0x42, 0x42, 0x03); # LLC for 802.1D STP.
$packet .= pack('CCC', 0xaa, 0xaa, 0x03); # LLC for SNAP.
$packet .= pack('CCC', 0, 0, 0); # SNAP OUI.
}
- if ($attrs{DL_VLAN} ne 'none') {
- $packet .= pack('nn', 0x8100, $flow{DL_VLAN});
- }
$packet .= pack('n', $flow{DL_TYPE});
if ($attrs{DL_TYPE} eq 'ip') {
my $ip = pack('CCnnnCCnNN',
if ($attrs{TP_PROTO} =~ '^TCP') {
my $tcp = pack('nnNNnnnn',
- $flow{TP_SRC}, # source port
- $flow{TP_DST}, # dest port
- 87123455, # seqno
- 712378912, # ackno
+ $flow{TP_SRC}, # source port
+ $flow{TP_DST}, # dest port
+ 87123455, # seqno
+ 712378912, # ackno
(5 << 12) | 0x02 | 0x10, # hdrlen, SYN, ACK
5823, # window size
18923, # checksum
- 12893); # urgent pointer
+ 12893); # urgent pointer
if ($attrs{TP_PROTO} eq 'TCP+options') {
substr($tcp, 12, 2) = pack('n', (6 << 12) | 0x02 | 0x10);
$tcp .= pack('CCn', 2, 4, 1975); # MSS option
$ip .= $udp;
} elsif ($attrs{TP_PROTO} eq 'ICMP') {
$ip .= pack('CCnnn',
- 8, # echo request
- 0, # code
- 0, # checksum
- 736, # identifier
- 931); # sequence number
+ 8, # echo request
+ 0, # code
+ 0, # checksum
+ 736, # identifier
+ 931); # sequence number
} elsif ($attrs{TP_PROTO} eq 'other') {
$ip .= 'other header';
} else {
die;
}
-
substr($ip, 2, 2) = pack('n', length($ip));
$packet .= $ip;
}
}
- substr($packet, 12, 2) = pack('n', length($packet))
- if $attrs{DL_HEADER} =~ /^802.2/;
+ if ($attrs{DL_HEADER} =~ /^802.2/) {
+ my $len = length ($packet);
+ $len -= 4 if $flow{DL_VLAN} != 0xffff;
+ substr($packet, $len_ofs, 2) = pack('n', $len);
+ }
print join(' ', map("$_=$attrs{$_}", keys(%attrs))), "\n";
print join(' ', map("$_=$flow{$_}", keys(%flow))), "\n";