]> git.proxmox.com Git - mirror_ovs.git/blame - tests/flowgen.pl
AUTHORS: Add Shu Shen.
[mirror_ovs.git] / tests / flowgen.pl
CommitLineData
064af421
BP
1#! /usr/bin/perl
2
41ca9a1e 3# Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
a14bc59f
BP
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at:
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
064af421
BP
17use strict;
18use warnings;
19
20open(FLOWS, ">&=3");# or die "failed to open fd 3 for writing: $!\n";
21open(PACKETS, ">&=4");# or die "failed to open fd 4 for writing: $!\n";
22
23# Print pcap file header.
24print PACKETS pack('NnnNNNN',
25 0xa1b2c3d4, # magic number
26 2, # major version
27 4, # minor version
28 0, # time zone offset
29 0, # time stamp accuracy
30 1518, # snaplen
31 1); # Ethernet
32
33output(DL_HEADER => '802.2');
34
b9ec4ff7 35for my $dl_header (qw(802.2+SNAP Ethernet)) {
064af421 36 my %a = (DL_HEADER => $dl_header);
b9ec4ff7 37 for my $dl_vlan (qw(none zero nonzero)) {
064af421
BP
38 my %b = (%a, DL_VLAN => $dl_vlan);
39
40 # Non-IP case.
41 output(%b, DL_TYPE => 'non-ip');
42
b9ec4ff7 43 for my $ip_options (qw(no yes)) {
064af421 44 my %c = (%b, DL_TYPE => 'ip', IP_OPTIONS => $ip_options);
b9ec4ff7 45 for my $ip_fragment (qw(no first middle last)) {
064af421 46 my %d = (%c, IP_FRAGMENT => $ip_fragment);
b9ec4ff7 47 for my $tp_proto (qw(TCP TCP+options UDP ICMP other)) {
064af421
BP
48 output(%d, TP_PROTO => $tp_proto);
49 }
50 }
51 }
52 }
53}
54
55sub output {
56 my (%attrs) = @_;
57
58 # Compose flow.
59 my (%flow);
60 $flow{DL_SRC} = "00:02:e3:0f:80:a4";
61 $flow{DL_DST} = "00:1a:92:40:ac:05";
62 $flow{NW_PROTO} = 0;
834377ea 63 $flow{NW_TOS} = 0;
064af421
BP
64 $flow{NW_SRC} = '0.0.0.0';
65 $flow{NW_DST} = '0.0.0.0';
66 $flow{TP_SRC} = 0;
67 $flow{TP_DST} = 0;
68 if (defined($attrs{DL_VLAN})) {
69 my (%vlan_map) = ('none' => 0xffff,
70 'zero' => 0,
71 'nonzero' => 0x0123);
72 $flow{DL_VLAN} = $vlan_map{$attrs{DL_VLAN}};
73 } else {
74 $flow{DL_VLAN} = 0xffff; # OFP_VLAN_NONE
75 }
76 if ($attrs{DL_HEADER} eq '802.2') {
77 $flow{DL_TYPE} = 0x5ff; # OFP_DL_TYPE_NOT_ETH_TYPE
78 } elsif ($attrs{DL_TYPE} eq 'ip') {
79 $flow{DL_TYPE} = 0x0800; # ETH_TYPE_IP
80 $flow{NW_SRC} = '10.0.2.15';
81 $flow{NW_DST} = '192.168.1.20';
834377ea 82 $flow{NW_TOS} = 44;
064af421
BP
83 if ($attrs{TP_PROTO} eq 'other') {
84 $flow{NW_PROTO} = 42;
85 } elsif ($attrs{TP_PROTO} eq 'TCP' ||
86 $attrs{TP_PROTO} eq 'TCP+options') {
6767a2cc 87 $flow{NW_PROTO} = 6; # IPPROTO_TCP
064af421
BP
88 $flow{TP_SRC} = 6667;
89 $flow{TP_DST} = 9998;
90 } elsif ($attrs{TP_PROTO} eq 'UDP') {
6767a2cc 91 $flow{NW_PROTO} = 17; # IPPROTO_UDP
064af421
BP
92 $flow{TP_SRC} = 1112;
93 $flow{TP_DST} = 2223;
94 } elsif ($attrs{TP_PROTO} eq 'ICMP') {
6767a2cc 95 $flow{NW_PROTO} = 1; # IPPROTO_ICMP
064af421
BP
96 $flow{TP_SRC} = 8; # echo request
97 $flow{TP_DST} = 0; # code
98 } else {
99 die;
100 }
7257b535 101 if ($attrs{IP_FRAGMENT} ne 'no' && $attrs{IP_FRAGMENT} ne 'first') {
064af421
BP
102 $flow{TP_SRC} = $flow{TP_DST} = 0;
103 }
104 } elsif ($attrs{DL_TYPE} eq 'non-ip') {
105 $flow{DL_TYPE} = 0x5678;
106 } else {
107 die;
108 }
109
110 # Compose packet.
111 my $packet = '';
94639963
JR
112 my $wildcards = 1 << 5 | 1 << 6 | 1 << 7 | 32 << 8 | 32 << 14 | 1 << 21;
113
064af421
BP
114 $packet .= pack_ethaddr($flow{DL_DST});
115 $packet .= pack_ethaddr($flow{DL_SRC});
50f06e16
BP
116 if ($flow{DL_VLAN} != 0xffff) {
117 $packet .= pack('nn', 0x8100, $flow{DL_VLAN});
41ca9a1e
BP
118 } else {
119 $wildcards |= 1 << 20; # OFPFW10_DL_VLAN_PCP
50f06e16
BP
120 }
121 my $len_ofs = length($packet);
064af421
BP
122 $packet .= pack('n', 0) if $attrs{DL_HEADER} =~ /^802.2/;
123 if ($attrs{DL_HEADER} eq '802.2') {
124 $packet .= pack('CCC', 0x42, 0x42, 0x03); # LLC for 802.1D STP.
125 } else {
126 if ($attrs{DL_HEADER} eq '802.2+SNAP') {
127 $packet .= pack('CCC', 0xaa, 0xaa, 0x03); # LLC for SNAP.
128 $packet .= pack('CCC', 0, 0, 0); # SNAP OUI.
129 }
064af421
BP
130 $packet .= pack('n', $flow{DL_TYPE});
131 if ($attrs{DL_TYPE} eq 'ip') {
132 my $ip = pack('CCnnnCCnNN',
133 (4 << 4) | 5, # version, hdrlen
834377ea 134 $flow{NW_TOS}, # type of service
064af421
BP
135 0, # total length (filled in later)
136 65432, # id
137 0, # frag offset
138 64, # ttl
139 $flow{NW_PROTO}, # protocol
140 0, # checksum
141 0x0a00020f, # source
142 0xc0a80114); # dest
94639963 143 $wildcards &= ~( 1 << 5 | 63 << 8 | 63 << 14 | 1 << 21);
064af421
BP
144 if ($attrs{IP_OPTIONS} eq 'yes') {
145 substr($ip, 0, 1) = pack('C', (4 << 4) | 8);
146 $ip .= pack('CCnnnCCCx',
147 130, # type
148 11, # length
149 0x6bc5, # top secret
150 0xabcd,
151 0x1234,
152 1,
153 2,
154 3);
155 }
94639963 156
064af421
BP
157 if ($attrs{IP_FRAGMENT} ne 'no') {
158 my (%frag_map) = ('first' => 0x2000, # more frags, ofs 0
159 'middle' => 0x2111, # more frags, ofs 0x888
160 'last' => 0x0222); # last frag, ofs 0x1110
161 substr($ip, 6, 2)
162 = pack('n', $frag_map{$attrs{IP_FRAGMENT}});
163 }
94639963
JR
164 if ($attrs{IP_FRAGMENT} eq 'no' || $attrs{IP_FRAGMENT} eq 'first') {
165 if ($attrs{TP_PROTO} =~ '^TCP') {
166 my $tcp = pack('nnNNnnnn',
167 $flow{TP_SRC}, # source port
168 $flow{TP_DST}, # dest port
169 87123455, # seqno
170 712378912, # ackno
171 (5 << 12) | 0x02 | 0x10, # hdrlen, SYN, ACK
172 5823, # window size
173 18923, # checksum
174 12893); # urgent pointer
175 if ($attrs{TP_PROTO} eq 'TCP+options') {
176 substr($tcp, 12, 2) = pack('n', (6 << 12) | 0x02 | 0x10);
177 $tcp .= pack('CCn', 2, 4, 1975); # MSS option
178 }
179 $tcp .= 'payload';
180 $ip .= $tcp;
181 $wildcards &= ~(1 << 6 | 1 << 7);
182 } elsif ($attrs{TP_PROTO} eq 'UDP') {
183 my $len = 15;
184 my $udp = pack('nnnn', $flow{TP_SRC}, $flow{TP_DST}, $len, 0);
185 $udp .= chr($len) while length($udp) < $len;
186 $ip .= $udp;
187 $wildcards &= ~(1 << 6 | 1 << 7);
188 } elsif ($attrs{TP_PROTO} eq 'ICMP') {
189 $ip .= pack('CCnnn',
190 8, # echo request
191 0, # code
192 0, # checksum
193 736, # identifier
194 931); # sequence number
195 $wildcards &= ~(1 << 6 | 1 << 7);
196 } elsif ($attrs{TP_PROTO} eq 'other') {
197 $ip .= 'other header';
198 } else {
199 die;
064af421 200 }
064af421 201 }
064af421
BP
202 substr($ip, 2, 2) = pack('n', length($ip));
203 $packet .= $ip;
204 }
205 }
50f06e16
BP
206 if ($attrs{DL_HEADER} =~ /^802.2/) {
207 my $len = length ($packet);
208 $len -= 4 if $flow{DL_VLAN} != 0xffff;
209 substr($packet, $len_ofs, 2) = pack('n', $len);
210 }
064af421
BP
211
212 print join(' ', map("$_=$attrs{$_}", keys(%attrs))), "\n";
213 print join(' ', map("$_=$flow{$_}", keys(%flow))), "\n";
214 print "\n";
215
216 print FLOWS pack('Nn',
41ca9a1e
BP
217 $wildcards, # wildcards
218 1); # in_port
064af421
BP
219 print FLOWS pack_ethaddr($flow{DL_SRC});
220 print FLOWS pack_ethaddr($flow{DL_DST});
834377ea 221 print FLOWS pack('nCxnCCxxNNnn',
064af421 222 $flow{DL_VLAN},
959a2ecd 223 0, # DL_VLAN_PCP
064af421 224 $flow{DL_TYPE},
834377ea 225 $flow{NW_TOS},
064af421
BP
226 $flow{NW_PROTO},
227 inet_aton($flow{NW_SRC}),
228 inet_aton($flow{NW_DST}),
229 $flow{TP_SRC},
230 $flow{TP_DST});
231
232 print PACKETS pack('NNNN',
233 0, # timestamp seconds
234 0, # timestamp microseconds
235 length($packet), # bytes saved
236 length($packet)), # total length
237 $packet;
238}
239
240sub pack_ethaddr {
241 local ($_) = @_;
242 my $xx = '([0-9a-fA-F][0-9a-fA-F])';
243 my (@octets) = /$xx:$xx:$xx:$xx:$xx:$xx/;
244 @octets == 6 or die $_;
245 my ($out) = '';
246 $out .= pack('C', hex($_)) foreach @octets;
247 return $out;
248}
249
250sub inet_aton {
251 local ($_) = @_;
252 my ($a, $b, $c, $d) = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
253 defined $d or die $_;
254 return ($a << 24) | ($b << 16) | ($c << 8) | $d;
255}