blob: db4d46b2ded64e4cc53ecc92a06fb072646ccbd4 [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):
145 self.log(
146 "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")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100165
166 def test_lb_ip6_gre4(self):
167 """ Load Balancer IP6 GRE4 """
168
Klement Sekeraf62ae122016-10-11 11:47:09 +0200169 try:
170 self.vapi.cli("lb vip 2001::/16 encap gre4")
171 for asid in self.ass:
172 self.vapi.cli("lb as 2001::/16 10.0.0.%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100173
Klement Sekeraf62ae122016-10-11 11:47:09 +0200174 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
175 self.pg_enable_capture(self.pg_interfaces)
176 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100177
Matej Klottond6338ab2016-11-10 15:36:19 +0100178 self.checkCapture(gre4=True, isv4=False)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200179 finally:
180 for asid in self.ass:
181 self.vapi.cli("lb as 2001::/16 10.0.0.%u del" % (asid))
182 self.vapi.cli("lb vip 2001::/16 encap gre4 del")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100183
184 def test_lb_ip4_gre6(self):
185 """ Load Balancer IP4 GRE6 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200186 try:
187 self.vapi.cli("lb vip 90.0.0.0/8 encap gre6")
188 for asid in self.ass:
189 self.vapi.cli("lb as 90.0.0.0/8 2002::%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100190
Klement Sekeraf62ae122016-10-11 11:47:09 +0200191 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
192 self.pg_enable_capture(self.pg_interfaces)
193 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100194
Matej Klottond6338ab2016-11-10 15:36:19 +0100195 self.checkCapture(gre4=False, isv4=True)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200196 finally:
197 for asid in self.ass:
Gabriel Ganneaa0dda42017-10-24 15:18:57 +0200198 self.vapi.cli("lb as 90.0.0.0/8 2002::%u del" % (asid))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200199 self.vapi.cli("lb vip 90.0.0.0/8 encap gre6 del")
Pierre Pfisterf588f352016-10-07 16:31:57 +0100200
201 def test_lb_ip6_gre6(self):
202 """ Load Balancer IP6 GRE6 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200203 try:
204 self.vapi.cli("lb vip 2001::/16 encap gre6")
205 for asid in self.ass:
206 self.vapi.cli("lb as 2001::/16 2002::%u" % (asid))
Pierre Pfisterf588f352016-10-07 16:31:57 +0100207
Klement Sekeraf62ae122016-10-11 11:47:09 +0200208 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
209 self.pg_enable_capture(self.pg_interfaces)
210 self.pg_start()
Pierre Pfisterf588f352016-10-07 16:31:57 +0100211
Matej Klottond6338ab2016-11-10 15:36:19 +0100212 self.checkCapture(gre4=False, isv4=False)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200213 finally:
214 for asid in self.ass:
215 self.vapi.cli("lb as 2001::/16 2002::%u del" % (asid))
216 self.vapi.cli("lb vip 2001::/16 encap gre6 del")