blob: e653b60b0ab62c4cb0e578f68c53499143e359b7 [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
18
19 As stated in comments below, GRE has issues with IPv6.
20 All test cases involving IPv6 are executed, but
21 received packets are not parsed and checked.
22
23"""
24
25
26class TestLB(VppTestCase):
Pierre Pfisterf588f352016-10-07 16:31:57 +010027 """ Load Balancer Test Case """
28
29 @classmethod
30 def setUpClass(cls):
31 super(TestLB, cls).setUpClass()
32
33 cls.ass = range(5)
34 cls.packets = range(100)
35
36 try:
Klement Sekeraf62ae122016-10-11 11:47:09 +020037 cls.create_pg_interfaces(range(2))
38 cls.interfaces = list(cls.pg_interfaces)
Pierre Pfisterf588f352016-10-07 16:31:57 +010039
Klement Sekeraf62ae122016-10-11 11:47:09 +020040 for i in cls.interfaces:
41 i.admin_up()
42 i.config_ip4()
43 i.config_ip6()
44 i.disable_ipv6_ra()
45 i.resolve_arp()
46 i.resolve_ndp()
47 dst4 = socket.inet_pton(socket.AF_INET, "10.0.0.0")
48 dst6 = socket.inet_pton(socket.AF_INET6, "2002::")
49 cls.vapi.ip_add_del_route(dst4, 24, cls.pg1.remote_ip4n)
50 cls.vapi.ip_add_del_route(dst6, 16, cls.pg1.remote_ip6n, is_ipv6=1)
51 cls.vapi.cli("lb conf ip4-src-address 39.40.41.42")
52 cls.vapi.cli("lb conf ip6-src-address 2004::1")
53 except Exception:
Pierre Pfisterf588f352016-10-07 16:31:57 +010054 super(TestLB, cls).tearDownClass()
55 raise
56
57 def tearDown(self):
Klement Sekeraf62ae122016-10-11 11:47:09 +020058 super(TestLB, self).tearDown()
59 if not self.vpp_dead:
Klement Sekera7bb873a2016-11-18 07:38:42 +010060 self.logger.info(self.vapi.cli("show lb vip verbose"))
Pierre Pfisterf588f352016-10-07 16:31:57 +010061
62 def getIPv4Flow(self, id):
63 return (IP(dst="90.0.%u.%u" % (id / 255, id % 255),
Klement Sekeraf62ae122016-10-11 11:47:09 +020064 src="40.0.%u.%u" % (id / 255, id % 255)) /
Pierre Pfisterf588f352016-10-07 16:31:57 +010065 UDP(sport=10000 + id, dport=20000 + id))
66
67 def getIPv6Flow(self, id):
68 return (IPv6(dst="2001::%u" % (id), src="fd00:f00d:ffff::%u" % (id)) /
Klement Sekeraf62ae122016-10-11 11:47:09 +020069 UDP(sport=10000 + id, dport=20000 + id))
Pierre Pfisterf588f352016-10-07 16:31:57 +010070
Klement Sekeraf62ae122016-10-11 11:47:09 +020071 def generatePackets(self, src_if, isv4):
Klement Sekeradab231a2016-12-21 08:50:14 +010072 self.reset_packet_infos()
Pierre Pfisterf588f352016-10-07 16:31:57 +010073 pkts = []
74 for pktid in self.packets:
Klement Sekeradab231a2016-12-21 08:50:14 +010075 info = self.create_packet_info(src_if, self.pg1)
Pierre Pfisterf588f352016-10-07 16:31:57 +010076 payload = self.info_to_payload(info)
77 ip = self.getIPv4Flow(pktid) if isv4 else self.getIPv6Flow(pktid)
Klement Sekeraf62ae122016-10-11 11:47:09 +020078 packet = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
79 ip /
80 Raw(payload))
Pierre Pfisterf588f352016-10-07 16:31:57 +010081 self.extend_packet(packet, 128)
82 info.data = packet.copy()
83 pkts.append(packet)
84 return pkts
85
86 def checkInner(self, gre, isv4):
Klement Sekeraf62ae122016-10-11 11:47:09 +020087 IPver = IP if isv4 else IPv6
Pierre Pfisterf588f352016-10-07 16:31:57 +010088 self.assertEqual(gre.proto, 0x0800 if isv4 else 0x86DD)
89 self.assertEqual(gre.flags, 0)
90 self.assertEqual(gre.version, 0)
Klement Sekeraf62ae122016-10-11 11:47:09 +020091 inner = IPver(str(gre.payload))
92 payload_info = self.payload_to_info(str(inner[Raw]))
Klement Sekeradab231a2016-12-21 08:50:14 +010093 self.info = self.packet_infos[payload_info.index]
94 self.assertEqual(payload_info.src, self.pg0.sw_if_index)
Klement Sekeraf62ae122016-10-11 11:47:09 +020095 self.assertEqual(str(inner), str(self.info.data[IPver]))
Pierre Pfisterf588f352016-10-07 16:31:57 +010096
97 def checkCapture(self, gre4, isv4):
Klement Sekera65cc8c02016-12-18 15:49:54 +010098 self.pg0.assert_nothing_captured()
Klement Sekeradab231a2016-12-21 08:50:14 +010099 out = self.pg1.get_capture(len(self.packets))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100100
101 load = [0] * len(self.ass)
102 self.info = None
103 for p in out:
104 try:
105 asid = 0
106 gre = None
107 if gre4:
108 ip = p[IP]
Pierre Pfisterf588f352016-10-07 16:31:57 +0100109 asid = int(ip.dst.split(".")[3])
110 self.assertEqual(ip.version, 4)
111 self.assertEqual(ip.flags, 0)
112 self.assertEqual(ip.src, "39.40.41.42")
113 self.assertEqual(ip.dst, "10.0.0.%u" % asid)
114 self.assertEqual(ip.proto, 47)
115 self.assertEqual(len(ip.options), 0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200116 self.assertGreaterEqual(ip.ttl, 64)
117 gre = p[GRE]
Pierre Pfisterf588f352016-10-07 16:31:57 +0100118 else:
119 ip = p[IPv6]
Pierre Pfisterf588f352016-10-07 16:31:57 +0100120 asid = ip.dst.split(":")
121 asid = asid[len(asid) - 1]
Klement Sekeraf62ae122016-10-11 11:47:09 +0200122 asid = 0 if asid == "" else int(asid)
Pierre Pfisterf588f352016-10-07 16:31:57 +0100123 self.assertEqual(ip.version, 6)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200124 self.assertEqual(ip.tc, 0)
125 self.assertEqual(ip.fl, 0)
126 self.assertEqual(ip.src, "2004::1")
127 self.assertEqual(
128 socket.inet_pton(socket.AF_INET6, ip.dst),
129 socket.inet_pton(socket.AF_INET6, "2002::%u" % asid)
130 )
131 self.assertEqual(ip.nh, 47)
132 self.assertGreaterEqual(ip.hlim, 64)
133 # self.assertEqual(len(ip.options), 0)
134 gre = GRE(str(p[IPv6].payload))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100135 self.checkInner(gre, isv4)
136 load[asid] += 1
137 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100138 self.logger.error(ppp("Unexpected or invalid packet:", p))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100139 raise
140
141 # This is just to roughly check that the balancing algorithm
142 # is not completly biased.
143 for asid in self.ass:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200144 if load[asid] < len(self.packets) / (len(self.ass) * 2):
Gabriel Ganne8e66b9b2017-12-14 16:20:37 +0100145 self.logger.error(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200146 "ASS is not balanced: load[%d] = %d" % (asid, load[asid]))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100147 raise Exception("Load Balancer algorithm is biased")
148
Pierre Pfisterf588f352016-10-07 16:31:57 +0100149 def test_lb_ip4_gre4(self):
150 """ Load Balancer IP4 GRE4 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200151 try:
152 self.vapi.cli("lb vip 90.0.0.0/8 encap gre4")
153 for asid in self.ass:
154 self.vapi.cli("lb as 90.0.0.0/8 10.0.0.%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100155
Klement Sekeraf62ae122016-10-11 11:47:09 +0200156 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
157 self.pg_enable_capture(self.pg_interfaces)
158 self.pg_start()
159 self.checkCapture(gre4=True, isv4=True)
Pierre Pfisterf588f352016-10-07 16:31:57 +0100160
Klement Sekeraf62ae122016-10-11 11:47:09 +0200161 finally:
162 for asid in self.ass:
163 self.vapi.cli("lb as 90.0.0.0/8 10.0.0.%u del" % (asid))
164 self.vapi.cli("lb vip 90.0.0.0/8 encap gre4 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100165 self.vapi.cli("test lb flowtable flush")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100166
167 def test_lb_ip6_gre4(self):
168 """ Load Balancer IP6 GRE4 """
169
Klement Sekeraf62ae122016-10-11 11:47:09 +0200170 try:
171 self.vapi.cli("lb vip 2001::/16 encap gre4")
172 for asid in self.ass:
173 self.vapi.cli("lb as 2001::/16 10.0.0.%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100174
Klement Sekeraf62ae122016-10-11 11:47:09 +0200175 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
176 self.pg_enable_capture(self.pg_interfaces)
177 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100178
Matej Klottond6338ab2016-11-10 15:36:19 +0100179 self.checkCapture(gre4=True, isv4=False)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200180 finally:
181 for asid in self.ass:
182 self.vapi.cli("lb as 2001::/16 10.0.0.%u del" % (asid))
183 self.vapi.cli("lb vip 2001::/16 encap gre4 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100184 self.vapi.cli("test lb flowtable flush")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100185
186 def test_lb_ip4_gre6(self):
187 """ Load Balancer IP4 GRE6 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200188 try:
189 self.vapi.cli("lb vip 90.0.0.0/8 encap gre6")
190 for asid in self.ass:
191 self.vapi.cli("lb as 90.0.0.0/8 2002::%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100192
Klement Sekeraf62ae122016-10-11 11:47:09 +0200193 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
194 self.pg_enable_capture(self.pg_interfaces)
195 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100196
Matej Klottond6338ab2016-11-10 15:36:19 +0100197 self.checkCapture(gre4=False, isv4=True)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200198 finally:
199 for asid in self.ass:
Gabriel Ganneaa0dda42017-10-24 15:18:57 +0200200 self.vapi.cli("lb as 90.0.0.0/8 2002::%u del" % (asid))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200201 self.vapi.cli("lb vip 90.0.0.0/8 encap gre6 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100202 self.vapi.cli("test lb flowtable flush")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100203
204 def test_lb_ip6_gre6(self):
205 """ Load Balancer IP6 GRE6 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200206 try:
207 self.vapi.cli("lb vip 2001::/16 encap gre6")
208 for asid in self.ass:
209 self.vapi.cli("lb as 2001::/16 2002::%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100210
Klement Sekeraf62ae122016-10-11 11:47:09 +0200211 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
212 self.pg_enable_capture(self.pg_interfaces)
213 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100214
Matej Klottond6338ab2016-11-10 15:36:19 +0100215 self.checkCapture(gre4=False, isv4=False)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200216 finally:
217 for asid in self.ass:
218 self.vapi.cli("lb as 2001::/16 2002::%u del" % (asid))
219 self.vapi.cli("lb vip 2001::/16 encap gre6 del")
Gabriel Ganneb3d1b202017-10-30 15:44:31 +0100220 self.vapi.cli("test lb flowtable flush")