diff options
author | Neale Ranns <neale.ranns@cisco.com> | 2018-04-24 07:45:33 -0700 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2018-04-25 14:00:46 +0000 |
commit | 4a6d02337b9058182172f19df894ad2e18e6ac68 (patch) | |
tree | 60e1da4bfef3226dcac74c1c041e4387e2a0120e | |
parent | 99ed486d1edf5d3eb6550179f3c379b1e9d4cafe (diff) |
GBPv6: NAT66 actions for GBP
Change-Id: I379150a88f2d53d6281be41e8bad6fc4f4e88a71
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
-rw-r--r-- | src/plugins/gbp/gbp_policy_dpo.c | 13 | ||||
-rw-r--r-- | src/vnet/fib/fib_path.c | 2 | ||||
-rw-r--r-- | src/vpp-api/vom/nat_binding.cpp | 66 | ||||
-rw-r--r-- | src/vpp-api/vom/nat_binding_cmds.cpp | 120 | ||||
-rw-r--r-- | src/vpp-api/vom/nat_binding_cmds.hpp | 118 | ||||
-rw-r--r-- | test/test_gbp.py | 208 |
6 files changed, 335 insertions, 192 deletions
diff --git a/src/plugins/gbp/gbp_policy_dpo.c b/src/plugins/gbp/gbp_policy_dpo.c index bfe5974f807..0f62fb3445d 100644 --- a/src/plugins/gbp/gbp_policy_dpo.c +++ b/src/plugins/gbp/gbp_policy_dpo.c @@ -92,6 +92,16 @@ gbp_policy_dpo_unlock (dpo_id_t * dpo) } } +static u32 +gbp_policy_dpo_get_urpf (const dpo_id_t * dpo) +{ + gbp_policy_dpo_t *gpd; + + gpd = gbp_policy_dpo_get_from_dpo (dpo); + + return (gpd->gpd_sw_if_index); +} + void gbp_policy_dpo_add_or_lock (dpo_proto_t dproto, epg_id_t epg, u32 sw_if_index, dpo_id_t * dpo) @@ -138,6 +148,7 @@ const static dpo_vft_t gbp_policy_dpo_vft = { .dv_lock = gbp_policy_dpo_lock, .dv_unlock = gbp_policy_dpo_unlock, .dv_format = format_gbp_policy_dpo, + .dv_get_urpf = gbp_policy_dpo_get_urpf, }; /** @@ -499,7 +510,7 @@ VLIB_NODE_FUNCTION_MULTIARCH (gbp_ip4_lpm_classify_node, gbp_ip4_lpm_classify); VLIB_REGISTER_NODE (gbp_ip6_lpm_classify_node) = { .function = gbp_ip6_lpm_classify, - .name = "ip6-gpb-lpm-classify", + .name = "ip6-gbp-lpm-classify", .vector_size = sizeof (u32), .format_trace = format_gbp_classify_trace, .type = VLIB_NODE_TYPE_INTERNAL, diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index e974e31e959..687e7167312 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -2072,7 +2072,7 @@ fib_path_get_resolving_interface (fib_node_index_t path_index) case FIB_PATH_TYPE_BIER_IMP: break; } - return (~0); + return (dpo_get_urpf(&path->fp_dpo)); } index_t diff --git a/src/vpp-api/vom/nat_binding.cpp b/src/vpp-api/vom/nat_binding.cpp index eca3f9041f0..64b7a1007ac 100644 --- a/src/vpp-api/vom/nat_binding.cpp +++ b/src/vpp-api/vom/nat_binding.cpp @@ -85,11 +85,20 @@ nat_binding::sweep() { if (m_binding) { if (direction_t::INPUT == m_dir) { - HW::enqueue(new nat_binding_cmds::unbind_44_input_cmd( - m_binding, m_itf->handle(), m_zone)); + if (l3_proto_t::IPV4 == m_proto) { + HW::enqueue(new nat_binding_cmds::unbind_44_input_cmd( + m_binding, m_itf->handle(), m_zone)); + } else { + HW::enqueue(new nat_binding_cmds::unbind_66_input_cmd( + m_binding, m_itf->handle(), m_zone)); + } } else { - HW::enqueue(new nat_binding_cmds::unbind_44_output_cmd( - m_binding, m_itf->handle(), m_zone)); + if (l3_proto_t::IPV4 == m_proto) { + HW::enqueue(new nat_binding_cmds::unbind_44_output_cmd( + m_binding, m_itf->handle(), m_zone)); + } else { + VOM_LOG(log_level_t::ERROR) << "NAT 66 output feature not supported"; + } } } HW::write(); @@ -100,11 +109,20 @@ nat_binding::replay() { if (m_binding) { if (direction_t::INPUT == m_dir) { - HW::enqueue(new nat_binding_cmds::bind_44_input_cmd( - m_binding, m_itf->handle(), m_zone)); + if (l3_proto_t::IPV4 == m_proto) { + HW::enqueue(new nat_binding_cmds::bind_44_input_cmd( + m_binding, m_itf->handle(), m_zone)); + } else { + HW::enqueue(new nat_binding_cmds::bind_66_input_cmd( + m_binding, m_itf->handle(), m_zone)); + } } else { - HW::enqueue(new nat_binding_cmds::bind_44_output_cmd( - m_binding, m_itf->handle(), m_zone)); + if (l3_proto_t::IPV4 == m_proto) { + HW::enqueue(new nat_binding_cmds::bind_44_output_cmd( + m_binding, m_itf->handle(), m_zone)); + } else { + VOM_LOG(log_level_t::ERROR) << "NAT 66 output feature not supported"; + } } } } @@ -117,11 +135,20 @@ nat_binding::update(const nat_binding& desired) */ if (!m_binding) { if (direction_t::INPUT == m_dir) { - HW::enqueue(new nat_binding_cmds::bind_44_input_cmd( - m_binding, m_itf->handle(), m_zone)); + if (l3_proto_t::IPV4 == m_proto) { + HW::enqueue(new nat_binding_cmds::bind_44_input_cmd( + m_binding, m_itf->handle(), m_zone)); + } else { + HW::enqueue(new nat_binding_cmds::bind_66_input_cmd( + m_binding, m_itf->handle(), m_zone)); + } } else { - HW::enqueue(new nat_binding_cmds::bind_44_output_cmd( - m_binding, m_itf->handle(), m_zone)); + if (l3_proto_t::IPV4 == m_proto) { + HW::enqueue(new nat_binding_cmds::bind_44_output_cmd( + m_binding, m_itf->handle(), m_zone)); + } else { + VOM_LOG(log_level_t::ERROR) << "NAT 66 output feature not supported"; + } } } } @@ -214,6 +241,21 @@ nat_binding::event_handler::handle_populate(const client_db::key_t& key) zone_t::from_vpp(payload.is_inside)); OM::commit(key, nb); } + + std::shared_ptr<nat_binding_cmds::dump_input_66_cmd> i6cmd = + std::make_shared<nat_binding_cmds::dump_input_66_cmd>(); + + HW::enqueue(i6cmd); + HW::write(); + + for (auto& record : *i6cmd) { + auto& payload = record.get_payload(); + + std::shared_ptr<interface> itf = interface::find(payload.sw_if_index); + nat_binding nb(*itf, direction_t::INPUT, l3_proto_t::IPV6, + zone_t::from_vpp(payload.is_inside)); + OM::commit(key, nb); + } } dependency_t diff --git a/src/vpp-api/vom/nat_binding_cmds.cpp b/src/vpp-api/vom/nat_binding_cmds.cpp index 66b2827abc2..4d98268249a 100644 --- a/src/vpp-api/vom/nat_binding_cmds.cpp +++ b/src/vpp-api/vom/nat_binding_cmds.cpp @@ -214,7 +214,7 @@ dump_input_44_cmd::issue(connection& con) std::string dump_input_44_cmd::to_string() const { - return ("nat-input-binding-dump"); + return ("nat-44-input-binding-dump"); } dump_output_44_cmd::dump_output_44_cmd() @@ -246,7 +246,123 @@ dump_output_44_cmd::issue(connection& con) std::string dump_output_44_cmd::to_string() const { - return ("nat-output-binding-dump"); + return ("nat-44-output-binding-dump"); +} + +bind_66_input_cmd::bind_66_input_cmd(HW::item<bool>& item, + const handle_t& itf, + const nat_binding::zone_t& zone) + : rpc_cmd(item) + , m_itf(itf) + , m_zone(zone) +{ +} + +bool +bind_66_input_cmd::operator==(const bind_66_input_cmd& other) const +{ + return ((m_itf == other.m_itf) && (m_zone == other.m_zone)); +} + +rc_t +bind_66_input_cmd::issue(connection& con) +{ + msg_t req(con.ctx(), std::ref(*this)); + + auto& payload = req.get_request().get_payload(); + payload.is_add = 1; + payload.is_inside = (nat_binding::zone_t::INSIDE == m_zone ? 1 : 0); + payload.sw_if_index = m_itf.value(); + + VAPI_CALL(req.execute()); + + m_hw_item.set(wait()); + + return rc_t::OK; +} + +std::string +bind_66_input_cmd::to_string() const +{ + std::ostringstream s; + s << "nat-66-input-binding-create: " << m_hw_item.to_string() + << " itf:" << m_itf << " " << m_zone.to_string(); + + return (s.str()); +} + +unbind_66_input_cmd::unbind_66_input_cmd(HW::item<bool>& item, + const handle_t& itf, + const nat_binding::zone_t& zone) + : rpc_cmd(item) + , m_itf(itf) + , m_zone(zone) +{ +} + +bool +unbind_66_input_cmd::operator==(const unbind_66_input_cmd& other) const +{ + return ((m_itf == other.m_itf) && (m_zone == other.m_zone)); +} + +rc_t +unbind_66_input_cmd::issue(connection& con) +{ + msg_t req(con.ctx(), std::ref(*this)); + + auto& payload = req.get_request().get_payload(); + payload.is_add = 0; + payload.is_inside = (nat_binding::zone_t::INSIDE == m_zone ? 1 : 0); + payload.sw_if_index = m_itf.value(); + + VAPI_CALL(req.execute()); + + m_hw_item.set(wait()); + + return rc_t::OK; +} + +std::string +unbind_66_input_cmd::to_string() const +{ + std::ostringstream s; + s << "nat-66-input-binding-create: " << m_hw_item.to_string() + << " itf:" << m_itf << " " << m_zone.to_string(); + + return (s.str()); +} + +dump_input_66_cmd::dump_input_66_cmd() +{ +} + +dump_input_66_cmd::dump_input_66_cmd(const dump_input_66_cmd& d) +{ +} + +bool +dump_input_66_cmd::operator==(const dump_input_66_cmd& other) const +{ + return (true); +} + +rc_t +dump_input_66_cmd::issue(connection& con) +{ + m_dump.reset(new msg_t(con.ctx(), std::ref(*this))); + + VAPI_CALL(m_dump->execute()); + + wait(); + + return rc_t::OK; +} + +std::string +dump_input_66_cmd::to_string() const +{ + return ("nat-66-input-binding-dump"); } }; // namespace nat_binding_cmds diff --git a/src/vpp-api/vom/nat_binding_cmds.hpp b/src/vpp-api/vom/nat_binding_cmds.hpp index 1b51192a73c..aa5a200515e 100644 --- a/src/vpp-api/vom/nat_binding_cmds.hpp +++ b/src/vpp-api/vom/nat_binding_cmds.hpp @@ -337,90 +337,6 @@ private: }; /** - * A functor class that binds a NAT configuration to an output interface - */ -/* class bind_66_output_cmd */ -/* : public rpc_cmd<HW::item<bool>, */ -/* rc_t, */ -/* vapi::Nat66_interface_add_del_output_feature> */ -/* { */ -/* public: */ -/* /\** */ -/* * Constructor */ -/* *\/ */ -/* bind_66_output_cmd(HW::item<bool>& item, */ -/* const handle_t& itf, */ -/* const nat_binding::zone_t& zone); */ - -/* /\** */ -/* * Issue the command to VPP/HW */ -/* *\/ */ -/* rc_t issue(connection& con); */ -/* /\** */ -/* * convert to string format for debug purposes */ -/* *\/ */ -/* std::string to_string() const; */ - -/* /\** */ -/* * Comparison operator - only used for UT */ -/* *\/ */ -/* bool operator==(const bind_66_output_cmd& i) const; */ - -/* private: */ -/* /\** */ -/* * The interface to bind */ -/* *\/ */ -/* const handle_t m_itf; */ - -/* /\** */ -/* * The zone the interface is in */ -/* *\/ */ -/* const nat_binding::zone_t m_zone; */ -/* }; */ - -/* /\** */ -/* * A cmd class that unbinds a NAT configuration from an output interface */ -/* *\/ */ -/* class unbind_66_output_cmd */ -/* : public rpc_cmd<HW::item<bool>, */ -/* rc_t, */ -/* vapi::Nat66_interface_add_del_output_feature> */ -/* { */ -/* public: */ -/* /\** */ -/* * Constructor */ -/* *\/ */ -/* unbind_66_output_cmd(HW::item<bool>& item, */ -/* const handle_t& itf, */ -/* const nat_binding::zone_t& zone); */ - -/* /\** */ -/* * Issue the command to VPP/HW */ -/* *\/ */ -/* rc_t issue(connection& con); */ -/* /\** */ -/* * convert to string format for debug purposes */ -/* *\/ */ -/* std::string to_string() const; */ - -/* /\** */ -/* * Comparison operator - only used for UT */ -/* *\/ */ -/* bool operator==(const unbind_66_output_cmd& i) const; */ - -/* private: */ -/* /\** */ -/* * The interface to bind */ -/* *\/ */ -/* const handle_t m_itf; */ - -/* /\** */ -/* * The zone the interface is in */ -/* *\/ */ -/* const nat_binding::zone_t m_zone; */ -/* }; */ - -/** * A cmd class that Dumps all the nat_statics */ class dump_input_66_cmd : public dump_cmd<vapi::Nat66_interface_dump> @@ -453,40 +369,6 @@ private: HW::item<bool> item; }; -/** - * A cmd class that Dumps all the nat_statics - */ -/* class dump_output_66_cmd */ -/* : public dump_cmd<vapi::Nat66_interface_output_feature_dump> */ -/* { */ -/* public: */ -/* /\** */ -/* * Constructor */ -/* *\/ */ -/* dump_output_66_cmd(); */ -/* dump_output_66_cmd(const dump_output_66_cmd& d); */ - -/* /\** */ -/* * Issue the command to VPP/HW */ -/* *\/ */ -/* rc_t issue(connection& con); */ -/* /\** */ -/* * convert to string format for debug purposes */ -/* *\/ */ -/* std::string to_string() const; */ - -/* /\** */ -/* * Comparison operator - only used for UT */ -/* *\/ */ -/* bool operator==(const dump_output_66_cmd& i) const; */ - -/* private: */ -/* /\** */ -/* * HW reutrn code */ -/* *\/ */ -/* HW::item<bool> item; */ -/* }; */ - }; // namespace nat_binding_cmds }; // namespace VOM diff --git a/test/test_gbp.py b/test/test_gbp.py index 805f2610ea3..3d9ebbc8f08 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -45,9 +45,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) @@ -184,7 +188,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 @@ -353,6 +358,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 +378,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,6 +398,16 @@ 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 """ @@ -486,9 +521,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 +531,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 +569,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 +577,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 +598,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 +639,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 +662,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, @@ -916,21 +945,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") / @@ -947,8 +994,22 @@ class TestGBP(VppTestCase): 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, @@ -964,9 +1025,25 @@ class TestGBP(VppTestCase): 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 +1051,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 +1081,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 +1093,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__': |