diff options
-rw-r--r-- | TODO-RELEASE | 2 | ||||
-rw-r--r-- | gtp/gtp.c | 5 | ||||
-rw-r--r-- | gtp/pdp.c | 13 | ||||
-rw-r--r-- | gtp/pdp.h | 3 | ||||
-rw-r--r-- | gtp/queue.c | 3 | ||||
-rw-r--r-- | gtp/queue.h | 3 |
6 files changed, 28 insertions, 1 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE index d0852fc..73e3189 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,5 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libgtp queue.h struct qmsg_t got a new field: entry +libgtp pdp.h struct pdp_t got a new field: qmsg_list_req @@ -513,6 +513,8 @@ static int gtp_req(struct gsn_t *gsn, uint8_t version, struct pdp_t *pdp, qmsg->cbp = cbp; qmsg->type = ntoh8(packet->gtp0.h.type); qmsg->fd = fd; + if (pdp) /* echo requests are not pdp-bound */ + llist_add(&qmsg->entry, &pdp->qmsg_list_req); } gsn->seq_next++; /* Count up this time */ return 0; @@ -697,6 +699,9 @@ static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp, qmsg->cbp = NULL; qmsg->type = 0; qmsg->fd = fd; + /* No need to add to pdp list here, because even on pdp ctx free + we want to leave messages in queue_resp until timeout to + detect duplicates */ } return 0; } @@ -31,6 +31,7 @@ #include "pdp.h" #include "gtp.h" #include "lookupa.h" +#include "queue.h" /* *********************************************************** * Functions related to PDP storage @@ -156,7 +157,7 @@ int gtp_pdp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t } /* Default: Generate G-PDU sequence numbers on Tx */ (*pdp)->tx_gpdu_seq = true; - + INIT_LLIST_HEAD(&(*pdp)->qmsg_list_req); return 0; } } @@ -165,7 +166,17 @@ int gtp_pdp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t int pdp_freepdp(struct pdp_t *pdp) { + struct qmsg_t *qmsg, *qmsg2; struct pdp_t *pdpa = pdp->gsn->pdpa; + int rc; + + /* Remove all enqueued messages belonging to this pdp from req tx transmit + queue. queue_freemsg will call llist_del(). */ + llist_for_each_entry_safe(qmsg, qmsg2, &pdp->qmsg_list_req, entry) { + if ((rc = queue_freemsg(pdp->gsn->queue_req, qmsg))) + LOGP(DLGTP, LOGL_ERROR, + "Failed freeing qmsg from qmsg_list_req during pdp_freepdp()! %d\n", rc); + } pdp_tiddel(pdp); @@ -17,6 +17,7 @@ #include <netinet/in.h> #include <osmocom/core/defs.h> +#include <osmocom/core/linuxlist.h> struct gsn_t; @@ -241,6 +242,8 @@ struct pdp_t { struct gsn_t *gsn; /* Back pointer to GSN where this pdp ctx belongs to */ bool tx_gpdu_seq; /* Transmit (true) or suppress G-PDU sequence numbers */ + + struct llist_head qmsg_list_req; /* list of req qmsg_t in retrans queue belonging this pdp ctx */ }; /* functions related to pdp_t management */ diff --git a/gtp/queue.c b/gtp/queue.c index ce4713e..4c25913 100644 --- a/gtp/queue.c +++ b/gtp/queue.c @@ -172,6 +172,7 @@ int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg, } else { *qmsg = &queue->qmsga[queue->next]; queue_seqset(queue, *qmsg, peer, seq); + INIT_LLIST_HEAD(&(*qmsg)->entry); (*qmsg)->state = 1; /* Space taken */ (*qmsg)->this = queue->next; (*qmsg)->next = -1; /* End of the queue */ @@ -206,6 +207,8 @@ int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg) return EOF; /* Not in queue */ } + llist_del(&qmsg->entry); + queue_seqdel(queue, qmsg); if (qmsg->next == -1) /* Are we the last in queue? */ diff --git a/gtp/queue.h b/gtp/queue.h index 76cb7be..9b0367b 100644 --- a/gtp/queue.h +++ b/gtp/queue.h @@ -17,6 +17,8 @@ #ifndef _QUEUE_H #define _QUEUE_H +#include <osmocom/core/linuxlist.h> + #include "gtp.h" #define QUEUE_DEBUG 0 /* Print debug information */ @@ -39,6 +41,7 @@ struct qmsg_t { /* Holder for queued packets */ int this; /* Pointer to myself */ time_t timeout; /* When do we retransmit this packet? */ int retrans; /* How many times did we retransmit this? */ + struct llist_head entry; /* Listed with other qmsg_t belonging to a pdp_t->qmsg_list_req */ }; struct queue_t { |