l2tpd: Add mechanism for explicitly ACKing a packet after 20ms

If we are not implicitly ACKing a control packet within 20ms of having
received it, let's send an explicit ACK.
This commit is contained in:
Harald Welte 2016-11-13 19:23:20 +01:00
parent 2d97ca9467
commit f8b6837862
3 changed files with 30 additions and 0 deletions

View File

@ -8,6 +8,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include "l2tpd_socket.h"
@ -48,6 +49,11 @@ struct l2tpd_connection {
struct osmo_fsm_inst *fsm;
/* finite state machine for traffic channels */
struct osmo_fsm_inst *conf_fsm;
/* acknowledgement timer for explicit ack */
struct {
struct osmo_timer_list timer;
uint16_t next_expected_nr;
} ack;
};
/* A L2TP session within a connection */
@ -108,3 +114,5 @@ enum {
};
extern struct l2tpd_instance *l2i;
extern void l2tpd_explicit_ack_cb(void *data);

View File

@ -73,6 +73,8 @@ l2tpd_cc_alloc(struct l2tpd_instance *l2i)
INIT_LLIST_HEAD(&l2c->sessions);
l2c->local.ccid = l2i->next_l_cc_id++;
l2c->ack.timer.cb = l2tpd_explicit_ack_cb;
l2c->ack.timer.data = l2c;
snprintf(id_str, 12, "%d", l2c->local.ccid);

View File

@ -294,6 +294,12 @@ static int l2tp_msgb_tx(struct msgb *msg, int not_ack)
l2h->length = htons(msgb_length(msg));
l2h->ccid = htonl(l2c->remote.ccid);
l2h->Nr = htons(l2c->next_rx_seq_nr);
/* if we are implicitly ACKing this number, stop the timer that
* would be senidng an explicit ack later */
if (not_ack && l2c->next_rx_seq_nr == l2c->ack.next_expected_nr)
osmo_timer_del(&l2c->ack.timer);
/* only acks dont increase seq */
if (not_ack)
l2h->Ns = htons(l2c->next_tx_seq_nr++);
@ -795,6 +801,19 @@ static int l2tp_rcvmsg_control_ericsson(struct l2tpd_connection *l2c,
}
}
static void schedule_explicit_ack(struct l2tpd_connection *l2c, uint16_t next_expected_nr)
{
l2c->ack.next_expected_nr = next_expected_nr;
osmo_timer_schedule(&l2c->ack.timer, 0, 20*1000);
};
/* call-back on explicit ACK timer expiration */
void l2tpd_explicit_ack_cb(void *data)
{
struct l2tpd_connection *l2c = data;
l2tp_tx_ack(l2c);
}
static int l2tp_rcvmsg_control(struct msgb *msg)
{
struct l2tp_control_hdr *ch = (struct l2tp_control_hdr *) msgb_data(msg);
@ -864,6 +883,7 @@ static int l2tp_rcvmsg_control(struct msgb *msg)
/* FIXME: do real seq numbering. check if already received etc. */
if (l2c->next_rx_seq_nr == ch->Ns) {
l2c->next_rx_seq_nr++;
schedule_explicit_ack(l2c, l2c->next_rx_seq_nr);
/* everything ok */
} else if (l2c->next_rx_seq_nr < ch->Ns) {
/* old packet, we already received this one, but might not sent a ACK */