netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / utilities / ovs-pipegen.py
1 #! /usr/bin/env python
2 # Copyright (c) 2013, 2014, 2015 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import argparse
17 import random
18 import sys
19 import textwrap
20
21 def flow_str(stage, match, action, priority=32768):
22     mtd_match = "metadata=%d" % stage
23     if match:
24         mtd_match += "," + match
25
26     return "priority=%d %s,actions=%s" % (priority, mtd_match, action)
27
28
29 def resubmit(nxt):
30     return "load:%d->OXM_OF_METADATA[],resubmit(,0)" % nxt
31
32
33 def rand_ip_mask():
34     return ("%d.%d.%d.%d" % (random.randint(0, 255), random.randint(0, 255),
35                              random.randint(0, 255), random.randint(0, 255)),
36             random.choice([8, 16, 24, 32]))
37
38
39 def rand_bool():
40     return bool(random.randint(0, 1))
41
42
43 def l2(stage, action):
44     mac = ["%x" % random.randint(0, 2 ** 8 - 1) for x in range(6)]
45     mac = [x.zfill(2) for x in mac]
46     mac = ":".join(mac)
47     return flow_str(stage, "dl_dst=%s" % mac, action)
48
49
50 def l3(stage, action):
51     ip, mask = rand_ip_mask()
52     return flow_str(stage, "ip,ip_dst=%s/%d" % (ip, mask), action,
53                     priority=mask)
54
55
56 def l4(stage, action):
57     match = "tcp"
58
59     if rand_bool():
60         match += ",ip_src=%s/%d" % rand_ip_mask()
61
62     if rand_bool():
63         match += ",ip_dst=%s/%d" % rand_ip_mask()
64
65     src_dst = "tp_src" if rand_bool() else "tp_dst"
66     match += ",%s=%d" % (src_dst, random.randint(1024, 2**16 - 1))
67     return flow_str(stage, match, action)
68
69
70 def pipeline(size):
71     pipeline = [l2, l3, l4, l2]
72
73     flows = []
74     for stage in xrange(len(pipeline)):
75         action = resubmit(stage + 1)
76         flows += [pipeline[stage](stage, action) for _ in xrange(size)]
77         flows.append(flow_str(stage, "", action, priority=1))
78
79     flows.append(flow_str(len(pipeline), "", "in_port"))
80
81     for f in flows:
82         print f
83
84
85 def main():
86     description = textwrap.dedent(
87         """
88         Generate a test OpenFlow pipeline.
89
90         Open vSwitch relies heavily on flow caching to get good performance for
91         packet processing.  While on average, this produces good results,
92         performance is heavily depedent on the slow path OpenFlow tables, and
93         how they're translated into datapath megaflows.  For this reason, when
94         doing performance testing it's important to run with "realistic"
95         OpenFlow tables to ensure results will stand up in the real world.
96
97         This script generates a simple OpenFlow pipeline intended to simulate
98         realistic network virtualization workloads.  All traffic received is
99         run through a series of OpenFlow tables designed to simulate a logical
100         switch, router, and firewall, before forwarded back on the in_port.
101         """)
102
103     epilog = textwrap.dedent(
104         """
105         typical usage:
106           ovs-ofctl del-flows bridge \\
107           && %s | ovs-ofctl add-flows bridge - \\
108           && ovs-ofctl dump-flows bridge
109         """ % sys.argv[0])
110
111     parser = argparse.ArgumentParser(description=description, epilog=epilog,
112                                      formatter_class=\
113                                      argparse.RawDescriptionHelpFormatter)
114     parser.add_argument("--size", dest="size", default=1000,
115                         help="Size (rules) of each OpenFlow table.")
116     args=parser.parse_args()
117
118     pipeline(int(args.size))
119
120
121 if __name__ == "__main__":
122     main()