コード例 #1
0
ファイル: gomach_internal.c プロジェクト: LudwigKnuepfer/RIOT
static void _cp_packet_process_data(gnrc_netif_t *netif,
                                    gnrc_gomach_packet_info_t *info,
                                    gnrc_pktsnip_t *pkt)
{
    if (memcmp(&netif->l2addr, &info->dst_addr.addr,
               netif->l2addr_len) == 0) {
        /* The data is for itself, now update the sender's queue-length indicator. */
        gnrc_gomach_indicator_update(netif, pkt, info);

        /* Check that whether this is a duplicate packet. */
        if ((gnrc_gomach_check_duplicate(netif, info))) {
            gnrc_pktbuf_release(pkt);
            LOG_DEBUG("[GOMACH]: received a duplicate packet.\n");
            return;
        }
        gnrc_gomach_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
        gnrc_mac_dispatch(&netif->mac.rx);

#if (GNRC_GOMACH_ENABLE_DUTYCYLE_RECORD == 1)
        /* Output radio duty-cycle ratio */
        uint64_t duty;
        duty = xtimer_now_usec64();
        duty = (netif->mac.prot.gomach.awake_duration_sum_ticks) * 100 /
               (duty - netif->mac.prot.gomach.system_start_time_ticks);
        printf("[GoMacH]: achieved radio duty-cycle: %lu %% \n", (uint32_t)duty);
#endif
    }
    else {
        /* If the data is not for the device, release it. */
        gnrc_pktbuf_release(pkt);
    }
}
コード例 #2
0
ファイル: lwmac.c プロジェクト: kamejoko80/RIOT
static void _rx_management_success(gnrc_netif_t *netif)
{
    LOG_DEBUG("[LWMAC] Reception was successful\n");
    gnrc_lwmac_rx_stop(netif);
    /* Dispatch received packets, timing is not critical anymore */
    gnrc_mac_dispatch(&netif->mac.rx);

    /* Here we check if we are close to the end of the cycle. If yes,
     * go to sleep. Firstly, get the relative phase. */
    uint32_t phase = rtt_get_counter();
    if (phase < netif->mac.lwmac.last_wakeup) {
        phase = (RTT_US_TO_TICKS(GNRC_LWMAC_PHASE_MAX) - netif->mac.lwmac.last_wakeup) +
                phase;
    }
    else {
        phase = phase - netif->mac.lwmac.last_wakeup;
    }
    /* If the relative phase is beyond 4/5 cycle time, go to sleep. */
    if (phase > (4 * RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US) / 5)) {
        gnrc_lwmac_set_quit_rx(netif, true);
    }

    if (gnrc_lwmac_get_quit_rx(netif)) {
        lwmac_set_state(netif, GNRC_LWMAC_SLEEPING);
    }
    else {
        /* Go back to LISTENING after successful reception */
        lwmac_set_state(netif, GNRC_LWMAC_LISTENING);
    }
}
コード例 #3
0
ファイル: gomach_internal.c プロジェクト: LudwigKnuepfer/RIOT
static bool _wait_preamble_ack_data(gnrc_netif_t *netif,
                                    gnrc_gomach_packet_info_t *info,
                                    gnrc_pktsnip_t *pkt)
{
    if (memcmp(&netif->l2addr, &info->dst_addr.addr,
               netif->l2addr_len) == 0) {
        /* The data is for itself, now update the sender's queue-length indicator. */
        gnrc_gomach_indicator_update(netif, pkt, info);

        /* Check that whether this is a duplicate packet. */
        if ((gnrc_gomach_check_duplicate(netif, info))) {
            gnrc_pktbuf_release(pkt);
            LOG_DEBUG("[GOMACH] t2u: received a duplicate packet.\n");
            return false;
        }

        gnrc_gomach_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
        gnrc_mac_dispatch(&netif->mac.rx);
    }
    else {
        /* If the data is not for the device, release it.  */
        gnrc_pktbuf_release(pkt);
    }
    return true;
}
コード例 #4
0
ファイル: rx_state_machine.c プロジェクト: ryankurte/RIOT
static uint8_t _packet_process_in_wait_for_wr(gnrc_netdev_t *gnrc_netdev)
{
    uint8_t rx_info = 0;
    gnrc_pktsnip_t *pkt;

    assert(gnrc_netdev != NULL);

    while ((pkt = gnrc_priority_pktqueue_pop(&gnrc_netdev->rx.queue)) != NULL) {
        LOG_DEBUG("[LWMAC-rx] Inspecting pkt @ %p\n", pkt);

        /* Parse packet */
        gnrc_lwmac_packet_info_t info;

        if (_gnrc_lwmac_parse_packet(pkt, &info) != 0) {
            LOG_DEBUG("[LWMAC-rx] Packet could not be parsed\n");
            gnrc_pktbuf_release(pkt);
            continue;
        }

        if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) {
            _gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
            gnrc_mac_dispatch(&gnrc_netdev->rx);
            rx_info |= GNRC_LWMAC_RX_FOUND_BROADCAST;
            /* quit listening period to avoid receiving duplicate broadcast packets */
            gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
            /* quit TX in this cycle to avoid collisions with broadcast packets */
            gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev, true);
            break;
        }

        if (info.header->type != GNRC_LWMAC_FRAMETYPE_WR) {
            LOG_DEBUG("[LWMAC-rx] Packet is not WR: 0x%02x\n", info.header->type);
            gnrc_pktbuf_release(pkt);
            continue;
        }

        /* No need to keep pkt anymore */
        gnrc_pktbuf_release(pkt);

        if (!(memcmp(&info.dst_addr.addr, &gnrc_netdev->l2_addr,
                     gnrc_netdev->l2_addr_len) == 0)) {
            LOG_DEBUG("[LWMAC-rx] Packet is WR but not for us\n");
            /* quit TX in this cycle to avoid collisions with other senders, since
             * found ongoing WR (preamble) stream */
            gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev, true);
            continue;
        }

        /* If reach here, the node gets a WR for itself. */
        /* Save source address for later addressing */
        gnrc_netdev->rx.l2_addr = info.src_addr;

        rx_info |= GNRC_LWMAC_RX_FOUND_WR;
        break;
    }

    return rx_info;
}
コード例 #5
0
ファイル: gomach_internal.c プロジェクト: LudwigKnuepfer/RIOT
static inline void _cp_packet_process_bcast(gnrc_netif_t *netif,
                                            gnrc_pktsnip_t *pkt)
{
    /* Receive a broadcast packet, quit the listening period to avoid receive duplicate
     * broadcast packet. */
    gnrc_gomach_set_quit_cycle(netif, true);
    gnrc_gomach_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
    gnrc_mac_dispatch(&netif->mac.rx);
}
コード例 #6
0
ファイル: lwmac.c プロジェクト: kamejoko80/RIOT
static void _lwmac_update_listening(gnrc_netif_t *netif)
{
    /* In case has pending packet to send, clear rtt alarm thus to goto
     * transmission initialization (in SLEEPING management) right after the
     * listening period */
    if ((_next_tx_neighbor(netif) != NULL) ||
        (netif->mac.tx.current_neighbor != NULL)) {
        rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif);
    }

    /* Set timeout for if there's no successful rx transaction that will
     * change state to SLEEPING. */
    if (!gnrc_lwmac_timeout_is_running(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) {
        gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD, GNRC_LWMAC_WAKEUP_DURATION_US);
    }
    else if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) {
        /* Dispatch first as there still may be broadcast packets. */
        gnrc_mac_dispatch(&netif->mac.rx);

        netif->mac.lwmac.state = GNRC_LWMAC_SLEEPING;
        /* Enable duty cycling again */
        rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, netif);

        _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_SLEEP);
        gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD);

        /* if there is a packet for transmission, schedule update to start
         * transmission initialization immediately. */
        gnrc_mac_tx_neighbor_t *neighbour = _next_tx_neighbor(netif);
        if ((neighbour != NULL) || (netif->mac.tx.current_neighbor != NULL)) {
            /* This triggers packet sending procedure in sleeping immediately. */
            lwmac_schedule_update(netif);
            return;
        }
    }

    if (gnrc_priority_pktqueue_length(&netif->mac.rx.queue) > 0) {
        /* Do wake-up extension in each packet reception. */
        gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD);
        lwmac_set_state(netif, GNRC_LWMAC_RECEIVING);
    }
}
コード例 #7
0
ファイル: gomach_internal.c プロジェクト: LudwigKnuepfer/RIOT
void gnrc_gomach_packet_process_in_vtdma(gnrc_netif_t *netif)
{
    assert(netif != NULL);

    gnrc_pktsnip_t *pkt;
    gnrc_gomach_packet_info_t receive_packet_info;

    while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) {
        /* Parse the received packet. */
        int res = _parse_packet(netif, pkt, &receive_packet_info);
        if (res != 0) {
            LOG_DEBUG("[GOMACH] vtdma: Packet could not be parsed: %i\n", res);
            gnrc_pktbuf_release(pkt);
            continue;
        }

        switch (receive_packet_info.header->type) {
            case GNRC_GOMACH_FRAME_DATA: {
                gnrc_gomach_indicator_update(netif, pkt, &receive_packet_info);

                if ((gnrc_gomach_check_duplicate(netif, &receive_packet_info))) {
                    gnrc_pktbuf_release(pkt);
                    LOG_DEBUG("[GOMACH] vtdma: received a duplicate packet.\n");
                    return;
                }

                gnrc_gomach_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
                gnrc_mac_dispatch(&netif->mac.rx);
                break;
            }
            default: {
                gnrc_pktbuf_release(pkt);
                break;
            }
        }
    }
}
コード例 #8
0
ファイル: tx_state_machine.c プロジェクト: A-Paul/RIOT
static uint8_t _packet_process_in_wait_for_wa(gnrc_netif_t *netif)
{
    assert(netif != NULL);

    uint8_t tx_info = 0;
    gnrc_pktsnip_t *pkt;
    bool found_wa = false;
    bool postponed = false;
    bool from_expected_destination = false;

    while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) {
        LOG_DEBUG("[LWMAC-tx] Inspecting pkt @ %p\n", pkt);

        /* Parse packet */
        gnrc_lwmac_packet_info_t info;
        int ret = _gnrc_lwmac_parse_packet(pkt, &info);

        if (ret != 0) {
            LOG_DEBUG("[LWMAC-tx] Packet could not be parsed: %i\n", ret);
            gnrc_pktbuf_release(pkt);
            continue;
        }

        if (memcmp(&info.src_addr.addr, &netif->mac.tx.current_neighbor->l2_addr,
                   netif->mac.tx.current_neighbor->l2_addr_len) == 0) {
            from_expected_destination = true;
        }

        if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) {
            _gnrc_lwmac_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
            gnrc_mac_dispatch(&netif->mac.rx);
            /* Drop pointer to it can't get released */
            pkt = NULL;
            continue;
        }

        /* Check if destination is talking to another node. It will sleep
         * after a finished transaction so there's no point in trying any
         * further now. */
        if (!(memcmp(&info.dst_addr.addr, &netif->l2addr,
                     netif->l2addr_len) == 0) && from_expected_destination) {
            if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
                gnrc_pktbuf_release(netif->mac.tx.packet);
                LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
            }
            /* drop pointer so it wont be free'd */
            netif->mac.tx.packet = NULL;
            postponed = true;
            gnrc_pktbuf_release(pkt);
            break;
        }

        /* if found anther node is also trying to send data,
         * quit this cycle for collision avoidance. */
        if (info.header->type == GNRC_LWMAC_FRAMETYPE_WR) {
            if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
                gnrc_pktbuf_release(netif->mac.tx.packet);
                LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
            }
            /* drop pointer so it wont be free'd */
            netif->mac.tx.packet = NULL;
            postponed = true;
            gnrc_pktbuf_release(pkt);
            break;
        }

        if (info.header->type != GNRC_LWMAC_FRAMETYPE_WA) {
            LOG_DEBUG("[LWMAC-tx] Packet is not WA: 0x%02x\n", info.header->type);
            gnrc_pktbuf_release(pkt);
            continue;
        }

        if (from_expected_destination) {
            /* calculate the phase of the receiver based on WA */
            netif->mac.tx.timestamp = _gnrc_lwmac_phase_now();
            gnrc_lwmac_frame_wa_t *wa_hdr;
            wa_hdr = (gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_LWMAC))->data;

            if (netif->mac.tx.timestamp >= wa_hdr->current_phase) {
                netif->mac.tx.timestamp = netif->mac.tx.timestamp -
                                          wa_hdr->current_phase;
            }
            else {
                netif->mac.tx.timestamp += RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US);
                netif->mac.tx.timestamp -= wa_hdr->current_phase;
            }

            uint32_t own_phase;
            own_phase = _gnrc_lwmac_ticks_to_phase(netif->mac.prot.lwmac.last_wakeup);

            if (own_phase >= netif->mac.tx.timestamp) {
                own_phase = own_phase - netif->mac.tx.timestamp;
            }
            else {
                own_phase = netif->mac.tx.timestamp - own_phase;
            }

            if ((own_phase < RTT_US_TO_TICKS((3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2))) ||
                (own_phase > RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US -
                                             (3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2)))) {
                gnrc_lwmac_set_phase_backoff(netif, true);
                LOG_WARNING("WARNING: [LWMAC-tx] phase close\n");
            }
        }

        /* No need to keep pkt anymore */
        gnrc_pktbuf_release(pkt);

        if (!from_expected_destination) {
            LOG_DEBUG("[LWMAC-tx] Packet is not from expected destination\n");
            break;
        }

        /* All checks passed so this must be a valid WA */
        gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WR);

        found_wa = true;
        break;
    }

    if (postponed) {
        LOG_INFO("[LWMAC-tx] Destination is talking to another node, postpone\n");
        tx_info |= GNRC_LWMAC_TX_FAIL;
        return tx_info;
    }

    if (!found_wa) {
        LOG_DEBUG("[LWMAC-tx] No WA yet\n");
        return tx_info;
    }

    /* Save newly calculated phase for destination */
    netif->mac.tx.current_neighbor->phase = netif->mac.tx.timestamp;
    LOG_INFO("[LWMAC-tx] New phase: %" PRIu32 "\n", netif->mac.tx.timestamp);

    /* We've got our WA, so discard the rest, TODO: no flushing */
    gnrc_priority_pktqueue_flush(&netif->mac.rx.queue);

    tx_info |= GNRC_LWMAC_TX_SUCCESS;
    return tx_info;
}
コード例 #9
0
ファイル: gomach_internal.c プロジェクト: LudwigKnuepfer/RIOT
void gnrc_gomach_packet_process_in_wait_beacon(gnrc_netif_t *netif)
{
    assert(netif != NULL);

    gnrc_pktsnip_t *pkt;
    gnrc_gomach_packet_info_t receive_packet_info;

    while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) {
        /* Parse the received packet. */
        int res = _parse_packet(netif, pkt, &receive_packet_info);
        if (res != 0) {
            LOG_DEBUG("[GOMACH] t2k: Packet could not be parsed: %i\n", res);
            gnrc_pktbuf_release(pkt);
            continue;
        }

        switch (receive_packet_info.header->type) {
            case GNRC_GOMACH_FRAME_BEACON: {
                if (memcmp(&netif->mac.tx.current_neighbor->l2_addr,
                           &receive_packet_info.src_addr.addr,
                           netif->mac.tx.current_neighbor->l2_addr_len) == 0) {
                    gnrc_gomach_clear_timeout(netif, GNRC_GOMACH_TIMEOUT_WAIT_BEACON);
                    gnrc_gomach_beacon_process(netif, pkt);
                }
                gnrc_pktbuf_release(pkt);
                break;
            }
            case GNRC_GOMACH_FRAME_PREAMBLE: {
                /* Release preamble packet no matter the preamble is for it or not,
                 * and quit the t2k procedure. */
                gnrc_gomach_set_quit_cycle(netif, true);
                gnrc_pktbuf_release(pkt);
                break;
            }
            case GNRC_GOMACH_FRAME_DATA: {
                /* It is unlikely that we will received a data for us here.
                 * This means the device' CP is close with its destination's. */
                if (memcmp(&netif->l2addr, &receive_packet_info.dst_addr.addr,
                           netif->l2addr_len) == 0) {
                    gnrc_gomach_indicator_update(netif, pkt, &receive_packet_info);

                    if ((gnrc_gomach_check_duplicate(netif, &receive_packet_info))) {
                        gnrc_pktbuf_release(pkt);
                        LOG_DEBUG("[GOMACH]: received a duplicate packet.\n");
                        return;
                    }

                    gnrc_gomach_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
                    gnrc_mac_dispatch(&netif->mac.rx);
                }
                else {
                    gnrc_pktbuf_release(pkt);
                }
                break;
            }
            case GNRC_GOMACH_FRAME_BROADCAST: {
                gnrc_gomach_set_quit_cycle(netif, true);
                gnrc_pktbuf_release(pkt);
                break;
            }
            default: {
                gnrc_pktbuf_release(pkt);
                break;
            }
        }
    }
}
コード例 #10
0
ファイル: rx_state_machine.c プロジェクト: ryankurte/RIOT
static uint8_t _packet_process_in_wait_for_data(gnrc_netdev_t *gnrc_netdev)
{
    uint8_t rx_info = 0;
    gnrc_pktsnip_t *pkt;

    assert(gnrc_netdev != NULL);

    pkt = NULL;

    while ((pkt = gnrc_priority_pktqueue_pop(&gnrc_netdev->rx.queue)) != NULL) {
        LOG_DEBUG("[LWMAC-rx] Inspecting pkt @ %p\n", pkt);

        /* Parse packet */
        gnrc_lwmac_packet_info_t info;

        if (_gnrc_lwmac_parse_packet(pkt, &info) != 0) {
            LOG_DEBUG("[LWMAC-rx] Packet could not be parsed\n");
            gnrc_pktbuf_release(pkt);
            continue;
        }

        if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) {
            _gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
            gnrc_mac_dispatch(&gnrc_netdev->rx);
            /* quit listening period to avoid receiving duplicate broadcast packets */
            gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
            continue;
        }

        if (!(memcmp(&info.src_addr.addr, &gnrc_netdev->rx.l2_addr.addr,
                     gnrc_netdev->rx.l2_addr.len) == 0)) {
            LOG_DEBUG("[LWMAC-rx] Packet is not from destination\n");
            gnrc_pktbuf_release(pkt);
            /* Reset timeout to wait for the data packet */
            gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
            gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
            continue;
        }

        if (!(memcmp(&info.dst_addr.addr, &gnrc_netdev->l2_addr,
                     gnrc_netdev->l2_addr_len) == 0)) {
            LOG_DEBUG("[LWMAC-rx] Packet is not for us\n");
            gnrc_pktbuf_release(pkt);
            /* Reset timeout to wait for the data packet */
            gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
            gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
            continue;
        }

        /* Sender maybe didn't get the WA */
        if (info.header->type == GNRC_LWMAC_FRAMETYPE_WR) {
            LOG_DEBUG("[LWMAC-rx] Found a WR while waiting for DATA\n");
            gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
            rx_info |= GNRC_LWMAC_RX_FOUND_WR;
            /* Push WR back to rx queue */
            gnrc_mac_queue_rx_packet(&gnrc_netdev->rx, 0, pkt);
            break;
        }

        switch (info.header->type) {
            case GNRC_LWMAC_FRAMETYPE_DATA:
            case GNRC_LWMAC_FRAMETYPE_DATA_PENDING: {
                /* Receiver gets the data packet */
                _gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
                gnrc_mac_dispatch(&gnrc_netdev->rx);
                LOG_DEBUG("[LWMAC-rx] Found DATA!\n");
                gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
                rx_info |= GNRC_LWMAC_RX_FOUND_DATA;
                return rx_info;
            }
            default: {
                gnrc_pktbuf_release(pkt);
            }
        }
    }

    return rx_info;
}