]> git.proxmox.com Git - mirror_ovs.git/blob - tests/flowgen.pl
ofproto: Match VLAN PCP and rewrite ToS bits (OpenFlow 0.9)
[mirror_ovs.git] / tests / flowgen.pl
1 #! /usr/bin/perl
2
3 # Copyright (c) 2009 Nicira Networks.
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
17 use strict;
18 use warnings;
19
20 open(FLOWS, ">&=3");# or die "failed to open fd 3 for writing: $!\n";
21 open(PACKETS, ">&=4");# or die "failed to open fd 4 for writing: $!\n";
22
23 # Print pcap file header.
24 print 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
33 output(DL_HEADER => '802.2');
34
35 for my $dl_header qw(802.2+SNAP Ethernet) {
36 my %a = (DL_HEADER => $dl_header);
37 for my $dl_vlan qw(none zero nonzero) {
38 my %b = (%a, DL_VLAN => $dl_vlan);
39
40 # Non-IP case.
41 output(%b, DL_TYPE => 'non-ip');
42
43 for my $ip_options qw(no yes) {
44 my %c = (%b, DL_TYPE => 'ip', IP_OPTIONS => $ip_options);
45 for my $ip_fragment qw(no first middle last) {
46 my %d = (%c, IP_FRAGMENT => $ip_fragment);
47 for my $tp_proto qw(TCP TCP+options UDP ICMP other) {
48 output(%d, TP_PROTO => $tp_proto);
49 }
50 }
51 }
52 }
53 }
54
55 sub 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;
63 $flow{NW_SRC} = '0.0.0.0';
64 $flow{NW_DST} = '0.0.0.0';
65 $flow{TP_SRC} = 0;
66 $flow{TP_DST} = 0;
67 if (defined($attrs{DL_VLAN})) {
68 my (%vlan_map) = ('none' => 0xffff,
69 'zero' => 0,
70 'nonzero' => 0x0123);
71 $flow{DL_VLAN} = $vlan_map{$attrs{DL_VLAN}};
72 } else {
73 $flow{DL_VLAN} = 0xffff; # OFP_VLAN_NONE
74 }
75 if ($attrs{DL_HEADER} eq '802.2') {
76 $flow{DL_TYPE} = 0x5ff; # OFP_DL_TYPE_NOT_ETH_TYPE
77 } elsif ($attrs{DL_TYPE} eq 'ip') {
78 $flow{DL_TYPE} = 0x0800; # ETH_TYPE_IP
79 $flow{NW_SRC} = '10.0.2.15';
80 $flow{NW_DST} = '192.168.1.20';
81 if ($attrs{TP_PROTO} eq 'other') {
82 $flow{NW_PROTO} = 42;
83 } elsif ($attrs{TP_PROTO} eq 'TCP' ||
84 $attrs{TP_PROTO} eq 'TCP+options') {
85 $flow{NW_PROTO} = 6; # IP_TYPE_TCP
86 $flow{TP_SRC} = 6667;
87 $flow{TP_DST} = 9998;
88 } elsif ($attrs{TP_PROTO} eq 'UDP') {
89 $flow{NW_PROTO} = 17; # IP_TYPE_UDP
90 $flow{TP_SRC} = 1112;
91 $flow{TP_DST} = 2223;
92 } elsif ($attrs{TP_PROTO} eq 'ICMP') {
93 $flow{NW_PROTO} = 1; # IP_TYPE_ICMP
94 $flow{TP_SRC} = 8; # echo request
95 $flow{TP_DST} = 0; # code
96 } else {
97 die;
98 }
99 if ($attrs{IP_FRAGMENT} ne 'no') {
100 $flow{TP_SRC} = $flow{TP_DST} = 0;
101 }
102 } elsif ($attrs{DL_TYPE} eq 'non-ip') {
103 $flow{DL_TYPE} = 0x5678;
104 } else {
105 die;
106 }
107
108 # Compose packet.
109 my $packet = '';
110 $packet .= pack_ethaddr($flow{DL_DST});
111 $packet .= pack_ethaddr($flow{DL_SRC});
112 $packet .= pack('n', 0) if $attrs{DL_HEADER} =~ /^802.2/;
113 if ($attrs{DL_HEADER} eq '802.2') {
114 $packet .= pack('CCC', 0x42, 0x42, 0x03); # LLC for 802.1D STP.
115 } else {
116 if ($attrs{DL_HEADER} eq '802.2+SNAP') {
117 $packet .= pack('CCC', 0xaa, 0xaa, 0x03); # LLC for SNAP.
118 $packet .= pack('CCC', 0, 0, 0); # SNAP OUI.
119 }
120 if ($attrs{DL_VLAN} ne 'none') {
121 $packet .= pack('nn', 0x8100, $flow{DL_VLAN});
122 }
123 $packet .= pack('n', $flow{DL_TYPE});
124 if ($attrs{DL_TYPE} eq 'ip') {
125 my $ip = pack('CCnnnCCnNN',
126 (4 << 4) | 5, # version, hdrlen
127 0, # type of service
128 0, # total length (filled in later)
129 65432, # id
130 0, # frag offset
131 64, # ttl
132 $flow{NW_PROTO}, # protocol
133 0, # checksum
134 0x0a00020f, # source
135 0xc0a80114); # dest
136 if ($attrs{IP_OPTIONS} eq 'yes') {
137 substr($ip, 0, 1) = pack('C', (4 << 4) | 8);
138 $ip .= pack('CCnnnCCCx',
139 130, # type
140 11, # length
141 0x6bc5, # top secret
142 0xabcd,
143 0x1234,
144 1,
145 2,
146 3);
147 }
148 if ($attrs{IP_FRAGMENT} ne 'no') {
149 my (%frag_map) = ('first' => 0x2000, # more frags, ofs 0
150 'middle' => 0x2111, # more frags, ofs 0x888
151 'last' => 0x0222); # last frag, ofs 0x1110
152 substr($ip, 6, 2)
153 = pack('n', $frag_map{$attrs{IP_FRAGMENT}});
154 }
155
156 if ($attrs{TP_PROTO} =~ '^TCP') {
157 my $tcp = pack('nnNNnnnn',
158 $flow{TP_SRC}, # source port
159 $flow{TP_DST}, # dest port
160 87123455, # seqno
161 712378912, # ackno
162 (5 << 12) | 0x02 | 0x10, # hdrlen, SYN, ACK
163 5823, # window size
164 18923, # checksum
165 12893); # urgent pointer
166 if ($attrs{TP_PROTO} eq 'TCP+options') {
167 substr($tcp, 12, 2) = pack('n', (6 << 12) | 0x02 | 0x10);
168 $tcp .= pack('CCn', 2, 4, 1975); # MSS option
169 }
170 $tcp .= 'payload';
171 $ip .= $tcp;
172 } elsif ($attrs{TP_PROTO} eq 'UDP') {
173 my $len = 15;
174 my $udp = pack('nnnn', $flow{TP_SRC}, $flow{TP_DST}, $len, 0);
175 $udp .= chr($len) while length($udp) < $len;
176 $ip .= $udp;
177 } elsif ($attrs{TP_PROTO} eq 'ICMP') {
178 $ip .= pack('CCnnn',
179 8, # echo request
180 0, # code
181 0, # checksum
182 736, # identifier
183 931); # sequence number
184 } elsif ($attrs{TP_PROTO} eq 'other') {
185 $ip .= 'other header';
186 } else {
187 die;
188 }
189
190 substr($ip, 2, 2) = pack('n', length($ip));
191 $packet .= $ip;
192 }
193 }
194 substr($packet, 12, 2) = pack('n', length($packet))
195 if $attrs{DL_HEADER} =~ /^802.2/;
196
197 print join(' ', map("$_=$attrs{$_}", keys(%attrs))), "\n";
198 print join(' ', map("$_=$flow{$_}", keys(%flow))), "\n";
199 print "\n";
200
201 print FLOWS pack('Nn',
202 0, # wildcards
203 1); # in_port
204 print FLOWS pack_ethaddr($flow{DL_SRC});
205 print FLOWS pack_ethaddr($flow{DL_DST});
206 print FLOWS pack('nCxnCxxxNNnn',
207 $flow{DL_VLAN},
208 0, # DL_VLAN_PCP
209 $flow{DL_TYPE},
210 $flow{NW_PROTO},
211 inet_aton($flow{NW_SRC}),
212 inet_aton($flow{NW_DST}),
213 $flow{TP_SRC},
214 $flow{TP_DST});
215
216 print PACKETS pack('NNNN',
217 0, # timestamp seconds
218 0, # timestamp microseconds
219 length($packet), # bytes saved
220 length($packet)), # total length
221 $packet;
222 }
223
224 sub pack_ethaddr {
225 local ($_) = @_;
226 my $xx = '([0-9a-fA-F][0-9a-fA-F])';
227 my (@octets) = /$xx:$xx:$xx:$xx:$xx:$xx/;
228 @octets == 6 or die $_;
229 my ($out) = '';
230 $out .= pack('C', hex($_)) foreach @octets;
231 return $out;
232 }
233
234 sub inet_aton {
235 local ($_) = @_;
236 my ($a, $b, $c, $d) = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
237 defined $d or die $_;
238 return ($a << 24) | ($b << 16) | ($c << 8) | $d;
239 }