diff options
author | Neale Ranns <nranns@cisco.com> | 2019-10-07 00:39:28 -0700 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2019-10-07 19:33:39 +0000 |
commit | 02bfd641b69aab83397e217b9ca4e35a6aab05c8 (patch) | |
tree | 665e232425f90d0662bc3d29729e11bb5e8727fc /src/vnet/dhcp | |
parent | 2c41a61d5fc87737b9b46b88cb9271d0f987721e (diff) |
dhcp: Move to plugin
Type: feature
Change-Id: I3fe27a8ef577741d9a5c4f090ec91cf68fb44fe3
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/dhcp')
24 files changed, 0 insertions, 10734 deletions
diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c deleted file mode 100644 index aaeda96327d..00000000000 --- a/src/vnet/dhcp/client.c +++ /dev/null @@ -1,1255 +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. - */ -#include <vlib/vlib.h> -#include <vlibmemory/api.h> -#include <vnet/dhcp/client.h> -#include <vnet/dhcp/dhcp_proxy.h> -#include <vnet/fib/fib_table.h> -#include <vnet/qos/qos_types.h> - -dhcp_client_main_t dhcp_client_main; -static u8 *format_dhcp_client_state (u8 * s, va_list * va); -static vlib_node_registration_t dhcp_client_process_node; - -#define foreach_dhcp_sent_packet_stat \ -_(DISCOVER, "DHCP discover packets sent") \ -_(OFFER, "DHCP offer packets sent") \ -_(REQUEST, "DHCP request packets sent") \ -_(ACK, "DHCP ack packets sent") - -#define foreach_dhcp_error_counter \ -_(NOT_FOR_US, "DHCP packets for other hosts, dropped") \ -_(NAK, "DHCP nak packets received") \ -_(NON_OFFER_DISCOVER, "DHCP non-offer packets in discover state") \ -_(ODDBALL, "DHCP non-ack, non-offer packets received") \ -_(BOUND, "DHCP bind success") - -typedef enum -{ -#define _(sym,str) DHCP_STAT_##sym, - foreach_dhcp_sent_packet_stat foreach_dhcp_error_counter -#undef _ - DHCP_STAT_UNKNOWN, - DHCP_STAT_N_STAT, -} sample_error_t; - -static char *dhcp_client_process_stat_strings[] = { -#define _(sym,string) string, - foreach_dhcp_sent_packet_stat foreach_dhcp_error_counter -#undef _ - "DHCP unknown packets sent", -}; - -static void -dhcp_client_acquire_address (dhcp_client_main_t * dcm, dhcp_client_t * c) -{ - /* - * Install any/all info gleaned from dhcp, right here - */ - ip4_add_del_interface_address (dcm->vlib_main, c->sw_if_index, - (void *) &c->leased_address, - c->subnet_mask_width, 0 /*is_del */ ); -} - -static void -dhcp_client_release_address (dhcp_client_main_t * dcm, dhcp_client_t * c) -{ - /* - * Remove any/all info gleaned from dhcp, right here. Caller(s) - * have not wiped out the info yet. - */ - - ip4_add_del_interface_address (dcm->vlib_main, c->sw_if_index, - (void *) &c->leased_address, - c->subnet_mask_width, 1 /*is_del */ ); -} - -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); -} - -static void -dhcp_client_addr_callback (dhcp_client_t * c) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - - /* disable the feature */ - vnet_feature_enable_disable ("ip4-unicast", - "ip4-dhcp-client-detect", - c->sw_if_index, 0 /* disable */ , 0, 0); - c->client_detect_feature_enabled = 0; - - /* if renewing the lease, the address and route have already been added */ - if (c->state == DHCP_BOUND) - return; - - /* add the address to the interface */ - dhcp_client_acquire_address (dcm, c); - - /* - * Configure default IP route: - */ - if (c->router_address.as_u32) - { - fib_prefix_t all_0s = { - .fp_len = 0, - .fp_addr.ip4.as_u32 = 0x0, - .fp_proto = FIB_PROTOCOL_IP4, - }; - ip46_address_t nh = { - .ip4 = c->router_address, - }; - - /* *INDENT-OFF* */ - fib_table_entry_path_add ( - fib_table_get_index_for_sw_if_index ( - FIB_PROTOCOL_IP4, - c->sw_if_index), - &all_0s, - FIB_SOURCE_DHCP, - FIB_ENTRY_FLAG_NONE, - DPO_PROTO_IP4, - &nh, c->sw_if_index, - ~0, 1, NULL, // no label stack - FIB_ROUTE_PATH_FLAG_NONE); - /* *INDENT-ON* */ - } - if (c->dhcp_server.as_u32) - { - ip46_address_t dst = { - .ip4 = c->dhcp_server, - }; - c->ai_ucast = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, - VNET_LINK_IP4, &dst, c->sw_if_index); - } - - /* - * Call the user's event callback to report DHCP information - */ - if (c->event_callback) - c->event_callback (c->client_index, c); -} - -/* - * dhcp_client_for_us - server-to-client callback. - * Called from proxy_node.c:dhcp_proxy_to_client_input(). - * This function first decides that the packet in question is - * actually for the dhcp client code in case we're also acting as - * a dhcp proxy. Ay caramba, what a folly! - */ -int -dhcp_client_for_us (u32 bi, vlib_buffer_t * b, - ip4_header_t * ip, - udp_header_t * udp, dhcp_header_t * dhcp) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - vlib_main_t *vm = dcm->vlib_main; - dhcp_client_t *c; - uword *p; - f64 now = vlib_time_now (dcm->vlib_main); - u8 dhcp_message_type = 0; - dhcp_option_t *o; - - /* - * Doing dhcp client on this interface? - * Presumably we will always receive dhcp clnt for-us pkts on - * the interface that's asking for an address. - */ - p = hash_get (dcm->client_by_sw_if_index, - vnet_buffer (b)->sw_if_index[VLIB_RX]); - if (p == 0) - return 0; /* no */ - - c = pool_elt_at_index (dcm->clients, p[0]); - - /* Mixing dhcp relay and dhcp proxy? DGMS... */ - if (c->state == DHCP_BOUND && c->retry_count == 0) - return 0; - - /* Packet not for us? Turf it... */ - if (memcmp (dhcp->client_hardware_address, c->client_hardware_address, - sizeof (c->client_hardware_address))) - { - vlib_node_increment_counter (vm, dhcp_client_process_node.index, - DHCP_STAT_NOT_FOR_US, 1); - return 0; - } - - /* 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 */ && - (u8 *) o < (b->data + b->current_data + b->current_length)) - { - switch (o->option) - { - case 53: /* dhcp message type */ - dhcp_message_type = o->data[0]; - break; - - case 51: /* lease time */ - { - u32 lease_time_in_seconds = - clib_host_to_net_u32 (o->data_as_u32[0]); - // for debug: lease_time_in_seconds = 20; /*$$$$*/ - c->lease_expires = now + (f64) lease_time_in_seconds; - c->lease_lifetime = lease_time_in_seconds; - /* Set a sensible default, in case we don't get opt 58 */ - c->lease_renewal_interval = lease_time_in_seconds / 2; - } - break; - - case 58: /* lease renew time in seconds */ - { - u32 lease_renew_time_in_seconds = - clib_host_to_net_u32 (o->data_as_u32[0]); - c->lease_renewal_interval = lease_renew_time_in_seconds; - } - break; - - case 54: /* dhcp server address */ - c->dhcp_server.as_u32 = o->data_as_u32[0]; - break; - - case 1: /* subnet mask */ - { - u32 subnet_mask = clib_host_to_net_u32 (o->data_as_u32[0]); - c->subnet_mask_width = count_set_bits (subnet_mask); - } - break; - case 3: /* router address */ - { - u32 router_address = o->data_as_u32[0]; - c->router_address.as_u32 = router_address; - } - break; - case 6: /* domain server address */ - { - vec_free (c->domain_server_address); - vec_validate (c->domain_server_address, - o->length / sizeof (ip4_address_t) - 1); - clib_memcpy (c->domain_server_address, o->data, o->length); - } - break; - case 12: /* hostname */ - { - /* Replace the existing hostname if necessary */ - vec_free (c->hostname); - vec_validate (c->hostname, o->length - 1); - clib_memcpy (c->hostname, o->data, o->length); - } - break; - - /* $$$$ Your message in this space, parse more options */ - default: - break; - } - - o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); - } - - switch (c->state) - { - case DHCP_DISCOVER: - if (dhcp_message_type != DHCP_PACKET_OFFER) - { - vlib_node_increment_counter (vm, dhcp_client_process_node.index, - DHCP_STAT_NON_OFFER_DISCOVER, 1); - c->next_transmit = now + 5.0; - break; - } - - /* 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 */ - 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: - case DHCP_REQUEST: - if (dhcp_message_type == DHCP_PACKET_NAK) - { - vlib_node_increment_counter (vm, dhcp_client_process_node.index, - DHCP_STAT_NAK, 1); - /* Probably never happens in bound state, but anyhow... */ - if (c->state == DHCP_BOUND) - { - ip4_add_del_interface_address (dcm->vlib_main, c->sw_if_index, - (void *) &c->leased_address, - c->subnet_mask_width, - 1 /*is_del */ ); - vnet_feature_enable_disable ("ip4-unicast", - "ip4-dhcp-client-detect", - c->sw_if_index, 1 /* enable */ , - 0, 0); - c->client_detect_feature_enabled = 1; - } - /* Wipe out any memory of the address we had... */ - c->state = DHCP_DISCOVER; - c->next_transmit = now; - c->retry_count = 0; - c->leased_address.as_u32 = 0; - c->subnet_mask_width = 0; - c->router_address.as_u32 = 0; - c->lease_renewal_interval = 0; - c->dhcp_server.as_u32 = 0; - vec_free (c->domain_server_address); - break; - } - - if (dhcp_message_type != DHCP_PACKET_ACK && - dhcp_message_type != DHCP_PACKET_OFFER) - { - vlib_node_increment_counter (vm, dhcp_client_process_node.index, - DHCP_STAT_NON_OFFER_DISCOVER, 1); - clib_warning ("sw_if_index %d state %U message type %d", - c->sw_if_index, format_dhcp_client_state, - c->state, dhcp_message_type); - c->next_transmit = now + 5.0; - break; - } - /* OK, we own the address (etc), add to the routing table(s) */ - vl_api_rpc_call_main_thread (dhcp_client_addr_callback, - (u8 *) c, sizeof (*c)); - - c->state = DHCP_BOUND; - c->retry_count = 0; - c->next_transmit = now + (f64) c->lease_renewal_interval; - c->lease_expires = now + (f64) c->lease_lifetime; - vlib_node_increment_counter (vm, dhcp_client_process_node.index, - DHCP_STAT_BOUND, 1); - break; - - default: - clib_warning ("client %d bogus state %d", c - dcm->clients, c->state); - break; - } - - /* drop the pkt, return 1 */ - vlib_buffer_free (vm, &bi, 1); - return 1; -} - -static void -send_dhcp_pkt (dhcp_client_main_t * dcm, dhcp_client_t * c, - dhcp_packet_type_t type, int is_broadcast) -{ - vlib_main_t *vm = dcm->vlib_main; - vnet_main_t *vnm = dcm->vnet_main; - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, c->sw_if_index); - vnet_sw_interface_t *sup_sw - = vnet_get_sup_sw_interface (vnm, c->sw_if_index); - vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, c->sw_if_index); - vlib_buffer_t *b; - u32 bi; - ip4_header_t *ip; - udp_header_t *udp; - dhcp_header_t *dhcp; - u32 *to_next; - vlib_frame_t *f; - dhcp_option_t *o; - u16 udp_length, ip_length; - u32 counter_index, node_index; - - /* Interface(s) down? */ - if ((hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) == 0) - return; - if ((sup_sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0) - return; - if ((sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0) - return; - - if (vlib_buffer_alloc (vm, &bi, 1) != 1) - { - clib_warning ("buffer allocation failure"); - c->next_transmit = 0; - return; - } - - /* Build a dhcpv4 pkt from whole cloth */ - b = vlib_get_buffer (vm, bi); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b); - - ASSERT (b->current_data == 0); - - vnet_buffer (b)->sw_if_index[VLIB_RX] = c->sw_if_index; - - if (is_broadcast) - { - node_index = ip4_rewrite_node.index; - vnet_buffer (b)->ip.adj_index[VLIB_TX] = c->ai_bcast; - } - else - { - ip_adjacency_t *adj = adj_get (c->ai_ucast); - - if (IP_LOOKUP_NEXT_ARP == adj->lookup_next_index) - node_index = ip4_arp_node.index; - else - node_index = ip4_rewrite_node.index; - vnet_buffer (b)->ip.adj_index[VLIB_TX] = c->ai_ucast; - } - - /* Enqueue the packet right now */ - f = vlib_get_frame_to_node (vm, node_index); - to_next = vlib_frame_vector_args (f); - to_next[0] = bi; - f->n_vectors = 1; - vlib_put_frame_to_node (vm, node_index, f); - - /* build the headers */ - ip = vlib_buffer_get_current (b); - udp = (udp_header_t *) (ip + 1); - dhcp = (dhcp_header_t *) (udp + 1); - - /* $$$ optimize, maybe */ - clib_memset (ip, 0, sizeof (*ip) + sizeof (*udp) + sizeof (*dhcp)); - - ip->ip_version_and_header_length = 0x45; - ip->ttl = 128; - ip->protocol = IP_PROTOCOL_UDP; - - ip->tos = c->dscp; - - if (ip->tos) - { - /* - * Setup the buffer's QoS settings so any QoS marker on the egress - * interface, that might set VLAN CoS bits, based on this DSCP setting - */ - vnet_buffer2 (b)->qos.source = QOS_SOURCE_IP; - vnet_buffer2 (b)->qos.bits = ip->tos; - b->flags |= VNET_BUFFER_F_QOS_DATA_VALID; - } - - if (is_broadcast) - { - /* src = 0.0.0.0, dst = 255.255.255.255 */ - ip->dst_address.as_u32 = ~0; - } - else - { - /* Renewing an active lease, plain old ip4 src/dst */ - ip->src_address.as_u32 = c->leased_address.as_u32; - ip->dst_address.as_u32 = c->dhcp_server.as_u32; - } - - udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client); - udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server); - - /* Send the interface MAC address */ - clib_memcpy (dhcp->client_hardware_address, - vnet_sw_interface_get_hw_address (vnm, c->sw_if_index), 6); - - /* And remember it for rx-packet-for-us checking */ - clib_memcpy (c->client_hardware_address, dhcp->client_hardware_address, - sizeof (c->client_hardware_address)); - - /* Lease renewal, set up client_ip_address */ - if (is_broadcast == 0) - dhcp->client_ip_address.as_u32 = c->leased_address.as_u32; - - dhcp->opcode = 1; /* request, all we send */ - dhcp->hardware_type = 1; /* ethernet */ - dhcp->hardware_address_length = 6; - dhcp->transaction_identifier = c->transaction_id; - dhcp->flags = - clib_host_to_net_u16 (is_broadcast && c->set_broadcast_flag ? - DHCP_FLAG_BROADCAST : 0); - dhcp->magic_cookie.as_u32 = DHCP_MAGIC; - - o = (dhcp_option_t *) dhcp->options; - - /* Send option 53, the DHCP message type */ - o->option = DHCP_PACKET_OPTION_MSG_TYPE; - o->length = 1; - o->data[0] = type; - o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); - - /* Send option 57, max msg length */ - if (0 /* not needed, apparently */ ) - { - o->option = 57; - o->length = 2; - { - u16 *o2 = (u16 *) o->data; - *o2 = clib_host_to_net_u16 (1152); - o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); - } - } - - /* - * If server ip address is available with non-zero value, - * option 54 (DHCP Server Identifier) is sent. - */ - if (c->dhcp_server.as_u32) - { - o->option = 54; - o->length = 4; - clib_memcpy (o->data, &c->dhcp_server.as_u32, 4); - o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); - } - - /* send option 50, requested IP address */ - if (c->leased_address.as_u32) - { - o->option = 50; - o->length = 4; - clib_memcpy (o->data, &c->leased_address.as_u32, 4); - o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); - } - - /* send option 12, host name */ - if (vec_len (c->hostname)) - { - o->option = 12; - o->length = vec_len (c->hostname); - clib_memcpy (o->data, c->hostname, vec_len (c->hostname)); - 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 */ - - /* - * send option 55, parameter request list - * The current list - see below, matches the Linux dhcp client's list - * Any specific dhcp server config and/or dhcp server may or may - * not yield specific options. - */ - o->option = 55; - o->length = vec_len (c->option_55_data); - clib_memcpy (o->data, c->option_55_data, vec_len (c->option_55_data)); - o = (dhcp_option_t *) (((uword) o) + (o->length + 2)); - - /* End of list */ - o->option = 0xff; - o->length = 0; - o++; - - b->current_length = ((u8 *) o) - b->data; - - /* fix ip length, checksum and udp length */ - ip_length = vlib_buffer_length_in_chain (vm, b); - - ip->length = clib_host_to_net_u16 (ip_length); - ip->checksum = ip4_header_checksum (ip); - - udp_length = ip_length - (sizeof (*ip)); - udp->length = clib_host_to_net_u16 (udp_length); - - switch (type) - { -#define _(a,b) case DHCP_PACKET_##a: {counter_index = DHCP_STAT_##a; break;} - foreach_dhcp_sent_packet_stat -#undef _ - default: - counter_index = DHCP_STAT_UNKNOWN; - break; - } - - vlib_node_increment_counter (vm, dhcp_client_process_node.index, - counter_index, 1); -} - -static int -dhcp_discover_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now) -{ - /* - * State machine "DISCOVER" state. Send a dhcp discover packet, - * eventually back off the retry rate. - */ - - if (c->client_detect_feature_enabled == 0) - { - vnet_feature_enable_disable ("ip4-unicast", - "ip4-dhcp-client-detect", - c->sw_if_index, 1 /* enable */ , 0, 0); - c->client_detect_feature_enabled = 1; - } - - send_dhcp_pkt (dcm, c, DHCP_PACKET_DISCOVER, 1 /* is_broadcast */ ); - - c->retry_count++; - if (c->retry_count > 10) - c->next_transmit = now + 5.0; - else - c->next_transmit = now + 1.0; - return 0; -} - -static int -dhcp_request_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now) -{ - /* - * State machine "REQUEST" state. Send a dhcp request packet, - * eventually drop back to the discover state. - */ - send_dhcp_pkt (dcm, c, DHCP_PACKET_REQUEST, 1 /* is_broadcast */ ); - - c->retry_count++; - if (c->retry_count > 7 /* lucky you */ ) - { - c->state = DHCP_DISCOVER; - c->next_transmit = now; - c->retry_count = 0; - return 1; - } - c->next_transmit = now + 1.0; - return 0; -} - -static int -dhcp_bound_state (dhcp_client_main_t * dcm, dhcp_client_t * c, f64 now) -{ - /* - * State machine "BOUND" state. Send a dhcp request packet to renew - * the lease. - * Eventually, when the lease expires, forget the dhcp data - * and go back to the stone age. - */ - - /* - * We disable the client detect feature when we bind a - * DHCP address. Turn it back on again on first renew attempt. - * Otherwise, if the DHCP server replies we'll never see it. - */ - if (c->client_detect_feature_enabled == 0) - { - vnet_feature_enable_disable ("ip4-unicast", - "ip4-dhcp-client-detect", - c->sw_if_index, 1 /* enable */ , 0, 0); - c->client_detect_feature_enabled = 1; - } - - send_dhcp_pkt (dcm, c, DHCP_PACKET_REQUEST, 0 /* is_broadcast */ ); - - c->retry_count++; - if (c->retry_count > 10) - c->next_transmit = now + 5.0; - else - c->next_transmit = now + 1.0; - - if (now > c->lease_expires) - { - /* Remove the default route */ - if (c->router_address.as_u32) - { - fib_prefix_t all_0s = { - .fp_len = 0, - .fp_addr.ip4.as_u32 = 0x0, - .fp_proto = FIB_PROTOCOL_IP4, - }; - ip46_address_t nh = { - .ip4 = c->router_address, - }; - - fib_table_entry_path_remove (fib_table_get_index_for_sw_if_index - (FIB_PROTOCOL_IP4, c->sw_if_index), - &all_0s, FIB_SOURCE_DHCP, - DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, - 1, FIB_ROUTE_PATH_FLAG_NONE); - } - /* Remove the interface address */ - dhcp_client_release_address (dcm, c); - c->state = DHCP_DISCOVER; - c->next_transmit = now; - c->retry_count = 0; - /* Wipe out any memory of the address we had... */ - c->leased_address.as_u32 = 0; - c->subnet_mask_width = 0; - c->router_address.as_u32 = 0; - c->lease_renewal_interval = 0; - c->dhcp_server.as_u32 = 0; - return 1; - } - return 0; -} - -static f64 -dhcp_client_sm (f64 now, f64 timeout, uword pool_index) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - dhcp_client_t *c; - - /* deleted, pooched, yadda yadda yadda */ - if (pool_is_free_index (dcm->clients, pool_index)) - return timeout; - - c = pool_elt_at_index (dcm->clients, pool_index); - - /* Time for us to do something with this client? */ - if (now < c->next_transmit) - return timeout; - -again: - switch (c->state) - { - case DHCP_DISCOVER: /* send a discover */ - if (dhcp_discover_state (dcm, c, now)) - goto again; - break; - - case DHCP_REQUEST: /* send a request */ - if (dhcp_request_state (dcm, c, now)) - goto again; - break; - - case DHCP_BOUND: /* bound, renew needed? */ - if (dhcp_bound_state (dcm, c, now)) - goto again; - break; - - default: - clib_warning ("dhcp client %d bogus state %d", - c - dcm->clients, c->state); - break; - } - - if (c->next_transmit < now + timeout) - return c->next_transmit - now; - - return timeout; -} - -static uword -dhcp_client_process (vlib_main_t * vm, - vlib_node_runtime_t * rt, vlib_frame_t * f) -{ - f64 timeout = 100.0; - f64 now; - uword event_type; - uword *event_data = 0; - dhcp_client_main_t *dcm = &dhcp_client_main; - dhcp_client_t *c; - int i; - - while (1) - { - vlib_process_wait_for_event_or_clock (vm, timeout); - - event_type = vlib_process_get_events (vm, &event_data); - - now = vlib_time_now (vm); - - switch (event_type) - { - case EVENT_DHCP_CLIENT_WAKEUP: - for (i = 0; i < vec_len (event_data); i++) - timeout = dhcp_client_sm (now, timeout, event_data[i]); - break; - - case ~0: - /* *INDENT-OFF* */ - pool_foreach (c, dcm->clients, - ({ - timeout = dhcp_client_sm (now, timeout, - (uword) (c - dcm->clients)); - })); - /* *INDENT-ON* */ - if (pool_elts (dcm->clients) == 0) - timeout = 100.0; - break; - } - - vec_reset_length (event_data); - } - - /* NOTREACHED */ - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp_client_process_node,static) = { - .function = dhcp_client_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "dhcp-client-process", - .process_log2_n_stack_bytes = 16, - .n_errors = ARRAY_LEN(dhcp_client_process_stat_strings), - .error_strings = dhcp_client_process_stat_strings, -}; -/* *INDENT-ON* */ - -static u8 * -format_dhcp_client_state (u8 * s, va_list * va) -{ - dhcp_client_state_t state = va_arg (*va, dhcp_client_state_t); - char *str = "BOGUS!"; - - switch (state) - { -#define _(a) \ - case a: \ - str = #a; \ - break; - foreach_dhcp_client_state; -#undef _ - default: - break; - } - - s = format (s, "%s", str); - return s; -} - -static u8 * -format_dhcp_client (u8 * s, va_list * va) -{ - dhcp_client_main_t *dcm = va_arg (*va, dhcp_client_main_t *); - dhcp_client_t *c = va_arg (*va, dhcp_client_t *); - int verbose = va_arg (*va, int); - ip4_address_t *addr; - - s = format (s, "[%d] %U state %U ", c - dcm->clients, - format_vnet_sw_if_index_name, dcm->vnet_main, c->sw_if_index, - format_dhcp_client_state, c->state); - - if (0 != c->dscp) - s = format (s, "dscp %d ", c->dscp); - - if (c->leased_address.as_u32) - { - s = format (s, "addr %U/%d gw %U", - format_ip4_address, &c->leased_address, - c->subnet_mask_width, format_ip4_address, - &c->router_address); - - vec_foreach (addr, c->domain_server_address) - s = format (s, " dns %U", format_ip4_address, addr); - } - else - { - s = format (s, "no address\n"); - } - - if (verbose) - { - s = - format (s, - "\n lease: lifetime:%d renewal-interval:%d expires:%.2f (now:%.2f)", - c->lease_lifetime, c->lease_renewal_interval, - c->lease_expires, vlib_time_now (dcm->vlib_main)); - s = - format (s, "\n retry-count:%d, next-xmt:%.2f", c->retry_count, - c->next_transmit); - s = - format (s, "\n adjacencies:[unicast:%d broadcast:%d]", c->ai_ucast, - c->ai_bcast); - } - return s; -} - -static clib_error_t * -show_dhcp_client_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - dhcp_client_t *c; - int verbose = 0; - u32 sw_if_index = ~0; - uword *p; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "intfc %U", - unformat_vnet_sw_interface, dcm->vnet_main, &sw_if_index)) - ; - else if (unformat (input, "verbose")) - verbose = 1; - else - break; - } - - if (sw_if_index != ~0) - { - p = hash_get (dcm->client_by_sw_if_index, sw_if_index); - if (p == 0) - return clib_error_return (0, "dhcp client not configured"); - c = pool_elt_at_index (dcm->clients, p[0]); - vlib_cli_output (vm, "%U", format_dhcp_client, dcm, c, verbose); - return 0; - } - - /* *INDENT-OFF* */ - pool_foreach (c, dcm->clients, - ({ - vlib_cli_output (vm, "%U", - format_dhcp_client, dcm, - c, verbose); - })); - /* *INDENT-ON* */ - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_dhcp_client_command, static) = { - .path = "show dhcp client", - .short_help = "show dhcp client [intfc <intfc>][verbose]", - .function = show_dhcp_client_command_fn, -}; -/* *INDENT-ON* */ - - -int -dhcp_client_add_del (dhcp_client_add_del_args_t * a) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - vlib_main_t *vm = dcm->vlib_main; - dhcp_client_t *c; - uword *p; - fib_prefix_t all_0s = { - .fp_len = 0, - .fp_addr.ip4.as_u32 = 0x0, - .fp_proto = FIB_PROTOCOL_IP4, - }; - - p = hash_get (dcm->client_by_sw_if_index, a->sw_if_index); - - if ((p && a->is_add) || (!p && a->is_add == 0)) - return VNET_API_ERROR_INVALID_VALUE; - - if (a->is_add) - { - dhcp_maybe_register_udp_ports (DHCP_PORT_REG_CLIENT); - pool_get (dcm->clients, c); - clib_memset (c, 0, sizeof (*c)); - c->state = DHCP_DISCOVER; - c->sw_if_index = a->sw_if_index; - c->client_index = a->client_index; - c->pid = a->pid; - c->event_callback = a->event_callback; - c->option_55_data = a->option_55_data; - c->hostname = a->hostname; - c->client_identifier = a->client_identifier; - c->set_broadcast_flag = a->set_broadcast_flag; - c->dscp = a->dscp; - c->ai_ucast = ADJ_INDEX_INVALID; - c->ai_bcast = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, - VNET_LINK_IP4, - &ADJ_BCAST_ADDR, c->sw_if_index); - - do - { - c->transaction_id = random_u32 (&dcm->seed); - } - while (c->transaction_id == 0); - - hash_set (dcm->client_by_sw_if_index, a->sw_if_index, c - dcm->clients); - - /* - * In order to accept any OFFER, whether broadcasted or unicasted, we - * need to configure the dhcp-client-detect feature as an input feature - * so the DHCP OFFER is sent to the ip4-local node. Without this a - * broadcasted OFFER hits the 255.255.255.255/32 address and a unicast - * hits 0.0.0.0/0 both of which default to drop and the latter may forward - * of box - not what we want. Nor to we want to change these route for - * all interfaces in this table - */ - vnet_feature_enable_disable ("ip4-unicast", - "ip4-dhcp-client-detect", - c->sw_if_index, 1 /* enable */ , 0, 0); - c->client_detect_feature_enabled = 1; - - vlib_process_signal_event (vm, dhcp_client_process_node.index, - EVENT_DHCP_CLIENT_WAKEUP, c - dcm->clients); - } - else - { - c = pool_elt_at_index (dcm->clients, p[0]); - - if (c->router_address.as_u32) - { - ip46_address_t nh = { - .ip4 = c->router_address, - }; - - fib_table_entry_path_remove (fib_table_get_index_for_sw_if_index - (FIB_PROTOCOL_IP4, c->sw_if_index), - &all_0s, FIB_SOURCE_DHCP, - DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, - 1, FIB_ROUTE_PATH_FLAG_NONE); - } - dhcp_client_release_address (dcm, c); - - adj_unlock (c->ai_ucast); - adj_unlock (c->ai_bcast); - - vec_free (c->domain_server_address); - vec_free (c->option_55_data); - vec_free (c->hostname); - vec_free (c->client_identifier); - hash_unset (dcm->client_by_sw_if_index, c->sw_if_index); - pool_put (dcm->clients, c); - } - return 0; -} - -int -dhcp_client_config (u32 is_add, - u32 client_index, - vlib_main_t * vm, - u32 sw_if_index, - u8 * hostname, - u8 * client_id, - dhcp_event_cb_t event_callback, - u8 set_broadcast_flag, ip_dscp_t dscp, u32 pid) -{ - dhcp_client_add_del_args_t _a, *a = &_a; - int rv; - - clib_memset (a, 0, sizeof (*a)); - a->is_add = is_add; - a->sw_if_index = sw_if_index; - a->client_index = client_index; - a->pid = pid; - a->event_callback = event_callback; - a->set_broadcast_flag = set_broadcast_flag; - a->dscp = dscp; - vec_validate (a->hostname, strlen ((char *) hostname) - 1); - strncpy ((char *) a->hostname, (char *) hostname, vec_len (a->hostname)); - 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. - */ - - /* Subnet Mask */ - vec_add1 (a->option_55_data, 1); - /* Broadcast address */ - vec_add1 (a->option_55_data, 28); - /* time offset */ - vec_add1 (a->option_55_data, 2); - /* Router */ - vec_add1 (a->option_55_data, 3); - /* Domain Name */ - vec_add1 (a->option_55_data, 15); - /* DNS */ - vec_add1 (a->option_55_data, 6); - /* Domain search */ - vec_add1 (a->option_55_data, 119); - /* Host name */ - vec_add1 (a->option_55_data, 12); - /* NetBIOS name server */ - vec_add1 (a->option_55_data, 44); - /* NetBIOS Scope */ - vec_add1 (a->option_55_data, 47); - /* MTU */ - vec_add1 (a->option_55_data, 26); - /* Classless static route */ - vec_add1 (a->option_55_data, 121); - /* NTP servers */ - vec_add1 (a->option_55_data, 42); - - rv = dhcp_client_add_del (a); - - switch (rv) - { - case 0: - break; - - case VNET_API_ERROR_INVALID_VALUE: - - vec_free (a->hostname); - vec_free (a->client_identifier); - vec_free (a->option_55_data); - - if (is_add) - clib_warning ("dhcp client already enabled on intf_idx %d", - sw_if_index); - else - clib_warning ("dhcp client not enabled on on intf_idx %d", - sw_if_index); - break; - - default: - clib_warning ("dhcp_client_add_del returned %d", rv); - } - - return rv; -} - -void -dhcp_client_walk (dhcp_client_walk_cb_t cb, void *ctx) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - dhcp_client_t *c; - - /* *INDENT-OFF* */ - pool_foreach (c, dcm->clients, - ({ - if (!cb(c, ctx)) - break; - })); - /* *INDENT-ON* */ - -} - -static clib_error_t * -dhcp_client_set_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - - dhcp_client_main_t *dcm = &dhcp_client_main; - u32 sw_if_index; - u8 *hostname = 0; - u8 sw_if_index_set = 0; - u8 set_broadcast_flag = 1; - int is_add = 1; - dhcp_client_add_del_args_t _a, *a = &_a; - int rv; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "intfc %U", - unformat_vnet_sw_interface, dcm->vnet_main, &sw_if_index)) - sw_if_index_set = 1; - else if (unformat (input, "hostname %v", &hostname)) - ; - else if (unformat (input, "del")) - is_add = 0; - else if (unformat (input, "broadcast", &set_broadcast_flag)) - is_add = 0; - else - break; - } - - if (sw_if_index_set == 0) - return clib_error_return (0, "interface not specified"); - - clib_memset (a, 0, sizeof (*a)); - a->is_add = is_add; - a->sw_if_index = sw_if_index; - a->hostname = hostname; - a->client_identifier = format (0, "vpe 1.0%c", 0); - a->set_broadcast_flag = set_broadcast_flag; - - /* - * Option 55 request list. These data precisely match - * the Ubuntu dhcp client. YMMV. - */ - - /* Subnet Mask */ - vec_add1 (a->option_55_data, 1); - /* Broadcast address */ - vec_add1 (a->option_55_data, 28); - /* time offset */ - vec_add1 (a->option_55_data, 2); - /* Router */ - vec_add1 (a->option_55_data, 3); - /* Domain Name */ - vec_add1 (a->option_55_data, 15); - /* DNS */ - vec_add1 (a->option_55_data, 6); - /* Domain search */ - vec_add1 (a->option_55_data, 119); - /* Host name */ - vec_add1 (a->option_55_data, 12); - /* NetBIOS name server */ - vec_add1 (a->option_55_data, 44); - /* NetBIOS Scope */ - vec_add1 (a->option_55_data, 47); - /* MTU */ - vec_add1 (a->option_55_data, 26); - /* Classless static route */ - vec_add1 (a->option_55_data, 121); - /* NTP servers */ - vec_add1 (a->option_55_data, 42); - - rv = dhcp_client_add_del (a); - - switch (rv) - { - case 0: - break; - - case VNET_API_ERROR_INVALID_VALUE: - - vec_free (a->hostname); - vec_free (a->client_identifier); - vec_free (a->option_55_data); - if (is_add) - return clib_error_return (0, "dhcp client already enabled on %U", - format_vnet_sw_if_index_name, - dcm->vnet_main, sw_if_index); - else - return clib_error_return (0, "dhcp client not enabled on %U", - format_vnet_sw_if_index_name, - dcm->vnet_main, sw_if_index); - break; - - default: - vlib_cli_output (vm, "dhcp_client_add_del returned %d", rv); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp_client_set_command, static) = { - .path = "set dhcp client", - .short_help = "set dhcp client [del] intfc <interface> [hostname <name>]", - .function = dhcp_client_set_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcp_client_init (vlib_main_t * vm) -{ - dhcp_client_main_t *dcm = &dhcp_client_main; - - dcm->vlib_main = vm; - dcm->vnet_main = vnet_get_main (); - dcm->seed = (u32) clib_cpu_time_now (); - return 0; -} - -VLIB_INIT_FUNCTION (dhcp_client_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/client.h b/src/vnet/dhcp/client.h deleted file mode 100644 index 5191fcf0fa8..00000000000 --- a/src/vnet/dhcp/client.h +++ /dev/null @@ -1,179 +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. - */ -/* - * client.h: dhcp client - */ - -#ifndef included_dhcp_client_h -#define included_dhcp_client_h - -#include <vnet/ip/ip.h> -#include <vnet/dhcp/dhcp4_packet.h> - -#define foreach_dhcp_client_state \ -_(DHCP_DISCOVER) \ -_(DHCP_REQUEST) \ -_(DHCP_BOUND) - -typedef enum -{ -#define _(a) a, - foreach_dhcp_client_state -#undef _ -} dhcp_client_state_t; - -struct dhcp_client_t_; - -/** - * Callback function for DHCP complete events - */ -typedef void (*dhcp_event_cb_t) (u32 client_index, - const struct dhcp_client_t_ * client); - -typedef struct dhcp_client_t_ -{ - dhcp_client_state_t state; - - /* the interface in question */ - u32 sw_if_index; - - /* State machine retry counter */ - u32 retry_count; - - /* Send next pkt at this time */ - f64 next_transmit; - f64 lease_expires; - - /* DHCP transaction ID, a random number */ - u32 transaction_id; - - /* leased address, other learned info DHCP */ - ip4_address_t leased_address; /* from your_ip_address field */ - ip4_address_t dhcp_server; - u32 subnet_mask_width; /* option 1 */ - ip4_address_t router_address; /* option 3 */ - ip4_address_t *domain_server_address; /* option 6 */ - u32 lease_renewal_interval; /* option 51 */ - u32 lease_lifetime; /* option 59 */ - - /* Requested data (option 55) */ - u8 *option_55_data; - - /* hostname and software client identifiers */ - u8 *hostname; - u8 *client_identifier; /* software version, e.g. vpe 1.0 */ - - /* Information used for event callback */ - u32 client_index; - u32 pid; - - /* Set the broadcast Flag in the Discover/Request messages */ - u8 set_broadcast_flag; - /* Interface MAC address, so we can do an rx-packet-for-us check */ - u8 client_hardware_address[6]; - u8 client_detect_feature_enabled; - - /* the unicast adjacency for the DHCP server */ - adj_index_t ai_ucast; - /* the broadcast adjacency on the link */ - adj_index_t ai_bcast; - /* IP DSCP to set in sent packets */ - ip_dscp_t dscp; - - dhcp_event_cb_t event_callback; -} dhcp_client_t; - -typedef struct -{ - /* DHCP client pool */ - dhcp_client_t *clients; - uword *client_by_sw_if_index; - u32 seed; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; -} dhcp_client_main_t; - -typedef struct -{ - int is_add; - u32 sw_if_index; - u8 set_broadcast_flag; - - /* vectors, consumed by dhcp client code */ - u8 *hostname; - u8 *client_identifier; - - /* Bytes containing requested option numbers */ - u8 *option_55_data; - - /* Information used for event callback */ - u32 client_index; - u32 pid; - ip_dscp_t dscp; - dhcp_event_cb_t event_callback; -} dhcp_client_add_del_args_t; - -extern dhcp_client_main_t dhcp_client_main; - -#define EVENT_DHCP_CLIENT_WAKEUP 1 - -int dhcp_client_for_us (u32 bi0, - vlib_buffer_t * b0, - ip4_header_t * ip0, - udp_header_t * u0, dhcp_header_t * dh0); - -/** - * Add/Delete DHCP clients - */ -extern int dhcp_client_config (u32 is_add, - u32 client_index, - vlib_main_t * vm, - u32 sw_if_index, - u8 * hostname, - u8 * client_id, - dhcp_event_cb_t event_callback, - u8 set_broadcast_flag, - ip_dscp_t dscp, u32 pid); - -/** - * callback function for clients walking the DHCP client configurations - * - * @param client The client being visitsed - * @param data The data passed during the call to 'walk' - * @return !0 to continue walking 0 to stop. - */ -typedef int (*dhcp_client_walk_cb_t) (const dhcp_client_t * client, - void *data); - -/** - * Walk (visit each) DHCP client configuration - * - * @param cb The callback function invoked as each client is visited - * @param ctx Context data passed back to the client in the invocation of - * the callback. - */ -extern void dhcp_client_walk (dhcp_client_walk_cb_t cb, void *ctx); - -#endif /* included_dhcp_client_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp.api b/src/vnet/dhcp/dhcp.api deleted file mode 100644 index f3fef5135f1..00000000000 --- a/src/vnet/dhcp/dhcp.api +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) 2015-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. - */ - -option version = "3.0.1"; - -import "vnet/interface_types.api"; -import "vnet/ip/ip_types.api"; -import "vnet/ethernet/ethernet_types.api"; - -enum vss_type { - VSS_TYPE_API_ASCII = 0, - VSS_TYPE_API_VPN_ID = 1, - VSS_TYPE_API_INVALID = 123, - VSS_TYPE_API_DEFAULT = 255, -}; - -enum dhcp_client_state { - DHCP_CLIENT_STATE_API_DISCOVER, - DHCP_CLIENT_STATE_API_REQUEST, - DHCP_CLIENT_STATE_API_BOUND, -}; - -enum dhcpv6_msg_type -{ - DHCPV6_MSG_API_SOLICIT = 1, - DHCPV6_MSG_API_ADVERTISE = 2, - DHCPV6_MSG_API_REQUEST = 3, - DHCPV6_MSG_API_CONFIRM = 4, - DHCPV6_MSG_API_RENEW = 5, - DHCPV6_MSG_API_REBIND = 6, - DHCPV6_MSG_API_REPLY = 7, - DHCPV6_MSG_API_RELEASE = 8, - DHCPV6_MSG_API_DECLINE = 9, - DHCPV6_MSG_API_RECONFIGURE = 10, - DHCPV6_MSG_API_INFORMATION_REQUEST = 11, - DHCPV6_MSG_API_RELAY_FORW = 12, - DHCPV6_MSG_API_RELAY_REPL = 13, -}; - -/** \brief DHCP Proxy config add / del request - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param rx_vrf_id - Rx/interface vrf id - @param server_vrf_id - server vrf id - @param is_add - add the config if non-zero, else delete - @param insert_circuit_id - option82 suboption 1 fib number - @param dhcp_server[] - server address - @param dhcp_src_address[] - <fix this, need details> -*/ -autoreply define dhcp_proxy_config -{ - u32 client_index; - u32 context; - u32 rx_vrf_id; - u32 server_vrf_id; - bool is_add; - vl_api_address_t dhcp_server; - vl_api_address_t dhcp_src_address; -}; - -/** \brief DHCP Proxy set / unset vss request - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param tbl_id - table id - @vss_type - 0: use ASCI vpn_id; 1: use oui/vpn_index; 255: global vpn - @vpn_ascii - null terminated ASCII VPN ID up to 128 characters - @param oui - first part of rfc2685 vpn id, 3 bytes oui - @param vpn_index - second part of rfc2685 vpn id, 4 bytes vpn index - @param is_ipv6 - ip6 if non-zero, else ip4 - @param is_add - set vss if non-zero, else delete -*/ -autoreply define dhcp_proxy_set_vss -{ - u32 client_index; - u32 context; - u32 tbl_id; - vl_api_vss_type_t vss_type; - string vpn_ascii_id[129]; - u32 oui; - u32 vpn_index; - bool is_ipv6; - bool is_add; -}; - -/** \brief DHCP Client config data - @param sw_if_index - index of the interface for DHCP client - @param hostname - hostname - @param id - Client ID - option 61 - @param want_dhcp_event - DHCP event sent to the sender - via dhcp_compl_event API message if non-zero - @param set_broadcast_flag - in the DHCP Discover to control - how the resulting OFFER is addressed. - @param dscp - DSCP value set in IP packets sent by the client - @param pid - sender's pid -*/ -typedef dhcp_client -{ - vl_api_interface_index_t sw_if_index; - string hostname[64]; - u8 id[64]; - bool want_dhcp_event; - bool set_broadcast_flag; - vl_api_ip_dscp_t dscp; - u32 pid; -}; - -/** \brief DHCP Client config add / del request - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param is_add - add the config if non-zero, else delete - @param client - client configuration data -*/ -autoreply define dhcp_client_config -{ - u32 client_index; - u32 context; - bool is_add; - vl_api_dhcp_client_t client; -}; - -/** \brief Struct representing domain server - @param address - IP address -*/ -typedef domain_server -{ - vl_api_address_t address; -}; - -/** \brief Data learned by the client during the DHCP process - @param sw_if_index - the interface on which the client is configured - @param state - the state of the lease - @param is_ipv6 - if non-zero the address is ipv6, else ipv4 - @param mask_width - The length of the subnet mask assigned - @param host_address - Host IP address - @param router_address - Router IP address - @param host_mac - Host MAC address -*/ -typedef dhcp_lease -{ - vl_api_interface_index_t sw_if_index; - vl_api_dhcp_client_state_t state; - bool is_ipv6; - string hostname[64]; - u8 mask_width; - vl_api_address_t host_address; - vl_api_address_t router_address; - vl_api_mac_address_t host_mac; - u8 count; - vl_api_domain_server_t domain_server[count]; -}; - -/** \brief Tell client about a DHCP completion event - @param client_index - opaque cookie to identify the sender - @param pid - client pid registered to receive notification - @param lease - Data learned during the DHCP process; -*/ -define dhcp_compl_event -{ - u32 client_index; - u32 pid; - vl_api_dhcp_lease_t lease; -}; - -service { - rpc dhcp_client_config returns dhcp_client_config_reply events dhcp_compl_event; -}; - -/** \brief Dump the DHCP client configurations - */ -define dhcp_client_dump -{ - u32 client_index; - u32 context; -}; - -/** \brief DHCP Client details returned from dump - * @param client - The configured client - * @param lease - The learned lease data - */ -define dhcp_client_details -{ - u32 context; - vl_api_dhcp_client_t client; - vl_api_dhcp_lease_t lease; -}; - -/** \brief Dump DHCP proxy table - @param client_index - opaque cookie to identify the sender - @param True for IPv6 proxy table -*/ -define dhcp_proxy_dump -{ - u32 client_index; - u32 context; - bool is_ip6; -}; - -typedef dhcp_server -{ - u32 server_vrf_id; - vl_api_address_t dhcp_server; -}; - -/** \brief Tell client about a DHCP completion event - @param client_index - opaque cookie to identify the sender -*/ -manual_endian manual_print define dhcp_proxy_details -{ - u32 context; - u32 rx_vrf_id; - u32 vss_oui; - u32 vss_fib_id; - vl_api_vss_type_t vss_type; - bool is_ipv6; - string vss_vpn_ascii_id[129]; - vl_api_address_t dhcp_src_address; - u8 count; - vl_api_dhcp_server_t servers[count]; -}; - -/** \brief Set DHCPv6 DUID-LL - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param duid_ll - DUID-LL binary string -*/ -autoreply define dhcp6_duid_ll_set -{ - u32 client_index; - u32 context; - u8 duid_ll[10]; -}; - -/** \brief Enable/disable listening on DHCPv6 client port - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ -autoreply define dhcp6_clients_enable_disable -{ - u32 client_index; - u32 context; - bool enable; -}; - -/** \brief Struct representing DHCPv6 address - @param address - address - @param valid_time - valid lifetime - @param preferred_time - preferred lifetime -*/ -typedef dhcp6_address_info -{ - vl_api_ip6_address_t address; - u32 valid_time; - u32 preferred_time; -}; - -/** \brief Struct representing DHCPv6 PD prefix - @param prefix - prefix - @param valid_time - valid lifetime - @param preferred_time - preferred lifetime -*/ -typedef dhcp6_pd_prefix_info -{ - vl_api_ip6_prefix_t prefix; - u32 valid_time; - u32 preferred_time; -}; - -/** \brief Send DHCPv6 client message of specified type - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - index of TX interface, also identifies IAID - @param server_index - used to dentify DHCPv6 server, - unique for each DHCPv6 server on the link, - value obrtained from dhcp6_reply_event API message, - use ~0 to send message to all DHCPv6 servers - @param irt - initial retransmission time - @param mrt - maximum retransmission time - @param mrc - maximum retransmission count - @param mrd - maximum retransmission duration - for sending the message - @param stop - if non-zero then stop resending the message, - otherwise start sending the message - @param msg_type - message type - @param T1 - value of T1 in IA_NA option - @param T2 - value of T2 in IA_NA option - @param n_addresses - number of addresses in IA_NA option - @param addresses - list of addresses in IA_NA option -*/ -autoreply define dhcp6_send_client_message -{ - u32 client_index; - u32 context; - vl_api_interface_index_t sw_if_index; - u32 server_index; - u32 irt; - u32 mrt; - u32 mrc; - u32 mrd; - bool stop; - vl_api_dhcpv6_msg_type_t msg_type; - u32 T1; - u32 T2; - u32 n_addresses; - vl_api_dhcp6_address_info_t addresses[n_addresses]; -}; - -/** \brief Send DHCPv6 PD client message of specified type - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - index of TX interface - @param server_index - used to dentify DHCPv6 server, - unique for each DHCPv6 server on the link, - value obrtained from dhcp6_pd_reply_event API message, - use ~0 to send message to all DHCPv6 servers - @param irt - initial retransmission time - @param mrt - maximum retransmission time - @param mrc - maximum retransmission count - @param mrd - maximum retransmission duration - for sending the message - @param stop - if non-zero then stop resending the message, - otherwise start sending the message - @param msg_type - message type - @param T1 - value of T1 in IA_PD option - @param T2 - value of T2 in IA_PD option - @param n_prefixes - number of addresses in IA_PD option - @param prefixes - list of prefixes in IA_PD option -*/ -autoreply define dhcp6_pd_send_client_message -{ - u32 client_index; - u32 context; - vl_api_interface_index_t sw_if_index; - u32 server_index; - u32 irt; - u32 mrt; - u32 mrc; - u32 mrd; - bool stop; - vl_api_dhcpv6_msg_type_t msg_type; - u32 T1; - u32 T2; - u32 n_prefixes; - vl_api_dhcp6_pd_prefix_info_t prefixes[n_prefixes]; -}; - -service { - rpc want_dhcp6_reply_events returns want_dhcp6_reply_events_reply - events dhcp6_reply_event; -}; - -service { - rpc want_dhcp6_pd_reply_events returns want_dhcp6_pd_reply_events_reply - events dhcp6_pd_reply_event; -}; - -/** \brief Register for DHCPv6 reply events - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param enable_disable - 1 => register for events, 0 => cancel registration - @param pid - sender's pid -*/ -autoreply define want_dhcp6_reply_events -{ - u32 client_index; - u32 context; - u8 enable_disable; - u32 pid; -}; - -/** \brief Register for DHCPv6 PD reply events - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param enable_disable - 1 => register for events, 0 => cancel registration - @param pid - sender's pid -*/ -autoreply define want_dhcp6_pd_reply_events -{ - u32 client_index; - u32 context; - bool enable_disable; - u32 pid; -}; - -/** \brief Tell client about a DHCPv6 server reply event - @param client_index - opaque cookie to identify the sender - @param pid - client pid registered to receive notification - @param sw_if_index - index of RX interface, also identifies IAID - @param server_index - used to dentify DHCPv6 server, - unique for each DHCPv6 server on the link - @param msg_type - message type - @param T1 - value of T1 in IA_NA option - @param T2 - value of T2 in IA_NA option - @param inner_status_code - value of status code inside IA_NA option - @param status_code - value of status code - @param preference - value of preference option in reply message - @param n_addresses - number of addresses in IA_NA option - @param addresses - list of addresses in IA_NA option -*/ -define dhcp6_reply_event -{ - u32 client_index; - u32 pid; - vl_api_interface_index_t sw_if_index; - u32 server_index; - vl_api_dhcpv6_msg_type_t msg_type; - u32 T1; - u32 T2; - u16 inner_status_code; - u16 status_code; - u8 preference; - u32 n_addresses; - vl_api_dhcp6_address_info_t addresses[n_addresses]; -}; - -/** \brief Tell client about a DHCPv6 PD server reply event - @param client_index - opaque cookie to identify the sender - @param pid - client pid registered to receive notification - @param sw_if_index - index of RX interface - @param server_index - used to dentify DHCPv6 server, - unique for each DHCPv6 server on the link - @param msg_type - message type - @param T1 - value of T1 in IA_PD option - @param T2 - value of T2 in IA_PD option - @param inner_status_code - value of status code inside IA_PD option - @param status_code - value of the main status code of DHCPv6 message - @param preference - value of preference option in reply message - @param n_prefixes - number of prefixes in IA_PD option - @param prefixes - list of prefixes in IA_PD option -*/ -define dhcp6_pd_reply_event -{ - u32 client_index; - u32 pid; - vl_api_interface_index_t sw_if_index; - u32 server_index; - vl_api_dhcpv6_msg_type_t msg_type; - u32 T1; - u32 T2; - u16 inner_status_code; - u16 status_code; - u8 preference; - u32 n_prefixes; - vl_api_dhcp6_pd_prefix_info_t prefixes[n_prefixes]; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp4_packet.h b/src/vnet/dhcp/dhcp4_packet.h deleted file mode 100644 index 3076dd9529d..00000000000 --- a/src/vnet/dhcp/dhcp4_packet.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef included_vnet_dhcp4_packet_h -#define included_vnet_dhcp4_packet_h - -/* - * DHCP packet format - * - * 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 <vnet/ip/ip4_packet.h> - -typedef struct -{ - u8 option; - u8 length; - union - { - u8 data[0]; - u32 data_as_u32[0]; - }; -} __attribute__ ((packed)) dhcp_option_t; - -typedef struct -{ - u8 opcode; /* 1 = request, 2 = reply */ - u8 hardware_type; /* 1 = ethernet */ - u8 hardware_address_length; - u8 hops; - u32 transaction_identifier; - u16 seconds; - u16 flags; -#define DHCP_FLAG_BROADCAST (1<<15) - ip4_address_t client_ip_address; - ip4_address_t your_ip_address; /* use this one */ - ip4_address_t server_ip_address; - ip4_address_t gateway_ip_address; /* use option 3, not this one */ - u8 client_hardware_address[16]; - u8 server_name[64]; - u8 boot_filename[128]; - ip4_address_t magic_cookie; - dhcp_option_t options[0]; -} dhcp_header_t; - -typedef enum -{ - DHCP_PACKET_DISCOVER = 1, - DHCP_PACKET_OFFER, - DHCP_PACKET_REQUEST, - DHCP_PACKET_ACK = 5, - DHCP_PACKET_NAK, -} dhcp_packet_type_t; - -typedef enum dhcp_packet_option_t_ -{ - DHCP_PACKET_OPTION_MSG_TYPE = 53, - DHCP_PACKET_OPTION_END = 0xff, -} dhcp_packet_option_t; - -/* charming antique: 99.130.83.99 is the dhcp magic cookie */ -#define DHCP_MAGIC (clib_host_to_net_u32(0x63825363)) - -#endif /* included_vnet_dhcp4_packet_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp4_proxy_error.def b/src/vnet/dhcp/dhcp4_proxy_error.def deleted file mode 100644 index adf04808fa3..00000000000 --- a/src/vnet/dhcp/dhcp4_proxy_error.def +++ /dev/null @@ -1,32 +0,0 @@ -/* - * dhcp_proxy_error.def: dhcp proxy errors - * - * 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. - */ - -dhcp_proxy_error (NONE, "no error") -dhcp_proxy_error (NO_SERVER, "no dhcp server configured") -dhcp_proxy_error (RELAY_TO_SERVER, "DHCP packets relayed to the server") -dhcp_proxy_error (RELAY_TO_CLIENT, "DHCP packets relayed to clients") -dhcp_proxy_error (OPTION_82_ERROR, "DHCP failed to insert option 82") -dhcp_proxy_error (NO_OPTION_82, "DHCP option 82 missing") -dhcp_proxy_error (BAD_OPTION_82_ITF, "Bad DHCP option 82 interface value") -dhcp_proxy_error (BAD_OPTION_82_ADDR, "Bad DHCP option 82 address value") -dhcp_proxy_error (BAD_FIB_ID, "DHCP option 82 fib-id to fib-index map failure") -dhcp_proxy_error (NO_INTERFACE_ADDRESS, "DHCP no interface address") -dhcp_proxy_error (OPTION_82_VSS_NOT_PROCESSED, "DHCP VSS not processed by DHCP server") -dhcp_proxy_error (BAD_YIADDR, "DHCP packets with bad your_ip_address fields") -dhcp_proxy_error (BAD_SVR_FIB_OR_ADDRESS, "DHCP packets not from DHCP server or server FIB.") -dhcp_proxy_error (PKT_TOO_BIG, "DHCP packets which are too big.") - diff --git a/src/vnet/dhcp/dhcp4_proxy_node.c b/src/vnet/dhcp/dhcp4_proxy_node.c deleted file mode 100644 index 3576f0cbf35..00000000000 --- a/src/vnet/dhcp/dhcp4_proxy_node.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * proxy_node.c: dhcp proxy node 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/dhcp/dhcp_proxy.h> -#include <vnet/dhcp/client.h> -#include <vnet/fib/ip4_fib.h> - -static char *dhcp_proxy_error_strings[] = { -#define dhcp_proxy_error(n,s) s, -#include <vnet/dhcp/dhcp4_proxy_error.def> -#undef dhcp_proxy_error -}; - -#define foreach_dhcp_proxy_to_server_input_next \ - _ (DROP, "error-drop") \ - _ (LOOKUP, "ip4-lookup") \ - _ (SEND_TO_CLIENT, "dhcp-proxy-to-client") - -typedef enum -{ -#define _(s,n) DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s, - foreach_dhcp_proxy_to_server_input_next -#undef _ - DHCP_PROXY_TO_SERVER_INPUT_N_NEXT, -} dhcp_proxy_to_server_input_next_t; - -typedef struct -{ - /* 0 => to server, 1 => to client */ - int which; - ip4_address_t trace_ip4_address; - u32 error; - u32 sw_if_index; - u32 original_sw_if_index; -} dhcp_proxy_trace_t; - -#define VPP_DHCP_OPTION82_SUB1_SIZE 6 -#define VPP_DHCP_OPTION82_SUB5_SIZE 6 -#define VPP_DHCP_OPTION82_VSS_SIZE 12 -#define VPP_DHCP_OPTION82_SIZE (VPP_DHCP_OPTION82_SUB1_SIZE + \ - VPP_DHCP_OPTION82_SUB5_SIZE + \ - VPP_DHCP_OPTION82_VSS_SIZE +3) - -static vlib_node_registration_t dhcp_proxy_to_server_node; -static vlib_node_registration_t dhcp_proxy_to_client_node; - -static u8 * -format_dhcp_proxy_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 *); - dhcp_proxy_trace_t *t = va_arg (*args, dhcp_proxy_trace_t *); - - if (t->which == 0) - s = format (s, "DHCP proxy: sent to server %U\n", - format_ip4_address, &t->trace_ip4_address, t->error); - else - s = format (s, "DHCP proxy: broadcast to client from %U\n", - format_ip4_address, &t->trace_ip4_address); - - if (t->error != (u32) ~ 0) - s = format (s, " error: %s\n", dhcp_proxy_error_strings[t->error]); - - s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n", - t->original_sw_if_index, t->sw_if_index); - - return s; -} - -static u8 * -format_dhcp_proxy_header_with_length (u8 * s, va_list * args) -{ - dhcp_header_t *h = va_arg (*args, dhcp_header_t *); - u32 max_header_bytes = va_arg (*args, u32); - u32 header_bytes; - - header_bytes = sizeof (h[0]); - if (max_header_bytes != 0 && header_bytes > max_header_bytes) - return format (s, "dhcp header truncated"); - - s = format (s, "DHCP Proxy"); - - return s; -} - -static uword -dhcp_proxy_to_server_input (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - u32 n_left_from, next_index, *from, *to_next; - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - u32 pkts_to_server = 0, pkts_to_client = 0, pkts_no_server = 0; - u32 pkts_no_interface_address = 0; - u32 pkts_too_big = 0; - ip4_main_t *im = &ip4_main; - - 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 > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t *b0; - udp_header_t *u0; - dhcp_header_t *h0; - ip4_header_t *ip0; - u32 next0; - u32 old0, new0; - ip_csum_t sum0; - u32 error0 = (u32) ~ 0; - u32 sw_if_index = 0; - u32 original_sw_if_index = 0; - u32 fib_index; - dhcp_proxy_t *proxy; - dhcp_server_t *server; - u32 rx_sw_if_index; - dhcp_option_t *o, *end; - u32 len = 0; - u8 is_discover = 0; - int space_left; - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - h0 = vlib_buffer_get_current (b0); - - /* - * udp_local hands us the DHCP header, need udp hdr, - * ip hdr to relay to server - */ - vlib_buffer_advance (b0, -(sizeof (*u0))); - u0 = vlib_buffer_get_current (b0); - - /* This blows. Return traffic has src_port = 67, dst_port = 67 */ - if (u0->src_port == - clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_server)) - { - vlib_buffer_advance (b0, sizeof (*u0)); - next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT; - error0 = 0; - pkts_to_client++; - goto do_enqueue; - } - - rx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - fib_index = im->fib_index_by_sw_if_index[rx_sw_if_index]; - proxy = dhcp_get_proxy (dpm, fib_index, FIB_PROTOCOL_IP4); - - if (PREDICT_FALSE (NULL == proxy)) - { - error0 = DHCP_PROXY_ERROR_NO_SERVER; - next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_no_server++; - goto do_trace; - } - - if (!vlib_buffer_chain_linearize (vm, b0)) - { - error0 = DHCP_PROXY_ERROR_PKT_TOO_BIG; - next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_too_big++; - goto do_trace; - } - space_left = vlib_buffer_space_left_at_end (vm, b0); - /* cant parse chains... - * and we need some space for option 82*/ - if ((b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0 || - space_left < VPP_DHCP_OPTION82_SIZE) - { - error0 = DHCP_PROXY_ERROR_PKT_TOO_BIG; - next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_too_big++; - goto do_trace; - } - - server = &proxy->dhcp_servers[0]; - vlib_buffer_advance (b0, -(sizeof (*ip0))); - ip0 = vlib_buffer_get_current (b0); - - /* disable UDP checksum */ - u0->checksum = 0; - sum0 = ip0->checksum; - old0 = ip0->dst_address.as_u32; - new0 = server->dhcp_server.ip4.as_u32; - ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32; - sum0 = ip_csum_update (sum0, old0, new0, - ip4_header_t /* structure */ , - dst_address /* changed member */ ); - ip0->checksum = ip_csum_fold (sum0); - - sum0 = ip0->checksum; - old0 = ip0->src_address.as_u32; - new0 = proxy->dhcp_src_address.ip4.as_u32; - ip0->src_address.as_u32 = new0; - sum0 = ip_csum_update (sum0, old0, new0, - ip4_header_t /* structure */ , - src_address /* changed member */ ); - ip0->checksum = ip_csum_fold (sum0); - - /* Send to DHCP server via the configured FIB */ - vnet_buffer (b0)->sw_if_index[VLIB_TX] = server->server_fib_index; - - h0->gateway_ip_address = proxy->dhcp_src_address.ip4; - pkts_to_server++; - - o = h0->options; - end = (void *) vlib_buffer_get_tail (b0); - - /* TLVs are not performance-friendly... */ - while (o->option != DHCP_PACKET_OPTION_END && o < end) - { - if (DHCP_PACKET_OPTION_MSG_TYPE == o->option) - { - if (DHCP_PACKET_DISCOVER == o->data[0]) - { - is_discover = 1; - } - } - o = (dhcp_option_t *) (o->data + o->length); - } - - if (o->option == DHCP_PACKET_OPTION_END && o <= end) - { - vnet_main_t *vnm = vnet_get_main (); - u16 old_l0, new_l0; - ip4_address_t _ia0, *ia0 = &_ia0; - dhcp_vss_t *vss; - vnet_sw_interface_t *swif; - - original_sw_if_index = sw_if_index = - vnet_buffer (b0)->sw_if_index[VLIB_RX]; - swif = vnet_get_sw_interface (vnm, sw_if_index); - if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) - sw_if_index = swif->unnumbered_sw_if_index; - - /* - * Get the first ip4 address on the [client-side] - * RX interface, if not unnumbered. otherwise use - * the loopback interface's ip address. - */ - ia0 = ip4_interface_first_address (&ip4_main, sw_if_index, 0); - - if (ia0 == 0) - { - error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS; - next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_no_interface_address++; - goto do_trace; - } - - /* Add option 82 */ - o->option = 82; /* option 82 */ - o->length = 12; /* 12 octets to follow */ - o->data[0] = 1; /* suboption 1, circuit ID (=FIB id) */ - o->data[1] = 4; /* length of suboption */ - u32 *o_ifid = (u32 *) & o->data[2]; - *o_ifid = clib_host_to_net_u32 (original_sw_if_index); - o->data[6] = 5; /* suboption 5 (client RX intfc address) */ - o->data[7] = 4; /* length 4 */ - u32 *o_addr = (u32 *) & o->data[8]; - *o_addr = ia0->as_u32; - o->data[12] = DHCP_PACKET_OPTION_END; - - vss = dhcp_get_vss_info (dpm, fib_index, FIB_PROTOCOL_IP4); - if (vss) - { - u32 id_len; /* length of VPN ID */ - - if (vss->vss_type == VSS_TYPE_VPN_ID) - { - id_len = sizeof (vss->vpn_id); /* vpn_id is 7 bytes */ - memcpy (&o->data[15], vss->vpn_id, id_len); - } - else if (vss->vss_type == VSS_TYPE_ASCII) - { - id_len = vec_len (vss->vpn_ascii_id); - memcpy (&o->data[15], vss->vpn_ascii_id, id_len); - } - else /* must be VSS_TYPE_DEFAULT, no VPN ID */ - id_len = 0; - - o->data[12] = 151; /* vss suboption */ - o->data[13] = id_len + 1; /* length: vss_type + id_len */ - o->data[14] = vss->vss_type; /* vss option type */ - o->data[15 + id_len] = 152; /* vss control suboption */ - o->data[16 + id_len] = 0; /* length */ - o->data[17 + id_len] = DHCP_PACKET_OPTION_END; /* "end-of-options" (0xFF) */ - /* 5 bytes for suboption headers 151+len, 152+len and 0xFF */ - o->length += id_len + 5; - } - - len = o->length + 3; - b0->current_length += len; - /* Fix IP header length and checksum */ - old_l0 = ip0->length; - new_l0 = clib_net_to_host_u16 (old_l0); - new_l0 += len; - new_l0 = clib_host_to_net_u16 (new_l0); - ip0->length = new_l0; - sum0 = ip0->checksum; - sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, - length /* changed member */ ); - ip0->checksum = ip_csum_fold (sum0); - - /* Fix UDP length */ - new_l0 = clib_net_to_host_u16 (u0->length); - new_l0 += len; - u0->length = clib_host_to_net_u16 (new_l0); - } - else - { - vlib_node_increment_counter - (vm, dhcp_proxy_to_server_node.index, - DHCP_PROXY_ERROR_OPTION_82_ERROR, 1); - } - - next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP; - - /* - * If we have multiple servers configured and this is the - * client's discover message, then send copies to each of - * those servers - */ - if (is_discover && vec_len (proxy->dhcp_servers) > 1) - { - u32 ii; - - for (ii = 1; ii < vec_len (proxy->dhcp_servers); ii++) - { - vlib_buffer_t *c0; - u32 ci0; - - c0 = vlib_buffer_copy (vm, b0); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (c0); - ci0 = vlib_get_buffer_index (vm, c0); - server = &proxy->dhcp_servers[ii]; - - ip0 = vlib_buffer_get_current (c0); - - sum0 = ip0->checksum; - old0 = ip0->dst_address.as_u32; - new0 = server->dhcp_server.ip4.as_u32; - ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32; - sum0 = ip_csum_update (sum0, old0, new0, - ip4_header_t /* structure */ , - dst_address /* changed member */ ); - ip0->checksum = ip_csum_fold (sum0); - - to_next[0] = ci0; - to_next += 1; - n_left_to_next -= 1; - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - ci0, next0); - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_proxy_trace_t *tr; - - tr = vlib_add_trace (vm, node, c0, sizeof (*tr)); - tr->which = 0; /* to server */ - tr->error = error0; - tr->original_sw_if_index = original_sw_if_index; - tr->sw_if_index = sw_if_index; - if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP) - tr->trace_ip4_address.as_u32 = - server->dhcp_server.ip4.as_u32; - } - - if (PREDICT_FALSE (0 == n_left_to_next)) - { - vlib_put_next_frame (vm, node, next_index, - n_left_to_next); - vlib_get_next_frame (vm, node, next_index, - to_next, n_left_to_next); - } - } - } - do_trace: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->which = 0; /* to server */ - tr->error = error0; - tr->original_sw_if_index = original_sw_if_index; - tr->sw_if_index = sw_if_index; - if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP) - tr->trace_ip4_address.as_u32 = - proxy->dhcp_servers[0].dhcp_server.ip4.as_u32; - } - - do_enqueue: - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - 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_node_increment_counter (vm, dhcp_proxy_to_server_node.index, - DHCP_PROXY_ERROR_RELAY_TO_CLIENT, - pkts_to_client); - vlib_node_increment_counter (vm, dhcp_proxy_to_server_node.index, - DHCP_PROXY_ERROR_RELAY_TO_SERVER, - pkts_to_server); - vlib_node_increment_counter (vm, dhcp_proxy_to_server_node.index, - DHCP_PROXY_ERROR_NO_SERVER, pkts_no_server); - vlib_node_increment_counter (vm, dhcp_proxy_to_server_node.index, - DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS, - pkts_no_interface_address); - vlib_node_increment_counter (vm, dhcp_proxy_to_server_node.index, - DHCP_PROXY_ERROR_PKT_TOO_BIG, pkts_too_big); - return from_frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp_proxy_to_server_node, static) = { - .function = dhcp_proxy_to_server_input, - .name = "dhcp-proxy-to-server", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - - .n_errors = DHCP_PROXY_N_ERROR, - .error_strings = dhcp_proxy_error_strings, - - .n_next_nodes = DHCP_PROXY_TO_SERVER_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, - foreach_dhcp_proxy_to_server_input_next -#undef _ - }, - - .format_buffer = format_dhcp_proxy_header_with_length, - .format_trace = format_dhcp_proxy_trace, -#if 0 - .unformat_buffer = unformat_dhcp_proxy_header, -#endif -}; -/* *INDENT-ON* */ - -static uword -dhcp_proxy_to_client_input (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - u32 n_left_from, *from; - ethernet_main_t *em = vnet_get_ethernet_main (); - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - vnet_main_t *vnm = vnet_get_main (); - ip4_main_t *im = &ip4_main; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - while (n_left_from > 0) - { - u32 bi0; - vlib_buffer_t *b0; - udp_header_t *u0; - dhcp_header_t *h0; - ip4_header_t *ip0 = 0; - ip4_address_t *ia0 = 0; - u32 old0, new0; - ip_csum_t sum0; - ethernet_interface_t *ei0; - ethernet_header_t *mac0; - vnet_hw_interface_t *hi0; - vlib_frame_t *f0; - u32 *to_next0; - u32 sw_if_index = ~0; - vnet_sw_interface_t *si0; - u32 error0 = (u32) ~ 0; - vnet_sw_interface_t *swif; - u32 fib_index; - dhcp_proxy_t *proxy; - dhcp_server_t *server; - u32 original_sw_if_index = (u32) ~ 0; - ip4_address_t relay_addr = { - .as_u32 = 0, - }; - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - h0 = vlib_buffer_get_current (b0); - - /* - * udp_local hands us the DHCP header, need udp hdr, - * ip hdr to relay to client - */ - vlib_buffer_advance (b0, -(sizeof (*u0))); - u0 = vlib_buffer_get_current (b0); - - vlib_buffer_advance (b0, -(sizeof (*ip0))); - ip0 = vlib_buffer_get_current (b0); - - /* Consumed by dhcp client code? */ - if (dhcp_client_for_us (bi0, b0, ip0, u0, h0)) - continue; - - if (1 /* dpm->insert_option_82 */ ) - { - /* linearize needed to "unclone" and scan options */ - int rv = vlib_buffer_chain_linearize (vm, b0); - if ((b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0 || !rv) - { - error0 = DHCP_PROXY_ERROR_PKT_TOO_BIG; - goto drop_packet; - } - - dhcp_option_t *o = h0->options, *end = - (void *) vlib_buffer_get_tail (b0); - - /* Parse through TLVs looking for option 82. - The circuit-ID is the FIB number we need - to track down the client-facing interface */ - - while (o->option != DHCP_PACKET_OPTION_END && o < end) - { - if (o->option == 82) - { - u32 vss_exist = 0; - u32 vss_ctrl = 0; - dhcp_option_t *sub = (dhcp_option_t *) & o->data[0]; - dhcp_option_t *subend = - (dhcp_option_t *) (o->data + o->length); - while (sub->option != DHCP_PACKET_OPTION_END - && sub < subend) - { - /* If this is one of ours, it will have - total length 12, circuit-id suboption type, - and the sw_if_index */ - if (sub->option == 1 && sub->length == 4) - { - sw_if_index = ((sub->data[0] << 24) | - (sub->data[1] << 16) | - (sub->data[2] << 8) | - (sub->data[3])); - } - else if (sub->option == 5 && sub->length == 4) - { - relay_addr.as_u8[0] = sub->data[0]; - relay_addr.as_u8[1] = sub->data[1]; - relay_addr.as_u8[2] = sub->data[2]; - relay_addr.as_u8[3] = sub->data[3]; - } - else if (sub->option == 151 && - sub->length == 7 && sub->data[0] == 1) - vss_exist = 1; - else if (sub->option == 152 && sub->length == 0) - vss_ctrl = 1; - sub = (dhcp_option_t *) (sub->data + sub->length); - } - if (vss_ctrl && vss_exist) - vlib_node_increment_counter - (vm, dhcp_proxy_to_client_node.index, - DHCP_PROXY_ERROR_OPTION_82_VSS_NOT_PROCESSED, 1); - - } - o = (dhcp_option_t *) (o->data + o->length); - } - } - - if (sw_if_index == (u32) ~ 0) - { - error0 = DHCP_PROXY_ERROR_NO_OPTION_82; - - drop_packet: - vlib_node_increment_counter (vm, dhcp_proxy_to_client_node.index, - error0, 1); - f0 = vlib_get_frame_to_node (vm, dpm->error_drop_node_index); - to_next0 = vlib_frame_vector_args (f0); - to_next0[0] = bi0; - f0->n_vectors = 1; - vlib_put_frame_to_node (vm, dpm->error_drop_node_index, f0); - goto do_trace; - } - - if (relay_addr.as_u32 == 0) - { - error0 = DHCP_PROXY_ERROR_BAD_OPTION_82_ADDR; - goto drop_packet; - } - - if (sw_if_index >= vec_len (im->fib_index_by_sw_if_index)) - { - error0 = DHCP_PROXY_ERROR_BAD_OPTION_82_ITF; - goto drop_packet; - } - - fib_index = im->fib_index_by_sw_if_index[sw_if_index]; - proxy = dhcp_get_proxy (dpm, fib_index, FIB_PROTOCOL_IP4); - - if (PREDICT_FALSE (NULL == proxy)) - { - error0 = DHCP_PROXY_ERROR_NO_SERVER; - goto drop_packet; - } - - vec_foreach (server, proxy->dhcp_servers) - { - if (ip0->src_address.as_u32 == server->dhcp_server.ip4.as_u32) - { - goto server_found; - } - } - - error0 = DHCP_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS; - goto drop_packet; - - server_found: - vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index; - - swif = vnet_get_sw_interface (vnm, sw_if_index); - original_sw_if_index = sw_if_index; - if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) - sw_if_index = swif->unnumbered_sw_if_index; - - ia0 = ip4_interface_first_address (&ip4_main, sw_if_index, 0); - if (ia0 == 0) - { - error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS; - goto drop_packet; - } - - if (relay_addr.as_u32 != ia0->as_u32) - { - error0 = DHCP_PROXY_ERROR_BAD_YIADDR; - goto drop_packet; - } - - u0->checksum = 0; - u0->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client); - sum0 = ip0->checksum; - old0 = ip0->dst_address.as_u32; - new0 = 0xFFFFFFFF; - ip0->dst_address.as_u32 = new0; - sum0 = ip_csum_update (sum0, old0, new0, ip4_header_t /* structure */ , - dst_address /* offset of changed member */ ); - ip0->checksum = ip_csum_fold (sum0); - - sum0 = ip0->checksum; - old0 = ip0->src_address.as_u32; - new0 = ia0->as_u32; - ip0->src_address.as_u32 = new0; - sum0 = ip_csum_update (sum0, old0, new0, ip4_header_t /* structure */ , - src_address /* offset of changed member */ ); - ip0->checksum = ip_csum_fold (sum0); - - vlib_buffer_advance (b0, -(sizeof (ethernet_header_t))); - si0 = vnet_get_sw_interface (vnm, original_sw_if_index); - if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) - vlib_buffer_advance (b0, -4 /* space for VLAN tag */ ); - - mac0 = vlib_buffer_get_current (b0); - - hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index); - ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance); - clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address)); - clib_memset (mac0->dst_address, 0xff, sizeof (mac0->dst_address)); - mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ? - clib_net_to_host_u16 (0x8100) : clib_net_to_host_u16 (0x0800); - - if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) - { - u32 *vlan_tag = (u32 *) (mac0 + 1); - u32 tmp; - tmp = (si0->sub.id << 16) | 0x0800; - *vlan_tag = clib_host_to_net_u32 (tmp); - } - - /* $$$ This needs to be rewritten, for sure */ - f0 = vlib_get_frame_to_node (vm, hi0->output_node_index); - to_next0 = vlib_frame_vector_args (f0); - to_next0[0] = bi0; - f0->n_vectors = 1; - vlib_put_frame_to_node (vm, hi0->output_node_index, f0); - - do_trace: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->which = 1; /* to client */ - tr->trace_ip4_address.as_u32 = ia0 ? ia0->as_u32 : 0; - tr->error = error0; - tr->original_sw_if_index = original_sw_if_index; - tr->sw_if_index = sw_if_index; - } - } - - return from_frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp_proxy_to_client_node, static) = { - .function = dhcp_proxy_to_client_input, - .name = "dhcp-proxy-to-client", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - - .n_errors = DHCP_PROXY_N_ERROR, - .error_strings = dhcp_proxy_error_strings, - .format_buffer = format_dhcp_proxy_header_with_length, - .format_trace = format_dhcp_proxy_trace, -#if 0 - .unformat_buffer = unformat_dhcp_proxy_header, -#endif -}; -/* *INDENT-ON* */ - -void -dhcp_maybe_register_udp_ports (dhcp_port_reg_flags_t ports) -{ - dhcp_proxy_main_t *dm = &dhcp_proxy_main; - vlib_main_t *vm = dm->vlib_main; - int port_regs_diff = dm->udp_ports_registered ^ ports; - - if (!port_regs_diff) - return; - - if ((port_regs_diff & DHCP_PORT_REG_CLIENT) & ports) - udp_register_dst_port (vm, UDP_DST_PORT_dhcp_to_client, - dhcp_proxy_to_client_node.index, 1 /* is_ip4 */ ); - - if ((port_regs_diff & DHCP_PORT_REG_SERVER) & ports) - udp_register_dst_port (vm, UDP_DST_PORT_dhcp_to_server, - dhcp_proxy_to_server_node.index, 1 /* is_ip4 */ ); - - dm->udp_ports_registered |= ports; -} - -static clib_error_t * -dhcp4_proxy_init (vlib_main_t * vm) -{ - dhcp_proxy_main_t *dm = &dhcp_proxy_main; - vlib_node_t *error_drop_node; - - error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop"); - dm->error_drop_node_index = error_drop_node->index; - dm->vlib_main = vm; - - return 0; -} - - -VLIB_INIT_FUNCTION (dhcp4_proxy_init); - -int -dhcp4_proxy_set_server (ip46_address_t * addr, - ip46_address_t * src_addr, - u32 rx_table_id, u32 server_table_id, int is_del) -{ - u32 rx_fib_index = 0; - int rc = 0; - - const fib_prefix_t all_1s = { - .fp_len = 32, - .fp_addr.ip4.as_u32 = 0xffffffff, - .fp_proto = FIB_PROTOCOL_IP4, - }; - - if (ip46_address_is_zero (addr)) - return VNET_API_ERROR_INVALID_DST_ADDRESS; - - if (ip46_address_is_zero (src_addr)) - return VNET_API_ERROR_INVALID_SRC_ADDRESS; - - dhcp_maybe_register_udp_ports (DHCP_PORT_REG_CLIENT | DHCP_PORT_REG_SERVER); - - rx_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, - rx_table_id, - FIB_SOURCE_DHCP); - - if (is_del) - { - if (dhcp_proxy_server_del (FIB_PROTOCOL_IP4, rx_fib_index, - addr, server_table_id)) - { - fib_table_entry_special_remove (rx_fib_index, - &all_1s, FIB_SOURCE_DHCP); - fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP); - } - } - else - { - if (dhcp_proxy_server_add (FIB_PROTOCOL_IP4, - addr, src_addr, - rx_fib_index, server_table_id)) - { - fib_table_entry_special_add (rx_fib_index, - &all_1s, - FIB_SOURCE_DHCP, FIB_ENTRY_FLAG_LOCAL); - fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP); - } - } - fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP); - - return (rc); -} - -static clib_error_t * -dhcp4_proxy_set_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ip46_address_t server_addr, src_addr; - u32 server_table_id = 0, rx_table_id = 0; - int is_del = 0; - int set_src = 0, set_server = 0; - - clib_memset (&server_addr, 0, sizeof (server_addr)); - clib_memset (&src_addr, 0, sizeof (src_addr)); - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "server %U", - unformat_ip4_address, &server_addr.ip4)) - set_server = 1; - else if (unformat (input, "server-fib-id %d", &server_table_id)) - ; - else if (unformat (input, "rx-fib-id %d", &rx_table_id)) - ; - else if (unformat (input, "src-address %U", - unformat_ip4_address, &src_addr.ip4)) - set_src = 1; - else if (unformat (input, "delete") || unformat (input, "del")) - is_del = 1; - else - break; - } - - if (is_del || (set_server && set_src)) - { - int rv; - - rv = dhcp4_proxy_set_server (&server_addr, &src_addr, rx_table_id, - server_table_id, is_del); - switch (rv) - { - case 0: - return 0; - - case VNET_API_ERROR_INVALID_DST_ADDRESS: - return clib_error_return (0, "Invalid server address"); - - case VNET_API_ERROR_INVALID_SRC_ADDRESS: - return clib_error_return (0, "Invalid src address"); - - case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return - (0, "Fib id %d: no per-fib DHCP server configured", rx_table_id); - - default: - return clib_error_return (0, "BUG: rv %d", rv); - } - } - else - return clib_error_return (0, "parse error`%U'", - format_unformat_error, input); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp_proxy_set_command, static) = { - .path = "set dhcp proxy", - .short_help = "set dhcp proxy [del] server <ip-addr> src-address <ip-addr> [server-fib-id <n>] [rx-fib-id <n>]", - .function = dhcp4_proxy_set_command_fn, -}; -/* *INDENT-ON* */ - -static u8 * -format_dhcp4_proxy_server (u8 * s, va_list * args) -{ - dhcp_proxy_t *proxy = va_arg (*args, dhcp_proxy_t *); - ip4_fib_t *rx_fib, *server_fib; - dhcp_server_t *server; - - if (proxy == 0) - { - s = format (s, "%=14s%=16s%s", "RX FIB", "Src Address", - "Servers FIB,Address"); - return s; - } - - rx_fib = ip4_fib_get (proxy->rx_fib_index); - - s = format (s, "%=14u%=16U", - rx_fib->table_id, - format_ip46_address, &proxy->dhcp_src_address, IP46_TYPE_ANY); - - vec_foreach (server, proxy->dhcp_servers) - { - server_fib = ip4_fib_get (server->server_fib_index); - s = format (s, "%u,%U ", - server_fib->table_id, - format_ip46_address, &server->dhcp_server, IP46_TYPE_ANY); - } - return s; -} - -static int -dhcp4_proxy_show_walk (dhcp_proxy_t * server, void *ctx) -{ - vlib_main_t *vm = ctx; - - vlib_cli_output (vm, "%U", format_dhcp4_proxy_server, server); - - return (1); -} - -static clib_error_t * -dhcp4_proxy_show_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "%U", format_dhcp4_proxy_server, - NULL /* header line */ ); - - dhcp_proxy_walk (FIB_PROTOCOL_IP4, dhcp4_proxy_show_walk, vm); - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp_proxy_show_command, static) = { - .path = "show dhcp proxy", - .short_help = "Display dhcp proxy server info", - .function = dhcp4_proxy_show_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcp_option_82_vss_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u8 is_del = 0, vss_type = VSS_TYPE_DEFAULT; - u32 oui = 0, fib_id = 0, tbl_id = ~0; - u8 *vpn_ascii_id = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "table %d", &tbl_id)) - ; - else if (unformat (input, "oui %d", &oui)) - vss_type = VSS_TYPE_VPN_ID; - else if (unformat (input, "vpn-id %d", &fib_id)) - vss_type = VSS_TYPE_VPN_ID; - else if (unformat (input, "vpn-ascii-id %s", &vpn_ascii_id)) - vss_type = VSS_TYPE_ASCII; - else if (unformat (input, "delete") || unformat (input, "del")) - is_del = 1; - else - break; - } - - if (tbl_id == ~0) - return clib_error_return (0, "no table ID specified."); - - int rv = dhcp_proxy_set_vss (FIB_PROTOCOL_IP4, tbl_id, vss_type, - vpn_ascii_id, oui, fib_id, is_del); - switch (rv) - { - case 0: - return 0; - case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, - "option 82 vss for table %d not found in in pool.", - tbl_id); - default: - return clib_error_return (0, "BUG: rv %d", rv); - - } -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp_proxy_vss_command,static) = { - .path = "set dhcp option-82 vss", - .short_help = "set dhcp option-82 vss [del] table <table id> [oui <n> vpn-id <n> | vpn-ascii-id <text>]", - .function = dhcp_option_82_vss_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcp_vss_show_command_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - dhcp_vss_walk (FIB_PROTOCOL_IP4, dhcp_vss_show_walk, vm); - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp_proxy_vss_show_command, static) = { - .path = "show dhcp vss", - .short_help = "show dhcp VSS", - .function = dhcp_vss_show_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcp_option_82_address_show_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - u32 sw_if_index0 = 0, sw_if_index; - vnet_sw_interface_t *swif; - ip4_address_t *ia0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - - if (unformat (input, "%U", - unformat_vnet_sw_interface, vnm, &sw_if_index0)) - { - swif = vnet_get_sw_interface (vnm, sw_if_index0); - sw_if_index = (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) ? - swif->unnumbered_sw_if_index : sw_if_index0; - ia0 = ip4_interface_first_address (&ip4_main, sw_if_index, 0); - if (ia0) - { - vlib_cli_output (vm, "%=20s%=20s", "interface", - "source IP address"); - - vlib_cli_output (vm, "%=20U%=20U", - format_vnet_sw_if_index_name, - vnm, sw_if_index0, format_ip4_address, ia0); - } - else - vlib_cli_output (vm, "%=34s %=20U", - "No IPv4 address configured on", - format_vnet_sw_if_index_name, vnm, sw_if_index); - } - else - break; - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp_proxy_address_show_command,static) = { - .path = "show dhcp option-82-address interface", - .short_help = "show dhcp option-82-address interface <interface>", - .function = dhcp_option_82_address_show_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_client_common_dp.c b/src/vnet/dhcp/dhcp6_client_common_dp.c deleted file mode 100644 index 7ca3b61defb..00000000000 --- a/src/vnet/dhcp/dhcp6_client_common_dp.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (c) 2018 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 <vnet/ethernet/ethernet.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> -#include <vnet/dhcp/dhcp6_ia_na_client_dp.h> -#include <vnet/dhcp/dhcp6_pd_client_dp.h> -#include <vnet/dhcp/dhcp6_packet.h> -#include <vnet/udp/udp.h> - -dhcp6_client_common_main_t dhcp6_client_common_main; -dhcpv6_duid_ll_string_t client_duid; - -u32 -server_index_get_or_create (u8 * data, u16 len) -{ - dhcp6_client_common_main_t *ccm = &dhcp6_client_common_main; - u32 i; - server_id_t *se; - server_id_t new_se; - - for (i = 0; i < vec_len (ccm->server_ids); i++) - { - se = &ccm->server_ids[i]; - if (se->len == len && 0 == memcmp (se->data, data, len)) - return i; - } - - new_se.len = len; - new_se.data = 0; - vec_validate (new_se.data, len - 1); - memcpy (new_se.data, data, len); - - vec_add1 (ccm->server_ids, new_se); - - return vec_len (ccm->server_ids) - 1; -} - -void -vl_api_dhcp6_duid_ll_set_t_handler (vl_api_dhcp6_duid_ll_set_t * mp) -{ - vl_api_dhcp6_duid_ll_set_reply_t *rmp; - dhcpv6_duid_ll_string_t *duid; - int rv = 0; - - duid = (dhcpv6_duid_ll_string_t *) mp->duid_ll; - if (duid->duid_type != htonl (DHCPV6_DUID_LL)) - { - rv = VNET_API_ERROR_INVALID_VALUE; - goto reply; - } - clib_memcpy (&client_duid, &duid, sizeof (client_duid)); - -reply: - REPLY_MACRO (VL_API_DHCP6_DUID_LL_SET_REPLY); -} - -static void -generate_client_duid (void) -{ - client_duid.duid_type = htons (DHCPV6_DUID_LL); - client_duid.hardware_type = htons (1); - - vnet_main_t *vnm = vnet_get_main (); - vnet_interface_main_t *im = &vnm->interface_main; - vnet_hw_interface_t *hi; - ethernet_interface_t *eth_if = 0; - - /* *INDENT-OFF* */ - pool_foreach (hi, im->hw_interfaces, - ({ - eth_if = ethernet_get_interface (ðernet_main, hi->hw_if_index); - if (eth_if) - break; - })); - /* *INDENT-ON* */ - - if (eth_if) - clib_memcpy (client_duid.lla, eth_if->address, 6); - else - { - clib_warning ("Failed to find any Ethernet interface, " - "setting DHCPv6 DUID link-layer address to random value"); - u32 seed = random_default_seed (); - random_u32 (&seed); - client_duid.lla[0] = 0xc2; /* locally administered unicast */ - client_duid.lla[1] = 0x18; - client_duid.lla[2] = 0x44; - client_duid.lla[3] = random_u32 (&seed); - client_duid.lla[4] = random_u32 (&seed); - client_duid.lla[5] = random_u32 (&seed); - } -} - -#define foreach_dhcpv6_client \ - _(DROP, "error-drop") \ - _(LOOKUP, "ip6-lookup") - -typedef enum -{ -#define _(sym,str) DHCPV6_CLIENT_NEXT_##sym, - foreach_dhcpv6_client -#undef _ - DHCPV6_CLIENT_N_NEXT, -} dhcpv6_client_next_t; - -/** - * per-packet trace data - */ -typedef struct dhcpv6_client_trace_t_ -{ -} dhcpv6_client_trace_t; - -static u8 * -format_dhcpv6_client_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 *); - //dhcpv6_client_trace_t *t = va_arg (*args, dhcpv6_client_trace_t *); - - s = format (s, "nothing"); - - return s; -} - -static uword -dhcpv6_client_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - dhcp6_ia_na_client_main_t *icm = &dhcp6_ia_na_client_main; - dhcp6_pd_client_main_t *pcm = &dhcp6_pd_client_main; - - dhcpv6_client_next_t next_index; - u32 n_left_from, *from, *to_next; - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - - 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 > 0 && n_left_to_next > 0) - { - ip6_header_t *ip0; - u32 options_length; - dhcpv6_header_t *dhcpv60; - dhcpv6_option_t *option; - vlib_buffer_t *b0; - dhcp6_report_common_t report; - dhcp6_address_info_t *addresses = 0; - dhcp6_prefix_info_t *prefixes = 0; - u32 next0 = DHCPV6_CLIENT_NEXT_DROP; - u32 bi0; - u32 xid; - u32 sw_if_index; - u32 iaid; - u8 client_id_present = 0; - u8 discard = 0; - u8 is_pd_packet = 0; - - dhcp6_ia_na_client_state_t *ia_na_client_state = NULL; - dhcp6_pd_client_state_t *pd_client_state = NULL; - - 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); - - dhcpv60 = vlib_buffer_get_current (b0); - ip0 = (void *) (b0->data + vnet_buffer (b0)->l3_hdr_offset); - u32 dhcpv6_ip6_payload_offset = - (u8 *) dhcpv60 - ((u8 *) ip0 + sizeof (*ip0)); - options_length = - ntohs (ip0->payload_length) - dhcpv6_ip6_payload_offset - - sizeof (*dhcpv60); - - clib_memset (&report, 0, sizeof (report)); - - sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - if (sw_if_index >= vec_len (icm->client_state_by_sw_if_index)) - ia_na_client_state = 0; - else - ia_na_client_state = - &icm->client_state_by_sw_if_index[sw_if_index]; - if (sw_if_index >= vec_len (pcm->client_state_by_sw_if_index)) - pd_client_state = 0; - else - pd_client_state = &pcm->client_state_by_sw_if_index[sw_if_index]; - - xid = - (dhcpv60->xid[0] << 16) + (dhcpv60->xid[1] << 8) + - dhcpv60->xid[2]; - if (ia_na_client_state && ia_na_client_state->transaction_id == xid) - is_pd_packet = 0; - else if (pd_client_state && pd_client_state->transaction_id == xid) - is_pd_packet = 1; - else - { - clib_warning - ("Received DHCPv6 message with wrong Transaction ID"); - discard = 1; - } - - report.sw_if_index = sw_if_index; - report.msg_type = dhcpv60->msg_type; - report.server_index = ~0; - - switch (dhcpv60->msg_type) - { - case DHCPV6_MSG_ADVERTISE: - case DHCPV6_MSG_REPLY: - option = (dhcpv6_option_t *) (dhcpv60 + 1); - while (options_length > 0) - { - if (options_length < - ntohs (option->length) + sizeof (*option)) - { - clib_warning - ("remaining payload length < option length (%d < %d)", - options_length, - ntohs (option->length) + sizeof (*option)); - break; - } - u16 oo = ntohs (option->option); - if (oo == DHCPV6_OPTION_IA_NA || oo == DHCPV6_OPTION_IA_PD) - { - u8 discard_option = 0; - dhcpv6_ia_header_t *ia_header = (void *) option; - iaid = ntohl (ia_header->iaid); - u32 T1 = ntohl (ia_header->t1); - u32 T2 = ntohl (ia_header->t2); - if (iaid != DHCPV6_CLIENT_IAID) - discard_option = 1; - if (T1 != 0 && T2 != 0 && T1 > T2) - discard_option = 1; - if (!discard_option) - { - report.T1 = T1; - report.T2 = T2; - } - dhcpv6_option_t *inner_option = - (void *) ia_header->data; - u16 inner_options_length = - ntohs (option->length) - (sizeof (*ia_header) - - sizeof (dhcpv6_option_t)); - while (inner_options_length > 0) - { - u16 inner_oo = ntohs (inner_option->option); - if (discard_option) - ; - else if (inner_oo == DHCPV6_OPTION_IAADDR) - { - dhcpv6_ia_opt_addr_t *iaaddr = - (void *) inner_option; - u32 n_addresses = vec_len (addresses); - vec_validate (addresses, n_addresses); - dhcp6_address_info_t *address_info = - &addresses[n_addresses]; - address_info->preferred_time = - ntohl (iaaddr->preferred); - address_info->valid_time = - ntohl (iaaddr->valid); - address_info->address = iaaddr->addr; - } - else if (inner_oo == DHCPV6_OPTION_IAPREFIX) - { - dhcpv6_ia_opt_pd_t *iaprefix = - (void *) inner_option; - u32 n_prefixes = vec_len (prefixes); - vec_validate (prefixes, n_prefixes); - dhcp6_prefix_info_t *prefix_info = - &prefixes[n_prefixes]; - prefix_info->preferred_time = - ntohl (iaprefix->preferred); - prefix_info->valid_time = - ntohl (iaprefix->valid); - prefix_info->prefix_length = iaprefix->prefix; - prefix_info->prefix = iaprefix->addr; - } - else if (inner_oo == DHCPV6_OPTION_STATUS_CODE) - { - dhcpv6_status_code_t *sc = - (void *) inner_option; - report.inner_status_code = - ntohs (sc->status_code); - } - inner_options_length -= - sizeof (*inner_option) + - ntohs (inner_option->length); - inner_option = - (void *) ((u8 *) inner_option + - sizeof (*inner_option) + - ntohs (inner_option->length)); - } - } - else if (oo == DHCPV6_OPTION_CLIENTID) - { - if (client_id_present) - { - clib_warning - ("Duplicate Client ID in received DHVPv6 message"); - discard = 1; - } - else - { - u16 len = ntohs (option->length); - client_id_present = 1; - if (len != CLIENT_DUID_LENGTH || - 0 != memcmp (option->data, - client_duid.bin_string, - CLIENT_DUID_LENGTH)) - { - clib_warning - ("Unrecognized client DUID inside received DHVPv6 message"); - discard = 1; - } - } - } - else if (oo == DHCPV6_OPTION_SERVERID) - { - if (report.server_index != ~0) - { - clib_warning - ("Duplicate Server ID in received DHVPv6 message"); - discard = 1; - } - else - { - u16 ol = ntohs (option->length); - if (ol - 2 /* 2 byte DUID type code */ > 128) - { - clib_warning - ("Server DUID (without type code) is longer than 128 octets"); - discard = 1; - } - else - { - report.server_index = - server_index_get_or_create (option->data, ol); - } - } - } - else if (oo == DHCPV6_OPTION_PREFERENCE) - { - report.preference = option->data[0]; - } - else if (oo == DHCPV6_OPTION_STATUS_CODE) - { - dhcpv6_status_code_t *sc = (void *) option; - report.status_code = ntohs (sc->status_code); - } - options_length -= sizeof (*option) + ntohs (option->length); - option = - (void *) ((u8 *) option + sizeof (*option) + - ntohs (option->length)); - } - - if (!client_id_present) - { - clib_warning - ("Missing Client ID in received DHVPv6 message"); - discard = 1; - } - if (report.server_index == ~0) - { - clib_warning - ("Missing Server ID in received DHVPv6 message"); - discard = 1; - } - - if (!discard) - { - if (!is_pd_packet) - { - address_report_t r; - r.body = report; - r.n_addresses = vec_len (addresses); - r.addresses = addresses; - dhcp6_publish_report (&r); - /* We just gave addresses to another process! */ - addresses = 0; - } - else - { - prefix_report_t r; - r.body = report; - r.n_prefixes = vec_len (prefixes); - r.prefixes = prefixes; - dhcp6_pd_publish_report (&r); - /* We just gave prefixes to another process! */ - prefixes = 0; - } - } - vec_free (addresses); - vec_free (prefixes); - - break; - default: - break; - } - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcpv6_client_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - } - - /* verify speculative enqueue, maybe switch current next frame */ - 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); - } - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcpv6_client_node, static) = { - .function = dhcpv6_client_node_fn, - .name = "dhcpv6-client", - .vector_size = sizeof (u32), - - .n_errors = 0, - - .n_next_nodes = DHCPV6_CLIENT_N_NEXT, - .next_nodes = { - #define _(s,n) [DHCPV6_CLIENT_NEXT_##s] = n, - foreach_dhcpv6_client - #undef _ - }, - - .format_trace = format_dhcpv6_client_trace, -}; -/* *INDENT-ON* */ - -void -dhcp6_clients_enable_disable (u8 enable) -{ - vlib_main_t *vm = vlib_get_main (); - - if (enable) - { - if (client_duid.duid_type == 0) - generate_client_duid (); - udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client, - dhcpv6_client_node.index, 0 /* is_ip6 */ ); - } - else - udp_unregister_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client, - 0 /* is_ip6 */ ); -} - -void - vl_api_dhcp6_clients_enable_disable_t_handler - (vl_api_dhcp6_clients_enable_disable_t * mp) -{ - vl_api_dhcp6_clients_enable_disable_reply_t *rmp; - int rv = 0; - - dhcp6_clients_enable_disable (mp->enable); - - REPLY_MACRO (VL_API_DHCP6_CLIENTS_ENABLE_DISABLE_REPLY); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_client_common_dp.h b/src/vnet/dhcp/dhcp6_client_common_dp.h deleted file mode 100644 index 0acef8408c6..00000000000 --- a/src/vnet/dhcp/dhcp6_client_common_dp.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2018 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_vnet_dhcp6_client_common_dp_h -#define included_vnet_dhcp6_client_common_dp_h - -#include <vlib/vlib.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> -#include <vnet/dhcp/dhcp6_packet.h> -#include <vnet/vnet_msg_enum.h> -#include <vlibapi/api_common.h> -#include <vlibmemory/api.h> - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include <vnet/vnet_all_api_h.h> -#undef vl_printfun - -#include <vlibapi/api_helper_macros.h> - -typedef struct -{ - u32 sw_if_index; - u32 server_index; - u8 msg_type; - u32 T1; - u32 T2; - u16 inner_status_code; - u16 status_code; - u8 preference; -} dhcp6_report_common_t; - -typedef struct -{ - u8 *data; - u16 len; -} server_id_t; - -typedef struct -{ - server_id_t *server_ids; -} dhcp6_client_common_main_t; - -extern dhcp6_client_common_main_t dhcp6_client_common_main; - -typedef union -{ - CLIB_PACKED (struct - { - u16 duid_type; - u16 hardware_type; - u8 lla[6]; - }); - char bin_string[10]; -} dhcpv6_duid_ll_string_t; - -extern dhcpv6_duid_ll_string_t client_duid; -#define CLIENT_DUID_LENGTH sizeof (client_duid) -#define DHCPV6_CLIENT_IAID 1 - -void dhcp6_clients_enable_disable (u8 enable); -u32 server_index_get_or_create (u8 * data, u16 len); - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -void vl_api_dhcp6_duid_ll_set_t_handler (vl_api_dhcp6_duid_ll_set_t * mp); - -static_always_inline f64 -random_f64_from_to (f64 from, f64 to) -{ - static u32 seed = 0; - static u8 seed_set = 0; - if (!seed_set) - { - seed = random_default_seed (); - seed_set = 1; - } - return random_f64 (&seed) * (to - from) + from; -} - -static const ip6_address_t all_dhcp6_relay_agents_and_servers = { - .as_u8 = { - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02} -}; - -#endif /* included_vnet_dhcp6_client_common_dp_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_ia_na_client_cp.api b/src/vnet/dhcp/dhcp6_ia_na_client_cp.api deleted file mode 100644 index caa4fd4afc8..00000000000 --- a/src/vnet/dhcp/dhcp6_ia_na_client_cp.api +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -option version = "1.0.1"; - -import "vnet/interface_types.api"; - -/** \brief Enable/disable DHCPv6 client on interface - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - interface to enable/disable client on - @param enable - 1 to enable, 0 to disable -*/ -autoreply define dhcp6_client_enable_disable -{ - u32 client_index; - u32 context; - vl_api_interface_index_t sw_if_index; - bool enable; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_ia_na_client_cp.c b/src/vnet/dhcp/dhcp6_ia_na_client_cp.c deleted file mode 100644 index e440805d707..00000000000 --- a/src/vnet/dhcp/dhcp6_ia_na_client_cp.c +++ /dev/null @@ -1,837 +0,0 @@ -/* - * Copyright (c) 2018 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 <vnet/vnet.h> -#include <vlibmemory/api.h> -#include <vnet/vnet_msg_enum.h> -#include <vnet/dhcp/dhcp6_packet.h> -#include <vnet/dhcp/dhcp6_ia_na_client_dp.h> -#include <vnet/ip/ip.h> -#include <vnet/ip/ip6.h> -#include <float.h> -#include <math.h> - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -#include <vlibapi/api_helper_macros.h> - -#define foreach_dhcp6_client_cp_msg \ -_(DHCP6_CLIENT_ENABLE_DISABLE, dhcp6_client_enable_disable) - -#define vl_api_dhcp6_client_enable_disable_t_print vl_noop_handler - -typedef struct -{ - u32 sw_if_index; - ip6_address_t address; - u32 preferred_lt; - u32 valid_lt; - f64 due_time; -} address_info_t; - -typedef struct -{ - u8 enabled; - u32 server_index; - u32 T1; - u32 T2; - f64 T1_due_time; - f64 T2_due_time; - u32 address_count; - u8 rebinding; -} client_state_t; - -typedef struct -{ - address_info_t *address_pool; - client_state_t *client_state_by_sw_if_index; - u32 n_clients; - f64 max_valid_due_time; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - api_main_t *api_main; - u32 node_index; -} dhcp6_client_cp_main_t; - -static dhcp6_client_cp_main_t dhcp6_client_cp_main; - -enum -{ - RD_CP_EVENT_INTERRUPT, - RD_CP_EVENT_DISABLE, -}; - -static void -send_client_message_start_stop (u32 sw_if_index, u32 server_index, - u8 msg_type, address_info_t * address_list, - u8 start) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - dhcp6_send_client_message_params_t params = { 0, }; - dhcp6_send_client_message_params_address_t *addresses = 0, *addr; - u32 i; - - ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) && - rm->client_state_by_sw_if_index[sw_if_index].enabled); - client_state_t *client_state = - &rm->client_state_by_sw_if_index[sw_if_index]; - - params.sw_if_index = sw_if_index; - params.server_index = server_index; - params.msg_type = msg_type; - if (start) - { - if (msg_type == DHCPV6_MSG_SOLICIT) - { - params.irt = 1; - params.mrt = 120; - } - else if (msg_type == DHCPV6_MSG_REQUEST) - { - params.irt = 1; - params.mrt = 30; - params.mrc = 10; - } - else if (msg_type == DHCPV6_MSG_RENEW) - { - params.irt = 10; - params.mrt = 600; - f64 current_time = vlib_time_now (rm->vlib_main); - i32 diff_time = client_state->T2 - current_time; - if (diff_time < 0) - diff_time = 0; - params.mrd = diff_time; - } - else if (msg_type == DHCPV6_MSG_REBIND) - { - params.irt = 10; - params.mrt = 600; - f64 current_time = vlib_time_now (rm->vlib_main); - i32 diff_time = rm->max_valid_due_time - current_time; - if (diff_time < 0) - diff_time = 0; - params.mrd = diff_time; - } - else if (msg_type == DHCPV6_MSG_RELEASE) - { - params.mrc = 1; - } - } - - params.T1 = 0; - params.T2 = 0; - if (vec_len (address_list) != 0) - vec_validate (addresses, vec_len (address_list) - 1); - for (i = 0; i < vec_len (address_list); i++) - { - address_info_t *address = &address_list[i]; - addr = &addresses[i]; - addr->valid_lt = address->valid_lt; - addr->preferred_lt = address->preferred_lt; - addr->address = address->address; - } - params.addresses = addresses; - - dhcp6_send_client_message (rm->vlib_main, sw_if_index, !start, ¶ms); - - vec_free (params.addresses); -} - -static void interrupt_process (void); - -static u32 -ip6_enable (u32 sw_if_index) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - clib_error_t *rv; - - rv = enable_ip6_interface (rm->vlib_main, sw_if_index); - - return rv != 0; -} - -static u8 -ip6_addresses_equal (ip6_address_t * address1, ip6_address_t * address2) -{ - if (address1->as_u64[0] != address2->as_u64[0]) - return 0; - return address1->as_u64[1] == address2->as_u64[1]; -} - -static clib_error_t * -dhcp6_reply_event_handler (vl_api_dhcp6_reply_event_t * mp) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - client_state_t *client_state; - ip6_address_t *address; - u32 sw_if_index; - u32 n_addresses; - vl_api_dhcp6_address_info_t *api_address; - u32 inner_status_code; - u32 status_code; - u32 server_index; - f64 current_time; - clib_error_t *error = 0; - u32 i; - - current_time = vlib_time_now (vm); - - sw_if_index = ntohl (mp->sw_if_index); - - if (sw_if_index >= vec_len (rm->client_state_by_sw_if_index)) - return 0; - - client_state = &rm->client_state_by_sw_if_index[sw_if_index]; - - if (!client_state->enabled) - return 0; - - server_index = ntohl (mp->server_index); - - n_addresses = ntohl (mp->n_addresses); - - inner_status_code = ntohs (mp->inner_status_code); - status_code = ntohs (mp->status_code); - - if (mp->msg_type == DHCPV6_MSG_API_ADVERTISE - && client_state->server_index == ~0) - { - address_info_t *address_list = 0, *address_info; - - if (inner_status_code == DHCPV6_STATUS_NOADDRS_AVAIL) - { - clib_warning - ("Advertise message arrived with NoAddrsAvail status code"); - return 0; - } - - if (n_addresses > 0) - vec_validate (address_list, n_addresses - 1); - for (i = 0; i < n_addresses; i++) - { - api_address = &mp->addresses[i]; - address = (ip6_address_t *) api_address->address; - - address_info = &address_list[i]; - address_info->address = *address; - address_info->preferred_lt = 0; - address_info->valid_lt = 0; - } - - client_state->server_index = server_index; - - send_client_message_start_stop (sw_if_index, server_index, - DHCPV6_MSG_REQUEST, address_list, 1); - vec_free (address_list); - } - - if (mp->msg_type != DHCPV6_MSG_API_REPLY) - return 0; - - if (!client_state->rebinding && client_state->server_index != server_index) - { - clib_warning ("Reply message arrived with Server ID different " - "from that in Request or Renew message"); - return 0; - } - - if (inner_status_code == DHCPV6_STATUS_NOADDRS_AVAIL) - { - clib_warning ("Reply message arrived with NoAddrsAvail status code"); - if (n_addresses > 0) - { - clib_warning - ("Invalid Reply message arrived: It contains NoAddrsAvail " - "status code but also contains addresses"); - return 0; - } - } - - if (status_code == DHCPV6_STATUS_UNSPEC_FAIL) - { - clib_warning ("Reply message arrived with UnspecFail status code"); - return 0; - } - - send_client_message_start_stop (sw_if_index, server_index, - mp->msg_type, 0, 0); - - for (i = 0; i < n_addresses; i++) - { - address_info_t *address_info = 0; - u32 valid_time; - u32 preferred_time; - - api_address = &mp->addresses[i]; - - address = (ip6_address_t *) api_address->address; - - if (ip6_address_is_link_local_unicast (address)) - continue; - - valid_time = ntohl (api_address->valid_time); - preferred_time = ntohl (api_address->preferred_time); - - if (preferred_time > valid_time) - continue; - - u8 address_already_present = 0; - /* *INDENT-OFF* */ - pool_foreach (address_info, rm->address_pool, - ({ - if (address_info->sw_if_index != sw_if_index) - ; - else if (!ip6_addresses_equal (&address_info->address, address)) - ; - else - { - address_already_present = 1; - goto address_pool_foreach_out; - } - })); - /* *INDENT-ON* */ - address_pool_foreach_out: - - if (address_already_present) - { - address_info->preferred_lt = preferred_time; - address_info->valid_lt = valid_time; - address_info->due_time = current_time + valid_time; - if (address_info->due_time > rm->max_valid_due_time) - rm->max_valid_due_time = address_info->due_time; - continue; - } - - if (valid_time == 0) - continue; - - pool_get (rm->address_pool, address_info); - address_info->sw_if_index = sw_if_index; - address_info->address = *address; - address_info->preferred_lt = preferred_time; - address_info->valid_lt = valid_time; - address_info->due_time = current_time + valid_time; - if (address_info->due_time > rm->max_valid_due_time) - rm->max_valid_due_time = address_info->due_time; - rm->client_state_by_sw_if_index[sw_if_index].address_count++; - - error = ip6_add_del_interface_address (vm, sw_if_index, - &address_info->address, 64, 0); - if (error) - clib_warning ("Failed to add interface address"); - } - - client_state->server_index = server_index; - client_state->T1 = ntohl (mp->T1); - client_state->T2 = ntohl (mp->T2); - if (client_state->T1 != 0) - client_state->T1_due_time = current_time + client_state->T1; - if (client_state->T2 != 0) - client_state->T2_due_time = current_time + client_state->T2; - client_state->rebinding = 0; - - interrupt_process (); - - return error; -} - -static address_info_t * -create_address_list (u32 sw_if_index) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - address_info_t *address_info, *address_list = 0;; - - /* *INDENT-OFF* */ - pool_foreach (address_info, rm->address_pool, - ({ - if (address_info->sw_if_index == sw_if_index) - { - u32 pos = vec_len (address_list); - vec_validate (address_list, pos); - clib_memcpy (&address_list[pos], address_info, sizeof (*address_info)); - } - })); - /* *INDENT-ON* */ - - return address_list; -} - -VNET_DHCP6_REPLY_EVENT_FUNCTION (dhcp6_reply_event_handler); - -static uword -dhcp6_client_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_frame_t * f) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - address_info_t *address_info; - client_state_t *client_state; - f64 sleep_time = 1e9; - clib_error_t *error; - f64 current_time; - f64 due_time; - uword event_type; - uword *event_data = 0; - int i; - - while (1) - { - vlib_process_wait_for_event_or_clock (vm, sleep_time); - event_type = vlib_process_get_events (vm, &event_data); - vec_reset_length (event_data); - - if (event_type == RD_CP_EVENT_DISABLE) - { - vlib_node_set_state (vm, rm->node_index, VLIB_NODE_STATE_DISABLED); - sleep_time = 1e9; - continue; - } - - current_time = vlib_time_now (vm); - do - { - due_time = current_time + 1e9; - /* *INDENT-OFF* */ - pool_foreach (address_info, rm->address_pool, - ({ - if (address_info->due_time > current_time) - { - if (address_info->due_time < due_time) - due_time = address_info->due_time; - } - else - { - u32 sw_if_index = address_info->sw_if_index; - error = ip6_add_del_interface_address (vm, sw_if_index, - &address_info->address, - 64, 1); - if (error) - clib_warning ("Failed to delete interface address"); - pool_put (rm->address_pool, address_info); - /* make sure ip6 stays enabled */ - ip6_enable (sw_if_index); - client_state = &rm->client_state_by_sw_if_index[sw_if_index]; - if (--client_state->address_count == 0) - { - client_state->rebinding = 0; - client_state->server_index = ~0; - send_client_message_start_stop (sw_if_index, ~0, - DHCPV6_MSG_SOLICIT, - 0, 1); - } - } - })); - /* *INDENT-ON* */ - for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++) - { - client_state_t *cs = &rm->client_state_by_sw_if_index[i]; - if (cs->enabled && cs->server_index != ~0) - { - if (cs->T2_due_time > current_time) - { - if (cs->T2_due_time < due_time) - due_time = cs->T2_due_time; - if (cs->T1_due_time > current_time) - { - if (cs->T1_due_time < due_time) - due_time = cs->T1_due_time; - } - else - { - cs->T1_due_time = DBL_MAX; - address_info_t *address_list; - address_list = create_address_list (i); - cs->rebinding = 1; - send_client_message_start_stop (i, cs->server_index, - DHCPV6_MSG_RENEW, - address_list, 1); - vec_free (address_list); - } - } - else - { - cs->T2_due_time = DBL_MAX; - address_info_t *address_list; - address_list = create_address_list (i); - cs->rebinding = 1; - send_client_message_start_stop (i, ~0, - DHCPV6_MSG_REBIND, - address_list, 1); - vec_free (address_list); - } - } - } - current_time = vlib_time_now (vm); - } - while (due_time < current_time); - - sleep_time = due_time - current_time; - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp6_client_cp_process_node) = { - .function = dhcp6_client_cp_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "dhcp6-client-cp-process", -}; -/* *INDENT-ON* */ - -static void -interrupt_process (void) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - - vlib_process_signal_event (vm, dhcp6_client_cp_process_node.index, - RD_CP_EVENT_INTERRUPT, 0); -} - -static void -disable_process (void) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - - vlib_process_signal_event (vm, dhcp6_client_cp_process_node.index, - RD_CP_EVENT_DISABLE, 0); -} - -static void -enable_process (void) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - vlib_node_t *node; - - node = vec_elt (vm->node_main.nodes, rm->node_index); - - vlib_node_set_state (vm, rm->node_index, VLIB_NODE_STATE_POLLING); - vlib_start_process (vm, node->runtime_index); -} - -static clib_error_t * -dhcp6_addresses_show_command_function (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - dhcp6_client_cp_main_t *dm = &dhcp6_client_cp_main; - clib_error_t *error = 0; - address_info_t *address_info; - f64 current_time = vlib_time_now (vm); - - /* *INDENT-OFF* */ - pool_foreach (address_info, dm->address_pool, - ({ - vlib_cli_output (vm, "address: %U, " - "preferred lifetime: %u, valid lifetime: %u " - "(%f remaining)", - format_ip6_address, &address_info->address, - address_info->preferred_lt, address_info->valid_lt, - address_info->due_time - current_time); - })); - /* *INDENT-ON* */ - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp6_addresses_show_command, static) = { - .path = "show dhcp6 addresses", - .short_help = "show dhcp6 addresses", - .function = dhcp6_addresses_show_command_function, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcp6_clients_show_command_function (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - clib_error_t *error = 0; - client_state_t *cs; - f64 current_time = vlib_time_now (vm); - char buf1[256]; - char buf2[256]; - const char *rebinding; - u32 i; - - for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++) - { - cs = &rm->client_state_by_sw_if_index[i]; - if (cs->enabled) - { - if (cs->T1_due_time != DBL_MAX && cs->T1_due_time > current_time) - { - sprintf (buf1, "%u remaining", - (u32) round (cs->T1_due_time - current_time)); - } - else - sprintf (buf1, "timeout"); - if (cs->T2_due_time != DBL_MAX && cs->T2_due_time > current_time) - sprintf (buf2, "%u remaining", - (u32) round (cs->T2_due_time - current_time)); - else - sprintf (buf2, "timeout"); - if (cs->rebinding) - rebinding = ", REBINDING"; - else - rebinding = ""; - if (cs->T1) - vlib_cli_output (vm, - "sw_if_index: %u, T1: %u (%s), " - "T2: %u (%s), server index: %d%s", i, - cs->T1, buf1, cs->T2, buf2, - cs->server_index, rebinding); - else - vlib_cli_output (vm, "sw_if_index: %u%s", i, rebinding); - } - } - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp6_clients_show_command, static) = { - .path = "show dhcp6 clients", - .short_help = "show dhcp6 clients", - .function = dhcp6_clients_show_command_function, -}; -/* *INDENT-ON* */ - -static int -dhcp6_client_enable_disable (u32 sw_if_index, u8 enable) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - vnet_main_t *vnm = rm->vnet_main; - vlib_main_t *vm = rm->vlib_main; - client_state_t *client_state; - client_state_t empty_config = { 0 }; - address_info_t *address_info; - clib_error_t *error; - - if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index)) - { - clib_warning ("Invalid sw_if_index"); - return 1; - } - - vec_validate_init_empty (rm->client_state_by_sw_if_index, sw_if_index, - empty_config); - client_state = &rm->client_state_by_sw_if_index[sw_if_index]; - - u8 old_enabled = client_state->enabled; - if (enable) - client_state->enabled = 1; - client_state->server_index = ~0; - - if (!old_enabled && enable) - { - rm->n_clients++; - if (rm->n_clients == 1) - { - enable_process (); - dhcp6_clients_enable_disable (1); - } - - ip6_enable (sw_if_index); - send_client_message_start_stop (sw_if_index, ~0, DHCPV6_MSG_SOLICIT, - 0, 1); - } - else if (old_enabled && !enable) - { - send_client_message_start_stop (sw_if_index, ~0, ~0, 0, 0); - - rm->n_clients--; - if (rm->n_clients == 0) - { - dhcp6_clients_enable_disable (0); - disable_process (); - } - - /* *INDENT-OFF* */ - pool_foreach (address_info, rm->address_pool, - ({ - if (address_info->sw_if_index == sw_if_index) - { - ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) && - rm->client_state_by_sw_if_index[sw_if_index].enabled); - client_state_t *client_state = - &rm->client_state_by_sw_if_index[sw_if_index]; - send_client_message_start_stop (sw_if_index, - client_state->server_index, - DHCPV6_MSG_RELEASE, address_info, - 1); - error = ip6_add_del_interface_address (vm, sw_if_index, - &address_info->address, - 64, 1); - if (error) - clib_warning ("Failed to delete interface address"); - pool_put (rm->address_pool, address_info); - } - })); - /* *INDENT-ON* */ - } - - if (!enable) - client_state->enabled = 0; - - return 0; -} - -static clib_error_t * -dhcp6_client_enable_disable_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - vnet_main_t *vnm = rm->vnet_main; - clib_error_t *error = 0; - u32 sw_if_index = ~0; - u8 enable = 1; - unformat_input_t _line_input, *line_input = &_line_input; - - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat - (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) - ; - else if (unformat (line_input, "disable")) - enable = 0; - else - { - error = clib_error_return (0, "unexpected input `%U'", - format_unformat_error, line_input); - goto done; - } - } - - unformat_free (line_input); - - if (sw_if_index != ~0) - { - if (dhcp6_client_enable_disable (sw_if_index, enable) != 0) - error = clib_error_return (0, "Invalid sw_if_index"); - } - else - error = clib_error_return (0, "Missing sw_if_index"); - -done: - return error; -} - -/*? - * This command is used to enable/disable DHCPv6 client - * on particular interface. - * - * @cliexpar - * @parblock - * Example of how to enable DHCPv6 client: - * @cliexcmd{dhcp6 client GigabitEthernet2/0/0} - * Example of how to disable DHCPv6 client: - * @cliexcmd{dhcp6 client GigabitEthernet2/0/0 disable} - * @endparblock -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp6_client_enable_disable_command, static) = { - .path = "dhcp6 client", - .short_help = "dhcp6 client <interface> [disable]", - .function = dhcp6_client_enable_disable_command_fn, -}; -/* *INDENT-ON* */ - -static void - vl_api_dhcp6_client_enable_disable_t_handler - (vl_api_dhcp6_client_enable_disable_t * mp) -{ - vl_api_dhcp6_client_enable_disable_reply_t *rmp; - u32 sw_if_index; - int rv = 0; - - VALIDATE_SW_IF_INDEX (mp); - - sw_if_index = ntohl (mp->sw_if_index); - - rv = dhcp6_client_enable_disable (sw_if_index, mp->enable); - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY); -} - -#define vl_msg_name_crc_list -#include <vnet/dhcp/dhcp6_ia_na_client_cp.api.h> -#undef vl_msg_name_crc_list - -static void -setup_message_id_table (api_main_t * am) -{ -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); - foreach_vl_msg_name_crc_dhcp6_ia_na_client_cp; -#undef _ -} - -static clib_error_t * -dhcp_client_cp_init (vlib_main_t * vm) -{ - dhcp6_client_cp_main_t *rm = &dhcp6_client_cp_main; - api_main_t *am = &api_main; - - rm->vlib_main = vm; - rm->vnet_main = vnet_get_main (); - rm->api_main = am; - rm->node_index = dhcp6_client_cp_process_node.index; - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 0/* do NOT trace! */); - foreach_dhcp6_client_cp_msg; -#undef _ - - /* - * Set up the (msg_name, crc, message-id) table - */ - setup_message_id_table (am); - - return 0; -} - -VLIB_INIT_FUNCTION (dhcp_client_cp_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_ia_na_client_dp.c b/src/vnet/dhcp/dhcp6_ia_na_client_dp.c deleted file mode 100644 index f49017b0236..00000000000 --- a/src/vnet/dhcp/dhcp6_ia_na_client_dp.c +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (c) 2018 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/dhcp/dhcp6_packet.h> -#include <vnet/dhcp/dhcp_proxy.h> -#include <vnet/mfib/mfib_table.h> -#include <vnet/mfib/ip6_mfib.h> -#include <vnet/fib/fib.h> -#include <vnet/adj/adj_mcast.h> -#include <vnet/ip/ip6_neighbor.h> -#include <vlibapi/api_common.h> -#include <vlibmemory/api.h> -#include <vnet/dhcp/dhcp6_ia_na_client_dp.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> -#include <vnet/ip/ip_types_api.h> - -#include <vnet/vnet_msg_enum.h> - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include <vnet/vnet_all_api_h.h> -#undef vl_printfun - -#include <vlibapi/api_helper_macros.h> - -dhcp6_ia_na_client_main_t dhcp6_ia_na_client_main; -dhcp6_ia_na_client_public_main_t dhcp6_ia_na_client_public_main; - -static void -signal_report (address_report_t * r) -{ - vlib_main_t *vm = vlib_get_main (); - dhcp6_ia_na_client_main_t *cm = &dhcp6_ia_na_client_main; - uword ni = cm->publisher_node; - uword et = cm->publisher_et; - - if (ni == (uword) ~ 0) - return; - address_report_t *q = - vlib_process_signal_event_data (vm, ni, et, 1, sizeof *q); - - *q = *r; -} - -int -dhcp6_publish_report (address_report_t * r) -{ - void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); - vl_api_rpc_call_main_thread (signal_report, (u8 *) r, sizeof *r); - return 0; -} - -void -dhcp6_set_publisher_node (uword node_index, uword event_type) -{ - dhcp6_ia_na_client_main_t *cm = &dhcp6_ia_na_client_main; - cm->publisher_node = node_index; - cm->publisher_et = event_type; -} - -static void -stop_sending_client_message (vlib_main_t * vm, - dhcp6_ia_na_client_state_t * client_state) -{ - u32 bi0; - - client_state->keep_sending_client_message = 0; - vec_free (client_state->params.addresses); - 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 vlib_buffer_t * -create_buffer_for_client_message (vlib_main_t * vm, u32 sw_if_index, - dhcp6_ia_na_client_state_t * client_state, - u32 type) -{ - dhcp6_client_common_main_t *ccm = &dhcp6_client_common_main; - vnet_main_t *vnm = vnet_get_main (); - - vlib_buffer_t *b; - u32 bi; - ip6_header_t *ip; - udp_header_t *udp; - dhcpv6_header_t *dhcp; - ip6_address_t src_addr; - u32 dhcp_opt_len = 0; - client_state->transaction_start = vlib_time_now (vm); - u32 n_addresses; - u32 i; - - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); - vnet_sw_interface_t *sup_sw = vnet_get_sup_sw_interface (vnm, sw_if_index); - vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index); - - /* Interface(s) down? */ - if ((hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) == 0) - return NULL; - if ((sup_sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0) - return NULL; - if ((sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0) - return NULL; - - /* Get a link-local address */ - src_addr = ip6_neighbor_get_link_local_address (sw_if_index); - - if (src_addr.as_u8[0] != 0xfe) - { - clib_warning ("Could not find source address to send DHCPv6 packet"); - return NULL; - } - - if (vlib_buffer_alloc (vm, &bi, 1) != 1) - { - clib_warning ("Buffer allocation failed"); - return NULL; - } - - b = vlib_get_buffer (vm, bi); - vnet_buffer (b)->sw_if_index[VLIB_RX] = sw_if_index; - vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index; - client_state->adj_index = adj_mcast_add_or_lock (FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - sw_if_index); - vnet_buffer (b)->ip.adj_index[VLIB_TX] = client_state->adj_index; - b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; - - ip = (ip6_header_t *) vlib_buffer_get_current (b); - udp = (udp_header_t *) (ip + 1); - dhcp = (dhcpv6_header_t *) (udp + 1); - - ip->src_address = src_addr; - ip->hop_limit = 255; - ip->ip_version_traffic_class_and_flow_label = - clib_host_to_net_u32 (0x6 << 28); - ip->payload_length = 0; - ip->protocol = IP_PROTOCOL_UDP; - - udp->src_port = clib_host_to_net_u16 (DHCPV6_CLIENT_PORT); - udp->dst_port = clib_host_to_net_u16 (DHCPV6_SERVER_PORT); - udp->checksum = 0; - udp->length = 0; - - dhcp->msg_type = type; - dhcp->xid[0] = (client_state->transaction_id & 0x00ff0000) >> 16; - dhcp->xid[1] = (client_state->transaction_id & 0x0000ff00) >> 8; - dhcp->xid[2] = (client_state->transaction_id & 0x000000ff) >> 0; - - void *d = (void *) dhcp->data; - dhcpv6_option_t *duid; - dhcpv6_elapsed_t *elapsed; - dhcpv6_ia_header_t *ia_hdr; - dhcpv6_ia_opt_addr_t *opt_addr; - if (type == DHCPV6_MSG_SOLICIT || type == DHCPV6_MSG_REQUEST || - type == DHCPV6_MSG_RENEW || type == DHCPV6_MSG_REBIND || - type == DHCPV6_MSG_RELEASE) - { - duid = (dhcpv6_option_t *) d; - duid->option = clib_host_to_net_u16 (DHCPV6_OPTION_CLIENTID); - duid->length = clib_host_to_net_u16 (CLIENT_DUID_LENGTH); - clib_memcpy (duid + 1, client_duid.bin_string, CLIENT_DUID_LENGTH); - d += sizeof (*duid) + CLIENT_DUID_LENGTH; - - if (client_state->params.server_index != ~0) - { - server_id_t *se = - &ccm->server_ids[client_state->params.server_index]; - - duid = (dhcpv6_option_t *) d; - duid->option = clib_host_to_net_u16 (DHCPV6_OPTION_SERVERID); - duid->length = clib_host_to_net_u16 (se->len); - clib_memcpy (duid + 1, se->data, se->len); - d += sizeof (*duid) + se->len; - } - - elapsed = (dhcpv6_elapsed_t *) d; - elapsed->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_ELAPSED_TIME); - elapsed->opt.length = - clib_host_to_net_u16 (sizeof (*elapsed) - sizeof (elapsed->opt)); - elapsed->elapsed_10ms = 0; - client_state->elapsed_pos = - (char *) &elapsed->elapsed_10ms - - (char *) vlib_buffer_get_current (b); - d += sizeof (*elapsed); - - ia_hdr = (dhcpv6_ia_header_t *) d; - ia_hdr->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_IA_NA); - ia_hdr->iaid = clib_host_to_net_u32 (DHCPV6_CLIENT_IAID); - ia_hdr->t1 = clib_host_to_net_u32 (client_state->params.T1); - ia_hdr->t2 = clib_host_to_net_u32 (client_state->params.T2); - d += sizeof (*ia_hdr); - - n_addresses = vec_len (client_state->params.addresses); - - ia_hdr->opt.length = - clib_host_to_net_u16 (sizeof (*ia_hdr) + - n_addresses * sizeof (*opt_addr) - - sizeof (ia_hdr->opt)); - - for (i = 0; i < n_addresses; i++) - { - dhcp6_send_client_message_params_address_t *addr = - &client_state->params.addresses[i]; - opt_addr = (dhcpv6_ia_opt_addr_t *) d; - opt_addr->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_IAADDR); - opt_addr->opt.length = - clib_host_to_net_u16 (sizeof (*opt_addr) - - sizeof (opt_addr->opt)); - opt_addr->addr = addr->address; - opt_addr->valid = clib_host_to_net_u32 (addr->valid_lt); - opt_addr->preferred = clib_host_to_net_u32 (addr->preferred_lt); - d += sizeof (*opt_addr); - } - } - else - { - clib_warning ("State not implemented"); - } - - dhcp_opt_len = ((u8 *) d) - dhcp->data; - udp->length = - clib_host_to_net_u16 (sizeof (*udp) + sizeof (*dhcp) + dhcp_opt_len); - ip->payload_length = udp->length; - b->current_length = - sizeof (*ip) + sizeof (*udp) + sizeof (*dhcp) + dhcp_opt_len; - - ip->dst_address = all_dhcp6_relay_agents_and_servers; - - return b; -} - -static inline u8 -check_send_client_message (vlib_main_t * vm, - dhcp6_ia_na_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_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; -} - -static uword -send_dhcp6_client_message_process (vlib_main_t * vm, - vlib_node_runtime_t * rt, - vlib_frame_t * f0) -{ - dhcp6_ia_na_client_main_t *cm = &dhcp6_ia_na_client_main; - dhcp6_ia_na_client_state_t *client_state; - uword *event_data = 0; - f64 sleep_time = 1e9; - f64 current_time; - f64 due_time; - f64 dt = 0; - int i; - - while (true) - { - vlib_process_wait_for_event_or_clock (vm, sleep_time); - vlib_process_get_events (vm, &event_data); - vec_reset_length (event_data); - - current_time = vlib_time_now (vm); - do - { - due_time = current_time + 1e9; - for (i = 0; i < vec_len (cm->client_state_by_sw_if_index); i++) - { - client_state = &cm->client_state_by_sw_if_index[i]; - if (!client_state->entry_valid) - continue; - if (check_send_client_message - (vm, client_state, current_time, &dt) && (dt < due_time)) - due_time = dt; - } - current_time = vlib_time_now (vm); - } - while (due_time < current_time); - - sleep_time = due_time - current_time; - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (send_dhcp6_client_message_process_node, static) = { - .function = send_dhcp6_client_message_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "send-dhcp6-client-message-process", -}; -/* *INDENT-ON* */ - -void -dhcp6_send_client_message (vlib_main_t * vm, u32 sw_if_index, u8 stop, - dhcp6_send_client_message_params_t * params) -{ - dhcp6_ia_na_client_main_t *cm = &dhcp6_ia_na_client_main; - dhcp6_ia_na_client_state_t *client_state = 0; - dhcp6_ia_na_client_state_t empty_state = { 0, }; - - ASSERT (~0 != sw_if_index); - - vec_validate_init_empty (cm->client_state_by_sw_if_index, sw_if_index, - empty_state); - client_state = &cm->client_state_by_sw_if_index[sw_if_index]; - if (!client_state->entry_valid) - { - client_state->entry_valid = 1; - client_state->adj_index = ~0; - } - - stop_sending_client_message (vm, client_state); - - if (!stop) - { - client_state->keep_sending_client_message = 1; - vec_free (client_state->params.addresses); - client_state->params = *params; - client_state->params.addresses = vec_dup (params->addresses); - client_state->n_left = params->mrc; - client_state->start_time = vlib_time_now (vm); - client_state->sleep_interval = - (1 + random_f64_from_to (-0.1, 0.1)) * params->irt; - client_state->due_time = 0; /* send first packet ASAP */ - client_state->transaction_id = random_u32 (&cm->seed) & 0x00ffffff; - client_state->buffer = - create_buffer_for_client_message (vm, sw_if_index, client_state, - params->msg_type); - if (!client_state->buffer) - client_state->keep_sending_client_message = 0; - else - vlib_process_signal_event (vm, - send_dhcp6_client_message_process_node.index, - 1, 0); - } -} - -void - vl_api_dhcp6_send_client_message_t_handler - (vl_api_dhcp6_send_client_message_t * mp) -{ - vl_api_dhcp6_send_client_message_reply_t *rmp; - dhcp6_send_client_message_params_t params; - vlib_main_t *vm = vlib_get_main (); - u32 n_addresses; - u32 i; - int rv = 0; - - VALIDATE_SW_IF_INDEX (mp); - - BAD_SW_IF_INDEX_LABEL; - REPLY_MACRO (VL_API_DHCP6_SEND_CLIENT_MESSAGE_REPLY); - - if (rv != 0) - return; - - params.sw_if_index = ntohl (mp->sw_if_index); - params.server_index = ntohl (mp->server_index); - params.irt = ntohl (mp->irt); - params.mrt = ntohl (mp->mrt); - params.mrc = ntohl (mp->mrc); - params.mrd = ntohl (mp->mrd); - params.msg_type = ntohl (mp->msg_type); - params.T1 = ntohl (mp->T1); - params.T2 = ntohl (mp->T2); - n_addresses = ntohl (mp->n_addresses); - params.addresses = 0; - if (n_addresses > 0) - vec_validate (params.addresses, n_addresses - 1); - for (i = 0; i < n_addresses; i++) - { - vl_api_dhcp6_address_info_t *ai = &mp->addresses[i]; - dhcp6_send_client_message_params_address_t *addr = ¶ms.addresses[i]; - addr->preferred_lt = ntohl (ai->preferred_time); - addr->valid_lt = ntohl (ai->valid_time); - ip6_address_decode (ai->address, &addr->address); - } - - dhcp6_send_client_message (vm, ntohl (mp->sw_if_index), mp->stop, ¶ms); -} - -clib_error_t * -call_dhcp6_reply_event_callbacks (void *data, - _vnet_dhcp6_reply_event_function_list_elt_t - * elt) -{ - clib_error_t *error = 0; - - while (elt) - { - error = elt->fp (data); - if (error) - return error; - elt = elt->next_dhcp6_reply_event_function; - } - - return error; -} - -static uword -dhcp6_reply_process (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_frame_t * f) -{ - /* These cross the longjmp boundary (vlib_process_wait_for_event) - * and need to be volatile - to prevent them from being optimized into - * a register - which could change during suspension */ - - while (1) - { - vlib_process_wait_for_event (vm); - uword event_type = DHCP6_DP_REPLY_REPORT; - void *event_data = vlib_process_get_event_data (vm, &event_type); - - int i; - if (event_type == DHCP6_DP_REPLY_REPORT) - { - address_report_t *events = event_data; - for (i = 0; i < vec_len (events); i++) - { - u32 event_size = - sizeof (vl_api_dhcp6_reply_event_t) + - vec_len (events[i].addresses) * - sizeof (vl_api_dhcp6_address_info_t); - vl_api_dhcp6_reply_event_t *event = clib_mem_alloc (event_size); - clib_memset (event, 0, event_size); - - event->sw_if_index = htonl (events[i].body.sw_if_index); - event->server_index = htonl (events[i].body.server_index); - event->msg_type = events[i].body.msg_type; - event->T1 = htonl (events[i].body.T1); - event->T2 = htonl (events[i].body.T2); - event->inner_status_code = - htons (events[i].body.inner_status_code); - event->status_code = htons (events[i].body.status_code); - event->preference = events[i].body.preference; - - event->n_addresses = htonl (vec_len (events[i].addresses)); - vl_api_dhcp6_address_info_t *address = - (typeof (address)) event->addresses; - u32 j; - for (j = 0; j < vec_len (events[i].addresses); j++) - { - dhcp6_address_info_t *info = &events[i].addresses[j]; - ip6_address_encode (&info->address, address->address); - address->valid_time = htonl (info->valid_time); - address->preferred_time = htonl (info->preferred_time); - address++; - } - vec_free (events[i].addresses); - - dhcp6_ia_na_client_public_main_t *dcpm = - &dhcp6_ia_na_client_public_main; - call_dhcp6_reply_event_callbacks (event, dcpm->functions); - - vpe_client_registration_t *reg; - /* *INDENT-OFF* */ - pool_foreach(reg, vpe_api_main.dhcp6_reply_events_registrations, - ({ - vl_api_registration_t *vl_reg; - vl_reg = - vl_api_client_index_to_registration (reg->client_index); - if (vl_reg && vl_api_can_send_msg (vl_reg)) - { - vl_api_dhcp6_reply_event_t *msg = - vl_msg_api_alloc (event_size); - clib_memcpy (msg, event, event_size); - msg->_vl_msg_id = htons (VL_API_DHCP6_REPLY_EVENT); - msg->client_index = reg->client_index; - msg->pid = reg->client_pid; - vl_api_send_msg (vl_reg, (u8 *) msg); - } - })); - /* *INDENT-ON* */ - - clib_mem_free (event); - } - } - vlib_process_put_event_data (vm, event_data); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp6_reply_process_node) = { - .function = dhcp6_reply_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "dhcp6-reply-publisher-process", -}; -/* *INDENT-ON* */ - -void - vl_api_want_dhcp6_reply_events_t_handler - (vl_api_want_dhcp6_reply_events_t * mp) -{ - vpe_api_main_t *am = &vpe_api_main; - vl_api_want_dhcp6_reply_events_reply_t *rmp; - int rv = 0; - - uword *p = - hash_get (am->dhcp6_reply_events_registration_hash, mp->client_index); - vpe_client_registration_t *rp; - if (p) - { - if (mp->enable_disable) - { - clib_warning ("pid %d: already enabled...", ntohl (mp->pid)); - rv = VNET_API_ERROR_INVALID_REGISTRATION; - goto reply; - } - else - { - rp = pool_elt_at_index (am->dhcp6_reply_events_registrations, p[0]); - pool_put (am->dhcp6_reply_events_registrations, rp); - hash_unset (am->dhcp6_reply_events_registration_hash, - mp->client_index); - if (pool_elts (am->dhcp6_reply_events_registrations) == 0) - dhcp6_set_publisher_node (~0, DHCP6_DP_REPORT_MAX); - goto reply; - } - } - if (mp->enable_disable == 0) - { - clib_warning ("pid %d: already disabled...", ntohl (mp->pid)); - rv = VNET_API_ERROR_INVALID_REGISTRATION; - goto reply; - } - pool_get (am->dhcp6_reply_events_registrations, rp); - rp->client_index = mp->client_index; - rp->client_pid = ntohl (mp->pid); - hash_set (am->dhcp6_reply_events_registration_hash, rp->client_index, - rp - am->dhcp6_reply_events_registrations); - dhcp6_set_publisher_node (dhcp6_reply_process_node.index, - DHCP6_DP_REPLY_REPORT); - -reply: - REPLY_MACRO (VL_API_WANT_DHCP6_REPLY_EVENTS_REPLY); -} - -static clib_error_t * -dhcp6_client_init (vlib_main_t * vm) -{ - dhcp6_ia_na_client_main_t *cm = &dhcp6_ia_na_client_main; - - cm->vlib_main = vm; - cm->vnet_main = vnet_get_main (); - - cm->publisher_node = ~0; - - cm->seed = 0xdeaccabe; - - return 0; -} - -VLIB_INIT_FUNCTION (dhcp6_client_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_ia_na_client_dp.h b/src/vnet/dhcp/dhcp6_ia_na_client_dp.h deleted file mode 100644 index a866479fbaf..00000000000 --- a/src/vnet/dhcp/dhcp6_ia_na_client_dp.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2018 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_vnet_dhcp6_client_dp_h -#define included_vnet_dhcp6_client_dp_h - -#include <vlib/vlib.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> - -typedef struct -{ - u32 preferred_lt; - u32 valid_lt; - ip6_address_t address; -} dhcp6_send_client_message_params_address_t; - -typedef struct -{ - u32 sw_if_index; - u32 server_index; - u32 irt; - u32 mrt; - u32 mrc; - u32 mrd; - u8 msg_type; - u32 T1; - u32 T2; - dhcp6_send_client_message_params_address_t *addresses; -} dhcp6_send_client_message_params_t; - -typedef struct -{ - u8 entry_valid; - u8 keep_sending_client_message; /* when true then next fields are valid */ - dhcp6_send_client_message_params_t params; - f64 transaction_start; - f64 sleep_interval; - f64 due_time; - u32 n_left; - f64 start_time; - u32 transaction_id; - vlib_buffer_t *buffer; - u32 elapsed_pos; - u32 adj_index; -} dhcp6_ia_na_client_state_t; - -typedef struct -{ - dhcp6_ia_na_client_state_t *client_state_by_sw_if_index; - - uword publisher_node; - uword publisher_et; - - u32 seed; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; -} dhcp6_ia_na_client_main_t; - -extern dhcp6_ia_na_client_main_t dhcp6_ia_na_client_main; - -typedef struct -{ - ip6_address_t address; - u32 valid_time; - u32 preferred_time; - u16 status_code; -} dhcp6_address_info_t; - -typedef struct -{ - dhcp6_report_common_t body; - u32 n_addresses; - dhcp6_address_info_t *addresses; -} address_report_t; - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -void dhcp6_send_client_message (vlib_main_t * vm, u32 sw_if_index, u8 stop, - dhcp6_send_client_message_params_t * params); -void dhcp6_set_publisher_node (uword node_index, uword event_type); -int dhcp6_publish_report (address_report_t * r); - - -void - vl_api_want_dhcp6_reply_events_t_handler - (vl_api_want_dhcp6_reply_events_t * mp); -void - vl_api_dhcp6_send_client_message_t_handler - (vl_api_dhcp6_send_client_message_t * mp); -void - vl_api_dhcp6_clients_enable_disable_t_handler - (vl_api_dhcp6_clients_enable_disable_t * mp); - -extern vlib_node_registration_t dhcp6_reply_process_node; - -enum -{ DHCP6_DP_REPLY_REPORT, DHCP6_DP_REPORT_MAX }; - -typedef struct _vnet_dhcp6_reply_function_list_elt -{ - struct _vnet_dhcp6_reply_function_list_elt *next_dhcp6_reply_event_function; - clib_error_t *(*fp) (vl_api_dhcp6_reply_event_t * mp); -} _vnet_dhcp6_reply_event_function_list_elt_t; - -typedef struct -{ - _vnet_dhcp6_reply_event_function_list_elt_t *functions; -} dhcp6_ia_na_client_public_main_t; - -extern dhcp6_ia_na_client_public_main_t dhcp6_ia_na_client_public_main; - -#define VNET_DHCP6_REPLY_EVENT_FUNCTION(f) \ - \ -static void __vnet_dhcp6_reply_event_function_init_##f (void) \ - __attribute__((__constructor__)) ; \ - \ -static void __vnet_dhcp6_reply_event_function_init_##f (void) \ -{ \ - dhcp6_ia_na_client_public_main_t * nm = &dhcp6_ia_na_client_public_main; \ - static _vnet_dhcp6_reply_event_function_list_elt_t init_function; \ - init_function.next_dhcp6_reply_event_function = nm->functions; \ - nm->functions = &init_function; \ - init_function.fp = (void *) &f; \ -} \ - \ -static void __vnet_dhcp6_reply_event_function_deinit_##f (void) \ - __attribute__((__destructor__)) ; \ - \ -static void __vnet_dhcp6_reply_event_function_deinit_##f (void) \ -{ \ - dhcp6_ia_na_client_public_main_t * nm = &dhcp6_ia_na_client_public_main; \ - _vnet_dhcp6_reply_event_function_list_elt_t *next; \ - if (nm->functions->fp == (void *) &f) \ - { \ - nm->functions = \ - nm->functions->next_dhcp6_reply_event_function; \ - return; \ - } \ - next = nm->functions; \ - while (next->next_dhcp6_reply_event_function) \ - { \ - if (next->next_dhcp6_reply_event_function->fp == (void *) &f) \ - { \ - next->next_dhcp6_reply_event_function = \ - next->next_dhcp6_reply_event_function->next_dhcp6_reply_event_function; \ - return; \ - } \ - next = next->next_dhcp6_reply_event_function; \ - } \ -} - -#endif /* included_vnet_dhcp6_client_dp_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_packet.h b/src/vnet/dhcp/dhcp6_packet.h deleted file mode 100644 index d5467952a64..00000000000 --- a/src/vnet/dhcp/dhcp6_packet.h +++ /dev/null @@ -1,271 +0,0 @@ -#ifndef included_vnet_dhcp6_packet_h -#define included_vnet_dhcp6_packet_h - -/* - * DHCP packet format - * - * 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 <vnet/ip/ip6_packet.h> - -// #define DHCP_VRF_NAME_MAX_LEN L3VM_MAX_NAME_STR_LEN -// #define DHCPV6_MAX_VRF_NAME_LEN L3VM_MAX_NAME_STR_LEN -#define DHCP_MAX_RELAY_ADDR 16 -#define PROTO_UDP 17 -#define DHCPV6_CLIENT_PORT 546 -#define DHCPV6_SERVER_PORT 547 -#define HOP_COUNT_LIMIT 32 -#define DHCPV6_CISCO_ENT_NUM 9 - -/* - * DHCPv6 message types - */ -typedef enum dhcpv6_msg_type_ -{ - DHCPV6_MSG_SOLICIT = 1, - DHCPV6_MSG_ADVERTISE = 2, - DHCPV6_MSG_REQUEST = 3, - DHCPV6_MSG_CONFIRM = 4, - DHCPV6_MSG_RENEW = 5, - DHCPV6_MSG_REBIND = 6, - DHCPV6_MSG_REPLY = 7, - DHCPV6_MSG_RELEASE = 8, - DHCPV6_MSG_DECLINE = 9, - DHCPV6_MSG_RECONFIGURE = 10, - DHCPV6_MSG_INFORMATION_REQUEST = 11, - DHCPV6_MSG_RELAY_FORW = 12, - DHCPV6_MSG_RELAY_REPL = 13, -} dhcpv6_msg_type_t; - -/* Name, code, min payload length */ -#define dhcpv6_foreach_option \ - _(CLIENTID , 1 , 4 ) \ - _(SERVERID , 2 , 4 ) \ - _(IA_NA , 3 , 12) \ - _(IA_TA , 4 , 4 ) \ - _(IAADDR , 5 , 24) \ - _(ORO , 6 , 0 ) \ - _(PREFERENCE , 7 , 1 ) \ - _(ELAPSED_TIME , 8 , 2 ) \ - _(RELAY_MSG , 9 , 0 ) \ - _(AUTH , 11 , 11) \ - _(UNICAST , 12 , 16) \ - _(STATUS_CODE , 13 , 2 ) \ - _(RAPID_COMMIT , 14 , 0 ) \ - _(USER_CLASS , 15 , 0 ) \ - _(VENDOR_CLASS , 16 , 4 ) \ - _(VENDOR_OPTS , 17 , 4 ) \ - _(INTERFACE_ID , 18 , 0 ) \ - _(RECONF_MSG , 19 , 1 ) \ - _(RECONF_ACCEPT , 20 , 0 ) \ - _(DNS_SEARCH , 24 , 0 ) \ - _(IA_PD , 25 , 12) \ - _(IAPREFIX , 26 , 25) \ - _(REMOTEID , 37 , 4 ) \ - _(VSS , 68 , 1 ) \ - _(CLIENT_LINK_LAYER_ADDRESS, 79 , 2 ) - -/* - * DHCPv6 options types - */ -enum -{ -#define _(a,b,c) DHCPV6_OPTION_##a = b, - dhcpv6_foreach_option -#undef _ - DHCPV6_OPTION_MAX -}; - -/* -* DHCPv6 status codes - */ -enum -{ - DHCPV6_STATUS_SUCCESS = 0, - DHCPV6_STATUS_UNSPEC_FAIL = 1, - DHCPV6_STATUS_NOADDRS_AVAIL = 2, - DHCPV6_STATUS_NO_BINDING = 3, - DHCPV6_STATUS_NOT_ONLINK = 4, - DHCPV6_STATUS_USE_MULTICAST = 5, - DHCPV6_STATUS_NOPREFIX_AVAIL = 6, -}; - -/* - * DHCPv6 DUID types - */ -enum -{ - DHCPV6_DUID_LLT = 1, /* DUID Based on Link-layer Address Plus Time */ - DHCPV6_DUID_EN = 2, /* DUID Based on Enterprise Number */ - DHCPV6_DUID_LL = 3, /* DUID Based on Link-layer Address */ -}; - -//Structure for DHCPv6 payload from client -typedef struct dhcpv6_hdr_ -{ - u8 msg_type; //DHCP msg type - u8 xid[3]; //Transaction id - u8 data[0]; -} dhcpv6_header_t; - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct dhcpv6_relay_ctx_ { - dhcpv6_header_t *pkt; - u32 pkt_len; - u32 dhcpv6_len; //DHCPv6 payload load -// if_ordinal iod; - u32 if_index; - u32 ctx_id; - char ctx_name[32+1]; - u8 dhcp_msg_type; -}) dhcpv6_relay_ctx_t; -/* *INDENT-ON* */ - -//Structure for DHCPv6 RELAY-FORWARD and DHCPv6 RELAY-REPLY pkts -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct dhcpv6_relay_hdr_ { - u8 msg_type; - u8 hop_count; - ip6_address_t link_addr; - ip6_address_t peer_addr; - u8 data[0]; -}) dhcpv6_relay_hdr_t; -/* *INDENT-ON* */ - -typedef enum dhcp_stats_action_type_ -{ - DHCP_STATS_ACTION_FORWARDED = 1, - DHCP_STATS_ACTION_RECEIVED, - DHCP_STATS_ACTION_DROPPED -} dhcp_stats_action_type_t; -//Generic counters for a packet -typedef struct dhcp_stats_counters_ -{ - u64 rx_pkts; //counter for received pkts - u64 tx_pkts; //counter for forwarded pkts - u64 drops; //counter for dropped pkts -} dhcp_stats_counters_t; - - -typedef enum dhcpv6_stats_drop_reason_ -{ - DHCPV6_RELAY_PKT_DROP_RELAYDISABLE = 1, - DHCPV6_RELAY_PKT_DROP_MAX_HOPS, - DHCPV6_RELAY_PKT_DROP_VALIDATION_FAIL, - DHCPV6_RELAY_PKT_DROP_UNKNOWN_OP_INTF, - DHCPV6_RELAY_PKT_DROP_BAD_CONTEXT, - DHCPV6_RELAY_PKT_DROP_OPT_INSERT_FAIL, - DHCPV6_RELAY_PKT_DROP_REPLY_FROM_CLIENT, -} dhcpv6_stats_drop_reason_t; - -#define dhcpv6_optlen(opt) clib_net_to_host_u16((opt)->length) - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - u16 option; - u16 length; - u8 data[0]; -}) dhcpv6_option_t; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - dhcpv6_option_t opt; - u16 status_code; -}) dhcpv6_status_code_t; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - dhcpv6_option_t opt; - u32 int_idx; -}) dhcpv6_int_id_t; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - dhcpv6_option_t opt; - u8 vss_type; - u8 data[0]; -}) dhcpv6_vss_t; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - dhcpv6_option_t opt; - u32 ent_num; - u32 rmt_id; -}) dhcpv6_rmt_id_t; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - dhcpv6_option_t opt; - u16 link_type; - u8 data[6]; // data[0]:data[5]: MAC address -}) dhcpv6_client_mac_t; -/* *INDENT-ON* */ - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; u32 iaid; u32 t1; - u32 t2; - u8 data[0]; - }) dhcpv6_ia_header_t; - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; u32 preferred; u32 valid; u8 prefix; - ip6_address_t addr; - }) dhcpv6_ia_opt_pd_t; - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; ip6_address_t addr; u32 preferred; - u32 valid; - }) dhcpv6_ia_opt_addr_t; - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; - u16 options[0]; - }) dhcpv6_oro_t; - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; u16 elapsed_10ms; - }) dhcpv6_elapsed_t; - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; u16 duid_type; - u16 hardware_type; - }) dhcpv6_duid_t; - -typedef CLIB_PACKED (struct - { - dhcpv6_option_t opt; u16 status_code; - u8 message[0]; - }) dhcpv6_status_t; - - -#endif /* included_vnet_dhcp6_packet_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_pd_client_cp.api b/src/vnet/dhcp/dhcp6_pd_client_cp.api deleted file mode 100644 index 43ed868e81e..00000000000 --- a/src/vnet/dhcp/dhcp6_pd_client_cp.api +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -option version = "1.0.0"; - -/** \brief Enable/disable DHCPv6 PD client on interface - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - interface to enable/disable client on - @param prefix_group - name of prefix group (relevant when 'enable' is 1) - @param enable - 1 to enable, 0 to disable -*/ -autoreply define dhcp6_pd_client_enable_disable -{ - u32 client_index; - u32 context; - u32 sw_if_index; - u8 prefix_group[64]; - u8 enable; -}; - -/** \brief Add/delete IPv6 address optionally using available prefix - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - software interface index of interface - to add/delete address to/from - @param prefix_group - name of prefix group, - prefix_group[0] == '\0' means no prefix should be used - @param address - address or suffix to be used with a prefix - from selected group - @param prefix_length - subnet prefix for the address - @param is_add - 1 for add, 0 for remove -*/ -autoreply define ip6_add_del_address_using_prefix -{ - u32 client_index; - u32 context; - u32 sw_if_index; - u8 prefix_group[64]; - u8 address[16]; - u8 prefix_length; - u8 is_add; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_pd_client_cp.c b/src/vnet/dhcp/dhcp6_pd_client_cp.c deleted file mode 100644 index cc538a78ab1..00000000000 --- a/src/vnet/dhcp/dhcp6_pd_client_cp.c +++ /dev/null @@ -1,1414 +0,0 @@ -/* - * Copyright (c) 2018 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 <vnet/vnet.h> -#include <vlibmemory/api.h> -#include <vnet/vnet_msg_enum.h> -#include <vnet/dhcp/dhcp6_packet.h> -#include <vnet/dhcp/dhcp6_pd_client_dp.h> -#include <vnet/ip/ip.h> -#include <vnet/ip/ip6.h> -#include <float.h> -#include <math.h> -#include <string.h> - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -#include <vlibapi/api_helper_macros.h> - -#define foreach_dhcp6_pd_client_cp_msg \ -_(DHCP6_PD_CLIENT_ENABLE_DISABLE, dhcp6_pd_client_enable_disable) \ -_(IP6_ADD_DEL_ADDRESS_USING_PREFIX, ip6_add_del_address_using_prefix) - -#define vl_api_dhcp6_pd_client_enable_disable_t_print vl_noop_handler -#define vl_api_ip6_add_del_address_using_prefix_t_print vl_noop_handler - -typedef struct -{ - u32 prefix_group_index; - uword opaque_data; // used by prefix publisher - ip6_address_t prefix; - u8 prefix_length; - u32 preferred_lt; - u32 valid_lt; - f64 due_time; -} prefix_info_t; - -typedef struct -{ - u8 enabled; - u32 prefix_group_index; - u32 server_index; - u32 T1; - u32 T2; - f64 T1_due_time; - f64 T2_due_time; - u32 prefix_count; - u8 rebinding; -} client_state_t; - -typedef struct -{ - client_state_t *client_state_by_sw_if_index; - clib_bitmap_t *prefix_ownership_bitmap; - u32 n_clients; - f64 max_valid_due_time; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - api_main_t *api_main; - u32 node_index; -} dhcp6_pd_client_cp_main_t; - -static dhcp6_pd_client_cp_main_t dhcp6_pd_client_cp_main; - -typedef struct -{ - prefix_info_t *prefix_pool; - const u8 **prefix_group_name_by_index; -} ip6_prefix_main_t; - -static ip6_prefix_main_t ip6_prefix_main; - -typedef struct -{ - /* config */ - u32 sw_if_index; - u32 prefix_group_index; - ip6_address_t address; - u8 prefix_length; - - /* state */ - u8 configured_in_data_plane; -} ip6_address_info_t; - -typedef struct -{ - ip6_address_info_t *addresses; - u32 *active_prefix_index_by_prefix_group_index; -} ip6_address_with_prefix_main_t; - -static ip6_address_with_prefix_main_t ip6_address_with_prefix_main; - -enum -{ - DHCPV6_PD_EVENT_INTERRUPT, - DHCPV6_PD_EVENT_DISABLE, -}; - -static_always_inline u32 -active_prefix_index_by_prefix_group_index_get (u32 prefix_group_index) -{ - ip6_address_with_prefix_main_t *apm = &ip6_address_with_prefix_main; - - if (prefix_group_index >= - vec_len (apm->active_prefix_index_by_prefix_group_index)) - return ~0; - - return apm->active_prefix_index_by_prefix_group_index[prefix_group_index]; -} - -static_always_inline void -active_prefix_index_by_prefix_group_index_set (u32 prefix_group_index, - u32 prefix_index) -{ - ip6_address_with_prefix_main_t *apm = &ip6_address_with_prefix_main; - static const u32 empty = ~0; - - ASSERT (prefix_group_index != ~0); - - if (prefix_index == ~0 - && prefix_group_index >= - vec_len (apm->active_prefix_index_by_prefix_group_index)) - return; - - vec_validate_init_empty (apm->active_prefix_index_by_prefix_group_index, - prefix_group_index, empty); - apm->active_prefix_index_by_prefix_group_index[prefix_group_index] = - prefix_index; -} - -static_always_inline u8 -is_dhcpv6_pd_prefix (prefix_info_t * prefix_info) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - u32 prefix_index; - - prefix_index = prefix_info - pm->prefix_pool; - return clib_bitmap_get (rm->prefix_ownership_bitmap, prefix_index); -} - -static_always_inline void -set_is_dhcpv6_pd_prefix (prefix_info_t * prefix_info, u8 value) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - u32 prefix_index; - - prefix_index = prefix_info - pm->prefix_pool; - rm->prefix_ownership_bitmap = - clib_bitmap_set (rm->prefix_ownership_bitmap, prefix_index, value); -} - -static void -cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add); - -static void -notify_prefix_add_del (u32 prefix_index, u8 is_add) -{ - // TODO: use registries - cp_ip6_address_prefix_add_del_handler (prefix_index, is_add); -} - -static void -send_client_message_start_stop (u32 sw_if_index, u32 server_index, - u8 msg_type, prefix_info_t * prefix_list, - u8 start) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - dhcp6_pd_send_client_message_params_t params = { 0, }; - dhcp6_pd_send_client_message_params_prefix_t *prefixes = 0, *pref; - u32 i; - - ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) && - rm->client_state_by_sw_if_index[sw_if_index].enabled); - client_state_t *client_state = - &rm->client_state_by_sw_if_index[sw_if_index]; - - params.sw_if_index = sw_if_index; - params.server_index = server_index; - params.msg_type = msg_type; - if (start) - { - if (msg_type == DHCPV6_MSG_SOLICIT) - { - params.irt = 1; - params.mrt = 120; - } - else if (msg_type == DHCPV6_MSG_REQUEST) - { - params.irt = 1; - params.mrt = 30; - params.mrc = 10; - } - else if (msg_type == DHCPV6_MSG_RENEW) - { - params.irt = 10; - params.mrt = 600; - f64 current_time = vlib_time_now (rm->vlib_main); - i32 diff_time = client_state->T2 - current_time; - if (diff_time < 0) - diff_time = 0; - params.mrd = diff_time; - } - else if (msg_type == DHCPV6_MSG_REBIND) - { - params.irt = 10; - params.mrt = 600; - f64 current_time = vlib_time_now (rm->vlib_main); - i32 diff_time = rm->max_valid_due_time - current_time; - if (diff_time < 0) - diff_time = 0; - params.mrd = diff_time; - } - else if (msg_type == DHCPV6_MSG_RELEASE) - { - params.mrc = 1; - } - } - - params.T1 = 0; - params.T2 = 0; - if (vec_len (prefix_list) != 0) - vec_validate (prefixes, vec_len (prefix_list) - 1); - for (i = 0; i < vec_len (prefix_list); i++) - { - prefix_info_t *prefix = &prefix_list[i]; - pref = &prefixes[i]; - pref->valid_lt = prefix->valid_lt; - pref->preferred_lt = prefix->preferred_lt; - pref->prefix = prefix->prefix; - pref->prefix_length = prefix->prefix_length; - } - params.prefixes = prefixes; - - dhcp6_pd_send_client_message (rm->vlib_main, sw_if_index, !start, ¶ms); - - vec_free (params.prefixes); -} - -static void interrupt_process (void); - -static u32 -ip6_enable (u32 sw_if_index) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - clib_error_t *rv; - - rv = enable_ip6_interface (rm->vlib_main, sw_if_index); - - return rv != 0; -} - -static u8 -ip6_prefixes_equal (ip6_address_t * prefix1, ip6_address_t * prefix2, u8 len) -{ - if (len >= 64) - { - if (prefix1->as_u64[0] != prefix2->as_u64[0]) - return 0; - if (len == 64) - return 1; - return clib_net_to_host_u64 (prefix1->as_u64[1]) >> (128 - len) == - clib_net_to_host_u64 (prefix2->as_u64[1]) >> (128 - len); - } - return clib_net_to_host_u64 (prefix1->as_u64[0]) >> (64 - len) == - clib_net_to_host_u64 (prefix2->as_u64[0]) >> (64 - len); -} - -static clib_error_t * -dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - vlib_main_t *vm = rm->vlib_main; - client_state_t *client_state; - ip6_address_t *prefix; - u32 sw_if_index; - u32 n_prefixes; - vl_api_dhcp6_pd_prefix_info_t *api_prefix; - u32 inner_status_code; - u32 status_code; - u32 server_index; - f64 current_time; - clib_error_t *error = 0; - u32 i; - - current_time = vlib_time_now (vm); - - sw_if_index = ntohl (mp->sw_if_index); - - if (sw_if_index >= vec_len (rm->client_state_by_sw_if_index)) - return 0; - - client_state = &rm->client_state_by_sw_if_index[sw_if_index]; - - if (!client_state->enabled) - return 0; - - server_index = ntohl (mp->server_index); - - n_prefixes = ntohl (mp->n_prefixes); - - inner_status_code = ntohs (mp->inner_status_code); - status_code = ntohs (mp->status_code); - - if (mp->msg_type == DHCPV6_MSG_API_ADVERTISE - && client_state->server_index == ~0) - { - prefix_info_t *prefix_list = 0, *prefix_info; - u8 prefix_length; - - if (inner_status_code == DHCPV6_STATUS_NOPREFIX_AVAIL) - { - clib_warning - ("Advertise message arrived with NoPrefixAvail status code"); - return 0; - } - - if (n_prefixes > 0) - vec_validate (prefix_list, n_prefixes - 1); - for (i = 0; i < n_prefixes; i++) - { - api_prefix = &mp->prefixes[i]; - prefix = (ip6_address_t *) api_prefix->prefix.address; - prefix_length = api_prefix->prefix.len; - - prefix_info = &prefix_list[i]; - prefix_info->prefix = *prefix; - prefix_info->prefix_length = prefix_length; - prefix_info->preferred_lt = 0; - prefix_info->valid_lt = 0; - } - - client_state->server_index = server_index; - - send_client_message_start_stop (sw_if_index, server_index, - DHCPV6_MSG_REQUEST, prefix_list, 1); - vec_free (prefix_list); - } - - if (mp->msg_type != DHCPV6_MSG_API_REPLY) - return 0; - - if (!client_state->rebinding && client_state->server_index != server_index) - { - clib_warning ("Reply message arrived with Server ID different " - "from that in Request or Renew message"); - return 0; - } - - if (inner_status_code == DHCPV6_STATUS_NOPREFIX_AVAIL) - { - clib_warning ("Reply message arrived with NoPrefixAvail status code"); - if (n_prefixes > 0) - { - clib_warning - ("Invalid Reply message arrived: It contains NoPrefixAvail " - "status code but also contains prefixes"); - return 0; - } - } - - if (status_code == DHCPV6_STATUS_UNSPEC_FAIL) - { - clib_warning ("Reply message arrived with UnspecFail status code"); - return 0; - } - - send_client_message_start_stop (sw_if_index, server_index, - mp->msg_type, 0, 0); - - for (i = 0; i < n_prefixes; i++) - { - prefix_info_t *prefix_info = 0; - u8 prefix_length; - u32 valid_time; - u32 preferred_time; - - api_prefix = &mp->prefixes[i]; - - prefix = (ip6_address_t *) api_prefix->prefix.address; - prefix_length = api_prefix->prefix.len; - - if (ip6_address_is_link_local_unicast (prefix)) - continue; - - valid_time = ntohl (api_prefix->valid_time); - preferred_time = ntohl (api_prefix->preferred_time); - prefix_length = api_prefix->prefix.len; - - if (preferred_time > valid_time) - continue; - - u8 address_prefix_present = 0; - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - if (is_dhcpv6_pd_prefix (prefix_info) && - prefix_info->opaque_data == sw_if_index && - prefix_info->prefix_length == prefix_length && - ip6_prefixes_equal (&prefix_info->prefix, prefix, prefix_length)) - { - address_prefix_present = 1; - goto prefix_pool_foreach_out; - } - })); - /* *INDENT-ON* */ - prefix_pool_foreach_out: - - if (address_prefix_present) - { - prefix_info->preferred_lt = preferred_time; - prefix_info->valid_lt = valid_time; - prefix_info->due_time = current_time + valid_time; - if (prefix_info->due_time > rm->max_valid_due_time) - rm->max_valid_due_time = prefix_info->due_time; - continue; - } - - if (valid_time == 0) - continue; - - pool_get (pm->prefix_pool, prefix_info); - prefix_info->prefix_group_index = client_state->prefix_group_index; - set_is_dhcpv6_pd_prefix (prefix_info, 1); - prefix_info->opaque_data = sw_if_index; - prefix_info->prefix_length = prefix_length; - prefix_info->prefix = *prefix; - prefix_info->preferred_lt = preferred_time; - prefix_info->valid_lt = valid_time; - prefix_info->due_time = current_time + valid_time; - if (prefix_info->due_time > rm->max_valid_due_time) - rm->max_valid_due_time = prefix_info->due_time; - rm->client_state_by_sw_if_index[sw_if_index].prefix_count++; - - u32 prefix_index = prefix_info - pm->prefix_pool; - notify_prefix_add_del (prefix_index, 1); - } - - client_state->server_index = server_index; - client_state->T1 = ntohl (mp->T1); - client_state->T2 = ntohl (mp->T2); - if (client_state->T1 != 0) - client_state->T1_due_time = current_time + client_state->T1; - if (client_state->T2 != 0) - client_state->T2_due_time = current_time + client_state->T2; - client_state->rebinding = 0; - - interrupt_process (); - - return error; -} - -static prefix_info_t * -create_prefix_list (u32 sw_if_index) -{ - ip6_prefix_main_t *pm = &ip6_prefix_main; - prefix_info_t *prefix_info, *prefix_list = 0;; - - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - if (is_dhcpv6_pd_prefix (prefix_info) && - prefix_info->opaque_data == sw_if_index) - { - u32 pos = vec_len (prefix_list); - vec_validate (prefix_list, pos); - clib_memcpy (&prefix_list[pos], prefix_info, sizeof (*prefix_info)); - } - })); - /* *INDENT-ON* */ - - return prefix_list; -} - -VNET_DHCP6_PD_REPLY_EVENT_FUNCTION (dhcp6_pd_reply_event_handler); - -static uword -dhcp6_pd_client_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_frame_t * f) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - prefix_info_t *prefix_info; - client_state_t *client_state; - f64 sleep_time = 1e9; - f64 current_time; - f64 due_time; - uword event_type; - uword *event_data = 0; - int i; - - while (1) - { - vlib_process_wait_for_event_or_clock (vm, sleep_time); - event_type = vlib_process_get_events (vm, &event_data); - vec_reset_length (event_data); - - if (event_type == DHCPV6_PD_EVENT_DISABLE) - { - vlib_node_set_state (vm, rm->node_index, VLIB_NODE_STATE_DISABLED); - sleep_time = 1e9; - continue; - } - - current_time = vlib_time_now (vm); - do - { - due_time = current_time + 1e9; - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - if (is_dhcpv6_pd_prefix (prefix_info)) - { - if (prefix_info->due_time > current_time) - { - if (prefix_info->due_time < due_time) - due_time = prefix_info->due_time; - } - else - { - u32 prefix_index = prefix_info - pm->prefix_pool; - notify_prefix_add_del (prefix_index, 0); - u32 sw_if_index = prefix_info->opaque_data; - set_is_dhcpv6_pd_prefix (prefix_info, 0); - pool_put (pm->prefix_pool, prefix_info); - client_state = &rm->client_state_by_sw_if_index[sw_if_index]; - if (--client_state->prefix_count == 0) - { - client_state->rebinding = 0; - client_state->server_index = ~0; - send_client_message_start_stop (sw_if_index, ~0, - DHCPV6_MSG_SOLICIT, - 0, 1); - } - } - } - })); - /* *INDENT-ON* */ - for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++) - { - client_state_t *cs = &rm->client_state_by_sw_if_index[i]; - if (cs->enabled && cs->server_index != ~0) - { - if (cs->T2_due_time > current_time) - { - if (cs->T2_due_time < due_time) - due_time = cs->T2_due_time; - if (cs->T1_due_time > current_time) - { - if (cs->T1_due_time < due_time) - due_time = cs->T1_due_time; - } - else - { - cs->T1_due_time = DBL_MAX; - prefix_info_t *prefix_list; - prefix_list = create_prefix_list (i); - send_client_message_start_stop (i, cs->server_index, - DHCPV6_MSG_RENEW, - prefix_list, 1); - vec_free (prefix_list); - } - } - else - { - cs->T2_due_time = DBL_MAX; - prefix_info_t *prefix_list; - prefix_list = create_prefix_list (i); - cs->rebinding = 1; - send_client_message_start_stop (i, ~0, - DHCPV6_MSG_REBIND, - prefix_list, 1); - vec_free (prefix_list); - } - } - } - current_time = vlib_time_now (vm); - } - while (due_time < current_time); - - sleep_time = due_time - current_time; - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp6_pd_client_cp_process_node) = { - .function = dhcp6_pd_client_cp_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "dhcp6-pd-client-cp-process", -}; -/* *INDENT-ON* */ - -static void -interrupt_process (void) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - - vlib_process_signal_event (vm, dhcp6_pd_client_cp_process_node.index, - DHCPV6_PD_EVENT_INTERRUPT, 0); -} - -static void -disable_process (void) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - - vlib_process_signal_event (vm, dhcp6_pd_client_cp_process_node.index, - DHCPV6_PD_EVENT_DISABLE, 0); -} - -static void -enable_process (void) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - vlib_main_t *vm = rm->vlib_main; - vlib_node_t *node; - - node = vec_elt (vm->node_main.nodes, rm->node_index); - - vlib_node_set_state (vm, rm->node_index, VLIB_NODE_STATE_POLLING); - vlib_start_process (vm, node->runtime_index); -} - -static u32 -cp_ip6_construct_address (ip6_address_info_t * address_info, u32 prefix_index, - ip6_address_t * r_addr) -{ - ip6_prefix_main_t *pm = &ip6_prefix_main; - prefix_info_t *prefix; - u64 mask, addr0, pref; - - addr0 = clib_net_to_host_u64 (address_info->address.as_u64[0]); - prefix = &pm->prefix_pool[prefix_index]; - if (prefix->prefix_length > 64) - { - clib_warning ("Prefix length is bigger that 64 bits"); - return 1; - } - mask = ((u64) 1 << (64 - prefix->prefix_length)) - 1; - addr0 &= mask; - pref = clib_host_to_net_u64 (prefix->prefix.as_u64[0]); - pref &= ~mask; - addr0 |= pref; - r_addr->as_u64[0] = clib_host_to_net_u64 (addr0); - r_addr->as_u64[1] = address_info->address.as_u64[1]; - - return 0; -} - -static void -cp_ip6_address_add_del_now (ip6_address_info_t * address_info, u8 is_add) -{ - vlib_main_t *vm = vlib_get_main (); - u32 prefix_index; - ip6_address_t addr; - clib_error_t *error; - - if (address_info->prefix_group_index != ~0) - prefix_index = - active_prefix_index_by_prefix_group_index_get - (address_info->prefix_group_index); - else - prefix_index = ~0; - - if (is_add && !address_info->configured_in_data_plane) - { - if (prefix_index != ~0) - { - if (cp_ip6_construct_address (address_info, prefix_index, &addr) != - 0) - return; - error = - ip6_add_del_interface_address (vm, address_info->sw_if_index, - &addr, address_info->prefix_length, - 0 /* add */ ); - if (error) - clib_warning ("Failed adding IPv6 address: %U", - format_clib_error, error); - else - address_info->configured_in_data_plane = 1; - } - else - { - if (address_info->prefix_group_index == ~0) - { - error = - ip6_add_del_interface_address (vm, address_info->sw_if_index, - &address_info->address, - address_info->prefix_length, - 0 /* add */ ); - if (error) - clib_warning ("Failed adding IPv6 address: %U", - format_clib_error, error); - else - address_info->configured_in_data_plane = 1; - } - } - } - else if (!is_add && address_info->configured_in_data_plane) - { - if (prefix_index == ~0) - { - if (address_info->prefix_group_index == ~0) - { - error = - ip6_add_del_interface_address (vm, address_info->sw_if_index, - &address_info->address, - address_info->prefix_length, - 1 /* del */ ); - if (error) - clib_warning ("Failed deleting IPv6 address: %U", - format_clib_error, error); - address_info->configured_in_data_plane = 0; - } - else - clib_warning ("Deleting address with prefix " - "but active prefix index is not set"); - } - else - { - if (cp_ip6_construct_address (address_info, prefix_index, &addr) != - 0) - return; - error = - ip6_add_del_interface_address (vm, address_info->sw_if_index, - &addr, address_info->prefix_length, - 1 /* del */ ); - if (error) - clib_warning ("Failed deleting IPv6 address: %U", - format_clib_error, error); - address_info->configured_in_data_plane = 0; - } - } -} - -static u32 -cp_ip6_address_find_new_active_prefix (u32 prefix_group_index, - u32 ignore_prefix_index) -{ - ip6_prefix_main_t *pm = &ip6_prefix_main; - prefix_info_t *prefix_info; - - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - if (prefix_info->prefix_group_index == prefix_group_index && - prefix_info - pm->prefix_pool != ignore_prefix_index) - return prefix_info - pm->prefix_pool; - })); - /* *INDENT-ON* */ - return ~0; -} - -static void -cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add) -{ - ip6_address_with_prefix_main_t *apm = &ip6_address_with_prefix_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - ip6_address_info_t *address_info; - prefix_info_t *prefix; - u32 new_prefix_index; - u32 prefix_group_index; - u32 i; - - prefix = &pm->prefix_pool[prefix_index]; - prefix_group_index = prefix->prefix_group_index; - - if (is_add) - { - if (active_prefix_index_by_prefix_group_index_get - (prefix_group_index) == ~0) - { - active_prefix_index_by_prefix_group_index_set - (prefix_group_index, prefix_index); - for (i = 0; i < vec_len (apm->addresses); i++) - { - address_info = &apm->addresses[i]; - if (address_info->prefix_group_index == prefix_group_index) - cp_ip6_address_add_del_now (address_info, 1 /* add */ ); - } - } - } - else - { - if (active_prefix_index_by_prefix_group_index_get - (prefix_group_index) == prefix_index) - { - for (i = 0; i < vec_len (apm->addresses); i++) - { - address_info = &apm->addresses[i]; - if (address_info->prefix_group_index == prefix_group_index) - cp_ip6_address_add_del_now (address_info, 0 /* del */ ); - } - active_prefix_index_by_prefix_group_index_set - (prefix_group_index, ~0); - new_prefix_index = - cp_ip6_address_find_new_active_prefix (prefix_group_index, - prefix_index); - if (new_prefix_index != ~0) - { - active_prefix_index_by_prefix_group_index_set - (prefix_group_index, new_prefix_index); - for (i = 0; i < vec_len (apm->addresses); i++) - { - address_info = &apm->addresses[i]; - if (address_info->prefix_group_index == prefix_group_index) - cp_ip6_address_add_del_now (address_info, 1 /* add */ ); - } - } - } - } -} - -static u32 -prefix_group_find_or_create (const u8 * name, u8 create) -{ - ip6_prefix_main_t *pm = &ip6_prefix_main; - u32 free_index = ~0; - u8 *name_dup; - u32 i; - - for (i = 0; i < vec_len (pm->prefix_group_name_by_index); i++) - { - if (pm->prefix_group_name_by_index[i] == 0) - free_index = i; - else if (0 == - strcmp ((const char *) pm->prefix_group_name_by_index[i], - (const char *) name)) - return i; - } - if (!create) - return ~0; - name_dup = (u8 *) strdup ((const char *) name); - if (free_index != ~0) - { - pm->prefix_group_name_by_index[free_index] = name_dup; - return free_index; - } - else - { - vec_add1 (pm->prefix_group_name_by_index, name_dup); - return vec_len (pm->prefix_group_name_by_index) - 1; - } -} - -static int -cp_ip6_address_add_del (u32 sw_if_index, const u8 * prefix_group, - ip6_address_t address, u8 prefix_length, u8 is_add) -{ - - ip6_address_with_prefix_main_t *apm = &ip6_address_with_prefix_main; - vnet_main_t *vnm = vnet_get_main (); - ip6_address_info_t *address_info; - u32 prefix_group_index; - u32 n; - - if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index)) - { - clib_warning ("Invalid sw_if_index"); - return VNET_API_ERROR_INVALID_VALUE; - } - - if (prefix_group != 0 && prefix_group[0] != '\0') - { - if (strnlen ((const char *) prefix_group, 64) == 64) - return VNET_API_ERROR_INVALID_VALUE; - - prefix_group_index = prefix_group_find_or_create (prefix_group, 1); - } - else - prefix_group_index = ~0; - - n = vec_len (apm->addresses); - - vec_foreach (address_info, apm->addresses) - { - if (address_info->sw_if_index == sw_if_index && - address_info->prefix_group_index == prefix_group_index && - address_info->prefix_length == prefix_length && - 0 == memcmp (&address_info->address, &address, 16)) - { - if (is_add) - return VNET_API_ERROR_DUPLICATE_IF_ADDRESS; - cp_ip6_address_add_del_now (address_info, 0 /* del */ ); - *address_info = apm->addresses[n - 1]; - _vec_len (apm->addresses) = n - 1; - return 0; - } - } - - if (!is_add) - return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE; - - vec_validate (apm->addresses, n); - address_info = &apm->addresses[n]; - address_info->sw_if_index = sw_if_index; - address_info->prefix_group_index = prefix_group_index; - address_info->address = address; - address_info->prefix_length = prefix_length; - cp_ip6_address_add_del_now (address_info, 1 /* add */ ); - - return 0; -} - -static void - vl_api_ip6_add_del_address_using_prefix_t_handler - (vl_api_ip6_add_del_address_using_prefix_t * mp) -{ - vl_api_ip6_add_del_address_using_prefix_reply_t *rmp; - u32 sw_if_index; - ip6_address_t address; - u8 prefix_length; - int rv = 0; - - VALIDATE_SW_IF_INDEX (mp); - - sw_if_index = ntohl (mp->sw_if_index); - - memcpy (address.as_u8, mp->address, 16); - prefix_length = mp->prefix_length; - - rv = - cp_ip6_address_add_del (sw_if_index, mp->prefix_group, address, - prefix_length, mp->is_add); - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_IP6_ADD_DEL_ADDRESS_USING_PREFIX_REPLY); -} - -static clib_error_t * -cp_ip6_address_add_del_command_function (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - clib_error_t *error = 0; - u32 sw_if_index = ~0; - u8 *prefix_group = 0; - ip6_address_t address; - u32 prefix_length; - u8 address_set = 0; - u8 add = 1; - unformat_input_t _line_input, *line_input = &_line_input; - - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat - (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)); - else if (unformat (line_input, "prefix group %s", &prefix_group)); - else - if (unformat (line_input, "%U/%d", unformat_ip6_address, - &address, &prefix_length)) - address_set = 1; - else if (unformat (line_input, "del")) - add = 0; - else - { - error = clib_error_return (0, "unexpected input `%U'", - format_unformat_error, line_input); - unformat_free (line_input); - goto done; - } - } - - unformat_free (line_input); - - if (sw_if_index == ~0) - error = clib_error_return (0, "Missing sw_if_index"); - else if (address_set == 0) - error = clib_error_return (0, "Missing address"); - else - { - if (cp_ip6_address_add_del - (sw_if_index, prefix_group, address, prefix_length, add) != 0) - error = clib_error_return (0, "Error adding or removing address"); - } - -done: - return error; -} - -/*? - * This command is used to add/delete IPv6 address - * potentially using available prefix from specified prefix group - * - * @cliexpar - * @parblock - * Example of how to add IPv6 address: - * @cliexcmd{set ip6 address GigabitEthernet2/0/0 - * prefix group my-prefix-group ::7/64} - * Example of how to delete IPv6 address: - * @cliexcmd{set ip6 address GigabitEthernet2/0/0 - * prefix group my-prefix-group ::7/64 del} - * @endparblock -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (ip6_address_add_del_command, static) = { - .path = "set ip6 address", - .short_help = "set ip6 address <interface> [prefix group <string>] " - "<address> [del]", - .function = cp_ip6_address_add_del_command_function, -}; -/* *INDENT-ON* */ - -static clib_error_t * -cp_ip6_addresses_show_command_function (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ip6_address_with_prefix_main_t *apm = &ip6_address_with_prefix_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - ip6_address_info_t *address_info; - const u8 *prefix_group; - clib_error_t *error = 0; - int i; - - for (i = 0; i < vec_len (apm->addresses); i++) - { - address_info = &apm->addresses[i]; - if (address_info->prefix_group_index == ~0) - prefix_group = (const u8 *) "NONE"; - else - prefix_group = - pm->prefix_group_name_by_index[address_info->prefix_group_index]; - vlib_cli_output (vm, - "sw_if_index: %u, prefix_group: %s, address: %U/%d", - address_info->sw_if_index, prefix_group, - format_ip6_address, &address_info->address, - address_info->prefix_length); - } - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (ip6_addresses_show_command, static) = { - .path = "show ip6 addresses", - .short_help = "show ip6 addresses", - .function = cp_ip6_addresses_show_command_function, -}; -/* *INDENT-ON* */ - -static clib_error_t * -cp_ip6_prefixes_show_command_function (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ip6_prefix_main_t *pm = &ip6_prefix_main; - clib_error_t *error = 0; - prefix_info_t *prefix_info; - const u8 *prefix_group; - f64 current_time = vlib_time_now (vm); - - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - prefix_group = - pm->prefix_group_name_by_index[prefix_info->prefix_group_index]; - vlib_cli_output (vm, "opaque_data: %lu, prefix: %U/%d, prefix group: %s, " - "preferred lifetime: %u, valid lifetime: %u " - "(%f remaining)", - prefix_info->opaque_data, format_ip6_address, - &prefix_info->prefix, prefix_info->prefix_length, - prefix_group, - prefix_info->preferred_lt, prefix_info->valid_lt, - prefix_info->due_time - current_time); - })); - /* *INDENT-ON* */ - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (ip6_prefixes_show_command, static) = { - .path = "show ip6 prefixes", - .short_help = "show ip6 prefixes", - .function = cp_ip6_prefixes_show_command_function, -}; -/* *INDENT-ON* */ - -static clib_error_t * -ip6_pd_clients_show_command_function (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - clib_error_t *error = 0; - client_state_t *cs; - f64 current_time = vlib_time_now (vm); - const u8 *prefix_group; - char buf1[256]; - char buf2[256]; - const char *rebinding; - u32 i; - - for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++) - { - cs = &rm->client_state_by_sw_if_index[i]; - if (cs->enabled) - { - if (cs->T1_due_time != DBL_MAX && cs->T1_due_time > current_time) - { - sprintf (buf1, "%u remaining", - (u32) round (cs->T1_due_time - current_time)); - } - else - sprintf (buf1, "timeout"); - if (cs->T2_due_time != DBL_MAX && cs->T2_due_time > current_time) - sprintf (buf2, "%u remaining", - (u32) round (cs->T2_due_time - current_time)); - else - sprintf (buf2, "timeout"); - if (cs->rebinding) - rebinding = ", REBINDING"; - else - rebinding = ""; - prefix_group = - pm->prefix_group_name_by_index[cs->prefix_group_index]; - if (cs->T1) - vlib_cli_output (vm, - "sw_if_index: %u, prefix group: %s, T1: %u (%s), " - "T2: %u (%s), server index: %d%s", i, - prefix_group, cs->T1, buf1, cs->T2, buf2, - cs->server_index, rebinding); - else - vlib_cli_output (vm, "sw_if_index: %u, prefix group: %s%s", i, - prefix_group, rebinding); - } - } - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (ip6_pd_clients_show_command, static) = { - .path = "show ip6 pd clients", - .short_help = "show ip6 pd clients", - .function = ip6_pd_clients_show_command_function, -}; -/* *INDENT-ON* */ - -static int -dhcp6_pd_client_enable_disable (u32 sw_if_index, const u8 * prefix_group, - u8 enable) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - ip6_prefix_main_t *pm = &ip6_prefix_main; - vnet_main_t *vnm = rm->vnet_main; - client_state_t *client_state; - static client_state_t empty_config = { - 0 - }; - prefix_info_t *prefix_info; - prefix_info_t *prefix_list = 0; - u32 prefix_group_index; - - if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index)) - { - clib_warning ("Invalid sw_if_index"); - return VNET_API_ERROR_INVALID_VALUE; - } - - vec_validate_init_empty (rm->client_state_by_sw_if_index, sw_if_index, - empty_config); - client_state = &rm->client_state_by_sw_if_index[sw_if_index]; - - u8 old_enabled = client_state->enabled; - - if (enable) - { - if (strnlen ((const char *) prefix_group, 64) == 64 - || prefix_group[0] == '\0') - return VNET_API_ERROR_INVALID_VALUE; - prefix_group_index = - prefix_group_find_or_create (prefix_group, !old_enabled); - if (old_enabled - && prefix_group_index != client_state->prefix_group_index) - return VNET_API_ERROR_INVALID_VALUE; - } - - if (!old_enabled && enable) - { - client_state->enabled = 1; - client_state->prefix_group_index = prefix_group_index; - ASSERT (client_state->prefix_group_index != ~0); - client_state->server_index = ~0; - - rm->n_clients++; - if (rm->n_clients == 1) - { - enable_process (); - dhcp6_clients_enable_disable (1); - } - - ip6_enable (sw_if_index); - send_client_message_start_stop (sw_if_index, ~0, DHCPV6_MSG_SOLICIT, - 0, 1); - } - else if (old_enabled && !enable) - { - send_client_message_start_stop (sw_if_index, ~0, ~0, 0, 0); - - rm->n_clients--; - if (rm->n_clients == 0) - { - dhcp6_clients_enable_disable (0); - disable_process (); - } - - vec_validate (prefix_list, 0); - - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - if (is_dhcpv6_pd_prefix (prefix_info) && - prefix_info->opaque_data == sw_if_index) - { - ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) && - rm->client_state_by_sw_if_index[sw_if_index].enabled); - client_state_t *client_state = - &rm->client_state_by_sw_if_index[sw_if_index]; - prefix_list[0] = *prefix_info; - send_client_message_start_stop (sw_if_index, - client_state->server_index, - DHCPV6_MSG_RELEASE, prefix_list, - 1); - u32 prefix_index = prefix_info - pm->prefix_pool; - notify_prefix_add_del (prefix_index, 0); - set_is_dhcpv6_pd_prefix (prefix_info, 0); - pool_put (pm->prefix_pool, prefix_info); - } - })); - /* *INDENT-ON* */ - - vec_free (prefix_list); - - clib_memset (client_state, 0, sizeof (*client_state)); - } - - return 0; -} - -static clib_error_t * -dhcp6_pd_client_enable_disable_command_fn (vlib_main_t * - vm, - unformat_input_t - * input, vlib_cli_command_t * cmd) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - vnet_main_t *vnm = rm->vnet_main; - clib_error_t *error = 0; - u8 *prefix_group = 0; - u32 sw_if_index = ~0; - u8 enable = 1; - unformat_input_t _line_input, *line_input = &_line_input; - - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat - (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) - ; - else if (unformat (line_input, "prefix group %s", &prefix_group)); - else if (unformat (line_input, "disable")) - enable = 0; - else - { - error = clib_error_return (0, "unexpected input `%U'", - format_unformat_error, line_input); - goto done; - } - } - - if (prefix_group == 0 && enable) - error = clib_error_return (0, "Prefix group must be set when enabling"); - else if (sw_if_index != ~0) - { - if (dhcp6_pd_client_enable_disable (sw_if_index, prefix_group, enable) - != 0) - error = clib_error_return (0, "Invalid sw_if_index or prefix group"); - } - else - error = clib_error_return (0, "Missing sw_if_index"); - -done: - vec_free (prefix_group); - unformat_free (line_input); - - return error; -} - -/*? - * This command is used to enable/disable DHCPv6 PD client - * on particular interface. - * - * @cliexpar - * @parblock - * Example of how to enable DHCPv6 PD client: - * @cliexcmd{dhcp6 pd client GigabitEthernet2/0/0 prefix group my-pd-group} - * Example of how to disable DHCPv6 PD client: - * @cliexcmd{dhcp6 pd client GigabitEthernet2/0/0 disable} - * @endparblock -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcp6_pd_client_enable_disable_command, static) = { - .path = "dhcp6 pd client", - .short_help = "dhcp6 pd client <interface> (prefix group <string> | disable)", - .function = dhcp6_pd_client_enable_disable_command_fn, -}; -/* *INDENT-ON* */ - -static void - vl_api_dhcp6_pd_client_enable_disable_t_handler - (vl_api_dhcp6_pd_client_enable_disable_t * mp) -{ - vl_api_dhcp6_pd_client_enable_disable_reply_t *rmp; - u32 sw_if_index; - int rv = 0; - - VALIDATE_SW_IF_INDEX (mp); - - sw_if_index = ntohl (mp->sw_if_index); - - rv = - dhcp6_pd_client_enable_disable (sw_if_index, mp->prefix_group, - mp->enable); - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_DHCP6_PD_CLIENT_ENABLE_DISABLE_REPLY); -} - -#define vl_msg_name_crc_list -#include <vnet/dhcp/dhcp6_pd_client_cp.api.h> -#undef vl_msg_name_crc_list - -static void -setup_message_id_table (api_main_t * am) -{ -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); - foreach_vl_msg_name_crc_dhcp6_pd_client_cp; -#undef _ -} - -static clib_error_t * -dhcp_pd_client_cp_init (vlib_main_t * vm) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - api_main_t *am = &api_main; - - rm->vlib_main = vm; - rm->vnet_main = vnet_get_main (); - rm->api_main = am; - rm->node_index = dhcp6_pd_client_cp_process_node.index; - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 0/* do NOT trace! */); - foreach_dhcp6_pd_client_cp_msg; -#undef _ - - /* - * Set up the (msg_name, crc, message-id) table - */ - setup_message_id_table (am); - - return 0; -} - -VLIB_INIT_FUNCTION (dhcp_pd_client_cp_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_pd_client_dp.c b/src/vnet/dhcp/dhcp6_pd_client_dp.c deleted file mode 100644 index c665b17281a..00000000000 --- a/src/vnet/dhcp/dhcp6_pd_client_dp.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (c) 2018 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/dhcp/dhcp6_packet.h> -#include <vnet/dhcp/dhcp_proxy.h> -#include <vnet/mfib/mfib_table.h> -#include <vnet/mfib/ip6_mfib.h> -#include <vnet/fib/fib.h> -#include <vnet/adj/adj_mcast.h> -#include <vnet/ip/ip6_neighbor.h> -#include <vlibapi/api_common.h> -#include <vlibmemory/api.h> -#include <vnet/dhcp/dhcp6_pd_client_dp.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> -#include <vnet/ip/ip_types_api.h> - -#include <vnet/vnet_msg_enum.h> - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include <vnet/vnet_all_api_h.h> -#undef vl_printfun - -#include <vlibapi/api_helper_macros.h> - -dhcp6_pd_client_main_t dhcp6_pd_client_main; -dhcp6_pd_client_public_main_t dhcp6_pd_client_public_main; - -static void -signal_report (prefix_report_t * r) -{ - vlib_main_t *vm = vlib_get_main (); - dhcp6_pd_client_main_t *cm = &dhcp6_pd_client_main; - uword ni = cm->publisher_node; - uword et = cm->publisher_et; - - if (ni == (uword) ~ 0) - return; - prefix_report_t *q = - vlib_process_signal_event_data (vm, ni, et, 1, sizeof *q); - - *q = *r; -} - -int -dhcp6_pd_publish_report (prefix_report_t * r) -{ - void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); - vl_api_rpc_call_main_thread (signal_report, (u8 *) r, sizeof *r); - return 0; -} - -void -dhcp6_pd_set_publisher_node (uword node_index, uword event_type) -{ - dhcp6_pd_client_main_t *cm = &dhcp6_pd_client_main; - cm->publisher_node = node_index; - cm->publisher_et = event_type; -} - -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 vlib_buffer_t * -create_buffer_for_client_message (vlib_main_t * vm, - u32 sw_if_index, - dhcp6_pd_client_state_t - * client_state, u32 type) -{ - dhcp6_client_common_main_t *ccm = &dhcp6_client_common_main; - vnet_main_t *vnm = vnet_get_main (); - - vlib_buffer_t *b; - u32 bi; - ip6_header_t *ip; - udp_header_t *udp; - dhcpv6_header_t *dhcp; - ip6_address_t src_addr; - u32 dhcp_opt_len = 0; - client_state->transaction_start = vlib_time_now (vm); - u32 n_prefixes; - u32 i; - - vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); - vnet_sw_interface_t *sup_sw = vnet_get_sup_sw_interface (vnm, sw_if_index); - vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index); - - /* Interface(s) down? */ - if ((hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) == 0) - return NULL; - if ((sup_sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0) - return NULL; - if ((sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0) - return NULL; - - /* Get a link-local address */ - src_addr = ip6_neighbor_get_link_local_address (sw_if_index); - - if (src_addr.as_u8[0] != 0xfe) - { - clib_warning ("Could not find source address to send DHCPv6 packet"); - return NULL; - } - - if (vlib_buffer_alloc (vm, &bi, 1) != 1) - { - clib_warning ("Buffer allocation failed"); - return NULL; - } - - b = vlib_get_buffer (vm, bi); - vnet_buffer (b)->sw_if_index[VLIB_RX] = sw_if_index; - vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index; - client_state->adj_index = adj_mcast_add_or_lock (FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - sw_if_index); - vnet_buffer (b)->ip.adj_index[VLIB_TX] = client_state->adj_index; - b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; - - ip = (ip6_header_t *) vlib_buffer_get_current (b); - udp = (udp_header_t *) (ip + 1); - dhcp = (dhcpv6_header_t *) (udp + 1); - - ip->src_address = src_addr; - ip->hop_limit = 255; - ip->ip_version_traffic_class_and_flow_label = - clib_host_to_net_u32 (0x6 << 28); - ip->payload_length = 0; - ip->protocol = IP_PROTOCOL_UDP; - - udp->src_port = clib_host_to_net_u16 (DHCPV6_CLIENT_PORT); - udp->dst_port = clib_host_to_net_u16 (DHCPV6_SERVER_PORT); - udp->checksum = 0; - udp->length = 0; - - dhcp->msg_type = type; - dhcp->xid[0] = (client_state->transaction_id & 0x00ff0000) >> 16; - dhcp->xid[1] = (client_state->transaction_id & 0x0000ff00) >> 8; - dhcp->xid[2] = (client_state->transaction_id & 0x000000ff) >> 0; - - void *d = (void *) dhcp->data; - dhcpv6_option_t *duid; - dhcpv6_elapsed_t *elapsed; - dhcpv6_ia_header_t *ia_hdr; - dhcpv6_ia_opt_pd_t *opt_pd; - if (type == DHCPV6_MSG_SOLICIT || type == DHCPV6_MSG_REQUEST || - type == DHCPV6_MSG_RENEW || type == DHCPV6_MSG_REBIND || - type == DHCPV6_MSG_RELEASE) - { - duid = (dhcpv6_option_t *) d; - duid->option = clib_host_to_net_u16 (DHCPV6_OPTION_CLIENTID); - duid->length = clib_host_to_net_u16 (CLIENT_DUID_LENGTH); - clib_memcpy (duid + 1, client_duid.bin_string, CLIENT_DUID_LENGTH); - d += sizeof (*duid) + CLIENT_DUID_LENGTH; - - if (client_state->params.server_index != ~0) - { - server_id_t *se = - &ccm->server_ids[client_state->params.server_index]; - - duid = (dhcpv6_option_t *) d; - duid->option = clib_host_to_net_u16 (DHCPV6_OPTION_SERVERID); - duid->length = clib_host_to_net_u16 (se->len); - clib_memcpy (duid + 1, se->data, se->len); - d += sizeof (*duid) + se->len; - } - - elapsed = (dhcpv6_elapsed_t *) d; - elapsed->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_ELAPSED_TIME); - elapsed->opt.length = - clib_host_to_net_u16 (sizeof (*elapsed) - sizeof (elapsed->opt)); - elapsed->elapsed_10ms = 0; - client_state->elapsed_pos = - (char *) &elapsed->elapsed_10ms - - (char *) vlib_buffer_get_current (b); - d += sizeof (*elapsed); - - ia_hdr = (dhcpv6_ia_header_t *) d; - ia_hdr->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_IA_PD); - ia_hdr->iaid = clib_host_to_net_u32 (DHCPV6_CLIENT_IAID); - ia_hdr->t1 = clib_host_to_net_u32 (client_state->params.T1); - ia_hdr->t2 = clib_host_to_net_u32 (client_state->params.T2); - d += sizeof (*ia_hdr); - - n_prefixes = vec_len (client_state->params.prefixes); - - ia_hdr->opt.length = - clib_host_to_net_u16 (sizeof (*ia_hdr) + - n_prefixes * sizeof (*opt_pd) - - sizeof (ia_hdr->opt)); - - for (i = 0; i < n_prefixes; i++) - { - dhcp6_pd_send_client_message_params_prefix_t *pref = - &client_state->params.prefixes[i]; - opt_pd = (dhcpv6_ia_opt_pd_t *) d; - opt_pd->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_IAPREFIX); - opt_pd->opt.length = - clib_host_to_net_u16 (sizeof (*opt_pd) - sizeof (opt_pd->opt)); - opt_pd->addr = pref->prefix; - opt_pd->prefix = pref->prefix_length; - opt_pd->valid = clib_host_to_net_u32 (pref->valid_lt); - opt_pd->preferred = clib_host_to_net_u32 (pref->preferred_lt); - d += sizeof (*opt_pd); - } - } - else - { - clib_warning ("State not implemented"); - } - - dhcp_opt_len = ((u8 *) d) - dhcp->data; - udp->length = - clib_host_to_net_u16 (sizeof (*udp) + sizeof (*dhcp) + dhcp_opt_len); - ip->payload_length = udp->length; - b->current_length = - sizeof (*ip) + sizeof (*udp) + sizeof (*dhcp) + dhcp_opt_len; - - ip->dst_address = all_dhcp6_relay_agents_and_servers; - - return b; -} - -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; -} - -static uword -send_dhcp6_pd_client_message_process (vlib_main_t * vm, - vlib_node_runtime_t * rt, - vlib_frame_t * f0) -{ - dhcp6_pd_client_main_t *cm = &dhcp6_pd_client_main; - dhcp6_pd_client_state_t *client_state; - uword *event_data = 0; - f64 sleep_time = 1e9; - f64 current_time; - f64 due_time; - f64 dt = 0; - int i; - - while (true) - { - vlib_process_wait_for_event_or_clock (vm, sleep_time); - vlib_process_get_events (vm, &event_data); - vec_reset_length (event_data); - - current_time = vlib_time_now (vm); - do - { - due_time = current_time + 1e9; - for (i = 0; i < vec_len (cm->client_state_by_sw_if_index); i++) - { - client_state = &cm->client_state_by_sw_if_index[i]; - if (!client_state->entry_valid) - continue; - if (check_pd_send_client_message - (vm, client_state, current_time, &dt) && (dt < due_time)) - due_time = dt; - } - current_time = vlib_time_now (vm); - } - while (due_time < current_time); - - sleep_time = due_time - current_time; - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (send_dhcp6_pd_client_message_process_node, static) = { - .function = send_dhcp6_pd_client_message_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "send-dhcp6-pd-client-message-process", -}; -/* *INDENT-ON* */ - -void -dhcp6_pd_send_client_message (vlib_main_t * vm, u32 sw_if_index, u8 stop, - dhcp6_pd_send_client_message_params_t * params) -{ - dhcp6_pd_client_main_t *cm = &dhcp6_pd_client_main; - dhcp6_pd_client_state_t *client_state = 0; - dhcp6_pd_client_state_t empty_state = { - 0, - }; - - ASSERT (~0 != sw_if_index); - - vec_validate_init_empty (cm->client_state_by_sw_if_index, sw_if_index, - empty_state); - client_state = &cm->client_state_by_sw_if_index[sw_if_index]; - if (!client_state->entry_valid) - { - client_state->entry_valid = 1; - client_state->adj_index = ~0; - } - - stop_sending_client_message (vm, client_state); - - if (!stop) - { - client_state->keep_sending_client_message = 1; - vec_free (client_state->params.prefixes); - client_state->params = *params; - client_state->params.prefixes = vec_dup (params->prefixes); - client_state->n_left = params->mrc; - client_state->start_time = vlib_time_now (vm); - client_state->sleep_interval = - (1 + random_f64_from_to (-0.1, 0.1)) * params->irt; - client_state->due_time = 0; /* send first packet ASAP */ - client_state->transaction_id = random_u32 (&cm->seed) & 0x00ffffff; - client_state->buffer = - create_buffer_for_client_message (vm, sw_if_index, client_state, - params->msg_type); - if (!client_state->buffer) - client_state->keep_sending_client_message = 0; - else - vlib_process_signal_event (vm, - send_dhcp6_pd_client_message_process_node.index, - 1, 0); - } -} - -void - vl_api_dhcp6_pd_send_client_message_t_handler - (vl_api_dhcp6_pd_send_client_message_t * mp) -{ - vl_api_dhcp6_pd_send_client_message_reply_t *rmp; - dhcp6_pd_send_client_message_params_t params; - vlib_main_t *vm = vlib_get_main (); - u32 n_prefixes; - u32 i; - int rv = 0; - - VALIDATE_SW_IF_INDEX (mp); - - BAD_SW_IF_INDEX_LABEL; - REPLY_MACRO (VL_API_DHCP6_PD_SEND_CLIENT_MESSAGE_REPLY); - - if (rv != 0) - return; - - params.sw_if_index = ntohl (mp->sw_if_index); - params.server_index = ntohl (mp->server_index); - params.irt = ntohl (mp->irt); - params.mrt = ntohl (mp->mrt); - params.mrc = ntohl (mp->mrc); - params.mrd = ntohl (mp->mrd); - params.msg_type = ntohl (mp->msg_type); - params.T1 = ntohl (mp->T1); - params.T2 = ntohl (mp->T2); - n_prefixes = ntohl (mp->n_prefixes); - params.prefixes = 0; - if (n_prefixes > 0) - vec_validate (params.prefixes, n_prefixes - 1); - for (i = 0; i < n_prefixes; i++) - { - vl_api_dhcp6_pd_prefix_info_t *pi = &mp->prefixes[i]; - dhcp6_pd_send_client_message_params_prefix_t *pref = - ¶ms.prefixes[i]; - pref->preferred_lt = ntohl (pi->preferred_time); - pref->valid_lt = ntohl (pi->valid_time); - ip6_address_decode (pi->prefix.address, &pref->prefix); - pref->prefix_length = pi->prefix.len; - } - - dhcp6_pd_send_client_message (vm, ntohl (mp->sw_if_index), mp->stop, - ¶ms); -} - -static clib_error_t * -call_dhcp6_pd_reply_event_callbacks (void *data, - _vnet_dhcp6_pd_reply_event_function_list_elt_t - * elt) -{ - clib_error_t *error = 0; - - while (elt) - { - error = elt->fp (data); - if (error) - return error; - elt = elt->next_dhcp6_pd_reply_event_function; - } - - return error; -} - -static uword -dhcp6_pd_reply_process (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_frame_t * f) -{ - /* These cross the longjmp boundary (vlib_process_wait_for_event) - * and need to be volatile - to prevent them from being optimized into - * a register - which could change during suspension */ - - while (1) - { - vlib_process_wait_for_event (vm); - uword event_type = DHCP6_PD_DP_REPLY_REPORT; - void *event_data = vlib_process_get_event_data (vm, &event_type); - - int i; - if (event_type == DHCP6_PD_DP_REPLY_REPORT) - { - prefix_report_t *events = event_data; - for (i = 0; i < vec_len (events); i++) - { - u32 event_size = - sizeof (vl_api_dhcp6_pd_reply_event_t) + - vec_len (events[i].prefixes) * - sizeof (vl_api_dhcp6_pd_prefix_info_t); - vl_api_dhcp6_pd_reply_event_t *event = - clib_mem_alloc (event_size); - clib_memset (event, 0, event_size); - - event->sw_if_index = htonl (events[i].body.sw_if_index); - event->server_index = htonl (events[i].body.server_index); - event->msg_type = events[i].body.msg_type; - event->T1 = htonl (events[i].body.T1); - event->T2 = htonl (events[i].body.T2); - event->inner_status_code = - htons (events[i].body.inner_status_code); - event->status_code = htons (events[i].body.status_code); - event->preference = events[i].body.preference; - - event->n_prefixes = htonl (vec_len (events[i].prefixes)); - vl_api_dhcp6_pd_prefix_info_t *prefix = - (typeof (prefix)) event->prefixes; - u32 j; - for (j = 0; j < vec_len (events[i].prefixes); j++) - { - dhcp6_prefix_info_t *info = &events[i].prefixes[j]; - ip6_address_encode (&info->prefix, prefix->prefix.address); - prefix->prefix.len = info->prefix_length; - prefix->valid_time = htonl (info->valid_time); - prefix->preferred_time = htonl (info->preferred_time); - prefix++; - } - vec_free (events[i].prefixes); - - dhcp6_pd_client_public_main_t *dpcpm = - &dhcp6_pd_client_public_main; - call_dhcp6_pd_reply_event_callbacks (event, dpcpm->functions); - - vpe_client_registration_t *reg; - /* *INDENT-OFF* */ - pool_foreach(reg, vpe_api_main.dhcp6_pd_reply_events_registrations, - ({ - vl_api_registration_t *vl_reg; - vl_reg = - vl_api_client_index_to_registration (reg->client_index); - if (vl_reg && vl_api_can_send_msg (vl_reg)) - { - vl_api_dhcp6_pd_reply_event_t *msg = - vl_msg_api_alloc (event_size); - clib_memcpy (msg, event, event_size); - msg->_vl_msg_id = htons (VL_API_DHCP6_PD_REPLY_EVENT); - msg->client_index = reg->client_index; - msg->pid = reg->client_pid; - vl_api_send_msg (vl_reg, (u8 *) msg); - } - })); - /* *INDENT-ON* */ - - clib_mem_free (event); - } - } - vlib_process_put_event_data (vm, event_data); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp6_pd_reply_process_node) = { - .function = dhcp6_pd_reply_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "dhcp6-pd-reply-publisher-process", -}; -/* *INDENT-ON* */ - -void - vl_api_want_dhcp6_pd_reply_events_t_handler - (vl_api_want_dhcp6_pd_reply_events_t * mp) -{ - vpe_api_main_t *am = &vpe_api_main; - vl_api_want_dhcp6_pd_reply_events_reply_t *rmp; - int rv = 0; - - uword *p = - hash_get (am->dhcp6_pd_reply_events_registration_hash, mp->client_index); - vpe_client_registration_t *rp; - if (p) - { - if (mp->enable_disable) - { - clib_warning ("pid %d: already enabled...", ntohl (mp->pid)); - rv = VNET_API_ERROR_INVALID_REGISTRATION; - goto reply; - } - else - { - rp = - pool_elt_at_index (am->dhcp6_pd_reply_events_registrations, p[0]); - pool_put (am->dhcp6_pd_reply_events_registrations, rp); - hash_unset (am->dhcp6_pd_reply_events_registration_hash, - mp->client_index); - if (pool_elts (am->dhcp6_pd_reply_events_registrations) == 0) - dhcp6_pd_set_publisher_node (~0, DHCP6_PD_DP_REPORT_MAX); - goto reply; - } - } - if (mp->enable_disable == 0) - { - clib_warning ("pid %d: already disabled...", ntohl (mp->pid)); - rv = VNET_API_ERROR_INVALID_REGISTRATION; - goto reply; - } - pool_get (am->dhcp6_pd_reply_events_registrations, rp); - rp->client_index = mp->client_index; - rp->client_pid = ntohl (mp->pid); - hash_set (am->dhcp6_pd_reply_events_registration_hash, rp->client_index, - rp - am->dhcp6_pd_reply_events_registrations); - dhcp6_pd_set_publisher_node (dhcp6_pd_reply_process_node.index, - DHCP6_PD_DP_REPLY_REPORT); - -reply: - REPLY_MACRO (VL_API_WANT_DHCP6_PD_REPLY_EVENTS_REPLY); -} - -static clib_error_t * -dhcp6_pd_client_init (vlib_main_t * vm) -{ - dhcp6_pd_client_main_t *cm = &dhcp6_pd_client_main; - - cm->vlib_main = vm; - cm->vnet_main = vnet_get_main (); - cm->publisher_node = ~0; - cm->seed = (u32) clib_cpu_time_now (); - - return 0; -} - -VLIB_INIT_FUNCTION (dhcp6_pd_client_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_pd_client_dp.h b/src/vnet/dhcp/dhcp6_pd_client_dp.h deleted file mode 100644 index 88c731c2e67..00000000000 --- a/src/vnet/dhcp/dhcp6_pd_client_dp.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2018 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_vnet_dhcp6_pd_client_dp_h -#define included_vnet_dhcp6_pd_client_dp_h - -#include <vlib/vlib.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> - -typedef struct -{ - u32 preferred_lt; - u32 valid_lt; - ip6_address_t prefix; - u8 prefix_length; -} dhcp6_pd_send_client_message_params_prefix_t; - -typedef struct -{ - u32 sw_if_index; - u32 server_index; - u32 irt; - u32 mrt; - u32 mrc; - u32 mrd; - u8 msg_type; - u32 T1; - u32 T2; - dhcp6_pd_send_client_message_params_prefix_t *prefixes; -} dhcp6_pd_send_client_message_params_t; - -typedef struct -{ - u8 entry_valid; - u8 keep_sending_client_message; /* when true then next fields are valid */ - dhcp6_pd_send_client_message_params_t params; - f64 transaction_start; - f64 sleep_interval; - f64 due_time; - u32 n_left; - f64 start_time; - u32 transaction_id; - vlib_buffer_t *buffer; - u32 elapsed_pos; - u32 adj_index; -} dhcp6_pd_client_state_t; - -typedef struct -{ - dhcp6_pd_client_state_t *client_state_by_sw_if_index; - - uword publisher_node; - uword publisher_et; - - u32 seed; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; -} dhcp6_pd_client_main_t; - -extern dhcp6_pd_client_main_t dhcp6_pd_client_main; - -typedef struct -{ - ip6_address_t prefix; - u8 prefix_length; - u32 valid_time; - u32 preferred_time; - u16 status_code; -} dhcp6_prefix_info_t; - -typedef struct -{ - dhcp6_report_common_t body; - u32 n_prefixes; - dhcp6_prefix_info_t *prefixes; -} prefix_report_t; - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -void dhcp6_pd_send_client_message (vlib_main_t * vm, u32 sw_if_index, u8 stop, - dhcp6_pd_send_client_message_params_t * - params); -void dhcp6_pd_set_publisher_node (uword node_index, uword event_type); -int dhcp6_pd_publish_report (prefix_report_t * r); - -void - vl_api_want_dhcp6_pd_reply_events_t_handler - (vl_api_want_dhcp6_pd_reply_events_t * mp); -void - vl_api_dhcp6_pd_send_client_message_t_handler - (vl_api_dhcp6_pd_send_client_message_t * mp); -void - vl_api_dhcp6_clients_enable_disable_t_handler - (vl_api_dhcp6_clients_enable_disable_t * mp); - -extern vlib_node_registration_t dhcp6_pd_reply_process_node; - -enum -{ DHCP6_PD_DP_REPLY_REPORT, DHCP6_PD_DP_REPORT_MAX }; - -typedef struct _vnet_dhcp6_pd_reply_function_list_elt -{ - struct _vnet_dhcp6_pd_reply_function_list_elt - *next_dhcp6_pd_reply_event_function; - clib_error_t *(*fp) (vl_api_dhcp6_pd_reply_event_t * mp); -} _vnet_dhcp6_pd_reply_event_function_list_elt_t; - -typedef struct -{ - _vnet_dhcp6_pd_reply_event_function_list_elt_t *functions; -} dhcp6_pd_client_public_main_t; - -extern dhcp6_pd_client_public_main_t dhcp6_pd_client_public_main; - -#define VNET_DHCP6_PD_REPLY_EVENT_FUNCTION(f) \ - \ -static void __vnet_dhcp6_pd_reply_event_function_init_##f (void) \ - __attribute__((__constructor__)) ; \ - \ -static void __vnet_dhcp6_pd_reply_event_function_init_##f (void) \ -{ \ - dhcp6_pd_client_public_main_t * nm = &dhcp6_pd_client_public_main; \ - static _vnet_dhcp6_pd_reply_event_function_list_elt_t init_function; \ - init_function.next_dhcp6_pd_reply_event_function = nm->functions; \ - nm->functions = &init_function; \ - init_function.fp = (void *) &f; \ -} \ - \ -static void __vnet_dhcp6_pd_reply_event_function_deinit_##f (void) \ - __attribute__((__destructor__)) ; \ - \ -static void __vnet_dhcp6_pd_reply_event_function_deinit_##f (void) \ -{ \ - dhcp6_pd_client_public_main_t * nm = &dhcp6_pd_client_public_main; \ - _vnet_dhcp6_pd_reply_event_function_list_elt_t *next; \ - if (nm->functions->fp == (void *) &f) \ - { \ - nm->functions = \ - nm->functions->next_dhcp6_pd_reply_event_function; \ - return; \ - } \ - next = nm->functions; \ - while (next->next_dhcp6_pd_reply_event_function) \ - { \ - if (next->next_dhcp6_pd_reply_event_function->fp == (void *) &f) \ - { \ - next->next_dhcp6_pd_reply_event_function = \ - next->next_dhcp6_pd_reply_event_function->next_dhcp6_pd_reply_event_function; \ - return; \ - } \ - next = next->next_dhcp6_pd_reply_event_function; \ - } \ -} - -#endif /* included_vnet_dhcp6_pd_client_dp_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp6_pd_doc.md b/src/vnet/dhcp/dhcp6_pd_doc.md deleted file mode 100644 index 0d0e0865f1b..00000000000 --- a/src/vnet/dhcp/dhcp6_pd_doc.md +++ /dev/null @@ -1,86 +0,0 @@ -# DHCPv6 prefix delegation {#dhcp6_pd_doc} - -DHCPv6 prefix delegation client implementation is split between Control Plane and Data Plane. -Data Plane can also be used alone by external application (external Control Plane) using Data Plane Binary API. - -Number of different IA\_PDs managed by VPP is currently limited to 1 (and corresponding IAID has value 1). -Client ID is of type DUID-LLT (Link Layer address plus time) and is created on VPP startup from avaliable interfaces (or chosen at random for debugging purposes). -Server ID is only visible to Data Plane. Control Plane identifies servers by a 32-bit handle (server\_index) mapped to Server ID by Data Plane. - -## Control Plane - -DHCPv6 PD clients are configured per interface. -When configuring a PD client we have to choose a name of a prefix group for that client. -Each prefix obtained through this client will be flagged as belonging to specified prefix group. -The prefix groups are used as a filter by prefix consumers. - -To enable client on particular interface call Binary API function dhcp6\_pd\_client\_enable\_disable with param 'sw\_if\_index' set to that interface, -'prefix\_group' set to prefix group name and 'enable' set to true. -Format of corresponding Debug CLI command is: "dhcp6 pd client <interface> [disable]" - -To add/delete IPv6 address potentially using available prefix from specified prefix group call Binary API command ip6\_add\_del\_address\_using\_prefix with parameters: -> sw\_if\_index - software interface index of interface to add/delete address to/from -> prefix\_group - name of prefix group, prefix\_group[0] == '\0' means no prefix should be used -> address - address or suffix to be used with a prefix from selected group -> prefix\_length - subnet prefix for the address -> is\_add - 1 for add, 0 for remove -or Debug CLI command with format: "set ip6 addresses <interface> [prefix group <n>] <address> [del]" - -When no prefix is avaliable, no address is physically added, but is added once a prefix becomes avaliable. -Address is removed when all available prefixes are removed. -When a used prefix is removed and there is other available prefix, the address that used the prefix is reconfigured using the available prefix. - -There are three debug CLI commands (with no parameters) used to show the state of clients, prefixes and addresses: - show ip6 pd clients - show ip6 prefixes - show ip6 addresses - -### Example configuration - -set int state GigabitEthernet0/8/0 up -dhcp6 pd client GigabitEthernet0/8/0 prefix group my-dhcp6-pd-group -set ip6 address GigabitEthernet0/8/0 prefix group my-dhcp6-pd-group ::7/64 - -## Data Plane - -First API message to be called is dhcp6\_clients\_enable\_disable with enable parameter set to 1. -It enables DHCPv6 client subsystem to receive UDP messages containing DHCPv6 client port (sets the router to DHCPv6 client mode). -This is to ensure client subsystem gets the messages instead of DHCPv6 proxy subsystem. - -There is one common Binary API call for sending DHCPv6 client messages (dhcp6\_pd\_send\_client\_message) with these fields: -> msg\_type - message type (e.g. Solicit) -> sw\_if\_index - index of TX interface -> server\_index - used to dentify DHCPv6 server, - unique for each DHCPv6 server on the link, - value obrtained from dhcp6\_pd\_reply\_event API message, - use ~0 to send message to all DHCPv6 servers -> param irt - initial retransmission time -> param mrt - maximum retransmission time -> param mrc - maximum retransmission count -> param mrd - maximum retransmission duration for sending the message -> stop - if non-zero then stop resending the message, otherwise start sending the message -> T1 - value of T1 in IA\_PD option -> T2 - value of T2 in IA\_PD option -> prefixes - list of prefixes in IA\_PD option - -The message is automatically resent by Data Plane based on parameters 'irt', 'mrt', 'mrc' and 'mrd'. -To stop the resending call the same function (same msg\_type is sufficient) with 'stop' set to 1. - -To subscribe for notifications of DHCPv6 messages from server call Binary API function -want\_dhcp6\_pd\_reply\_events with enable\_disable set to 1 -Notification (dhcp6\_pd\_reply\_event) fileds are: -> sw\_if\_index - index of RX interface -> server\_index - used to dentify DHCPv6 server, unique for each DHCPv6 server on the link -> msg\_type - message type -> T1 - value of T1 in IA\_PD option -> T2 - value of T2 in IA\_PD option -> inner\_status\_code - value of status code inside IA\_PD option -> status\_code - value of status code -> preference - value of preference option in reply message -> prefixes - list of prefixes in IA\_PD option - -Prefix is a struct with with these fields: -> prefix - prefix bytes -> prefix\_length - prefix length -> valid\_time - valid lifetime -> preferred\_time - preferred lifetime diff --git a/src/vnet/dhcp/dhcp6_proxy_error.def b/src/vnet/dhcp/dhcp6_proxy_error.def deleted file mode 100644 index 55fa731766c..00000000000 --- a/src/vnet/dhcp/dhcp6_proxy_error.def +++ /dev/null @@ -1,29 +0,0 @@ -/* - * dhcp_proxy_error.def: dhcp proxy errors - * - * 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. - */ - -dhcpv6_proxy_error (NONE, "no error") -dhcpv6_proxy_error (NO_SERVER, "no dhcpv6 server configured") -dhcpv6_proxy_error (RELAY_TO_SERVER, "DHCPV6 packets relayed to the server") -dhcpv6_proxy_error (RELAY_TO_CLIENT, "DHCPV6 packets relayed to clients") -dhcpv6_proxy_error (NO_INTERFACE_ADDRESS, "DHCPV6 no interface address") -dhcpv6_proxy_error (WRONG_MESSAGE_TYPE, "DHCPV6 wrong message type.") -dhcpv6_proxy_error (NO_SRC_ADDRESS, "DHCPV6 no srouce IPv6 address configured.") -dhcpv6_proxy_error (NO_CIRCUIT_ID_OPTION, "DHCPv6 reply packets without circuit ID option") -dhcpv6_proxy_error (NO_RELAY_MESSAGE_OPTION, "DHCPv6 reply packets without relay message option") -dhcpv6_proxy_error (BAD_SVR_FIB_OR_ADDRESS, "DHCPv6 packets not from DHCPv6 server or server FIB.") -dhcpv6_proxy_error (PKT_TOO_BIG, "DHCPv6 packets which are too big.") -dhcpv6_proxy_error (WRONG_INTERFACE_ID_OPTION, "DHCPv6 reply to invalid interface.") diff --git a/src/vnet/dhcp/dhcp6_proxy_node.c b/src/vnet/dhcp/dhcp6_proxy_node.c deleted file mode 100644 index 174548f24eb..00000000000 --- a/src/vnet/dhcp/dhcp6_proxy_node.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * dhcp6_proxy_node.c: dhcpv6 proxy node 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/dhcp/dhcp_proxy.h> -#include <vnet/dhcp/dhcp6_packet.h> -#include <vnet/mfib/mfib_table.h> -#include <vnet/mfib/ip6_mfib.h> -#include <vnet/fib/fib.h> - -static char *dhcpv6_proxy_error_strings[] = { -#define dhcpv6_proxy_error(n,s) s, -#include <vnet/dhcp/dhcp6_proxy_error.def> -#undef dhcpv6_proxy_error -}; - -#define foreach_dhcpv6_proxy_to_server_input_next \ - _ (DROP, "error-drop") \ - _ (LOOKUP, "ip6-lookup") \ - _ (SEND_TO_CLIENT, "dhcpv6-proxy-to-client") - - -typedef enum -{ -#define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s, - foreach_dhcpv6_proxy_to_server_input_next -#undef _ - DHCPV6_PROXY_TO_SERVER_INPUT_N_NEXT, -} dhcpv6_proxy_to_server_input_next_t; - -typedef struct -{ - /* 0 => to server, 1 => to client */ - int which; - u8 packet_data[64]; - u32 error; - u32 sw_if_index; - u32 original_sw_if_index; -} dhcpv6_proxy_trace_t; - -static vlib_node_registration_t dhcpv6_proxy_to_server_node; -static vlib_node_registration_t dhcpv6_proxy_to_client_node; - -/* all DHCP servers address */ -static ip6_address_t all_dhcpv6_server_address; -static ip6_address_t all_dhcpv6_server_relay_agent_address; - -static u8 * -format_dhcpv6_proxy_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 *); - dhcpv6_proxy_trace_t *t = va_arg (*args, dhcpv6_proxy_trace_t *); - - if (t->which == 0) - s = format (s, "DHCPV6 proxy: sent to server %U", - format_ip6_address, &t->packet_data, sizeof (ip6_address_t)); - else - s = format (s, "DHCPV6 proxy: sent to client from %U", - format_ip6_address, &t->packet_data, sizeof (ip6_address_t)); - if (t->error != (u32) ~ 0) - s = format (s, " error: %s\n", dhcpv6_proxy_error_strings[t->error]); - - s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n", - t->original_sw_if_index, t->sw_if_index); - - return s; -} - -static u8 * -format_dhcpv6_proxy_header_with_length (u8 * s, va_list * args) -{ - dhcpv6_header_t *h = va_arg (*args, dhcpv6_header_t *); - u32 max_header_bytes = va_arg (*args, u32); - u32 header_bytes; - - header_bytes = sizeof (h[0]); - if (max_header_bytes != 0 && header_bytes > max_header_bytes) - return format (s, "dhcpv6 header truncated"); - - s = format (s, "DHCPV6 Proxy"); - - return s; -} - -/* get first interface address */ -static ip6_address_t * -ip6_interface_first_global_or_site_address (ip6_main_t * im, u32 sw_if_index) -{ - ip_lookup_main_t *lm = &im->lookup_main; - ip_interface_address_t *ia = 0; - ip6_address_t *result = 0; - - /* *INDENT-OFF* */ - foreach_ip_interface_address (lm, ia, sw_if_index, - 1 /* honor unnumbered */, - ({ - ip6_address_t * a = ip_interface_address_get_address (lm, ia); - if ((a->as_u8[0] & 0xe0) == 0x20 || - (a->as_u8[0] & 0xfe) == 0xfc) { - result = a; - break; - } - })); - /* *INDENT-ON* */ - return result; -} - -static inline void -copy_ip6_address (ip6_address_t * dst, ip6_address_t * src) -{ - dst->as_u64[0] = src->as_u64[0]; - dst->as_u64[1] = src->as_u64[1]; -} - -static uword -dhcpv6_proxy_to_server_input (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - u32 n_left_from, next_index, *from, *to_next; - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - u32 pkts_to_server = 0, pkts_to_client = 0, pkts_no_server = 0; - u32 pkts_no_interface_address = 0, pkts_no_exceeding_max_hop = 0; - u32 pkts_no_src_address = 0; - u32 pkts_wrong_msg_type = 0; - u32 pkts_too_big = 0; - ip6_main_t *im = &ip6_main; - ip6_address_t *src; - int bogus_length; - dhcp_proxy_t *proxy; - dhcp_server_t *server; - u32 rx_fib_idx = 0, server_fib_idx = 0; - - 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 > 0 && n_left_to_next > 0) - { - vnet_main_t *vnm = vnet_get_main (); - u32 sw_if_index = 0; - u32 rx_sw_if_index = 0; - vnet_sw_interface_t *swif; - u32 bi0; - vlib_buffer_t *b0; - udp_header_t *u0, *u1; - dhcpv6_header_t *h0; // client msg hdr - ip6_header_t *ip0, *ip1; - ip6_address_t _ia0, *ia0 = &_ia0; - u32 next0; - u32 error0 = (u32) ~ 0; - dhcpv6_option_t *fwd_opt; - dhcpv6_relay_hdr_t *r1; - u16 len; - dhcpv6_int_id_t *id1; - dhcpv6_vss_t *vss1; - dhcpv6_client_mac_t *cmac; // client mac - ethernet_header_t *e_h0; - u8 client_src_mac[6]; - dhcp_vss_t *vss; - u8 is_solicit = 0; - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - h0 = vlib_buffer_get_current (b0); - - /* - * udp_local hands us the DHCPV6 header. - */ - u0 = (void *) h0 - (sizeof (*u0)); - ip0 = (void *) u0 - (sizeof (*ip0)); - e_h0 = (void *) ip0 - ethernet_buffer_header_size (b0); - - clib_memcpy (client_src_mac, e_h0->src_address, 6); - - switch (h0->msg_type) - { - case DHCPV6_MSG_SOLICIT: - case DHCPV6_MSG_REQUEST: - case DHCPV6_MSG_CONFIRM: - case DHCPV6_MSG_RENEW: - case DHCPV6_MSG_REBIND: - case DHCPV6_MSG_RELEASE: - case DHCPV6_MSG_DECLINE: - case DHCPV6_MSG_INFORMATION_REQUEST: - case DHCPV6_MSG_RELAY_FORW: - /* send to server */ - break; - case DHCPV6_MSG_RELAY_REPL: - /* send to client */ - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT; - error0 = 0; - pkts_to_client++; - goto do_enqueue; - default: - /* drop the packet */ - pkts_wrong_msg_type++; - error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE; - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP; - goto do_trace; - - } - - /* Send to DHCPV6 server via the configured FIB */ - rx_sw_if_index = sw_if_index = - vnet_buffer (b0)->sw_if_index[VLIB_RX]; - rx_fib_idx = im->mfib_index_by_sw_if_index[rx_sw_if_index]; - proxy = dhcp_get_proxy (dpm, rx_fib_idx, FIB_PROTOCOL_IP6); - - if (PREDICT_FALSE (NULL == proxy)) - { - error0 = DHCPV6_PROXY_ERROR_NO_SERVER; - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_no_server++; - goto do_trace; - } - - server = &proxy->dhcp_servers[0]; - server_fib_idx = server->server_fib_index; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = server_fib_idx; - - - /* relay-option header pointer */ - vlib_buffer_advance (b0, -(sizeof (*fwd_opt))); - fwd_opt = vlib_buffer_get_current (b0); - /* relay message header pointer */ - vlib_buffer_advance (b0, -(sizeof (*r1))); - r1 = vlib_buffer_get_current (b0); - - vlib_buffer_advance (b0, -(sizeof (*u1))); - u1 = vlib_buffer_get_current (b0); - - vlib_buffer_advance (b0, -(sizeof (*ip1))); - ip1 = vlib_buffer_get_current (b0); - - /* fill in all that rubbish... */ - len = clib_net_to_host_u16 (u0->length) - sizeof (udp_header_t); - copy_ip6_address (&r1->peer_addr, &ip0->src_address); - - r1->msg_type = DHCPV6_MSG_RELAY_FORW; - fwd_opt->length = clib_host_to_net_u16 (len); - fwd_opt->option = clib_host_to_net_u16 (DHCPV6_OPTION_RELAY_MSG); - - r1->hop_count++; - r1->hop_count = - (h0->msg_type != DHCPV6_MSG_RELAY_FORW) ? 0 : r1->hop_count; - - if (PREDICT_FALSE (r1->hop_count >= HOP_COUNT_LIMIT)) - { - error0 = DHCPV6_RELAY_PKT_DROP_MAX_HOPS; - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_no_exceeding_max_hop++; - goto do_trace; - } - - - /* If relay-fwd and src address is site or global unicast address */ - if (h0->msg_type == DHCPV6_MSG_RELAY_FORW && - ((ip0->src_address.as_u8[0] & 0xe0) == 0x20 || - (ip0->src_address.as_u8[0] & 0xfe) == 0xfc)) - { - /* Set link address to zero */ - r1->link_addr.as_u64[0] = 0; - r1->link_addr.as_u64[1] = 0; - goto link_address_set; - } - - /* if receiving interface is unnumbered, use receiving interface - * IP address as link address, otherwise use the loopback interface - * IP address as link address. - */ - - swif = vnet_get_sw_interface (vnm, rx_sw_if_index); - if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) - sw_if_index = swif->unnumbered_sw_if_index; - - ia0 = - ip6_interface_first_global_or_site_address (&ip6_main, - sw_if_index); - if (ia0 == 0) - { - error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS; - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_no_interface_address++; - goto do_trace; - } - - copy_ip6_address (&r1->link_addr, ia0); - - link_address_set: - - if ((b0->current_length + sizeof (*id1) + sizeof (*vss1) + - sizeof (*cmac)) > vlib_buffer_get_default_data_size (vm)) - { - error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG; - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_too_big++; - goto do_trace; - } - - id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length); - b0->current_length += (sizeof (*id1)); - - id1->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_INTERFACE_ID); - id1->opt.length = clib_host_to_net_u16 (sizeof (rx_sw_if_index)); - id1->int_idx = clib_host_to_net_u32 (rx_sw_if_index); - - u1->length = 0; - if (h0->msg_type != DHCPV6_MSG_RELAY_FORW) - { - cmac = - (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length); - b0->current_length += (sizeof (*cmac)); - cmac->opt.length = clib_host_to_net_u16 (sizeof (*cmac) - - sizeof (cmac->opt)); - cmac->opt.option = - clib_host_to_net_u16 - (DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS); - cmac->link_type = clib_host_to_net_u16 (1); /* ethernet */ - clib_memcpy (cmac->data, client_src_mac, 6); - u1->length += sizeof (*cmac); - } - - vss = dhcp_get_vss_info (dpm, rx_fib_idx, FIB_PROTOCOL_IP6); - - if (vss) - { - u16 id_len; /* length of VPN ID */ - u16 type_len = sizeof (vss1->vss_type); - - vss1 = (dhcpv6_vss_t *) (((uword) ip1) + b0->current_length); - vss1->vss_type = vss->vss_type; - if (vss->vss_type == VSS_TYPE_VPN_ID) - { - id_len = sizeof (vss->vpn_id); /* vpn_id is 7 bytes */ - memcpy (vss1->data, vss->vpn_id, id_len); - } - else if (vss->vss_type == VSS_TYPE_ASCII) - { - id_len = vec_len (vss->vpn_ascii_id); - memcpy (vss1->data, vss->vpn_ascii_id, id_len); - } - else /* must be VSS_TYPE_DEFAULT, no VPN ID */ - id_len = 0; - - vss1->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_VSS); - vss1->opt.length = clib_host_to_net_u16 (type_len + id_len); - u1->length += type_len + id_len + sizeof (vss1->opt); - b0->current_length += type_len + id_len + sizeof (vss1->opt); - } - - pkts_to_server++; - u1->checksum = 0; - u1->src_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcpv6_to_client); - u1->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcpv6_to_server); - - u1->length = - clib_host_to_net_u16 (clib_net_to_host_u16 (fwd_opt->length) + - sizeof (*r1) + sizeof (*fwd_opt) + - sizeof (*u1) + sizeof (*id1) + u1->length); - - clib_memset (ip1, 0, sizeof (*ip1)); - ip1->ip_version_traffic_class_and_flow_label = 0x60; - ip1->payload_length = u1->length; - ip1->protocol = PROTO_UDP; - ip1->hop_limit = HOP_COUNT_LIMIT; - src = ((server->dhcp_server.ip6.as_u64[0] || - server->dhcp_server.ip6.as_u64[1]) ? - &server->dhcp_server.ip6 : &all_dhcpv6_server_address); - copy_ip6_address (&ip1->dst_address, src); - - - ia0 = ip6_interface_first_global_or_site_address - (&ip6_main, vnet_buffer (b0)->sw_if_index[VLIB_RX]); - - src = (proxy->dhcp_src_address.ip6.as_u64[0] || - proxy->dhcp_src_address.ip6.as_u64[1]) ? - &proxy->dhcp_src_address.ip6 : ia0; - if (ia0 == 0) - { - error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS; - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP; - pkts_no_src_address++; - goto do_trace; - } - - copy_ip6_address (&ip1->src_address, src); - - - u1->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip1, - &bogus_length); - ASSERT (bogus_length == 0); - - next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP; - - is_solicit = (DHCPV6_MSG_SOLICIT == h0->msg_type); - - /* - * If we have multiple servers configured and this is the - * client's discover message, then send copies to each of - * those servers - */ - if (is_solicit && vec_len (proxy->dhcp_servers) > 1) - { - u32 ii; - - for (ii = 1; ii < vec_len (proxy->dhcp_servers); ii++) - { - vlib_buffer_t *c0; - u32 ci0; - - c0 = vlib_buffer_copy (vm, b0); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (c0); - ci0 = vlib_get_buffer_index (vm, c0); - server = &proxy->dhcp_servers[ii]; - - ip0 = vlib_buffer_get_current (c0); - - src = ((server->dhcp_server.ip6.as_u64[0] || - server->dhcp_server.ip6.as_u64[1]) ? - &server->dhcp_server.ip6 : - &all_dhcpv6_server_address); - copy_ip6_address (&ip1->dst_address, src); - - to_next[0] = ci0; - to_next += 1; - n_left_to_next -= 1; - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - ci0, next0); - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcpv6_proxy_trace_t *tr; - - tr = vlib_add_trace (vm, node, c0, sizeof (*tr)); - tr->which = 0; /* to server */ - tr->error = error0; - tr->original_sw_if_index = rx_sw_if_index; - tr->sw_if_index = sw_if_index; - if (next0 == DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP) - copy_ip6_address ((ip6_address_t *) & - tr->packet_data[0], - &server->dhcp_server.ip6); - } - - if (PREDICT_FALSE (0 == n_left_to_next)) - { - vlib_put_next_frame (vm, node, next_index, - n_left_to_next); - vlib_get_next_frame (vm, node, next_index, - to_next, n_left_to_next); - } - } - } - - do_trace: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->which = 0; /* to server */ - tr->error = error0; - tr->original_sw_if_index = rx_sw_if_index; - tr->sw_if_index = sw_if_index; - if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0) - copy_ip6_address ((ip6_address_t *) & tr->packet_data[0], - &server->dhcp_server.ip6); - } - - do_enqueue: - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - 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_node_increment_counter (vm, dhcpv6_proxy_to_server_node.index, - DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT, - pkts_to_client); - vlib_node_increment_counter (vm, dhcpv6_proxy_to_server_node.index, - DHCPV6_PROXY_ERROR_RELAY_TO_SERVER, - pkts_to_server); - vlib_node_increment_counter (vm, dhcpv6_proxy_to_server_node.index, - DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS, - pkts_no_interface_address); - vlib_node_increment_counter (vm, dhcpv6_proxy_to_server_node.index, - DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE, - pkts_wrong_msg_type); - vlib_node_increment_counter (vm, dhcpv6_proxy_to_server_node.index, - DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS, - pkts_no_src_address); - vlib_node_increment_counter (vm, dhcpv6_proxy_to_server_node.index, - DHCPV6_PROXY_ERROR_PKT_TOO_BIG, pkts_too_big); - return from_frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcpv6_proxy_to_server_node, static) = { - .function = dhcpv6_proxy_to_server_input, - .name = "dhcpv6-proxy-to-server", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - - .n_errors = DHCPV6_PROXY_N_ERROR, - .error_strings = dhcpv6_proxy_error_strings, - - .n_next_nodes = DHCPV6_PROXY_TO_SERVER_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, - foreach_dhcpv6_proxy_to_server_input_next -#undef _ - }, - - .format_buffer = format_dhcpv6_proxy_header_with_length, - .format_trace = format_dhcpv6_proxy_trace, -#if 0 - .unformat_buffer = unformat_dhcpv6_proxy_header, -#endif -}; -/* *INDENT-ON* */ - -static uword -dhcpv6_proxy_to_client_input (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - - u32 n_left_from, *from; - ethernet_main_t *em = vnet_get_ethernet_main (); - dhcp_proxy_main_t *dm = &dhcp_proxy_main; - dhcp_proxy_t *proxy; - dhcp_server_t *server; - vnet_main_t *vnm = vnet_get_main (); - int bogus_length; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - while (n_left_from > 0) - { - u32 bi0; - vlib_buffer_t *b0; - udp_header_t *u0, *u1 = 0; - dhcpv6_relay_hdr_t *h0; - ip6_header_t *ip1 = 0, *ip0; - ip6_address_t _ia0, *ia0 = &_ia0; - ip6_address_t client_address; - ethernet_interface_t *ei0; - ethernet_header_t *mac0; - vnet_hw_interface_t *hi0; - vlib_frame_t *f0; - u32 *to_next0; - u32 sw_if_index = ~0; - u32 original_sw_if_index = ~0; - vnet_sw_interface_t *si0; - u32 error0 = (u32) ~ 0; - vnet_sw_interface_t *swif; - dhcpv6_option_t *r0 = 0, *o; - u16 len = 0; - u8 interface_opt_flag = 0; - u8 relay_msg_opt_flag = 0; - ip6_main_t *im = &ip6_main; - u32 server_fib_idx, client_fib_idx; - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - h0 = vlib_buffer_get_current (b0); - - if (DHCPV6_MSG_RELAY_REPL != h0->msg_type) - { - error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE; - - drop_packet: - vlib_node_increment_counter (vm, dhcpv6_proxy_to_client_node.index, - error0, 1); - - f0 = vlib_get_frame_to_node (vm, dm->error_drop_node_index); - to_next0 = vlib_frame_vector_args (f0); - to_next0[0] = bi0; - f0->n_vectors = 1; - vlib_put_frame_to_node (vm, dm->error_drop_node_index, f0); - goto do_trace; - } - /* hop count seems not need to be checked */ - if (HOP_COUNT_LIMIT < h0->hop_count) - { - error0 = DHCPV6_RELAY_PKT_DROP_MAX_HOPS; - goto drop_packet; - } - u0 = (void *) h0 - (sizeof (*u0)); - ip0 = (void *) u0 - (sizeof (*ip0)); - - vlib_buffer_advance (b0, sizeof (*h0)); - o = vlib_buffer_get_current (b0); - - /* Parse through TLVs looking for option 18 (DHCPV6_OPTION_INTERFACE_ID) - _and_ option 9 (DHCPV6_OPTION_RELAY_MSG) option which must be there. - Currently assuming no other options need to be processed - The interface-ID is the FIB number we need - to track down the client-facing interface */ - - while ((u8 *) o < (b0->data + b0->current_data + b0->current_length)) - { - if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16 (o->option)) - { - interface_opt_flag = 1; - if (clib_net_to_host_u16 (o->length) == sizeof (sw_if_index)) - sw_if_index = - clib_net_to_host_u32 (((dhcpv6_int_id_t *) o)->int_idx); - if (sw_if_index >= vec_len (im->fib_index_by_sw_if_index)) - { - error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION; - goto drop_packet; - } - } - if (DHCPV6_OPTION_RELAY_MSG == clib_net_to_host_u16 (o->option)) - { - relay_msg_opt_flag = 1; - r0 = vlib_buffer_get_current (b0); - } - if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1)) - break; - vlib_buffer_advance (b0, - sizeof (*o) + - clib_net_to_host_u16 (o->length)); - o = - (dhcpv6_option_t *) (((uword) o) + - clib_net_to_host_u16 (o->length) + - sizeof (*o)); - } - - if ((relay_msg_opt_flag == 0) || (r0 == 0)) - { - error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION; - goto drop_packet; - } - - if ((u32) ~ 0 == sw_if_index) - { - error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION; - goto drop_packet; - } - - //Advance buffer to start of encapsulated DHCPv6 message - vlib_buffer_advance (b0, sizeof (*r0)); - - client_fib_idx = im->mfib_index_by_sw_if_index[sw_if_index]; - proxy = dhcp_get_proxy (dm, client_fib_idx, FIB_PROTOCOL_IP6); - - if (NULL == proxy) - { - error0 = DHCPV6_PROXY_ERROR_NO_SERVER; - goto drop_packet; - } - - server_fib_idx = im->fib_index_by_sw_if_index - [vnet_buffer (b0)->sw_if_index[VLIB_RX]]; - - vec_foreach (server, proxy->dhcp_servers) - { - if (server_fib_idx == server->server_fib_index && - ip0->src_address.as_u64[0] == server->dhcp_server.ip6.as_u64[0] && - ip0->src_address.as_u64[1] == server->dhcp_server.ip6.as_u64[1]) - { - goto server_found; - } - } - - //drop packet if not from server with configured address or FIB - error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS; - goto drop_packet; - - server_found: - vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index - = sw_if_index; - - swif = vnet_get_sw_interface (vnm, original_sw_if_index); - if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) - sw_if_index = swif->unnumbered_sw_if_index; - - - /* - * udp_local hands us the DHCPV6 header, need udp hdr, - * ip hdr to relay to client - */ - vlib_buffer_advance (b0, -(sizeof (*u1))); - u1 = vlib_buffer_get_current (b0); - - vlib_buffer_advance (b0, -(sizeof (*ip1))); - ip1 = vlib_buffer_get_current (b0); - - copy_ip6_address (&client_address, &h0->peer_addr); - - ia0 = ip6_interface_first_address (&ip6_main, sw_if_index); - if (ia0 == 0) - { - error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS; - goto drop_packet; - } - - len = clib_net_to_host_u16 (r0->length); - clib_memset (ip1, 0, sizeof (*ip1)); - copy_ip6_address (&ip1->dst_address, &client_address); - u1->checksum = 0; - u1->src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server); - u1->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client); - u1->length = clib_host_to_net_u16 (len + sizeof (udp_header_t)); - - ip1->ip_version_traffic_class_and_flow_label = - ip0->ip_version_traffic_class_and_flow_label & 0x00000fff; - ip1->payload_length = u1->length; - ip1->protocol = PROTO_UDP; - ip1->hop_limit = HOP_COUNT_LIMIT; - copy_ip6_address (&ip1->src_address, ia0); - - u1->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip1, - &bogus_length); - ASSERT (bogus_length == 0); - - vlib_buffer_advance (b0, -(sizeof (ethernet_header_t))); - si0 = vnet_get_sw_interface (vnm, original_sw_if_index); - if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) - vlib_buffer_advance (b0, -4 /* space for VLAN tag */ ); - - mac0 = vlib_buffer_get_current (b0); - - hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index); - ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance); - clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address)); - clib_memset (&mac0->dst_address, 0xff, sizeof (mac0->dst_address)); - mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ? - clib_net_to_host_u16 (0x8100) : clib_net_to_host_u16 (0x86dd); - - if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) - { - u32 *vlan_tag = (u32 *) (mac0 + 1); - u32 tmp; - tmp = (si0->sub.id << 16) | 0x0800; - *vlan_tag = clib_host_to_net_u32 (tmp); - } - - /* $$$ consider adding a dynamic next to the graph node, for performance */ - f0 = vlib_get_frame_to_node (vm, hi0->output_node_index); - to_next0 = vlib_frame_vector_args (f0); - to_next0[0] = bi0; - f0->n_vectors = 1; - vlib_put_frame_to_node (vm, hi0->output_node_index, f0); - - do_trace: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->which = 1; /* to client */ - if (ia0) - copy_ip6_address ((ip6_address_t *) tr->packet_data, ia0); - tr->error = error0; - tr->original_sw_if_index = original_sw_if_index; - tr->sw_if_index = sw_if_index; - } - } - return from_frame->n_vectors; - -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcpv6_proxy_to_client_node, static) = { - .function = dhcpv6_proxy_to_client_input, - .name = "dhcpv6-proxy-to-client", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - - .n_errors = DHCPV6_PROXY_N_ERROR, - .error_strings = dhcpv6_proxy_error_strings, - .format_buffer = format_dhcpv6_proxy_header_with_length, - .format_trace = format_dhcpv6_proxy_trace, -#if 0 - .unformat_buffer = unformat_dhcpv6_proxy_header, -#endif -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcp6_proxy_init (vlib_main_t * vm) -{ - dhcp_proxy_main_t *dm = &dhcp_proxy_main; - vlib_node_t *error_drop_node; - - error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop"); - dm->error_drop_node_index = error_drop_node->index; - - /* RFC says this is the dhcpv6 server address */ - all_dhcpv6_server_address.as_u64[0] = - clib_host_to_net_u64 (0xFF05000000000000); - all_dhcpv6_server_address.as_u64[1] = clib_host_to_net_u64 (0x00010003); - - /* RFC says this is the server and agent address */ - all_dhcpv6_server_relay_agent_address.as_u64[0] = - clib_host_to_net_u64 (0xFF02000000000000); - all_dhcpv6_server_relay_agent_address.as_u64[1] = - clib_host_to_net_u64 (0x00010002); - - return 0; -} - -VLIB_INIT_FUNCTION (dhcp6_proxy_init); - -int -dhcp6_proxy_set_server (ip46_address_t * addr, - ip46_address_t * src_addr, - u32 rx_table_id, u32 server_table_id, int is_del) -{ - vlib_main_t *vm = vlib_get_main (); - u32 rx_fib_index = 0; - int rc = 0; - - const mfib_prefix_t all_dhcp_servers = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_grp_addr = { - .ip6 = all_dhcpv6_server_relay_agent_address, - } - }; - - if (ip46_address_is_zero (addr)) - return VNET_API_ERROR_INVALID_DST_ADDRESS; - - if (ip46_address_is_zero (src_addr)) - return VNET_API_ERROR_INVALID_SRC_ADDRESS; - - rx_fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, - rx_table_id, - MFIB_SOURCE_DHCP); - - if (is_del) - { - if (dhcp_proxy_server_del (FIB_PROTOCOL_IP6, rx_fib_index, - addr, server_table_id)) - { - mfib_table_entry_delete (rx_fib_index, - &all_dhcp_servers, MFIB_SOURCE_DHCP); - mfib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP6, - MFIB_SOURCE_DHCP); - - udp_unregister_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client, - 0 /* is_ip6 */ ); - udp_unregister_dst_port (vm, UDP_DST_PORT_dhcpv6_to_server, - 0 /* is_ip6 */ ); - } - } - else - { - const fib_route_path_t path_for_us = { - .frp_proto = DPO_PROTO_IP6, - .frp_addr = zero_addr, - .frp_sw_if_index = 0xffffffff, - .frp_fib_index = ~0, - .frp_weight = 1, - .frp_flags = FIB_ROUTE_PATH_LOCAL, - .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD, - }; - if (dhcp_proxy_server_add (FIB_PROTOCOL_IP6, addr, src_addr, - rx_fib_index, server_table_id)) - { - mfib_table_entry_path_update (rx_fib_index, - &all_dhcp_servers, - MFIB_SOURCE_DHCP, &path_for_us); - /* - * Each interface that is enabled in this table, needs to be added - * as an accepting interface, but this is not easily doable in VPP. - * So we cheat. Add a flag to the entry that indicates accept form - * any interface. - * We will still only accept on v6 enabled interfaces, since the - * input feature ensures this. - */ - mfib_table_entry_update (rx_fib_index, - &all_dhcp_servers, - MFIB_SOURCE_DHCP, - MFIB_RPF_ID_NONE, - MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF); - mfib_table_lock (rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP); - - udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client, - dhcpv6_proxy_to_client_node.index, - 0 /* is_ip6 */ ); - udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_server, - dhcpv6_proxy_to_server_node.index, - 0 /* is_ip6 */ ); - } - } - - mfib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP); - - return (rc); -} - -static clib_error_t * -dhcpv6_proxy_set_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ip46_address_t addr, src_addr; - int set_server = 0, set_src_address = 0; - u32 rx_table_id = 0, server_table_id = 0; - int is_del = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "server %U", unformat_ip6_address, &addr.ip6)) - set_server = 1; - else if (unformat (input, "src-address %U", - unformat_ip6_address, &src_addr.ip6)) - set_src_address = 1; - else if (unformat (input, "server-fib-id %d", &server_table_id)) - ; - else if (unformat (input, "rx-fib-id %d", &rx_table_id)) - ; - else if (unformat (input, "delete") || unformat (input, "del")) - is_del = 1; - else - break; - } - - if (is_del || (set_server && set_src_address)) - { - int rv; - - rv = dhcp6_proxy_set_server (&addr, &src_addr, rx_table_id, - server_table_id, is_del); - - //TODO: Complete the errors - switch (rv) - { - case 0: - return 0; - - case VNET_API_ERROR_INVALID_DST_ADDRESS: - return clib_error_return (0, "Invalid server address"); - - case VNET_API_ERROR_INVALID_SRC_ADDRESS: - return clib_error_return (0, "Invalid src address"); - - case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return - (0, "Fib id %d: no per-fib DHCP server configured", rx_table_id); - - default: - return clib_error_return (0, "BUG: rv %d", rv); - } - } - else - return clib_error_return (0, "parse error`%U'", - format_unformat_error, input); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcpv6_proxy_set_command, static) = { - .path = "set dhcpv6 proxy", - .short_help = "set dhcpv6 proxy [del] server <ipv6-addr> src-address <ipv6-addr> " - "[server-fib-id <fib-id>] [rx-fib-id <fib-id>] ", - .function = dhcpv6_proxy_set_command_fn, -}; -/* *INDENT-ON* */ - -static u8 * -format_dhcp6_proxy_server (u8 * s, va_list * args) -{ - dhcp_proxy_t *proxy = va_arg (*args, dhcp_proxy_t *); - fib_table_t *server_fib; - dhcp_server_t *server; - ip6_mfib_t *rx_fib; - - if (proxy == 0) - { - s = format (s, "%=14s%=16s%s", "RX FIB", "Src Address", - "Servers FIB,Address"); - return s; - } - - rx_fib = ip6_mfib_get (proxy->rx_fib_index); - - s = format (s, "%=14u%=16U", - rx_fib->table_id, - format_ip46_address, &proxy->dhcp_src_address, IP46_TYPE_ANY); - - vec_foreach (server, proxy->dhcp_servers) - { - server_fib = fib_table_get (server->server_fib_index, FIB_PROTOCOL_IP6); - s = format (s, "%u,%U ", - server_fib->ft_table_id, - format_ip46_address, &server->dhcp_server, IP46_TYPE_ANY); - } - - return s; -} - -static int -dhcp6_proxy_show_walk (dhcp_proxy_t * proxy, void *ctx) -{ - vlib_main_t *vm = ctx; - - vlib_cli_output (vm, "%U", format_dhcp6_proxy_server, proxy); - - return (1); -} - -static clib_error_t * -dhcpv6_proxy_show_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "%U", format_dhcp6_proxy_server, - NULL /* header line */ ); - - dhcp_proxy_walk (FIB_PROTOCOL_IP6, dhcp6_proxy_show_walk, vm); - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcpv6_proxy_show_command, static) = { - .path = "show dhcpv6 proxy", - .short_help = "Display dhcpv6 proxy info", - .function = dhcpv6_proxy_show_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcpv6_vss_command_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u8 is_del = 0, vss_type = VSS_TYPE_DEFAULT; - u8 *vpn_ascii_id = 0; - u32 oui = 0, fib_id = 0, tbl_id = ~0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "table %d", &tbl_id)) - ; - else if (unformat (input, "oui %d", &oui)) - vss_type = VSS_TYPE_VPN_ID; - else if (unformat (input, "vpn-id %d", &fib_id)) - vss_type = VSS_TYPE_VPN_ID; - else if (unformat (input, "vpn-ascii-id %s", &vpn_ascii_id)) - vss_type = VSS_TYPE_ASCII; - else if (unformat (input, "delete") || unformat (input, "del")) - is_del = 1; - else - break; - } - - if (tbl_id == ~0) - return clib_error_return (0, "no table ID specified."); - - int rv = dhcp_proxy_set_vss (FIB_PROTOCOL_IP6, tbl_id, vss_type, - vpn_ascii_id, oui, fib_id, is_del); - switch (rv) - { - case 0: - return 0; - case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "vss for table %d not found in pool.", - tbl_id); - default: - return clib_error_return (0, "BUG: rv %d", rv); - } -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcpv6_proxy_vss_command, static) = { - .path = "set dhcpv6 vss", - .short_help = "set dhcpv6 vss table <table-id> [oui <n> vpn-id <n> | vpn-ascii-id <text>]", - .function = dhcpv6_vss_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcpv6_vss_show_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - dhcp_vss_walk (FIB_PROTOCOL_IP6, dhcp_vss_show_walk, vm); - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcpv6_proxy_vss_show_command, static) = { - .path = "show dhcpv6 vss", - .short_help = "show dhcpv6 VSS", - .function = dhcpv6_vss_show_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dhcpv6_link_address_show_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - u32 sw_if_index0 = 0, sw_if_index; - vnet_sw_interface_t *swif; - ip6_address_t *ia0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - - if (unformat (input, "%U", - unformat_vnet_sw_interface, vnm, &sw_if_index0)) - { - swif = vnet_get_sw_interface (vnm, sw_if_index0); - sw_if_index = (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) ? - swif->unnumbered_sw_if_index : sw_if_index0; - ia0 = ip6_interface_first_address (&ip6_main, sw_if_index); - if (ia0) - { - vlib_cli_output (vm, "%=20s%=48s", "interface", "link-address"); - - vlib_cli_output (vm, "%=20U%=48U", - format_vnet_sw_if_index_name, vnm, - sw_if_index0, format_ip6_address, ia0); - } - else - vlib_cli_output (vm, "%=34s%=20U", - "No IPv6 address configured on", - format_vnet_sw_if_index_name, vnm, sw_if_index); - } - else - break; - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dhcpv6_proxy_address_show_command, static) = { - .path = "show dhcpv6 link-address interface", - .short_help = "show dhcpv6 link-address interface <interface>", - .function = dhcpv6_link_address_show_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp_api.c b/src/vnet/dhcp/dhcp_api.c deleted file mode 100644 index 252f2df7d6b..00000000000 --- a/src/vnet/dhcp/dhcp_api.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - *------------------------------------------------------------------ - * dhcp_api.c - dhcp api - * - * Copyright (c) 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. - *------------------------------------------------------------------ - */ - -#include <vnet/vnet.h> -#include <vlibmemory/api.h> - -#include <vnet/interface.h> -#include <vnet/api_errno.h> -#include <vnet/dhcp/dhcp_proxy.h> -#include <vnet/dhcp/client.h> -#include <vnet/dhcp/dhcp6_pd_client_dp.h> -#include <vnet/dhcp/dhcp6_ia_na_client_dp.h> -#include <vnet/dhcp/dhcp6_client_common_dp.h> -#include <vnet/fib/fib_table.h> -#include <vnet/ip/ip_types_api.h> - -#include <vnet/vnet_msg_enum.h> - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include <vnet/vnet_all_api_h.h> -#undef vl_printfun - -#include <vlibapi/api_helper_macros.h> - -#define foreach_vpe_api_msg \ -_(DHCP_PROXY_CONFIG,dhcp_proxy_config) \ -_(DHCP_PROXY_DUMP,dhcp_proxy_dump) \ -_(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss) \ -_(DHCP_CLIENT_CONFIG, dhcp_client_config) \ -_(DHCP_CLIENT_DUMP, dhcp_client_dump) \ -_(WANT_DHCP6_PD_REPLY_EVENTS, want_dhcp6_pd_reply_events) \ -_(DHCP6_PD_SEND_CLIENT_MESSAGE, dhcp6_pd_send_client_message) \ -_(WANT_DHCP6_REPLY_EVENTS, want_dhcp6_reply_events) \ -_(DHCP6_SEND_CLIENT_MESSAGE, dhcp6_send_client_message) \ -_(DHCP6_CLIENTS_ENABLE_DISABLE, dhcp6_clients_enable_disable) \ -_(DHCP6_DUID_LL_SET, dhcp6_duid_ll_set) - - -static void -vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp) -{ - vl_api_dhcp_proxy_set_vss_reply_t *rmp; - u8 *vpn_ascii_id; - int rv; - - mp->vpn_ascii_id[sizeof (mp->vpn_ascii_id) - 1] = 0; - vpn_ascii_id = format (0, "%s", mp->vpn_ascii_id); - rv = - dhcp_proxy_set_vss ((mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4), - ntohl (mp->tbl_id), ntohl (mp->vss_type), - vpn_ascii_id, ntohl (mp->oui), ntohl (mp->vpn_index), - mp->is_add == 0); - - REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY); -} - - -static void vl_api_dhcp_proxy_config_t_handler - (vl_api_dhcp_proxy_config_t * mp) -{ - vl_api_dhcp_proxy_set_vss_reply_t *rmp; - ip46_address_t src, server; - int rv = -1; - - if (mp->dhcp_src_address.af != mp->dhcp_server.af) - { - rv = VNET_API_ERROR_INVALID_ARGUMENT; - goto reply; - } - - ip_address_decode (&mp->dhcp_src_address, &src); - ip_address_decode (&mp->dhcp_server, &server); - - if (mp->dhcp_src_address.af == ADDRESS_IP4) - { - rv = dhcp4_proxy_set_server (&server, - &src, - (u32) ntohl (mp->rx_vrf_id), - (u32) ntohl (mp->server_vrf_id), - (int) (mp->is_add == 0)); - } - else - { - rv = dhcp6_proxy_set_server (&server, - &src, - (u32) ntohl (mp->rx_vrf_id), - (u32) ntohl (mp->server_vrf_id), - (int) (mp->is_add == 0)); - } - -reply: - REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY); -} - -static void -vl_api_dhcp_proxy_dump_t_handler (vl_api_dhcp_proxy_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return;; - - dhcp_proxy_dump ((mp->is_ip6 == 1 ? - FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4), reg, mp->context); -} - -void -dhcp_send_details (fib_protocol_t proto, - void *opaque, u32 context, dhcp_proxy_t * proxy) -{ - vl_api_dhcp_proxy_details_t *mp; - vl_api_registration_t *reg = opaque; - vl_api_dhcp_server_t *v_server; - dhcp_server_t *server; - fib_table_t *s_fib; - dhcp_vss_t *vss; - u32 count; - size_t n; - - count = vec_len (proxy->dhcp_servers); - n = sizeof (*mp) + (count * sizeof (vl_api_dhcp_server_t)); - mp = vl_msg_api_alloc (n); - if (!mp) - return; - clib_memset (mp, 0, n); - mp->_vl_msg_id = ntohs (VL_API_DHCP_PROXY_DETAILS); - mp->context = context; - mp->count = count; - - mp->is_ipv6 = (proto == FIB_PROTOCOL_IP6); - mp->rx_vrf_id = - htonl (dhcp_proxy_rx_table_get_table_id (proto, proxy->rx_fib_index)); - - vss = dhcp_get_vss_info (&dhcp_proxy_main, proxy->rx_fib_index, proto); - - if (vss) - { - mp->vss_type = ntohl (vss->vss_type); - if (vss->vss_type == VSS_TYPE_ASCII) - { - u32 id_len = vec_len (vss->vpn_ascii_id); - clib_memcpy (mp->vss_vpn_ascii_id, vss->vpn_ascii_id, id_len); - } - else if (vss->vss_type == VSS_TYPE_VPN_ID) - { - u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8) - + ((u32) vss->vpn_id[2]); - u32 fib_id = ((u32) vss->vpn_id[3] << 24) + - ((u32) vss->vpn_id[4] << 16) + ((u32) vss->vpn_id[5] << 8) + - ((u32) vss->vpn_id[6]); - mp->vss_oui = htonl (oui); - mp->vss_fib_id = htonl (fib_id); - } - } - else - mp->vss_type = VSS_TYPE_INVALID; - - vec_foreach_index (count, proxy->dhcp_servers) - { - server = &proxy->dhcp_servers[count]; - v_server = &mp->servers[count]; - - s_fib = fib_table_get (server->server_fib_index, proto); - - v_server->server_vrf_id = htonl (s_fib->ft_table_id); - - if (mp->is_ipv6) - { - memcpy (&v_server->dhcp_server.un, &server->dhcp_server.ip6, 16); - } - else - { - /* put the address in the first bytes */ - memcpy (&v_server->dhcp_server.un, &server->dhcp_server.ip4, 4); - } - } - - if (mp->is_ipv6) - { - memcpy (&mp->dhcp_src_address.un, &proxy->dhcp_src_address.ip6, 16); - } - else - { - /* put the address in the first bytes */ - memcpy (&mp->dhcp_src_address.un, &proxy->dhcp_src_address.ip4, 4); - } - vl_api_send_msg (reg, (u8 *) mp); -} - -static void -dhcp_client_lease_encode (vl_api_dhcp_lease_t * lease, - const dhcp_client_t * client) -{ - size_t len; - u8 i; - - lease->is_ipv6 = 0; // only support IPv6 clients - lease->sw_if_index = ntohl (client->sw_if_index); - lease->state = ntohl (client->state); - len = clib_min (sizeof (lease->hostname) - 1, vec_len (client->hostname)); - clib_memcpy (&lease->hostname, client->hostname, len); - lease->hostname[len] = 0; - - lease->mask_width = client->subnet_mask_width; - clib_memcpy (&lease->host_address.un, (u8 *) & client->leased_address, - sizeof (ip4_address_t)); - clib_memcpy (&lease->router_address.un, (u8 *) & client->router_address, - sizeof (ip4_address_t)); - - lease->count = vec_len (client->domain_server_address); - for (i = 0; i < lease->count; i++) - clib_memcpy (&lease->domain_server[i].address, - (u8 *) & client->domain_server_address[i], - sizeof (ip4_address_t)); - - clib_memcpy (&lease->host_mac[0], client->client_hardware_address, 6); -} - -static void -dhcp_client_data_encode (vl_api_dhcp_client_t * vclient, - const dhcp_client_t * client) -{ - size_t len; - - vclient->sw_if_index = ntohl (client->sw_if_index); - len = clib_min (sizeof (vclient->hostname) - 1, vec_len (client->hostname)); - clib_memcpy (&vclient->hostname, client->hostname, len); - vclient->hostname[len] = 0; - - len = clib_min (sizeof (vclient->id) - 1, - vec_len (client->client_identifier)); - clib_memcpy (&vclient->id, client->client_identifier, len); - vclient->id[len] = 0; - - if (NULL != client->event_callback) - vclient->want_dhcp_event = 1; - else - vclient->want_dhcp_event = 0; - vclient->set_broadcast_flag = client->set_broadcast_flag; - vclient->dscp = ip_dscp_encode (client->dscp); - vclient->pid = client->pid; -} - -static void -dhcp_compl_event_callback (u32 client_index, const dhcp_client_t * client) -{ - vl_api_registration_t *reg; - vl_api_dhcp_compl_event_t *mp; - - reg = vl_api_client_index_to_registration (client_index); - if (!reg) - return; - - mp = vl_msg_api_alloc (sizeof (*mp)); - mp->client_index = client_index; - mp->pid = client->pid; - dhcp_client_lease_encode (&mp->lease, client); - - mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT); - - vl_api_send_msg (reg, (u8 *) mp); -} - -static void vl_api_dhcp_client_config_t_handler - (vl_api_dhcp_client_config_t * mp) -{ - vlib_main_t *vm = vlib_get_main (); - vl_api_dhcp_client_config_reply_t *rmp; - u32 sw_if_index; - ip_dscp_t dscp; - int rv = 0; - - VALIDATE_SW_IF_INDEX (&(mp->client)); - - sw_if_index = ntohl (mp->client.sw_if_index); - dscp = ip_dscp_decode (mp->client.dscp); - - rv = dhcp_client_config (mp->is_add, - mp->client_index, - vm, - sw_if_index, - mp->client.hostname, - mp->client.id, - (mp->client.want_dhcp_event ? - dhcp_compl_event_callback : - NULL), - mp->client.set_broadcast_flag, - dscp, mp->client.pid); - - BAD_SW_IF_INDEX_LABEL; - REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY); -} - -typedef struct dhcp_client_send_walk_ctx_t_ -{ - vl_api_registration_t *reg; - u32 context; -} dhcp_client_send_walk_ctx_t; - -static int -send_dhcp_client_entry (const dhcp_client_t * client, void *arg) -{ - dhcp_client_send_walk_ctx_t *ctx; - vl_api_dhcp_client_details_t *mp; - - ctx = arg; - - mp = vl_msg_api_alloc (sizeof (*mp)); - clib_memset (mp, 0, sizeof (*mp)); - - mp->_vl_msg_id = ntohs (VL_API_DHCP_CLIENT_DETAILS); - mp->context = ctx->context; - - dhcp_client_data_encode (&mp->client, client); - dhcp_client_lease_encode (&mp->lease, client); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (1); -} - -static void -vl_api_dhcp_client_dump_t_handler (vl_api_dhcp_client_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - dhcp_client_send_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - dhcp_client_walk (send_dhcp_client_entry, &ctx); -} - -/* - * dhcp_api_hookup - * Add vpe's API message handlers to the table. - * vlib has already mapped shared memory and - * added the client registration handlers. - * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() - */ -#define vl_msg_name_crc_list -#include <vnet/vnet_all_api_h.h> -#undef vl_msg_name_crc_list - -static void -setup_message_id_table (api_main_t * am) -{ -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); - foreach_vl_msg_name_crc_dhcp; -#undef _ -} - -static clib_error_t * -dhcp_api_hookup (vlib_main_t * vm) -{ - api_main_t *am = &api_main; - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_vpe_api_msg; -#undef _ - - /* - * Set up the (msg_name, crc, message-id) table - */ - setup_message_id_table (am); - - dhcp6_pd_set_publisher_node (dhcp6_pd_reply_process_node.index, - DHCP6_PD_DP_REPLY_REPORT); - dhcp6_set_publisher_node (dhcp6_reply_process_node.index, - DHCP6_DP_REPLY_REPORT); - - return 0; -} - -VLIB_API_INIT_FUNCTION (dhcp_api_hookup); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp_client_detect.c b/src/vnet/dhcp/dhcp_client_detect.c deleted file mode 100644 index c79970d1456..00000000000 --- a/src/vnet/dhcp/dhcp_client_detect.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * DHCP feature; applied as an input feature to select DHCP packets - * - * 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 <vnet/dhcp/client.h> -#include <vnet/udp/udp.h> - -#define foreach_dhcp_client_detect \ - _(EXTRACT, "Extract") - -typedef enum -{ -#define _(sym,str) DHCP_CLIENT_DETECT_ERROR_##sym, - foreach_dhcp_client_detect -#undef _ - DHCP_CLIENT_DETECT_N_ERROR, -} dhcp_client_detect_error_t; - -static char *dhcp_client_detect_error_strings[] = { -#define _(sym,string) string, - foreach_dhcp_client_detect -#undef _ -}; - -typedef enum -{ -#define _(sym,str) DHCP_CLIENT_DETECT_NEXT_##sym, - foreach_dhcp_client_detect -#undef _ - DHCP_CLIENT_DETECT_N_NEXT, -} dhcp_client_detect_next_t; - -/** - * per-packet trace data - */ -typedef struct dhcp_client_detect_trace_t_ -{ - /* per-pkt trace data */ - u8 extracted; -} dhcp_client_detect_trace_t; - -VLIB_NODE_FN (dhcp_client_detect_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - dhcp_client_detect_next_t next_index; - u16 dhcp_client_port_network_order; - u32 n_left_from, *from, *to_next; - u32 extractions; - - dhcp_client_port_network_order = - clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client); - next_index = 0; - extractions = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - /* - * This loop is optimised not so we can really quickly process DHCp - * offers... but so we can quickly sift them out when the interface - * is also receiving 'normal' packets - */ - while (n_left_from >= 8 && n_left_to_next >= 4) - { - udp_header_t *udp0, *udp1, *udp2, *udp3; - ip4_header_t *ip0, *ip1, *ip2, *ip3; - vlib_buffer_t *b0, *b1, *b2, *b3; - u32 next0, next1, next2, next3; - u32 bi0, bi1, bi2, bi3; - - next0 = next1 = next2 = next3 = ~0; - bi0 = to_next[0] = from[0]; - bi1 = to_next[1] = from[1]; - bi2 = to_next[2] = from[2]; - bi3 = to_next[3] = from[3]; - - /* Prefetch next iteration. */ - { - vlib_buffer_t *p2, *p3, *p4, *p5; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - p4 = vlib_get_buffer (vm, from[4]); - p5 = vlib_get_buffer (vm, from[5]); - - vlib_prefetch_buffer_header (p2, STORE); - vlib_prefetch_buffer_header (p3, STORE); - vlib_prefetch_buffer_header (p4, STORE); - vlib_prefetch_buffer_header (p5, STORE); - - CLIB_PREFETCH (p2->data, sizeof (ip0[0]) + sizeof (udp0[0]), - STORE); - CLIB_PREFETCH (p3->data, sizeof (ip0[0]) + sizeof (udp0[0]), - STORE); - CLIB_PREFETCH (p4->data, sizeof (ip0[0]) + sizeof (udp0[0]), - STORE); - CLIB_PREFETCH (p5->data, sizeof (ip0[0]) + sizeof (udp0[0]), - STORE); - } - - from += 4; - to_next += 4; - n_left_from -= 4; - n_left_to_next -= 4; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - b2 = vlib_get_buffer (vm, bi2); - b3 = vlib_get_buffer (vm, bi3); - ip0 = vlib_buffer_get_current (b0); - ip1 = vlib_buffer_get_current (b1); - ip2 = vlib_buffer_get_current (b2); - ip3 = vlib_buffer_get_current (b2); - - vnet_feature_next (&next0, b0); - vnet_feature_next (&next1, b1); - vnet_feature_next (&next2, b2); - vnet_feature_next (&next3, b3); - - if (ip0->protocol == IP_PROTOCOL_UDP) - { - udp0 = (udp_header_t *) (ip0 + 1); - - if (dhcp_client_port_network_order == udp0->dst_port) - { - next0 = DHCP_CLIENT_DETECT_NEXT_EXTRACT; - extractions++; - } - } - if (ip1->protocol == IP_PROTOCOL_UDP) - { - udp1 = (udp_header_t *) (ip1 + 1); - - if (dhcp_client_port_network_order == udp1->dst_port) - { - next1 = DHCP_CLIENT_DETECT_NEXT_EXTRACT; - extractions++; - } - } - if (ip2->protocol == IP_PROTOCOL_UDP) - { - udp2 = (udp_header_t *) (ip2 + 1); - - if (dhcp_client_port_network_order == udp2->dst_port) - { - next2 = DHCP_CLIENT_DETECT_NEXT_EXTRACT; - extractions++; - } - } - if (ip3->protocol == IP_PROTOCOL_UDP) - { - udp3 = (udp_header_t *) (ip3 + 1); - - if (dhcp_client_port_network_order == udp3->dst_port) - { - next3 = DHCP_CLIENT_DETECT_NEXT_EXTRACT; - extractions++; - } - } - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_client_detect_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->extracted = (next0 == DHCP_CLIENT_DETECT_NEXT_EXTRACT); - } - if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_client_detect_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->extracted = (next1 == DHCP_CLIENT_DETECT_NEXT_EXTRACT); - } - if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_client_detect_trace_t *t = - vlib_add_trace (vm, node, b2, sizeof (*t)); - t->extracted = (next2 == DHCP_CLIENT_DETECT_NEXT_EXTRACT); - } - if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_client_detect_trace_t *t = - vlib_add_trace (vm, node, b3, sizeof (*t)); - t->extracted = (next3 == DHCP_CLIENT_DETECT_NEXT_EXTRACT); - } - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x4 (vm, node, next_index, - to_next, n_left_to_next, - bi0, bi1, bi2, bi3, - next0, next1, next2, next3); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - udp_header_t *udp0; - vlib_buffer_t *b0; - ip4_header_t *ip0; - u32 next0 = ~0; - u32 bi0; - - 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); - ip0 = vlib_buffer_get_current (b0); - - /* - * when this feature is applied on an interface that is already - * accepting packets (because e.g. the interface has other addresses - * assigned) we are looking for the preverbial needle in the haystack - * so assume the packet is not the one we are looking for. - */ - vnet_feature_next (&next0, b0); - - /* - * all we are looking for here is DHCP/BOOTP packet-to-client - * UDO port. - */ - if (ip0->protocol == IP_PROTOCOL_UDP) - { - udp0 = (udp_header_t *) (ip0 + 1); - - if (dhcp_client_port_network_order == udp0->dst_port) - { - next0 = DHCP_CLIENT_DETECT_NEXT_EXTRACT; - extractions++; - } - } - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dhcp_client_detect_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->extracted = (next0 == DHCP_CLIENT_DETECT_NEXT_EXTRACT); - } - - /* verify speculative enqueue, maybe switch current next frame */ - 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_node_increment_counter (vm, node->node_index, - DHCP_CLIENT_DETECT_ERROR_EXTRACT, extractions); - - return frame->n_vectors; -} - -/* packet trace format function */ -static u8 * -format_dhcp_client_detect_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 *); - dhcp_client_detect_trace_t *t = - va_arg (*args, dhcp_client_detect_trace_t *); - - s = format (s, "dhcp-client-detect: %s", (t->extracted ? "yes" : "no")); - - return s; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dhcp_client_detect_node) = { - .name = "ip4-dhcp-client-detect", - .vector_size = sizeof (u32), - .format_trace = format_dhcp_client_detect_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(dhcp_client_detect_error_strings), - .error_strings = dhcp_client_detect_error_strings, - - .n_next_nodes = DHCP_CLIENT_DETECT_N_NEXT, - .next_nodes = { - /* - * Jump straight to the UDP dispatch node thus avoiding - * the RPF checks in ip4-local that will fail - */ - [DHCP_CLIENT_DETECT_NEXT_EXTRACT] = "ip4-udp-lookup", - }, -}; - -VNET_FEATURE_INIT (ip4_dvr_reinject_feat_node, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "ip4-dhcp-client-detect", - .runs_before = VNET_FEATURES ("ip4-not-enabled"), -}; - -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp_proxy.c b/src/vnet/dhcp/dhcp_proxy.c deleted file mode 100644 index 9a69041bc1d..00000000000 --- a/src/vnet/dhcp/dhcp_proxy.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * proxy_node.c: common dhcp v4 and v6 proxy node 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 <vnet/dhcp/dhcp_proxy.h> -#include <vnet/fib/fib_table.h> -#include <vnet/mfib/mfib_table.h> - -/** - * @brief Shard 4/6 instance of DHCP main - */ -dhcp_proxy_main_t dhcp_proxy_main; - -static void -dhcp_proxy_rx_table_lock (fib_protocol_t proto, u32 fib_index) -{ - if (FIB_PROTOCOL_IP4 == proto) - fib_table_lock (fib_index, proto, FIB_SOURCE_DHCP); - else - mfib_table_lock (fib_index, proto, MFIB_SOURCE_DHCP); -} - -static void -dhcp_proxy_rx_table_unlock (fib_protocol_t proto, u32 fib_index) -{ - if (FIB_PROTOCOL_IP4 == proto) - fib_table_unlock (fib_index, proto, FIB_SOURCE_DHCP); - else - mfib_table_unlock (fib_index, proto, MFIB_SOURCE_DHCP); -} - -u32 -dhcp_proxy_rx_table_get_table_id (fib_protocol_t proto, u32 fib_index) -{ - if (FIB_PROTOCOL_IP4 == proto) - { - fib_table_t *fib; - - fib = fib_table_get (fib_index, proto); - - return (fib->ft_table_id); - } - else - { - mfib_table_t *mfib; - - mfib = mfib_table_get (fib_index, proto); - - return (mfib->mft_table_id); - } -} - -void -dhcp_proxy_walk (fib_protocol_t proto, dhcp_proxy_walk_fn_t fn, void *ctx) -{ - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - dhcp_proxy_t *server; - u32 server_index, i; - - vec_foreach_index (i, dpm->dhcp_server_index_by_rx_fib_index[proto]) - { - server_index = dpm->dhcp_server_index_by_rx_fib_index[proto][i]; - if (~0 == server_index) - continue; - - server = pool_elt_at_index (dpm->dhcp_servers[proto], server_index); - - if (!fn (server, ctx)) - break; - } -} - -void -dhcp_vss_walk (fib_protocol_t proto, dhcp_vss_walk_fn_t fn, void *ctx) -{ - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - mfib_table_t *mfib; - dhcp_vss_t *vss; - u32 vss_index, i; - fib_table_t *fib; - - vec_foreach_index (i, dpm->vss_index_by_rx_fib_index[proto]) - { - vss_index = dpm->vss_index_by_rx_fib_index[proto][i]; - if (~0 == vss_index) - continue; - - vss = pool_elt_at_index (dpm->vss[proto], vss_index); - - if (FIB_PROTOCOL_IP4 == proto) - { - fib = fib_table_get (i, proto); - - if (!fn (vss, fib->ft_table_id, ctx)) - break; - } - else - { - mfib = mfib_table_get (i, proto); - - if (!fn (vss, mfib->mft_table_id, ctx)) - break; - } - } -} - -static u32 -dhcp_proxy_server_find (dhcp_proxy_t * proxy, - fib_protocol_t proto, - ip46_address_t * addr, u32 server_table_id) -{ - dhcp_server_t *server; - u32 ii, fib_index; - - vec_foreach_index (ii, proxy->dhcp_servers) - { - server = &proxy->dhcp_servers[ii]; - fib_index = fib_table_find (proto, server_table_id); - - if (ip46_address_is_equal (&server->dhcp_server, - addr) && - (server->server_fib_index == fib_index)) - { - return (ii); - } - } - return (~0); -} - -int -dhcp_proxy_server_del (fib_protocol_t proto, - u32 rx_fib_index, - ip46_address_t * addr, u32 server_table_id) -{ - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - dhcp_proxy_t *proxy = 0; - - proxy = dhcp_get_proxy (dpm, rx_fib_index, proto); - - if (NULL != proxy) - { - dhcp_server_t *server; - u32 index; - - index = dhcp_proxy_server_find (proxy, proto, addr, server_table_id); - - if (~0 != index) - { - server = &proxy->dhcp_servers[index]; - fib_table_unlock (server->server_fib_index, proto, FIB_SOURCE_DHCP); - - vec_del1 (proxy->dhcp_servers, index); - - if (0 == vec_len (proxy->dhcp_servers)) - { - /* no servers left, delete the proxy config */ - dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] = - ~0; - vec_free (proxy->dhcp_servers); - pool_put (dpm->dhcp_servers[proto], proxy); - return (1); - } - } - } - - /* the proxy still exists */ - return (0); -} - -int -dhcp_proxy_server_add (fib_protocol_t proto, - ip46_address_t * addr, - ip46_address_t * src_address, - u32 rx_fib_index, u32 server_table_id) -{ - dhcp_proxy_main_t *dpm = &dhcp_proxy_main; - dhcp_proxy_t *proxy = 0; - int new = 0; - - proxy = dhcp_get_proxy (dpm, rx_fib_index, proto); - - if (NULL == proxy) - { - vec_validate_init_empty (dpm->dhcp_server_index_by_rx_fib_index[proto], - rx_fib_index, ~0); - - pool_get (dpm->dhcp_servers[proto], proxy); - clib_memset (proxy, 0, sizeof (*proxy)); - new = 1; - - dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] = - proxy - dpm->dhcp_servers[proto]; - - proxy->dhcp_src_address = *src_address; - proxy->rx_fib_index = rx_fib_index; - } - else - { - if (~0 != dhcp_proxy_server_find (proxy, proto, addr, server_table_id)) - { - return (new); - } - } - - dhcp_server_t server = { - .dhcp_server = *addr, - .server_fib_index = fib_table_find_or_create_and_lock (proto, - server_table_id, - FIB_SOURCE_DHCP), - }; - - vec_add1 (proxy->dhcp_servers, server); - - return (new); -} - -typedef struct dhcp4_proxy_dump_walk_ctx_t_ -{ - fib_protocol_t proto; - void *opaque; - u32 context; -} dhcp_proxy_dump_walk_cxt_t; - -static int -dhcp_proxy_dump_walk (dhcp_proxy_t * proxy, void *arg) -{ - dhcp_proxy_dump_walk_cxt_t *ctx = arg; - - dhcp_send_details (ctx->proto, ctx->opaque, ctx->context, proxy); - - return (1); -} - -void -dhcp_proxy_dump (fib_protocol_t proto, void *opaque, u32 context) -{ - dhcp_proxy_dump_walk_cxt_t ctx = { - .proto = proto, - .opaque = opaque, - .context = context, - }; - dhcp_proxy_walk (proto, dhcp_proxy_dump_walk, &ctx); -} - -int -dhcp_vss_show_walk (dhcp_vss_t * vss, u32 rx_table_id, void *ctx) -{ - vlib_main_t *vm = ctx; - - if (vss->vss_type == VSS_TYPE_VPN_ID) - { - u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8) - + ((u32) vss->vpn_id[2]); - u32 fib_id = ((u32) vss->vpn_id[3] << 24) + ((u32) vss->vpn_id[4] << 16) - + ((u32) vss->vpn_id[5] << 8) + ((u32) vss->vpn_id[6]); - vlib_cli_output (vm, " fib_table: %d oui: %d vpn_index: %d", - rx_table_id, oui, fib_id); - } - else if (vss->vss_type == VSS_TYPE_ASCII) - vlib_cli_output (vm, " fib_table: %d vpn_id: %s", - rx_table_id, vss->vpn_ascii_id); - else - vlib_cli_output (vm, " fib_table: %d default global vpn", rx_table_id); - - return (1); -} - -void -update_vss (dhcp_vss_t * v, - u8 vss_type, u8 * vpn_ascii_id, u32 oui, u32 vpn_index) -{ - v->vss_type = vss_type; - if (v->vpn_ascii_id) - { - if (v->vpn_ascii_id == (u8 *) ~ 0) - v->vpn_ascii_id = 0; - else - vec_free (v->vpn_ascii_id); - } - - if (vss_type == VSS_TYPE_ASCII) - v->vpn_ascii_id = vpn_ascii_id; - else if (vss_type == VSS_TYPE_VPN_ID) - { - v->vpn_id[0] = (oui >> 16) & 0xff; - v->vpn_id[1] = (oui >> 8) & 0xff; - v->vpn_id[2] = (oui >> 0) & 0xff; - v->vpn_id[3] = (vpn_index >> 24) & 0xff; - v->vpn_id[4] = (vpn_index >> 16) & 0xff; - v->vpn_id[5] = (vpn_index >> 8) & 0xff; - v->vpn_id[6] = (vpn_index >> 0) & 0xff; - } -} - -int -dhcp_proxy_set_vss (fib_protocol_t proto, - u32 tbl_id, - u8 vss_type, - u8 * vpn_ascii_id, u32 oui, u32 vpn_index, u8 is_del) -{ - dhcp_proxy_main_t *dm = &dhcp_proxy_main; - dhcp_vss_t *v = NULL; - u32 rx_fib_index; - int rc = 0; - - if (proto == FIB_PROTOCOL_IP4) - rx_fib_index = fib_table_find_or_create_and_lock (proto, tbl_id, - FIB_SOURCE_DHCP); - else - rx_fib_index = mfib_table_find_or_create_and_lock (proto, tbl_id, - MFIB_SOURCE_DHCP); - v = dhcp_get_vss_info (dm, rx_fib_index, proto); - - if (NULL != v) - { - if (is_del) - { - /* release the lock held on the table when the VSS - * info was created */ - dhcp_proxy_rx_table_unlock (proto, rx_fib_index); - - vec_free (v->vpn_ascii_id); - pool_put (dm->vss[proto], v); - dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0; - } - else - { - update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index); - } - } - else - { - if (is_del) - rc = VNET_API_ERROR_NO_SUCH_ENTRY; - else - { - /* create a new entry */ - vec_validate_init_empty (dm->vss_index_by_rx_fib_index[proto], - rx_fib_index, ~0); - - /* hold a lock on the table whilst the VSS info exist */ - pool_get (dm->vss[proto], v); - update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index); - dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = - v - dm->vss[proto]; - dhcp_proxy_rx_table_lock (proto, rx_fib_index); - } - } - - /* Release the lock taken during the create_or_lock at the start */ - dhcp_proxy_rx_table_unlock (proto, rx_fib_index); - - return (rc); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dhcp/dhcp_proxy.h b/src/vnet/dhcp/dhcp_proxy.h deleted file mode 100644 index 60c4eb838c8..00000000000 --- a/src/vnet/dhcp/dhcp_proxy.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * dhcp_proxy.h: DHCP v4 & v6 proxy common functions/types - * - * 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_dhcp_proxy_h -#define included_dhcp_proxy_h - -#include <vnet/vnet.h> -#include <vnet/dhcp/dhcp4_packet.h> -#include <vnet/ethernet/ethernet.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> -#include <vnet/udp/udp.h> - -typedef enum -{ -#define dhcp_proxy_error(n,s) DHCP_PROXY_ERROR_##n, -#include <vnet/dhcp/dhcp4_proxy_error.def> -#undef dhcp_proxy_error - DHCP_PROXY_N_ERROR, -} dhcp_proxy_error_t; - -typedef enum -{ -#define dhcpv6_proxy_error(n,s) DHCPV6_PROXY_ERROR_##n, -#include <vnet/dhcp/dhcp6_proxy_error.def> -#undef dhcpv6_proxy_error - DHCPV6_PROXY_N_ERROR, -} dhcpv6_proxy_error_t; - -/* flags to indicate which DHCP ports should be or have been registered */ -typedef enum -{ - DHCP_PORT_REG_CLIENT = 0x1, - DHCP_PORT_REG_SERVER = 0x2, -} dhcp_port_reg_flags_t; - -/** - * @brief The Virtual Sub-net Selection information for a given RX FIB - */ -typedef struct dhcp_vss_t_ -{ - /** - * @brief VSS type as defined in RFC 6607: - * 0 for NVT ASCII VPN Identifier - * 1 for RFC 2685 VPN-ID of 7 octects - 3 bytes OUI & 4 bytes VPN index - * 255 for global default VPN - */ - u8 vss_type; -#define VSS_TYPE_ASCII 0 -#define VSS_TYPE_VPN_ID 1 -#define VSS_TYPE_INVALID 123 -#define VSS_TYPE_DEFAULT 255 - /** - * @brief Type 1 VPN-ID - */ - u8 vpn_id[7]; - /** - * @brief Type 0 ASCII VPN Identifier - */ - u8 *vpn_ascii_id; -} dhcp_vss_t; - -/** - * @brief A representation of a single DHCP Server within a given VRF config - */ -typedef struct dhcp_server_t_ -{ - /** - * @brief The address of the DHCP server to which to relay the client's - * messages - */ - ip46_address_t dhcp_server; - - /** - * @brief The FIB index (not the external Table-ID) in which the server - * is reachable. - */ - u32 server_fib_index; -} dhcp_server_t; - -/** - * @brief A DHCP proxy representation fpr per-client VRF config - */ -typedef struct dhcp_proxy_t_ -{ - /** - * @brief The set of DHCP servers to which messages are relayed. - * If multiple servers are configured then discover/solict messages - * are relayed to each. A cookie is maintained for the relay, and only - * one message is replayed to the client, based on the presence of the - * cookie. - * The expectation is there are only 1 or 2 servers, hence no fancy DB. - */ - dhcp_server_t *dhcp_servers; - - /** - * @brief Hash table of pending requets key'd on the clients MAC address - */ - uword *dhcp_pending; - - /** - * @brief A lock for the pending request DB. - */ - int lock; - - /** - * @brief The source address to use in relayed messaes - */ - ip46_address_t dhcp_src_address; - - /** - * @brief The FIB index (not the external Table-ID) in which the client - * is resides. - */ - u32 rx_fib_index; -} dhcp_proxy_t; - -#define DHCP_N_PROTOS (FIB_PROTOCOL_IP6 + 1) - -/** - * @brief Collection of global DHCP proxy data - */ -typedef struct -{ - /* Pool of DHCP servers */ - dhcp_proxy_t *dhcp_servers[DHCP_N_PROTOS]; - - /* Pool of selected DHCP server. Zero is the default server */ - u32 *dhcp_server_index_by_rx_fib_index[DHCP_N_PROTOS]; - - /* to drop pkts in server-to-client direction */ - u32 error_drop_node_index; - - dhcp_vss_t *vss[DHCP_N_PROTOS]; - - /* hash lookup specific vrf_id -> option 82 vss suboption */ - u32 *vss_index_by_rx_fib_index[DHCP_N_PROTOS]; - - /* flags to indicate which udp ports have been registered */ - int udp_ports_registered; - - /* convenience */ - vlib_main_t *vlib_main; - -} dhcp_proxy_main_t; - -extern dhcp_proxy_main_t dhcp_proxy_main; - -/** - * @brief Register the dhcp client and/or server ports, if not already done - */ -void dhcp_maybe_register_udp_ports (dhcp_port_reg_flags_t ports); - -/** - * @brief Send the details of a proxy session to the API client during a dump - */ -void dhcp_send_details (fib_protocol_t proto, - void *opaque, u32 context, dhcp_proxy_t * proxy); - -/** - * @brief Show (on CLI) a VSS config during a show walk - */ -int dhcp_vss_show_walk (dhcp_vss_t * vss, u32 rx_table_id, void *ctx); - -/** - * @brief Configure/set a new VSS info - */ -int dhcp_proxy_set_vss (fib_protocol_t proto, - u32 tbl_id, - u8 vss_type, - u8 * vpn_ascii_id, u32 oui, u32 vpn_index, u8 is_del); - -/** - * @brief Dump the proxy configs to the API - */ -void dhcp_proxy_dump (fib_protocol_t proto, void *opaque, u32 context); - -/** - * @brief Add a new DHCP proxy server configuration. - * @return 1 is the config is new, - * 0 otherwise (implying a modify of an existing) - */ -int dhcp_proxy_server_add (fib_protocol_t proto, - ip46_address_t * addr, - ip46_address_t * src_address, - u32 rx_fib_iindex, u32 server_table_id); - -/** - * @brief Delete a DHCP proxy config - * @return 1 if the proxy is deleted, 0 otherwise - */ -int dhcp_proxy_server_del (fib_protocol_t proto, - u32 rx_fib_index, - ip46_address_t * addr, u32 server_table_id); - -u32 dhcp_proxy_rx_table_get_table_id (fib_protocol_t proto, u32 fib_index); - -/** - * @brief Callback function invoked for each DHCP proxy entry - * return 0 to break the walk, non-zero otherwise. - */ -typedef int (*dhcp_proxy_walk_fn_t) (dhcp_proxy_t * server, void *ctx); - -/** - * @brief Walk/Visit each DHCP proxy server - */ -void dhcp_proxy_walk (fib_protocol_t proto, - dhcp_proxy_walk_fn_t fn, void *ctx); - -/** - * @brief Callback function invoked for each DHCP VSS entry - * return 0 to break the walk, non-zero otherwise. - */ -typedef int (*dhcp_vss_walk_fn_t) (dhcp_vss_t * server, - u32 rx_table_id, void *ctx); - -/** - * @brief Walk/Visit each DHCP proxy VSS - */ -void dhcp_vss_walk (fib_protocol_t proto, dhcp_vss_walk_fn_t fn, void *ctx); - -/** - * @brief Lock a proxy object to prevent simultaneous access of its - * pending store - */ -void dhcp_proxy_lock (dhcp_proxy_t * server); - -/** - * @brief Lock a proxy object to prevent simultaneous access of its - * pending store - */ -void dhcp_proxy_unlock (dhcp_proxy_t * server); - -/** - * @brief Get the VSS data for the FIB index - */ -static inline dhcp_vss_t * -dhcp_get_vss_info (dhcp_proxy_main_t * dm, - u32 rx_fib_index, fib_protocol_t proto) -{ - dhcp_vss_t *v = NULL; - - if (vec_len (dm->vss_index_by_rx_fib_index[proto]) > rx_fib_index && - dm->vss_index_by_rx_fib_index[proto][rx_fib_index] != ~0) - { - v = pool_elt_at_index (dm->vss[proto], - dm->vss_index_by_rx_fib_index[proto] - [rx_fib_index]); - } - - return (v); -} - -/** - * @brief Get the DHCP proxy server data for the FIB index - */ -static inline dhcp_proxy_t * -dhcp_get_proxy (dhcp_proxy_main_t * dm, - u32 rx_fib_index, fib_protocol_t proto) -{ - dhcp_proxy_t *s = NULL; - - if (vec_len (dm->dhcp_server_index_by_rx_fib_index[proto]) > rx_fib_index && - dm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] != ~0) - { - s = pool_elt_at_index (dm->dhcp_servers[proto], - dm->dhcp_server_index_by_rx_fib_index[proto] - [rx_fib_index]); - } - - return (s); -} - -int dhcp6_proxy_set_server (ip46_address_t * addr, - ip46_address_t * src_addr, - u32 rx_table_id, u32 server_table_id, int is_del); -int dhcp4_proxy_set_server (ip46_address_t * addr, - ip46_address_t * src_addr, - u32 rx_table_id, u32 server_table_id, int is_del); - -#endif /* included_dhcp_proxy_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |