]> git.proxmox.com Git - mirror_ovs.git/blob - tests/flowgen.py
system-afxdp.at: Add test for infinite re-addition of failed ports.
[mirror_ovs.git] / tests / flowgen.py
1 #! /usr/bin/env python3
2
3 # Copyright (c) 2009, 2010, 2011, 2012, 2015, 2017 Nicira, Inc.
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 import socket
18 import struct
19
20
21 def pack_ethaddr(ea):
22 octets = ea.split(':')
23 assert len(octets) == 6
24 return b''.join([struct.pack('B', int(octet, 16)) for octet in octets])
25
26
27 def output(attrs):
28 # Compose flow.
29
30 flow = {}
31 flow['DL_SRC'] = "00:02:e3:0f:80:a4"
32 flow['DL_DST'] = "00:1a:92:40:ac:05"
33 flow['NW_PROTO'] = 0
34 flow['NW_TOS'] = 0
35 flow['NW_SRC'] = '0.0.0.0'
36 flow['NW_DST'] = '0.0.0.0'
37 flow['TP_SRC'] = 0
38 flow['TP_DST'] = 0
39 if 'DL_VLAN' in attrs:
40 flow['DL_VLAN'] = {'none': 0xffff,
41 'zero': 0,
42 'nonzero': 0x0123}[attrs['DL_VLAN']]
43 else:
44 flow['DL_VLAN'] = 0xffff # OFP_VLAN_NONE
45 if attrs['DL_HEADER'] == '802.2':
46 flow['DL_TYPE'] = 0x5ff # OFP_DL_TYPE_NOT_ETH_TYPE
47 elif attrs['DL_TYPE'] == 'ip':
48 flow['DL_TYPE'] = 0x0800 # ETH_TYPE_IP
49 flow['NW_SRC'] = '10.0.2.15'
50 flow['NW_DST'] = '192.168.1.20'
51 flow['NW_TOS'] = 44
52 if attrs['TP_PROTO'] == 'other':
53 flow['NW_PROTO'] = 42
54 elif attrs['TP_PROTO'] in ('TCP', 'TCP+options'):
55 flow['NW_PROTO'] = 6 # IPPROTO_TCP
56 flow['TP_SRC'] = 6667
57 flow['TP_DST'] = 9998
58 elif attrs['TP_PROTO'] == 'UDP':
59 flow['NW_PROTO'] = 17 # IPPROTO_UDP
60 flow['TP_SRC'] = 1112
61 flow['TP_DST'] = 2223
62 elif attrs['TP_PROTO'] == 'ICMP':
63 flow['NW_PROTO'] = 1 # IPPROTO_ICMP
64 flow['TP_SRC'] = 8 # echo request
65 flow['TP_DST'] = 0 # code
66 else:
67 assert False
68 if attrs['IP_FRAGMENT'] not in ('no', 'first'):
69 flow['TP_SRC'] = flow['TP_DST'] = 0
70 elif attrs['DL_TYPE'] == 'non-ip':
71 flow['DL_TYPE'] = 0x5678
72 else:
73 assert False
74
75 # Compose packet
76 packet = b''
77 wildcards = 1 << 5 | 1 << 6 | 1 << 7 | 32 << 8 | 32 << 14 | 1 << 21
78
79 packet += pack_ethaddr(flow['DL_DST'])
80 packet += pack_ethaddr(flow['DL_SRC'])
81 if flow['DL_VLAN'] != 0xffff:
82 packet += struct.pack('>HH', 0x8100, flow['DL_VLAN'])
83 len_ofs = len(packet)
84 if attrs['DL_HEADER'].startswith('802.2'):
85 packet += struct.pack('>H', 0)
86 if attrs['DL_HEADER'] == '802.2':
87 packet += struct.pack('BBB', 0x42, 0x42, 0x03) # LLC for 802.1D STP
88 else:
89 if attrs['DL_HEADER'] == '802.2+SNAP':
90 packet += struct.pack('BBB', 0xaa, 0xaa, 0x03) # LLC for SNAP
91 packet += struct.pack('BBB', 0, 0, 0) # SNAP OUI
92 packet += struct.pack('>H', flow['DL_TYPE'])
93 if attrs['DL_TYPE'] == 'ip':
94 ip = struct.pack('>BBHHHBBHLL',
95 (4 << 4) | 5, # version, hdrlen
96 flow['NW_TOS'], # type of service
97 0, # total length, filled in later
98 65432, # id
99 0, # frag offset
100 64, # ttl
101 flow['NW_PROTO'], # protocol
102 0, # checksum
103 0x0a00020f, # source
104 0xc0a80114) # dest
105 wildcards &= ~(1 << 5 | 63 << 8 | 63 << 14 | 1 << 21)
106 if attrs['IP_OPTIONS'] == 'yes':
107 ip = struct.pack('B', (4 << 4) | 8) + ip[1:]
108 ip += struct.pack('>BBHHHBBBx',
109 130, # type
110 11, # length
111 0x6bc5, # top secret
112 0xabcd,
113 0x1234,
114 1,
115 2,
116 3)
117 if attrs['IP_FRAGMENT'] != 'no':
118 frag_map = {'first': 0x2000, # more frags, ofs 0
119 'middle': 0x2111, # more frags, ofs 0x888
120 'last': 0x0222} # last frag, ofs 0x1110
121 ip = (ip[:6]
122 + struct.pack('>H', frag_map[attrs['IP_FRAGMENT']])
123 + ip[8:])
124 if attrs['IP_FRAGMENT'] in ('no', 'first'):
125 if attrs['TP_PROTO'].startswith('TCP'):
126 tcp = struct.pack('>HHLLHHHH',
127 flow['TP_SRC'], # source port
128 flow['TP_DST'], # dest port
129 87123455, # seqno
130 712378912, # ackno
131 (5 << 12) | 0x02 | 0x10,
132 # hdrlen, SYN, ACK
133 5823, # window size
134 18923, # checksum
135 12893) # urgent pointer
136 if attrs['TP_PROTO'] == 'TCP+options':
137 tcp = (tcp[:12]
138 + struct.pack('H', (6 << 12) | 0x02 | 0x10)
139 + tcp[14:])
140 tcp += struct.pack('>BBH', 2, 4, 1975) # MSS option
141 tcp += b'payload'
142 ip += tcp
143 wildcards &= ~(1 << 6 | 1 << 7)
144 elif attrs['TP_PROTO'] == 'UDP':
145 udp_len = 15
146 udp = struct.pack('>HHHH',
147 flow['TP_SRC'],
148 flow['TP_DST'],
149 udp_len, 0)
150 while len(udp) < udp_len:
151 udp += struct.pack('B', udp_len)
152 ip += udp
153 wildcards &= ~(1 << 6 | 1 << 7)
154 elif attrs['TP_PROTO'] == 'ICMP':
155 ip += struct.pack('>BBHHH',
156 8, # echo request
157 0, # code
158 0, # checksum
159 736, # identifier
160 931) # sequence number
161 wildcards &= ~(1 << 6 | 1 << 7)
162 elif attrs['TP_PROTO'] == 'other':
163 ip += b'other header'
164 else:
165 assert False
166 ip = ip[:2] + struct.pack('>H', len(ip)) + ip[4:]
167 packet += ip
168 if attrs['DL_HEADER'].startswith('802.2'):
169 packet_len = len(packet)
170 if flow['DL_VLAN'] != 0xffff:
171 packet_len -= 4
172 packet = (packet[:len_ofs]
173 + struct.pack('>H', packet_len)
174 + packet[len_ofs + 2:])
175
176 print(' '.join(['%s=%s' for k, v in attrs.items()]))
177 print(' '.join(['%s=%s' for k, v in flow.items()]))
178 print()
179
180 flows.write(struct.pack('>LH',
181 wildcards, # wildcards
182 1)) # in_port
183 flows.write(pack_ethaddr(flow['DL_SRC']))
184 flows.write(pack_ethaddr(flow['DL_DST']))
185 flows.write(struct.pack('>HBxHBBxx',
186 flow['DL_VLAN'],
187 0, # DL_VLAN_PCP
188 flow['DL_TYPE'],
189 flow['NW_TOS'],
190 flow['NW_PROTO']))
191 flows.write(socket.inet_aton(flow['NW_SRC']))
192 flows.write(socket.inet_aton(flow['NW_DST']))
193 flows.write(struct.pack('>HH', flow['TP_SRC'], flow['TP_DST']))
194
195 packets.write(struct.pack('>LLLL',
196 0, # timestamp seconds
197 0, # timestamp microseconds
198 len(packet), # bytes saved
199 len(packet))) # total length
200 packets.write(packet)
201
202
203 flows = open('flows', 'wb')
204 packets = open('pcap', 'wb')
205
206 # Print pcap file header.
207 packets.write(struct.pack('>LHHLLLL',
208 0xa1b2c3d4, # magic number
209 2, # major version
210 4, # minor version
211 0, # time zone offset
212 0, # time stamp accuracy
213 1518, # snaplen
214 1)) # Ethernet
215
216 output({'DL_HEADER': '802.2'})
217
218 for dl_header in ('802.2+SNAP', 'Ethernet'):
219 a = {'DL_HEADER': dl_header}
220 for dl_vlan in ('none', 'zero', 'nonzero'):
221 b = a.copy()
222 b['DL_VLAN'] = dl_vlan
223
224 # Non-IP case.
225 c = b.copy()
226 c['DL_TYPE'] = 'non-ip'
227 output(c)
228
229 for ip_options in ('no', 'yes'):
230 c = b.copy()
231 c['DL_TYPE'] = 'ip'
232 c['IP_OPTIONS'] = ip_options
233 for ip_fragment in ('no', 'first', 'middle', 'last'):
234 d = c.copy()
235 d['IP_FRAGMENT'] = ip_fragment
236 for tp_proto in ('TCP', 'TCP+options', 'UDP', 'ICMP', 'other'):
237 e = d.copy()
238 e['TP_PROTO'] = tp_proto
239 output(e)