aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/in_fib_dxr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/in_fib_dxr.c')
-rw-r--r--sys/netinet/in_fib_dxr.c131
1 files changed, 50 insertions, 81 deletions
diff --git a/sys/netinet/in_fib_dxr.c b/sys/netinet/in_fib_dxr.c
index e7eede53ea51..b889131b544b 100644
--- a/sys/netinet/in_fib_dxr.c
+++ b/sys/netinet/in_fib_dxr.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2012-2022 Marko Zec
+ * Copyright (c) 2012-2024 Marko Zec
* Copyright (c) 2005, 2018 University of Zagreb
* Copyright (c) 2005 International Computer Science Institute
*
@@ -68,9 +68,6 @@
CTASSERT(DXR_TRIE_BITS >= 16 && DXR_TRIE_BITS <= 24);
-/* DXR2: two-stage primary trie, instead of a single direct lookup table */
-#define DXR2
-
#if DXR_TRIE_BITS > 16
#define DXR_D 16
#else
@@ -317,7 +314,6 @@ range_lookup(struct range_entry_long *rt, struct direct_entry de, uint32_t dst)
ntohl(key.addr4.s_addr))]); \
}
-#ifdef DXR2
#if DXR_TRIE_BITS > 16
DXR_LOOKUP_DEFINE(16)
#endif
@@ -328,23 +324,16 @@ DXR_LOOKUP_DEFINE(12)
DXR_LOOKUP_DEFINE(11)
DXR_LOOKUP_DEFINE(10)
DXR_LOOKUP_DEFINE(9)
-#endif /* DXR2 */
static int inline
dxr_lookup(struct dxr *dxr, uint32_t dst)
{
struct direct_entry de;
-#ifdef DXR2
uint16_t *dt = dxr->d;
struct direct_entry *xt = dxr->x;
de = xt[(dt[dst >> dxr->d_shift] << dxr->x_shift) +
((dst >> DXR_RANGE_SHIFT) & dxr->x_mask)];
-#else /* !DXR2 */
- struct direct_entry *dt = dxr->d;
-
- de = dt[dst >> DXR_RANGE_SHIFT];
-#endif /* !DXR2 */
if (__predict_true(de.fragments == FRAGS_MARK_HIT))
return (de.base);
return (range_lookup(dxr->r, de, dst));
@@ -474,8 +463,7 @@ chunk_ref(struct dxr_aux *da, uint32_t chunk)
cdp->cd_max_size = size;
cdp->cd_base = fdesc->base;
LIST_INSERT_HEAD(&da->all_chunks, cdp, cd_all_le);
- KASSERT(cdp->cd_base + cdp->cd_max_size == da->rtbl_top,
- ("dxr: %s %d", __FUNCTION__, __LINE__));
+ MPASS(cdp->cd_base + cdp->cd_max_size == da->rtbl_top);
}
cdp->cd_hash = hash;
@@ -497,8 +485,11 @@ chunk_ref(struct dxr_aux *da, uint32_t chunk)
da->range_tbl = realloc(da->range_tbl,
sizeof(*da->range_tbl) * da->rtbl_size + FRAGS_PREF_SHORT,
M_DXRAUX, M_NOWAIT);
- if (da->range_tbl == NULL)
+ if (da->range_tbl == NULL) {
+ FIB_PRINTF(LOG_NOTICE, da->fd,
+ "Unable to allocate DXR range table");
return (1);
+ }
}
return (0);
@@ -522,7 +513,7 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)
sizeof(struct range_entry_long) * size) == 0)
break;
- KASSERT(cdp != NULL, ("dxr: dangling chunk"));
+ MPASS(cdp != NULL);
if (--cdp->cd_refcnt > 0)
return;
@@ -533,8 +524,7 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)
/* 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__));
+ MPASS(cdp2->cd_base + cdp2->cd_max_size == cdp->cd_base);
LIST_REMOVE(cdp, cd_all_le);
LIST_REMOVE(cdp2, cd_hash_le);
cdp2->cd_max_size += cdp->cd_max_size;
@@ -545,8 +535,7 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)
/* 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__));
+ MPASS(cdp->cd_base + cdp->cd_max_size == cdp2->cd_base);
LIST_REMOVE(cdp, cd_all_le);
LIST_REMOVE(cdp2, cd_hash_le);
cdp2->cd_max_size += cdp->cd_max_size;
@@ -557,8 +546,7 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)
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__));
+ MPASS(cdp == LIST_FIRST(&da->all_chunks));
da->rtbl_top -= cdp->cd_max_size;
da->unused_chunks_size -= cdp->cd_max_size;
LIST_REMOVE(cdp, cd_all_le);
@@ -572,7 +560,6 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)
LIST_INSERT_HEAD(&da->unused_chunks[i], cdp, cd_hash_le);
}
-#ifdef DXR2
static uint32_t
trie_hash(struct dxr_aux *da, uint32_t dxr_x, uint32_t index)
{
@@ -632,8 +619,11 @@ trie_ref(struct dxr_aux *da, uint32_t index)
da->xtbl_size += XTBL_SIZE_INCR;
da->x_tbl = realloc(da->x_tbl,
sizeof(*da->x_tbl) * da->xtbl_size, M_DXRAUX, M_NOWAIT);
- if (da->x_tbl == NULL)
+ if (da->x_tbl == NULL) {
+ FIB_PRINTF(LOG_NOTICE, da->fd,
+ "Unable to allocate DXR extension table");
return (-1);
+ }
}
return(tp->td_index);
}
@@ -668,7 +658,6 @@ trie_unref(struct dxr_aux *da, uint32_t index)
}
} while (tp != NULL);
}
-#endif
static void
heap_inject(struct dxr_aux *da, uint32_t start, uint32_t end, uint32_t preflen,
@@ -862,21 +851,23 @@ dxr_build(struct dxr *dxr)
uint32_t r_size, dxr_tot_size;
uint32_t i, m, range_rebuild = 0;
uint32_t range_frag;
-#ifdef DXR2
struct trie_desc *tp;
uint32_t d_tbl_size, dxr_x, d_size, x_size;
uint32_t ti, trie_rebuild = 0, prev_size = 0;
uint32_t trie_frag;
-#endif
- KASSERT(dxr->d == NULL, ("dxr: d not free"));
+ MPASS(dxr->d == NULL);
if (da == NULL) {
da = malloc(sizeof(*dxr->aux), M_DXRAUX, M_NOWAIT);
- if (da == NULL)
+ if (da == NULL) {
+ FIB_PRINTF(LOG_NOTICE, dxr->fd,
+ "Unable to allocate DXR aux struct");
return;
+ }
dxr->aux = da;
da->fibnum = dxr->fibnum;
+ da->fd = dxr->fd;
da->refcnt = 1;
LIST_INIT(&da->all_chunks);
LIST_INIT(&da->all_trie);
@@ -894,20 +885,23 @@ dxr_build(struct dxr *dxr)
if (da->range_tbl == NULL) {
da->range_tbl = malloc(sizeof(*da->range_tbl) * da->rtbl_size
+ FRAGS_PREF_SHORT, M_DXRAUX, M_NOWAIT);
- if (da->range_tbl == NULL)
+ if (da->range_tbl == NULL) {
+ FIB_PRINTF(LOG_NOTICE, da->fd,
+ "Unable to allocate DXR range table");
return;
+ }
range_rebuild = 1;
}
-#ifdef DXR2
if (da->x_tbl == NULL) {
da->x_tbl = malloc(sizeof(*da->x_tbl) * da->xtbl_size,
M_DXRAUX, M_NOWAIT);
- if (da->x_tbl == NULL)
+ if (da->x_tbl == NULL) {
+ FIB_PRINTF(LOG_NOTICE, da->fd,
+ "Unable to allocate DXR extension table");
return;
+ }
trie_rebuild = 1;
}
-#endif
- da->fd = dxr->fd;
microuptime(&t0);
@@ -959,7 +953,6 @@ range_build:
r_size = sizeof(*da->range_tbl) * da->rtbl_top;
microuptime(&t1);
-#ifdef DXR2
if (range_rebuild ||
abs(fls(da->prefixes) - fls(da->trie_rebuilt_prefixes)) > 1)
trie_rebuild = 1;
@@ -1033,15 +1026,13 @@ dxr2_try_squeeze:
goto dxr2_try_squeeze;
}
microuptime(&t2);
-#else /* !DXR2 */
- dxr_tot_size = sizeof(da->direct_tbl) + r_size;
- t2 = t1;
-#endif
dxr->d = malloc(dxr_tot_size, M_DXRLPM, M_NOWAIT);
- if (dxr->d == NULL)
+ if (dxr->d == NULL) {
+ FIB_PRINTF(LOG_NOTICE, da->fd,
+ "Unable to allocate DXR lookup table");
return;
-#ifdef DXR2
+ }
memcpy(dxr->d, da->d_tbl, d_size);
dxr->x = ((char *) dxr->d) + d_size;
memcpy(dxr->x, da->x_tbl, x_size);
@@ -1049,10 +1040,6 @@ dxr2_try_squeeze:
dxr->d_shift = 32 - da->d_bits;
dxr->x_shift = dxr_x;
dxr->x_mask = 0xffffffffU >> (32 - dxr_x);
-#else /* !DXR2 */
- memcpy(dxr->d, da->direct_tbl, sizeof(da->direct_tbl));
- dxr->r = ((char *) dxr->d) + sizeof(da->direct_tbl);
-#endif
memcpy(dxr->r, da->range_tbl, r_size);
if (da->updates_low <= da->updates_high)
@@ -1062,43 +1049,31 @@ dxr2_try_squeeze:
da->updates_high = 0;
microuptime(&t3);
-#ifdef DXR2
FIB_PRINTF(LOG_INFO, da->fd, "D%dX%dR, %d prefixes, %d nhops (max)",
da->d_bits, dxr_x, rinfo.num_prefixes, rinfo.num_nhops);
-#else
- FIB_PRINTF(LOG_INFO, da->fd, "D%dR, %d prefixes, %d nhops (max)",
- DXR_D, rinfo.num_prefixes, rinfo.num_nhops);
-#endif
i = dxr_tot_size * 100;
if (rinfo.num_prefixes)
i /= rinfo.num_prefixes;
FIB_PRINTF(LOG_INFO, da->fd, "%d.%02d KBytes, %d.%02d Bytes/prefix",
dxr_tot_size / 1024, dxr_tot_size * 100 / 1024 % 100,
i / 100, i % 100);
-#ifdef DXR2
FIB_PRINTF(LOG_INFO, da->fd,
"%d.%02d%% trie, %d.%02d%% range fragmentation",
trie_frag / 100, trie_frag % 100,
range_frag / 100, range_frag % 100);
-#else
- FIB_PRINTF(LOG_INFO, da->fd, "%d.%01d%% range fragmentation",
- range_frag / 100, range_frag % 100);
-#endif
i = (t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec;
FIB_PRINTF(LOG_INFO, da->fd, "range table %s in %u.%03u ms",
range_rebuild ? "rebuilt" : "updated", i / 1000, i % 1000);
-#ifdef DXR2
i = (t2.tv_sec - t1.tv_sec) * 1000000 + t2.tv_usec - t1.tv_usec;
FIB_PRINTF(LOG_INFO, da->fd, "trie %s in %u.%03u ms",
trie_rebuild ? "rebuilt" : "updated", i / 1000, i % 1000);
-#endif
i = (t3.tv_sec - t2.tv_sec) * 1000000 + t3.tv_usec - t2.tv_usec;
FIB_PRINTF(LOG_INFO, da->fd, "snapshot forked in %u.%03u ms",
i / 1000, i % 1000);
}
/*
- * Glue functions for attaching to FreeBSD 13 fib_algo infrastructure.
+ * Glue functions for attaching to the FIB_ALGO infrastructure.
*/
static struct nhop_object *
@@ -1118,11 +1093,15 @@ dxr_init(uint32_t fibnum, struct fib_data *fd, void *old_data, void **data)
struct dxr *dxr;
dxr = malloc(sizeof(*dxr), M_DXRAUX, M_NOWAIT);
- if (dxr == NULL)
+ if (dxr == NULL) {
+ FIB_PRINTF(LOG_NOTICE, fd,
+ "Unable to allocate DXR container struct");
return (FLM_REBUILD);
+ }
/* Check whether we may reuse the old auxiliary structures */
- if (old_dxr != NULL && old_dxr->aux != NULL) {
+ if (old_dxr != NULL && old_dxr->aux != NULL &&
+ old_dxr->aux->fd == fd) {
da = old_dxr->aux;
atomic_add_int(&da->refcnt, 1);
}
@@ -1140,14 +1119,11 @@ static void
dxr_destroy(void *data)
{
struct dxr *dxr = data;
- struct dxr_aux *da;
+ struct dxr_aux *da = dxr->aux;
struct chunk_desc *cdp;
struct trie_desc *tp;
- if (dxr->d != NULL)
- free(dxr->d, M_DXRLPM);
-
- da = dxr->aux;
+ free(dxr->d, M_DXRLPM);
free(dxr, M_DXRAUX);
if (da == NULL || atomic_fetchadd_int(&da->refcnt, -1) > 1)
@@ -1179,7 +1155,6 @@ static void *
choose_lookup_fn(struct dxr_aux *da)
{
-#ifdef DXR2
switch (da->d_bits) {
#if DXR_TRIE_BITS > 16
case 16:
@@ -1200,7 +1175,6 @@ choose_lookup_fn(struct dxr_aux *da)
case 9:
return (dxr_fib_lookup_9);
}
-#endif /* DXR2 */
return (dxr_fib_lookup);
}
@@ -1213,17 +1187,12 @@ dxr_dump_end(void *data, struct fib_dp *dp)
dxr_build(dxr);
da = dxr->aux;
- if (da == NULL)
+ if (da == NULL || dxr->d == NULL)
return (FLM_REBUILD);
- /* Structural limit exceeded, hard error */
if (da->rtbl_top >= BASE_MAX)
return (FLM_ERROR);
- /* A malloc(,, M_NOWAIT) failed somewhere, retry later */
- if (dxr->d == NULL)
- return (FLM_REBUILD);
-
dp->f = choose_lookup_fn(da);
dp->arg = dxr;
@@ -1260,13 +1229,14 @@ dxr_change_rib_batch(struct rib_head *rnh, struct fib_change_queue *q,
int update_delta = 0;
#endif
- KASSERT(data != NULL, ("%s: NULL data", __FUNCTION__));
- KASSERT(q != NULL, ("%s: NULL q", __FUNCTION__));
- KASSERT(q->count < q->size, ("%s: q->count %d q->size %d",
- __FUNCTION__, q->count, q->size));
+ MPASS(data != NULL);
+ MPASS(q != NULL);
+ MPASS(q->count < q->size);
da = dxr->aux;
- KASSERT(da != NULL, ("%s: NULL dxr->aux", __FUNCTION__));
+ MPASS(da != NULL);
+ MPASS(da->fd == dxr->fd);
+ MPASS(da->refcnt > 0);
FIB_PRINTF(LOG_INFO, da->fd, "processing %d update(s)", q->count);
for (ui = 0; ui < q->count; ui++) {
@@ -1299,8 +1269,7 @@ dxr_change_rib_batch(struct rib_head *rnh, struct fib_change_queue *q,
#ifdef INVARIANTS
fib_get_rtable_info(fib_get_rh(da->fd), &rinfo);
- KASSERT(da->prefixes + update_delta == rinfo.num_prefixes,
- ("%s: update count mismatch", __FUNCTION__));
+ MPASS(da->prefixes + update_delta == rinfo.num_prefixes);
#endif
res = dxr_init(0, dxr->fd, data, (void **) &new_dxr);
@@ -1315,7 +1284,6 @@ dxr_change_rib_batch(struct rib_head *rnh, struct fib_change_queue *q,
return (FLM_ERROR);
}
- /* A malloc(,, M_NOWAIT) failed somewhere, retry later */
if (new_dxr->d == NULL) {
dxr_destroy(new_dxr);
return (FLM_REBUILD);
@@ -1329,6 +1297,7 @@ dxr_change_rib_batch(struct rib_head *rnh, struct fib_change_queue *q,
return (FLM_SUCCESS);
}
+ FIB_PRINTF(LOG_NOTICE, dxr->fd, "fib_set_datapath_ptr() failed");
dxr_destroy(new_dxr);
return (FLM_REBUILD);
}