aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2018-03-27 14:48:39 +0200
committerNeale Ranns <nranns@cisco.com>2018-04-13 13:27:44 +0000
commit70083ee74c3141bbefb185525315f1b34497dcaa (patch)
tree2b93f23b853239152864ad5ee0db073d37c341ea /src/vnet/ip
parent25b049484fcf9161edb2c19250066b893c38c264 (diff)
MTU: Setting of MTU on software interface (instead of hardware interface)
Change-Id: I98bd454a761a1032738a21edeb0fe847e801f901 Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src/vnet/ip')
-rw-r--r--src/vnet/ip/icmp4.c6
-rw-r--r--src/vnet/ip/icmp6.c7
-rw-r--r--src/vnet/ip/ip4_forward.c98
-rw-r--r--src/vnet/ip/ip6_forward.c104
-rw-r--r--src/vnet/ip/ip6_neighbor.c7
5 files changed, 128 insertions, 94 deletions
diff --git a/src/vnet/ip/icmp4.c b/src/vnet/ip/icmp4.c
index 1fe01e48500..a4808f23271 100644
--- a/src/vnet/ip/icmp4.c
+++ b/src/vnet/ip/icmp4.c
@@ -513,13 +513,15 @@ ip4_icmp_error (vlib_main_t * vm,
b->current_length = 0;
}
}
- p0->current_length =
- p0->current_length > 576 ? 576 : p0->current_length;
/* Add IP header and ICMPv4 header including a 4 byte data field */
vlib_buffer_advance (p0,
-sizeof (ip4_header_t) -
sizeof (icmp46_header_t) - 4);
+
+ p0->current_length =
+ p0->current_length > 576 ? 576 : p0->current_length;
+
out_ip0 = vlib_buffer_get_current (p0);
icmp0 = (icmp46_header_t *) & out_ip0[1];
diff --git a/src/vnet/ip/icmp6.c b/src/vnet/ip/icmp6.c
index fd5d0ecba38..6beec28c2cf 100644
--- a/src/vnet/ip/icmp6.c
+++ b/src/vnet/ip/icmp6.c
@@ -526,13 +526,14 @@ ip6_icmp_error (vlib_main_t * vm,
b->current_length = 0;
}
}
- p0->current_length =
- p0->current_length > 1280 ? 1280 : p0->current_length;
-
/* Add IP header and ICMPv6 header including a 4 byte data field */
vlib_buffer_advance (p0,
-sizeof (ip6_header_t) -
sizeof (icmp46_header_t) - 4);
+
+ p0->current_length =
+ p0->current_length > 1280 ? 1280 : p0->current_length;
+
out_ip0 = vlib_buffer_get_current (p0);
icmp0 = (icmp46_header_t *) & out_ip0[1];
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 7c56a294436..3dce590c807 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1940,6 +1940,29 @@ typedef enum
IP4_REWRITE_NEXT_ICMP_ERROR,
} ip4_rewrite_next_t;
+always_inline void
+ip4_mtu_check (vlib_buffer_t * b, u16 buffer_packet_bytes,
+ u16 adj_packet_bytes, bool df, u32 * next, u32 * error)
+{
+ if (buffer_packet_bytes > adj_packet_bytes)
+ {
+ *error = IP4_ERROR_MTU_EXCEEDED;
+ if (df)
+ {
+ icmp4_error_set_vnet_buffer
+ (b, ICMP4_destination_unreachable,
+ ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
+ adj_packet_bytes);
+ *next = IP4_REWRITE_NEXT_ICMP_ERROR;
+ }
+ else
+ {
+ /* Add support for fragmentation here */
+ *next = IP4_REWRITE_NEXT_DROP;
+ }
+ }
+}
+
always_inline uword
ip4_rewrite_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -2100,26 +2123,20 @@ ip4_rewrite_inline (vlib_main_t * vm,
vnet_buffer (p1)->ip.save_rewrite_length = rw_len1;
/* Check MTU of outgoing interface. */
- if (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].rewrite_header.max_l3_packet_bytes)
- {
- error0 = IP4_ERROR_MTU_EXCEEDED;
- next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
- icmp4_error_set_vnet_buffer
- (p0, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
- 0);
- }
- if (vlib_buffer_length_in_chain (vm, p1) >
- adj1[0].rewrite_header.max_l3_packet_bytes)
- {
- error1 = IP4_ERROR_MTU_EXCEEDED;
- next1 = IP4_REWRITE_NEXT_ICMP_ERROR;
- icmp4_error_set_vnet_buffer
- (p1, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
- 0);
- }
+ ip4_mtu_check (p0, vlib_buffer_length_in_chain (vm, p0),
+ adj0[0].rewrite_header.max_l3_packet_bytes,
+ ip0->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
+ &next0, &error0);
+ ip4_mtu_check (p1, vlib_buffer_length_in_chain (vm, p1),
+ adj1[0].rewrite_header.max_l3_packet_bytes,
+ ip1->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
+ &next1, &error1);
+
+ /* 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_mcast)
{
@@ -2143,10 +2160,17 @@ ip4_rewrite_inline (vlib_main_t * vm,
tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
+ if (is_midchain)
+ {
+ adj0->sub_type.midchain.fixup_func
+ (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
+ }
+
if (PREDICT_FALSE
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
vnet_feature_arc_start (lm->output_feature_arc_index,
tx_sw_if_index0, &next0, p0);
+
}
if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
{
@@ -2157,16 +2181,18 @@ ip4_rewrite_inline (vlib_main_t * vm,
tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
+ if (is_midchain)
+ {
+ adj1->sub_type.midchain.fixup_func
+ (vm, adj1, p1, adj0->sub_type.midchain.fixup_data);
+ }
+
if (PREDICT_FALSE
(adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
vnet_feature_arc_start (lm->output_feature_arc_index,
tx_sw_if_index1, &next1, p1);
}
- /* Guess we are only writing on simple Ethernet header. */
- vnet_rewrite_two_headers (adj0[0], adj1[0],
- ip0, ip1, sizeof (ethernet_header_t));
-
/*
* Bump the per-adjacency counters
*/
@@ -2185,13 +2211,6 @@ ip4_rewrite_inline (vlib_main_t * vm,
vlib_buffer_length_in_chain (vm, p1) + rw_len1);
}
- if (is_midchain)
- {
- adj0->sub_type.midchain.fixup_func
- (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
- adj1->sub_type.midchain.fixup_func
- (vm, adj1, p1, adj0->sub_type.midchain.fixup_data);
- }
if (is_mcast)
{
/*
@@ -2272,6 +2291,7 @@ ip4_rewrite_inline (vlib_main_t * vm,
/* Guess we are only writing on simple Ethernet header. */
vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
+
if (is_mcast)
{
/*
@@ -2291,16 +2311,12 @@ ip4_rewrite_inline (vlib_main_t * vm,
vlib_buffer_length_in_chain (vm, p0) + rw_len0);
/* Check MTU of outgoing interface. */
- if (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].rewrite_header.max_l3_packet_bytes)
- {
- error0 = IP4_ERROR_MTU_EXCEEDED;
- next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
- icmp4_error_set_vnet_buffer
- (p0, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
- 0);
- }
+ ip4_mtu_check (p0, vlib_buffer_length_in_chain (vm, p0),
+ adj0[0].rewrite_header.max_l3_packet_bytes,
+ ip0->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
+ &next0, &error0);
+
if (is_mcast)
{
error0 = ((adj0[0].rewrite_header.sw_if_index ==
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 588cd0675a4..7599733fcb5 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1774,6 +1774,19 @@ typedef enum
IP6_REWRITE_NEXT_ICMP_ERROR,
} ip6_rewrite_next_t;
+always_inline void
+ip6_mtu_check (vlib_buffer_t * b, u16 buffer_packet_bytes,
+ u16 adj_packet_bytes, u32 * next, u32 * error)
+{
+ if (adj_packet_bytes >= 1280 && buffer_packet_bytes > adj_packet_bytes)
+ {
+ *error = IP6_ERROR_MTU_EXCEEDED;
+ icmp6_error_set_vnet_buffer (b, ICMP6_packet_too_big, 0,
+ adj_packet_bytes);
+ *next = IP6_REWRITE_NEXT_ICMP_ERROR;
+ }
+}
+
always_inline uword
ip6_rewrite_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -1898,9 +1911,14 @@ ip6_rewrite_inline (vlib_main_t * vm,
{
p1->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED;
}
+
adj0 = adj_get (adj_index0);
adj1 = adj_get (adj_index1);
+ /* Guess we are only writing on simple Ethernet header. */
+ vnet_rewrite_two_headers (adj0[0], adj1[0],
+ ip0, ip1, sizeof (ethernet_header_t));
+
rw_len0 = adj0[0].rewrite_header.data_bytes;
rw_len1 = adj1[0].rewrite_header.data_bytes;
vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
@@ -1919,16 +1937,12 @@ ip6_rewrite_inline (vlib_main_t * vm,
}
/* Check MTU of outgoing interface. */
- error0 =
- (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].
- rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED :
- error0);
- error1 =
- (vlib_buffer_length_in_chain (vm, p1) >
- adj1[0].
- rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED :
- error1);
+ ip6_mtu_check (p0, vlib_buffer_length_in_chain (vm, p0),
+ adj0[0].rewrite_header.max_l3_packet_bytes, &next0,
+ &error0);
+ ip6_mtu_check (p1, vlib_buffer_length_in_chain (vm, p1),
+ adj1[0].rewrite_header.max_l3_packet_bytes, &next1,
+ &error1);
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP headerr */
@@ -1945,6 +1959,19 @@ ip6_rewrite_inline (vlib_main_t * vm,
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
vnet_feature_arc_start (lm->output_feature_arc_index,
tx_sw_if_index0, &next0, p0);
+
+ if (is_midchain)
+ {
+ adj0->sub_type.midchain.fixup_func
+ (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
+ }
+ if (is_mcast)
+ {
+ /*
+ * copy bytes from the IP address into the MAC rewrite
+ */
+ vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+ }
}
if (PREDICT_TRUE (error1 == IP6_ERROR_NONE))
{
@@ -1959,26 +1986,19 @@ ip6_rewrite_inline (vlib_main_t * vm,
(adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
vnet_feature_arc_start (lm->output_feature_arc_index,
tx_sw_if_index1, &next1, p1);
- }
- /* 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, p0, adj0->sub_type.midchain.fixup_data);
- adj1->sub_type.midchain.fixup_func
- (vm, adj1, p1, adj1->sub_type.midchain.fixup_data);
- }
- if (is_mcast)
- {
- /*
- * copy bytes from the IP address into the MAC rewrite
- */
- vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
- vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1);
+ if (is_midchain)
+ {
+ adj1->sub_type.midchain.fixup_func
+ (vm, adj1, p1, adj1->sub_type.midchain.fixup_data);
+ }
+ if (is_mcast)
+ {
+ /*
+ * copy bytes from the IP address into the MAC rewrite
+ */
+ vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1);
+ }
}
vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -2054,11 +2074,9 @@ ip6_rewrite_inline (vlib_main_t * vm,
}
/* Check MTU of outgoing interface. */
- error0 =
- (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].
- rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED :
- error0);
+ ip6_mtu_check (p0, vlib_buffer_length_in_chain (vm, p0),
+ adj0[0].rewrite_header.max_l3_packet_bytes, &next0,
+ &error0);
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP headerr */
@@ -2076,16 +2094,16 @@ ip6_rewrite_inline (vlib_main_t * vm,
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
vnet_feature_arc_start (lm->output_feature_arc_index,
tx_sw_if_index0, &next0, p0);
- }
- if (is_midchain)
- {
- adj0->sub_type.midchain.fixup_func
- (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
- }
- if (is_mcast)
- {
- vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+ if (is_midchain)
+ {
+ adj0->sub_type.midchain.fixup_func
+ (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
+ }
+ if (is_mcast)
+ {
+ vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+ }
}
p0->error = error_node->errors[error0];
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index fee4356f5e0..a1439faa154 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -2575,10 +2575,6 @@ ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm,
{
if (is_add)
{
- vnet_hw_interface_t *hw_if0;
-
- hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index);
-
pool_get (nm->if_radv_pool, a);
ri = a - nm->if_radv_pool;
@@ -2612,7 +2608,8 @@ ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm,
a->send_radv = 1;
/* fill in radv_info for this interface that will be needed later */
- a->adv_link_mtu = hw_if0->max_l3_packet_bytes[VLIB_RX];
+ a->adv_link_mtu =
+ vnet_sw_interface_get_mtu (vnm, sw_if_index, VLIB_TX);
clib_memcpy (a->link_layer_address, eth_if0->address, 6);