test_pppd.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import os
  2. import time
  3. import infra.basetest
  4. class TestPppd(infra.basetest.BRTest):
  5. # This test needs a Kernel with ppp support.
  6. kern_frag = \
  7. infra.filepath("tests/package/test_pppd/linux-ppp.fragment")
  8. # Our test config also enables socat and iproute2 used as
  9. # supporting tools for this test.
  10. config = \
  11. f"""
  12. BR2_aarch64=y
  13. BR2_TOOLCHAIN_EXTERNAL=y
  14. BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
  15. BR2_LINUX_KERNEL=y
  16. BR2_LINUX_KERNEL_CUSTOM_VERSION=y
  17. BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.57"
  18. BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
  19. BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
  20. BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{kern_frag}"
  21. BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
  22. BR2_PACKAGE_IPROUTE2=y
  23. BR2_PACKAGE_PPPD=y
  24. BR2_PACKAGE_SOCAT=y
  25. BR2_TARGET_ROOTFS_CPIO=y
  26. BR2_TARGET_ROOTFS_CPIO_GZIP=y
  27. # BR2_TARGET_ROOTFS_TAR is not set
  28. """
  29. def test_run(self):
  30. img = os.path.join(self.builddir, "images", "rootfs.cpio.gz")
  31. kern = os.path.join(self.builddir, "images", "Image")
  32. self.emulator.boot(arch="aarch64",
  33. kernel=kern,
  34. kernel_cmdline=["console=ttyAMA0"],
  35. options=["-M", "virt", "-cpu", "cortex-a57", "-m", "256M", "-initrd", img])
  36. self.emulator.login()
  37. # We define our socat output log file.
  38. socat_log = "/tmp/socat.log"
  39. # We define two PTY names we will use for this test.
  40. pty0 = "/dev/ttyppp0"
  41. pty1 = "/dev/ttyppp1"
  42. # We define two IP addresses.
  43. local_ip = "192.168.12.34"
  44. remote_ip = "10.20.30.40"
  45. # We define few parameters for our ping.
  46. ping_count = 3
  47. ping_size = 32
  48. ping_payload = "aa"
  49. # We check the program can execute.
  50. self.assertRunOk("pppd --version")
  51. # We create two PTYs connected to each other with socat. We
  52. # will connect a pppd on each one to create connection end
  53. # points. We also enable some debugging to print the content
  54. # of packets forwarded by socat. We will use that to later
  55. # validate data actually passed through this channel. Note: we
  56. # start the command in a subshell to suppress the job control
  57. # message, when this background process will be killed later
  58. # in this test.
  59. cmd = "( socat -d2 -x -lu"
  60. cmd += f" PTY,link={pty0},rawer,b115200 PTY,link={pty1},rawer,b115200"
  61. cmd += f" > {socat_log} 2>&1 & )"
  62. self.assertRunOk(cmd)
  63. # We create a network namespace. We will use it to isolate one
  64. # of the two pppd instances (our fake remote). We do so to
  65. # make sure our network test will not use the default routes
  66. # (or local loopback). This will make sure our communication
  67. # data will go through our PPP link.
  68. namespace = "remote-ppp"
  69. self.assertRunOk(f"ip netns add {namespace}")
  70. # We start our (fake) remote pppd instance, in our netns.
  71. cmd = f"ip netns exec {namespace} "
  72. cmd += f"pppd noauth ifname ppp1 {pty1} {remote_ip}:{local_ip}"
  73. self.assertRunOk(cmd)
  74. # We wait a bit for the pppd to settle...
  75. time.sleep(3)
  76. # We start out local pppd instance, this time in the default
  77. # network namespace.
  78. cmd = f"pppd noauth ifname ppp0 {pty0} {local_ip}:{remote_ip}"
  79. self.assertRunOk(cmd)
  80. # We wait again...
  81. time.sleep(3)
  82. # We check we can ping our two IPs. The local IP is expected
  83. # to go through the interface loopback (and not go through our
  84. # PPP link). Only the remote IP ping is expected to go through
  85. # our socat PTYs.
  86. for ip in local_ip, remote_ip:
  87. cmd = f"ping -c {ping_count} -s {ping_size} -p {ping_payload} {ip}"
  88. self.assertRunOk(cmd)
  89. # We stop our pppd and socat processes.
  90. self.assertRunOk("killall pppd")
  91. self.assertRunOk("killall socat")
  92. # For debugging this test, it can be useful to print the socat
  93. # log on the console. Uncomment this line, if needed.
  94. # self.assertRunOk(f"cat {socat_log}")
  95. # The actual ping payload set with our payload_data is
  96. # slightly smaller as the ping packet size, due other data
  97. # written by the ping command. This is why we subtract 4 bytes
  98. # to the size.
  99. pattern = " ".join([ping_payload] * (ping_size - 4))
  100. # We count the number of packets with this payload transmitted
  101. # through socat...
  102. out, ret = self.emulator.run(f"grep -Fc '{pattern}' {socat_log}")
  103. self.assertEqual(ret, 0)
  104. # We check we have exactly twice our requested ping count (one
  105. # for ICMP ECHO, one for the REPLY).
  106. self.assertEqual(int(out[0]), ping_count * 2)