2021-01-12 21:49:38 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""Policy 1:1 NAT functional tests"""
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
from scapy.layers.inet import Ether, IP, UDP, ICMP
|
2023-08-31 00:47:44 -04:00
|
|
|
from framework import VppTestCase
|
|
|
|
from asfframework import VppTestRunner
|
2021-01-12 21:49:38 +01:00
|
|
|
from vpp_papi import VppEnum
|
2024-03-11 10:38:46 +00:00
|
|
|
from config import config
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
|
2024-03-11 10:38:46 +00:00
|
|
|
@unittest.skipIf("nat" in config.excluded_plugins, "Exclude NAT plugin tests")
|
2021-01-12 21:49:38 +01:00
|
|
|
class TestPNAT(VppTestCase):
|
2022-04-26 19:02:15 +02:00
|
|
|
"""PNAT Test Case"""
|
|
|
|
|
2021-01-12 21:49:38 +01:00
|
|
|
maxDiff = None
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
super(TestPNAT, cls).setUpClass()
|
|
|
|
cls.create_pg_interfaces(range(2))
|
|
|
|
cls.interfaces = list(cls.pg_interfaces)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
|
|
|
super(TestPNAT, cls).tearDownClass()
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(TestPNAT, self).setUp()
|
|
|
|
for i in self.interfaces:
|
|
|
|
i.admin_up()
|
|
|
|
i.config_ip4()
|
|
|
|
i.resolve_arp()
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
super(TestPNAT, self).tearDown()
|
|
|
|
if not self.vpp_dead:
|
|
|
|
for i in self.pg_interfaces:
|
|
|
|
i.unconfig_ip4()
|
|
|
|
i.admin_down()
|
|
|
|
|
|
|
|
def validate(self, rx, expected):
|
2024-07-23 01:28:19 -04:00
|
|
|
self.assertTrue(bytes(rx), bytes(expected))
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
def validate_bytes(self, rx, expected):
|
|
|
|
self.assertEqual(rx, expected)
|
|
|
|
|
|
|
|
def ping_check(self):
|
2022-04-26 19:02:15 +02:00
|
|
|
"""Verify non matching traffic works."""
|
2021-01-12 21:49:38 +01:00
|
|
|
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
|
|
|
|
2022-04-26 19:02:15 +02:00
|
|
|
icmpecho = IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / ICMP()
|
|
|
|
reply = IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / ICMP(
|
|
|
|
type="echo-reply"
|
|
|
|
)
|
|
|
|
rx = self.send_and_expect(self.pg0, p_ether / icmpecho * 1, self.pg0)
|
2021-01-12 21:49:38 +01:00
|
|
|
for p in rx:
|
|
|
|
reply[IP].id = p[IP].id
|
|
|
|
self.validate(p[1], reply)
|
|
|
|
|
|
|
|
def test_pnat(self):
|
2022-04-26 19:02:15 +02:00
|
|
|
"""PNAT test"""
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
PNAT_IP4_INPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_INPUT
|
2022-04-26 19:02:15 +02:00
|
|
|
PNAT_IP4_OUTPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_OUTPUT
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
tests = [
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {
|
|
|
|
"mask": 0xA,
|
|
|
|
"dst": "10.10.10.10",
|
|
|
|
"proto": 17,
|
|
|
|
"dport": 6871,
|
|
|
|
},
|
|
|
|
"rewrite": {"mask": 0x2, "dst": self.pg1.remote_ip4},
|
|
|
|
"send": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst="10.10.10.10") / UDP(dport=6871)
|
|
|
|
),
|
|
|
|
"reply": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(dport=6871)
|
|
|
|
),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_OUTPUT,
|
|
|
|
"sw_if_index": self.pg1.sw_if_index,
|
|
|
|
"match": {
|
|
|
|
"mask": 0x9,
|
|
|
|
"src": self.pg0.remote_ip4,
|
|
|
|
"proto": 17,
|
|
|
|
"dport": 6871,
|
|
|
|
},
|
|
|
|
"rewrite": {"mask": 0x1, "src": "11.11.11.11"},
|
|
|
|
"send": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(dport=6871)
|
|
|
|
),
|
|
|
|
"reply": (
|
|
|
|
IP(src="11.11.11.11", dst=self.pg1.remote_ip4) / UDP(dport=6871)
|
|
|
|
),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {
|
|
|
|
"mask": 0xA,
|
|
|
|
"dst": "10.10.10.10",
|
|
|
|
"proto": 17,
|
|
|
|
"dport": 6871,
|
|
|
|
},
|
|
|
|
"rewrite": {"mask": 0xA, "dst": self.pg1.remote_ip4, "dport": 5555},
|
|
|
|
"send": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst="10.10.10.10")
|
|
|
|
/ UDP(sport=65530, dport=6871)
|
|
|
|
),
|
|
|
|
"reply": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(sport=65530, dport=5555)
|
|
|
|
),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {
|
|
|
|
"mask": 0xA,
|
|
|
|
"dst": self.pg1.remote_ip4,
|
|
|
|
"proto": 17,
|
|
|
|
"dport": 6871,
|
|
|
|
},
|
|
|
|
"rewrite": {"mask": 0x8, "dport": 5555},
|
|
|
|
"send": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(dport=6871, chksum=0)
|
|
|
|
),
|
|
|
|
"reply": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(dport=5555, chksum=0)
|
|
|
|
),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {"mask": 0x2, "dst": self.pg1.remote_ip4, "proto": 1},
|
|
|
|
"rewrite": {"mask": 0x1, "src": "8.8.8.8"},
|
|
|
|
"send": (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) / ICMP()),
|
|
|
|
"reply": IP(src="8.8.8.8", dst=self.pg1.remote_ip4) / ICMP(),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
|
|
|
for t in tests:
|
2022-04-26 19:02:15 +02:00
|
|
|
rv = self.vapi.pnat_binding_add(match=t["match"], rewrite=t["rewrite"])
|
|
|
|
self.vapi.pnat_binding_attach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
|
|
|
|
|
|
|
reply = t["reply"]
|
2021-01-12 21:49:38 +01:00
|
|
|
reply[IP].ttl -= 1
|
2022-04-26 19:02:15 +02:00
|
|
|
rx = self.send_and_expect(self.pg0, p_ether / t["send"] * 1, self.pg1)
|
2021-01-12 21:49:38 +01:00
|
|
|
for p in rx:
|
|
|
|
# p.show2()
|
|
|
|
self.validate(p[1], reply)
|
|
|
|
|
|
|
|
self.ping_check()
|
|
|
|
|
2022-04-26 19:02:15 +02:00
|
|
|
self.vapi.pnat_binding_detach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
2021-01-12 21:49:38 +01:00
|
|
|
self.vapi.pnat_binding_del(binding_index=rv.binding_index)
|
|
|
|
|
|
|
|
def test_pnat_show(self):
|
2022-04-26 19:02:15 +02:00
|
|
|
"""PNAT show tests"""
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
PNAT_IP4_INPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_INPUT
|
2022-04-26 19:02:15 +02:00
|
|
|
PNAT_IP4_OUTPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_OUTPUT
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
tests = [
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {
|
|
|
|
"mask": 0xA,
|
|
|
|
"dst": "10.10.10.10",
|
|
|
|
"proto": 17,
|
|
|
|
"dport": 6871,
|
|
|
|
},
|
|
|
|
"rewrite": {"mask": 0x2, "dst": self.pg1.remote_ip4},
|
|
|
|
"send": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst="10.10.10.10") / UDP(dport=6871)
|
|
|
|
),
|
|
|
|
"reply": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(dport=6871)
|
|
|
|
),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
{
|
2022-04-26 19:02:15 +02:00
|
|
|
"input": PNAT_IP4_OUTPUT,
|
|
|
|
"sw_if_index": self.pg1.sw_if_index,
|
|
|
|
"match": {
|
|
|
|
"mask": 0x9,
|
|
|
|
"src": self.pg0.remote_ip4,
|
|
|
|
"proto": 17,
|
|
|
|
"dport": 6871,
|
|
|
|
},
|
|
|
|
"rewrite": {"mask": 0x1, "src": "11.11.11.11"},
|
|
|
|
"send": (
|
|
|
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
|
|
|
|
/ UDP(dport=6871)
|
|
|
|
),
|
|
|
|
"reply": (
|
|
|
|
IP(src="11.11.11.11", dst=self.pg1.remote_ip4) / UDP(dport=6871)
|
|
|
|
),
|
2021-01-12 21:49:38 +01:00
|
|
|
},
|
|
|
|
]
|
|
|
|
binding_index = []
|
|
|
|
for t in tests:
|
2022-04-26 19:02:15 +02:00
|
|
|
rv = self.vapi.pnat_binding_add(match=t["match"], rewrite=t["rewrite"])
|
2021-01-12 21:49:38 +01:00
|
|
|
binding_index.append(rv.binding_index)
|
2022-04-26 19:02:15 +02:00
|
|
|
self.vapi.pnat_binding_attach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
2021-01-12 21:49:38 +01:00
|
|
|
|
|
|
|
rv, l = self.vapi.pnat_bindings_get()
|
|
|
|
self.assertEqual(len(l), len(tests))
|
|
|
|
|
|
|
|
rv, l = self.vapi.pnat_interfaces_get()
|
|
|
|
self.assertEqual(len(l), 2)
|
|
|
|
|
|
|
|
self.logger.info(self.vapi.cli("show pnat translations"))
|
|
|
|
self.logger.info(self.vapi.cli("show pnat interfaces"))
|
|
|
|
|
|
|
|
for i, t in enumerate(tests):
|
2022-04-26 19:02:15 +02:00
|
|
|
self.vapi.pnat_binding_detach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=binding_index[i],
|
|
|
|
)
|
2021-01-12 21:49:38 +01:00
|
|
|
self.vapi.pnat_binding_del(binding_index=binding_index[i])
|
|
|
|
|
2022-05-10 01:03:52 -05:00
|
|
|
def test_pnat_wildcard_proto(self):
|
|
|
|
"""
|
|
|
|
PNAT test wildcard IP protocol, PNAT_PROTO for mask should be set by
|
|
|
|
handler
|
|
|
|
"""
|
|
|
|
|
|
|
|
PNAT_IP4_INPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_INPUT
|
2022-05-13 08:34:34 +00:00
|
|
|
PNAT_IP4_OUTPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_OUTPUT
|
2022-05-10 01:03:52 -05:00
|
|
|
|
|
|
|
tests = [
|
|
|
|
{
|
2022-05-13 08:34:34 +00:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {"mask": 0x2, "dst": "10.10.10.10"},
|
|
|
|
"rewrite": {"mask": 0x2, "dst": self.pg1.remote_ip4},
|
|
|
|
"send": (IP(src=self.pg0.remote_ip4, dst="10.10.10.10")),
|
|
|
|
"reply": (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)),
|
2022-05-10 01:03:52 -05:00
|
|
|
},
|
|
|
|
{
|
2022-05-13 08:34:34 +00:00
|
|
|
"input": PNAT_IP4_OUTPUT,
|
|
|
|
"sw_if_index": self.pg1.sw_if_index,
|
|
|
|
"match": {"mask": 0x1, "src": self.pg0.remote_ip4},
|
|
|
|
"rewrite": {"mask": 0x1, "src": "11.11.11.11"},
|
|
|
|
"send": (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)),
|
|
|
|
"reply": (IP(src="11.11.11.11", dst=self.pg1.remote_ip4)),
|
2022-05-10 01:03:52 -05:00
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
|
|
|
for t in tests:
|
2022-05-13 08:34:34 +00:00
|
|
|
rv = self.vapi.pnat_binding_add(match=t["match"], rewrite=t["rewrite"])
|
|
|
|
self.vapi.pnat_binding_attach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
2022-05-10 01:03:52 -05:00
|
|
|
|
2022-05-13 08:34:34 +00:00
|
|
|
reply = t["reply"]
|
2022-05-10 01:03:52 -05:00
|
|
|
reply[IP].ttl -= 1
|
2022-05-13 08:34:34 +00:00
|
|
|
rx = self.send_and_expect(self.pg0, p_ether / t["send"] * 1, self.pg1)
|
2022-05-10 01:03:52 -05:00
|
|
|
for p in rx:
|
|
|
|
self.validate(p[1], reply)
|
|
|
|
|
|
|
|
self.ping_check()
|
|
|
|
|
2022-05-13 08:34:34 +00:00
|
|
|
self.vapi.pnat_binding_detach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
2022-05-10 01:03:52 -05:00
|
|
|
self.vapi.pnat_binding_del(binding_index=rv.binding_index)
|
|
|
|
|
|
|
|
def test_pnat_wildcard_proto_v2(self):
|
2022-05-13 08:34:34 +00:00
|
|
|
"""PNAT test wildcard IP protocol using pnat_binding_add_v2"""
|
2022-05-10 01:03:52 -05:00
|
|
|
|
|
|
|
PNAT_IP4_INPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_INPUT
|
2022-05-13 08:34:34 +00:00
|
|
|
PNAT_IP4_OUTPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_OUTPUT
|
2022-05-10 01:03:52 -05:00
|
|
|
|
|
|
|
tests = [
|
|
|
|
{
|
2022-05-13 08:34:34 +00:00
|
|
|
"input": PNAT_IP4_INPUT,
|
|
|
|
"sw_if_index": self.pg0.sw_if_index,
|
|
|
|
"match": {"mask": 0x42, "dst": "10.10.10.10"},
|
|
|
|
"rewrite": {"mask": 0x42, "dst": self.pg1.remote_ip4},
|
|
|
|
"send": (IP(src=self.pg0.remote_ip4, dst="10.10.10.10")),
|
|
|
|
"reply": (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)),
|
2022-05-10 01:03:52 -05:00
|
|
|
},
|
|
|
|
{
|
2022-05-13 08:34:34 +00:00
|
|
|
"input": PNAT_IP4_OUTPUT,
|
|
|
|
"sw_if_index": self.pg1.sw_if_index,
|
|
|
|
"match": {"mask": 0x41, "src": self.pg0.remote_ip4},
|
|
|
|
"rewrite": {"mask": 0x41, "src": "11.11.11.11"},
|
|
|
|
"send": (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)),
|
|
|
|
"reply": (IP(src="11.11.11.11", dst=self.pg1.remote_ip4)),
|
2022-05-10 01:03:52 -05:00
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
|
|
|
for t in tests:
|
2022-05-13 08:34:34 +00:00
|
|
|
rv = self.vapi.pnat_binding_add_v2(match=t["match"], rewrite=t["rewrite"])
|
|
|
|
self.vapi.pnat_binding_attach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
2022-05-10 01:03:52 -05:00
|
|
|
|
2022-05-13 08:34:34 +00:00
|
|
|
reply = t["reply"]
|
2022-05-10 01:03:52 -05:00
|
|
|
reply[IP].ttl -= 1
|
2022-05-13 08:34:34 +00:00
|
|
|
rx = self.send_and_expect(self.pg0, p_ether / t["send"] * 1, self.pg1)
|
2022-05-10 01:03:52 -05:00
|
|
|
for p in rx:
|
|
|
|
self.validate(p[1], reply)
|
|
|
|
|
|
|
|
self.ping_check()
|
|
|
|
|
2022-05-13 08:34:34 +00:00
|
|
|
self.vapi.pnat_binding_detach(
|
|
|
|
sw_if_index=t["sw_if_index"],
|
|
|
|
attachment=t["input"],
|
|
|
|
binding_index=rv.binding_index,
|
|
|
|
)
|
2022-05-10 01:03:52 -05:00
|
|
|
self.vapi.pnat_binding_del(binding_index=rv.binding_index)
|
|
|
|
|
2022-04-26 19:02:15 +02:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2021-01-12 21:49:38 +01:00
|
|
|
unittest.main(testRunner=VppTestRunner)
|