blob: 731790bce72e821cd9b00ab5f0834bb28dcf11d7 [file] [log] [blame]
Pierre Pfisterf588f352016-10-07 16:31:57 +01001import socket
Pierre Pfisterf588f352016-10-07 16:31:57 +01002
Pierre Pfisterf588f352016-10-07 16:31:57 +01003from scapy.layers.inet import IP, UDP
Klement Sekera65cc8c02016-12-18 15:49:54 +01004from scapy.layers.inet6 import IPv6
Klement Sekeraf62ae122016-10-11 11:47:09 +02005from scapy.layers.l2 import Ether, GRE
6from scapy.packet import Raw
Pierre Pfisterf588f352016-10-07 16:31:57 +01007
Klement Sekeraf62ae122016-10-11 11:47:09 +02008from framework import VppTestCase
Klement Sekera7bb873a2016-11-18 07:38:42 +01009from util import ppp
Klement Sekeraf62ae122016-10-11 11:47:09 +020010
11""" TestLB is a subclass of VPPTestCase classes.
12
13 TestLB class defines Load Balancer test cases for:
14 - IP4 to GRE4 encap
15 - IP4 to GRE6 encap
16 - IP6 to GRE4 encap
17 - IP6 to GRE6 encap
Hongjun Ni647f6092018-01-23 19:17:23 +080018 - IP4 to L3DSR encap
Klement Sekeraf62ae122016-10-11 11:47:09 +020019
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
24"""
25
26
27class TestLB(VppTestCase):
Pierre Pfisterf588f352016-10-07 16:31:57 +010028 """ Load Balancer Test Case """
29
30 @classmethod
31 def setUpClass(cls):
32 super(TestLB, cls).setUpClass()
33
34 cls.ass = range(5)
35 cls.packets = range(100)
36
37 try:
Klement Sekeraf62ae122016-10-11 11:47:09 +020038 cls.create_pg_interfaces(range(2))
39 cls.interfaces = list(cls.pg_interfaces)
Pierre Pfisterf588f352016-10-07 16:31:57 +010040
Klement Sekeraf62ae122016-10-11 11:47:09 +020041 for i in cls.interfaces:
42 i.admin_up()
43 i.config_ip4()
44 i.config_ip6()
45 i.disable_ipv6_ra()
46 i.resolve_arp()
47 i.resolve_ndp()
48 dst4 = socket.inet_pton(socket.AF_INET, "10.0.0.0")
49 dst6 = socket.inet_pton(socket.AF_INET6, "2002::")
50 cls.vapi.ip_add_del_route(dst4, 24, cls.pg1.remote_ip4n)
51 cls.vapi.ip_add_del_route(dst6, 16, cls.pg1.remote_ip6n, is_ipv6=1)
52 cls.vapi.cli("lb conf ip4-src-address 39.40.41.42")
53 cls.vapi.cli("lb conf ip6-src-address 2004::1")
54 except Exception:
Pierre Pfisterf588f352016-10-07 16:31:57 +010055 super(TestLB, cls).tearDownClass()
56 raise
57
58 def tearDown(self):
Klement Sekeraf62ae122016-10-11 11:47:09 +020059 super(TestLB, self).tearDown()
60 if not self.vpp_dead:
Klement Sekera7bb873a2016-11-18 07:38:42 +010061 self.logger.info(self.vapi.cli("show lb vip verbose"))
Pierre Pfisterf588f352016-10-07 16:31:57 +010062
63 def getIPv4Flow(self, id):
64 return (IP(dst="90.0.%u.%u" % (id / 255, id % 255),
Klement Sekeraf62ae122016-10-11 11:47:09 +020065 src="40.0.%u.%u" % (id / 255, id % 255)) /
Pierre Pfisterf588f352016-10-07 16:31:57 +010066 UDP(sport=10000 + id, dport=20000 + id))
67
68 def getIPv6Flow(self, id):
69 return (IPv6(dst="2001::%u" % (id), src="fd00:f00d:ffff::%u" % (id)) /
Klement Sekeraf62ae122016-10-11 11:47:09 +020070 UDP(sport=10000 + id, dport=20000 + id))
Pierre Pfisterf588f352016-10-07 16:31:57 +010071
Klement Sekeraf62ae122016-10-11 11:47:09 +020072 def generatePackets(self, src_if, isv4):
Klement Sekeradab231a2016-12-21 08:50:14 +010073 self.reset_packet_infos()
Pierre Pfisterf588f352016-10-07 16:31:57 +010074 pkts = []
75 for pktid in self.packets:
Klement Sekeradab231a2016-12-21 08:50:14 +010076 info = self.create_packet_info(src_if, self.pg1)
Pierre Pfisterf588f352016-10-07 16:31:57 +010077 payload = self.info_to_payload(info)
78 ip = self.getIPv4Flow(pktid) if isv4 else self.getIPv6Flow(pktid)
Klement Sekeraf62ae122016-10-11 11:47:09 +020079 packet = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
80 ip /
81 Raw(payload))
Pierre Pfisterf588f352016-10-07 16:31:57 +010082 self.extend_packet(packet, 128)
83 info.data = packet.copy()
84 pkts.append(packet)
85 return pkts
86
87 def checkInner(self, gre, isv4):
Klement Sekeraf62ae122016-10-11 11:47:09 +020088 IPver = IP if isv4 else IPv6
Pierre Pfisterf588f352016-10-07 16:31:57 +010089 self.assertEqual(gre.proto, 0x0800 if isv4 else 0x86DD)
90 self.assertEqual(gre.flags, 0)
91 self.assertEqual(gre.version, 0)
Klement Sekeraf62ae122016-10-11 11:47:09 +020092 inner = IPver(str(gre.payload))
93 payload_info = self.payload_to_info(str(inner[Raw]))
Klement Sekeradab231a2016-12-21 08:50:14 +010094 self.info = self.packet_infos[payload_info.index]
95 self.assertEqual(payload_info.src, self.pg0.sw_if_index)
Klement Sekeraf62ae122016-10-11 11:47:09 +020096 self.assertEqual(str(inner), str(self.info.data[IPver]))
Pierre Pfisterf588f352016-10-07 16:31:57 +010097
Hongjun Ni647f6092018-01-23 19:17:23 +080098 def checkCapture(self, encap, isv4):
Klement Sekera65cc8c02016-12-18 15:49:54 +010099 self.pg0.assert_nothing_captured()
Klement Sekeradab231a2016-12-21 08:50:14 +0100100 out = self.pg1.get_capture(len(self.packets))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100101
102 load = [0] * len(self.ass)
103 self.info = None
104 for p in out:
105 try:
106 asid = 0
107 gre = None
Hongjun Ni647f6092018-01-23 19:17:23 +0800108 if (encap == 'gre4'):
Pierre Pfisterf588f352016-10-07 16:31:57 +0100109 ip = p[IP]
Pierre Pfisterf588f352016-10-07 16:31:57 +0100110 asid = int(ip.dst.split(".")[3])
111 self.assertEqual(ip.version, 4)
112 self.assertEqual(ip.flags, 0)
113 self.assertEqual(ip.src, "39.40.41.42")
114 self.assertEqual(ip.dst, "10.0.0.%u" % asid)
115 self.assertEqual(ip.proto, 47)
116 self.assertEqual(len(ip.options), 0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200117 self.assertGreaterEqual(ip.ttl, 64)
118 gre = p[GRE]
Hongjun Ni647f6092018-01-23 19:17:23 +0800119 self.checkInner(gre, isv4)
120 elif (encap == 'gre6'):
Pierre Pfisterf588f352016-10-07 16:31:57 +0100121 ip = p[IPv6]
Pierre Pfisterf588f352016-10-07 16:31:57 +0100122 asid = ip.dst.split(":")
123 asid = asid[len(asid) - 1]
Klement Sekeraf62ae122016-10-11 11:47:09 +0200124 asid = 0 if asid == "" else int(asid)
Pierre Pfisterf588f352016-10-07 16:31:57 +0100125 self.assertEqual(ip.version, 6)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200126 self.assertEqual(ip.tc, 0)
127 self.assertEqual(ip.fl, 0)
128 self.assertEqual(ip.src, "2004::1")
129 self.assertEqual(
130 socket.inet_pton(socket.AF_INET6, ip.dst),
131 socket.inet_pton(socket.AF_INET6, "2002::%u" % asid)
132 )
133 self.assertEqual(ip.nh, 47)
134 self.assertGreaterEqual(ip.hlim, 64)
135 # self.assertEqual(len(ip.options), 0)
136 gre = GRE(str(p[IPv6].payload))
Hongjun Ni647f6092018-01-23 19:17:23 +0800137 self.checkInner(gre, isv4)
138 if (encap == 'l3dsr'):
139 ip = p[IP]
140 asid = int(ip.dst.split(".")[3])
141 self.assertEqual(ip.version, 4)
142 self.assertEqual(ip.flags, 0)
143 self.assertEqual(ip.dst, "10.0.0.%u" % asid)
144 self.assertEqual(ip.tos, 0x1c)
145 self.assertEqual(len(ip.options), 0)
Pierre Pfisterf588f352016-10-07 16:31:57 +0100146 load[asid] += 1
147 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100148 self.logger.error(ppp("Unexpected or invalid packet:", p))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100149 raise
150
151 # This is just to roughly check that the balancing algorithm
152 # is not completly biased.
153 for asid in self.ass:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200154 if load[asid] < len(self.packets) / (len(self.ass) * 2):
Gabriel Ganne8e66b9b2017-12-14 16:20:37 +0100155 self.logger.error(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200156 "ASS is not balanced: load[%d] = %d" % (asid, load[asid]))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100157 raise Exception("Load Balancer algorithm is biased")
158
Pierre Pfisterf588f352016-10-07 16:31:57 +0100159 def test_lb_ip4_gre4(self):
160 """ Load Balancer IP4 GRE4 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200161 try:
162 self.vapi.cli("lb vip 90.0.0.0/8 encap gre4")
163 for asid in self.ass:
164 self.vapi.cli("lb as 90.0.0.0/8 10.0.0.%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100165
Klement Sekeraf62ae122016-10-11 11:47:09 +0200166 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
167 self.pg_enable_capture(self.pg_interfaces)
168 self.pg_start()
Hongjun Ni647f6092018-01-23 19:17:23 +0800169 self.checkCapture(encap='gre4', isv4=True)
Pierre Pfisterf588f352016-10-07 16:31:57 +0100170
Klement Sekeraf62ae122016-10-11 11:47:09 +0200171 finally:
172 for asid in self.ass:
173 self.vapi.cli("lb as 90.0.0.0/8 10.0.0.%u del" % (asid))
174 self.vapi.cli("lb vip 90.0.0.0/8 encap gre4 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100175 self.vapi.cli("test lb flowtable flush")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100176
177 def test_lb_ip6_gre4(self):
178 """ Load Balancer IP6 GRE4 """
179
Klement Sekeraf62ae122016-10-11 11:47:09 +0200180 try:
181 self.vapi.cli("lb vip 2001::/16 encap gre4")
182 for asid in self.ass:
183 self.vapi.cli("lb as 2001::/16 10.0.0.%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100184
Klement Sekeraf62ae122016-10-11 11:47:09 +0200185 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
186 self.pg_enable_capture(self.pg_interfaces)
187 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100188
Hongjun Ni647f6092018-01-23 19:17:23 +0800189 self.checkCapture(encap='gre4', isv4=False)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200190 finally:
191 for asid in self.ass:
192 self.vapi.cli("lb as 2001::/16 10.0.0.%u del" % (asid))
193 self.vapi.cli("lb vip 2001::/16 encap gre4 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100194 self.vapi.cli("test lb flowtable flush")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100195
196 def test_lb_ip4_gre6(self):
197 """ Load Balancer IP4 GRE6 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200198 try:
199 self.vapi.cli("lb vip 90.0.0.0/8 encap gre6")
200 for asid in self.ass:
201 self.vapi.cli("lb as 90.0.0.0/8 2002::%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100202
Klement Sekeraf62ae122016-10-11 11:47:09 +0200203 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
204 self.pg_enable_capture(self.pg_interfaces)
205 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100206
Hongjun Ni647f6092018-01-23 19:17:23 +0800207 self.checkCapture(encap='gre6', isv4=True)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200208 finally:
209 for asid in self.ass:
Gabriel Ganneaa0dda42017-10-24 15:18:57 +0200210 self.vapi.cli("lb as 90.0.0.0/8 2002::%u del" % (asid))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200211 self.vapi.cli("lb vip 90.0.0.0/8 encap gre6 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100212 self.vapi.cli("test lb flowtable flush")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100213
214 def test_lb_ip6_gre6(self):
215 """ Load Balancer IP6 GRE6 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200216 try:
217 self.vapi.cli("lb vip 2001::/16 encap gre6")
218 for asid in self.ass:
219 self.vapi.cli("lb as 2001::/16 2002::%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100220
Klement Sekeraf62ae122016-10-11 11:47:09 +0200221 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
222 self.pg_enable_capture(self.pg_interfaces)
223 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100224
Hongjun Ni647f6092018-01-23 19:17:23 +0800225 self.checkCapture(encap='gre6', isv4=False)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200226 finally:
227 for asid in self.ass:
228 self.vapi.cli("lb as 2001::/16 2002::%u del" % (asid))
229 self.vapi.cli("lb vip 2001::/16 encap gre6 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100230 self.vapi.cli("test lb flowtable flush")
Hongjun Ni647f6092018-01-23 19:17:23 +0800231
232 def test_lb_ip4_l3dsr(self):
233 """ Load Balancer IP4 L3DSR """
234 try:
235 self.vapi.cli("lb vip 90.0.0.0/8 encap l3dsr dscp 7")
236 for asid in self.ass:
237 self.vapi.cli("lb as 90.0.0.0/8 10.0.0.%u" % (asid))
238
239 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
240 self.pg_enable_capture(self.pg_interfaces)
241 self.pg_start()
242 self.checkCapture(encap='l3dsr', isv4=True)
243
244 finally:
245 for asid in self.ass:
246 self.vapi.cli("lb as 90.0.0.0/8 10.0.0.%u del" % (asid))
247 self.vapi.cli("lb vip 90.0.0.0/8 encap l3dsr dscp 7 del")
248 self.vapi.cli("test lb flowtable flush")