/* * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ option version = "5.2.0"; import "vnet/ip/ip_types.api"; import "vnet/interface_types.api"; /** * @file nat.api * @brief VPP control-plane API messages. * * This file defines VPP control-plane API messages which are generally * called through a shared memory interface. */ /* * Common NAT plugin APIs */ enum nat_config_flags : u8 { NAT_IS_NONE = 0x00, NAT_IS_TWICE_NAT = 0x01, NAT_IS_SELF_TWICE_NAT = 0x02, NAT_IS_OUT2IN_ONLY = 0x04, NAT_IS_ADDR_ONLY = 0x08, NAT_IS_OUTSIDE = 0x10, NAT_IS_INSIDE = 0x20, NAT_IS_STATIC = 0x40, NAT_IS_EXT_HOST_VALID = 0x80, }; /** \brief Control ping from client to api server request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_control_ping { u32 client_index; u32 context; }; /** \brief Control ping from the client to the server response @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param retval - return code for the request @param vpe_pid - the pid of the vpe, returned by the server */ define nat_control_ping_reply { u32 context; i32 retval; u32 client_index; u32 vpe_pid; }; /** \brief Show NAT plugin startup config @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_show_config { u32 client_index; u32 context; }; /** \brief Show NAT plugin startup config reply @param context - sender context, to match reply w/ request @param retval - return code for the request @param static_mapping_only - if true dynamic translations disabled @param static_mapping_connection_tracking - if true create session data @param deterministic - if true deterministic mapping @param endpoint_dependent - if true endpoint-dependent mode @param out2in_dpo - if true out2in dpo mode @param dslite_ce - if true DS-Lite is CE/B4 element, if false AFTR elemet @param translation_buckets - number of translation hash buckets @param translation_memory_size - translation hash memory size @param user_buckets - number of user hash buckets @param user_memory_size - user hash memory size @param max_translations_per_user - maximum number of translations per user @param outside_vrf_id - outside VRF id @param inside_vrf_id - default inside VRF id @param nat64_bib_buckets - number of NAT64 BIB hash buckets @param nat64_bib_memory_size - memory size of NAT64 BIB hash @param nat64_st_buckets - number of NAT64 session table hash buckets @param nat64_st_memory_size - memory size of NAT64 session table hash */ define nat_show_config_reply { u32 context; i32 retval; bool static_mapping_only; bool static_mapping_connection_tracking; bool deterministic; bool endpoint_dependent; bool out2in_dpo; bool dslite_ce; u32 translation_buckets; u32 translation_memory_size; u32 user_buckets; u64 user_memory_size; u32 max_translations_per_user; u32 outside_vrf_id; u32 inside_vrf_id; u32 nat64_bib_buckets; u64 nat64_bib_memory_size; u32 nat64_st_buckets; u64 nat64_st_memory_size; }; enum nat_log_level : u8 { NAT_LOG_NONE = 0x00, NAT_LOG_ERROR = 0x01, NAT_LOG_WARNING = 0x02, NAT_LOG_NOTICE = 0x03, NAT_LOG_INFO = 0x04, NAT_LOG_DEBUG = 0x05, }; /** \brief Run nat44 garbage collection @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ autoreply define nat44_session_cleanup { u32 client_index; u32 context; }; /** \brief Set NAT logging level @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param log_level - logging level */ autoreply define nat_set_log_level { u32 client_index; u32 context; vl_api_nat_log_level_t log_level; }; /** \brief Set NAT workers @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param worker_mask - NAT workers mask */ autoreply define nat_set_workers { u32 client_index; u32 context; u64 worker_mask; }; /** \brief Dump NAT workers @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_worker_dump { u32 client_index; u32 context; }; /** \brief NAT workers details response @param context - sender context, to match reply w/ request @param worker_index - worker index @param lcore_id - lcore ID @param name - worker name */ define nat_worker_details { u32 context; u32 worker_index; u32 lcore_id; string name[64]; }; /** \brief Enable/disable NAT IPFIX logging @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param domain_id - observation domain ID @param src_port - source port number @param enable - true if enable, false if disable */ autoreply define nat_ipfix_enable_disable { u32 client_index; u32 context; u32 domain_id; u16 src_port; bool enable; }; /** \brief Set values of timeouts for NAT sessions (seconds) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param udp - UDP timeout (default 300sec) @param tcp_established - TCP established timeout (default 7440sec) @param tcp_transitory - TCP transitory timeout (default 240sec) @param icmp - ICMP timeout (default 60sec) */ autoreply define nat_set_timeouts { u32 client_index; u32 context; u32 udp; u32 tcp_established; u32 tcp_transitory; u32 icmp; }; /** \brief Get values of timeouts for NAT sessions (seconds) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_get_timeouts { u32 client_index; u32 context; }; /** \brief Get values of timeouts for NAT sessions reply @param context - sender context, to match reply w/ request @param retval - return code @param udp - UDP timeout @param tcp_established - TCP established timeout @param tcp_transitory - TCP transitory timeout @param icmp - ICMP timeout */ define nat_get_timeouts_reply { u32 context; i32 retval; u32 udp; u32 tcp_established; u32 tcp_transitory; u32 icmp; }; /** \brief Set address and port assignment algorithm @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param alg - address and port assignment algorithm: 0 - default, 1 - MAP-E, 2 - port range (see nat_addr_and_port_alloc_alg_t in nat.h) @param psid_offset - number of offset bits (valid only for MAP-E alg) @param psid_length - length of PSID (valid only for MAP-E alg) @param psid - Port Set Identifier (PSID) value (valid only for MAP-E alg) @param start_port - beginning of the port range @param end_port - end of the port range */ autoreply define nat_set_addr_and_port_alloc_alg { u32 client_index; u32 context; u8 alg; u8 psid_offset; u8 psid_length; u16 psid; u16 start_port; u16 end_port; }; /** \brief Get address and port assignment algorithm @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_get_addr_and_port_alloc_alg { u32 client_index; u32 context; }; /** \brief Get address and port assignment algorithm reply @param context - sender context, to match reply w/ request @param retval - return code @param alg - address and port assignment algorithm: 0 - default, 1 - MAP-E, 2 - port range (see nat_addr_and_port_alloc_alg_t in nat.h) @param psid_offset - number of offset bits (valid only for MAP-E alg) @param psid_length - length of PSID (valid only for MAP-E alg) @param psid - Port Set Identifier (PSID) value (valid only for MAP-E alg) @param start_port - beginning of the port range @param end_port - end of the port range */ define nat_get_addr_and_port_alloc_alg_reply { u32 context; i32 retval; u8 alg; u8 psid_offset; u8 psid_length; u16 psid; u16 start_port; u16 end_port; }; /** \brief Set TCP MSS rewriting configuration @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param mss_value - MSS value to be used for MSS rewriting @param enable - if true enable MSS rewriting feature else disable */ autoreply define nat_set_mss_clamping { u32 client_index; u32 context; u16 mss_value; bool enable; }; /** \brief Get TCP MSS rewriting configuration @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_get_mss_clamping { u32 client_index; u32 context; }; /** \brief Get TCP MSS rewriting configuration reply @param context - sender context, to match reply w/ request @param retval - return code @param mss_value - MSS value to be used for MSS rewriting @param enable - if true enable MSS rewriting feature else disable */ define nat_get_mss_clamping_reply { u32 context; i32 retval; u16 mss_value; bool enable; }; /** \brief Set HA listener (local settings) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param ip_address - local IP4 address @param port - local UDP port number @param path_mtu - path MTU between local and failover */ autoreply define nat_ha_set_listener { u32 client_index; u32 context; vl_api_ip4_address_t ip_address; u16 port; u32 path_mtu; }; /** \brief Set HA failover (remote settings) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param ip_address - failover IP4 address @param port - failvoer UDP port number @param session_refresh_interval - number of seconds after which to send session counters refresh */ autoreply define nat_ha_set_failover { u32 client_index; u32 context; vl_api_ip4_address_t ip_address; u16 port; u32 session_refresh_interval; }; /** \brief Get HA listener/local configuration @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_ha_get_listener { u32 client_index; u32 context; }; /** \brief Get HA listener/local configuration reply @param context - sender context, to match reply w/ request @param retval - return code @param ip_address - local IP4 address @param port - local UDP port number @param path_mtu - Path MTU between local and failover */ define nat_ha_get_listener_reply { u32 context; i32 retval; vl_api_ip4_address_t ip_address; u16 port; u32 path_mtu; }; /** \brief Get HA failover/remote settings @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat_ha_get_failover { u32 client_index; u32 context; }; /** \brief Get HA failover/remote settings reply @param context - sender context, to match reply w/ request @param retval - return code @param ip_address - failover IP4 address @param port - failvoer UDP port number @param session_refresh_interval - number of seconds after which to send session counters refresh */ define nat_ha_get_failover_reply { u32 context; i32 retval; vl_api_ip4_address_t ip_address; u16 port; u32 session_refresh_interval; }; /** \brief Flush the current HA data (for testing) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ autoreply define nat_ha_flush { u32 client_index; u32 context; }; /** \brief Resync HA (resend existing sessions to new failover) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param want_resync_event - resync completed event sent to the sender via nat_ha_resync_completed_event API message if non-zero @param pid - sender's pid */ autoreply define nat_ha_resync { u32 client_index; u32 context; u8 want_resync_event; u32 pid; }; /** \brief Tell client about a HA resync completion event @param client_index - opaque cookie to identify the sender @param pid - client pid registered to receive notification @param missed_count - number of missed (not ACKed) messages */ define nat_ha_resync_completed_event { u32 client_index; u32 pid; u32 missed_count; }; service { rpc nat_ha_resync returns nat_ha_resync_reply events nat_ha_resync_completed_event; }; /* * NAT44 APIs */ /** \brief Del NAT44 user @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param ip_address - IPv4 address @param fib_index - FIB index */ autoreply define nat44_del_user { u32 client_index; u32 context; vl_api_ip4_address_t ip_address; u32 fib_index; }; /** \brief Add/del NAT44 address range @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param first_ip_address - first IPv4 address @param last_ip_address - last IPv4 address @param vrf_id - VRF id of tenant, ~0 means independent of VRF @param is_add - true if add, false if delete @param flags - flag NAT_IS_TWICE_NAT if NAT address range for external hosts */ autoreply define nat44_add_del_address_range { u32 client_index; u32 context; vl_api_ip4_address_t first_ip_address; vl_api_ip4_address_t last_ip_address; u32 vrf_id; bool is_add; vl_api_nat_config_flags_t flags; }; /** \brief Dump NAT44 addresses @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat44_address_dump { u32 client_index; u32 context; }; /** \brief NAT44 address details response @param context - sender context, to match reply w/ request @param ip_address - IPv4 address @param flags - flag NAT_IS_TWICE_NAT if NAT address range for external hosts @param vrf_id - VRF id of tenant, ~0 means independent of VRF */ define nat44_address_details { u32 context; vl_api_ip4_address_t ip_address; vl_api_nat_config_flags_t flags; u32 vrf_id; }; /** \brief Enable/disable NAT44 feature on the interface @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param is_add - true if add, false if delete @param flags - flag NAT_IS_INSIDE if interface is inside else interface is outside @param sw_if_index - software index of the interface */ autoreply define nat44_interface_add_del_feature { u32 client_index; u32 context; bool is_add; vl_api_nat_config_flags_t flags; vl_api_interface_index_t sw_if_index; }; /** \brief Dump interfaces with NAT44 feature @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat44_interface_dump { u32 client_index; u32 context; }; /** \brief NAT44 interface details response @param context - sender context, to match reply w/ request @param sw_if_index - software index of the interface @param flags - flag NAT_IS_INSIDE if interface is inside, flag NAT_IS_OUTSIDE if interface is outside and if both flags are set the interface is both inside and outside */ define nat44_interface_details { u32 context; vl_api_nat_config_flags_t flags; vl_api_interface_index_t sw_if_index; }; /** \brief Enable/disbale NAT44 as an interface output feature (postrouting in2out translation) @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param is_add - true if add, false if delete @param flags - flag NAT_IS_INSIDE if interface is inside else interface is outside @param sw_if_index - software index of the interface */ autoreply define nat44_interface_add_del_output_feature { u32 client_index; u32 context; bool is_add; vl_api_nat_config_flags_t flags; vl_api_interface_index_t sw_if_index; }; /** \brief Dump interfaces with NAT44 output feature @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat44_interface_output_feature_dump { u32 client_index; u32 context; }; /** \brief NAT44 interface with output feature details response @param context - sender context, to match reply w/ request @param flags - flag NAT_IS_INSIDE if interface is inside else interface is outside @param sw_if_index - software index of the interface */ define nat44_interface_output_feature_details { u32 context; vl_api_nat_config_flags_t flags; vl_api_interface_index_t sw_if_index; }; /** \brief Add/delete NAT44 static mapping @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param is_add - true if add, false if delete @param flags - flag NAT_IS_ADDR_ONLY if address only mapping, flag nat_is_twice_nat if nat address range for external hosts, flag NAT_IS_SELF_TWICE_NAT if translate external host address and port whenever external host address equals local address of internal host, flag NAT_IS_OUT2IN_ONLY if rule match only out2in direction @param local_ip_address - local IPv4 address @param external_ip_address - external IPv4 address @param protocol - IP protocol, used only if addr_only=0 @param local_port - local port number, used only if addr_only=0 @param external_port - external port number, used only if addr_only=0 @param external_sw_if_index - external interface (if set external_ip_address is ignored, ~0 means not used) @param vfr_id - VRF ID @param tag - opaque string tag */ autoreply define nat44_add_del_static_mapping { u32 client_index; u32 context; bool is_add; vl_api_nat_config_flags_t flags; vl_api_ip4_address_t local_ip_address; vl_api_ip4_address_t external_ip_address; u8 protocol; u16 local_port; u16 external_port; vl_api_interface_index_t external_sw_if_index; u32 vrf_id; string tag[64]; }; /** \brief Dump NAT44 static mappings @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define nat44_static_mapping_dump { u32 client_index; u32 context; }; /** \brief NAT44 static mapping details response @param context - sender context, to match reply w/ request @param flags - flag NAT_ADDR_ONLY if address only mapping, flag NAT_TWICE_NAT if NAT address range for external hosts, flag NAT_SELF_TWICE_NAT if translate external host address and port whenever external host address equals local address of internal host, flag NAT_OUT2IN_ONLY if rule match only out2in direction @param local_ip_address - local IPv4 address @param external_ip_address - external IPv4 address @param protocol - IP protocol, valid only if no NAT_ADDR_ONLY flag @param local_port - local port number, valid only if no NAT_ADDR_ONLY flag @param external_port - external port number, valid only if no NAT_ADDR_ONLY flag @param external_sw_if_index - external interface @param vfr_id - VRF ID @param tag - opaque string tag */ define nat44_static_mapping_details { u32 context; vl_api_nat_config_flags_t flags; vl_api_ip4_address_t local_ip_address; vl_api_ip4_address_t external_ip_address; u8 protocol; u16 local_port; u16 external_port; vl_api_interface_index_t external_sw_if_index; u32 vrf_id; string tag[64]; }; /** \brief Add/delete NAT44 identity mapping @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param is_add - true if add, false if delete @param flags - flag NAT_ADDR_ONLY if address only mapping @param
#!/usr/bin/env python3
"""IP4 VRF Multi-instance Test Case HLD:
**NOTES:**
- higher number of pg-ip4 interfaces causes problems => only 15 pg-ip4 \
interfaces in 5 VRFs are tested
- jumbo packets in configuration with 15 pg-ip4 interfaces leads to \
problems too
**config 1**
- add 15 pg-ip4 interfaces
- configure 5 hosts per pg-ip4 interface
- configure 4 VRFs
- add 3 pg-ip4 interfaces per VRF
**test 1**
- send IP4 packets between all pg-ip4 interfaces in all VRF groups
**verify 1**
- check VRF data by parsing output of ip_fib_dump API command
- all packets received correctly in case of pg-ip4 interfaces in the same
VRF
- no packet received in case of pg-ip4 interfaces not in VRF
- no packet received in case of pg-ip4 interfaces in different VRFs
**config 2**
- reset 2 VRFs
**test 2**
- send IP4 packets between all pg-ip4 interfaces in all VRF groups
**verify 2**
- all packets received correctly in case of pg-ip4 interfaces in the same
VRF
- no packet received in case of pg-ip4 interfaces not in VRF
- no packet received in case of pg-ip4 interfaces in different VRFs
**config 3**
- add 1 of reset VRFs and 1 new VRF
**test 3**
- send IP4 packets between all pg-ip4 interfaces in all VRF groups
**verify 3**
- check VRF data by parsing output of ip_fib_dump API command
- all packets received correctly in case of pg-ip4 interfaces in the same
VRF
- no packet received in case of pg-ip4 interfaces not in VRF
- no packet received in case of pg-ip4 interfaces in different VRFs
**config 4**
- reset all created VRFs
**test 4**
- send IP4 packets between all pg-ip4 interfaces in all VRF groups
**verify 4**
- check VRF data by parsing output of ip_fib_dump API command
- all packets received correctly in case of pg-ip4 interfaces in the same
VRF
- no packet received in case of pg-ip4 interfaces not in VRF
- no packet received in case of pg-ip4 interfaces in different VRFs
"""
import unittest
import random
import socket
import scapy.compat
from scapy.packet import Raw
from scapy.layers.l2 import Ether, ARP
from scapy.layers.inet import IP, UDP
from framework import VppTestCase, VppTestRunner
from util import ppp
from vrf import VRFState
def is_ipv4_misc(p):
""" Is packet one of uninteresting IPv4 broadcasts? """
if p.haslayer(ARP):
return True
return False
class TestIp4VrfMultiInst(VppTestCase):
""" IP4 VRF Multi-instance Test Case """
@classmethod
def setUpClass(cls):
"""
Perform standard class setup (defined by class method setUpClass in
class VppTestCase) before running the test case, set test case related
variables and configure VPP.
"""
super(TestIp4VrfMultiInst, cls).setUpClass()
# Test variables
cls.hosts_per_pg = 5
cls.nr_of_vrfs = 5
cls.pg_ifs_per_vrf = 3
try:
# Create pg interfaces
cls.create_pg_interfaces(
range(cls.nr_of_vrfs * cls.pg_ifs_per_vrf))
# Packet flows mapping pg0 -> pg1, pg2 etc.
cls.flows = dict()
for i in range(len(cls.pg_interfaces)):
multiplicand = i // cls.pg_ifs_per_vrf
pg_list = [
cls.pg_interfaces[multiplicand * cls.pg_ifs_per_vrf + j]
for j in range(cls.pg_ifs_per_vrf)
if (multiplicand * cls.pg_ifs_per_vrf + j) != i]
cls.flows[cls.pg_interfaces[i]] = pg_list
# Packet sizes - jumbo packet (9018 bytes) skipped
cls.pg_if_packet_sizes = [64, 512, 1518]
# Set up all interfaces
for pg_if in cls.pg_interfaces:
pg_if.admin_up()
pg_if.generate_remote_hosts(cls.hosts_per_pg)
# Create list of VRFs
cls.vrf_list = list()
# Create list of reset VRFs
cls.vrf_reset_list = list()
# Create list of pg_interfaces in VRFs
cls.pg_in_vrf = list()
# Create list of pg_interfaces not in VRFs
cls.pg_not_in_vrf = [pg_if for pg_if in cls.pg_interfaces]
# Create mapping of pg_interfaces to VRF IDs
cls.pg_if_by_vrf_id = dict()
for i in range(cls.nr_of_vrfs):
vrf_id = i + 1
pg_list = [
cls.pg_interfaces[i * cls.pg_ifs_per_vrf + j]
for j in range(cls.pg_ifs_per_vrf)]
cls.pg_if_by_vrf_id[vrf_id] = pg_list
except Exception:
super(TestIp4VrfMultiInst, cls).tearDownClass()
raise
@classmethod
def tearDownClass(cls):
super(TestIp4VrfMultiInst, cls).tearDownClass()
def setUp(self):
"""
Clear trace and packet infos before running each test.
"""
super(TestIp4VrfMultiInst, self).setUp()
self.reset_packet_infos()
def tearDown(self):
"""
Show various debug prints after each test.
"""
super(TestIp4VrfMultiInst, self).tearDown()
def show_commands_at_teardown(self):
self.logger.info(self.vapi.ppcli("show ip fib"))
self.logger.info(self.vapi.ppcli("show ip4 neighbors"))
def create_vrf_and_assign_interfaces(self, count, start=1):
"""
Create required number of FIB tables / VRFs, put 3 pg-ip4 interfaces