summaryrefslogtreecommitdiffstats
path: root/src/vnet/ip
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip')
-rw-r--r--src/vnet/ip/ip.h4
-rw-r--r--src/vnet/ip/ip4.h42
-rw-r--r--src/vnet/ip/ip4_forward.c173
-rw-r--r--src/vnet/ip/ip4_packet.h26
-rw-r--r--src/vnet/ip/ip6.h44
-rw-r--r--src/vnet/ip/ip6_packet.h26
-rw-r--r--src/vnet/ip/punt.c2
-rw-r--r--src/vnet/ip/tcp_packet.h141
-rw-r--r--src/vnet/ip/udp.h315
-rw-r--r--src/vnet/ip/udp_error.def21
-rw-r--r--src/vnet/ip/udp_format.c91
-rw-r--r--src/vnet/ip/udp_init.c71
-rw-r--r--src/vnet/ip/udp_local.c645
-rw-r--r--src/vnet/ip/udp_packet.h65
-rw-r--r--src/vnet/ip/udp_pg.c237
15 files changed, 220 insertions, 1683 deletions
diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h
index 02a1a9636ee..70b4ccd8dd7 100644
--- a/src/vnet/ip/ip.h
+++ b/src/vnet/ip/ip.h
@@ -50,8 +50,8 @@
#include <vnet/ip/ip_packet.h>
#include <vnet/ip/lookup.h>
-#include <vnet/ip/tcp_packet.h>
-#include <vnet/ip/udp_packet.h>
+#include <vnet/tcp/tcp_packet.h>
+#include <vnet/udp/udp_packet.h>
#include <vnet/ip/icmp46_packet.h>
#include <vnet/ip/ip4.h>
diff --git a/src/vnet/ip/ip4.h b/src/vnet/ip/ip4.h
index b184fbaef42..4e075d0fb5c 100644
--- a/src/vnet/ip/ip4.h
+++ b/src/vnet/ip/ip4.h
@@ -309,8 +309,8 @@ ip4_compute_flow_hash (const ip4_header_t * ip,
b = (flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? t1 : t2;
b ^= (flow_hash_config & IP_FLOW_HASH_PROTO) ? ip->protocol : 0;
- t1 = is_tcp_udp ? tcp->ports.src : 0;
- t2 = is_tcp_udp ? tcp->ports.dst : 0;
+ t1 = is_tcp_udp ? tcp->src : 0;
+ t2 = is_tcp_udp ? tcp->dst : 0;
t1 = (flow_hash_config & IP_FLOW_HASH_SRC_PORT) ? t1 : 0;
t2 = (flow_hash_config & IP_FLOW_HASH_DST_PORT) ? t2 : 0;
@@ -334,6 +334,44 @@ u8 *format_ip4_forward_next_trace (u8 * s, va_list * args);
u32 ip4_tcp_udp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0);
+#define IP_DF 0x4000 /* don't fragment */
+
+/**
+ * Push IPv4 header to buffer
+ *
+ * This does not support fragmentation.
+ *
+ * @param vm - vlib_main
+ * @param b - buffer to write the header to
+ * @param src - source IP
+ * @param dst - destination IP
+ * @param prot - payload proto
+ *
+ * @return - pointer to start of IP header
+ */
+always_inline void *
+vlib_buffer_push_ip4 (vlib_main_t * vm, vlib_buffer_t * b,
+ ip4_address_t * src, ip4_address_t * dst, int proto)
+{
+ ip4_header_t *ih;
+
+ /* make some room */
+ ih = vlib_buffer_push_uninit (b, sizeof (ip4_header_t));
+
+ ih->ip_version_and_header_length = 0x45;
+ ih->tos = 0;
+ ih->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b));
+
+ /* No fragments */
+ ih->flags_and_fragment_offset = clib_host_to_net_u16 (IP_DF);
+ ih->ttl = 255;
+ ih->protocol = proto;
+ ih->src_address.as_u32 = src->as_u32;
+ ih->dst_address.as_u32 = dst->as_u32;
+
+ ih->checksum = ip4_header_checksum (ih);
+ return ih;
+}
#endif /* included_ip_ip4_h */
/*
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 8081b34b3dc..66d91ab697d 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1478,8 +1478,18 @@ ip4_tcp_udp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0)
return p0->flags;
}
-static uword
-ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
+/* *INDENT-OFF* */
+VNET_FEATURE_ARC_INIT (ip4_local) =
+{
+ .arc_name = "ip4-local",
+ .start_nodes = VNET_FEATURES ("ip4-local"),
+};
+/* *INDENT-ON* */
+
+static inline uword
+ip4_local_inline (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame, int head_of_feature_arc)
{
ip4_main_t *im = &ip4_main;
ip_lookup_main_t *lm = &im->lookup_main;
@@ -1487,6 +1497,7 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
u32 *from, *to_next, n_left_from, n_left_to_next;
vlib_node_runtime_t *error_node =
vlib_node_get_runtime (vm, ip4_input_node.index);
+ u8 arc_index = vnet_feat_arc_ip4_local.feature_arc_index;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -1513,7 +1524,7 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
i32 len_diff0, len_diff1;
u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
u8 error1, is_udp1, is_tcp_udp1, good_tcp_udp1, proto1;
- u8 enqueue_code;
+ u32 sw_if_index0, sw_if_index1;
pi0 = to_next[0] = from[0];
pi1 = to_next[1] = from[1];
@@ -1522,6 +1533,8 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
to_next += 2;
n_left_to_next -= 2;
+ next0 = next1 = IP_LOCAL_NEXT_DROP;
+
p0 = vlib_get_buffer (vm, pi0);
p1 = vlib_get_buffer (vm, pi1);
@@ -1531,14 +1544,18 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
vnet_buffer (p1)->ip.start_of_ip_header = p1->current_data;
- fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (p0)->sw_if_index[VLIB_RX]);
+ sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
+ sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
+
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
+ fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
+
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
fib_index0 =
(vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
(u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
- fib_index1 = vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (p1)->sw_if_index[VLIB_RX]);
+ fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
fib_index1 =
(vnet_buffer (p1)->sw_if_index[VLIB_TX] ==
(u32) ~ 0) ? fib_index1 : vnet_buffer (p1)->sw_if_index[VLIB_TX];
@@ -1557,6 +1574,13 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
until support of IP frag reassembly is implemented */
proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
proto1 = ip4_is_fragment (ip1) ? 0xfe : ip1->protocol;
+
+ if (head_of_feature_arc == 0)
+ {
+ error0 = error1 = IP4_ERROR_UNKNOWN_PROTOCOL;
+ goto skip_checks;
+ }
+
is_udp0 = proto0 == IP_PROTOCOL_UDP;
is_udp1 = proto1 == IP_PROTOCOL_UDP;
is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
@@ -1686,6 +1710,7 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
next0 = lm->local_next_by_ip_protocol[proto0];
next1 = lm->local_next_by_ip_protocol[proto1];
+ skip_checks:
next0 =
error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
next1 =
@@ -1694,44 +1719,17 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
p0->error = error0 ? error_node->errors[error0] : 0;
p1->error = error1 ? error_node->errors[error1] : 0;
- enqueue_code = (next0 != next_index) + 2 * (next1 != next_index);
-
- if (PREDICT_FALSE (enqueue_code != 0))
+ if (head_of_feature_arc)
{
- switch (enqueue_code)
- {
- case 1:
- /* A B A */
- to_next[-2] = pi1;
- to_next -= 1;
- n_left_to_next += 1;
- vlib_set_next_frame_buffer (vm, node, next0, pi0);
- break;
-
- case 2:
- /* A A B */
- to_next -= 1;
- n_left_to_next += 1;
- vlib_set_next_frame_buffer (vm, node, next1, pi1);
- break;
-
- case 3:
- /* A B B or A B C */
- to_next -= 2;
- n_left_to_next += 2;
- vlib_set_next_frame_buffer (vm, node, next0, pi0);
- vlib_set_next_frame_buffer (vm, node, next1, pi1);
- if (next0 == next1)
- {
- vlib_put_next_frame (vm, node, next_index,
- n_left_to_next);
- next_index = next1;
- vlib_get_next_frame (vm, node, next_index, to_next,
- n_left_to_next);
- }
- break;
- }
+ if (PREDICT_TRUE (error0 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
+ vnet_feature_arc_start (arc_index, sw_if_index0, &next0, p0);
+ if (PREDICT_TRUE (error1 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
+ vnet_feature_arc_start (arc_index, sw_if_index1, &next1, p1);
}
+
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
+ n_left_to_next, pi0, pi1,
+ next0, next1);
}
while (n_left_from > 0 && n_left_to_next > 0)
@@ -1746,6 +1744,7 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
load_balance_t *lb0;
const dpo_id_t *dpo0;
+ u32 sw_if_index0;
pi0 = to_next[0] = from[0];
from += 1;
@@ -1753,14 +1752,18 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
to_next += 1;
n_left_to_next -= 1;
+ next0 = IP_LOCAL_NEXT_DROP;
+
p0 = vlib_get_buffer (vm, pi0);
ip0 = vlib_buffer_get_current (p0);
vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
- fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (p0)->sw_if_index[VLIB_RX]);
+ sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
+
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
+
fib_index0 =
(vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
(u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
@@ -1775,6 +1778,13 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
/* Treat IP frag packets as "experimental" protocol for now
until support of IP frag reassembly is implemented */
proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
+
+ if (head_of_feature_arc == 0)
+ {
+ error0 = IP4_ERROR_UNKNOWN_PROTOCOL;
+ goto skip_check;
+ }
+
is_udp0 = proto0 == IP_PROTOCOL_UDP;
is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
@@ -1847,6 +1857,8 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
ip0->dst_address.as_u32 != 0xFFFFFFFF)
? IP4_ERROR_SRC_LOOKUP_MISS : error0);
+ skip_check:
+
next0 = lm->local_next_by_ip_protocol[proto0];
next0 =
@@ -1854,18 +1866,15 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
p0->error = error0 ? error_node->errors[error0] : 0;
- if (PREDICT_FALSE (next0 != next_index))
+ if (head_of_feature_arc)
{
- n_left_to_next += 1;
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
-
- next_index = next0;
- vlib_get_next_frame (vm, node, next_index, to_next,
- n_left_to_next);
- to_next[0] = pi0;
- to_next += 1;
- n_left_to_next -= 1;
+ if (PREDICT_TRUE (error0 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
+ vnet_feature_arc_start (arc_index, sw_if_index0, &next0, p0);
}
+
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, pi0, next0);
+
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
@@ -1874,21 +1883,57 @@ ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
return frame->n_vectors;
}
+static uword
+ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ return ip4_local_inline (vm, node, frame, 1 /* head of feature arc */ );
+}
+
+/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip4_local_node) =
{
- .function = ip4_local,.name = "ip4-local",.vector_size =
- sizeof (u32),.format_trace =
- format_ip4_forward_next_trace,.n_next_nodes =
- IP_LOCAL_N_NEXT,.next_nodes =
+ .function = ip4_local,
+ .name = "ip4-local",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ip4_forward_next_trace,
+ .n_next_nodes = IP_LOCAL_N_NEXT,
+ .next_nodes =
{
- [IP_LOCAL_NEXT_DROP] = "error-drop",
- [IP_LOCAL_NEXT_PUNT] = "error-punt",
- [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
- [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",}
-,};
+ [IP_LOCAL_NEXT_DROP] = "error-drop",
+ [IP_LOCAL_NEXT_PUNT] = "error-punt",
+ [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
+ [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",},
+};
+/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_node, ip4_local);
+static uword
+ip4_local_end_of_arc (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ return ip4_local_inline (vm, node, frame, 0 /* head of feature arc */ );
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (ip4_local_end_of_arc_node,static) = {
+ .function = ip4_local_end_of_arc,
+ .name = "ip4-local-end-of-arc",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_ip4_forward_next_trace,
+ .sibling_of = "ip4-local",
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_end_of_arc_node, ip4_local_end_of_arc)
+
+VNET_FEATURE_INIT (ip4_local_end_of_arc, static) = {
+ .arc_name = "ip4-local",
+ .node_name = "ip4-local-end-of-arc",
+ .runs_before = 0, /* not before any other features */
+};
+/* *INDENT-ON* */
+
void
ip4_register_protocol (u32 protocol, u32 node_index)
{
diff --git a/src/vnet/ip/ip4_packet.h b/src/vnet/ip/ip4_packet.h
index 8da788b411f..b2c1fcd49c1 100644
--- a/src/vnet/ip/ip4_packet.h
+++ b/src/vnet/ip/ip4_packet.h
@@ -41,7 +41,7 @@
#define included_ip4_packet_h
#include <vnet/ip/ip_packet.h> /* for ip_csum_t */
-#include <vnet/ip/tcp_packet.h> /* for tcp_header_t */
+#include <vnet/tcp/tcp_packet.h> /* for tcp_header_t */
#include <vppinfra/byte_order.h> /* for clib_net_to_host_u16 */
/* IP4 address which can be accessed either as 4 bytes
@@ -342,10 +342,10 @@ ip4_tcp_reply_x1 (ip4_header_t * ip0, tcp_header_t * tcp0)
ip0->src_address.data_u32 = dst0;
ip0->dst_address.data_u32 = src0;
- src0 = tcp0->ports.src;
- dst0 = tcp0->ports.dst;
- tcp0->ports.src = dst0;
- tcp0->ports.dst = src0;
+ src0 = tcp0->src;
+ dst0 = tcp0->dst;
+ tcp0->src = dst0;
+ tcp0->dst = src0;
}
always_inline void
@@ -363,14 +363,14 @@ ip4_tcp_reply_x2 (ip4_header_t * ip0, ip4_header_t * ip1,
ip0->dst_address.data_u32 = src0;
ip1->dst_address.data_u32 = src1;
- src0 = tcp0->ports.src;
- src1 = tcp1->ports.src;
- dst0 = tcp0->ports.dst;
- dst1 = tcp1->ports.dst;
- tcp0->ports.src = dst0;
- tcp1->ports.src = dst1;
- tcp0->ports.dst = src0;
- tcp1->ports.dst = src1;
+ src0 = tcp0->src;
+ src1 = tcp1->src;
+ dst0 = tcp0->dst;
+ dst1 = tcp1->dst;
+ tcp0->src = dst0;
+ tcp1->src = dst1;
+ tcp0->dst = src0;
+ tcp1->dst = src1;
}
#endif /* included_ip4_packet_h */
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index 5456f0f2ed6..2615fbfab02 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -461,8 +461,8 @@ ip6_compute_flow_hash (const ip6_header_t * ip,
b = (flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? t1 : t2;
b ^= (flow_hash_config & IP_FLOW_HASH_PROTO) ? ip->protocol : 0;
- t1 = is_tcp_udp ? tcp->ports.src : 0;
- t2 = is_tcp_udp ? tcp->ports.dst : 0;
+ t1 = is_tcp_udp ? tcp->src : 0;
+ t2 = is_tcp_udp ? tcp->dst : 0;
t1 = (flow_hash_config & IP_FLOW_HASH_SRC_PORT) ? t1 : 0;
t2 = (flow_hash_config & IP_FLOW_HASH_DST_PORT) ? t2 : 0;
@@ -497,6 +497,46 @@ int ip6_hbh_register_option (u8 option,
int ip6_hbh_unregister_option (u8 option);
void ip6_hbh_set_next_override (uword next);
+/**
+ * Push IPv6 header to buffer
+ *
+ * @param vm - vlib_main
+ * @param b - buffer to write the header to
+ * @param src - source IP
+ * @param dst - destination IP
+ * @param prot - payload proto
+ *
+ * @return - pointer to start of IP header
+ */
+always_inline void *
+vlib_buffer_push_ip6 (vlib_main_t * vm, vlib_buffer_t * b,
+ ip6_address_t * src, ip6_address_t * dst, int proto)
+{
+ ip6_header_t *ip6h;
+ u16 payload_length;
+
+ /* make some room */
+ ip6h = vlib_buffer_push_uninit (b, sizeof (ip6_header_t));
+
+ ip6h->ip_version_traffic_class_and_flow_label =
+ clib_host_to_net_u32 (0x6 << 28);
+
+ /* calculate ip6 payload length */
+ payload_length = vlib_buffer_length_in_chain (vm, b);
+ payload_length -= sizeof (*ip6h);
+
+ ip6h->payload_length = clib_host_to_net_u16 (payload_length);
+
+ ip6h->hop_limit = 0xff;
+ ip6h->protocol = proto;
+ clib_memcpy (ip6h->src_address.as_u8, src->as_u8,
+ sizeof (ip6h->src_address));
+ clib_memcpy (ip6h->dst_address.as_u8, dst->as_u8,
+ sizeof (ip6h->src_address));
+
+ return ip6h;
+}
+
#endif /* included_ip_ip6_h */
/*
diff --git a/src/vnet/ip/ip6_packet.h b/src/vnet/ip/ip6_packet.h
index 1e551c8b67d..4fd14b960e4 100644
--- a/src/vnet/ip/ip6_packet.h
+++ b/src/vnet/ip/ip6_packet.h
@@ -40,7 +40,7 @@
#ifndef included_ip6_packet_h
#define included_ip6_packet_h
-#include <vnet/ip/tcp_packet.h>
+#include <vnet/tcp/tcp_packet.h>
#include <vnet/ip/ip4_packet.h>
typedef union
@@ -373,10 +373,10 @@ ip6_tcp_reply_x1 (ip6_header_t * ip0, tcp_header_t * tcp0)
{
u16 src0, dst0;
- src0 = tcp0->ports.src;
- dst0 = tcp0->ports.dst;
- tcp0->ports.src = dst0;
- tcp0->ports.dst = src0;
+ src0 = tcp0->src;
+ dst0 = tcp0->dst;
+ tcp0->src = dst0;
+ tcp0->dst = src0;
}
}
@@ -400,14 +400,14 @@ ip6_tcp_reply_x2 (ip6_header_t * ip0, ip6_header_t * ip1,
{
u16 src0, dst0, src1, dst1;
- src0 = tcp0->ports.src;
- src1 = tcp1->ports.src;
- dst0 = tcp0->ports.dst;
- dst1 = tcp1->ports.dst;
- tcp0->ports.src = dst0;
- tcp1->ports.src = dst1;
- tcp0->ports.dst = src0;
- tcp1->ports.dst = src1;
+ src0 = tcp0->src;
+ src1 = tcp1->src;
+ dst0 = tcp0->dst;
+ dst1 = tcp1->dst;
+ tcp0->src = dst0;
+ tcp1->src = dst1;
+ tcp0->dst = src0;
+ tcp1->dst = src1;
}
}
diff --git a/src/vnet/ip/punt.c b/src/vnet/ip/punt.c
index 9c735128a3b..48558401292 100644
--- a/src/vnet/ip/punt.c
+++ b/src/vnet/ip/punt.c
@@ -23,7 +23,7 @@
*/
#include <vlib/vlib.h>
#include <vnet/pg/pg.h>
-#include <vnet/ip/udp.h>
+#include <vnet/udp/udp.h>
#include <vnet/ip/punt.h>
#define foreach_punt_next \
diff --git a/src/vnet/ip/tcp_packet.h b/src/vnet/ip/tcp_packet.h
deleted file mode 100644
index 93f73e010aa..00000000000
--- a/src/vnet/ip/tcp_packet.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * ip4/tcp_packet.h: TCP packet format (see RFC 793)
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_tcp_packet_h
-#define included_tcp_packet_h
-
-/* TCP flags bit 0 first. */
-#define foreach_tcp_flag \
- _ (FIN) \
- _ (SYN) \
- _ (RST) \
- _ (PSH) \
- _ (ACK) \
- _ (URG) \
- _ (ECE) \
- _ (CWR)
-
-enum
-{
-#define _(f) TCP_FLAG_BIT_##f,
- foreach_tcp_flag
-#undef _
- TCP_N_FLAG_BITS,
-
-#define _(f) TCP_FLAG_##f = 1 << TCP_FLAG_BIT_##f,
- foreach_tcp_flag
-#undef _
-};
-
-typedef struct
-{
- /* Source and destination port. */
- union
- {
- union
- {
- struct
- {
- u16 src, dst;
- };
- u32 src_and_dst;
- } ports;
- struct
- {
- u16 src_port, dst_port;
- };
- };
-
- /* Sequence and acknowledgment number. */
- u32 seq_number, ack_number;
-
- /* Size of TCP header in 32-bit units plus 4 reserved bits. */
- u8 tcp_header_u32s_and_reserved;
-
- /* see foreach_tcp_flag for enumation of tcp flags. */
- u8 flags;
-
- /* Current window advertised by sender.
- This is the number of bytes sender is willing to receive
- right now. */
- u16 window;
-
- /* Checksum of TCP pseudo header and data. */
- u16 checksum;
-
- u16 urgent_pointer;
-} tcp_header_t;
-
-always_inline int
-tcp_header_bytes (tcp_header_t * t)
-{
- return (t->tcp_header_u32s_and_reserved >> 4) * sizeof (u32);
-}
-
-/* TCP options. */
-typedef enum tcp_option_type
-{
- TCP_OPTION_END = 0,
- TCP_OPTION_NOP = 1,
- TCP_OPTION_MSS = 2,
- TCP_OPTION_WINDOW_SCALE = 3,
- TCP_OPTION_SACK_PERMITTED = 4,
- TCP_OPTION_SACK_BLOCK = 5,
- TCP_OPTION_TIME_STAMP = 8,
-} tcp_option_type_t;
-
-/* All except NOP and END have 1 byte length field. */
-typedef struct
-{
- tcp_option_type_t type:8;
-
- /* Length of this option in bytes. */
- u8 length;
-} tcp_option_with_length_t;
-
-#endif /* included_tcp_packet_h */
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vnet/ip/udp.h b/src/vnet/ip/udp.h
deleted file mode 100644
index bad58b5d440..00000000000
--- a/src/vnet/ip/udp.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * ip/udp.h: udp protocol
- *
- * Copyright (c) 2013 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef included_udp_h
-#define included_udp_h
-
-#include <vnet/vnet.h>
-#include <vnet/ip/udp_packet.h>
-#include <vnet/ip/ip.h>
-#include <vnet/ip/ip4.h>
-#include <vnet/ip/ip4_packet.h>
-#include <vnet/pg/pg.h>
-#include <vnet/ip/format.h>
-
-typedef enum
-{
-#define udp_error(n,s) UDP_ERROR_##n,
-#include <vnet/ip/udp_error.def>
-#undef udp_error
- UDP_N_ERROR,
-} udp_error_t;
-
-#define foreach_udp4_dst_port \
-_ (67, dhcp_to_server) \
-_ (68, dhcp_to_client) \
-_ (500, ikev2) \
-_ (3784, bfd4) \
-_ (3785, bfd_echo4) \
-_ (4341, lisp_gpe) \
-_ (4342, lisp_cp) \
-_ (4739, ipfix) \
-_ (4789, vxlan) \
-_ (4789, vxlan6) \
-_ (4790, vxlan_gpe) \
-_ (6633, vpath_3)
-
-
-#define foreach_udp6_dst_port \
-_ (547, dhcpv6_to_server) \
-_ (546, dhcpv6_to_client) \
-_ (3784, bfd6) \
-_ (3785, bfd_echo6) \
-_ (4341, lisp_gpe6) \
-_ (4342, lisp_cp6) \
-_ (4790, vxlan6_gpe) \
-_ (6633, vpath6_3)
-
-typedef enum
-{
-#define _(n,f) UDP_DST_PORT_##f = n,
- foreach_udp4_dst_port foreach_udp6_dst_port
-#undef _
-} udp_dst_port_t;
-
-typedef enum
-{
-#define _(n,f) UDP6_DST_PORT_##f = n,
- foreach_udp6_dst_port
-#undef _
-} udp6_dst_port_t;
-
-typedef struct
-{
- /* Name (a c string). */
- char *name;
-
- /* GRE protocol type in host byte order. */
- udp_dst_port_t dst_port;
-
- /* Node which handles this type. */
- u32 node_index;
-
- /* Next index for this type. */
- u32 next_index;
-} udp_dst_port_info_t;
-
-typedef enum
-{
- UDP_IP6 = 0,
- UDP_IP4, /* the code is full of is_ip4... */
- N_UDP_AF,
-} udp_af_t;
-
-typedef struct
-{
- udp_dst_port_info_t *dst_port_infos[N_UDP_AF];
-
- /* Hash tables mapping name/protocol to protocol info index. */
- uword *dst_port_info_by_name[N_UDP_AF];
- uword *dst_port_info_by_dst_port[N_UDP_AF];
-
- /* convenience */
- vlib_main_t *vlib_main;
-} udp_main_t;
-
-always_inline udp_dst_port_info_t *
-udp_get_dst_port_info (udp_main_t * um, udp_dst_port_t dst_port, u8 is_ip4)
-{
- uword *p = hash_get (um->dst_port_info_by_dst_port[is_ip4], dst_port);
- return p ? vec_elt_at_index (um->dst_port_infos[is_ip4], p[0]) : 0;
-}
-
-format_function_t format_udp_header;
-format_function_t format_udp_rx_trace;
-
-unformat_function_t unformat_udp_header;
-
-void udp_register_dst_port (vlib_main_t * vm,
- udp_dst_port_t dst_port,
- u32 node_index, u8 is_ip4);
-
-void udp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add);
-
-always_inline void
-ip_udp_fixup_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 is_ip4)
-{
- u16 new_l0;
- udp_header_t *udp0;
-
- if (is_ip4)
- {
- ip4_header_t *ip0;
- ip_csum_t sum0;
- u16 old_l0 = 0;
-
- ip0 = vlib_buffer_get_current (b0);
-
- /* fix the <bleep>ing outer-IP checksum */
- sum0 = ip0->checksum;
- /* old_l0 always 0, see the rewrite setup */
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
-
- sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
- length /* changed member */ );
- ip0->checksum = ip_csum_fold (sum0);
- ip0->length = new_l0;
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
- - sizeof (*ip0));
- udp0->length = new_l0;
- }
- else
- {
- ip6_header_t *ip0;
- int bogus0;
-
- ip0 = vlib_buffer_get_current (b0);
-
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
- - sizeof (*ip0));
- ip0->payload_length = new_l0;
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
- udp0->length = new_l0;
-
- udp0->checksum =
- ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
- ASSERT (bogus0 == 0);
-
- if (udp0->checksum == 0)
- udp0->checksum = 0xffff;
- }
-}
-
-always_inline void
-ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
- u8 is_ip4)
-{
- vlib_buffer_advance (b0, -ec_len);
-
- if (is_ip4)
- {
- ip4_header_t *ip0;
-
- ip0 = vlib_buffer_get_current (b0);
-
- /* Apply the encap string. */
- clib_memcpy (ip0, ec0, ec_len);
- ip_udp_fixup_one (vm, b0, 1);
- }
- else
- {
- ip6_header_t *ip0;
-
- ip0 = vlib_buffer_get_current (b0);
-
- /* Apply the encap string. */
- clib_memcpy (ip0, ec0, ec_len);
- ip_udp_fixup_one (vm, b0, 0);
- }
-}
-
-always_inline void
-ip_udp_encap_two (vlib_main_t * vm, vlib_buffer_t * b0, vlib_buffer_t * b1,
- u8 * ec0, u8 * ec1, word ec_len, u8 is_v4)
-{
- u16 new_l0, new_l1;
- udp_header_t *udp0, *udp1;
-
- ASSERT (_vec_len (ec0) == _vec_len (ec1));
-
- vlib_buffer_advance (b0, -ec_len);
- vlib_buffer_advance (b1, -ec_len);
-
- if (is_v4)
- {
- ip4_header_t *ip0, *ip1;
- ip_csum_t sum0, sum1;
- u16 old_l0 = 0, old_l1 = 0;
-
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
-
- /* Apply the encap string */
- clib_memcpy (ip0, ec0, ec_len);
- clib_memcpy (ip1, ec1, ec_len);
-
- /* fix the <bleep>ing outer-IP checksum */
- sum0 = ip0->checksum;
- sum1 = ip1->checksum;
-
- /* old_l0 always 0, see the rewrite setup */
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
- new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1));
-
- sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
- length /* changed member */ );
- sum1 = ip_csum_update (sum1, old_l1, new_l1, ip4_header_t,
- length /* changed member */ );
-
- ip0->checksum = ip_csum_fold (sum0);
- ip1->checksum = ip_csum_fold (sum1);
-
- ip0->length = new_l0;
- ip1->length = new_l1;
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
- udp1 = (udp_header_t *) (ip1 + 1);
-
- new_l0 =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
- sizeof (*ip0));
- new_l1 =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1) -
- sizeof (*ip1));
- udp0->length = new_l0;
- udp1->length = new_l1;
- }
- else
- {
- ip6_header_t *ip0, *ip1;
- int bogus0, bogus1;
-
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
-
- /* Apply the encap string. */
- clib_memcpy (ip0, ec0, ec_len);
- clib_memcpy (ip1, ec1, ec_len);
-
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
- - sizeof (*ip0));
- new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)
- - sizeof (*ip1));
- ip0->payload_length = new_l0;
- ip1->payload_length = new_l1;
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
- udp1 = (udp_header_t *) (ip1 + 1);
-
- udp0->length = new_l0;
- udp1->length = new_l1;
-
- udp0->checksum =
- ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
- udp1->checksum =
- ip6_tcp_udp_icmp_compute_checksum (vm, b1, ip1, &bogus1);
- ASSERT (bogus0 == 0);
- ASSERT (bogus1 == 0);
-
- if (udp0->checksum == 0)
- udp0->checksum = 0xffff;
- if (udp1->checksum == 0)
- udp1->checksum = 0xffff;
- }
-}
-
-#endif /* included_udp_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vnet/ip/udp_error.def b/src/vnet/ip/udp_error.def
deleted file mode 100644
index bfdae0acc77..00000000000
--- a/src/vnet/ip/udp_error.def
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * udp_error.def: udp errors
- *
- * Copyright (c) 2013-2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-udp_error (NONE, "no error")
-udp_error (NO_LISTENER, "no listener for dst port")
-udp_error (LENGTH_ERROR, "UDP packets with length errors")
-udp_error (PUNT, "no listener punt")
diff --git a/src/vnet/ip/udp_format.c b/src/vnet/ip/udp_format.c
deleted file mode 100644
index abdf561e8c9..00000000000
--- a/src/vnet/ip/udp_format.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * ip/udp_format.c: udp formatting
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vnet/ip/ip.h>
-
-/* Format UDP header. */
-u8 *
-format_udp_header (u8 * s, va_list * args)
-{
- udp_header_t *udp = va_arg (*args, udp_header_t *);
- u32 max_header_bytes = va_arg (*args, u32);
- uword indent;
- u32 header_bytes = sizeof (udp[0]);
-
- /* Nothing to do. */
- if (max_header_bytes < sizeof (udp[0]))
- return format (s, "UDP header truncated");
-
- indent = format_get_indent (s);
- indent += 2;
-
- s = format (s, "UDP: %d -> %d",
- clib_net_to_host_u16 (udp->src_port),
- clib_net_to_host_u16 (udp->dst_port));
-
- s = format (s, "\n%Ulength %d, checksum 0x%04x",
- format_white_space, indent,
- clib_net_to_host_u16 (udp->length),
- clib_net_to_host_u16 (udp->checksum));
-
- /* Recurse into next protocol layer. */
- if (max_header_bytes != 0 && header_bytes < max_header_bytes)
- {
- ip_main_t *im = &ip_main;
- tcp_udp_port_info_t *pi;
-
- pi = ip_get_tcp_udp_port_info (im, udp->dst_port);
-
- if (pi && pi->format_header)
- s = format (s, "\n%U%U",
- format_white_space, indent - 2, pi->format_header,
- /* next protocol header */ (udp + 1),
- max_header_bytes - sizeof (udp[0]));
- }
-
- return s;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vnet/ip/udp_init.c b/src/vnet/ip/udp_init.c
deleted file mode 100644
index 1241ca4ab32..00000000000
--- a/src/vnet/ip/udp_init.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * ip/udp_init.c: udp initialization
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vnet/ip/ip.h>
-
-clib_error_t *
-udp_init (vlib_main_t * vm)
-{
- ip_main_t *im = &ip_main;
- ip_protocol_info_t *pi;
- clib_error_t *error;
-
- error = vlib_call_init_function (vm, ip_main_init);
-
- if (!error)
- {
- pi = ip_get_protocol_info (im, IP_PROTOCOL_UDP);
- if (pi == 0)
- return clib_error_return (0, "UDP protocol info AWOL");
- pi->format_header = format_udp_header;
- pi->unformat_pg_edit = unformat_pg_udp_header;
- }
-
- return 0;
-}
-
-VLIB_INIT_FUNCTION (udp_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vnet/ip/udp_local.c b/src/vnet/ip/udp_local.c
deleted file mode 100644
index 13ab6e4fb32..00000000000
--- a/src/vnet/ip/udp_local.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * node.c: udp packet processing
- *
- * Copyright (c) 2013 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/vlib.h>
-#include <vnet/pg/pg.h>
-#include <vnet/ip/udp.h>
-#include <vnet/ip/udp_packet.h>
-#include <vppinfra/sparse_vec.h>
-
-udp_main_t udp_main;
-
-#define foreach_udp_input_next \
- _ (PUNT, "error-punt") \
- _ (DROP, "error-drop") \
- _ (ICMP4_ERROR, "ip4-icmp-error") \
- _ (ICMP6_ERROR, "ip6-icmp-error")
-
-typedef enum
-{
-#define _(s,n) UDP_INPUT_NEXT_##s,
- foreach_udp_input_next
-#undef _
- UDP_INPUT_N_NEXT,
-} udp_input_next_t;
-
-typedef struct
-{
- u16 src_port;
- u16 dst_port;
- u8 bound;
-} udp_rx_trace_t;
-
-u8 *
-format_udp_rx_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 *);
- udp_rx_trace_t *t = va_arg (*args, udp_rx_trace_t *);
-
- s = format (s, "UDP: src-port %d dst-port %d%s",
- clib_net_to_host_u16 (t->src_port),
- clib_net_to_host_u16 (t->dst_port),
- t->bound ? "" : " (no listener)");
- return s;
-}
-
-typedef struct
-{
- /* Sparse vector mapping udp dst_port in network byte order
- to next index. */
- u16 *next_by_dst_port;
- u8 punt_unknown;
-} udp_input_runtime_t;
-
-vlib_node_registration_t udp4_input_node;
-vlib_node_registration_t udp6_input_node;
-
-always_inline uword
-udp46_input_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame, int is_ip4)
-{
- udp_input_runtime_t *rt = is_ip4 ?
- (void *) vlib_node_get_runtime_data (vm, udp4_input_node.index)
- : (void *) vlib_node_get_runtime_data (vm, udp6_input_node.index);
- __attribute__ ((unused)) u32 n_left_from, next_index, *from, *to_next;
- word n_no_listener = 0;
- u8 punt_unknown = rt->punt_unknown;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
-
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- udp_header_t *h0 = 0, *h1 = 0;
- u32 i0, i1, dst_port0, dst_port1;
- u32 advance0, advance1;
- u32 error0, next0, error1, next1;
-
- /* 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, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, sizeof (h0[0]), LOAD);
- CLIB_PREFETCH (p3->data, sizeof (h1[0]), LOAD);
- }
-
- bi0 = from[0];
- bi1 = from[1];
- to_next[0] = bi0;
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_to_next -= 2;
- n_left_from -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- /* ip4/6_local hands us the ip header, not the udp header */
- if (is_ip4)
- {
- advance0 = sizeof (ip4_header_t);
- advance1 = sizeof (ip4_header_t);
- }
- else
- {
- advance0 = sizeof (ip6_header_t);
- advance1 = sizeof (ip6_header_t);
- }
-
- if (PREDICT_FALSE (b0->current_length < advance0 + sizeof (*h0)))
- {
- error0 = UDP_ERROR_LENGTH_ERROR;
- next0 = UDP_INPUT_NEXT_DROP;
- }
- else
- {
- vlib_buffer_advance (b0, advance0);
- h0 = vlib_buffer_get_current (b0);
- error0 = next0 = 0;
- if (PREDICT_FALSE (clib_net_to_host_u16 (h0->length) >
- vlib_buffer_length_in_chain (vm, b0)))
- {
- error0 = UDP_ERROR_LENGTH_ERROR;
- next0 = UDP_INPUT_NEXT_DROP;
- }
- }
-
- if (PREDICT_FALSE (b1->current_length < advance1 + sizeof (*h1)))
- {
- error1 = UDP_ERROR_LENGTH_ERROR;
- next1 = UDP_INPUT_NEXT_DROP;
- }
- else
- {
- vlib_buffer_advance (b1, advance1);
- h1 = vlib_buffer_get_current (b1);
- error1 = next1 = 0;
- if (PREDICT_FALSE (clib_net_to_host_u16 (h1->length) >
- vlib_buffer_length_in_chain (vm, b1)))
- {
- error1 = UDP_ERROR_LENGTH_ERROR;
- next1 = UDP_INPUT_NEXT_DROP;
- }
- }
-
- /* Index sparse array with network byte order. */
- dst_port0 = (error0 == 0) ? h0->dst_port : 0;
- dst_port1 = (error1 == 0) ? h1->dst_port : 0;
- sparse_vec_index2 (rt->next_by_dst_port, dst_port0, dst_port1,
- &i0, &i1);
- next0 = (error0 == 0) ? vec_elt (rt->next_by_dst_port, i0) : next0;
- next1 = (error1 == 0) ? vec_elt (rt->next_by_dst_port, i1) : next1;
-
- if (PREDICT_FALSE (i0 == SPARSE_VEC_INVALID_INDEX))
- {
- // move the pointer back so icmp-error can find the
- // ip packet header
- vlib_buffer_advance (b0, -(word) advance0);
-
- if (PREDICT_FALSE (punt_unknown))
- {
- b0->error = node->errors[UDP_ERROR_PUNT];
- next0 = UDP_INPUT_NEXT_PUNT;
- }
- else if (is_ip4)
- {
- icmp4_error_set_vnet_buffer (b0,
- ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_port_unreachable,
- 0);
- next0 = UDP_INPUT_NEXT_ICMP4_ERROR;
- n_no_listener++;
- }
- else
- {
- icmp6_error_set_vnet_buffer (b0,
- ICMP6_destination_unreachable,
- ICMP6_destination_unreachable_port_unreachable,
- 0);
- next0 = UDP_INPUT_NEXT_ICMP6_ERROR;
- n_no_listener++;
- }
- }
- else
- {
- b0->error = node->errors[UDP_ERROR_NONE];
- // advance to the payload
- vlib_buffer_advance (b0, sizeof (*h0));
- }
-
- if (PREDICT_FALSE (i1 == SPARSE_VEC_INVALID_INDEX))
- {
- // move the pointer back so icmp-error can find the
- // ip packet header
- vlib_buffer_advance (b1, -(word) advance1);
-
- if (PREDICT_FALSE (punt_unknown))
- {
- b1->error = node->errors[UDP_ERROR_PUNT];
- next1 = UDP_INPUT_NEXT_PUNT;
- }
- else if (is_ip4)
- {
- icmp4_error_set_vnet_buffer (b1,
- ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_port_unreachable,
- 0);
- next1 = UDP_INPUT_NEXT_ICMP4_ERROR;
- n_no_listener++;
- }
- else
- {
- icmp6_error_set_vnet_buffer (b1,
- ICMP6_destination_unreachable,
- ICMP6_destination_unreachable_port_unreachable,
- 0);
- next1 = UDP_INPUT_NEXT_ICMP6_ERROR;
- n_no_listener++;
- }
- }
- else
- {
- b1->error = node->errors[UDP_ERROR_NONE];
- // advance to the payload
- vlib_buffer_advance (b1, sizeof (*h1));
- }
-
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- udp_rx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- if (b0->error != node->errors[UDP_ERROR_LENGTH_ERROR])
- {
- tr->src_port = h0 ? h0->src_port : 0;
- tr->dst_port = h0 ? h0->dst_port : 0;
- tr->bound = (next0 != UDP_INPUT_NEXT_ICMP4_ERROR &&
- next0 != UDP_INPUT_NEXT_ICMP6_ERROR);
- }
- }
- if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- udp_rx_trace_t *tr = vlib_add_trace (vm, node,
- b1, sizeof (*tr));
- if (b1->error != node->errors[UDP_ERROR_LENGTH_ERROR])
- {
- tr->src_port = h1 ? h1->src_port : 0;
- tr->dst_port = h1 ? h1->dst_port : 0;
- tr->bound = (next1 != UDP_INPUT_NEXT_ICMP4_ERROR &&
- next1 != UDP_INPUT_NEXT_ICMP6_ERROR);
- }
- }
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- udp_header_t *h0 = 0;
- u32 i0, next0;
- u32 advance0;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- /* ip4/6_local hands us the ip header, not the udp header */
- if (is_ip4)
- advance0 = sizeof (ip4_header_t);
- else
- advance0 = sizeof (ip6_header_t);
-
- if (PREDICT_FALSE (b0->current_length < advance0 + sizeof (*h0)))
- {
- b0->error = node->errors[UDP_ERROR_LENGTH_ERROR];
- next0 = UDP_INPUT_NEXT_DROP;
- goto trace_x1;
- }
-
- vlib_buffer_advance (b0, advance0);
-
- h0 = vlib_buffer_get_current (b0);
-
- if (PREDICT_TRUE (clib_net_to_host_u16 (h0->length) <=
- vlib_buffer_length_in_chain (vm, b0)))
- {
- i0 = sparse_vec_index (rt->next_by_dst_port, h0->dst_port);
- next0 = vec_elt (rt->next_by_dst_port, i0);
-
- if (PREDICT_FALSE (i0 == SPARSE_VEC_INVALID_INDEX))
- {
- // move the pointer back so icmp-error can find the
- // ip packet header
- vlib_buffer_advance (b0, -(word) advance0);
-
- if (PREDICT_FALSE (punt_unknown))
- {
- b0->error = node->errors[UDP_ERROR_PUNT];
- next0 = UDP_INPUT_NEXT_PUNT;
- }
- else if (is_ip4)
- {
- icmp4_error_set_vnet_buffer (b0,
- ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_port_unreachable,
- 0);
- next0 = UDP_INPUT_NEXT_ICMP4_ERROR;
- n_no_listener++;
- }
- else
- {
- icmp6_error_set_vnet_buffer (b0,
- ICMP6_destination_unreachable,
- ICMP6_destination_unreachable_port_unreachable,
- 0);
- next0 = UDP_INPUT_NEXT_ICMP6_ERROR;
- n_no_listener++;
- }
- }
- else
- {
- b0->error = node->errors[UDP_ERROR_NONE];
- // advance to the payload
- vlib_buffer_advance (b0, sizeof (*h0));
- }
- }
- else
- {
- b0->error = node->errors[UDP_ERROR_LENGTH_ERROR];
- next0 = UDP_INPUT_NEXT_DROP;
- }
-
- trace_x1:
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- udp_rx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- if (b0->error != node->errors[UDP_ERROR_LENGTH_ERROR])
- {
- tr->src_port = h0->src_port;
- tr->dst_port = h0->dst_port;
- tr->bound = (next0 != UDP_INPUT_NEXT_ICMP4_ERROR &&
- next0 != UDP_INPUT_NEXT_ICMP6_ERROR);
- }
- }
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
- vlib_error_count (vm, node->node_index, UDP_ERROR_NO_LISTENER,
- n_no_listener);
- return from_frame->n_vectors;
-}
-
-static char *udp_error_strings[] = {
-#define udp_error(n,s) s,
-#include "udp_error.def"
-#undef udp_error
-};
-
-static uword
-udp4_input (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * from_frame)
-{
- return udp46_input_inline (vm, node, from_frame, 1 /* is_ip4 */ );
-}
-
-static uword
-udp6_input (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * from_frame)
-{
- return udp46_input_inline (vm, node, from_frame, 0 /* is_ip4 */ );
-}
-
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (udp4_input_node) = {
- .function = udp4_input,
- .name = "ip4-udp-lookup",
- /* Takes a vector of packets. */
- .vector_size = sizeof (u32),
-
- .runtime_data_bytes = sizeof (udp_input_runtime_t),
-
- .n_errors = UDP_N_ERROR,
- .error_strings = udp_error_strings,
-
- .n_next_nodes = UDP_INPUT_N_NEXT,
- .next_nodes = {
-#define _(s,n) [UDP_INPUT_NEXT_##s] = n,
- foreach_udp_input_next
-#undef _
- },
-
- .format_buffer = format_udp_header,
- .format_trace = format_udp_rx_trace,
- .unformat_buffer = unformat_udp_header,
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (udp4_input_node, udp4_input);
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (udp6_input_node) = {
- .function = udp6_input,
- .name = "ip6-udp-lookup",
- /* Takes a vector of packets. */
- .vector_size = sizeof (u32),
-
- .runtime_data_bytes = sizeof (udp_input_runtime_t),
-
- .n_errors = UDP_N_ERROR,
- .error_strings = udp_error_strings,
-
- .n_next_nodes = UDP_INPUT_N_NEXT,
- .next_nodes = {
-#define _(s,n) [UDP_INPUT_NEXT_##s] = n,
- foreach_udp_input_next
-#undef _
- },
-
- .format_buffer = format_udp_header,
- .format_trace = format_udp_rx_trace,
- .unformat_buffer = unformat_udp_header,
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (udp6_input_node, udp6_input);
-
-static void
-add_dst_port (udp_main_t * um,
- udp_dst_port_t dst_port, char *dst_port_name, u8 is_ip4)
-{
- udp_dst_port_info_t *pi;
- u32 i;
-
- vec_add2 (um->dst_port_infos[is_ip4], pi, 1);
- i = pi - um->dst_port_infos[is_ip4];
-
- pi->name = dst_port_name;
- pi->dst_port = dst_port;
- pi->next_index = pi->node_index = ~0;
-
- hash_set (um->dst_port_info_by_dst_port[is_ip4], dst_port, i);
-
- if (pi->name)
- hash_set_mem (um->dst_port_info_by_name[is_ip4], pi->name, i);
-}
-
-void
-udp_register_dst_port (vlib_main_t * vm,
- udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
-{
- udp_main_t *um = &udp_main;
- udp_dst_port_info_t *pi;
- udp_input_runtime_t *rt;
- u16 *n;
-
- {
- clib_error_t *error = vlib_call_init_function (vm, udp_local_init);
- if (error)
- clib_error_report (error);
- }
-
- pi = udp_get_dst_port_info (um, dst_port, is_ip4);
- if (!pi)
- {
- add_dst_port (um, dst_port, 0, is_ip4);
- pi = udp_get_dst_port_info (um, dst_port, is_ip4);
- ASSERT (pi);
- }
-
- pi->node_index = node_index;
- pi->next_index = vlib_node_add_next (vm,
- is_ip4 ? udp4_input_node.index
- : udp6_input_node.index, node_index);
-
- /* Setup udp protocol -> next index sparse vector mapping. */
- rt = vlib_node_get_runtime_data
- (vm, is_ip4 ? udp4_input_node.index : udp6_input_node.index);
- n = sparse_vec_validate (rt->next_by_dst_port,
- clib_host_to_net_u16 (dst_port));
- n[0] = pi->next_index;
-}
-
-void
-udp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add)
-{
- udp_input_runtime_t *rt;
-
- {
- clib_error_t *error = vlib_call_init_function (vm, udp_local_init);
- if (error)
- clib_error_report (error);
- }
-
- rt = vlib_node_get_runtime_data
- (vm, is_ip4 ? udp4_input_node.index : udp6_input_node.index);
-
- rt->punt_unknown = is_add;
-}
-
-/* Parse a UDP header. */
-uword
-unformat_udp_header (unformat_input_t * input, va_list * args)
-{
- u8 **result = va_arg (*args, u8 **);
- udp_header_t *udp;
- __attribute__ ((unused)) int old_length;
- u16 src_port, dst_port;
-
- /* Allocate space for IP header. */
- {
- void *p;
-
- old_length = vec_len (*result);
- vec_add2 (*result, p, sizeof (ip4_header_t));
- udp = p;
- }
-
- memset (udp, 0, sizeof (udp[0]));
- if (unformat (input, "src-port %d dst-port %d", &src_port, &dst_port))
- {
- udp->src_port = clib_host_to_net_u16 (src_port);
- udp->dst_port = clib_host_to_net_u16 (dst_port);
- return 1;
- }
- return 0;
-}
-
-static void
-udp_setup_node (vlib_main_t * vm, u32 node_index)
-{
- vlib_node_t *n = vlib_get_node (vm, node_index);
- pg_node_t *pn = pg_get_node (node_index);
-
- n->format_buffer = format_udp_header;
- n->unformat_buffer = unformat_udp_header;
- pn->unformat_edit = unformat_pg_udp_header;
-}
-
-clib_error_t *
-udp_local_init (vlib_main_t * vm)
-{
- udp_input_runtime_t *rt;
- udp_main_t *um = &udp_main;
- int i;
-
- {
- clib_error_t *error;
- error = vlib_call_init_function (vm, udp_init);
- if (error)
- clib_error_report (error);
- }
-
-
- for (i = 0; i < 2; i++)
- {
- um->dst_port_info_by_name[i] = hash_create_string (0, sizeof (uword));
- um->dst_port_info_by_dst_port[i] = hash_create (0, sizeof (uword));
- }
-
- udp_setup_node (vm, udp4_input_node.index);
- udp_setup_node (vm, udp6_input_node.index);
-
- rt = vlib_node_get_runtime_data (vm, udp4_input_node.index);
-
- rt->next_by_dst_port = sparse_vec_new
- ( /* elt bytes */ sizeof (rt->next_by_dst_port[0]),
- /* bits in index */ BITS (((udp_header_t *) 0)->dst_port));
-
- rt->punt_unknown = 0;
-
-#define _(n,s) add_dst_port (um, UDP_DST_PORT_##s, #s, 1 /* is_ip4 */);
- foreach_udp4_dst_port
-#undef _
- rt = vlib_node_get_runtime_data (vm, udp6_input_node.index);
-
- rt->next_by_dst_port = sparse_vec_new
- ( /* elt bytes */ sizeof (rt->next_by_dst_port[0]),
- /* bits in index */ BITS (((udp_header_t *) 0)->dst_port));
-
- rt->punt_unknown = 0;
-
-#define _(n,s) add_dst_port (um, UDP_DST_PORT_##s, #s, 0 /* is_ip4 */);
- foreach_udp6_dst_port
-#undef _
- ip4_register_protocol (IP_PROTOCOL_UDP, udp4_input_node.index);
- /* Note: ip6 differs from ip4, UDP is hotwired to ip6-udp-lookup */
- return 0;
-}
-
-VLIB_INIT_FUNCTION (udp_local_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vnet/ip/udp_packet.h b/src/vnet/ip/udp_packet.h
deleted file mode 100644
index beea3059246..00000000000
--- a/src/vnet/ip/udp_packet.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * ip4/udp_packet.h: UDP packet format
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_udp_packet_h
-#define included_udp_packet_h
-
-typedef struct
-{
- /* Source and destination port. */
- u16 src_port, dst_port;
-
- /* Length of UDP header plus payload. */
- u16 length;
-
- /* Checksum of UDP pseudo-header and data or
- zero if checksum is disabled. */
- u16 checksum;
-} udp_header_t;
-
-#endif /* included_udp_packet_h */
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vnet/ip/udp_pg.c b/src/vnet/ip/udp_pg.c
deleted file mode 100644
index c9d8d38ca4a..00000000000
--- a/src/vnet/ip/udp_pg.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * ip/udp_pg: UDP packet-generator interface
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vnet/pg/pg.h>
-#include <vnet/ip/ip.h> /* for unformat_udp_udp_port */
-
-#define UDP_PG_EDIT_LENGTH (1 << 0)
-#define UDP_PG_EDIT_CHECKSUM (1 << 1)
-
-always_inline void
-udp_pg_edit_function_inline (pg_main_t * pg,
- pg_stream_t * s,
- pg_edit_group_t * g,
- u32 * packets, u32 n_packets, u32 flags)
-{
- vlib_main_t *vm = vlib_get_main ();
- u32 ip_offset, udp_offset;
-
- udp_offset = g->start_byte_offset;
- ip_offset = (g - 1)->start_byte_offset;
-
- while (n_packets >= 1)
- {
- vlib_buffer_t *p0;
- ip4_header_t *ip0;
- udp_header_t *udp0;
- u32 udp_len0;
-
- p0 = vlib_get_buffer (vm, packets[0]);
- n_packets -= 1;
- packets += 1;
-
- ip0 = (void *) (p0->data + ip_offset);
- udp0 = (void *) (p0->data + udp_offset);
- udp_len0 = clib_net_to_host_u16 (ip0->length) - sizeof (ip0[0]);
-
- if (flags & UDP_PG_EDIT_LENGTH)
- udp0->length =
- clib_net_to_host_u16 (vlib_buffer_length_in_chain (vm, p0)
- - ip_offset);
-
- /* Initialize checksum with header. */
- if (flags & UDP_PG_EDIT_CHECKSUM)
- {
- ip_csum_t sum0;
-
- sum0 = clib_mem_unaligned (&ip0->src_address, u64);
-
- sum0 = ip_csum_with_carry
- (sum0, clib_host_to_net_u32 (udp_len0 + (ip0->protocol << 16)));
-
- /* Invalidate possibly old checksum. */
- udp0->checksum = 0;
-
- sum0 =
- ip_incremental_checksum_buffer (vm, p0, udp_offset, udp_len0,
- sum0);
-
- sum0 = ~ip_csum_fold (sum0);
-
- /* Zero checksum means checksumming disabled. */
- sum0 = sum0 != 0 ? sum0 : 0xffff;
-
- udp0->checksum = sum0;
- }
- }
-}
-
-static void
-udp_pg_edit_function (pg_main_t * pg,
- pg_stream_t * s,
- pg_edit_group_t * g, u32 * packets, u32 n_packets)
-{
- switch (g->edit_function_opaque)
- {
- case UDP_PG_EDIT_LENGTH:
- udp_pg_edit_function_inline (pg, s, g, packets, n_packets,
- UDP_PG_EDIT_LENGTH);
- break;
-
- case UDP_PG_EDIT_CHECKSUM:
- udp_pg_edit_function_inline (pg, s, g, packets, n_packets,
- UDP_PG_EDIT_CHECKSUM);
- break;
-
- case UDP_PG_EDIT_CHECKSUM | UDP_PG_EDIT_LENGTH:
- udp_pg_edit_function_inline (pg, s, g, packets, n_packets,
- UDP_PG_EDIT_CHECKSUM | UDP_PG_EDIT_LENGTH);
- break;
-
- default:
- ASSERT (0);
- break;
- }
-}
-
-typedef struct
-{
- pg_edit_t src_port, dst_port;
- pg_edit_t length;
- pg_edit_t checksum;
-} pg_udp_header_t;
-
-static inline void
-pg_udp_header_init (pg_udp_header_t * p)
-{
- /* Initialize fields that are not bit fields in the IP header. */
-#define _(f) pg_edit_init (&p->f, udp_header_t, f);
- _(src_port);
- _(dst_port);
- _(length);
- _(checksum);
-#undef _
-}
-
-uword
-unformat_pg_udp_header (unformat_input_t * input, va_list * args)
-{
- pg_stream_t *s = va_arg (*args, pg_stream_t *);
- pg_udp_header_t *p;
- u32 group_index;
-
- p = pg_create_edit_group (s, sizeof (p[0]), sizeof (udp_header_t),
- &group_index);
- pg_udp_header_init (p);
-
- /* Defaults. */
- p->checksum.type = PG_EDIT_UNSPECIFIED;
- p->length.type = PG_EDIT_UNSPECIFIED;
-
- if (!unformat (input, "UDP: %U -> %U",
- unformat_pg_edit,
- unformat_tcp_udp_port, &p->src_port,
- unformat_pg_edit, unformat_tcp_udp_port, &p->dst_port))
- goto error;
-
- /* Parse options. */
- while (1)
- {
- if (unformat (input, "length %U",
- unformat_pg_edit, unformat_pg_number, &p->length))
- ;
-
- else if (unformat (input, "checksum %U",
- unformat_pg_edit, unformat_pg_number, &p->checksum))
- ;
-
- /* Can't parse input: try next protocol level. */
- else
- break;
- }
-
- {
- ip_main_t *im = &ip_main;
- u16 dst_port;
- tcp_udp_port_info_t *pi;
-
- pi = 0;
- if (p->dst_port.type == PG_EDIT_FIXED)
- {
- dst_port = pg_edit_get_value (&p->dst_port, PG_EDIT_LO);
- pi = ip_get_tcp_udp_port_info (im, dst_port);
- }
-
- if (pi && pi->unformat_pg_edit
- && unformat_user (input, pi->unformat_pg_edit, s))
- ;
-
- else if (!unformat_user (input, unformat_pg_payload, s))
- goto error;
-
- p = pg_get_edit_group (s, group_index);
- if (p->checksum.type == PG_EDIT_UNSPECIFIED
- || p->length.type == PG_EDIT_UNSPECIFIED)
- {
- pg_edit_group_t *g = pg_stream_get_group (s, group_index);
- g->edit_function = udp_pg_edit_function;
- g->edit_function_opaque = 0;
- if (p->checksum.type == PG_EDIT_UNSPECIFIED)
- g->edit_function_opaque |= UDP_PG_EDIT_CHECKSUM;
- if (p->length.type == PG_EDIT_UNSPECIFIED)
- g->edit_function_opaque |= UDP_PG_EDIT_LENGTH;
- }
-
- return 1;
- }
-
-error:
- /* Free up any edits we may have added. */
- pg_free_edit_group (s);
- return 0;
-}
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */