1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

Implement optional table entry limits for if_llatbl.

Implement counting of table entries linked on a per-table base
with an optional (if set > 0) limit of the maximum number of table
entries.

For that the public lltable_link_entry() and lltable_unlink_entry()
functions as well as the internal function pointers change from void
to having an int return type.

Given no consumer currently sets the new llt_maxentries this can be
committed on its own.  The moment we make use of the table limits,
the callers of the link function must check the return value as
it can change and entries might not be added.

Adjustments for IPv6 (and possibly IPv4) will follow.

Sponsored by:	Netflix (originally)
Reviewed by:	melifaro
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D22713
This commit is contained in:
Bjoern A. Zeeb 2020-03-04 17:17:02 +00:00
parent 96dad2b720
commit 3818c25a1d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=358625
2 changed files with 41 additions and 13 deletions

View File

@ -153,17 +153,29 @@ htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
return (error);
}
static void
/*
* The htable_[un]link_entry() functions return:
* 0 if the entry was (un)linked already and nothing changed,
* 1 if the entry was added/removed to/from the table, and
* -1 on error (e.g., not being able to add the entry due to limits reached).
* While the "unlink" operation should never error, callers of
* lltable_link_entry() need to check for errors and handle them.
*/
static int
htable_link_entry(struct lltable *llt, struct llentry *lle)
{
struct llentries *lleh;
uint32_t hashidx;
if ((lle->la_flags & LLE_LINKED) != 0)
return;
return (0);
IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
if (llt->llt_maxentries > 0 &&
llt->llt_entries >= llt->llt_maxentries)
return (-1);
hashidx = llt->llt_hash(lle, llt->llt_hsize);
lleh = &llt->lle_head[hashidx];
@ -171,22 +183,33 @@ htable_link_entry(struct lltable *llt, struct llentry *lle)
lle->lle_head = lleh;
lle->la_flags |= LLE_LINKED;
CK_LIST_INSERT_HEAD(lleh, lle, lle_next);
llt->llt_entries++;
return (1);
}
static void
static int
htable_unlink_entry(struct llentry *lle)
{
struct lltable *llt;
if ((lle->la_flags & LLE_LINKED) == 0)
return;
return (0);
llt = lle->lle_tbl;
IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
KASSERT(llt->llt_entries > 0, ("%s: lltable %p (%s) entries %d <= 0",
__func__, llt, if_name(llt->llt_ifp), llt->llt_entries));
IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
CK_LIST_REMOVE(lle, lle_next);
lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
#if 0
lle->lle_tbl = NULL;
lle->lle_head = NULL;
#endif
llt->llt_entries--;
return (1);
}
struct prefix_match_data {
@ -483,6 +506,9 @@ lltable_free(struct lltable *llt)
llentry_free(lle);
}
KASSERT(llt->llt_entries == 0, ("%s: lltable %p (%s) entires not 0: %d",
__func__, llt, llt->llt_ifp->if_xname, llt->llt_entries));
llt->llt_free_tbl(llt);
}
@ -608,18 +634,18 @@ lltable_free_entry(struct lltable *llt, struct llentry *lle)
llt->llt_free_entry(llt, lle);
}
void
int
lltable_link_entry(struct lltable *llt, struct llentry *lle)
{
llt->llt_link_entry(llt, lle);
return (llt->llt_link_entry(llt, lle));
}
void
int
lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
{
llt->llt_unlink_entry(lle);
return (llt->llt_unlink_entry(lle));
}
void

View File

@ -151,8 +151,8 @@ typedef int (llt_match_prefix_t)(const struct sockaddr *,
typedef void (llt_free_entry_t)(struct lltable *, struct llentry *);
typedef void (llt_fill_sa_entry_t)(const struct llentry *, struct sockaddr *);
typedef void (llt_free_tbl_t)(struct lltable *);
typedef void (llt_link_entry_t)(struct lltable *, struct llentry *);
typedef void (llt_unlink_entry_t)(struct llentry *);
typedef int (llt_link_entry_t)(struct lltable *, struct llentry *);
typedef int (llt_unlink_entry_t)(struct llentry *);
typedef void (llt_mark_used_t)(struct llentry *);
typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
@ -162,6 +162,8 @@ struct lltable {
SLIST_ENTRY(lltable) llt_link;
int llt_af;
int llt_hsize;
int llt_entries;
int llt_maxentries;
struct llentries *lle_head;
struct ifnet *llt_ifp;
@ -230,8 +232,8 @@ struct llentry *lltable_alloc_entry(struct lltable *llt, u_int flags,
void lltable_free_entry(struct lltable *llt, struct llentry *lle);
int lltable_delete_addr(struct lltable *llt, u_int flags,
const struct sockaddr *l3addr);
void lltable_link_entry(struct lltable *llt, struct llentry *lle);
void lltable_unlink_entry(struct lltable *llt, struct llentry *lle);
int lltable_link_entry(struct lltable *llt, struct llentry *lle);
int lltable_unlink_entry(struct lltable *llt, struct llentry *lle);
void lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa);
struct ifnet *lltable_get_ifp(const struct lltable *llt);
int lltable_get_af(const struct lltable *llt);