📄 mad_rlc.c
字号:
/* $Author: peltotas $ $Date: 2006/03/08 10:36:28 $ $Revision: 1.11 $ *//* * MAD-ALCLIB: Implementation of ALC/LCT protocols, Compact No-Code FEC, * Simple XOR FEC, Reed-Solomon FEC, and RLC Congestion Control protocol. * Copyright (c) 2003-2006 TUT - Tampere University of Technology * main authors/contacts: jani.peltotalo@tut.fi and sami.peltotalo@tut.fi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * Portions of code derived from MCL library by Vincent Roca et al. * (http://www.inrialpes.fr/planete/people/roca/mcl/) * * Copyright (c) 1999-2004 INRIA - Universite Paris 6 - All rights reserved * (main author: Julien Laboure - julien.laboure@inrialpes.fr * Vincent Roca - vincent.roca@inrialpes.fr) */#include "inc.h"static int mad_rlc_check_sequence(alc_session_t *s, int layer, int seqid);static int mad_rlc_process_rx_sp(alc_session_t *s);static int mad_rlc_add_late(alc_session_t *s, int layer, int nseq);static int mad_rlc_remove_late(alc_session_t *s, int layer, int nseq);static int mad_rlc_update_late_list(alc_session_t *s);static int mad_rlc_add_lost (alc_session_t *s);static int mad_rlc_update_loss_list(alc_session_t *s);static void mad_rlc_free_lists(alc_session_t *s);/* * This function initializes MAD RLC Congestion Control. * * Params: alc_session_t *s: Pointer to session * * Return: int: 0 in success, -1 otherwise * */int init_mad_rlc(alc_session_t *s) { int i; if(!(s->rlc = (mad_rlc_t*)calloc(1, sizeof(mad_rlc_t)))) { printf("Could not alloc memory for mad rlc congestion control!\n"); return -1; } if(s->mode == SENDER) { s->rlc->sp_cycle = RLC_SP_CYCLE; } else if(s->mode == RECEIVER) { s->rlc->drop_highest_layer = false; s->rlc->pkt_timeout = RLC_PKT_TIMEOUT; s->rlc->deaf_period = RLC_DEAF_PERIOD; s->rlc->loss_accepted = RLC_LOSS_ACCEPTED; s->rlc->late_accepted = RLC_LATE_ACCEPTED; s->rlc->loss_limit = RLC_LOSS_LIMIT; s->rlc->loss_timeout = RLC_LOSS_TIMEOUT; s->rlc->rx_deaf_wait = 0; for(i = 0 ; i < MAX_CHANNELS_IN_SESSION; i++) { s->rlc->rx_first_pkt[i] = 1; s->rlc->rx_first_sp[i] = 0; } } return 0; }/* * This function closes MAD RLC Congestion Control. * * Params: alc_session_t *s: Pointer to session * * Return: void * */void close_mad_rlc(alc_session_t *s) { if(s->mode == RECEIVER) { mad_rlc_free_lists(s); } free(s->rlc);}/* * This function calculates next SP time. * * Params: alc_session_t *s: Pointer to session, * int layer: Layer number. * * Return: double: Next SP time. * */double mad_rlc_next_sp(alc_session_t *s, int layer) { double spacing; double currenttime; currenttime = sec(); spacing = (double)((double)s->rlc->sp_cycle / (double)1000) * (double)(min((1 << layer), 128 + layer)); return (currenttime + (double)spacing);}/* * This function resets SP. * * Params: alc_session_t *s: Pointer to session * * Return: void * */void mad_rlc_reset_tx_sp(alc_session_t *s) { int i; for(i = 0 ; i < MAX_CHANNELS_IN_SESSION; i++) { s->rlc->tx_next_sp[i] = mad_rlc_next_sp(s, i); }}/* * This function fills RLC header. * * Params: alc_session_t *s: Pointer to session, * rlc_hdr_t *rlc_hdr: Pointer to RLC header, * int layer: Layer number. * * Return: int: 0 in success, -1 otherwise. * */int mad_rlc_fill_header(alc_session_t *s, rlc_hdr_t *rlc_hdr, int layer) { unsigned short hdr_seqid; double currenttime; currenttime = sec(); if(layer > MAX_CHANNELS_IN_SESSION || layer > s->nb_channel) { printf("BAD layer!\n"); fflush(stdout); return -1; } hdr_seqid = s->rlc->tx_layers_seq[layer]; s->rlc->tx_layers_seq[layer]++; rlc_hdr->reserved = 0x55; /* unused: rlc_reserved = 1010101 */ rlc_hdr->layer = layer; rlc_hdr->seqid = htons(hdr_seqid); if(s->rlc->tx_next_sp[layer] <= currenttime) { if((layer + 1) == s->nb_channel) { rlc_hdr->sp = 0; } else { /* OK this is a new SP for this layer */ rlc_hdr->sp = 1; /* calculate when next SP will occur */ s->rlc->tx_next_sp[layer] = mad_rlc_next_sp(s, layer); if(layer + 1 < MAX_CHANNELS_IN_SESSION && s->ch_list[layer + 1]->start_sending == false) { s->ch_list[layer + 1]->start_sending = true; s->nb_sending_channel++; } } } else { /* not a SP... */ rlc_hdr->sp = 0; } return 0;}/* * This function analyzes ALC packets CCI field. * * Params: alc_session_t *s: Pointer to session, * rlc_hdr_t *rlc_hdr: Pointer to RLC header. * * Return: * */int mad_rlc_analyze_cci(alc_session_t *s, rlc_hdr_t *rlc_hdr) { unsigned char hdr_layer; unsigned short hdr_seqid; unsigned char hdr_sp; double currenttime; hdr_seqid = ntohs(rlc_hdr->seqid); hdr_layer = rlc_hdr->layer; hdr_sp = rlc_hdr->sp; if(rlc_hdr->reserved != 0x55) { return -1; } if(rlc_hdr->layer >= s->nb_channel) { return -1; } mad_rlc_update_loss_list(s); mad_rlc_update_late_list(s); currenttime = sec(); if(s->rlc->rx_deaf_wait != 0) { if(s->rlc->rx_deaf_wait > currenttime) { s->rlc->rx_wait_for[rlc_hdr->layer] = hdr_seqid + 1; return 0; } } if(s->rlc->rx_first_pkt[hdr_layer]) { /* First packet on this layer... */ s->rlc->rx_wait_for[hdr_layer] = hdr_seqid + 1; s->rlc->rx_first_pkt[hdr_layer] = 0; /* continue as this pkt may contain an SP */ } else { /* check if some pkts have been lost or not */ mad_rlc_check_sequence(s, hdr_layer, hdr_seqid); } if(hdr_sp) { if(hdr_layer == s->nb_channel - 1) { /* This is a Synchronisation Point */ if(s->rlc->rx_first_sp[hdr_layer] == 1) { /* skip 1st SP, especially after deaf-period */ s->rlc->rx_first_sp[hdr_layer] = 0; } else { mad_rlc_process_rx_sp(s); } } } return 0;}/* * This function checks packet's RLC sequence number. * * Params: alc_session_t *s: Pointer to session, * int layer: Layer number, * int seqid: Packet's sequence number. * * Return: int: 0 * */int mad_rlc_check_sequence(alc_session_t *s, int layer, int seqid) { unsigned short Delta1; unsigned short Delta2; int i; int late_limit; if(s->rlc->rx_wait_for[layer] == seqid ) { /* This is the packet we're waiting for, let's go on! */ s->rlc->rx_wait_for[layer]++; return 0; } /* This is not the one we're waiting for... */ if(s->rlc->rx_wait_for[layer] < seqid) { Delta1 = seqid - s->rlc->rx_wait_for[layer]; Delta2 = 65535 - Delta1; if(Delta1 < Delta2) { late_limit = RLC_MAX_LATES; for(i = s->rlc->rx_wait_for[layer]; i < seqid; i++) { mad_rlc_add_late(s, layer, i); late_limit--; if(late_limit <= 0 ) { printf("RLC Warning*** Max number of LATE packets reached\n"); fflush(stdout); break; } } /* EOFIX */ s->rlc->rx_wait_for[layer] = seqid + 1; } else { /* Late arrival packet (uint16 overflow) */ /* eg. we're waiting seq 4 and we get seq 65532 */ mad_rlc_remove_late(s, layer, seqid); } } else { /* rx_wait_for > rlc_seqid */ Delta1 = s->rlc->rx_wait_for[layer] - seqid; Delta2 = 65535 - Delta1; if (Delta1 < Delta2) { /* Late arrival packet */ /* ie: we're waiting seq 501 and we get seq 498 */ mad_rlc_remove_late(s, layer, seqid); } else { /* Some packet(s) are missing (uint16 overflow) */ /* ie: waiting seq 65531 and get seq 3 */ /* FIX 14/12/01 */ late_limit = RLC_MAX_LATES; for(i = s->rlc->rx_wait_for[layer]; i != (seqid-1); i++) { mad_rlc_add_late(s, layer, i); late_limit--; if(late_limit <= 0 ) { printf("RLC Warning*** Max number of LATE packets reached\n"); fflush(stdout); break; } } /* EOFIX */ s->rlc->rx_wait_for[layer] = seqid + 1; } } return 0;}/* * This function process RLC SP. * * Params: alc_session_t *s: Pointer to session. * * Return: int: 0 when no new layer, 1 when new layer, -1 otherwise. * */int mad_rlc_process_rx_sp(alc_session_t *s) { unsigned long addr_nb; int port_nb; struct sockaddr_in ipv4; static char addrs[MAX_CHANNELS_IN_SESSION][MAX_LENGTH]; /* multicast addresses */ static char ports[MAX_CHANNELS_IN_SESSION][MAX_LENGTH]; /* local port numbers */ int retval = 0; int ch_id; unsigned short ipv6addr[8]; int nb_ipv6_part; int dup_sep = 0; char tmp[5]; int retcode; int l, m, k;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -