X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Ftest_gbp.py;h=b6faa12c6a65323b9c160e7e3f8c0954f7cd1260;hb=22b3b846822df2701bb6cb508fa4e023526e5717;hp=805f2610ea36da6089568bb0fec6e3f0c6bfaab3;hpb=25b049484fcf9161edb2c19250066b893c38c264;p=vpp.git diff --git a/test/test_gbp.py b/test/test_gbp.py index 805f2610ea3..b6faa12c6a6 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -1,8 +1,6 @@ #!/usr/bin/env python import unittest -import socket -import struct from framework import VppTestCase, VppTestRunner from vpp_object import VppObject @@ -13,17 +11,17 @@ from scapy.packet import Raw from scapy.layers.l2 import Ether, ARP from scapy.layers.inet import IP, UDP from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \ - ICMPv6NDOptDstLLAddr, ICMPv6ND_NA + ICMPv6ND_NA from scapy.utils6 import in6_getnsma, in6_getnsmac from socket import AF_INET, AF_INET6 from scapy.utils import inet_pton, inet_ntop -from util import Host, mactobinary +from util import mactobinary class VppGbpEndpoint(VppObject): """ - GDB Endpoint + GBP Endpoint """ @property @@ -45,9 +43,13 @@ class VppGbpEndpoint(VppObject): if is_ip6: self.proto = DpoProto.DPO_PROTO_IP6 self.af = AF_INET6 + self.is_ip6 = True + self.ip_len = 128 else: self.proto = DpoProto.DPO_PROTO_IP4 self.af = AF_INET + self.is_ip6 = False + self.ip_len = 32 self.ip_n = inet_pton(self.af, ip) self.floating_ip_n = inet_pton(self.af, fip) @@ -92,7 +94,7 @@ class VppGbpEndpoint(VppObject): class VppGbpRecirc(VppObject): """ - GDB Recirculation Interface + GBP Recirculation Interface """ def __init__(self, test, epg, recirc, is_ext=False): @@ -132,7 +134,7 @@ class VppGbpRecirc(VppObject): class VppGbpSubnet(VppObject): """ - GDB Subnet + GBP Subnet """ def __init__(self, test, table_id, address, address_len, @@ -184,7 +186,8 @@ class VppGbpSubnet(VppObject): ss = self._test.vapi.gbp_subnet_dump() for s in ss: if s.subnet.table_id == self.table_id and \ - s.subnet.address_length == self.address_len: + s.subnet.address_length == self.address_len and \ + s.subnet.is_ip6 == self.is_ip6: if self.is_ip6: if s.subnet.address == self.address_n: return True @@ -196,7 +199,7 @@ class VppGbpSubnet(VppObject): class VppGbpEndpointGroup(VppObject): """ - GDB Endpoint Group + GBP Endpoint Group """ def __init__(self, test, epg, rd, bd, uplink, @@ -247,7 +250,7 @@ class VppGbpEndpointGroup(VppObject): class VppGbpContract(VppObject): """ - GDB Contract + GBP Contract """ def __init__(self, test, src_epg, dst_epg, acl_index): @@ -288,6 +291,61 @@ class VppGbpContract(VppObject): return False +class VppGbpAcl(VppObject): + """ + GBP Acl + """ + + def __init__(self, test): + self._test = test + self.acl_index = 4294967295 + + def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1, + s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0, + sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00', + dport_from=0, dport_to=65535): + if proto == -1 or proto == 0: + sport_to = 0 + dport_to = sport_to + elif proto == 1 or proto == 58: + sport_to = 255 + dport_to = sport_to + rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto, + 'srcport_or_icmptype_first': sport_from, + 'srcport_or_icmptype_last': sport_to, + 'src_ip_prefix_len': s_prefix, + 'src_ip_addr': s_ip, + 'dstport_or_icmpcode_first': dport_from, + 'dstport_or_icmpcode_last': dport_to, + 'dst_ip_prefix_len': d_prefix, + 'dst_ip_addr': d_ip}) + return rule + + def add_vpp_config(self, rules): + + reply = self._test.vapi.acl_add_replace(self.acl_index, + r=rules, + tag='GBPTest') + self.acl_index = reply.acl_index + return self.acl_index + + def remove_vpp_config(self): + self._test.vapi.acl_del(self.acl_index) + + def __str__(self): + return self.object_id() + + def object_id(self): + return "gbp-acl;[%d]" % (self.acl_index) + + def query_vpp_config(self): + cs = self._test.vapi.acl_dump() + for c in cs: + if c.acl_index == self.acl_index: + return True + return False + + class TestGBP(VppTestCase): """ GBP Test Case """ @@ -295,7 +353,7 @@ class TestGBP(VppTestCase): super(TestGBP, self).setUp() self.create_pg_interfaces(range(9)) - self.create_loopback_interfaces(range(9)) + self.create_loopback_interfaces(9) self.router_mac = "00:11:22:33:44:55" @@ -353,6 +411,16 @@ class TestGBP(VppTestCase): self.assertEqual(r[IP].dst, tx[0][IP].dst) return rx + def send_and_expect_natted6(self, src, tx, dst, src_ip): + rx = self.send_and_expect(src, tx, dst) + + for r in rx: + self.assertEqual(r[Ether].src, tx[0][Ether].src) + self.assertEqual(r[Ether].dst, tx[0][Ether].dst) + self.assertEqual(r[IPv6].src, src_ip) + self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst) + return rx + def send_and_expect_unnatted(self, src, tx, dst, dst_ip): rx = self.send_and_expect(src, tx, dst) @@ -363,6 +431,16 @@ class TestGBP(VppTestCase): self.assertEqual(r[IP].src, tx[0][IP].src) return rx + def send_and_expect_unnatted6(self, src, tx, dst, dst_ip): + rx = self.send_and_expect(src, tx, dst) + + for r in rx: + self.assertEqual(r[Ether].src, tx[0][Ether].src) + self.assertEqual(r[Ether].dst, tx[0][Ether].dst) + self.assertEqual(r[IPv6].dst, dst_ip) + self.assertEqual(r[IPv6].src, tx[0][IPv6].src) + return rx + def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip): rx = self.send_and_expect(src, tx, dst) @@ -373,11 +451,23 @@ class TestGBP(VppTestCase): self.assertEqual(r[IP].src, src_ip) return rx + def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip): + rx = self.send_and_expect(src, tx, dst) + + for r in rx: + self.assertEqual(r[Ether].src, self.router_mac) + self.assertEqual(r[Ether].dst, dst.remote_mac) + self.assertEqual(r[IPv6].dst, dst_ip) + self.assertEqual(r[IPv6].src, src_ip) + return rx + def test_gbp(self): """ Group Based Policy """ nat_table = VppIpTable(self, 20) nat_table.add_vpp_config() + nat_table = VppIpTable(self, 20, is_ip6=True) + nat_table.add_vpp_config() # # Bridge Domains @@ -486,9 +576,9 @@ class TestGBP(VppTestCase): self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index, is_inside=1, is_add=1) - # self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index, - # is_inside=1, - # is_add=1) + self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index, + is_inside=1, + is_add=1) self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, epg.bvi_ip4_n, @@ -496,10 +586,11 @@ class TestGBP(VppTestCase): self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, epg.bvi_ip6_n, 128, - is_ipv6=1) + is_ipv6=True) # EPG uplink interfaces in the BD epg.uplink.set_table_ip4(epg.rd) + epg.uplink.set_table_ip6(epg.rd) self.vapi.sw_interface_set_l2_bridge(epg.uplink.sw_if_index, epg.bd) @@ -533,6 +624,7 @@ class TestGBP(VppTestCase): for recirc in recircs: # EPG's ingress recirculation interface maps to its RD recirc.recirc.set_table_ip4(recirc.epg.rd) + recirc.recirc.set_table_ip6(recirc.epg.rd) # in the bridge to allow DVR. L2 emulation to punt to L3 self.vapi.sw_interface_set_l2_bridge(recirc.recirc.sw_if_index, @@ -540,22 +632,14 @@ class TestGBP(VppTestCase): self.vapi.sw_interface_set_l2_emulation( recirc.recirc.sw_if_index) - if recirc.is_ext: - # recirc interfaces on NAT EPGs are outside and an - # output feature - self.vapi.nat44_interface_add_del_output_feature( - recirc.recirc.sw_if_index, - is_inside=0, - is_add=1) - else: - self.vapi.nat44_interface_add_del_feature( - recirc.recirc.sw_if_index, - is_inside=0, - is_add=1) - # self.vapi.nat66_add_del_interface( - # recirc.recirc.sw_if_index, - # is_inside=0, - # is_add=1) + self.vapi.nat44_interface_add_del_feature( + recirc.recirc.sw_if_index, + is_inside=0, + is_add=1) + self.vapi.nat66_add_del_interface( + recirc.recirc.sw_if_index, + is_inside=0, + is_add=1) recirc.add_vpp_config() @@ -569,7 +653,7 @@ class TestGBP(VppTestCase): # adj-fibs due to the fact the the BVI address has /32 and # the subnet is not attached. # - r = VppIpRoute(self, ep.ip, 32, + r = VppIpRoute(self, ep.ip, ep.ip_len, [VppRoutePath(ep.ip, ep.epg.bvi.sw_if_index, proto=ep.proto)], @@ -610,10 +694,10 @@ class TestGBP(VppTestCase): ep.floating_ip_n, vrf_id=0, addr_only=1) - # else: - # self.vapi.nat66_add_del_static_mapping(ep.ip_n, - # ep.floating_ip_n, - # vrf_id=20) + else: + self.vapi.nat66_add_del_static_mapping(ep.ip_n, + ep.floating_ip_n, + vrf_id=0) # VPP EP create ... ep.add_vpp_config() @@ -633,11 +717,11 @@ class TestGBP(VppTestCase): self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd, mac=ep.bin_mac, ip=ep.floating_ip_n, - is_ipv6=0, + is_ipv6=ep.is_ip6, is_add=1) # floating IPs route via EPG recirc - r = VppIpRoute(self, ep.floating_ip, 32, + r = VppIpRoute(self, ep.floating_ip, ep.ip_len, [VppRoutePath(ep.floating_ip, ep.recirc.recirc.sw_if_index, is_dvr=1, @@ -846,7 +930,11 @@ class TestGBP(VppTestCase): # # A uni-directional contract from EPG 220 -> 221 # - c1 = VppGbpContract(self, 220, 221, 0) + acl = VppGbpAcl(self) + rule = acl.create_rule(permit_deny=1, proto=17) + rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17) + acl_index = acl.add_vpp_config([rule, rule2]) + c1 = VppGbpContract(self, 220, 221, acl_index) c1.add_vpp_config() self.send_and_expect_bridged(self.pg0, @@ -858,7 +946,7 @@ class TestGBP(VppTestCase): # # contract for the return direction # - c2 = VppGbpContract(self, 221, 220, 0) + c2 = VppGbpContract(self, 221, 220, acl_index) c2.add_vpp_config() self.send_and_expect_bridged(self.pg0, @@ -878,7 +966,7 @@ class TestGBP(VppTestCase): # # A uni-directional contract from EPG 220 -> 222 'L3 routed' # - c3 = VppGbpContract(self, 220, 222, 0) + c3 = VppGbpContract(self, 220, 222, acl_index) c3.add_vpp_config() self.logger.info(self.vapi.cli("sh gbp contract")) @@ -894,6 +982,7 @@ class TestGBP(VppTestCase): c2.remove_vpp_config() c1.remove_vpp_config() c3.remove_vpp_config() + acl.remove_vpp_config() self.send_and_assert_no_replies(self.pg2, pkt_inter_epg_221_to_220 * 65) @@ -916,21 +1005,39 @@ class TestGBP(VppTestCase): sw_if_index=recirc_nat.recirc.sw_if_index, epg=epg_nat.epg) se2.add_vpp_config() + se16 = VppGbpSubnet(self, 0, "::", 0, + is_internal=False, + sw_if_index=recirc_nat.recirc.sw_if_index, + epg=epg_nat.epg, + is_ip6=True) + se16.add_vpp_config() # in the NAT RD an external subnet via the NAT EPG's uplink se3 = VppGbpSubnet(self, 20, "0.0.0.0", 0, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, epg=epg_nat.epg) + se36 = VppGbpSubnet(self, 20, "::", 0, + is_internal=False, + sw_if_index=epg_nat.uplink.sw_if_index, + epg=epg_nat.epg, + is_ip6=True) se4 = VppGbpSubnet(self, 20, "11.0.0.0", 8, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, epg=epg_nat.epg) se3.add_vpp_config() + se36.add_vpp_config() se4.add_vpp_config() self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0")) self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1")) + self.logger.info(self.vapi.cli("sh ip6 fib ::/0")) + self.logger.info(self.vapi.cli("sh ip6 fib %s" % + eps[4].floating_ip)) + # + # From an EP to an outside addess: IN2OUT + # pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, dst="1.1.1.1") / @@ -941,14 +1048,36 @@ class TestGBP(VppTestCase): self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_global * 65) - c4 = VppGbpContract(self, 220, 333, 0) + acl2 = VppGbpAcl(self) + rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234, + sport_to=1234, dport_from=1234, dport_to=1234) + rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17, + sport_from=1234, sport_to=1234, + dport_from=1234, dport_to=1234) + + acl_index2 = acl2.add_vpp_config([rule, rule2]) + c4 = VppGbpContract(self, 220, 333, acl_index2) c4.add_vpp_config() self.send_and_expect_natted(self.pg0, pkt_inter_epg_220_to_global * 65, self.pg7, - "11.0.0.1") + eps[0].floating_ip) + + pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac, + dst=self.router_mac) / + IPv6(src=eps[4].ip, dst="6001::1") / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_expect_natted6(self.pg0, + pkt_inter_epg_220_to_global * 65, + self.pg7, + eps[4].floating_ip) + # + # From a global address to an EP: OUT2IN + # pkt_inter_epg_220_from_global = (Ether(src=self.router_mac, dst=self.pg0.remote_mac) / IP(dst=eps[0].floating_ip, @@ -959,14 +1088,30 @@ class TestGBP(VppTestCase): self.send_and_assert_no_replies(self.pg7, pkt_inter_epg_220_from_global * 65) - c5 = VppGbpContract(self, 333, 220, 0) + c5 = VppGbpContract(self, 333, 220, acl_index2) c5.add_vpp_config() self.send_and_expect_unnatted(self.pg7, pkt_inter_epg_220_from_global * 65, - self.pg0, - "10.0.0.1") + eps[0].itf, + eps[0].ip) + pkt_inter_epg_220_from_global = (Ether(src=self.router_mac, + dst=self.pg0.remote_mac) / + IPv6(dst=eps[4].floating_ip, + src="6001::1") / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_expect_unnatted6(self.pg7, + pkt_inter_epg_220_from_global * 65, + eps[4].itf, + eps[4].ip) + + # + # From a local VM to another local VM using resp. public addresses: + # IN2OUT2IN + # pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, @@ -974,11 +1119,24 @@ class TestGBP(VppTestCase): UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) - self.send_and_expect_double_natted(self.pg0, + self.send_and_expect_double_natted(eps[0].itf, pkt_intra_epg_220_global * 65, - self.pg1, - "11.0.0.1", - "10.0.0.2") + eps[1].itf, + eps[0].floating_ip, + eps[1].ip) + + pkt_intra_epg_220_global = (Ether(src=self.pg4.remote_mac, + dst=self.router_mac) / + IPv6(src=eps[4].ip, + dst=eps[5].floating_ip) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_expect_double_natted6(eps[4].itf, + pkt_intra_epg_220_global * 65, + eps[5].itf, + eps[4].floating_ip, + eps[5].ip) # # cleanup @@ -991,11 +1149,11 @@ class TestGBP(VppTestCase): vrf_id=0, addr_only=1, is_add=0) - # else: - # self.vapi.nat66_add_del_static_mapping(ep.ip_n, - # ep.floating_ip_n, - # vrf_id=0, - # is_add=0) + else: + self.vapi.nat66_add_del_static_mapping(ep.ip_n, + ep.floating_ip_n, + vrf_id=0, + is_add=0) for epg in epgs: # IP config on the BVI interfaces @@ -1003,37 +1161,39 @@ class TestGBP(VppTestCase): epg.bvi_ip4_n, 32, is_add=0) + self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, + epg.bvi_ip6_n, + 128, + is_add=0, + is_ipv6=True) self.logger.info(self.vapi.cli("sh int addr")) epg.uplink.set_table_ip4(0) + epg.uplink.set_table_ip6(0) if epg != epgs[0] and epg != epgs[3]: epg.bvi.set_table_ip4(0) + epg.bvi.set_table_ip6(0) self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index, is_inside=1, is_add=0) - # self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index, - # is_inside=1, - # is_add=0) + self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index, + is_inside=1, + is_add=0) for recirc in recircs: recirc.recirc.set_table_ip4(0) - - if recirc.is_ext: - self.vapi.nat44_interface_add_del_output_feature( - recirc.recirc.sw_if_index, - is_inside=0, - is_add=0) - else: - self.vapi.nat44_interface_add_del_feature( - recirc.recirc.sw_if_index, - is_inside=0, - is_add=0) - # self.vapi.nat66_add_del_interface( - # recirc.recirc.sw_if_index, - # is_inside=0, - # is_add=0) + recirc.recirc.set_table_ip6(0) + + self.vapi.nat44_interface_add_del_feature( + recirc.recirc.sw_if_index, + is_inside=0, + is_add=0) + self.vapi.nat66_add_del_interface( + recirc.recirc.sw_if_index, + is_inside=0, + is_add=0) if __name__ == '__main__':