X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat.c;h=c1a18394aff5ee69bedfe989f0a7c3e1d7596abf;hb=f126e746fc01c75bc99329d10ce9127b26b23814;hp=d85fb267bed8e47cda394725b214371bf325ebc1;hpb=3535501b19aec95dfd32870c784f841f57b5c045;p=vpp.git diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index d85fb267bed..c1a18394aff 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -26,13 +26,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include @@ -46,13 +46,15 @@ fib_source_t nat_fib_src_low; VNET_FEATURE_INIT (nat_pre_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat-pre-in2out", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + "ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (nat_pre_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat-pre-out2in", .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", - "ip4-dhcp-client-detect"), + "ip4-dhcp-client-detect", + "ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (snat_in2out_worker_handoff, static) = { .arc_name = "ip4-unicast", @@ -68,103 +70,103 @@ VNET_FEATURE_INIT (snat_out2in_worker_handoff, static) = { VNET_FEATURE_INIT (ip4_snat_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-in2out", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_snat_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", "ip4-dhcp-client-detect"), }; VNET_FEATURE_INIT (ip4_nat_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-classify", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-det-in2out", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-det-out2in", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", "ip4-dhcp-client-detect"), }; VNET_FEATURE_INIT (ip4_nat_det_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-det-classify", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_nat44_ed_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-ed-in2out", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_nat44_ed_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-ed-out2in", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", "ip4-dhcp-client-detect"), }; VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-ed-classify", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-handoff-classify", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-in2out-fast", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in-fast", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature", "ip4-dhcp-client-detect"), }; VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-hairpin-dst", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_dst, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-ed-hairpin-dst", - .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa","ip4-sv-reassembly-feature"), }; /* Hook up output features */ VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = { .arc_name = "ip4-output", .node_name = "nat44-in2out-output", - .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"), }; VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = { .arc_name = "ip4-output", .node_name = "nat44-in2out-output-worker-handoff", - .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"), }; VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = { .arc_name = "ip4-output", .node_name = "nat44-hairpin-src", - .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"), }; VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = { .arc_name = "ip4-output", .node_name = "nat44-ed-in2out-output", - .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"), }; VNET_FEATURE_INIT (ip4_nat44_ed_hairpin_src, static) = { .arc_name = "ip4-output", .node_name = "nat44-ed-hairpin-src", - .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"), }; /* Hook up ip4-local features */ @@ -1869,6 +1871,9 @@ feature_set: feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in"; } + int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0); vnet_feature_enable_disable ("ip4-unicast", feature_name, @@ -1887,6 +1892,9 @@ feature_set: } else { + int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 0, 0, 0); pool_put (sm->interfaces, i); @@ -1934,6 +1942,9 @@ feature_set: feature_name = "nat44-classify"; } + int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0); vnet_feature_enable_disable ("ip4-unicast", feature_name, @@ -1964,6 +1975,10 @@ feature_set: vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, 0); + int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + return rv; + if (is_inside && !sm->out2in_dpo) { if (sm->endpoint_dependent) @@ -2063,6 +2078,15 @@ feature_set: { if (sm->endpoint_dependent) { + int rv = + ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); + if (rv) + return rv; + rv = + ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, + !is_del); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-hairpin-dst", sw_if_index, !is_del, 0, 0); vnet_feature_enable_disable ("ip4-output", "nat44-ed-hairpin-src", @@ -2070,6 +2094,15 @@ feature_set: } else { + int rv = + ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); + if (rv) + return rv; + rv = + ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, + !is_del); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst", sw_if_index, !is_del, 0, 0); vnet_feature_enable_disable ("ip4-output", "nat44-hairpin-src", @@ -2080,6 +2113,13 @@ feature_set: if (sm->num_workers > 1) { + int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); + if (rv) + return rv; + rv = + ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, !is_del); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in-worker-handoff", sw_if_index, !is_del, 0, 0); @@ -2091,6 +2131,15 @@ feature_set: { if (sm->endpoint_dependent) { + int rv = + ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); + if (rv) + return rv; + rv = + ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, + !is_del); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in", sw_if_index, !is_del, 0, 0); vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output", @@ -2098,6 +2147,15 @@ feature_set: } else { + int rv = + ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); + if (rv) + return rv; + rv = + ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, + !is_del); + if (rv) + return rv; vnet_feature_enable_disable ("ip4-unicast", "nat44-out2in", sw_if_index, !is_del, 0, 0); vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output", @@ -2352,29 +2410,21 @@ snat_init (vlib_main_t * vm) sm->in2out_slowpath_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output-slowpath"); sm->in2out_slowpath_output_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-reass"); - sm->in2out_reass_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out"); sm->ed_in2out_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-slowpath"); sm->ed_in2out_slowpath_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-in2out-reass"); - sm->ed_in2out_reass_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in"); sm->out2in_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-fast"); sm->out2in_fast_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat44-out2in-reass"); - sm->out2in_reass_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in"); sm->ed_out2in_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-slowpath"); sm->ed_out2in_slowpath_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "nat44-ed-out2in-reass"); - sm->ed_out2in_reass_node_index = node->index; node = vlib_get_node_by_name (vm, (u8 *) "nat44-det-in2out"); sm->det_in2out_node_index = node->index; @@ -2471,8 +2521,7 @@ snat_init (vlib_main_t * vm) FIB_SOURCE_PRIORITY_LOW, FIB_SOURCE_BH_SIMPLE); - /* Init virtual fragmenentation reassembly */ - return nat_reass_init (vm); + return error; } VLIB_INIT_FUNCTION (snat_init); @@ -3012,8 +3061,8 @@ snat_get_worker_in2out_cb (ip4_header_t * ip0, u32 rx_fib_index0, } static u32 -snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0, - u8 is_output) +snat_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip0, + u32 rx_fib_index0, u8 is_output) { snat_main_t *sm = &snat_main; udp_header_t *udp; @@ -3044,52 +3093,6 @@ snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0, udp = ip4_next_header (ip0); port = udp->dst_port; - if (PREDICT_FALSE (ip4_is_fragment (ip0))) - { - if (PREDICT_FALSE (nat_reass_is_drop_frag (0))) - return vlib_get_thread_index (); - - nat_reass_ip4_t *reass; - reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address, - ip0->fragment_id, ip0->protocol); - - if (reass && (reass->thread_index != (u32) ~ 0)) - return reass->thread_index; - - if (ip4_is_first_fragment (ip0)) - { - reass = - nat_ip4_reass_create (ip0->src_address, ip0->dst_address, - ip0->fragment_id, ip0->protocol); - if (!reass) - goto no_reass; - - if (PREDICT_FALSE (pool_elts (sm->static_mappings))) - { - m_key.addr = ip0->dst_address; - m_key.port = clib_net_to_host_u16 (port); - m_key.protocol = proto; - m_key.fib_index = rx_fib_index0; - kv.key = m_key.as_u64; - if (!clib_bihash_search_8_8 - (&sm->static_mapping_by_external, &kv, &value)) - { - m = pool_elt_at_index (sm->static_mappings, value.value); - reass->thread_index = m->workers[0]; - return reass->thread_index; - } - } - reass->thread_index = sm->first_worker_index; - reass->thread_index += - sm->workers[(clib_net_to_host_u16 (port) - 1024) / - sm->port_per_thread]; - return reass->thread_index; - } - else - return vlib_get_thread_index (); - } - -no_reass: /* unknown protocol */ if (PREDICT_FALSE (proto == ~0)) { @@ -3101,10 +3104,12 @@ no_reass: { icmp46_header_t *icmp = (icmp46_header_t *) udp; icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1); - if (!icmp_is_error_message (icmp)) - port = echo->identifier; + if (!icmp_type_is_error_message + (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)) + port = vnet_buffer (b)->ip.reass.l4_src_port; else { + /* if error message, then it's not fragmented and we can access it */ ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1); proto = ip_proto_to_snat_proto (inner_ip->protocol); void *l4_header = ip4_next_header (inner_ip); @@ -3252,8 +3257,8 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index, } static u32 -nat44_ed_get_worker_out2in_cb (ip4_header_t * ip, u32 rx_fib_index, - u8 is_output) +nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, + u32 rx_fib_index, u8 is_output) { snat_main_t *sm = &snat_main; clib_bihash_kv_8_8_t kv, value; @@ -3295,7 +3300,7 @@ nat44_ed_get_worker_out2in_cb (ip4_header_t * ip, u32 rx_fib_index, { nat_ed_ses_key_t key; - if (!get_icmp_o2i_ed_key (ip, &key)) + if (!get_icmp_o2i_ed_key (b, ip, &key)) { key.fib_index = rx_fib_index; @@ -3349,10 +3354,12 @@ nat44_ed_get_worker_out2in_cb (ip4_header_t * ip, u32 rx_fib_index, { icmp46_header_t *icmp = (icmp46_header_t *) udp; icmp_echo_header_t *echo = (icmp_echo_header_t *) (icmp + 1); - if (!icmp_is_error_message (icmp)) - port = echo->identifier; + if (!icmp_type_is_error_message + (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)) + port = vnet_buffer (b)->ip.reass.l4_src_port; else { + /* if error message, then it's not fragmented and we can access it */ ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1); proto = ip_proto_to_snat_proto (inner_ip->protocol); void *l4_header = ip4_next_header (inner_ip); @@ -4359,11 +4366,8 @@ VLIB_REGISTER_NODE (nat_default_node) = { [NAT_NEXT_IN2OUT_ED_FAST_PATH] = "nat44-ed-in2out", [NAT_NEXT_IN2OUT_ED_SLOW_PATH] = "nat44-ed-in2out-slowpath", [NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH] = "nat44-ed-in2out-output-slowpath", - [NAT_NEXT_IN2OUT_ED_REASS] = "nat44-ed-in2out-reass", - [NAT_NEXT_IN2OUT_ED_OUTPUT_REASS] = "nat44-ed-in2out-reass-output", [NAT_NEXT_OUT2IN_ED_FAST_PATH] = "nat44-ed-out2in", [NAT_NEXT_OUT2IN_ED_SLOW_PATH] = "nat44-ed-out2in-slowpath", - [NAT_NEXT_OUT2IN_ED_REASS] = "nat44-ed-out2in-reass", }, }; /* *INDENT-ON* */