summaryrefslogtreecommitdiffstats
path: root/vnet/vnet/ip/ip_frag.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnet/vnet/ip/ip_frag.c')
-rw-r--r--vnet/vnet/ip/ip_frag.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/vnet/vnet/ip/ip_frag.c b/vnet/vnet/ip/ip_frag.c
index 22176187a9c..3436090a426 100644
--- a/vnet/vnet/ip/ip_frag.c
+++ b/vnet/vnet/ip/ip_frag.c
@@ -37,9 +37,8 @@ static u8 * format_ip_frag_trace (u8 * s, va_list * args)
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
ip_frag_trace_t * t = va_arg (*args, ip_frag_trace_t *);
- s = format(s, "IPv%s offset: %u mtu: %u fragments: %u next: %s",
- t->ipv6?"6":"4",
- t->header_offset, t->mtu, t->n_fragments, node->next_node_names[t->next]);
+ s = format(s, "IPv%s offset: %u mtu: %u fragments: %u",
+ t->ipv6?"6":"4", t->header_offset, t->mtu, t->n_fragments);
return s;
}
@@ -146,6 +145,14 @@ ip4_frag_do_fragment(vlib_main_t *vm, u32 pi, u32 **buffer, ip_frag_error_t *err
}
}
+void
+ip_frag_set_vnet_buffer (vlib_buffer_t *b, u16 offset, u16 mtu, u8 next_index, u8 flags)
+{
+ vnet_buffer(b)->ip_frag.header_offset = offset;
+ vnet_buffer(b)->ip_frag.mtu = mtu;
+ vnet_buffer(b)->ip_frag.next_index = next_index;
+ vnet_buffer(b)->ip_frag.flags = flags;
+}
static uword
ip4_frag (vlib_main_t *vm,
@@ -189,13 +196,25 @@ ip4_frag (vlib_main_t *vm,
tr->next = vnet_buffer(p0)->ip_frag.next_index;
}
- next0 = (error0 == IP_FRAG_ERROR_NONE) ? vnet_buffer(p0)->ip_frag.next_index : IP4_FRAG_NEXT_DROP;
- frag_sent += vec_len(buffer);
- small_packets += (vec_len(buffer) == 1);
+ if (error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET) {
+ icmp4_error_set_vnet_buffer(p0, ICMP4_destination_unreachable,
+ ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
+ vnet_buffer(p0)->ip_frag.mtu);
+ vlib_buffer_advance(p0, vnet_buffer(p0)->ip_frag.header_offset);
+ next0 = IP4_FRAG_NEXT_ICMP_ERROR;
+ } else
+ next0 = (error0 == IP_FRAG_ERROR_NONE) ? vnet_buffer(p0)->ip_frag.next_index : IP4_FRAG_NEXT_DROP;
+
+ if (error0 == IP_FRAG_ERROR_NONE) {
+ frag_sent += vec_len(buffer);
+ small_packets += (vec_len(buffer) == 1);
+ } else
+ vlib_error_count(vm, ip4_frag_node.index, error0, 1);
//Send fragments that were added in the frame
frag_from = buffer;
frag_left = vec_len(buffer);
+
while (frag_left > 0) {
while (frag_left > 0 && n_left_to_next > 0) {
u32 i;
@@ -218,6 +237,7 @@ ip4_frag (vlib_main_t *vm,
vlib_put_next_frame(vm, node, next_index, n_left_to_next);
}
vec_free(buffer);
+
vlib_node_increment_counter(vm, ip4_frag_node.index, IP_FRAG_ERROR_FRAGMENT_SENT, frag_sent);
vlib_node_increment_counter(vm, ip4_frag_node.index, IP_FRAG_ERROR_SMALL_PACKET, small_packets);
@@ -426,6 +446,7 @@ VLIB_REGISTER_NODE (ip4_frag_node) = {
.next_nodes = {
[IP4_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
[IP4_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
+ [IP4_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error",
[IP4_FRAG_NEXT_DROP] = "error-drop"
},
};