- /*
- * $$$ parse through header(s) to pick the point
- * where we punch in the SR extention header
- */
-
- adj0 = ip_get_adjacency (lm, vnet_buffer(b0)->ip.adj_index[VLIB_TX]);
- adj1 = ip_get_adjacency (lm, vnet_buffer(b1)->ip.adj_index[VLIB_TX]);
- t0 = pool_elt_at_index (sm->tunnels,
- adj0->rewrite_header.sw_if_index);
- t1 = pool_elt_at_index (sm->tunnels,
- adj1->rewrite_header.sw_if_index);
-
- ASSERT (VLIB_BUFFER_PRE_DATA_SIZE
- >= ((word) vec_len (t0->rewrite)) + b0->current_data);
- ASSERT (VLIB_BUFFER_PRE_DATA_SIZE
- >= ((word) vec_len (t1->rewrite)) + b1->current_data);
-
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->tx_fib_index;
- vnet_buffer(b1)->sw_if_index[VLIB_TX] = t1->tx_fib_index;
-
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
-
- /*
- * SR-unaware service chaining case: pkt coming back from
- * service has the original dst address, and will already
- * have an SR header. If so, send it to sr-local
- */
- if (PREDICT_FALSE(ip0->protocol == 43))
- {
- vlib_buffer_advance (b0, sizeof(ip0));
- sr0 = (ip6_sr_header_t *) (ip0+1);
- new_l0 = clib_net_to_host_u16(ip0->payload_length);
- next0 = SR_REWRITE_NEXT_SR_LOCAL;
- }
- else
- {
- copy_dst0 = (u64 *)(((u8 *)ip0) - vec_len (t0->rewrite));
- copy_src0 = (u64 *) ip0;
-
- /*
- * Copy data before the punch-in point left by the
- * required amount. Assume (for the moment) that only
- * the main packet header needs to be copied.
- */
- copy_dst0 [0] = copy_src0 [0];
- copy_dst0 [1] = copy_src0 [1];
- copy_dst0 [2] = copy_src0 [2];
- copy_dst0 [3] = copy_src0 [3];
- copy_dst0 [4] = copy_src0 [4];
- vlib_buffer_advance (b0, - (word) vec_len(t0->rewrite));
- ip0 = vlib_buffer_get_current (b0);
- sr0 = (ip6_sr_header_t *) (ip0+1);
- /* $$$ tune */
- clib_memcpy (sr0, t0->rewrite, vec_len (t0->rewrite));
- /* Fix the next header chain */
- sr0->protocol = ip0->protocol;
- ip0->protocol = 43; /* routing extension header */
- new_l0 = clib_net_to_host_u16(ip0->payload_length) +
- vec_len (t0->rewrite);
- ip0->payload_length = clib_host_to_net_u16(new_l0);
- /* Rewrite the ip6 dst address */
- ip0->dst_address.as_u64[0] = t0->first_hop.as_u64[0];
- ip0->dst_address.as_u64[1] = t0->first_hop.as_u64[1];
-
- sr_fix_hmac (sm, ip0, sr0);
-
- next0 = sr_local_cb ? sr_local_cb (vm, node, b0, ip0, sr0) :
- next0;
-
- /*
- * Ignore "do not rewrite" shtik in this path
- */
- if (PREDICT_FALSE (next0 & 0x80000000))
- {
- next0 ^= 0xFFFFFFFF;
- if (PREDICT_FALSE(next0 == SR_REWRITE_NEXT_ERROR))
- b0->error =
- node->errors[SR_REWRITE_ERROR_APP_CALLBACK];
- }
- }
-
- if (PREDICT_FALSE(ip1->protocol == 43))
- {
- vlib_buffer_advance (b1, sizeof(ip1));
- sr1 = (ip6_sr_header_t *) (ip1+1);
- new_l1 = clib_net_to_host_u16(ip1->payload_length);
- next1 = SR_REWRITE_NEXT_SR_LOCAL;
- }
- else
- {
- copy_dst1 = (u64 *)(((u8 *)ip1) - vec_len (t1->rewrite));
- copy_src1 = (u64 *) ip1;
-
- copy_dst1 [0] = copy_src1 [0];
- copy_dst1 [1] = copy_src1 [1];
- copy_dst1 [2] = copy_src1 [2];
- copy_dst1 [3] = copy_src1 [3];
- copy_dst1 [4] = copy_src1 [4];
- vlib_buffer_advance (b1, - (word) vec_len(t1->rewrite));
- ip1 = vlib_buffer_get_current (b1);
- sr1 = (ip6_sr_header_t *) (ip1+1);
- clib_memcpy (sr1, t1->rewrite, vec_len (t1->rewrite));
- sr1->protocol = ip1->protocol;
- ip1->protocol = 43;
- new_l1 = clib_net_to_host_u16(ip1->payload_length) +
- vec_len (t1->rewrite);
- ip1->payload_length = clib_host_to_net_u16(new_l1);
- ip1->dst_address.as_u64[0] = t1->first_hop.as_u64[0];
- ip1->dst_address.as_u64[1] = t1->first_hop.as_u64[1];
-
- sr_fix_hmac (sm, ip1, sr1);
-
- next1 = sr_local_cb ? sr_local_cb (vm, node, b1, ip1, sr1) :
- next1;
-
- /*
- * Ignore "do not rewrite" shtik in this path
- */
- if (PREDICT_FALSE (next1 & 0x80000000))
- {
- next1 ^= 0xFFFFFFFF;
- if (PREDICT_FALSE(next1 == SR_REWRITE_NEXT_ERROR))
- b1->error =
- node->errors[SR_REWRITE_ERROR_APP_CALLBACK];
- }
- }
-
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- sr_rewrite_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- tr->tunnel_index = t0 - sm->tunnels;
- clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8,
- sizeof (tr->src.as_u8));
- clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8,
- sizeof (tr->dst.as_u8));
- tr->length = new_l0;
- tr->next_index = next0;
- clib_memcpy (tr->sr, sr0, sizeof (tr->sr));
- }
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- sr_rewrite_trace_t *tr = vlib_add_trace (vm, node,
- b1, sizeof (*tr));
- tr->tunnel_index = t1 - sm->tunnels;
- clib_memcpy (tr->src.as_u8, ip1->src_address.as_u8,
- sizeof (tr->src.as_u8));
- clib_memcpy (tr->dst.as_u8, ip1->dst_address.as_u8,
- sizeof (tr->dst.as_u8));
- tr->length = new_l1;
- tr->next_index = next1;
- clib_memcpy (tr->sr, sr1, sizeof (tr->sr));
- }
+ /*
+ * $$$ parse through header(s) to pick the point
+ * where we punch in the SR extention header
+ */
+
+ adj0 =
+ ip_get_adjacency (lm, vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
+ adj1 =
+ ip_get_adjacency (lm, vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
+ t0 =
+ pool_elt_at_index (sm->tunnels, adj0->rewrite_header.sw_if_index);
+ t1 =
+ pool_elt_at_index (sm->tunnels, adj1->rewrite_header.sw_if_index);
+
+ ASSERT (VLIB_BUFFER_PRE_DATA_SIZE
+ >= ((word) vec_len (t0->rewrite)) + b0->current_data);
+ ASSERT (VLIB_BUFFER_PRE_DATA_SIZE
+ >= ((word) vec_len (t1->rewrite)) + b1->current_data);
+
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = t0->tx_fib_index;
+ vnet_buffer (b1)->sw_if_index[VLIB_TX] = t1->tx_fib_index;
+
+ ip0 = vlib_buffer_get_current (b0);
+ ip1 = vlib_buffer_get_current (b1);
+
+ /*
+ * SR-unaware service chaining case: pkt coming back from
+ * service has the original dst address, and will already
+ * have an SR header. If so, send it to sr-local
+ */
+ if (PREDICT_FALSE (ip0->protocol == IPPROTO_IPV6_ROUTE))
+ {
+ vlib_buffer_advance (b0, sizeof (ip0));
+ sr0 = (ip6_sr_header_t *) (ip0 + 1);
+ new_l0 = clib_net_to_host_u16 (ip0->payload_length);
+ next0 = SR_REWRITE_NEXT_SR_LOCAL;
+ }
+ else
+ {
+ /*
+ * Copy data before the punch-in point left by the
+ * required amount. Assume (for the moment) that only
+ * the main packet header needs to be copied.
+ */
+ clib_memcpy (((u8 *) ip0) - vec_len (t0->rewrite),
+ ip0, sizeof (ip6_header_t));
+ vlib_buffer_advance (b0, -(word) vec_len (t0->rewrite));
+ ip0 = vlib_buffer_get_current (b0);
+ sr0 = (ip6_sr_header_t *) (ip0 + 1);
+ /* $$$ tune */
+ clib_memcpy (sr0, t0->rewrite, vec_len (t0->rewrite));
+
+ /* Fix the next header chain */
+ sr0->protocol = ip0->protocol;
+ ip0->protocol = IPPROTO_IPV6_ROUTE; /* routing extension header */
+ new_l0 = clib_net_to_host_u16 (ip0->payload_length) +
+ vec_len (t0->rewrite);
+ ip0->payload_length = clib_host_to_net_u16 (new_l0);
+
+ /* Copy dst address into the DA slot in the segment list */
+ clib_memcpy (sr0->segments, ip0->dst_address.as_u64,
+ sizeof (ip6_address_t));
+ /* Rewrite the ip6 dst address with the first hop */
+ clib_memcpy (ip0->dst_address.as_u64, t0->first_hop.as_u64,
+ sizeof (ip6_address_t));
+
+ sr_fix_hmac (sm, ip0, sr0);
+
+ next0 = sr_local_cb ? sr_local_cb (vm, node, b0, ip0, sr0) :
+ next0;
+
+ /*
+ * Ignore "do not rewrite" shtik in this path
+ */
+ if (PREDICT_FALSE (next0 & 0x80000000))
+ {
+ next0 ^= 0xFFFFFFFF;
+ if (PREDICT_FALSE (next0 == SR_REWRITE_NEXT_ERROR))
+ b0->error = node->errors[SR_REWRITE_ERROR_APP_CALLBACK];
+ }
+ }
+
+ if (PREDICT_FALSE (ip1->protocol == IPPROTO_IPV6_ROUTE))
+ {
+ vlib_buffer_advance (b1, sizeof (ip1));
+ sr1 = (ip6_sr_header_t *) (ip1 + 1);
+ new_l1 = clib_net_to_host_u16 (ip1->payload_length);
+ next1 = SR_REWRITE_NEXT_SR_LOCAL;
+ }
+ else
+ {
+ clib_memcpy (((u8 *) ip0) - vec_len (t0->rewrite),
+ ip0, sizeof (ip6_header_t));
+ vlib_buffer_advance (b1, -(word) vec_len (t1->rewrite));
+ ip1 = vlib_buffer_get_current (b1);
+ sr1 = (ip6_sr_header_t *) (ip1 + 1);
+ clib_memcpy (sr1, t1->rewrite, vec_len (t1->rewrite));
+
+ sr1->protocol = ip1->protocol;
+ ip1->protocol = IPPROTO_IPV6_ROUTE;
+ new_l1 = clib_net_to_host_u16 (ip1->payload_length) +
+ vec_len (t1->rewrite);
+ ip1->payload_length = clib_host_to_net_u16 (new_l1);
+
+ /* Copy dst address into the DA slot in the segment list */
+ clib_memcpy (sr1->segments, ip1->dst_address.as_u64,
+ sizeof (ip6_address_t));
+ /* Rewrite the ip6 dst address with the first hop */
+ clib_memcpy (ip1->dst_address.as_u64, t1->first_hop.as_u64,
+ sizeof (ip6_address_t));
+
+ sr_fix_hmac (sm, ip1, sr1);
+
+ next1 = sr_local_cb ? sr_local_cb (vm, node, b1, ip1, sr1) :
+ next1;
+
+ /*
+ * Ignore "do not rewrite" shtik in this path
+ */
+ if (PREDICT_FALSE (next1 & 0x80000000))
+ {
+ next1 ^= 0xFFFFFFFF;
+ if (PREDICT_FALSE (next1 == SR_REWRITE_NEXT_ERROR))
+ b1->error = node->errors[SR_REWRITE_ERROR_APP_CALLBACK];
+ }
+ }
+
+ if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ sr_rewrite_trace_t *tr = vlib_add_trace (vm, node,
+ b0, sizeof (*tr));
+ tr->tunnel_index = t0 - sm->tunnels;
+ clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8,
+ sizeof (tr->src.as_u8));
+ clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8,
+ sizeof (tr->dst.as_u8));
+ tr->length = new_l0;
+ tr->next_index = next0;
+ clib_memcpy (tr->sr, sr0, sizeof (tr->sr));
+ }
+ if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ sr_rewrite_trace_t *tr = vlib_add_trace (vm, node,
+ b1, sizeof (*tr));
+ tr->tunnel_index = t1 - sm->tunnels;
+ clib_memcpy (tr->src.as_u8, ip1->src_address.as_u8,
+ sizeof (tr->src.as_u8));
+ clib_memcpy (tr->dst.as_u8, ip1->dst_address.as_u8,
+ sizeof (tr->dst.as_u8));
+ tr->length = new_l1;
+ tr->next_index = next1;
+ clib_memcpy (tr->sr, sr1, sizeof (tr->sr));
+ }