X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdhcp%2Fclient.c;h=5986438b85f6ce2a80e889b0168da0784c70de25;hb=b8d4481a93f919291d4b682ef0ac8948a9f1be32;hp=c352e3109eec3f0eaf31e47b082086d2a78a655c;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c index c352e3109ee..5986438b85f 100644 --- a/src/vnet/dhcp/client.c +++ b/src/vnet/dhcp/client.c @@ -13,7 +13,8 @@ * limitations under the License. */ #include -#include +#include +#include #include dhcp_client_main_t dhcp_client_main; @@ -21,6 +22,70 @@ static u8 * format_dhcp_client_state (u8 * s, va_list * va); static vlib_node_registration_t dhcp_client_process_node; static void +dhcp_client_add_rx_address (dhcp_client_main_t * dcm, dhcp_client_t * c) +{ + /* Install a local entry for the offered address */ + fib_prefix_t rx = + { + .fp_len = 32, + .fp_addr.ip4 = c->leased_address, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + fib_table_entry_special_add(fib_table_get_index_for_sw_if_index( + FIB_PROTOCOL_IP4, + c->sw_if_index), + &rx, + FIB_SOURCE_DHCP, + (FIB_ENTRY_FLAG_LOCAL)); + + /* And add the server's address as uRPF exempt so we can accept + * local packets from it */ + fib_prefix_t server = + { + .fp_len = 32, + .fp_addr.ip4 = c->dhcp_server, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + fib_table_entry_special_add(fib_table_get_index_for_sw_if_index( + FIB_PROTOCOL_IP4, + c->sw_if_index), + &server, + FIB_SOURCE_URPF_EXEMPT, + (FIB_ENTRY_FLAG_DROP)); +} + +static void +dhcp_client_remove_rx_address (dhcp_client_main_t * dcm, dhcp_client_t * c) +{ + fib_prefix_t rx = + { + .fp_len = 32, + .fp_addr.ip4 = c->leased_address, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + fib_table_entry_special_remove(fib_table_get_index_for_sw_if_index( + FIB_PROTOCOL_IP4, + c->sw_if_index), + &rx, + FIB_SOURCE_DHCP); + fib_prefix_t server = + { + .fp_len = 32, + .fp_addr.ip4 = c->dhcp_server, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + fib_table_entry_special_remove(fib_table_get_index_for_sw_if_index( + FIB_PROTOCOL_IP4, + c->sw_if_index), + &server, + FIB_SOURCE_URPF_EXEMPT); +} + +static void dhcp_client_acquire_address (dhcp_client_main_t * dcm, dhcp_client_t * c) { /* @@ -55,6 +120,17 @@ set_l2_rewrite (dhcp_client_main_t * dcm, dhcp_client_t * c) 0 /* broadcast */); } +void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); + +static void +dhcp_client_proc_callback (uword * client_index) +{ + vlib_main_t *vm = vlib_get_main (); + ASSERT (vlib_get_thread_index () == 0); + vlib_process_signal_event (vm, dhcp_client_process_node.index, + EVENT_DHCP_CLIENT_WAKEUP, *client_index); +} + /* * dhcp_client_for_us - server-to-client callback. * Called from proxy_node.c:dhcp_proxy_to_client_input(). @@ -94,7 +170,9 @@ int dhcp_client_for_us (u32 bi, vlib_buffer_t * b, /* parse through the packet, learn what we can */ if (dhcp->your_ip_address.as_u32) c->leased_address.as_u32 = dhcp->your_ip_address.as_u32; - + + c->dhcp_server.as_u32 = dhcp->server_ip_address.as_u32; + o = (dhcp_option_t *) dhcp->options; while (o->option != 0xFF /* end of options */ && @@ -171,13 +249,22 @@ int dhcp_client_for_us (u32 bi, vlib_buffer_t * b, c->next_transmit = now + 5.0; break; } + /* + * in order to accept unicasted ACKs we need to configure the offered + * address on the interface. However, at this point we may not know the + * subnet-mask (an OFFER may not contain it). So add a temporary receice + * and uRPF excempt entry + */ + dhcp_client_add_rx_address (dcm, c); + /* Received an offer, go send a request */ c->state = DHCP_REQUEST; c->retry_count = 0; c->next_transmit = 0; /* send right now... */ /* Poke the client process, which will send the request */ - vlib_process_signal_event (vm, dhcp_client_process_node.index, - EVENT_DHCP_CLIENT_WAKEUP, c - dcm->clients); + uword client_id = c - dcm->clients; + vl_api_rpc_call_main_thread (dhcp_client_proc_callback, + (u8 *) &client_id, sizeof (uword)); break; case DHCP_BOUND: @@ -193,8 +280,10 @@ int dhcp_client_for_us (u32 bi, vlib_buffer_t * b, /* OK, we own the address (etc), add to the routing table(s) */ if (c->state == DHCP_REQUEST) { - void (*fp)(u32, u32, u8 *, u8, u8 *, u8 *, u8 *) = c->event_callback; + void (*fp)(u32, u32, u8 *, u8, u8, u8 *, u8 *, u8 *) = c->event_callback; + /* replace the temporary RX address with the correct subnet */ + dhcp_client_remove_rx_address (dcm, c); dhcp_client_acquire_address (dcm, c); /* @@ -219,7 +308,7 @@ int dhcp_client_for_us (u32 bi, vlib_buffer_t * b, &all_0s, FIB_SOURCE_DHCP, FIB_ENTRY_FLAG_NONE, - FIB_PROTOCOL_IP4, + DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, @@ -235,6 +324,7 @@ int dhcp_client_for_us (u32 bi, vlib_buffer_t * b, (*fp) (c->client_index, /* clinet index */ c->pid, c->hostname, + c->subnet_mask_width, 0, /* is_ipv6 */ (u8 *)&c->leased_address, /* host IP address */ (u8 *)&c->router_address, /* router IP address */ @@ -365,7 +455,7 @@ send_dhcp_pkt (dhcp_client_main_t * dcm, dhcp_client_t * c, o = (dhcp_option_t * )dhcp->options; /* Send option 53, the DHCP message type */ - o->option = 53; + o->option = DHCP_PACKET_OPTION_MSG_TYPE; o->length = 1; o->data[0] = type; o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); @@ -412,6 +502,16 @@ send_dhcp_pkt (dhcp_client_main_t * dcm, dhcp_client_t * c, o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); } + /* send option 61, client_id */ + if (vec_len (c->client_identifier)) + { + o->option = 61; + o->length = vec_len (c->client_identifier); + clib_memcpy (o->data, c->client_identifier, + vec_len (c->client_identifier)); + o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); + } + /* $$ maybe send the client s/w version if anyone cares */ /* @@ -517,7 +617,7 @@ dhcp_bound_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now) c->sw_if_index), &all_0s, FIB_SOURCE_DHCP, - FIB_PROTOCOL_IP4, + DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, @@ -780,8 +880,7 @@ int dhcp_client_add_del (dhcp_client_add_del_args_t * a) c->sw_if_index), &all_1s, FIB_SOURCE_DHCP, - FIB_ENTRY_FLAG_LOCAL, - ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_LOCAL); /* * enable the interface to RX IPv4 packets @@ -813,13 +912,15 @@ int dhcp_client_add_del (dhcp_client_add_del_args_t * a) c->sw_if_index), &all_0s, FIB_SOURCE_DHCP, - FIB_PROTOCOL_IP4, + DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, 1, FIB_ROUTE_PATH_FLAG_NONE); } + dhcp_client_remove_rx_address (dcm, c); + dhcp_client_release_address (dcm, c); ip4_sw_interface_enable_disable (c->sw_if_index, 0); vec_free (c->option_55_data); @@ -836,6 +937,7 @@ int dhcp_client_config (vlib_main_t * vm, u32 sw_if_index, u8 * hostname, + u8 * client_id, u32 is_add, u32 client_index, void * event_callback, @@ -852,7 +954,9 @@ dhcp_client_config (vlib_main_t * vm, a->event_callback = event_callback; vec_validate(a->hostname, strlen((char *)hostname) - 1); strncpy((char *)a->hostname, (char *)hostname, vec_len(a->hostname)); - a->client_identifier = format (0, "vpe 1.0%c", 0); + vec_validate(a->client_identifier, strlen((char *)client_id) - 1); + strncpy((char *)a->client_identifier, (char *)client_id, vec_len(a->client_identifier)); + /* * Option 55 request list. These data precisely match * the Ubuntu dhcp client. YMMV.