summaryrefslogtreecommitdiffstats
path: root/src/plugins/gtpu/gtpu_encap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gtpu/gtpu_encap.c')
-rw-r--r--src/plugins/gtpu/gtpu_encap.c218
1 files changed, 177 insertions, 41 deletions
diff --git a/src/plugins/gtpu/gtpu_encap.c b/src/plugins/gtpu/gtpu_encap.c
index 4b7d98786f4..2c3c46a4be2 100644
--- a/src/plugins/gtpu/gtpu_encap.c
+++ b/src/plugins/gtpu/gtpu_encap.c
@@ -199,7 +199,8 @@ gtpu_encap_inline (vlib_main_t * vm,
copy_dst3 = (u64 *) ip4_3;
copy_src3 = (u64 *) t3->rewrite;
- /* Copy first 32 octets 8-bytes at a time */
+ /* Copy first 32 octets 8-bytes at a time (minimum size)
+ * TODO: check if clib_memcpy_fast is better */
#define _(offs) copy_dst0[offs] = copy_src0[offs];
foreach_fixed_header4_offset;
#undef _
@@ -212,19 +213,83 @@ gtpu_encap_inline (vlib_main_t * vm,
#define _(offs) copy_dst3[offs] = copy_src3[offs];
foreach_fixed_header4_offset;
#undef _
- /* Last 4 octets. Hopefully gcc will be our friend */
- copy_dst_last0 = (u32 *)(&copy_dst0[4]);
- copy_src_last0 = (u32 *)(&copy_src0[4]);
- copy_dst_last0[0] = copy_src_last0[0];
- copy_dst_last1 = (u32 *)(&copy_dst1[4]);
- copy_src_last1 = (u32 *)(&copy_src1[4]);
- copy_dst_last1[0] = copy_src_last1[0];
- copy_dst_last2 = (u32 *)(&copy_dst2[4]);
- copy_src_last2 = (u32 *)(&copy_src2[4]);
- copy_dst_last2[0] = copy_src_last2[0];
- copy_dst_last3 = (u32 *)(&copy_dst3[4]);
- copy_src_last3 = (u32 *)(&copy_src3[4]);
- copy_dst_last3[0] = copy_src_last3[0];
+
+ /* Copy last octets */
+ if (_vec_len (t0->rewrite) == 36)
+ {
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last0 = (u32 *) (&copy_dst0[4]);
+ copy_src_last0 = (u32 *) (&copy_src0[4]);
+ copy_dst_last0[0] = copy_src_last0[0];
+ }
+ else
+ {
+ /* Near last 8 octets. */
+#define _(offs) copy_dst0[offs] = copy_src0[offs];
+ _ (4);
+#undef _
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last0 = (u32 *) (&copy_dst0[5]);
+ copy_src_last0 = (u32 *) (&copy_src0[5]);
+ copy_dst_last0[0] = copy_src_last0[0];
+ }
+
+ if (_vec_len (t1->rewrite) == 36)
+ {
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last1 = (u32 *) (&copy_dst1[4]);
+ copy_src_last1 = (u32 *) (&copy_src1[4]);
+ copy_dst_last1[0] = copy_src_last1[0];
+ }
+ else
+ {
+ /* Near last 8 octets. */
+#define _(offs) copy_dst1[offs] = copy_src1[offs];
+ _ (4);
+#undef _
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last1 = (u32 *) (&copy_dst1[5]);
+ copy_src_last1 = (u32 *) (&copy_src1[5]);
+ copy_dst_last1[0] = copy_src_last1[0];
+ }
+
+ if (_vec_len (t2->rewrite) == 36)
+ {
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last2 = (u32 *) (&copy_dst2[4]);
+ copy_src_last2 = (u32 *) (&copy_src2[4]);
+ copy_dst_last2[0] = copy_src_last2[0];
+ }
+ else
+ {
+ /* Near last 8 octets. */
+#define _(offs) copy_dst2[offs] = copy_src2[offs];
+ _ (4);
+#undef _
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last2 = (u32 *) (&copy_dst2[5]);
+ copy_src_last2 = (u32 *) (&copy_src2[5]);
+ copy_dst_last2[0] = copy_src_last2[0];
+ }
+
+ if (_vec_len (t3->rewrite) == 36)
+ {
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last3 = (u32 *) (&copy_dst3[4]);
+ copy_src_last3 = (u32 *) (&copy_src3[4]);
+ copy_dst_last3[0] = copy_src_last3[0];
+ }
+ else
+ {
+ /* Near last 8 octets. */
+#define _(offs) copy_dst3[offs] = copy_src3[offs];
+ _ (4);
+#undef _
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last3 = (u32 *) (&copy_dst3[5]);
+ copy_src_last3 = (u32 *) (&copy_src3[5]);
+ copy_dst_last3[0] = copy_src_last3[0];
+ }
/* Fix the IP4 checksum and length */
sum0 = ip4_0->checksum;
@@ -318,7 +383,7 @@ gtpu_encap_inline (vlib_main_t * vm,
copy_src2 = (u64 *) t2->rewrite;
copy_dst3 = (u64 *) ip6_3;
copy_src3 = (u64 *) t3->rewrite;
- /* Copy first 56 (ip6) octets 8-bytes at a time */
+ /* Copy first 56 (ip6) octets 8-bytes at a time (minimum size) */
#define _(offs) copy_dst0[offs] = copy_src0[offs];
foreach_fixed_header6_offset;
#undef _
@@ -331,6 +396,40 @@ gtpu_encap_inline (vlib_main_t * vm,
#define _(offs) copy_dst3[offs] = copy_src3[offs];
foreach_fixed_header6_offset;
#undef _
+
+ /* Copy last octets */
+ if (_vec_len (t0->rewrite) == 64)
+ {
+ /* Last 8 octets. */
+#define _(offs) copy_dst0[offs] = copy_src0[offs];
+ _ (7);
+#undef _
+ }
+
+ if (_vec_len (t1->rewrite) == 64)
+ {
+ /* Last 8 octets. */
+#define _(offs) copy_dst1[offs] = copy_src1[offs];
+ _ (7);
+#undef _
+ }
+
+ if (_vec_len (t2->rewrite) == 64)
+ {
+ /* Last 8 octets. */
+#define _(offs) copy_dst2[offs] = copy_src2[offs];
+ _ (7);
+#undef _
+ }
+
+ if (_vec_len (t3->rewrite) == 64)
+ {
+ /* Last 8 octets. */
+#define _(offs) copy_dst3[offs] = copy_src3[offs];
+ _ (7);
+#undef _
+ }
+
/* Fix IP6 payload length */
new_l0 =
clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
@@ -466,15 +565,19 @@ gtpu_encap_inline (vlib_main_t * vm,
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->tunnel_index = t0 - gtm->tunnels;
tr->tteid = t0->tteid;
- }
+ tr->pdu_extension = t0->pdu_extension;
+ tr->qfi = t0->qfi;
+ }
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- gtpu_encap_trace_t *tr =
- vlib_add_trace (vm, node, b1, sizeof (*tr));
- tr->tunnel_index = t1 - gtm->tunnels;
- tr->tteid = t1->tteid;
- }
+ if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ gtpu_encap_trace_t *tr =
+ vlib_add_trace (vm, node, b1, sizeof (*tr));
+ tr->tunnel_index = t1 - gtm->tunnels;
+ tr->tteid = t1->tteid;
+ tr->pdu_extension = t1->pdu_extension;
+ tr->qfi = t1->qfi;
+ }
if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
{
@@ -482,15 +585,19 @@ gtpu_encap_inline (vlib_main_t * vm,
vlib_add_trace (vm, node, b2, sizeof (*tr));
tr->tunnel_index = t2 - gtm->tunnels;
tr->tteid = t2->tteid;
- }
+ tr->pdu_extension = t2->pdu_extension;
+ tr->qfi = t2->qfi;
+ }
- if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
- {
- gtpu_encap_trace_t *tr =
- vlib_add_trace (vm, node, b3, sizeof (*tr));
- tr->tunnel_index = t3 - gtm->tunnels;
- tr->tteid = t3->tteid;
- }
+ if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ gtpu_encap_trace_t *tr =
+ vlib_add_trace (vm, node, b3, sizeof (*tr));
+ tr->tunnel_index = t3 - gtm->tunnels;
+ tr->tteid = t3->tteid;
+ tr->pdu_extension = t3->pdu_extension;
+ tr->qfi = t3->qfi;
+ }
vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
to_next, n_left_to_next,
@@ -532,8 +639,9 @@ gtpu_encap_inline (vlib_main_t * vm,
next0 = t0->next_dpo.dpoi_next_node;
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = t0->next_dpo.dpoi_index;
- /* Apply the rewrite string. $$$$ vnet_rewrite? */
- vlib_buffer_advance (b0, -(word)_vec_len(t0->rewrite));
+ /* Apply the rewrite string. $$$$ vnet_rewrite.
+ * The correct total size is set in ip_udp_gtpu_rewrite() */
+ vlib_buffer_advance (b0, -(word) _vec_len (t0->rewrite));
if (is_ip4)
{
@@ -546,10 +654,26 @@ gtpu_encap_inline (vlib_main_t * vm,
#define _(offs) copy_dst0[offs] = copy_src0[offs];
foreach_fixed_header4_offset;
#undef _
- /* Last 4 octets. Hopefully gcc will be our friend */
- copy_dst_last0 = (u32 *)(&copy_dst0[4]);
- copy_src_last0 = (u32 *)(&copy_src0[4]);
- copy_dst_last0[0] = copy_src_last0[0];
+
+ /* Copy last octets */
+ if (_vec_len (t0->rewrite) == 36)
+ {
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last0 = (u32 *) (&copy_dst0[4]);
+ copy_src_last0 = (u32 *) (&copy_src0[4]);
+ copy_dst_last0[0] = copy_src_last0[0];
+ }
+ else
+ {
+ /* Near last 8 octets. */
+#define _(offs) copy_dst0[offs] = copy_src0[offs];
+ _ (4);
+#undef _
+ /* Last 4 octets. Hopefully gcc will be our friend */
+ copy_dst_last0 = (u32 *) (&copy_dst0[5]);
+ copy_src_last0 = (u32 *) (&copy_src0[5]);
+ copy_dst_last0[0] = copy_src_last0[0];
+ }
/* Fix the IP4 checksum and length */
sum0 = ip4_0->checksum;
@@ -587,6 +711,16 @@ gtpu_encap_inline (vlib_main_t * vm,
#define _(offs) copy_dst0[offs] = copy_src0[offs];
foreach_fixed_header6_offset;
#undef _
+
+ /* Copy last octets */
+ if (_vec_len (t0->rewrite) == 64)
+ {
+ /* Last 8 octets. */
+#define _(offs) copy_dst0[offs] = copy_src0[offs];
+ _ (7);
+#undef _
+ }
+
/* Fix IP6 payload length */
new_l0 =
clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
@@ -600,9 +734,9 @@ gtpu_encap_inline (vlib_main_t * vm,
/* Fix GTPU length */
gtpu0 = (gtpu_header_t *)(udp0+1);
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain(vm, b0)
- - sizeof (*ip4_0) - sizeof(*udp0)
- - GTPU_V1_HDR_LEN);
+ new_l0 = clib_host_to_net_u16 (
+ vlib_buffer_length_in_chain (vm, b0) - sizeof (*ip6_0) -
+ sizeof (*udp0) - GTPU_V1_HDR_LEN);
gtpu0->length = new_l0;
/* IPv6 UDP checksum is mandatory */
@@ -644,7 +778,9 @@ gtpu_encap_inline (vlib_main_t * vm,
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->tunnel_index = t0 - gtm->tunnels;
tr->tteid = t0->tteid;
- }
+ tr->pdu_extension = t0->pdu_extension;
+ tr->qfi = t0->qfi;
+ }
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
to_next, n_left_to_next,
bi0, next0);