pg: add GSO support
[vpp.git] / test / test_gso.py
1 #!/usr/bin/env python
2 """GSO functional tests"""
3
4 #
5 # Add tests for:
6 # - GSO
7 # - Verify that sending Jumbo frame without GSO enabled correctly
8 # - Verify that sending Jumbo frame with GSO enabled correctly
9 # - Verify that sending Jumbo frame with GSO enabled only on ingress interface
10 #
11 import unittest
12
13 from scapy.packet import Raw
14 from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig
15 from scapy.layers.inet import TCP, ICMP
16 from scapy.layers.vxlan import VXLAN
17 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
18
19 from framework import VppTestCase, VppTestRunner
20 from vpp_object import VppObject
21 from vpp_interface import VppInterface
22 from vpp_ip import DpoProto
23 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
24 from socket import AF_INET, AF_INET6, inet_pton
25 from util import reassemble4
26
27
28 """ Test_gso is a subclass of VPPTestCase classes.
29     GSO tests.
30 """
31
32
33 class TestGSO(VppTestCase):
34     """ GSO Test Case """
35
36     def __init__(self, *args):
37         VppTestCase.__init__(self, *args)
38
39     @classmethod
40     def setUpClass(self):
41         super(TestGSO, self).setUpClass()
42
43     @classmethod
44     def tearDownClass(self):
45         super(TestGSO, self).tearDownClass()
46
47     def setUp(self):
48         super(TestGSO, self).setUp()
49
50     def tearDown(self):
51         super(TestGSO, self).tearDown()
52         if not self.vpp_dead:
53             for i in self.pg_interfaces:
54                 i.unconfig_ip4()
55                 i.unconfig_ip6()
56                 i.admin_down()
57
58     def test_gso(self):
59         """ GSO test """
60         #
61         # Send jumbo frame with gso disabled and DF bit is set
62         #
63         self.create_pg_interfaces(range(2))
64         for i in self.pg_interfaces:
65             i.admin_up()
66             i.config_ip4()
67             i.config_ip6()
68             i.disable_ipv6_ra()
69             i.resolve_arp()
70             i.resolve_ndp()
71
72         p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
73               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4,
74                  flags='DF') /
75               TCP(sport=1234, dport=1234) /
76               Raw('\xa5' * 65200))
77
78         rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
79
80         for rx in rxs:
81             self.assertEqual(rx[Ether].src, self.pg0.local_mac)
82             self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
83             self.assertEqual(rx[IP].src, self.pg0.local_ip4)
84             self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
85             self.assertEqual(rx[ICMP].type, 3)  # "dest-unreach"
86             self.assertEqual(rx[ICMP].code, 4)  # "fragmentation-needed"
87
88         #
89         # Send jumbo frame with gso enabled and DF bit is set
90         # input and output interfaces support GSO
91         #
92         self.create_pg_interfaces(range(2, 4), 1, 1460)
93         for i in self.pg_interfaces:
94             i.admin_up()
95             i.config_ip4()
96             i.config_ip6()
97             i.disable_ipv6_ra()
98             i.resolve_arp()
99             i.resolve_ndp()
100
101         p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
102                IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
103                   flags='DF') /
104                TCP(sport=1234, dport=1234) /
105                Raw('\xa5' * 65200))
106
107         rxs = self.send_and_expect(self.pg2, [p41], self.pg3)
108
109         for rx in rxs:
110             self.assertEqual(rx[Ether].src, self.pg3.local_mac)
111             self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
112             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
113             self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
114             self.assertEqual(rx[IP].len, 65240)  # 65200 + 20 (IP) + 20 (TCP)
115             self.assertEqual(rx[TCP].sport, 1234)
116             self.assertEqual(rx[TCP].dport, 1234)
117
118         #
119         # Send jumbo frame with gso enabled only on input interface
120         # and DF bit is set. GSO packet will be chunked into gso_size
121         # data payload
122         #
123         self.create_pg_interfaces(range(4, 5))
124         for i in self.pg_interfaces:
125             i.admin_up()
126             i.config_ip4()
127             i.config_ip6()
128             i.disable_ipv6_ra()
129             i.resolve_arp()
130             i.resolve_ndp()
131
132         p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
133                IP(src=self.pg2.remote_ip4, dst=self.pg4.remote_ip4,
134                   flags='DF') /
135                TCP(sport=1234, dport=1234) /
136                Raw('\xa5' * 65200))
137
138         rxs = self.send_and_expect(self.pg2, [p42], self.pg4, 45)
139         size = 0
140         for rx in rxs:
141             self.assertEqual(rx[Ether].src, self.pg4.local_mac)
142             self.assertEqual(rx[Ether].dst, self.pg4.remote_mac)
143             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
144             self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
145             self.assertEqual(rx[TCP].sport, 1234)
146             self.assertEqual(rx[TCP].dport, 1234)
147
148         size = rxs[44][TCP].seq + rxs[44][IP].len - 20 - 20
149         self.assertEqual(size, 65200)
150
151         #
152         # Send jumbo frame with gso enabled only on input interface
153         # and DF bit is unset. GSO packet will be fragmented.
154         #
155         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
156
157         p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
158                IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
159                TCP(sport=1234, dport=1234) /
160                Raw('\xa5' * 65200))
161
162         rxs = self.send_and_expect(self.pg2, [p43], self.pg1, 119)
163         size = 0
164         for rx in rxs:
165             rx.show()
166             self.assertEqual(rx[Ether].src, self.pg1.local_mac)
167             self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
168             self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
169             self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
170             size += rx[IP].len - 20
171         size -= 20  # TCP header
172         self.assertEqual(size, 65200)
173
174 if __name__ == '__main__':
175     unittest.main(testRunner=VppTestRunner)