#include <vnet/mfib/mfib_table.h> /* for mFIB table and entry creation */
#include <vnet/ip/ip4_forward.h>
+#include <vnet/interface_output.h>
/** @brief IPv4 lookup node.
@node ip4-lookup
always_inline uword
-ip4_rewrite_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- int do_counters, int is_midchain, int is_mcast)
+ip4_rewrite_inline_with_gso (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame,
+ int do_counters, int is_midchain, int is_mcast,
+ int do_gso)
{
ip_lookup_main_t *lm = &ip4_main.lookup_main;
u32 *from = vlib_frame_vector_args (frame);
CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
/* Check MTU of outgoing interface. */
- ip4_mtu_check (b[0], clib_net_to_host_u16 (ip0->length),
+ u16 ip0_len = clib_net_to_host_u16 (ip0->length);
+ u16 ip1_len = clib_net_to_host_u16 (ip1->length);
+
+ if (do_gso && (b[0]->flags & VNET_BUFFER_F_GSO))
+ ip0_len = gso_mtu_sz (b[0]);
+ if (do_gso && (b[1]->flags & VNET_BUFFER_F_GSO))
+ ip1_len = gso_mtu_sz (b[1]);
+
+ ip4_mtu_check (b[0], ip0_len,
adj0[0].rewrite_header.max_l3_packet_bytes,
ip0->flags_and_fragment_offset &
clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
next + 0, &error0);
- ip4_mtu_check (b[1], clib_net_to_host_u16 (ip1->length),
+ ip4_mtu_check (b[1], ip1_len,
adj1[0].rewrite_header.max_l3_packet_bytes,
ip1->flags_and_fragment_offset &
clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
IP4_ERROR_SAME_INTERFACE : error1);
}
- b[0]->error = error_node->errors[error0];
- b[1]->error = error_node->errors[error1];
/* Don't adjust the buffer for ttl issue; icmp-error node wants
- * to see the IP headerr */
+ * to see the IP header */
if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
{
u32 next_index = adj0[0].rewrite_header.next_index;
tx_sw_if_index0, &next_index, b[0]);
next[0] = next_index;
}
+ else
+ {
+ b[0]->error = error_node->errors[error0];
+ }
if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
{
u32 next_index = adj1[0].rewrite_header.next_index;
tx_sw_if_index1, &next_index, b[1]);
next[1] = next_index;
}
-
+ else
+ {
+ b[1]->error = error_node->errors[error1];
+ }
+ if (is_midchain)
+ {
+ calc_checksums (vm, b[0]);
+ calc_checksums (vm, b[1]);
+ }
/* Guess we are only writing on simple Ethernet header. */
vnet_rewrite_two_headers (adj0[0], adj1[0],
ip0, ip1, sizeof (ethernet_header_t));
if (is_midchain)
{
- adj0->sub_type.midchain.fixup_func
- (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
- adj1->sub_type.midchain.fixup_func
- (vm, adj1, b[1], adj1->sub_type.midchain.fixup_data);
+ if (adj0->sub_type.midchain.fixup_func)
+ adj0->sub_type.midchain.fixup_func
+ (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
+ if (adj1->sub_type.midchain.fixup_func)
+ adj1->sub_type.midchain.fixup_func
+ (vm, adj1, b[1], adj1->sub_type.midchain.fixup_data);
}
if (is_mcast)
vnet_buffer (b[0])->ip.save_rewrite_length = rw_len0;
/* Check MTU of outgoing interface. */
- ip4_mtu_check (b[0], clib_net_to_host_u16 (ip0->length),
+ u16 ip0_len = clib_net_to_host_u16 (ip0->length);
+ if (do_gso && (b[0]->flags & VNET_BUFFER_F_GSO))
+ ip0_len = gso_mtu_sz (b[0]);
+
+ ip4_mtu_check (b[0], ip0_len,
adj0[0].rewrite_header.max_l3_packet_bytes,
ip0->flags_and_fragment_offset &
clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
vnet_buffer (b[0])->sw_if_index[VLIB_RX]) ?
IP4_ERROR_SAME_INTERFACE : error0);
}
- b[0]->error = error_node->errors[error0];
/* Don't adjust the buffer for ttl issue; icmp-error node wants
- * to see the IP headerr */
+ * to see the IP header */
if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
{
u32 next_index = adj0[0].rewrite_header.next_index;
tx_sw_if_index0, &next_index, b[0]);
next[0] = next_index;
}
-
+ else
+ {
+ b[0]->error = error_node->errors[error0];
+ }
+ if (is_midchain)
+ {
+ calc_checksums (vm, b[0]);
+ }
/* Guess we are only writing on simple Ethernet header. */
vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
if (is_midchain)
{
- adj0->sub_type.midchain.fixup_func
- (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
+ if (adj0->sub_type.midchain.fixup_func)
+ adj0->sub_type.midchain.fixup_func
+ (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
}
if (is_mcast)
return frame->n_vectors;
}
+always_inline uword
+ip4_rewrite_inline (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame,
+ int do_counters, int is_midchain, int is_mcast)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ if (PREDICT_FALSE (vnm->interface_main.gso_interface_count > 0))
+ return ip4_rewrite_inline_with_gso (vm, node, frame, do_counters,
+ is_midchain, is_mcast,
+ 1 /* do_gso */ );
+ else
+ return ip4_rewrite_inline_with_gso (vm, node, frame, do_counters,
+ is_midchain, is_mcast,
+ 0 /* no do_gso */ );
+}
+
/** @brief IPv4 rewrite node.
@node ip4-rewrite