Changeset b417559 in mainline for uspace/srv/net/dhcp/dhcp.c


Ignore:
Timestamp:
2013-09-24T21:00:52Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b0602a3
Parents:
66ec63a
Message:

Retransmit DHCP discover and request messages on timeout. Introduce DHCP link states.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/dhcp/dhcp.c

    r66ec63a rb417559  
    3737#include <adt/list.h>
    3838#include <bitops.h>
     39#include <fibril_synch.h>
    3940#include <inet/addr.h>
    4041#include <inet/dnsr.h>
     
    5253#include "transport.h"
    5354
     55#define DHCP_DISCOVER_TIMEOUT_VAL (5 * 1000 * 1000)
     56#define DHCP_REQUEST_TIMEOUT_VAL (1 * 1000 * 1000)
     57
    5458#define MAX_MSG_SIZE 1024
    5559static uint8_t msgbuf[MAX_MSG_SIZE];
    5660
     61/** List of registered links (of dhcp_link_t) */
    5762static list_t dhcp_links;
     63
     64static void dhcpsrv_discover_timeout(void *);
     65static void dhcpsrv_request_timeout(void *);
     66
     67typedef enum {
     68        ds_bound,
     69        ds_init,
     70        ds_init_reboot,
     71        ds_rebinding,
     72        ds_renewing,
     73        ds_requesting,
     74        ds_selecting
     75} dhcp_state_t;
    5876
    5977typedef struct {
     
    7189
    7290typedef struct {
     91        /** Link to dhcp_links list */
    7392        link_t links;
     93        /** Link service ID */
    7494        service_id_t link_id;
     95        /** Link info */
    7596        inet_link_info_t link_info;
     97        /** Transport */
    7698        dhcp_transport_t dt;
     99        /** Transport timeout */
     100        fibril_timer_t *timeout;
     101        /** Link state */
     102        dhcp_state_t state;
     103        /** Last received offer */
     104        dhcp_offer_t offer;
    77105} dhcp_link_t;
    78106
     
    366394}
    367395
     396void dhcpsrv_links_init(void)
     397{
     398        list_initialize(&dhcp_links);
     399}
     400
     401static dhcp_link_t *dhcpsrv_link_find(service_id_t link_id)
     402{
     403        list_foreach(dhcp_links, links, dhcp_link_t, dlink) {
     404                if (dlink->link_id == link_id)
     405                        return dlink;
     406        }
     407
     408        return NULL;
     409}
     410
    368411int dhcpsrv_link_add(service_id_t link_id)
    369412{
     
    372415
    373416        log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_link_add(%zu)", link_id);
     417
     418        if (dhcpsrv_link_find(link_id) != NULL) {
     419                log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu already added",
     420                    link_id);
     421                return EEXIST;
     422        }
    374423
    375424        dlink = calloc(1, sizeof(dhcp_link_t));
     
    378427
    379428        dlink->link_id = link_id;
     429        dlink->timeout = fibril_timer_create();
     430        if (dlink->timeout == NULL) {
     431                rc = ENOMEM;
     432                goto error;
     433        }
    380434
    381435        /* Get link hardware address */
     
    396450        }
    397451
     452        dlink->state = ds_selecting;
     453
    398454        log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER");
    399455        rc = dhcp_send_discover(dlink);
     
    403459        }
    404460
    405         if (0) list_append(&dlink->links, &dhcp_links);
     461        fibril_timer_set(dlink->timeout, DHCP_DISCOVER_TIMEOUT_VAL,
     462            dhcpsrv_discover_timeout, dlink);
     463
     464        list_append(&dlink->links, &dhcp_links);
    406465
    407466        return EOK;
    408467error:
     468        if (dlink != NULL && dlink->timeout != NULL)
     469                fibril_timer_destroy(dlink->timeout);
    409470        free(dlink);
    410471        return rc;
     
    416477}
    417478
     479static void dhcpsrv_recv_offer(dhcp_link_t *dlink, dhcp_offer_t *offer)
     480{
     481        int rc;
     482
     483        if (dlink->state != ds_selecting) {
     484                log_msg(LOG_DEFAULT, LVL_DEBUG, "Received offer in state "
     485                    " %d, ignoring.", (int)dlink->state);
     486                return;
     487        }
     488
     489        fibril_timer_clear(dlink->timeout);
     490        dlink->offer = *offer;
     491        dlink->state = ds_requesting;
     492
     493        log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPREQUEST");
     494        rc = dhcp_send_request(dlink, offer);
     495        if (rc != EOK) {
     496                log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request.");
     497                return;
     498        }
     499
     500        fibril_timer_set(dlink->timeout, DHCP_REQUEST_TIMEOUT_VAL,
     501            dhcpsrv_request_timeout, dlink);
     502}
     503
     504static void dhcpsrv_recv_ack(dhcp_link_t *dlink, dhcp_offer_t *offer)
     505{
     506        int rc;
     507
     508        if (dlink->state != ds_requesting) {
     509                log_msg(LOG_DEFAULT, LVL_DEBUG, "Received ack in state "
     510                    " %d, ignoring.", (int)dlink->state);
     511                return;
     512        }
     513
     514        fibril_timer_clear(dlink->timeout);
     515        dlink->offer = *offer;
     516        dlink->state = ds_bound;
     517
     518        rc = dhcp_cfg_create(dlink->link_id, offer);
     519        if (rc != EOK) {
     520                log_msg(LOG_DEFAULT, LVL_DEBUG, "Error creating configuration.");
     521                return;
     522        }
     523}
     524
    418525static void dhcpsrv_recv(void *arg, void *msg, size_t size)
    419526{
     
    430537        }
    431538
    432         if (offer.msg_type == msg_dhcpoffer) {
    433                 rc = dhcp_send_request(dlink, &offer);
    434                 if (rc != EOK) {
    435                         log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request.");
    436                         return;
    437                 }
    438         }
    439 
    440         if (offer.msg_type == msg_dhcpack) {
    441                 rc = dhcp_cfg_create(dlink->link_id, &offer);
    442                 if (rc != EOK) {
    443                         log_msg(LOG_DEFAULT, LVL_DEBUG, "Error creating configuration.");
    444                         return;
    445                 }
    446         }
     539        switch (offer.msg_type) {
     540        case msg_dhcpoffer:
     541                dhcpsrv_recv_offer(dlink, &offer);
     542                break;
     543        case msg_dhcpack:
     544                dhcpsrv_recv_ack(dlink, &offer);
     545                break;
     546        default:
     547                log_msg(LOG_DEFAULT, LVL_DEBUG, "Received unexpected "
     548                    "message type. %d", (int)offer.msg_type);
     549                break;
     550        }
     551}
     552
     553static void dhcpsrv_discover_timeout(void *arg)
     554{
     555        dhcp_link_t *dlink = (dhcp_link_t *)arg;
     556        int rc;
     557
     558        assert(dlink->state == ds_selecting);
     559        log_msg(LOG_DEFAULT, LVL_NOTE, "dcpsrv_discover_timeout");
     560
     561        log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER");
     562        rc = dhcp_send_discover(dlink);
     563        if (rc != EOK) {
     564                log_msg(LOG_DEFAULT, LVL_ERROR, "Error sending DHCPDISCOVER");
     565                return;
     566        }
     567
     568        fibril_timer_set(dlink->timeout, DHCP_DISCOVER_TIMEOUT_VAL,
     569            dhcpsrv_discover_timeout, dlink);
     570}
     571
     572static void dhcpsrv_request_timeout(void *arg)
     573{
     574        dhcp_link_t *dlink = (dhcp_link_t *)arg;
     575        int rc;
     576
     577        assert(dlink->state == ds_requesting);
     578        log_msg(LOG_DEFAULT, LVL_NOTE, "dcpsrv_request_timeout");
     579
     580        log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPREQUEST");
     581        rc = dhcp_send_request(dlink, &dlink->offer);
     582        if (rc != EOK) {
     583                log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request.");
     584                return;
     585        }
     586
     587        fibril_timer_set(dlink->timeout, DHCP_REQUEST_TIMEOUT_VAL,
     588            dhcpsrv_request_timeout, dlink);
    447589}
    448590
Note: See TracChangeset for help on using the changeset viewer.