blob: eb3081957660077fc2c03dfa553c850f4c6b3bf7 [file] [log] [blame]
Pierre Pfisterf588f352016-10-07 16:31:57 +01001import unittest
2import time
3import socket
4from framework import VppTestCase, VppTestRunner
5from util import Util
6
7from scapy.packet import Raw
8from scapy.layers.l2 import Ether, GRE
9from scapy.layers.inet import IP, UDP
10from scapy.layers.inet6 import IPv6
11
12## TestLB is a subclass of Util and VPPTestCase classes.
13#
14# TestLB class defines Load Balancer test cases for:
15# - IP4 to GRE4 encap
16# - IP4 to GRE6 encap
17# - IP6 to GRE4 encap
18# - IP6 to GRE6 encap
19#
20# As stated in comments below, GRE has issues with IPv6.
21# All test cases involving IPv6 are executed, but
22# received packets are not parsed and checked.
23#
24class TestLB(Util, VppTestCase):
25 """ Load Balancer Test Case """
26
27 @classmethod
28 def setUpClass(cls):
29 super(TestLB, cls).setUpClass()
30
31 cls.ass = range(5)
32 cls.packets = range(100)
33
34 try:
35 cls.create_interfaces([0,1])
36 cls.api("sw_interface_dump")
37 cls.config_ip4([0,1])
38 cls.config_ip6([0,1])
39 cls.resolve_arp([0,1])
40 cls.resolve_icmpv6_nd([0,1])
41 cls.cli(0, "ip route add 10.0.0.0/24 via %s pg1" % (cls.MY_IP4S[1]))
42 cls.cli(0, "ip route add 2002::/16 via %s pg1" % (cls.MY_IP6S[1]))
43 cls.cli(0, "lb conf buckets-log2 20 ip4-src-address 39.40.41.42 ip6-src-address fd00:f00d::1")
44
45 except Exception as e:
46 super(TestLB, cls).tearDownClass()
47 raise
48
49 def tearDown(self):
50 self.cli(2, "show int")
51 self.cli(2, "show trace")
52 self.cli(2, "show lb vip verbose")
53
54 def getIPv4Flow(self, id):
55 return (IP(dst="90.0.%u.%u" % (id / 255, id % 255),
56 src="40.0.%u.%u" % (id / 255, id % 255)) /
57 UDP(sport=10000 + id, dport=20000 + id))
58
59 def getIPv6Flow(self, id):
60 return (IPv6(dst="2001::%u" % (id), src="fd00:f00d:ffff::%u" % (id)) /
61 UDP(sport=10000 + id, dport=20000 + id))
62
63 def generatePackets(self, isv4):
64 pkts = []
65 for pktid in self.packets:
66 info = self.create_packet_info(0, pktid)
67 payload = self.info_to_payload(info)
68 ip = self.getIPv4Flow(pktid) if isv4 else self.getIPv6Flow(pktid)
69 packet=(Ether(dst=self.VPP_MACS[0], src=self.MY_MACS[0]) /
70 ip / Raw(payload))
71 self.extend_packet(packet, 128)
72 info.data = packet.copy()
73 pkts.append(packet)
74 return pkts
75
76 def checkInner(self, gre, isv4):
77 self.assertEqual(gre.proto, 0x0800 if isv4 else 0x86DD)
78 self.assertEqual(gre.flags, 0)
79 self.assertEqual(gre.version, 0)
80 inner = gre[IP] if isv4 else gre[IPv6]
81 payload_info = self.payload_to_info(str(gre[Raw]))
82 packet_index = payload_info.index
83 self.info = self.get_next_packet_info_for_interface2(0, payload_info.dst, self.info)
84 self.assertEqual(str(inner), str(self.info.data[IP]))
85
86 def checkCapture(self, gre4, isv4):
87 out = self.pg_get_capture(0)
88 self.assertEqual(len(out), 0)
89 out = self.pg_get_capture(1)
90 self.assertEqual(len(out), len(self.packets))
91
92 load = [0] * len(self.ass)
93 self.info = None
94 for p in out:
95 try:
96 asid = 0
97 gre = None
98 if gre4:
99 ip = p[IP]
100 gre = p[GRE]
101 inner = gre[IP] if isv4 else gre[IPv6]
102 asid = int(ip.dst.split(".")[3])
103 self.assertEqual(ip.version, 4)
104 self.assertEqual(ip.flags, 0)
105 self.assertEqual(ip.src, "39.40.41.42")
106 self.assertEqual(ip.dst, "10.0.0.%u" % asid)
107 self.assertEqual(ip.proto, 47)
108 self.assertEqual(len(ip.options), 0)
109 self.assertTrue(ip.ttl >= 64)
110 else:
111 ip = p[IPv6]
112 gre = p[GRE]
113 inner = gre[IP] if isv4 else gre[IPv6]
114 asid = ip.dst.split(":")
115 asid = asid[len(asid) - 1]
116 asid = 0 if asid=="" else int(asid)
117 self.assertEqual(ip.version, 6)
118 # Todo: Given scapy... I will do that when it works.
119 self.checkInner(gre, isv4)
120 load[asid] += 1
121 except:
122 self.log("Unexpected or invalid packet:")
123 p.show()
124 raise
125
126 # This is just to roughly check that the balancing algorithm
127 # is not completly biased.
128 for asid in self.ass:
129 if load[asid] < len(self.packets)/(len(self.ass)*2):
130 self.log("ASS is not balanced: load[%d] = %d" % (asid, load[asid]))
131 raise Exception("Load Balancer algorithm is biased")
132
133
134 def test_lb_ip4_gre4(self):
135 """ Load Balancer IP4 GRE4 """
136
137 return
138 self.cli(0, "lb vip 90.0.0.0/8 encap gre4")
139 for asid in self.ass:
140 self.cli(0, "lb as 90.0.0.0/8 10.0.0.%u" % (asid))
141
142 self.pg_add_stream(0, self.generatePackets(1))
143 self.pg_enable_capture([0,1])
144 self.pg_start()
145 self.checkCapture(1, 1)
146
147 for asid in self.ass:
148 self.cli(0, "lb as 90.0.0.0/8 10.0.0.%u del" % (asid))
149 self.cli(0, "lb vip 90.0.0.0/8 encap gre4 del")
150
151
152 def test_lb_ip6_gre4(self):
153 """ Load Balancer IP6 GRE4 """
154
155 self.cli(0, "lb vip 2001::/16 encap gre4")
156 for asid in self.ass:
157 self.cli(0, "lb as 2001::/16 10.0.0.%u" % (asid))
158
159 self.pg_add_stream(0, self.generatePackets(0))
160 self.pg_enable_capture([0,1])
161 self.pg_start()
162
163 # Scapy fails parsing IPv6 over GRE.
164 # This check is therefore disabled for now.
165 #self.checkCapture(1, 0)
166
167 for asid in self.ass:
168 self.cli(0, "lb as 2001::/16 10.0.0.%u del" % (asid))
169 self.cli(0, "lb vip 2001::/16 encap gre4 del")
170
171
172 def test_lb_ip4_gre6(self):
173 """ Load Balancer IP4 GRE6 """
174
175 self.cli(0, "lb vip 90.0.0.0/8 encap gre6")
176 for asid in self.ass:
177 self.cli(0, "lb as 90.0.0.0/8 2002::%u" % (asid))
178
179 self.pg_add_stream(0, self.generatePackets(1))
180 self.pg_enable_capture([0,1])
181 self.pg_start()
182
183 # Scapy fails parsing GRE over IPv6.
184 # This check is therefore disabled for now.
185 # One can easily patch layers/inet6.py to fix the issue.
186 #self.checkCapture(0, 1)
187
188 for asid in self.ass:
189 self.cli(0, "lb as 90.0.0.0/8 2002::%u" % (asid))
190 self.cli(0, "lb vip 90.0.0.0/8 encap gre6 del")
191
192 def test_lb_ip6_gre6(self):
193 """ Load Balancer IP6 GRE6 """
194
195 self.cli(0, "lb vip 2001::/16 encap gre6")
196 for asid in self.ass:
197 self.cli(0, "lb as 2001::/16 2002::%u" % (asid))
198
199 self.pg_add_stream(0, self.generatePackets(0))
200 self.pg_enable_capture([0,1])
201 self.pg_start()
202
203 # Scapy fails parsing IPv6 over GRE and IPv6 over GRE.
204 # This check is therefore disabled for now.
205 #self.checkCapture(0, 0)
206
207 for asid in self.ass:
208 self.cli(0, "lb as 2001::/16 2002::%u del" % (asid))
209 self.cli(0, "lb vip 2001::/16 encap gre6 del")
210