Hi,

On Fri, 2014-01-03 at 17:40 +0800, Guoqiang Liu wrote:
> From: Zhang zhengguang <[email protected]>
> 
> According to DHCP protocol below:
>       rfc2131 4.3.2 DHCPREQUEST generated during INIT-REBOOT state
>       rfc2131 4.4.2 Initialization with known network address
> 
> For a favorite service which is connected before, when it is connected
> again and request IP address through DHCP, it doesn't need to broadcast
> DHCPDISCOVER message every time to get the IP address. It can request to
> reuse the previously allocated IP address, and broadcast a DHCPREQUEST
> message directly and omit the steps such as dhcp DISCOVER/OFFER/SELECT.

This description of how Init-Reboot enhances DHCP is fine. What also
would be of interest is a description of how this patch provides the
Init-Reboot functionality from a logical implementation starting point
and ending with either Bound or Init state. Choosing between a protocol
description and patch description I'd choose the latter; the RFC
references should anyhow be kept.

> Signed-off-by: Zhang zhengguang <[email protected]>
> ---
>  gdhcp/client.c |   70 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 66 insertions(+), 4 deletions(-)
> 
> diff --git a/gdhcp/client.c b/gdhcp/client.c
> index b24d19d..329faa0 100644
> --- a/gdhcp/client.c
> +++ b/gdhcp/client.c
> @@ -62,6 +62,7 @@ typedef enum _listen_mode {
>  
>  typedef enum _dhcp_client_state {
>       INIT_SELECTING,
> +     REBOOTING,
>       REQUESTING,
>       BOUND,
>       RENEWING,
> @@ -438,6 +439,30 @@ static int send_discover(GDHCPClient *dhcp_client, 
> uint32_t requested)
>                                       MAC_BCAST_ADDR, dhcp_client->ifindex);
>  }
>  
> +static int send_rebooting(GDHCPClient *dhcp_client)
> +{
> +     struct dhcp_packet packet;
> +     debug(dhcp_client, "sending DHCP rebooting request");
> +
> +     init_packet(dhcp_client, &packet, DHCPREQUEST);
> +
> +     packet.xid = dhcp_client->xid;
> +     packet.secs = dhcp_attempt_secs(dhcp_client);
> +
> +     dhcp_add_option_uint32(&packet, DHCP_REQUESTED_IP,
> +                                     dhcp_client->requested_ip);
> +
> +     dhcp_add_option_uint16(&packet, DHCP_MAX_SIZE, 576);
> +
> +     add_request_options(dhcp_client, &packet);
> +
> +     add_send_options(dhcp_client, &packet);
> +
> +     return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
> +                                     INADDR_BROADCAST, SERVER_PORT,
> +                                     MAC_BCAST_ADDR, dhcp_client->ifindex);
> +}
> +

This code should be factored in with send_select() so that the code for
sending a broadcasted DHCP Request packet is implemented only once.

>  static int send_select(GDHCPClient *dhcp_client)
>  {
>       struct dhcp_packet packet;
> @@ -1756,10 +1781,14 @@ static gboolean restart_dhcp_timeout(gpointer 
> user_data)
>  
>       debug(dhcp_client, "restart DHCP timeout");
>  
> -     dhcp_client->ack_retry_times++;
> -
> -     restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
> -
> +     if (dhcp_client->state == REBOOTING) {
> +             g_free(dhcp_client->last_address);
> +             dhcp_client->last_address = NULL;
> +             restart_dhcp(dhcp_client, 0);
> +     } else {
> +             dhcp_client->ack_retry_times++;
> +             restart_dhcp(dhcp_client, dhcp_client->ack_retry_times);
> +     }
>       return FALSE;
>  }
>  
> @@ -2330,6 +2359,7 @@ static gboolean listener_event(GIOChannel *channel, 
> GIOCondition condition,
>               start_request(dhcp_client);
>  
>               return TRUE;
> +     case REBOOTING:
>       case REQUESTING:
>       case RENEWING:
>       case REBINDING:
> @@ -2565,6 +2595,22 @@ static gboolean discover_timeout(gpointer user_data)
>       return FALSE;
>  }
>  
> +static gboolean reboot_timeout(gpointer user_data)
> +{
> +     GDHCPClient *dhcp_client = user_data;
> +     dhcp_client->retry_times = 0;
> +     dhcp_client->requested_ip = 0;
> +     dhcp_client->state = INIT_SELECTING;
> +     /*
> +      * We do not send the REQUESTED IP option because the server didn't
> +      * respond when we send DHCPREQUEST with the REQUESTED IP option in
> +      * init-reboot state
> +      */
> +     g_dhcp_client_start(dhcp_client, NULL);
> +
> +     return FALSE;
> +}
> +
>  static gboolean ipv4ll_defend_timeout(gpointer dhcp_data)
>  {
>       GDHCPClient *dhcp_client = dhcp_data;
> @@ -2753,6 +2799,21 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, 
> const char *last_address)
>                       dhcp_client->last_address = g_strdup(last_address);
>               }
>       }
> +
> +     if ((addr != 0) && (dhcp_client->type != G_DHCP_IPV4LL)) {
> +             debug(dhcp_client, "DHCP client start with state init_reboot");
> +             dhcp_client->requested_ip = addr;
> +             dhcp_client->state = REBOOTING;
> +             send_rebooting(dhcp_client);
> +
> +             dhcp_client->timeout = g_timeout_add_seconds_full(

Nitpick: the line could be wrapped after the equal sign.

> +                                                             G_PRIORITY_HIGH,
> +                                                             REQUEST_TIMEOUT,
> +                                                             reboot_timeout,
> +                                                             dhcp_client,
> +                                                             NULL);
> +             return 0;
> +     }
>       send_discover(dhcp_client, addr);
>  
>       dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
> @@ -2919,6 +2980,7 @@ char *g_dhcp_client_get_netmask(GDHCPClient 
> *dhcp_client)
>               if (option)
>                       return g_strdup(option->data);
>       case INIT_SELECTING:
> +     case REBOOTING:
>       case REQUESTING:
>       case RELEASED:
>       case IPV4LL_PROBE:

Otherwise looks good.

Cheers,

        Patrik


_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to