Fix issues reported by coverity
[vpp.git] / vnet / vnet / adj / adj_midchain.c
index 2fbedae..8c6ab5a 100644 (file)
@@ -24,8 +24,8 @@
 /**
  * The two midchain tx feature node indices
  */
-static u32 adj_midchain_tx_feature_node[FIB_LINK_NUM];
-static u32 adj_midchain_tx_no_count_feature_node[FIB_LINK_NUM];
+static u32 adj_midchain_tx_feature_node[VNET_LINK_NUM];
+static u32 adj_midchain_tx_no_count_feature_node[VNET_LINK_NUM];
 
 /**
  * @brief Trace data for packets traversing the midchain tx node
@@ -39,7 +39,7 @@ typedef struct adj_midchain_tx_trace_t_
 } adj_midchain_tx_trace_t;
 
 always_inline uword
-adj_mdichain_tx_inline (vlib_main_t * vm,
+adj_midchain_tx_inline (vlib_main_t * vm,
                        vlib_node_runtime_t * node,
                        vlib_frame_t * frame,
                        int interface_count)
@@ -64,10 +64,95 @@ adj_mdichain_tx_inline (vlib_main_t * vm,
        /* set up to enqueue to our disposition with index = next_index */
        vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
 
-       /*
-        * FIXME DUAL LOOP
-        */
 
+       while (n_left_from >= 4 && n_left_to_next > 2)
+       {
+           u32 bi0, adj_index0, next0;
+           const ip_adjacency_t * adj0;
+           const dpo_id_t *dpo0;
+           vlib_buffer_t * b0;
+           u32 bi1, adj_index1, next1;
+           const ip_adjacency_t * adj1;
+           const dpo_id_t *dpo1;
+           vlib_buffer_t * b1;
+
+           /* Prefetch next iteration. */
+           {
+               vlib_buffer_t * p2, * p3;
+
+               p2 = vlib_get_buffer (vm, from[2]);
+               p3 = vlib_get_buffer (vm, from[3]);
+
+               vlib_prefetch_buffer_header (p2, LOAD);
+               vlib_prefetch_buffer_header (p3, LOAD);
+
+               CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
+               CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
+           }
+
+           bi0 = from[0];
+           to_next[0] = bi0;
+           bi1 = from[1];
+           to_next[1] = bi1;
+
+           from += 2;
+           to_next += 2;
+           n_left_from -= 2;
+           n_left_to_next -= 2;
+
+           b0 = vlib_get_buffer(vm, bi0);
+           b1 = vlib_get_buffer(vm, bi1);
+
+           /* Follow the DPO on which the midchain is stacked */
+           adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
+           adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
+
+           adj0 = adj_get(adj_index0);
+           adj1 = adj_get(adj_index1);
+
+           dpo0 = &adj0->sub_type.midchain.next_dpo;
+           dpo1 = &adj1->sub_type.midchain.next_dpo;
+
+           next0 = dpo0->dpoi_next_node;
+           next1 = dpo1->dpoi_next_node;
+
+           vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
+           vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+
+           if (interface_count)
+           {
+               vlib_increment_combined_counter (im->combined_sw_if_counters
+                                                + VNET_INTERFACE_COUNTER_TX,
+                                                cpu_index,
+                                                adj0->rewrite_header.sw_if_index,
+                                                1,
+                                                vlib_buffer_length_in_chain (vm, b0));
+               vlib_increment_combined_counter (im->combined_sw_if_counters
+                                                + VNET_INTERFACE_COUNTER_TX,
+                                                cpu_index,
+                                                adj1->rewrite_header.sw_if_index,
+                                                1,
+                                                vlib_buffer_length_in_chain (vm, b1));
+           }
+
+           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+           {
+               adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+                                                             b0, sizeof (*tr));
+               tr->ai = adj_index0;
+           }
+           if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
+           {
+               adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+                                                             b1, sizeof (*tr));
+               tr->ai = adj_index1;
+           }
+
+           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
+                                            to_next, n_left_to_next,
+                                            bi0, bi1,
+                                            next0, next1);
+       }
        while (n_left_from > 0 && n_left_to_next > 0)
        {
            u32 bi0, adj_index0, next0;
@@ -116,9 +201,6 @@ adj_mdichain_tx_inline (vlib_main_t * vm,
        vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     }
 
-    vlib_node_increment_counter (vm, gre_input_node.index,
-                                GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
-
     return frame->n_vectors;
 }
 
@@ -141,7 +223,7 @@ adj_midchain_tx (vlib_main_t * vm,
                 vlib_node_runtime_t * node,
                 vlib_frame_t * frame)
 {
-    return (adj_mdichain_tx_inline(vm, node, frame, 1));
+    return (adj_midchain_tx_inline(vm, node, frame, 1));
 }
 
 VLIB_REGISTER_NODE (adj_midchain_tx_node, static) = {
@@ -162,7 +244,7 @@ adj_midchain_tx_no_count (vlib_main_t * vm,
                          vlib_node_runtime_t * node,
                          vlib_frame_t * frame)
 {
-    return (adj_mdichain_tx_inline(vm, node, frame, 0));
+    return (adj_midchain_tx_inline(vm, node, frame, 0));
 }
 
 VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node, static) = {
@@ -178,99 +260,108 @@ VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node, static) = {
     },
 };
 
-VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
+    .arc_name = "ip4-output",
     .node_name = "adj-midchain-tx",
-    .runs_before = ORDER_CONSTRAINTS {"interface-output"},
-    .feature_index = &adj_midchain_tx_feature_node[FIB_LINK_IP4],
+    .runs_before = VNET_FEATURES ("interface-output"),
+    .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
 };
-VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
+    .arc_name = "ip4-output",
     .node_name = "adj-midchain-tx-no-count",
-    .runs_before = ORDER_CONSTRAINTS {"interface-output"},
-    .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_LINK_IP4],
+    .runs_before = VNET_FEATURES ("interface-output"),
+    .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP4],
 };
-VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
+    .arc_name = "ip6-output",
     .node_name = "adj-midchain-tx",
-    .runs_before = ORDER_CONSTRAINTS {"interface-output"},
-    .feature_index = &adj_midchain_tx_feature_node[FIB_LINK_IP6],
+    .runs_before = VNET_FEATURES ("interface-output"),
+    .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
 };
-VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
+    .arc_name = "ip6-output",
     .node_name = "adj-midchain-tx-no-count",
-    .runs_before = ORDER_CONSTRAINTS {"interface-output"},
-    .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_LINK_IP6],
+    .runs_before = VNET_FEATURES ("interface-output"),
+    .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP6],
 };
-VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
-    .node_name = "adj-midchain-txs",
-    .runs_before = ORDER_CONSTRAINTS {"interface-output"},
-    .feature_index = &adj_midchain_tx_feature_node[FIB_LINK_MPLS],
+VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
+    .arc_name = "mpls-output",
+    .node_name = "adj-midchain-tx",
+    .runs_before = VNET_FEATURES ("interface-output"),
+    .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
 };
-VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
+    .arc_name = "mpls-output",
     .node_name = "adj-midchain-tx-no-count",
-    .runs_before = ORDER_CONSTRAINTS {"interface-output"},
-    .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_LINK_MPLS],
+    .runs_before = VNET_FEATURES ("interface-output"),
+    .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_MPLS],
 };
-VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
+    .arc_name = "ethernet-output",
     .node_name = "adj-midchain-tx",
-    .runs_before = ORDER_CONSTRAINTS {"error-drop"},
-    .feature_index = &adj_midchain_tx_feature_node[FIB_LINK_ETHERNET],
+    .runs_before = VNET_FEATURES ("error-drop"),
+    .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET],
 };
-VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
+    .arc_name = "ethernet-output",
     .node_name = "adj-midchain-tx-no-count",
-    .runs_before = ORDER_CONSTRAINTS {"error-drop"},
-    .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_LINK_ETHERNET],
+    .runs_before = VNET_FEATURES ("error-drop"),
+    .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET],
 };
 
 static inline u32
-adj_get_midchain_node (fib_link_t link)
+adj_get_midchain_node (vnet_link_t link)
 {
     switch (link) {
-    case FIB_LINK_IP4:
+    case VNET_LINK_IP4:
        return (ip4_midchain_node.index);
-    case FIB_LINK_IP6:
+    case VNET_LINK_IP6:
        return (ip6_midchain_node.index);
-    case FIB_LINK_MPLS:
+    case VNET_LINK_MPLS:
        return (mpls_midchain_node.index);
-    case FIB_LINK_ETHERNET:
+    case VNET_LINK_ETHERNET:
        return (adj_l2_midchain_node.index);
+    case VNET_LINK_ARP:
+       break;
     }
     ASSERT(0);
     return (0);
 }
 
-static ip_config_main_t *
-adj_midchain_get_cofing_for_link_type (const ip_adjacency_t *adj)
+static u8
+adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj)
 {
-    ip_config_main_t *cm = NULL;
-
+  u8 arc = (u8) ~0;
     switch (adj->ia_link)
     {
-    case FIB_LINK_IP4:
+    case VNET_LINK_IP4:
        {
-           ip4_main_t * im = &ip4_main;
-           ip_lookup_main_t * lm = &im->lookup_main;
-           cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
+           arc = ip4_main.lookup_main.output_feature_arc_index;
            break;
        }
-    case FIB_LINK_IP6:
+    case VNET_LINK_IP6:
        {
-           ip6_main_t * im = &ip6_main;
-           ip_lookup_main_t * lm = &im->lookup_main;
-           cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
+           arc = ip6_main.lookup_main.output_feature_arc_index;
            break;
        }
-    case FIB_LINK_MPLS:
+    case VNET_LINK_MPLS:
        {
-           mpls_main_t * mm = &mpls_main;
-           cm = &mm->feature_config_mains[VNET_IP_TX_FEAT];
+           arc = mpls_main.output_feature_arc_index;
            break;
        }
-    case FIB_LINK_ETHERNET:
+    case VNET_LINK_ETHERNET:
        {
-           cm = &ethernet_main.feature_config_mains[VNET_IP_TX_FEAT];
+           arc = ethernet_main.output_feature_arc_index;
            break;
        }
+    case VNET_LINK_ARP:
+       ASSERT(0);
+       break;
     }
 
-    return (cm);
+    ASSERT (arc != (u8) ~0);
+
+    return (arc);
 }
 
 /**
@@ -286,10 +377,9 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
                                 adj_midchain_flag_t flags,
                                 u8 *rewrite)
 {
-    vnet_config_main_t * vcm;
-    ip_config_main_t *cm;
     ip_adjacency_t *adj;
-    u32 ci;
+    u8 arc_index;
+    u32 feature_index;
 
     ASSERT(ADJ_INDEX_INVALID != adj_index);
 
@@ -307,43 +397,18 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
 
     adj->sub_type.midchain.fixup_func = fixup;
 
-    cm = adj_midchain_get_cofing_for_link_type(adj);
-    vcm = &(cm->config_main);
-    vec_validate_init_empty(cm->config_index_by_sw_if_index,
-                           adj->rewrite_header.sw_if_index, ~0);
-    ci = cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index];
+    arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj);
+    feature_index = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ?
+                    adj_midchain_tx_no_count_feature_node[adj->ia_link] :
+                    adj_midchain_tx_feature_node[adj->ia_link];
 
-    /*
-     * Choose the adj tx function based on whether the client wants
-     * to count against the interface or not and insert the appropriate
-     * TX feature.
-     */
-    if (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT)
-    {
-       adj->sub_type.midchain.tx_function_node =
-           adj_midchain_tx_no_count_node.index;
-
-       ci = vnet_config_add_feature(
-                vlib_get_main(),
-                vcm, ci,
-                adj_midchain_tx_no_count_feature_node[adj->ia_link],
-                /* config data */ 0,
-                /* # bytes of config data */ 0);
-    }
-    else
-    {
-       adj->sub_type.midchain.tx_function_node =
-           adj_midchain_tx_node.index;
-       ci = vnet_config_add_feature(
-                vlib_get_main(),
-                vcm, ci,
-                adj_midchain_tx_feature_node[adj->ia_link],
-                /* config data */ 0,
-                /* # bytes of config data */ 0);
-    }
-
-    cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index] = ci;
+    adj->sub_type.midchain.tx_function_node = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ?
+                                               adj_midchain_tx_no_count_node.index :
+                                               adj_midchain_tx_node.index;
 
+    vnet_feature_enable_disable_with_index (arc_index, feature_index,
+                                           adj->rewrite_header.sw_if_index,
+                                           1 /* enable */, 0, 0);
 
     /*
      * stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
@@ -354,7 +419,7 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
      */
     dpo_stack_from_node(adj->sub_type.midchain.tx_function_node,
                        &adj->sub_type.midchain.next_dpo,
-                       drop_dpo_get(fib_link_to_dpo_proto(adj->ia_link)));
+                       drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
 
     /*
      * update the rewirte with the workers paused.
@@ -364,15 +429,6 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
                                    adj_get_midchain_node(adj->ia_link),
                                    adj->sub_type.midchain.tx_function_node,
                                    rewrite);
-
-    /*
-     * time for walkies fido.
-     */
-    fib_node_back_walk_ctx_t bw_ctx = {
-       .fnbw_reason = FIB_NODE_BW_REASON_ADJ_UPDATE,
-    };
-
-    fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
 }
 
 /**
@@ -393,9 +449,9 @@ adj_nbr_midchain_unstack (adj_index_t adj_index)
      * stack on the drop
      */
     dpo_stack(DPO_ADJACENCY_MIDCHAIN,
-             fib_link_to_dpo_proto(adj->ia_link),
+             vnet_link_to_dpo_proto(adj->ia_link),
              &adj->sub_type.midchain.next_dpo,
-             drop_dpo_get(fib_link_to_dpo_proto(adj->ia_link)));
+             drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
 
     CLIB_MEMORY_BARRIER();
 }
@@ -428,7 +484,7 @@ format_adj_midchain (u8* s, va_list *ap)
     vnet_main_t * vnm = vnet_get_main();
     ip_adjacency_t * adj = adj_get(index);
 
-    s = format (s, "%U", format_fib_link, adj->ia_link);
+    s = format (s, "%U", format_vnet_link, adj->ia_link);
     s = format (s, " via %U ",
                format_ip46_address, &adj->sub_type.nbr.next_hop);
     s = format (s, " %U",