xref: /aosp_15_r20/kernel/tests/net/test/tcp_test.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2015 The Android Open Source Project
4*2f2c4c7aSAndroid Build Coastguard Worker#
5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*2f2c4c7aSAndroid Build Coastguard Worker#
9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0
10*2f2c4c7aSAndroid Build Coastguard Worker#
11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License.
16*2f2c4c7aSAndroid Build Coastguard Worker
17*2f2c4c7aSAndroid Build Coastguard Workerimport time
18*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
19*2f2c4c7aSAndroid Build Coastguard Worker
20*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
21*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base
22*2f2c4c7aSAndroid Build Coastguard Workerimport packets
23*2f2c4c7aSAndroid Build Coastguard Worker
24*2f2c4c7aSAndroid Build Coastguard Worker# TCP states. See include/net/tcp_states.h.
25*2f2c4c7aSAndroid Build Coastguard WorkerTCP_ESTABLISHED = 1
26*2f2c4c7aSAndroid Build Coastguard WorkerTCP_SYN_SENT = 2
27*2f2c4c7aSAndroid Build Coastguard WorkerTCP_SYN_RECV = 3
28*2f2c4c7aSAndroid Build Coastguard WorkerTCP_FIN_WAIT1 = 4
29*2f2c4c7aSAndroid Build Coastguard WorkerTCP_FIN_WAIT2 = 5
30*2f2c4c7aSAndroid Build Coastguard WorkerTCP_TIME_WAIT = 6
31*2f2c4c7aSAndroid Build Coastguard WorkerTCP_CLOSE = 7
32*2f2c4c7aSAndroid Build Coastguard WorkerTCP_CLOSE_WAIT = 8
33*2f2c4c7aSAndroid Build Coastguard WorkerTCP_LAST_ACK = 9
34*2f2c4c7aSAndroid Build Coastguard WorkerTCP_LISTEN = 10
35*2f2c4c7aSAndroid Build Coastguard WorkerTCP_CLOSING = 11
36*2f2c4c7aSAndroid Build Coastguard WorkerTCP_NEW_SYN_RECV = 12
37*2f2c4c7aSAndroid Build Coastguard Worker
38*2f2c4c7aSAndroid Build Coastguard WorkerTCP_NOT_YET_ACCEPTED = -1
39*2f2c4c7aSAndroid Build Coastguard Worker
40*2f2c4c7aSAndroid Build Coastguard Worker
41*2f2c4c7aSAndroid Build Coastguard Workerclass TcpBaseTest(multinetwork_base.MultiNetworkBaseTest):
42*2f2c4c7aSAndroid Build Coastguard Worker
43*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self, *args, **kwargs):
44*2f2c4c7aSAndroid Build Coastguard Worker    super().__init__(*args, **kwargs)
45*2f2c4c7aSAndroid Build Coastguard Worker    self.accepted = None
46*2f2c4c7aSAndroid Build Coastguard Worker    self.s = None
47*2f2c4c7aSAndroid Build Coastguard Worker    self.last_packet = None
48*2f2c4c7aSAndroid Build Coastguard Worker    self.sent_fin = False
49*2f2c4c7aSAndroid Build Coastguard Worker
50*2f2c4c7aSAndroid Build Coastguard Worker  def CloseSockets(self):
51*2f2c4c7aSAndroid Build Coastguard Worker    if self.accepted:
52*2f2c4c7aSAndroid Build Coastguard Worker      self.accepted.close()
53*2f2c4c7aSAndroid Build Coastguard Worker      self.accepted = None
54*2f2c4c7aSAndroid Build Coastguard Worker    if self.s:
55*2f2c4c7aSAndroid Build Coastguard Worker      self.s.close()
56*2f2c4c7aSAndroid Build Coastguard Worker      self.s = None
57*2f2c4c7aSAndroid Build Coastguard Worker
58*2f2c4c7aSAndroid Build Coastguard Worker  def tearDown(self):
59*2f2c4c7aSAndroid Build Coastguard Worker    self.CloseSockets()
60*2f2c4c7aSAndroid Build Coastguard Worker    super(TcpBaseTest, self).tearDown()
61*2f2c4c7aSAndroid Build Coastguard Worker
62*2f2c4c7aSAndroid Build Coastguard Worker  def OpenListenSocket(self, version, netid):
63*2f2c4c7aSAndroid Build Coastguard Worker    family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version]
64*2f2c4c7aSAndroid Build Coastguard Worker    address = {4: "0.0.0.0", 5: "::", 6: "::"}[version]
65*2f2c4c7aSAndroid Build Coastguard Worker    s = net_test.Socket(family, SOCK_STREAM, IPPROTO_TCP)
66*2f2c4c7aSAndroid Build Coastguard Worker    # We haven't configured inbound iptables marking, so bind explicitly.
67*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s, netid, "mark")
68*2f2c4c7aSAndroid Build Coastguard Worker    self.port = net_test.BindRandomPort(version, s)
69*2f2c4c7aSAndroid Build Coastguard Worker    return s
70*2f2c4c7aSAndroid Build Coastguard Worker
71*2f2c4c7aSAndroid Build Coastguard Worker  def _ReceiveAndExpectResponse(self, netid, packet, reply, msg):
72*2f2c4c7aSAndroid Build Coastguard Worker    pkt = super(TcpBaseTest, self)._ReceiveAndExpectResponse(netid, packet,
73*2f2c4c7aSAndroid Build Coastguard Worker                                                             reply, msg)
74*2f2c4c7aSAndroid Build Coastguard Worker    self.last_packet = pkt
75*2f2c4c7aSAndroid Build Coastguard Worker    return pkt
76*2f2c4c7aSAndroid Build Coastguard Worker
77*2f2c4c7aSAndroid Build Coastguard Worker  def ReceivePacketOn(self, netid, packet):
78*2f2c4c7aSAndroid Build Coastguard Worker    super(TcpBaseTest, self).ReceivePacketOn(netid, packet)
79*2f2c4c7aSAndroid Build Coastguard Worker    self.last_packet = packet
80*2f2c4c7aSAndroid Build Coastguard Worker
81*2f2c4c7aSAndroid Build Coastguard Worker  def ReceiveRstPacketOn(self, netid):
82*2f2c4c7aSAndroid Build Coastguard Worker    # self.last_packet is the last packet we received. Invert direction twice.
83*2f2c4c7aSAndroid Build Coastguard Worker    _, ack = packets.ACK(self.version, self.myaddr, self.remoteaddr,
84*2f2c4c7aSAndroid Build Coastguard Worker                         self.last_packet)
85*2f2c4c7aSAndroid Build Coastguard Worker    desc, rst = packets.RST(self.version, self.remoteaddr, self.myaddr,
86*2f2c4c7aSAndroid Build Coastguard Worker                            ack)
87*2f2c4c7aSAndroid Build Coastguard Worker    super(TcpBaseTest, self).ReceivePacketOn(netid, rst)
88*2f2c4c7aSAndroid Build Coastguard Worker
89*2f2c4c7aSAndroid Build Coastguard Worker  def RstPacket(self):
90*2f2c4c7aSAndroid Build Coastguard Worker    return packets.RST(self.version, self.myaddr, self.remoteaddr,
91*2f2c4c7aSAndroid Build Coastguard Worker                       self.last_packet, self.sent_fin)
92*2f2c4c7aSAndroid Build Coastguard Worker
93*2f2c4c7aSAndroid Build Coastguard Worker  def FinPacket(self):
94*2f2c4c7aSAndroid Build Coastguard Worker    return packets.FIN(self.version, self.myaddr, self.remoteaddr,
95*2f2c4c7aSAndroid Build Coastguard Worker                       self.last_packet)
96*2f2c4c7aSAndroid Build Coastguard Worker
97*2f2c4c7aSAndroid Build Coastguard Worker  def ExpectPacketOn(self, netid, msg, pkt):
98*2f2c4c7aSAndroid Build Coastguard Worker    self.sent_fin |= (pkt.getlayer("TCP").flags & packets.TCP_FIN) != 0
99*2f2c4c7aSAndroid Build Coastguard Worker    return super(TcpBaseTest, self).ExpectPacketOn(netid, msg, pkt)
100*2f2c4c7aSAndroid Build Coastguard Worker
101*2f2c4c7aSAndroid Build Coastguard Worker  def IncomingConnection(self, version, end_state, netid):
102*2f2c4c7aSAndroid Build Coastguard Worker    self.s = self.OpenListenSocket(version, netid)
103*2f2c4c7aSAndroid Build Coastguard Worker    self.end_state = end_state
104*2f2c4c7aSAndroid Build Coastguard Worker
105*2f2c4c7aSAndroid Build Coastguard Worker    remoteaddr = self.remoteaddr = self.GetRemoteAddress(version)
106*2f2c4c7aSAndroid Build Coastguard Worker    remotesockaddr = self.remotesockaddr = self.GetRemoteSocketAddress(version)
107*2f2c4c7aSAndroid Build Coastguard Worker
108*2f2c4c7aSAndroid Build Coastguard Worker    myaddr = self.myaddr = self.MyAddress(version, netid)
109*2f2c4c7aSAndroid Build Coastguard Worker    mysockaddr = self.mysockaddr = self.MySocketAddress(version, netid)
110*2f2c4c7aSAndroid Build Coastguard Worker
111*2f2c4c7aSAndroid Build Coastguard Worker    if version == 5: version = 4
112*2f2c4c7aSAndroid Build Coastguard Worker    self.version = version
113*2f2c4c7aSAndroid Build Coastguard Worker
114*2f2c4c7aSAndroid Build Coastguard Worker    if end_state == TCP_LISTEN:
115*2f2c4c7aSAndroid Build Coastguard Worker      return
116*2f2c4c7aSAndroid Build Coastguard Worker
117*2f2c4c7aSAndroid Build Coastguard Worker    desc, syn = packets.SYN(self.port, version, remoteaddr, myaddr)
118*2f2c4c7aSAndroid Build Coastguard Worker    synack_desc, synack = packets.SYNACK(version, myaddr, remoteaddr, syn)
119*2f2c4c7aSAndroid Build Coastguard Worker    msg = "Received %s, expected to see reply %s" % (desc, synack_desc)
120*2f2c4c7aSAndroid Build Coastguard Worker    reply = self._ReceiveAndExpectResponse(netid, syn, synack, msg)
121*2f2c4c7aSAndroid Build Coastguard Worker    if end_state == TCP_SYN_RECV:
122*2f2c4c7aSAndroid Build Coastguard Worker      return
123*2f2c4c7aSAndroid Build Coastguard Worker
124*2f2c4c7aSAndroid Build Coastguard Worker    establishing_ack = packets.ACK(version, remoteaddr, myaddr, reply)[1]
125*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, establishing_ack)
126*2f2c4c7aSAndroid Build Coastguard Worker
127*2f2c4c7aSAndroid Build Coastguard Worker    if end_state == TCP_NOT_YET_ACCEPTED:
128*2f2c4c7aSAndroid Build Coastguard Worker      return
129*2f2c4c7aSAndroid Build Coastguard Worker
130*2f2c4c7aSAndroid Build Coastguard Worker    self.accepted, _ = self.s.accept()
131*2f2c4c7aSAndroid Build Coastguard Worker    net_test.DisableFinWait(self.accepted)
132*2f2c4c7aSAndroid Build Coastguard Worker
133*2f2c4c7aSAndroid Build Coastguard Worker    if end_state == TCP_ESTABLISHED:
134*2f2c4c7aSAndroid Build Coastguard Worker      return
135*2f2c4c7aSAndroid Build Coastguard Worker
136*2f2c4c7aSAndroid Build Coastguard Worker    desc, data = packets.ACK(version, myaddr, remoteaddr, establishing_ack,
137*2f2c4c7aSAndroid Build Coastguard Worker                             payload=net_test.UDP_PAYLOAD)
138*2f2c4c7aSAndroid Build Coastguard Worker    self.accepted.send(net_test.UDP_PAYLOAD)
139*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(netid, msg + ": expecting %s" % desc, data)
140*2f2c4c7aSAndroid Build Coastguard Worker
141*2f2c4c7aSAndroid Build Coastguard Worker    desc, fin = packets.FIN(version, remoteaddr, myaddr, data)
142*2f2c4c7aSAndroid Build Coastguard Worker    fin = packets._GetIpLayer(version)(bytes(fin))
143*2f2c4c7aSAndroid Build Coastguard Worker    ack_desc, ack = packets.ACK(version, myaddr, remoteaddr, fin)
144*2f2c4c7aSAndroid Build Coastguard Worker    msg = "Received %s, expected to see reply %s" % (desc, ack_desc)
145*2f2c4c7aSAndroid Build Coastguard Worker
146*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: Why can't we use this?
147*2f2c4c7aSAndroid Build Coastguard Worker    #   self._ReceiveAndExpectResponse(netid, fin, ack, msg)
148*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, fin)
149*2f2c4c7aSAndroid Build Coastguard Worker    time.sleep(0.1)
150*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(netid, msg + ": expecting %s" % ack_desc, ack)
151*2f2c4c7aSAndroid Build Coastguard Worker    if end_state == TCP_CLOSE_WAIT:
152*2f2c4c7aSAndroid Build Coastguard Worker      return
153*2f2c4c7aSAndroid Build Coastguard Worker
154*2f2c4c7aSAndroid Build Coastguard Worker    raise ValueError("Invalid TCP state %d specified" % end_state)
155