diff --git a/CMakeLists.txt b/CMakeLists.txt index f3d881d..af23bc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ set(UPF_PLUGIN_HEADER_FILES upf/upf_ipfilter.h upf/upf_app_dpo.h upf/upf_app_db.h + upf/upf_nat.h upf/flowtable.h upf/flowtable_tcp.h upf/upf_buffer_opaque.h diff --git a/upf/upf_nat.c b/upf/upf_nat.c index 44dddb9..e01a5ba 100644 --- a/upf/upf_nat.c +++ b/upf/upf_nat.c @@ -23,9 +23,11 @@ #include #include #include +#include #include #include +#include #if CLIB_DEBUG > 2 #define upf_debug clib_warning @@ -104,6 +106,24 @@ format_upf_session_dpo_trace (u8 *s, va_list *args) return s; } +always_inline void +init_ed_k (clib_bihash_kv_16_8_t *kv, u32 l_addr, u16 l_port, u32 r_addr, + u16 r_port, u32 fib_index, ip_protocol_t proto) +{ + kv->key[0] = (u64) r_addr << 32 | l_addr; + kv->key[1] = + (u64) r_port << 48 | (u64) l_port << 32 | fib_index << 8 | proto; +} + +always_inline void +init_ed_kv (clib_bihash_kv_16_8_t *kv, u32 l_addr, u16 l_port, u32 r_addr, + u16 r_port, u32 fib_index, u8 proto, u32 thread_index, + u32 session_index) +{ + init_ed_k (kv, l_addr, l_port, r_addr, r_port, fib_index, proto); + kv->value = (u64) thread_index << 32 | session_index; +} + VLIB_NODE_FN (upf_nat_o2i) (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame) { @@ -236,6 +256,20 @@ VLIB_NODE_FN (upf_nat_i2o) sx0 = pool_elt_at_index (gtm->sessions, upf_buffer_opaque (b)->gtpu.session_index); + nat_6t_t lookup; + clib_bihash_kv_16_8_t kv0 = { 0 }, value0; + init_ed_k (&kv0, lookup.saddr.as_u32, lookup.sport, + lookup.daddr.as_u32, lookup.dport, lookup.fib_index, + lookup.proto); + + // lookup flow + if (clib_bihash_search_16_8 (>m->flow_hash, &kv0, &value0)) + { + // flow does not exist go slow path + // next[0] = def_slow; + // goto trace0; + } + bool is_outgoing = sx0->user_addr.as_u32 == ip4->src_address.as_u32; if (is_outgoing) diff --git a/upf/upf_nat.h b/upf/upf_nat.h new file mode 100644 index 0000000..d658ed6 --- /dev/null +++ b/upf/upf_nat.h @@ -0,0 +1,40 @@ +#include + +typedef union +{ + struct + { + ip4_address_t saddr, daddr; + u16 sport; // ICMP id for ICMP case + u16 dport; + u32 fib_index : 24; + u8 proto; + }; + u64 as_u64[2]; + u64x2u as_u128; +} nat_6t_t; + +STATIC_ASSERT_SIZEOF (nat_6t_t, 2 * sizeof (u64)); + +typedef struct +{ +#define NAT_FLOW_OP_SADDR_REWRITE (1 << 1) +#define NAT_FLOW_OP_SPORT_REWRITE (1 << 2) +#define NAT_FLOW_OP_DADDR_REWRITE (1 << 3) +#define NAT_FLOW_OP_DPORT_REWRITE (1 << 4) +#define NAT_FLOW_OP_ICMP_ID_REWRITE (1 << 5) +#define NAT_FLOW_OP_TXFIB_REWRITE (1 << 6) + int ops; + nat_6t_t match; + struct + { + ip4_address_t saddr, daddr; + u16 sport; + u16 dport; + u32 fib_index; + u8 proto; + u16 icmp_id; + } rewrite; + uword l3_csum_delta; + uword l4_csum_delta; +} nat_6t_flow_t; diff --git a/upf/upf_pfcp.c b/upf/upf_pfcp.c index 75145d4..8799fdc 100644 --- a/upf/upf_pfcp.c +++ b/upf/upf_pfcp.c @@ -1513,8 +1513,8 @@ pfcp_add_del_ue_ip (const void *ip, void *si, int is_add) u32 *ip2 = &ue_ip->addr.ip4.as_u32; // this seems to be the one - - clib_warning ("QQQQQ XD2 : ip = 0x%08x", *ip2); + clib_warning ("QQQQQ XD2 : ip = 0x%08x, fib_index=%d, sw_if_index=%d", *ip2, + ue_ip->fib_index, ue_ip->sw_if_index); if (*ip2 == 0x300010a) { *ip2 = 0x14000090; @@ -1599,15 +1599,6 @@ pfcp_add_del_tdf (const void *tdf, void *si, int is_ip4, int is_add) upf_acl_t *acl = (upf_acl_t *) tdf; upf_session_t *sx = si; - u32 *ip = &acl->match.address[UPF_ACL_FIELD_SRC].ip4.as_u32; - - clib_warning ("QQQQQ XD : ip = 0x%08x", *ip); - if (*ip == 0x300010a) - { - // *ip = 0x14000090; - clib_warning ("QQQQQCD = 0x%08x", *ip); - } - fib_prefix_t pfx = { .fp_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6, .fp_addr = acl->match.address[UPF_ACL_FIELD_SRC],