ip: retain local interface address adjacency
[vpp.git] / src / vnet / ip / ip4_forward.c
index f3819e3..a05428c 100644 (file)
 VLIB_NODE_FN (ip4_lookup_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
                                vlib_frame_t * frame)
 {
-  return ip4_lookup_inline (vm, node, frame,
-                           /* lookup_for_responses_to_locally_received_packets */
-                           0);
-
+  return ip4_lookup_inline (vm, node, frame);
 }
 
 static u8 *format_ip4_lookup_trace (u8 * s, va_list * args);
@@ -515,6 +512,12 @@ ip4_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
 
   vnet_feature_enable_disable ("ip4-multicast", "ip4-not-enabled",
                               sw_if_index, !is_enable, 0, 0);
+
+  {
+    ip4_enable_disable_interface_callback_t *cb;
+    vec_foreach (cb, im->enable_disable_interface_callbacks)
+      cb->function (im, cb->function_opaque, sw_if_index, is_enable);
+  }
 }
 
 static clib_error_t *
@@ -1317,6 +1320,12 @@ ip4_local_check_src (vlib_buffer_t * b, ip4_header_t * ip0,
     vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0 ?
     vnet_buffer (b)->sw_if_index[VLIB_TX] : vnet_buffer (b)->ip.fib_index;
 
+  /*
+   * vnet_buffer()->ip.adj_index[VLIB_RX] will be set to the index of the
+   *  adjacency for the destination address (the local interface address).
+   * vnet_buffer()->ip.adj_index[VLIB_TX] will be set to the index of the
+   *  adjacency for the source address (the remote sender's address)
+   */
   if (PREDICT_FALSE (last_check->first ||
                     (last_check->src.as_u32 != ip0->src_address.as_u32)))
     {
@@ -1326,8 +1335,9 @@ ip4_local_check_src (vlib_buffer_t * b, ip4_header_t * ip0,
       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
       lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
 
+      vnet_buffer (b)->ip.adj_index[VLIB_RX] =
+       vnet_buffer (b)->ip.adj_index[VLIB_TX];
       vnet_buffer (b)->ip.adj_index[VLIB_TX] = lbi0;
-      vnet_buffer (b)->ip.adj_index[VLIB_RX] = lbi0;
 
       lb0 = load_balance_get (lbi0);
       dpo0 = load_balance_get_bucket_i (lb0, 0);
@@ -1357,8 +1367,9 @@ ip4_local_check_src (vlib_buffer_t * b, ip4_header_t * ip0,
     }
   else
     {
+      vnet_buffer (b)->ip.adj_index[VLIB_RX] =
+       vnet_buffer (b)->ip.adj_index[VLIB_TX];
       vnet_buffer (b)->ip.adj_index[VLIB_TX] = last_check->lbi;
-      vnet_buffer (b)->ip.adj_index[VLIB_RX] = last_check->lbi;
       *error0 = last_check->error;
       last_check->first = 0;
     }
@@ -1389,6 +1400,12 @@ ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip,
     vnet_buffer (b[1])->sw_if_index[VLIB_TX] :
     vnet_buffer (b[1])->ip.fib_index;
 
+  /*
+   * vnet_buffer()->ip.adj_index[VLIB_RX] will be set to the index of the
+   *  adjacency for the destination address (the local interface address).
+   * vnet_buffer()->ip.adj_index[VLIB_TX] will be set to the index of the
+   *  adjacency for the source address (the remote sender's address)
+   */
   if (PREDICT_FALSE (not_last_hit))
     {
       mtrie[0] = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie;
@@ -1410,11 +1427,13 @@ ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip,
       lbi[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf[0]);
       lbi[1] = ip4_fib_mtrie_leaf_get_adj_index (leaf[1]);
 
+      vnet_buffer (b[0])->ip.adj_index[VLIB_RX] =
+       vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
       vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = lbi[0];
-      vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = lbi[0];
 
+      vnet_buffer (b[1])->ip.adj_index[VLIB_RX] =
+       vnet_buffer (b[1])->ip.adj_index[VLIB_TX];
       vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = lbi[1];
-      vnet_buffer (b[1])->ip.adj_index[VLIB_RX] = lbi[1];
 
       lb[0] = load_balance_get (lbi[0]);
       lb[1] = load_balance_get (lbi[1]);
@@ -1444,11 +1463,13 @@ ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip,
     }
   else
     {
+      vnet_buffer (b[0])->ip.adj_index[VLIB_RX] =
+       vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
       vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = last_check->lbi;
-      vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = last_check->lbi;
 
+      vnet_buffer (b[1])->ip.adj_index[VLIB_RX] =
+       vnet_buffer (b[1])->ip.adj_index[VLIB_TX];
       vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = last_check->lbi;
-      vnet_buffer (b[1])->ip.adj_index[VLIB_RX] = last_check->lbi;
 
       error[0] = last_check->error;
       error[1] = last_check->error;
@@ -1673,6 +1694,16 @@ ip4_register_protocol (u32 protocol, u32 node_index)
   lm->local_next_by_ip_protocol[protocol] =
     vlib_node_add_next (vm, ip4_local_node.index, node_index);
 }
+
+void
+ip4_unregister_protocol (u32 protocol)
+{
+  ip4_main_t *im = &ip4_main;
+  ip_lookup_main_t *lm = &im->lookup_main;
+
+  ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
+  lm->local_next_by_ip_protocol[protocol] = IP_LOCAL_NEXT_PUNT;
+}
 #endif
 
 static clib_error_t *
@@ -1691,8 +1722,8 @@ show_ip_local_command_fn (vlib_main_t * vm,
          u32 node_index = vlib_get_node (vm,
                                          ip4_local_node.index)->
            next_nodes[lm->local_next_by_ip_protocol[i]];
-         vlib_cli_output (vm, "%d: %U", i, format_vlib_node_name, vm,
-                          node_index);
+         vlib_cli_output (vm, "%U: %U", format_ip_protocol, i,
+                          format_vlib_node_name, vm, node_index);
        }
     }
   return 0;
@@ -1820,11 +1851,6 @@ ip4_arp_inline (vlib_main_t * vm,
            vlib_packet_template_get_packet (vm,
                                             &im->ip4_arp_request_packet_template,
                                             &bi0);
-         b0 = vlib_get_buffer (vm, bi0);
-
-         /* copy the persistent fields from the original */
-         clib_memcpy_fast (b0->opaque2, p0->opaque2, sizeof (p0->opaque2));
-
          /* Seems we're out of buffers */
          if (PREDICT_FALSE (!h0))
            {
@@ -1832,6 +1858,11 @@ ip4_arp_inline (vlib_main_t * vm,
              continue;
            }
 
+         b0 = vlib_get_buffer (vm, bi0);
+
+         /* copy the persistent fields from the original */
+         clib_memcpy_fast (b0->opaque2, p0->opaque2, sizeof (p0->opaque2));
+
          /* Add rewrite/encap string for ARP packet. */
          vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t));