fib: Decouple source from priority and behaviour
[vpp.git] / src / plugins / nat / nat.c
index 85072bc..d713368 100755 (executable)
 
 snat_main_t snat_main;
 
-/* *INDENT-OFF* */
+fib_source_t nat_fib_src_hi;
+fib_source_t nat_fib_src_low;
 
+/* *INDENT-OFF* */
 /* Hook up input features */
+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"),
+};
+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"),
+};
+VNET_FEATURE_INIT (snat_in2out_worker_handoff, static) = {
+  .arc_name = "ip4-unicast",
+  .node_name = "nat44-in2out-worker-handoff",
+  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
+};
+VNET_FEATURE_INIT (snat_out2in_worker_handoff, static) = {
+  .arc_name = "ip4-unicast",
+  .node_name = "nat44-out2in-worker-handoff",
+  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
+                               "ip4-dhcp-client-detect"),
+};
 VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
   .arc_name = "ip4-unicast",
   .node_name = "nat44-in2out",
@@ -89,17 +113,6 @@ VNET_FEATURE_INIT (ip4_nat44_ed_classify, static) = {
   .node_name = "nat44-ed-classify",
   .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
 };
-VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
-  .arc_name = "ip4-unicast",
-  .node_name = "nat44-in2out-worker-handoff",
-  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
-};
-VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
-  .arc_name = "ip4-unicast",
-  .node_name = "nat44-out2in-worker-handoff",
-  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
-                               "ip4-dhcp-client-detect"),
-};
 VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
   .arc_name = "ip4-unicast",
   .node_name = "nat44-handoff-classify",
@@ -526,7 +539,7 @@ snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
   if (is_add)
     fib_table_entry_update_one_path (fib_index,
                                     &prefix,
-                                    FIB_SOURCE_PLUGIN_LOW,
+                                    nat_fib_src_low,
                                     (FIB_ENTRY_FLAG_CONNECTED |
                                      FIB_ENTRY_FLAG_LOCAL |
                                      FIB_ENTRY_FLAG_EXCLUSIVE),
@@ -535,7 +548,7 @@ snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
                                     sw_if_index,
                                     ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
   else
-    fib_table_entry_delete (fib_index, &prefix, FIB_SOURCE_PLUGIN_LOW);
+    fib_table_entry_delete (fib_index, &prefix, nat_fib_src_low);
 }
 
 int
@@ -567,7 +580,7 @@ snat_add_address (snat_main_t * sm, ip4_address_t * addr, u32 vrf_id,
   if (vrf_id != ~0)
     ap->fib_index =
       fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                        FIB_SOURCE_PLUGIN_LOW);
+                                        nat_fib_src_low);
   else
     ap->fib_index = ~0;
 #define _(N, i, n, s) \
@@ -803,7 +816,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
              local->vrf_id = vrf_id;
              local->fib_index =
                fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                                  FIB_SOURCE_PLUGIN_LOW);
+                                                  nat_fib_src_low);
              m_key.addr = m->local_addr;
              m_key.port = m->local_port;
              m_key.protocol = m->proto;
@@ -824,13 +837,13 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       if (vrf_id != ~0)
        fib_index =
          fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                            FIB_SOURCE_PLUGIN_LOW);
+                                            nat_fib_src_low);
       /* If not specified use inside VRF id from SNAT plugin startup config */
       else
        {
          fib_index = sm->inside_fib_index;
          vrf_id = sm->inside_vrf_id;
-         fib_table_lock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+         fib_table_lock (fib_index, FIB_PROTOCOL_IP4, nat_fib_src_low);
        }
 
       if (!(out2in_only || identity_nat))
@@ -1123,7 +1136,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
            }
        }
 
-      fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+      fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, nat_fib_src_low);
       if (pool_elts (m->locals))
        return 0;
 
@@ -1281,7 +1294,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
          locals[i].fib_index =
            fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                               locals[i].vrf_id,
-                                              FIB_SOURCE_PLUGIN_LOW);
+                                              nat_fib_src_low);
          m_key.addr = locals[i].addr;
          m_key.fib_index = locals[i].fib_index;
          if (!out2in_only)
@@ -1371,7 +1384,7 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       pool_foreach (local, m->locals,
       ({
           fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4,
-                            FIB_SOURCE_PLUGIN_LOW);
+                            nat_fib_src_low);
           m_key.addr = local->addr;
           if (!out2in_only)
             {
@@ -1504,7 +1517,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
       local->vrf_id = vrf_id;
       local->fib_index =
        fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
-                                          FIB_SOURCE_PLUGIN_LOW);
+                                          nat_fib_src_low);
 
       if (!is_out2in_only_static_mapping (m))
        {
@@ -1526,7 +1539,7 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
        return VNET_API_ERROR_UNSPECIFIED;
 
       fib_table_unlock (match_local->fib_index, FIB_PROTOCOL_IP4,
-                       FIB_SOURCE_PLUGIN_LOW);
+                       nat_fib_src_low);
 
       if (!is_out2in_only_static_mapping (m))
        {
@@ -1677,7 +1690,7 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
     }
 
   if (a->fib_index != ~0)
-    fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_LOW);
+    fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nat_fib_src_low);
 
   /* Delete sessions using address */
   if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
@@ -1775,18 +1788,20 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
       else if (sm->deterministic)
        feature_name = is_inside ? "nat44-det-in2out" : "nat44-det-out2in";
       else if (sm->endpoint_dependent)
-       feature_name = is_inside ? "nat44-ed-in2out" : "nat44-ed-out2in";
+       {
+         feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in";
+       }
       else
        feature_name = is_inside ? "nat44-in2out" : "nat44-out2in";
     }
 
   if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
-    sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index,
-                                                     NAT_FQ_NELTS);
+    sm->fq_in2out_index =
+      vlib_frame_queue_main_init (sm->handoff_in2out_index, NAT_FQ_NELTS);
 
   if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
-    sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index,
-                                                     NAT_FQ_NELTS);
+    sm->fq_out2in_index =
+      vlib_frame_queue_main_init (sm->handoff_out2in_index, NAT_FQ_NELTS);
 
   if (!is_inside)
     {
@@ -1844,8 +1859,8 @@ feature_set:
                 else if (sm->endpoint_dependent)
                   {
                     del_feature_name = "nat44-ed-classify";
-                    feature_name = !is_inside ?  "nat44-ed-in2out" :
-                                                 "nat44-ed-out2in";
+                    feature_name = !is_inside ?  "nat-pre-in2out" :
+                                                 "nat-pre-out2in";
                   }
                 else
                   {
@@ -1907,8 +1922,9 @@ feature_set:
               }
             else if (sm->endpoint_dependent)
               {
-                del_feature_name = !is_inside ?  "nat44-ed-in2out" :
-                                                 "nat44-ed-out2in";
+                del_feature_name = !is_inside ?  "nat-pre-in2out" :
+                                                 "nat-pre-out2in";
+
                 feature_name = "nat44-ed-classify";
               }
             else
@@ -2074,7 +2090,7 @@ feature_set:
     {
       if (sm->endpoint_dependent)
        {
-         vnet_feature_enable_disable ("ip4-unicast", "nat44-ed-out2in",
+         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",
                                       sw_if_index, !is_del, 0, 0);
@@ -2091,11 +2107,11 @@ feature_set:
 fq:
   if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
     sm->fq_in2out_output_index =
-      vlib_frame_queue_main_init (sm->in2out_output_node_index, 0);
+      vlib_frame_queue_main_init (sm->handoff_in2out_output_index, 0);
 
   if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
     sm->fq_out2in_index =
-      vlib_frame_queue_main_init (sm->out2in_node_index, 0);
+      vlib_frame_queue_main_init (sm->handoff_out2in_index, 0);
 
   /* *INDENT-OFF* */
   pool_foreach (i, sm->output_feature_interfaces,
@@ -2316,6 +2332,19 @@ snat_init (vlib_main_t * vm)
   node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
   sm->error_node_index = node->index;
 
+  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-in2out");
+  sm->pre_in2out_node_index = node->index;
+  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in");
+  sm->pre_out2in_node_index = node->index;
+
+  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-in2out");
+  sm->pre_in2out_node_index = node->index;
+
+  node = vlib_get_node_by_name (vm, (u8 *) "nat-pre-out2in");
+  sm->pre_out2in_node_index = node->index;
+
+  // TODO: output ?? (special node)
+
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out");
   sm->in2out_node_index = node->index;
   node = vlib_get_node_by_name (vm, (u8 *) "nat44-in2out-output");
@@ -2438,6 +2467,13 @@ snat_init (vlib_main_t * vm)
   };
   vec_add1 (ip4_main.table_bind_callbacks, cbt4);
 
+  nat_fib_src_hi = fib_source_allocate ("nat-hi",
+                                       FIB_SOURCE_PRIORITY_HI,
+                                       FIB_SOURCE_BH_SIMPLE);
+  nat_fib_src_low = fib_source_allocate ("nat-low",
+                                        FIB_SOURCE_PRIORITY_LOW,
+                                        FIB_SOURCE_BH_SIMPLE);
+
   /* Init virtual fragmenentation reassembly */
   return nat_reass_init (vm);
 }
@@ -2889,13 +2925,13 @@ nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add)
   if (is_add)
     {
       nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
-      fib_table_entry_special_dpo_add (0, &pfx, FIB_SOURCE_PLUGIN_HI,
+      fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi,
                                       FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
       dpo_reset (&dpo_v4);
     }
   else
     {
-      fib_table_entry_special_remove (0, &pfx, FIB_SOURCE_PLUGIN_HI);
+      fib_table_entry_special_remove (0, &pfx, nat_fib_src_hi);
     }
 }
 
@@ -3810,15 +3846,15 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
   sm->outside_vrf_id = outside_vrf_id;
   sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                                             outside_vrf_id,
-                                                            FIB_SOURCE_PLUGIN_HI);
+                                                            nat_fib_src_hi);
   nm->outside_vrf_id = outside_ip6_vrf_id;
   nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
                                                             outside_ip6_vrf_id,
-                                                            FIB_SOURCE_PLUGIN_HI);
+                                                            nat_fib_src_hi);
   sm->inside_vrf_id = inside_vrf_id;
   sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
                                                            inside_vrf_id,
-                                                           FIB_SOURCE_PLUGIN_HI);
+                                                           nat_fib_src_hi);
   sm->static_mapping_only = static_mapping_only;
   sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
 
@@ -3839,9 +3875,16 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
        {
          sm->worker_in2out_cb = nat44_ed_get_worker_in2out_cb;
          sm->worker_out2in_cb = nat44_ed_get_worker_out2in_cb;
+
+         sm->handoff_out2in_index = nat_pre_out2in_node.index;
+         sm->handoff_in2out_index = nat_pre_in2out_node.index;
+         // TODO: test
+         sm->handoff_in2out_output_index = nat44_ed_in2out_output_node.index;
+
          sm->in2out_node_index = nat44_ed_in2out_node.index;
          sm->in2out_output_node_index = nat44_ed_in2out_output_node.index;
          sm->out2in_node_index = nat44_ed_out2in_node.index;
+
          sm->icmp_match_in2out_cb = icmp_match_in2out_ed;
          sm->icmp_match_out2in_cb = icmp_match_out2in_ed;
          nat_affinity_init (vm);
@@ -3852,6 +3895,12 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
        {
          sm->worker_in2out_cb = snat_get_worker_in2out_cb;
          sm->worker_out2in_cb = snat_get_worker_out2in_cb;
+
+         sm->handoff_out2in_index = snat_in2out_node.index;
+         sm->handoff_in2out_index = snat_out2in_node.index;
+         // TODO: test
+         sm->handoff_in2out_output_index = snat_in2out_output_node.index;
+
          sm->in2out_node_index = snat_in2out_node.index;
          sm->in2out_output_node_index = snat_in2out_output_node.index;
          sm->out2in_node_index = snat_out2in_node.index;
@@ -4263,6 +4312,38 @@ nat_set_alloc_addr_and_port_default (void)
   sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
 }
 
+VLIB_NODE_FN (nat_default_node) (vlib_main_t * vm,
+                                vlib_node_runtime_t * node,
+                                vlib_frame_t * frame)
+{
+  return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (nat_default_node) = {
+  .name = "nat-default",
+  .vector_size = sizeof (u32),
+  .format_trace = 0,
+  .type = VLIB_NODE_TYPE_INTERNAL,
+  .n_errors = 0,
+  .n_next_nodes = NAT_N_NEXT,
+  .next_nodes = {
+    [NAT_NEXT_DROP] = "error-drop",
+    [NAT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
+    [NAT_NEXT_IN2OUT_PRE] = "nat-pre-in2out",
+    [NAT_NEXT_OUT2IN_PRE] = "nat-pre-out2in",
+    [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* */
+
 /*
  * fd.io coding-style-patch-verification: ON
  *