- while (n_left_from > 0)
- {
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- ip_adjacency_t *adj0, *adj1;
- vlib_buffer_t *p0, *p1;
- ip4_header_t *ip0, *ip1;
- u32 pi0, rw_len0, next0, error0, checksum0, adj_index0;
- u32 pi1, rw_len1, next1, error1, checksum1, adj_index1;
- u32 tx_sw_if_index0, tx_sw_if_index1;
-
- /* 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, STORE);
- vlib_prefetch_buffer_header (p3, STORE);
-
- CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
- CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
- }
-
- pi0 = to_next[0] = from[0];
- pi1 = to_next[1] = from[1];
-
- from += 2;
- n_left_from -= 2;
- to_next += 2;
- n_left_to_next -= 2;
-
- p0 = vlib_get_buffer (vm, pi0);
- p1 = vlib_get_buffer (vm, pi1);
-
- adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
- adj_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
-
- /*
- * pre-fetch the per-adjacency counters
- */
- if (do_counters)
- {
- vlib_prefetch_combined_counter (&adjacency_counters,
- thread_index, adj_index0);
- vlib_prefetch_combined_counter (&adjacency_counters,
- thread_index, adj_index1);
- }
-
- ip0 = vlib_buffer_get_current (p0);
- ip1 = vlib_buffer_get_current (p1);
-
- error0 = error1 = IP4_ERROR_NONE;
- next0 = next1 = IP4_REWRITE_NEXT_DROP;
-
- /* Decrement TTL & update checksum.
- Works either endian, so no need for byte swap. */
- if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)))
- {
- i32 ttl0 = ip0->ttl;
-
- /* Input node should have reject packets with ttl 0. */
- ASSERT (ip0->ttl > 0);
-
- checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
- checksum0 += checksum0 >= 0xffff;
-
- ip0->checksum = checksum0;
- ttl0 -= 1;
- ip0->ttl = ttl0;
-
- /*
- * If the ttl drops below 1 when forwarding, generate
- * an ICMP response.
- */
- if (PREDICT_FALSE (ttl0 <= 0))
- {
- error0 = IP4_ERROR_TIME_EXPIRED;
- vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
- }