blob: 76e2ec91cebf42116bd71a93802751aee38cda8b [file] [log] [blame]
Hongjun Nic91f5022017-08-29 01:00:42 +08001import socket
2import unittest
3
4from scapy.layers.inet import IP, UDP
5from scapy.layers.inet6 import IPv6
6from scapy.layers.l2 import Ether
7from scapy.packet import Raw
8
9from framework import VppTestCase, running_extended_tests
10from util import ppp
11
12""" TestKP is a subclass of VPPTestCase classes.
13
14 TestKP class defines Four NAT test case for:
15 - IP4 to IP4 NAT
16 - IP4 to IP6 NAT
17 - IP6 to IP4 NAT
18 - IP6 to IP6 NAT
19
20"""
21
22
23class TestKP(VppTestCase):
24 """ Kube-proxy Test Case """
25
26 @classmethod
27 def setUpClass(cls):
28 super(TestKP, cls).setUpClass()
29 cls.pods = range(5)
30 cls.packets = range(5)
31
32 try:
33 cls.create_pg_interfaces(range(2))
34 cls.interfaces = list(cls.pg_interfaces)
35
36 for i in cls.interfaces:
37 i.admin_up()
38 i.config_ip4()
39 i.config_ip6()
40 i.disable_ipv6_ra()
41 i.resolve_arp()
42 i.resolve_ndp()
43 dst4 = socket.inet_pton(socket.AF_INET, "10.0.0.0")
44 dst6 = socket.inet_pton(socket.AF_INET6, "2002::")
45 cls.vapi.ip_add_del_route(dst4, 24, cls.pg1.remote_ip4n)
46 cls.vapi.ip_add_del_route(dst6, 16, cls.pg1.remote_ip6n, is_ipv6=1)
47 except Exception:
48 super(TestKP, cls).tearDownClass()
49 raise
50
51 def tearDown(self):
52 super(TestKP, self).tearDown()
53 if not self.vpp_dead:
54 self.logger.info(self.vapi.cli("show ku vip verbose"))
55
56 def getIPv4Flow(self, id):
57 return (IP(dst="90.0.%u.%u" % (id / 255, id % 255),
58 src="40.0.%u.%u" % (id / 255, id % 255)) /
59 UDP(sport=10000 + id, dport=3306))
60
61 def getIPv6Flow(self, id):
62 return (IPv6(dst="2001::%u" % (id), src="fd00:f00d:ffff::%u" % (id)) /
63 UDP(sport=10000 + id, dport=3306))
64
65 def generatePackets(self, src_if, isv4):
66 self.reset_packet_infos()
67 pkts = []
68 for pktid in self.packets:
69 info = self.create_packet_info(src_if, self.pg1)
70 payload = self.info_to_payload(info)
71 ip = self.getIPv4Flow(pktid) if isv4 else self.getIPv6Flow(pktid)
72 packet = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
73 ip /
74 Raw(payload))
75 self.extend_packet(packet, 128)
76 info.data = packet.copy()
77 pkts.append(packet)
78 return pkts
79
80 def checkInner(self, udp):
81 self.assertEqual(udp.dport, 3307)
82
83 def checkCapture(self, nat4, isv4):
84 self.pg0.assert_nothing_captured()
85 out = self.pg1.get_capture(len(self.packets))
86
87 load = [0] * len(self.pods)
88 self.info = None
89 for p in out:
90 try:
91 podid = 0
92 udp = None
93 if nat4:
94 ip = p[IP]
95 podid = int(ip.dst.split(".")[3])
96 self.assertEqual(ip.version, 4)
97 self.assertEqual(ip.flags, 0)
98 self.assertEqual(ip.dst, "10.0.0.%u" % podid)
99 self.assertEqual(ip.proto, 17)
100 self.assertEqual(len(ip.options), 0)
101 self.assertGreaterEqual(ip.ttl, 63)
102 udp = p[UDP]
103 else:
104 ip = p[IPv6]
105 podid = ip.dst.split(":")
106 podid = podid[len(podid) - 1]
107 podid = 0 if podid == "" else int(podid)
108 self.assertEqual(ip.version, 6)
109 self.assertEqual(ip.tc, 0)
110 self.assertEqual(ip.fl, 0)
111 self.assertEqual(
112 socket.inet_pton(socket.AF_INET6, ip.dst),
113 socket.inet_pton(socket.AF_INET6, "2002::%u" % podid)
114 )
115 self.assertEqual(ip.nh, 17)
116 self.assertGreaterEqual(ip.hlim, 63)
117 udp = UDP(str(p[IPv6].payload))
118 # self.assertEqual(len(ip.options), 0)
119 self.checkInner(udp)
120 load[podid] += 1
121 except:
122 self.logger.error(ppp("Unexpected or invalid packet:", p))
123 raise
124
125 # This is just to roughly check that the balancing algorithm
126 # is not completly biased.
127 for podid in self.pods:
128 if load[podid] < len(self.packets) / (len(self.pods) * 2):
129 self.log(
130 "Pod isn't balanced: load[%d] = %d" % (podid, load[podid]))
131 raise Exception("Kube-proxy algorithm is biased")
132
133 def test_kp_ip4_nat4(self):
134 """ Kube-proxy NAT44 """
135 try:
136 self.vapi.cli("ku vip 90.0.0.0/8 port 3306 target_port 3307 nat4")
137 for podid in self.pods:
138 self.vapi.cli("ku pod 90.0.0.0/8 10.0.0.%u" % (podid))
139
140 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
141 self.pg_enable_capture(self.pg_interfaces)
142 self.pg_start()
143 self.checkCapture(nat4=True, isv4=True)
144
145 finally:
146 for podid in self.pods:
147 self.vapi.cli("ku pod 90.0.0.0/8 10.0.0.%u del" % (podid))
148 self.vapi.cli("ku vip 90.0.0.0/8 nat4 del")
Gabriel Ganne4c8a4542017-12-19 16:13:44 +0100149 self.vapi.cli("test kube-proxy flowtable flush")
Hongjun Nic91f5022017-08-29 01:00:42 +0800150
Klement Sekerafa5fb2d2018-02-21 11:13:39 +0100151 @unittest.skip("this test is broken")
Hongjun Nic91f5022017-08-29 01:00:42 +0800152 def test_kp_ip6_nat4(self):
153 """ Kube-proxy NAT64 """
154
155 try:
156 self.vapi.cli("ku vip 90.0.0.0/8 port 3306 target_port 3307 nat4")
157 for podid in self.pods:
158 self.vapi.cli("ku pod 2001::/16 10.0.0.%u" % (podid))
159
160 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
161 self.pg_enable_capture(self.pg_interfaces)
162 self.pg_start()
163
164 self.checkCapture(nat4=True, isv4=False)
165 finally:
166 for podid in self.pods:
167 self.vapi.cli("ku pod 2001::/16 10.0.0.%u del" % (podid))
168 self.vapi.cli("ku vip 2001::/16 nat4 del")
Gabriel Ganne4c8a4542017-12-19 16:13:44 +0100169 self.vapi.cli("test kube-proxy flowtable flush")
Hongjun Nic91f5022017-08-29 01:00:42 +0800170
Klement Sekerafa5fb2d2018-02-21 11:13:39 +0100171 @unittest.skip("this test is broken")
Hongjun Nic91f5022017-08-29 01:00:42 +0800172 def test_kp_ip4_nat6(self):
173 """ Kube-proxy NAT46 """
174 try:
175 self.vapi.cli("ku vip 90.0.0.0/8 port 3306 target_port 3307 nat6")
176 for podid in self.pods:
177 self.vapi.cli("ku pod 90.0.0.0/8 2002::%u" % (podid))
178
179 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
180 self.pg_enable_capture(self.pg_interfaces)
181 self.pg_start()
182
183 self.checkCapture(nat4=False, isv4=True)
184 finally:
185 for podid in self.pods:
Gabriel Ganne4c8a4542017-12-19 16:13:44 +0100186 self.vapi.cli("ku pod 90.0.0.0/8 2002::%u del" % (podid))
Hongjun Nic91f5022017-08-29 01:00:42 +0800187 self.vapi.cli("ku vip 90.0.0.0/8 nat6 del")
Gabriel Ganne4c8a4542017-12-19 16:13:44 +0100188 self.vapi.cli("test kube-proxy flowtable flush")
Hongjun Nic91f5022017-08-29 01:00:42 +0800189
190 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
191 def test_kp_ip6_nat6(self):
192 """ Kube-proxy NAT66 """
193 try:
Gabriel Ganne4c8a4542017-12-19 16:13:44 +0100194 self.vapi.cli("ku vip 2001::/16 port 3306 target_port 3307 nat6")
Hongjun Nic91f5022017-08-29 01:00:42 +0800195 for podid in self.pods:
196 self.vapi.cli("ku pod 2001::/16 2002::%u" % (podid))
197
198 self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
199 self.pg_enable_capture(self.pg_interfaces)
200 self.pg_start()
201
202 self.checkCapture(nat4=False, isv4=False)
203 finally:
204 for podid in self.pods:
205 self.vapi.cli("ku pod 2001::/16 2002::%u del" % (podid))
206 self.vapi.cli("ku vip 2001::/16 nat6 del")
Gabriel Ganne4c8a4542017-12-19 16:13:44 +0100207 self.vapi.cli("test kube-proxy flowtable flush")