diff --git a/lib/librte_ip_frag/ip_frag_common.h b/lib/librte_ip_frag/ip_frag_common.h
index 9f56196..fdc2085 100644
--- a/lib/librte_ip_frag/ip_frag_common.h
+++ b/lib/librte_ip_frag/ip_frag_common.h
@@ -43,6 +43,12 @@
 #define        IP_FRAG_LOG(lvl, fmt, args...)  do {} while(0)
 #endif /* IP_FRAG_DEBUG */
 
+#ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT
+#define        IP_FRAG_TBL_STAT_UPDATE(s, f, v)        ((s)->f += (v))
+#else
+#define        IP_FRAG_TBL_STAT_UPDATE(s, f, v)        do {} while (0)
+#endif /* IP_FRAG_TBL_STAT */
+
 #define IPV4_KEYLEN 1
 #define IPV6_KEYLEN 4
 
@@ -55,9 +61,9 @@
        "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 "%08" PRIx64
 
 /* internal functions declarations */
-struct rte_mbuf * ip_frag_process(struct ip_frag_pkt *fp,
-               struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb,
-               uint16_t ofs, uint16_t len, uint16_t more_frags);
+struct rte_mbuf * ip_frag_process(struct rte_ip_frag_tbl *tbl, 
+       struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr, 
+       struct rte_mbuf *mb, uint16_t ofs, uint16_t len, uint16_t more_frags);
 
 struct ip_frag_pkt * ip_frag_find(struct rte_ip_frag_tbl *tbl,
                struct rte_ip_frag_death_row *dr,
@@ -71,8 +77,6 @@ struct ip_frag_pkt * ip_frag_lookup(struct rte_ip_frag_tbl *tbl,
 struct rte_mbuf *ipv4_frag_reassemble(struct ip_frag_pkt *fp);
 struct rte_mbuf *ipv6_frag_reassemble(struct ip_frag_pkt *fp);
 
-
-
 /*
  * misc frag key functions
  */
@@ -114,7 +118,8 @@ ip_frag_key_cmp(const struct ip_frag_key * k1, const struct ip_frag_key * k2)
 
 /* put fragment on death row */
 static inline void
-ip_frag_free(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr)
+ip_frag_free(struct rte_ip_frag_tbl *tbl, struct ip_frag_pkt *fp, 
+       struct rte_ip_frag_death_row *dr)
 {
        uint32_t i, k;
 
@@ -123,6 +128,7 @@ ip_frag_free(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr)
                if (fp->frags[i].mb != NULL) {
                        dr->row[k++] = fp->frags[i].mb;
                        fp->frags[i].mb = NULL;
+                       tbl->nb_mbufs --;
                }
        }
 
@@ -178,4 +184,16 @@ ip_frag_reset(struct ip_frag_pkt *fp, uint64_t tms)
        fp->frags[IP_FIRST_FRAG_IDX] = zero_frag;
 }
 
+/* frag table helper functions */
+static inline void
+ip_frag_tbl_del(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr,
+       struct ip_frag_pkt *fp)
+{
+       ip_frag_free(tbl, fp, dr);
+       ip_frag_key_invalidate(&fp->key);
+       TAILQ_REMOVE(&tbl->lru, fp, lru);
+       tbl->use_entries--;
+       IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, del_num, 1);
+}
+
 #endif /* _IP_FRAG_COMMON_H_ */
diff --git a/lib/librte_ip_frag/ip_frag_internal.c b/lib/librte_ip_frag/ip_frag_internal.c
index 46c44ff..7cdcdfc 100644
--- a/lib/librte_ip_frag/ip_frag_internal.c
+++ b/lib/librte_ip_frag/ip_frag_internal.c
@@ -43,23 +43,7 @@
 #define        IP_FRAG_TBL_POS(tbl, sig)       \
        ((tbl)->pkt + ((sig) & (tbl)->entry_mask))
 
-#ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT
-#define        IP_FRAG_TBL_STAT_UPDATE(s, f, v)        ((s)->f += (v))
-#else
-#define        IP_FRAG_TBL_STAT_UPDATE(s, f, v)        do {} while (0)
-#endif /* IP_FRAG_TBL_STAT */
-
 /* local frag table helper functions */
-static inline void
-ip_frag_tbl_del(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr,
-       struct ip_frag_pkt *fp)
-{
-       ip_frag_free(fp, dr);
-       ip_frag_key_invalidate(&fp->key);
-       TAILQ_REMOVE(&tbl->lru, fp, lru);
-       tbl->use_entries--;
-       IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, del_num, 1);
-}
 
 static inline void
 ip_frag_tbl_add(struct rte_ip_frag_tbl *tbl,  struct ip_frag_pkt *fp,
@@ -76,7 +60,7 @@ static inline void
 ip_frag_tbl_reuse(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr,
        struct ip_frag_pkt *fp, uint64_t tms)
 {
-       ip_frag_free(fp, dr);
+       ip_frag_free(tbl, fp, dr);
        ip_frag_reset(fp, tms);
        TAILQ_REMOVE(&tbl->lru, fp, lru);
        TAILQ_INSERT_TAIL(&tbl->lru, fp, lru);
@@ -135,8 +119,9 @@ ipv6_frag_hash(const struct ip_frag_key *key, uint32_t *v1, uint32_t *v2)
 }
 
 struct rte_mbuf *
-ip_frag_process(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr,
-       struct rte_mbuf *mb, uint16_t ofs, uint16_t len, uint16_t more_frags)
+ip_frag_process(struct rte_ip_frag_tbl *tbl, struct ip_frag_pkt *fp,
+       struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint16_t ofs,
+       uint16_t len, uint16_t more_frags)
 {
        uint32_t idx;
 
@@ -194,7 +179,7 @@ ip_frag_process(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr,
                                fp->frags[IP_LAST_FRAG_IDX].len);
 
                /* free all fragments, invalidate the entry. */
-               ip_frag_free(fp, dr);
+               ip_frag_free(tbl, fp, dr);
                ip_frag_key_invalidate(&fp->key);
                IP_FRAG_MBUF2DR(dr, mb);
 
@@ -204,6 +189,7 @@ ip_frag_process(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr,
        fp->frags[idx].ofs = ofs;
        fp->frags[idx].len = len;
        fp->frags[idx].mb = mb;
+       tbl->nb_mbufs++;
 
        mb = NULL;
 
@@ -252,7 +238,10 @@ ip_frag_process(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr,
                                fp->frags[IP_LAST_FRAG_IDX].len);
 
                /* free associated resources. */
-               ip_frag_free(fp, dr);
+               ip_frag_free(tbl, fp, dr);
+       }
+       else {
+               tbl->nb_mbufs -= fp->last_idx;
        }
 
        /* we are done with that entry, invalidate it. */
diff --git a/lib/librte_ip_frag/rte_ip_frag.h b/lib/librte_ip_frag/rte_ip_frag.h
index 0144164..bc6becd 100644
--- a/lib/librte_ip_frag/rte_ip_frag.h
+++ b/lib/librte_ip_frag/rte_ip_frag.h
@@ -94,10 +94,12 @@ struct ip_frag_pkt {
 
 #define IP_FRAG_DEATH_ROW_LEN 32 /**< death row size (in packets) */
 
+#define IP_FRAG_DEATH_ROW_MBUF_LEN (IP_FRAG_DEATH_ROW_LEN * (IP_MAX_FRAG_NUM + 1))
+
 /** mbuf death row (packets to be freed) */
 struct rte_ip_frag_death_row {
        uint32_t cnt;          /**< number of mbufs currently on death row */
-       struct rte_mbuf *row[IP_FRAG_DEATH_ROW_LEN * (IP_MAX_FRAG_NUM + 1)];
+       struct rte_mbuf *row[IP_FRAG_DEATH_ROW_MBUF_LEN];
        /**< mbufs to be freed */
 };
 
@@ -122,6 +124,7 @@ struct rte_ip_frag_tbl {
        uint32_t             bucket_entries;  /**< hash associativity. */
        uint32_t             nb_entries;      /**< total size of the table. */
        uint32_t             nb_buckets;      /**< num of associativity lines. */
+       uint32_t             nb_mbufs;        /**< num of mbufs holded in the tbl. */
        struct ip_frag_pkt *last;         /**< last used entry. */
        struct ip_pkt_list lru;           /**< LRU list for table entries. */
        struct ip_frag_tbl_stat stat;     /**< statistics counters. */
@@ -354,6 +357,32 @@ void rte_ip_frag_free_death_row(struct rte_ip_frag_death_row *dr,
 void
 rte_ip_frag_table_statistics_dump(FILE * f, const struct rte_ip_frag_tbl *tbl);
 
+/**
+ * Number of mbufs holded in the fragmentation table.
+ *
+ * @param tbl
+ *   Fragmentation table
+ * 
+ * @return
+ *   Number of mbufs holded in the fragmentation table.
+ */
+static inline uint32_t
+rte_frag_table_mbuf_count(const struct rte_ip_frag_tbl *tbl)
+{
+       return tbl->nb_mbufs;
+}
+
+/*
+ */
+void
+rte_frag_table_del_expired_entries(struct rte_ip_frag_tbl *tbl,
+       struct rte_ip_frag_death_row *dr, uint64_t tms);
+
+#ifdef RTE_IP_FRAG_DEBUG
+void
+rte_frag_table_print(struct rte_ip_frag_tbl *tbl);
+#endif /* RTE_IP_FRAG_DEBUG */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ip_frag/rte_ip_frag_common.c b/lib/librte_ip_frag/rte_ip_frag_common.c
index 8460f8e..b9a67f4 100644
--- a/lib/librte_ip_frag/rte_ip_frag_common.c
+++ b/lib/librte_ip_frag/rte_ip_frag_common.c
@@ -104,6 +104,7 @@ rte_ip_frag_table_create(uint32_t bucket_num, uint32_t bucket_entries,
        tbl->nb_buckets = bucket_num;
        tbl->bucket_entries = bucket_entries;
        tbl->entry_mask = (tbl->nb_entries - 1) & ~(tbl->bucket_entries  - 1);
+       tbl->nb_mbufs = 0;
 
        TAILQ_INIT(&(tbl->lru));
        return tbl;
@@ -150,3 +151,52 @@ rte_ip_frag_table_statistics_dump(FILE *f, const struct rte_ip_frag_tbl *tbl)
                fail_nospace,
                fail_total - fail_nospace);
 }
+
+/*
+ *
+ */
+void
+rte_frag_table_del_expired_entries(struct rte_ip_frag_tbl *tbl,
+       struct rte_ip_frag_death_row *dr, uint64_t tms)
+{
+       uint64_t max_cycles;
+       struct ip_frag_pkt *fp;
+
+       max_cycles = tbl->max_cycles;
+
+       TAILQ_FOREACH(fp, &tbl->lru, lru)
+               if (max_cycles + fp->start < tms) {
+                       /* check that death row has enough space */
+                       if (IP_FRAG_DEATH_ROW_MBUF_LEN - dr->cnt >= fp->last_idx)
+                               ip_frag_tbl_del(tbl, dr, fp);
+                       else
+                               return;
+               }
+               else {
+                       return;
+               }
+}
+
+#ifdef RTE_IP_FRAG_DEBUG
+
+void
+rte_frag_table_print(struct rte_ip_frag_tbl *tbl)
+{
+       uint32_t i, cnt;
+       printf("entries in use: %u, mbuf holded %u\n", tbl->use_entries,
+                         tbl->nb_mbufs);
+       struct ip_frag_pkt *fp;
+       TAILQ_FOREACH(fp, &tbl->lru, lru)
+               if (!ip_frag_key_is_empty(&fp->key)) {
+
+                       /* cnt mbufs in the packet */
+                       cnt = 0;
+                       for (i=0; i!=fp->last_idx; i++)
+                               if (fp->frags[i].mb != NULL)
+                                       cnt++;
+
+                       printf("start %"PRIu64", mbuf cnt %u\n", fp->start, cnt);
+               }
+}
+
+#endif /* RTE_IP_FRAG_DEBUG */
\ No newline at end of file
diff --git a/lib/librte_ip_frag/rte_ipv4_reassembly.c b/lib/librte_ip_frag/rte_ipv4_reassembly.c
index 040bd70..4bb0dce 100644
--- a/lib/librte_ip_frag/rte_ipv4_reassembly.c
+++ b/lib/librte_ip_frag/rte_ipv4_reassembly.c
@@ -173,7 +173,7 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 
 
        /* process the fragmented packet. */
-       mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len, ip_flag);
+       mb = ip_frag_process(tbl, fp, dr, mb, ip_ofs, ip_len, ip_flag);
        ip_frag_inuse(tbl, fp);
 
        IP_FRAG_LOG(DEBUG, "%s:%d:\n"
diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_frag/rte_ipv6_reassembly.c
index dde58cb..b374d39 100644
--- a/lib/librte_ip_frag/rte_ipv6_reassembly.c
+++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c
@@ -213,7 +213,7 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 
 
        /* process the fragmented packet. */
-       mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len,
+       mb = ip_frag_process(tbl, fp, dr, mb, ip_ofs, ip_len,
                        MORE_FRAGS(frag_hdr->frag_data));
        ip_frag_inuse(tbl, fp);
 
