static void stop_sending_client_message (vlib_main_t * vm, dhcp6_pd_client_state_t * client_state) { u32 bi0; client_state->keep_sending_client_message = 0; vec_free (client_state->params.prefixes); if (client_state->buffer) { bi0 = vlib_get_buffer_index (vm, client_state->buffer); vlib_buffer_free (vm, &bi0, 1); client_state->buffer = 0; adj_unlock (client_state->adj_index); client_state->adj_index = ~0; } }
static inline u8 check_pd_send_client_message (vlib_main_t * vm, dhcp6_pd_client_state_t * client_state, f64 current_time, f64 * due_time) { vlib_buffer_t *p0; vlib_frame_t *f; u32 *to_next; u32 next_index; vlib_buffer_t *c0; ip6_header_t *ip; udp_header_t *udp; u32 ci0; int bogus_length = 0; dhcp6_pd_send_client_message_params_t *params; f64 now = vlib_time_now (vm); if (!client_state->keep_sending_client_message) return false; params = &client_state->params; if (client_state->due_time > current_time) { *due_time = client_state->due_time; return true; } p0 = client_state->buffer; next_index = ip6_rewrite_mcast_node.index; c0 = vlib_buffer_copy (vm, p0); ci0 = vlib_get_buffer_index (vm, c0); ip = (ip6_header_t *) vlib_buffer_get_current (c0); udp = (udp_header_t *) (ip + 1); u16 *elapsed_field = (u16 *) ((void *) ip + client_state->elapsed_pos); *elapsed_field = clib_host_to_net_u16 ((u16) ((now - client_state->transaction_start) * 100)); udp->checksum = 0; udp->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, 0, ip, &bogus_length); f = vlib_get_frame_to_node (vm, next_index); to_next = vlib_frame_vector_args (f); to_next[0] = ci0; f->n_vectors = 1; vlib_put_frame_to_node (vm, next_index, f); if (params->mrc != 0 && --client_state->n_left == 0) stop_sending_client_message (vm, client_state); else { client_state->sleep_interval = (2 + random_f64_from_to (-0.1, 0.1)) * client_state->sleep_interval; if (client_state->sleep_interval > params->mrt) client_state->sleep_interval = (1 + random_f64_from_to (-0.1, 0.1)) * params->mrt; client_state->due_time = current_time + client_state->sleep_interval; if (params->mrd != 0 && current_time > client_state->start_time + params->mrd) stop_sending_client_message (vm, client_state); else *due_time = client_state->due_time; } return client_state->keep_sending_client_message; }
/** * Enqueue buffer chain tail */ always_inline int session_enqueue_chain_tail (session_t * s, vlib_buffer_t * b, u32 offset, u8 is_in_order) { vlib_buffer_t *chain_b; u32 chain_bi, len, diff; vlib_main_t *vm = vlib_get_main (); u8 *data; u32 written = 0; int rv = 0; if (is_in_order && offset) { diff = offset - b->current_length; if (diff > b->total_length_not_including_first_buffer) return 0; chain_b = b; session_enqueue_discard_chain_bytes (vm, b, &chain_b, diff); chain_bi = vlib_get_buffer_index (vm, chain_b); } else chain_bi = b->next_buffer; do { chain_b = vlib_get_buffer (vm, chain_bi); data = vlib_buffer_get_current (chain_b); len = chain_b->current_length; if (!len) continue; if (is_in_order) { rv = svm_fifo_enqueue (s->rx_fifo, len, data); if (rv == len) { written += rv; } else if (rv < len) { return (rv > 0) ? (written + rv) : written; } else if (rv > len) { written += rv; /* written more than what was left in chain */ if (written > b->total_length_not_including_first_buffer) return written; /* drop the bytes that have already been delivered */ session_enqueue_discard_chain_bytes (vm, b, &chain_b, rv - len); } } else { rv = svm_fifo_enqueue_with_offset (s->rx_fifo, offset, len, data); if (rv) { clib_warning ("failed to enqueue multi-buffer seg"); return -1; } offset += len; } } while ((chain_bi = (chain_b->flags & VLIB_BUFFER_NEXT_PRESENT) ? chain_b->next_buffer : 0)); if (is_in_order) return written; return 0; }