VPP-521: Classify API enhancement to redirect traffic to pre-defined VRF
[vpp.git] / vnet / vnet / ip / ip_input_acl.c
index 75aa9ef..93a580c 100644 (file)
@@ -71,6 +71,9 @@ ip_inacl_inline (vlib_main_t * vm,
   u32 chain_hits = 0;
   input_acl_table_id_t tid;
   vlib_node_runtime_t * error_node;
+  u32 n_next_nodes;
+
+  n_next_nodes = node->n_next_nodes;
 
   if (is_ip4)
     {
@@ -112,11 +115,9 @@ ip_inacl_inline (vlib_main_t * vm,
 
       bi0 = from[0];
       b0 = vlib_get_buffer (vm, bi0);
-      h0 = b0->data;
 
       bi1 = from[1];
       b1 = vlib_get_buffer (vm, bi1);
-      h1 = b1->data;
 
       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
       table_index0 = am->classify_table_index_by_sw_if_index[tid][sw_if_index0];
@@ -128,11 +129,21 @@ ip_inacl_inline (vlib_main_t * vm,
 
       t1 = pool_elt_at_index (vcm->tables, table_index1);
 
+      if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+        h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+      else
+        h0 = b0->data;
+
       vnet_buffer(b0)->l2_classify.hash =
         vnet_classify_hash_packet (t0, (u8 *) h0);
 
       vnet_classify_prefetch_bucket (t0, vnet_buffer(b0)->l2_classify.hash);
 
+      if (t1->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+        h1 = (void *)vlib_buffer_get_current (b1) + t1->current_data_offset;
+      else
+        h1 = b1->data;
+
       vnet_buffer(b1)->l2_classify.hash =
         vnet_classify_hash_packet (t1, (u8 *) h1);
 
@@ -157,12 +168,17 @@ ip_inacl_inline (vlib_main_t * vm,
 
       bi0 = from[0];
       b0 = vlib_get_buffer (vm, bi0);
-      h0 = b0->data;
 
       sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
       table_index0 = am->classify_table_index_by_sw_if_index[tid][sw_if_index0];
 
       t0 = pool_elt_at_index (vcm->tables, table_index0);
+
+      if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+        h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+      else
+        h0 = b0->data;
+
       vnet_buffer(b0)->l2_classify.hash =
         vnet_classify_hash_packet (t0, (u8 *) h0);
 
@@ -224,28 +240,35 @@ ip_inacl_inline (vlib_main_t * vm,
           n_left_to_next -= 1;
 
           b0 = vlib_get_buffer (vm, bi0);
-          h0 = b0->data;
           table_index0 = vnet_buffer(b0)->l2_classify.table_index;
           e0 = 0;
           t0 = 0;
-
           vnet_get_config_data (am->vnet_config_main[tid],
-                                &vnet_buffer(b0)->ip.current_config_index,
+                                &b0->current_config_index,
                                 &next0,
                                 /* # bytes of config data */ 0);
 
+          vnet_buffer(b0)->l2_classify.opaque_index = ~0;
+
           if (PREDICT_TRUE(table_index0 != ~0))
             {
               hash0 = vnet_buffer(b0)->l2_classify.hash;
               t0 = pool_elt_at_index (vcm->tables, table_index0);
 
+              if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+                h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+              else
+                h0 = b0->data;
+
               e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0,
                                              now);
               if (e0)
                 {
+                  vnet_buffer(b0)->l2_classify.opaque_index
+                    = e0->opaque_index;
                   vlib_buffer_advance (b0, e0->advance);
 
-                  next0 = (e0->next_index < ACL_NEXT_INDEX_N_NEXT)?
+                  next0 = (e0->next_index < n_next_nodes)?
                            e0->next_index:next0;
 
                   hits++;
@@ -257,6 +280,10 @@ ip_inacl_inline (vlib_main_t * vm,
                     error0 = (next0 == ACL_NEXT_INDEX_DENY)?
                       IP6_ERROR_INACL_SESSION_DENY:IP6_ERROR_NONE;
                   b0->error = error_node->errors[error0];
+
+                  if (e0->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX ||
+                      e0->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
+                    vnet_buffer (b0)->sw_if_index[VLIB_TX] = e0->metadata;
                 }
               else
                 {
@@ -267,7 +294,7 @@ ip_inacl_inline (vlib_main_t * vm,
                                                 t0->next_table_index);
                       else
                         {
-                          next0 = (t0->miss_next_index < ACL_NEXT_INDEX_N_NEXT)?
+                          next0 = (t0->miss_next_index < n_next_nodes)?
                                    t0->miss_next_index:next0;
 
                           misses++;
@@ -282,13 +309,20 @@ ip_inacl_inline (vlib_main_t * vm,
                           break;
                         }
 
+                      if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+                        h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+                      else
+                        h0 = b0->data;
+
                       hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
                       e0 = vnet_classify_find_entry
                         (t0, (u8 *) h0, hash0, now);
                       if (e0)
                         {
+                          vnet_buffer(b0)->l2_classify.opaque_index
+                            = e0->opaque_index;
                           vlib_buffer_advance (b0, e0->advance);
-                          next0 = (e0->next_index < ACL_NEXT_INDEX_N_NEXT)?
+                          next0 = (e0->next_index < n_next_nodes)?
                                    e0->next_index:next0;
                           hits++;
                           chain_hits++;
@@ -300,6 +334,10 @@ ip_inacl_inline (vlib_main_t * vm,
                             error0 = (next0 == ACL_NEXT_INDEX_DENY)?
                               IP6_ERROR_INACL_SESSION_DENY:IP6_ERROR_NONE;
                           b0->error = error_node->errors[error0];
+
+                          if (e0->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX ||
+                              e0->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
+                            vnet_buffer (b0)->sw_if_index[VLIB_TX] = e0->metadata;
                           break;
                         }
                     }
@@ -314,7 +352,7 @@ ip_inacl_inline (vlib_main_t * vm,
               t->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
               t->next_index = next0;
               t->table_index = t0 ? t0 - vcm->tables : ~0;
-              t->offset = e0 ? vnet_classify_get_offset (t0, e0): ~0;
+              t->offset = (e0 && t0) ? vnet_classify_get_offset (t0, e0): ~0;
             }
 
           /* verify speculative enqueue, maybe switch current next frame */
@@ -361,6 +399,8 @@ VLIB_REGISTER_NODE (ip4_inacl_node) = {
   },
 };
 
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_inacl_node, ip4_inacl)
+
 static uword
 ip6_inacl (vlib_main_t * vm,
               vlib_node_runtime_t * node,
@@ -384,6 +424,8 @@ VLIB_REGISTER_NODE (ip6_inacl_node) = {
   },
 };
 
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_inacl_node, ip6_inacl)
+
 static clib_error_t *
 ip_inacl_init (vlib_main_t * vm)
 {