svn commit: r358625 - head/sys/net

Bjoern A. Zeeb bz at FreeBSD.org
Wed Mar 4 17:17:03 UTC 2020


Author: bz
Date: Wed Mar  4 17:17:02 2020
New Revision: 358625
URL: https://svnweb.freebsd.org/changeset/base/358625

Log:
  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

Modified:
  head/sys/net/if_llatbl.c
  head/sys/net/if_llatbl.h

Modified: head/sys/net/if_llatbl.c
==============================================================================
--- head/sys/net/if_llatbl.c	Wed Mar  4 17:13:35 2020	(r358624)
+++ head/sys/net/if_llatbl.c	Wed Mar  4 17:17:02 2020	(r358625)
@@ -153,17 +153,29 @@ htable_foreach_lle(struct lltable *llt, llt_foreach_cb
 	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_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);
 
-	IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
+	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));
+
 	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
 	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

Modified: head/sys/net/if_llatbl.h
==============================================================================
--- head/sys/net/if_llatbl.h	Wed Mar  4 17:13:35 2020	(r358624)
+++ head/sys/net/if_llatbl.h	Wed Mar  4 17:17:02 2020	(r358625)
@@ -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 *ll
 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);


More information about the svn-src-head mailing list