X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fcnat%2Fcnat_translation.c;h=1cdb94f04a6e6b6be3d177625e6d7d6ad6f6c50d;hb=589fe7ca6;hp=8b7cf2451b791e31bf58f9f66a8c926fb4a1f264;hpb=4d237874e5c9922330c62ac1b003a9a171c1bc3b;p=vpp.git diff --git a/src/plugins/cnat/cnat_translation.c b/src/plugins/cnat/cnat_translation.c index 8b7cf2451b7..1cdb94f04a6 100644 --- a/src/plugins/cnat/cnat_translation.c +++ b/src/plugins/cnat/cnat_translation.c @@ -20,15 +20,13 @@ #include #include +#include #include #include cnat_translation_t *cnat_translation_pool; clib_bihash_8_8_t cnat_translation_db; addr_resolution_t *tr_resolutions; - -typedef void (*cnat_if_addr_add_cb_t) (addr_resolution_t * ar, - ip_address_t * address, u8 is_del); cnat_if_addr_add_cb_t *cnat_if_addr_add_cbs; static fib_node_type_t cnat_translation_fib_node_type; @@ -203,108 +201,7 @@ cnat_remove_translation_from_db (index_t cci, cnat_endpoint_t * vip, clib_bihash_add_del_8_8 (&cnat_translation_db, &bkey, 0); } -typedef struct -{ - cnat_ep_trk_t *trk; - u32 index; - u32 offset; - u32 skip; -} cnat_maglev_entry_t; - -static int -cnat_maglev_entry_compare (void *_a, void *_b) -{ - cnat_ep_trk_t *a = ((cnat_maglev_entry_t *) _a)->trk; - cnat_ep_trk_t *b = ((cnat_maglev_entry_t *) _b)->trk; - int rv = 0; - if ((rv = - ip_address_cmp (&a->ct_ep[VLIB_TX].ce_ip, &b->ct_ep[VLIB_TX].ce_ip))) - return rv; - if ((rv = a->ct_ep[VLIB_TX].ce_port - a->ct_ep[VLIB_TX].ce_port)) - return rv; - if ((rv = - ip_address_cmp (&a->ct_ep[VLIB_RX].ce_ip, &b->ct_ep[VLIB_RX].ce_ip))) - return rv; - if ((rv = a->ct_ep[VLIB_RX].ce_port - a->ct_ep[VLIB_RX].ce_port)) - return rv; - return 0; -} - -static void -cnat_translation_init_maglev (cnat_translation_t *ct) -{ - cnat_maglev_entry_t *backends = NULL, *bk; - cnat_main_t *cm = &cnat_main; - u32 done = 0; - cnat_ep_trk_t *trk; - int ep_idx = 0; - - vec_foreach (trk, ct->ct_active_paths) - { - cnat_maglev_entry_t bk; - u32 h1, h2; - - if (AF_IP4 == ip_addr_version (&trk->ct_ep[VLIB_TX].ce_ip)) - { - u32 a, b, c; - a = ip_addr_v4 (&trk->ct_ep[VLIB_TX].ce_ip).data_u32; - b = trk->ct_ep[VLIB_TX].ce_port << 16 | trk->ct_ep[VLIB_RX].ce_port; - c = ip_addr_v4 (&trk->ct_ep[VLIB_RX].ce_ip).data_u32; - hash_v3_mix32 (a, b, c); - hash_v3_finalize32 (a, b, c); - h1 = c; - h2 = b; - } - else - { - u64 a, b, c; - a = ip_addr_v6 (&trk->ct_ep[VLIB_TX].ce_ip).as_u64[0] ^ - ip_addr_v6 (&trk->ct_ep[VLIB_TX].ce_ip).as_u64[1]; - b = trk->ct_ep[VLIB_TX].ce_port << 16 | trk->ct_ep[VLIB_RX].ce_port; - c = ip_addr_v6 (&trk->ct_ep[VLIB_RX].ce_ip).as_u64[0] ^ - ip_addr_v6 (&trk->ct_ep[VLIB_RX].ce_ip).as_u64[1]; - hash_mix64 (a, b, c); - h1 = c; - h2 = b; - } - - bk.offset = h1 % cm->maglev_len; - bk.skip = h2 % (cm->maglev_len - 1) + 1; - bk.index = ep_idx++; - bk.trk = trk; - vec_add1 (backends, bk); - } - - if (0 == ep_idx) - return; - - vec_sort_with_function (backends, cnat_maglev_entry_compare); - - /* Don't free if previous vector exists, just zero */ - vec_validate (ct->lb_maglev, cm->maglev_len); - vec_set (ct->lb_maglev, -1); - - while (1) - { - vec_foreach (bk, backends) - { - u32 next = 0; - u32 c = (bk->offset + next * bk->skip) % cm->maglev_len; - while (ct->lb_maglev[c] != (u32) -1) - { - next++; - c = (bk->offset + next * bk->skip) % cm->maglev_len; - } - ct->lb_maglev[c] = bk->index; - done++; - if (done == cm->maglev_len) - goto finished; - } - } -finished: - vec_free (backends); -} static void cnat_translation_stack (cnat_translation_t * ct) @@ -324,8 +221,11 @@ cnat_translation_stack (cnat_translation_t * ct) if (trk->ct_flags & CNAT_TRK_ACTIVE) vec_add1 (ct->ct_active_paths, *trk); + flow_hash_config_t fhc = IP_FLOW_HASH_DEFAULT; + if (ct->fhc != 0) + fhc = ct->fhc; lbi = load_balance_create (vec_len (ct->ct_active_paths), - fib_proto_to_dpo (fproto), IP_FLOW_HASH_DEFAULT); + fib_proto_to_dpo (fproto), fhc); ep_idx = 0; vec_foreach (trk, ct->ct_active_paths) @@ -336,7 +236,7 @@ cnat_translation_stack (cnat_translation_t * ct) dpo_set (&ct->ct_lb, DPO_LOAD_BALANCE, dproto, lbi); dpo_stack (cnat_client_dpo, dproto, &ct->ct_lb, &ct->ct_lb); - ct->flags |= CNAT_TRANSLATION_STACKED; + ct->flags |= CNAT_TR_FLAG_STACKED; } int @@ -366,7 +266,7 @@ cnat_translation_delete (u32 id) u32 cnat_translation_update (cnat_endpoint_t *vip, ip_protocol_t proto, cnat_endpoint_tuple_t *paths, u8 flags, - cnat_lb_type_t lb_type) + cnat_lb_type_t lb_type, flow_hash_config_t fhc) { cnat_endpoint_tuple_t *path; const cnat_client_t *cc; @@ -399,6 +299,7 @@ cnat_translation_update (cnat_endpoint_t *vip, ip_protocol_t proto, ct->ct_cci = cci; ct->index = ct - cnat_translation_pool; ct->lb_type = lb_type; + ct->fhc = fhc; cnat_add_translation_to_db (cci, vip, proto, ct->index); cnat_client_translation_added (cci); @@ -418,7 +319,7 @@ cnat_translation_update (cnat_endpoint_t *vip, ip_protocol_t proto, } vec_reset_length (ct->ct_paths); - ct->flags &= ~CNAT_TRANSLATION_STACKED; + ct->flags &= ~CNAT_TR_FLAG_STACKED; u64 path_idx = 0; vec_foreach (path, paths) @@ -487,6 +388,11 @@ format_cnat_translation (u8 * s, va_list * args) format_ip_protocol, ct->ct_proto); s = format (s, "lb:%U ", format_cnat_lb_type, ct->lb_type); + if ((ct->fhc == 0) || (ct->fhc == IP_FLOW_HASH_DEFAULT)) + s = format (s, "fhc:0x%x(default)", IP_FLOW_HASH_DEFAULT); + else + s = format (s, "fhc:0x%x", ct->fhc); + vec_foreach (ck, ct->ct_paths) s = format (s, "\n%U", format_cnat_ep_trk, ck, 2); @@ -616,7 +522,7 @@ cnat_translation_back_walk_notify (fib_node_t * node, /* If we have more than FIB_PATH_LIST_POPULAR paths * we might get called during path tracking * (cnat_tracker_track) */ - if (!(ct->flags & CNAT_TRANSLATION_STACKED)) + if (!(ct->flags & CNAT_TR_FLAG_STACKED)) return (FIB_NODE_BACK_WALK_CONTINUE); cnat_translation_stack (ct); @@ -679,8 +585,9 @@ cnat_translation_cli_add_del (vlib_main_t * vm, } } + flow_hash_config_t fhc = 0; if (INDEX_INVALID == del_index) - cnat_translation_update (&vip, proto, paths, flags, lb_type); + cnat_translation_update (&vip, proto, paths, flags, lb_type, fhc); else cnat_translation_delete (del_index); @@ -765,37 +672,11 @@ cnat_if_addr_add_del_backend_cb (addr_resolution_t * ar, ep->ce_flags |= CNAT_EP_FLAG_RESOLVED; } - ct->flags &= ~CNAT_TRANSLATION_STACKED; + ct->flags &= ~CNAT_TR_FLAG_STACKED; cnat_tracker_track (ar->cti, trk); cnat_translation_stack (ct); - ct->flags |= CNAT_TRANSLATION_STACKED; -} - -static void -cnat_if_addr_add_del_snat_cb (addr_resolution_t * ar, ip_address_t * address, - u8 is_del) -{ - cnat_endpoint_t *ep; - ep = AF_IP4 == ar->af ? &cnat_main.snat_ip4 : &cnat_main.snat_ip6; - - if (!is_del && ep->ce_flags & CNAT_EP_FLAG_RESOLVED) - return; - - if (is_del) - { - ep->ce_flags &= ~CNAT_EP_FLAG_RESOLVED; - /* Are there remaining addresses ? */ - if (0 == cnat_resolve_addr (ar->sw_if_index, ar->af, address)) - is_del = 0; - } - - if (!is_del) - { - ip_address_copy (&ep->ce_ip, address); - ep->ce_flags |= CNAT_EP_FLAG_RESOLVED; - } - + ct->flags |= CNAT_TR_FLAG_STACKED; } static void @@ -837,6 +718,14 @@ cnat_ip4_if_addr_add_del_callback (struct ip4_main_t *im, cnat_if_addr_add_del_callback (sw_if_index, &addr, is_del); } +void +cnat_translation_register_addr_add_cb (cnat_addr_resol_type_t typ, + cnat_if_addr_add_cb_t fn) +{ + vec_validate (cnat_if_addr_add_cbs, CNAT_ADDR_N_RESOLUTIONS); + cnat_if_addr_add_cbs[typ] = fn; +} + static clib_error_t * cnat_translation_init (vlib_main_t * vm) { @@ -844,7 +733,7 @@ cnat_translation_init (vlib_main_t * vm) ip6_main_t *i6m = &ip6_main; cnat_main_t *cm = &cnat_main; cnat_translation_fib_node_type = - fib_node_register_new_type (&cnat_translation_vft); + fib_node_register_new_type ("cnat-translation", &cnat_translation_vft); clib_bihash_init_8_8 (&cnat_translation_db, "CNat translation DB", cm->translation_hash_buckets, @@ -858,12 +747,11 @@ cnat_translation_init (vlib_main_t * vm) cb6.function = cnat_ip6_if_addr_add_del_callback; vec_add1 (i6m->add_del_interface_address_callbacks, cb6); - vec_validate (cnat_if_addr_add_cbs, CNAT_ADDR_N_RESOLUTIONS); - cnat_if_addr_add_cbs[CNAT_RESOLV_ADDR_BACKEND] = - cnat_if_addr_add_del_backend_cb; - cnat_if_addr_add_cbs[CNAT_RESOLV_ADDR_SNAT] = cnat_if_addr_add_del_snat_cb; - cnat_if_addr_add_cbs[CNAT_RESOLV_ADDR_TRANSLATION] = - cnat_if_addr_add_del_translation_cb; + cnat_translation_register_addr_add_cb (CNAT_RESOLV_ADDR_BACKEND, + cnat_if_addr_add_del_backend_cb); + cnat_translation_register_addr_add_cb (CNAT_RESOLV_ADDR_TRANSLATION, + cnat_if_addr_add_del_translation_cb); + return (NULL); }