Skip to content

Commit

Permalink
[fib_algo][dxr] Merge adjacent empty range table chunks.
Browse files Browse the repository at this point in the history
MFC after:	3 days
  • Loading branch information
gornjas committed Sep 29, 2021
1 parent 095d3f9 commit c5981a8
Showing 1 changed file with 45 additions and 15 deletions.
60 changes: 45 additions & 15 deletions sys/netinet/in_fib_dxr.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,29 +418,32 @@ chunk_ref(struct dxr_aux *da, uint32_t chunk)
fdesc->base = cdp->cd_base;
da->rtbl_top -= size;
da->unused_chunks_cnt--;
if (cdp->cd_max_size > size + 1) {
if (cdp->cd_max_size > size) {
/* Split the range in two, need a new descriptor */
empty_cdp = uma_zalloc(chunk_zone, M_NOWAIT);
if (empty_cdp == NULL)
return (1);
empty_cdp->cd_cur_size = 0;
empty_cdp->cd_max_size = cdp->cd_max_size - size;
empty_cdp->cd_base = cdp->cd_base + size;
LIST_INSERT_AFTER(cdp, empty_cdp, cd_all_le);
LIST_INSERT_BEFORE(cdp, empty_cdp, cd_all_le);
LIST_INSERT_AFTER(cdp, empty_cdp, cd_hash_le);
da->all_chunks_cnt++;
da->unused_chunks_cnt++;
cdp->cd_max_size = size;
}
LIST_REMOVE(cdp, cd_hash_le);
} else {
/* Alloc a new descriptor */
/* Alloc a new descriptor at the top of the heap*/
cdp = uma_zalloc(chunk_zone, M_NOWAIT);
if (cdp == NULL)
return (1);
cdp->cd_max_size = size;
cdp->cd_base = fdesc->base;
LIST_INSERT_HEAD(&da->all_chunks, cdp, cd_all_le);
da->all_chunks_cnt++;
KASSERT(cdp->cd_base + cdp->cd_max_size == da->rtbl_top,
("dxr: %s %d", __FUNCTION__, __LINE__));
}

cdp->cd_hash = hash;
Expand Down Expand Up @@ -473,12 +476,12 @@ static void
chunk_unref(struct dxr_aux *da, uint32_t chunk)
{
struct direct_entry *fdesc = &da->direct_tbl[chunk];
struct chunk_desc *cdp;
struct chunk_desc *cdp, *cdp2;
uint32_t base = fdesc->base;
uint32_t size = chunk_size(da, fdesc);
uint32_t hash = chunk_hash(da, fdesc);

/* Find an existing descriptor */
/* Find the corresponding descriptor */
LIST_FOREACH(cdp, &da->chunk_hashtbl[hash & CHUNK_HASH_MASK],
cd_hash_le)
if (cdp->cd_hash == hash && cdp->cd_cur_size == size &&
Expand All @@ -492,23 +495,50 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)

LIST_REMOVE(cdp, cd_hash_le);
da->unused_chunks_cnt++;
if (cdp->cd_base + cdp->cd_max_size != da->rtbl_top) {
LIST_INSERT_HEAD(&da->unused_chunks, cdp, cd_hash_le);
return;
cdp->cd_cur_size = 0;

/* Attempt to merge with the preceding chunk, if empty */
cdp2 = LIST_NEXT(cdp, cd_all_le);
if (cdp2 != NULL && cdp2->cd_cur_size == 0) {
KASSERT(cdp2->cd_base + cdp2->cd_max_size == cdp->cd_base,
("dxr: %s %d", __FUNCTION__, __LINE__));
LIST_REMOVE(cdp, cd_all_le);
da->all_chunks_cnt--;
LIST_REMOVE(cdp2, cd_hash_le);
da->unused_chunks_cnt--;
cdp2->cd_max_size += cdp->cd_max_size;
uma_zfree(chunk_zone, cdp);
cdp = cdp2;
}

do {
/* Attempt to merge with the subsequent chunk, if empty */
cdp2 = LIST_PREV(cdp, &da->all_chunks, chunk_desc, cd_all_le);
if (cdp2 != NULL && cdp2->cd_cur_size == 0) {
KASSERT(cdp->cd_base + cdp->cd_max_size == cdp2->cd_base,
("dxr: %s %d", __FUNCTION__, __LINE__));
LIST_REMOVE(cdp, cd_all_le);
da->all_chunks_cnt--;
LIST_REMOVE(cdp2, cd_hash_le);
da->unused_chunks_cnt--;
cdp2->cd_max_size += cdp->cd_max_size;
cdp2->cd_base = cdp->cd_base;
uma_zfree(chunk_zone, cdp);
cdp = cdp2;
}

if (cdp->cd_base + cdp->cd_max_size == da->rtbl_top) {
/* Free the chunk on the top of the range heap, trim the heap */
KASSERT(cdp == LIST_FIRST(&da->all_chunks),
("dxr: %s %d", __FUNCTION__, __LINE__));
da->all_chunks_cnt--;
da->unused_chunks_cnt--;
da->rtbl_top -= cdp->cd_max_size;
LIST_REMOVE(cdp, cd_all_le);
uma_zfree(chunk_zone, cdp);
LIST_FOREACH(cdp, &da->unused_chunks, cd_hash_le)
if (cdp->cd_base + cdp->cd_max_size == da->rtbl_top) {
LIST_REMOVE(cdp, cd_hash_le);
break;
}
} while (cdp != NULL);
return;
}

LIST_INSERT_HEAD(&da->unused_chunks, cdp, cd_hash_le);
}

#ifdef DXR2
Expand Down

0 comments on commit c5981a8

Please sign in to comment.