summaryrefslogtreecommitdiffstats
path: root/src/plugins/acl/session_inlines.h
diff options
context:
space:
mode:
authorAndrew Yourtchenko <ayourtch@gmail.com>2018-05-24 16:53:27 +0200
committerDamjan Marion <dmarion.lists@gmail.com>2018-05-26 16:56:02 +0000
commita34c08c8c5a505e55178a9a8ef5391224d5460a5 (patch)
tree961461e2a4261dcea81b21e2eddfb026c3d01b8e /src/plugins/acl/session_inlines.h
parentc6f186b23d00685b3e9f132ba79a5cb44f0a44c0 (diff)
acl-plugin: create forward and return sessions in lieu of making a special per-packet session key
Using a separate session key has proven to be tricky for the following reasons: - it's a lot of storage to have what looks to be nearly identical to 5tuple, just maybe with some fields swapped - shuffling the fields from 5tuple adds to memory pressure - the fact that the fields do not coincide with the packet memory means for any staged processing we need to use up a lot of memory Thus, just add two entries into the bihash table pointing to the same session entry, so we could match the packets from either direction. With this we have the key layout of L3 info (which takes up the majority of space for IPv6 case) the same as in the packet, thus, opening up the possibility for other optimizations. Not having to create and store a separate session key should also give us a small performance win in itself. Also, add the routine to show the session bihash in a better way than a bunch of numbers. Alas, the memory usage in the bihash obviously doubles. Change-Id: I8fd2ed4714ad7fc447c4fa224d209bc0b736b371 Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
Diffstat (limited to 'src/plugins/acl/session_inlines.h')
-rw-r--r--src/plugins/acl/session_inlines.h174
1 files changed, 104 insertions, 70 deletions
diff --git a/src/plugins/acl/session_inlines.h b/src/plugins/acl/session_inlines.h
index e75582b647b..d43e550bef9 100644
--- a/src/plugins/acl/session_inlines.h
+++ b/src/plugins/acl/session_inlines.h
@@ -67,72 +67,6 @@ acl_fa_ifc_has_out_acl (acl_main_t * am, int sw_if_index0)
return it_has;
}
-/* Session keys match the packets received, and mirror the packets sent */
-always_inline u32
-acl_make_5tuple_session_key (acl_main_t * am, int is_input, int is_ip6,
- u32 sw_if_index, fa_5tuple_t * p5tuple_pkt,
- fa_5tuple_t * p5tuple_sess)
-{
- int src_index = is_input ? 0 : 1;
- int dst_index = is_input ? 1 : 0;
- u32 valid_new_sess = 1;
- p5tuple_sess->addr[src_index] = p5tuple_pkt->addr[0];
- p5tuple_sess->addr[dst_index] = p5tuple_pkt->addr[1];
- p5tuple_sess->l4.as_u64 = p5tuple_pkt->l4.as_u64;
-
- if (PREDICT_TRUE (p5tuple_pkt->l4.proto != icmp_protos[is_ip6]))
- {
- p5tuple_sess->l4.port[src_index] = p5tuple_pkt->l4.port[0];
- p5tuple_sess->l4.port[dst_index] = p5tuple_pkt->l4.port[1];
- }
- else
- {
- static const u8 *icmp_invmap[] = { icmp4_invmap, icmp6_invmap };
- static const u8 *icmp_valid_new[] =
- { icmp4_valid_new, icmp6_valid_new };
- static const u8 icmp_invmap_size[] = { sizeof (icmp4_invmap),
- sizeof (icmp6_invmap)
- };
- static const u8 icmp_valid_new_size[] = { sizeof (icmp4_valid_new),
- sizeof (icmp6_valid_new)
- };
- int type =
- is_ip6 ? p5tuple_pkt->l4.port[0] - 128 : p5tuple_pkt->l4.port[0];
-
- p5tuple_sess->l4.port[0] = p5tuple_pkt->l4.port[0];
- p5tuple_sess->l4.port[1] = p5tuple_pkt->l4.port[1];
-
- /*
- * Invert ICMP type for valid icmp_invmap messages:
- * 1) input node with outbound ACL interface
- * 2) output node with inbound ACL interface
- *
- */
- if ((is_input && acl_fa_ifc_has_out_acl (am, sw_if_index)) ||
- (!is_input && acl_fa_ifc_has_in_acl (am, sw_if_index)))
- {
- if (type >= 0 &&
- type <= icmp_invmap_size[is_ip6] && icmp_invmap[is_ip6][type])
- {
- p5tuple_sess->l4.port[0] = icmp_invmap[is_ip6][type] - 1;
- }
- }
-
- /*
- * ONLY ICMP messages defined in icmp4_valid_new/icmp6_valid_new table
- * are allowed to create stateful ACL.
- * The other messages will be forwarded without creating a reflexive ACL.
- */
- if (type < 0 ||
- type > icmp_valid_new_size[is_ip6] || !icmp_valid_new[is_ip6][type])
- {
- valid_new_sess = 0;
- }
- }
-
- return valid_new_sess;
-}
-
always_inline int
fa_session_get_timeout_type (acl_main_t * am, fa_session_t * sess)
{
@@ -316,6 +250,100 @@ acl_fa_track_session (acl_main_t * am, int is_input, u32 sw_if_index, u64 now,
return 3;
}
+always_inline u64
+reverse_l4_u64_fastpath (u64 l4, int is_ip6)
+{
+ fa_session_l4_key_t l4i = {.as_u64 = l4 };
+ fa_session_l4_key_t l4o;
+
+ l4o.port[1] = l4i.port[0];
+ l4o.port[0] = l4i.port[1];
+
+ l4o.non_port_l4_data = l4i.non_port_l4_data;
+ l4o.is_input = 1 - l4i.is_input;
+ return l4o.as_u64;
+}
+
+always_inline u64
+reverse_l4_u64_slowpath (u64 l4, int is_ip6)
+{
+ fa_session_l4_key_t l4i = {.as_u64 = l4 };
+ fa_session_l4_key_t l4o;
+
+ if (l4i.proto == icmp_protos[is_ip6])
+ {
+ static const u8 *icmp_invmap[] = { icmp4_invmap, icmp6_invmap };
+ static const u8 *icmp_valid_new[] =
+ { icmp4_valid_new, icmp6_valid_new };
+ static const u8 icmp_invmap_size[] = { sizeof (icmp4_invmap),
+ sizeof (icmp6_invmap)
+ };
+ static const u8 icmp_valid_new_size[] = { sizeof (icmp4_valid_new),
+ sizeof (icmp6_valid_new)
+ };
+ int type = is_ip6 ? l4i.port[0] - 128 : l4i.port[0];
+
+ l4o.non_port_l4_data = l4i.non_port_l4_data;
+ l4o.port[0] = l4i.port[0];
+ l4o.port[1] = l4i.port[1];
+
+
+ /*
+ * ONLY ICMP messages defined in icmp4_valid_new/icmp6_valid_new table
+ * are allowed to create stateful ACL.
+ * The other messages will be forwarded without creating a reverse session.
+ */
+
+ if (type >= 0 && (type <= icmp_valid_new_size[is_ip6])
+ && (icmp_valid_new[is_ip6][type])
+ && (type <= icmp_invmap_size[is_ip6]) && icmp_invmap[is_ip6][type])
+ {
+ /*
+ * we set the inverse direction and correct the port,
+ * if it is okay to add the reverse session.
+ * If not, then the same session will be added twice
+ * to bihash, which is the same as adding just one session.
+ */
+ l4o.is_input = 1 - l4i.is_input;
+ l4o.port[0] = icmp_invmap[is_ip6][type] - 1;
+ }
+
+ return l4o.as_u64;
+ }
+ else
+ return reverse_l4_u64_fastpath (l4, is_ip6);
+}
+
+always_inline u64
+reverse_l4_u64 (u64 l4, int is_ip6)
+{
+ fa_session_l4_key_t l4i = {.as_u64 = l4 };
+
+ if (PREDICT_FALSE (l4i.is_slowpath))
+ {
+ return reverse_l4_u64_slowpath (l4, is_ip6);
+ }
+ else
+ {
+ return reverse_l4_u64_fastpath (l4, is_ip6);
+ }
+}
+
+always_inline void
+reverse_session_add_del (acl_main_t * am, const int is_ip6,
+ clib_bihash_kv_40_8_t * pkv, int is_add)
+{
+ clib_bihash_kv_40_8_t kv2;
+ /* the first 4xu64 is two addresses, so just swap them */
+ kv2.key[0] = pkv->key[2];
+ kv2.key[1] = pkv->key[3];
+ kv2.key[2] = pkv->key[0];
+ kv2.key[3] = pkv->key[1];
+ /* the last u64 needs special treatment (ports, etc.) */
+ kv2.key[4] = reverse_l4_u64 (pkv->key[4], is_ip6);
+ kv2.value = pkv->value;
+ clib_bihash_add_del_40_8 (&am->fa_sessions_hash, &kv2, is_add);
+}
always_inline void
acl_fa_delete_session (acl_main_t * am, u32 sw_if_index,
@@ -326,6 +354,9 @@ acl_fa_delete_session (acl_main_t * am, u32 sw_if_index,
get_session_ptr (am, sess_id.thread_index, sess_id.session_index);
ASSERT (sess->thread_index == os_get_thread_index ());
clib_bihash_add_del_40_8 (&am->fa_sessions_hash, &sess->info.kv, 0);
+
+ reverse_session_add_del (am, sess->info.pkt.is_ip6, &sess->info.kv, 0);
+
acl_fa_per_worker_data_t *pw = &am->per_worker_data[sess_id.thread_index];
pool_put_index (pw->fa_sessions_pool, sess_id.session_index);
/* Deleting from timer structures not needed,
@@ -362,9 +393,11 @@ acl_fa_try_recycle_session (acl_main_t * am, int is_input, u16 thread_index,
}
}
+
always_inline fa_session_t *
-acl_fa_add_session (acl_main_t * am, int is_input, u32 sw_if_index, u64 now,
- fa_5tuple_t * p5tuple, u16 current_policy_epoch)
+acl_fa_add_session (acl_main_t * am, int is_input, int is_ip6,
+ u32 sw_if_index, u64 now, fa_5tuple_t * p5tuple,
+ u16 current_policy_epoch)
{
clib_bihash_kv_40_8_t *pkv = &p5tuple->kv;
clib_bihash_kv_40_8_t kv;
@@ -396,10 +429,11 @@ acl_fa_add_session (acl_main_t * am, int is_input, u32 sw_if_index, u64 now,
sess->link_prev_idx = ~0;
sess->link_next_idx = ~0;
-
-
ASSERT (am->fa_sessions_hash_is_initialized == 1);
clib_bihash_add_del_40_8 (&am->fa_sessions_hash, &kv, 1);
+
+ reverse_session_add_del (am, is_ip6, &kv, 1);
+
acl_fa_conn_list_add_session (am, f_sess_id, now);
vec_validate (pw->fa_session_adds_by_sw_if_index, sw_if_index);
: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * Copyright (c) 2017 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.
 */
/**
 * @file
 * @brief NAT64 global declarations
 */
#ifndef __included_nat64_h__
#define __included_nat64_h__

#include <nat/nat.h>
#include <nat/nat64_db.h>

#define foreach_nat64_tcp_ses_state            \
  _(0, CLOSED, "closed")                       \
  _(1, V4_INIT, "v4-init")                     \
  _(2, V6_INIT, "v6-init")                     \
  _(3, ESTABLISHED, "established")             \
  _(4, V4_FIN_RCV, "v4-fin-rcv")               \
  _(5, V6_FIN_RCV, "v6-fin-rcv")               \
  _(6, V6_FIN_V4_FIN_RCV, "v6-fin-v4-fin-rcv") \
  _(7, TRANS, "trans")

typedef enum
{
#define _(v, N, s) NAT64_TCP_STATE_##N = v,
  foreach_nat64_tcp_ses_state
#undef _
} nat64_tcp_ses_state_t;

typedef enum
{
  NAT64_CLEANER_RESCHEDULE = 1,
} nat64_cleaner_process_event_e;

typedef struct
{
  ip6_address_t prefix;
  u8 plen;
  u32 vrf_id;
  u32 fib_index;
} nat64_prefix_t;

typedef struct
{
  ip6_address_t in_addr;
  u16 in_port;
  ip4_address_t out_addr;
  u16 out_port;
  u32 fib_index;
  u32 thread_index;
  u8 proto;
  u8 is_add;
  u8 done;
} nat64_static_bib_to_update_t;

typedef struct
{
  /** Interface pool */
  snat_interface_t *interfaces;

  /** Address pool vector */
  snat_address_t *addr_pool;

  /** sw_if_indices whose interface addresses should be auto-added */
  u32 *auto_add_sw_if_indices;

  /** Pref64 vector */
  nat64_prefix_t *pref64;

  /** BIB and session DB per thread */
  nat64_db_t *db;

  /** Worker handoff */
  u32 fq_in2out_index;
  u32 fq_out2in_index;

  /** Pool of static BIB entries to be added/deleted in worker threads */
  nat64_static_bib_to_update_t *static_bibs;

  /** config parameters */
  u32 bib_buckets;
  u32 bib_memory_size;
  u32 st_buckets;
  u32 st_memory_size;

  /** values of various timeouts */
  u32 udp_timeout;
  u32 icmp_timeout;
  u32 tcp_trans_timeout;
  u32 tcp_est_timeout;

  /* Total count of interfaces enabled */
  u32 total_enabled_count;
  /* The process node which orcherstrates the cleanup */
  u32 nat64_expire_walk_node_index;

  /* counters/gauges */
  vlib_simple_counter_main_t total_bibs;
  vlib_simple_counter_main_t total_sessions;

  /** node index **/
  u32 error_node_index;

  u32 in2out_node_index;
  u32 in2out_slowpath_node_index;

  u32 out2in_node_index;

  ip4_main_t *ip4_main;
  snat_main_t *sm;
} nat64_main_t;

extern nat64_main_t nat64_main;
extern vlib_node_registration_t nat64_in2out_node;
extern vlib_node_registration_t nat64_out2in_node;

/**
 * @brief Add/delete address to NAT64 pool.
 *
 * @param thread_index Thread index used by ipfix nat logging (not address per thread).
 * @param addr   IPv4 address.
 * @param vrf_id VRF id of tenant, ~0 means independent of VRF.
 * @param is_add 1 if add, 0 if delete.
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_add_del_pool_addr (u32 thread_index,
			     ip4_address_t * addr, u32 vrf_id, u8 is_add);

/**
 * @brief Call back function when walking addresses in NAT64 pool, non-zero
 * return value stop walk.
 */
typedef int (*nat64_pool_addr_walk_fn_t) (snat_address_t * addr, void *ctx);

/**
 * @brief Walk NAT64 pool.
 *
 * @param fn The function to invoke on each entry visited.
 * @param ctx A context passed in the visit function.
 */
void nat64_pool_addr_walk (nat64_pool_addr_walk_fn_t fn, void *ctx);

/**
 * @brief NAT64 pool address from specific (DHCP addressed) interface.
 *
 * @param sw_if_index Index of the interface.
 * @param is_add      1 if add, 0 if delete.
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_add_interface_address (u32 sw_if_index, int is_add);

/**
 * @brief Enable/disable NAT64 feature on the interface.
 *
 * @param sw_if_index Index of the interface.
 * @param is_inside   1 if inside, 0 if outside.
 * @param is_add      1 if add, 0 if delete.
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add);

/**
 * @brief Call back function when walking interfaces with NAT64 feature,
 * non-zero return value stop walk.
 */
typedef int (*nat64_interface_walk_fn_t) (snat_interface_t * i, void *ctx);

/**
 * @brief Walk NAT64 interfaces.
 *
 * @param fn The function to invoke on each entry visited.
 * @param ctx A context passed in the visit function.
 */
void nat64_interfaces_walk (nat64_interface_walk_fn_t fn, void *ctx);

/**
 * @brief Initialize NAT64.
 *
 * @param vm vlib main.
 *
 * @return error code.
 */
clib_error_t *nat64_init (vlib_main_t * vm);

/**
 * @brief Add/delete static NAT64 BIB entry.
 *
 * @param in_addr  Inside IPv6 address.
 * @param out_addr Outside IPv4 address.
 * @param in_port  Inside port number.
 * @param out_port Outside port number.
 * @param proto    L4 protocol.
 * @param vrf_id   VRF id of tenant.
 * @param is_add   1 if add, 0 if delete.
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_add_del_static_bib_entry (ip6_address_t * in_addr,
				    ip4_address_t * out_addr, u16 in_port,
				    u16 out_port, u8 proto, u32 vrf_id,
				    u8 is_add);

/**
 * @brief Alloce IPv4 address and port pair from NAT64 pool.
 *
 * @param fib_index    FIB index of tenant.
 * @param proto        L4 protocol.
 * @param addr         Allocated IPv4 address.
 * @param port         Allocated port number.
 * @param thread_index Thread index.
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_alloc_out_addr_and_port (u32 fib_index, snat_protocol_t proto,
				   ip4_address_t * addr, u16 * port,
				   u32 thread_index);

/**
 * @brief Set UDP session timeout.
 *
 * @param timeout Timeout value in seconds (if 0 reset to default value 300sec).
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_set_udp_timeout (u32 timeout);

/**
 * @brief Get UDP session timeout.
 *
 * @returns UDP session timeout in seconds.
 */
u32 nat64_get_udp_timeout (void);

/**
 * @brief Set ICMP session timeout.
 *
 * @param timeout Timeout value in seconds (if 0 reset to default value 60sec).
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_set_icmp_timeout (u32 timeout);

/**
 * @brief Get ICMP session timeout.
 *
 * @returns ICMP session timeout in seconds.
 */
u32 nat64_get_icmp_timeout (void);

/**
 * @brief Set TCP session timeouts.
 *
 * @param trans Transitory timeout in seconds (if 0 reset to default value 240sec).
 * @param est Established timeout in seconds (if 0 reset to default value 7440sec).
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_set_tcp_timeouts (u32 trans, u32 est);

/**
 * @brief Get TCP transitory timeout.
 *
 * @returns TCP transitory timeout in seconds.
 */
u32 nat64_get_tcp_trans_timeout (void);

/**
 * @brief Get TCP established timeout.
 *
 * @returns TCP established timeout in seconds.
 */
u32 nat64_get_tcp_est_timeout (void);

/**
 * @brief Reset NAT64 session timeout.
 *
 * @param ste Session table entry.
 * @param vm VLIB main.
 **/
void nat64_session_reset_timeout (nat64_db_st_entry_t * ste,
				  vlib_main_t * vm);

/**
 * @brief Set NAT64 TCP session state.
 *
 * @param ste Session table entry.
 * @param tcp TCP header.
 * @param is_ip6 1 if IPv6 packet, 0 if IPv4.
 */
void nat64_tcp_session_set_state (nat64_db_st_entry_t * ste,
				  tcp_header_t * tcp, u8 is_ip6);

/**
 * @brief Add/delete NAT64 prefix.
 *
 * @param prefix NAT64 prefix.
 * @param plen Prefix length.
 * @param vrf_id VRF id of tenant.
 * @param is_add 1 if add, 0 if delete.
 *
 * @returns 0 on success, non-zero value otherwise.
 */
int nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id,
			  u8 is_add);

/**
 * @brief Call back function when walking addresses in NAT64 prefixes, non-zero
 * return value stop walk.
 */
typedef int (*nat64_prefix_walk_fn_t) (nat64_prefix_t * pref64, void *ctx);

/**
 * @brief Walk NAT64 prefixes.
 *
 * @param fn The function to invoke on each entry visited.
 * @param ctx A context passed in the visit function.
 */
void nat64_prefix_walk (nat64_prefix_walk_fn_t fn, void *ctx);

/**
 * Compose IPv4-embedded IPv6 addresses.
 * @param ip6 IPv4-embedded IPv6 addresses.
 * @param ip4 IPv4 address.
 * @param fib_index Tenant FIB index.
 */
void nat64_compose_ip6 (ip6_address_t * ip6, ip4_address_t * ip4,
			u32 fib_index);

/**
 * Extract IPv4 address from the IPv4-embedded IPv6 addresses.
 *
 * @param ip6 IPv4-embedded IPv6 addresses.
 * @param ip4 IPv4 address.
 * @param fib_index Tenant FIB index.
 */
void nat64_extract_ip4 (ip6_address_t * ip6, ip4_address_t * ip4,
			u32 fib_index);

/**
 * @brief Set NAT64 hash tables configuration.
 *
 * @param bib_buckets Number of BIB hash buckets.
 * @param bib_memory_size Memory size of BIB hash.
 * @param st_buckets Number of session table hash buckets.
 * @param st_memory_size Memory size of session table hash.
 */
void nat64_set_hash (u32 bib_buckets, u32 bib_memory_size, u32 st_buckets,
		     u32 st_memory_size);

/**
 * @brief Get worker thread index for NAT64 in2out.
 *
 * @param addr IPv6 src address.
 *
 * @returns worker thread index.
 */
u32 nat64_get_worker_in2out (ip6_address_t * addr);

/**
 * @brief Get worker thread index for NAT64 out2in.
 *
 * @param ip IPv4 header.
 *
 * @returns worker thread index.
 */
u32 nat64_get_worker_out2in (vlib_buffer_t * b, ip4_header_t * ip);

#endif /* __included_nat64_h__ */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */