aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShesha Sreenivasamurthy <shesha@cisco.com>2016-06-15 11:48:13 -0700
committerDamjan Marion <damarion@cisco.com>2016-06-17 12:34:38 +0000
commit378893a485d0e0dd331cebcb2ebefdeca073b1ab (patch)
treed272ab1627fd555d37f5e31a0a9f9a6d5a53fd3b
parentbd05e17d79156fb72cb12a0d4855bfeaf44bfa32 (diff)
Support NAT across multiple interface pairs
Some of the commands require interface name as an additional parameter as we support multiple interfaces. Example: set vcgn map inside TenGigabitEthernete/0/0 10.1.0.1 - 10.1.0.1 show vcgn inside-translation protocol tcp interface TenGigabitEthernete/0/0 inside-addr 1.0.0.2 show vcgn outside-translation protocol tcp interface TenGigabitEthernet9/0/0 outside-addr 10.1.0.1 Change-Id: Id691ccd3f2c863c665a1568982c819b79dda007e Signed-off-by: Shesha Sreenivasamurthy <shesha@cisco.com>
-rw-r--r--vnet/vnet/vcgn/cnat_cli_handler.c4
-rw-r--r--vnet/vnet/vcgn/vcgn_classify.c193
2 files changed, 140 insertions, 57 deletions
diff --git a/vnet/vnet/vcgn/cnat_cli_handler.c b/vnet/vnet/vcgn/cnat_cli_handler.c
index e76d7cc4248..4650559c299 100644
--- a/vnet/vnet/vcgn/cnat_cli_handler.c
+++ b/vnet/vnet/vcgn/cnat_cli_handler.c
@@ -339,9 +339,9 @@ void cnat_nat44_handle_show_config(vlib_main_t *vm)
pool_foreach(my_vrfmap, cnat_map_by_vrf, ({
hw = vnet_get_hw_interface (dm->vnet_main, my_vrfmap->i_vrf);
- vlib_cli_output(vm, "\tInside Interface : %s\n", hw->name);
+ vlib_cli_output(vm, "\tInside Interface : %v\n", hw->name);
hw = vnet_get_hw_interface (dm->vnet_main, my_vrfmap->o_vrf);
- vlib_cli_output(vm, "\tOutside Interface : %s\n", hw->name);
+ vlib_cli_output(vm, "\tOutside Interface : %v\n", hw->name);
memset(status_str, 0x00, sizeof(status_str));
switch(my_vrfmap->status) {
diff --git a/vnet/vnet/vcgn/vcgn_classify.c b/vnet/vnet/vcgn/vcgn_classify.c
index 8a1e9ac31dd..7747266aa95 100644
--- a/vnet/vnet/vcgn/vcgn_classify.c
+++ b/vnet/vnet/vcgn/vcgn_classify.c
@@ -39,12 +39,13 @@ typedef struct {
u32 cached_next_index;
/* inside, outside interface handles */
- u32 inside_sw_if_index;
- u32 outside_sw_if_index;
+ u32 * inside_sw_if_index_table;
+ u32 * outside_sw_if_index_table;
/* convenience variables */
vlib_main_t * vlib_main;
vnet_main_t * vnet_main;
+ u8 cnat_db_initalized;
} vcgn_classify_main_t;
typedef struct {
@@ -273,18 +274,24 @@ vcgn_classify_node_fn (vlib_main_t * vm,
next0 = VCGN_CLASSIFY_NEXT_IP4_INPUT;
counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED;
- if (protocol_type == 0x11) { /* UDP# 17 */
- next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0;
+ if (protocol_type == 0x11) { /* UDP# 17 */
+ next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
+ vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0;
+
+ next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
+ vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0;
- next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0;
} else if (protocol_type == 0x06) { /* TCP# 6 */
- next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0;
+ next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
+ vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0;
+
+ next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
+ vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0;
- next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0;
} else if (protocol_type == 0x01) { /* ICMP # 1 */
ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2;
@@ -293,18 +300,22 @@ vcgn_classify_node_fn (vlib_main_t * vm,
if ((icmp_type == ICMPV4_ECHO) ||
(icmp_type == ICMPV4_ECHOREPLY)) {
- next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0;
+ next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
+ vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0;
- next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0;
- } else {
- next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0;
+ next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
+ vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0;
- next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
- VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0;
+ } else {
+ next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
+ vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0;
+ next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
+ vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
+ VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0;
}
} else {
/* cannot do NATting with this L4 protocol */
@@ -394,8 +405,21 @@ clib_error_t *vcgn_classify_init (vlib_main_t *vm)
mp->vlib_main = vm;
mp->vnet_main = vnet_get_main();
- mp->inside_sw_if_index = 1;
- mp->outside_sw_if_index = 0;
+ u32 inside_sw_if_index = 1;
+ u32 outside_sw_if_index = 0;
+
+ vec_validate_init_empty (mp->inside_sw_if_index_table,
+ inside_sw_if_index + 1, EMPTY);
+ vec_validate_init_empty (mp->outside_sw_if_index_table,
+ outside_sw_if_index + 1, EMPTY);
+
+ /*
+ * inside_sw_if_index cell of the table stores outside_sw_if_index
+ * and vice versa. This is ensurs pair of indices being remembered
+ * using one mem-location.
+ */
+ mp->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
+ mp->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
#if DPDK==1
dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify");
@@ -440,15 +464,14 @@ show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- /*
vnet_main_t * vnm = vnet_get_main();
- */
vcgn_classify_main_t * vcm = &vcgn_classify_main;
spp_api_cnat_v4_show_inside_entry_req_t inside_req;
u8 *proto;
ip4_address_t inside_addr;
u32 start_port = 1;
u32 end_port = 65535;
+ u32 inside_sw_if_index = EMPTY;
inside_req.start_port = start_port;
inside_req.end_port = end_port;
@@ -461,6 +484,12 @@ show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
} else {
inside_req.protocol = 3;
}
+ } else if (unformat (input, "interface %U",
+ unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) {
+ if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
+ vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
+ return clib_error_return (0, "Could not find the inside interface");
+ }
} else if (unformat (input, "inside-addr %U",
unformat_ip4_address, &inside_addr)) {
inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32);
@@ -470,7 +499,7 @@ show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
inside_req.end_port = end_port;
} else { break;}
}
- inside_req.vrf_id = vcm->inside_sw_if_index;
+ inside_req.vrf_id = inside_sw_if_index;
inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
inside_req.all_entries = 0; /* we can see it later */
#if DEBUG
@@ -480,7 +509,7 @@ show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
inside_req.ipv4_addr,
inside_req.start_port,
inside_req.end_port,
- vcm->inside_sw_if_index);
+ inside_sw_if_index);
#endif
if (cnat_db_init_done) {
cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm);
@@ -498,12 +527,15 @@ show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
{
void cnat_v4_show_outside_entry_req_t_handler
(spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm);
+ vnet_main_t * vnm = vnet_get_main();
vcgn_classify_main_t * vcm = &vcgn_classify_main;
spp_api_cnat_v4_show_outside_entry_req_t outside_req;
u8 *proto;
ip4_address_t outside_addr;
u32 start_port = 1;
u32 end_port = 65535;
+ u32 outside_sw_if_index = EMPTY;
+
outside_req.start_port = start_port;
outside_req.end_port = end_port;
@@ -516,6 +548,12 @@ show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
} else {
outside_req.protocol = 3;
}
+ } else if (unformat (input, "interface %U",
+ unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) {
+ if (outside_sw_if_index > vec_len(vcm->outside_sw_if_index_table) ||
+ vcm->outside_sw_if_index_table[outside_sw_if_index] == EMPTY) {
+ return clib_error_return (0, "Could not find the outside interface");
+ }
} else if (unformat (input, "outside-addr %U",
unformat_ip4_address, &outside_addr)) {
outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32);
@@ -525,7 +563,7 @@ show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
outside_req.end_port = end_port;
} else { break;}
}
- outside_req.vrf_id = vcm->outside_sw_if_index;
+ outside_req.vrf_id = outside_sw_if_index;
outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
#if DEBUG
vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, "
@@ -534,7 +572,7 @@ show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
outside_req.ipv4_addr,
outside_req.start_port,
outside_req.end_port,
- vcm->outside_sw_if_index);
+ outside_sw_if_index);
#endif
if (cnat_db_init_done) {
cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm);
@@ -574,13 +612,36 @@ set_vcgn_inside_command_fn (vlib_main_t * vm,
if (inside_sw_if_index == outside_sw_if_index)
return clib_error_return (0, "inside and outside interfaces can't be the same...");
- vcm->inside_sw_if_index = inside_sw_if_index;
- vcm->outside_sw_if_index = outside_sw_if_index;
+ /*
+ * Initialize in/out sw_if_index table. Could use
+ * non-indexed table to reduce memory. However, this
+ * is consulted in vcgn_classify for every packet.
+ * Therefore, table is indexed by sw_if_index.
+ */
+ vec_validate_init_empty (vcm->inside_sw_if_index_table,
+ inside_sw_if_index + 1, EMPTY);
+ vec_validate_init_empty (vcm->outside_sw_if_index_table,
+ outside_sw_if_index + 1, EMPTY);
- cnat_db_v2_init();
-
- /* Turn on the db scanner process */
- cnat_scanner_db_process_turn_on(vm);
+ /*
+ * inside_sw_if_index cell of the table stores outside_sw_if_index
+ * and vice versa. This is ensurs pair of indices being remembered
+ * using one mem-location.
+ */
+ vcm->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
+ vcm->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
+
+ if (! vcm->cnat_db_initalized) {
+ int i;
+ cnat_db_v2_init();
+
+ for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
+ vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY;
+ }
+ /* Turn on the db scanner process */
+ cnat_scanner_db_process_turn_on(vm);
+ vcm->cnat_db_initalized = 1;
+ }
return 0;
}
@@ -589,14 +650,21 @@ set_vcgn_map_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
+ vnet_main_t * vnm = vnet_get_main();
vcgn_classify_main_t * vcm = &vcgn_classify_main;
ip4_address_t lo, hi;
spp_api_cnat_v4_add_vrf_map_t map;
- int i;
+ u32 inside_sw_if_index = EMPTY;
+ u32 outside_sw_if_index;
vnet_hw_interface_t *inside_hw_if_index = NULL;
vnet_hw_interface_t *outside_hw_if_index = NULL;
+ if (! unformat(input, "inside %U",
+ unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+
if (!unformat (input, "%U", unformat_ip4_address, &lo))
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
@@ -608,26 +676,30 @@ set_vcgn_map_command_fn (vlib_main_t * vm,
/* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */
/* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */
- map.i_vrf_id = vcm->inside_sw_if_index;
- map.o_vrf_id = vcm->outside_sw_if_index;
- map.i_vrf = vcm->inside_sw_if_index;
- map.o_vrf = vcm->outside_sw_if_index;
+
+ if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
+ vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
+ return clib_error_return (0, "Could not find the inside interface");
+ }
+ outside_sw_if_index = vcm->inside_sw_if_index_table[inside_sw_if_index];
+
+ map.i_vrf_id = inside_sw_if_index;
+ map.o_vrf_id = outside_sw_if_index;
+ map.i_vrf = inside_sw_if_index;
+ map.o_vrf = outside_sw_if_index;
map.start_addr[0] = clib_net_to_host_u32(lo.as_u32);
map.end_addr[0] = clib_net_to_host_u32(hi.as_u32);
- for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
- vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY;
- }
cnat_nat44_add_vrf_map_t_handler(&map, vm);
#if 1
- inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, vcm->inside_sw_if_index);
+ inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, inside_sw_if_index);
if (inside_hw_if_index) {
vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
inside_hw_if_index->hw_if_index, vcgn_classify_node.index);
}
- outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, vcm->outside_sw_if_index);
+ outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, outside_sw_if_index);
if (outside_hw_if_index) {
vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
outside_hw_if_index->hw_if_index, vcgn_classify_node.index);
@@ -940,22 +1012,23 @@ set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL;
cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL;
cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp = 0;
- u16 i_vrf;
- u32 i_vrf_id;
+ u16 i_vrf = ~0;
+ u32 i_vrf_id = ~0;
u8 found;
+ u32 inside_sw_if_index = EMPTY;
/*
* Init NFv9 logging info as needed, this will be done only once
*/
cnat_nfv9_logging_init();
- i_vrf = vcm->inside_sw_if_index;
- i_vrf_id = vcm->inside_sw_if_index;
-
found = 0;
/* vcgn changes end*/
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
- if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
+ if (unformat (input, "inside %U",
+ unformat_vnet_sw_interface, &inside_sw_if_index)) {
+ /* Do nothing */
+ } else if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
ip_addr = clib_net_to_host_u32(server_addr.as_u32);
else if (unformat(input, "port %u", &port))
;
@@ -970,6 +1043,12 @@ set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
else break;
}
+ if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
+ vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
+ return clib_error_return (0, "Could not find the inside interface");
+ }
+ i_vrf = inside_sw_if_index;
+ i_vrf_id = inside_sw_if_index;
#if 0
vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, "
@@ -982,8 +1061,8 @@ set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
nfv9_conf.enable = enable;
nfv9_conf.ipv4_address = ip_addr;
- nfv9_conf.i_vrf_id = vcm->inside_sw_if_index;
- nfv9_conf.i_vrf = vcm->inside_sw_if_index;
+ nfv9_conf.i_vrf_id = inside_sw_if_index;
+ nfv9_conf.i_vrf = inside_sw_if_index;
nfv9_conf.port = port;
nfv9_conf.refresh_rate = refresh_rate;
nfv9_conf.timeout_rate = timeout;
@@ -1329,7 +1408,9 @@ VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = {
VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = {
.path = "set vcgn nfv9",
- .short_help = "set vcgn nfv9 [del] server <ip-addr> port <port> [refresh-rate <n>] [timeout <n>] [pmtu <n>]",
+ .short_help = "set vcgn nfv9 [del] inside <interface> "
+ "server <ip-addr> port <port> [refresh-rate <n>] "
+ "[timeout <n>] [pmtu <n>]",
.function = set_vcgn_nfv9_logging_cofig_command_fn,
};
@@ -1350,14 +1431,16 @@ VLIB_CLI_COMMAND (show_vcgn_stat_command) = {
VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = {
.path = "show vcgn inside-translation",
.short_help = "show vcgn inside-translation protocol <tcp/udp/icmp> "
- "inside-addr <ip-addr> [start-port <n>] [end-port <n>]",
+ "interface <inside-if> inside-addr <ip-addr> "
+ "[start-port <n>] [end-port <n>]",
.function = show_vcgn_inside_translation_command_fn,
};
VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = {
.path = "show vcgn outside-translation",
.short_help = "show vcgn outside-translation protocol <tcp/udp/icmp> "
- "outside-addr <ip-addr> [start-port <n>] [end-port <n>]",
+ "interface <outside-if> outside-addr <ip-addr> "
+ "[start-port <n>] [end-port <n>]",
.function = show_vcgn_outside_translation_command_fn,
};