summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-06-28 10:51:00 +0200
committerMaria Matejka <mq@ucw.cz>2022-07-11 16:07:09 +0200
commitfd72c696784ba74e793db1fb7c44668c47a383b2 (patch)
treea7bf6725f33e44c3c2dd6d2191b1afce03a6ec53 /lib
parentdc720a085f0f805891eb086bf96dac99c8a1b7da (diff)
Attribute lists split to storage headers and data to save BGP memory
Diffstat (limited to 'lib')
-rw-r--r--lib/route.h29
1 files changed, 21 insertions, 8 deletions
diff --git a/lib/route.h b/lib/route.h
index 130465f9..30be7c4e 100644
--- a/lib/route.h
+++ b/lib/route.h
@@ -147,10 +147,6 @@ typedef struct eattr {
#define EA_BIT_GET(ea) ((ea) >> 24)
typedef struct ea_list {
- struct ea_list *next_hash; /* Next in hash chain */
- struct ea_list **pprev_hash; /* Previous in hash chain */
- u32 uc; /* Use count */
- u32 hash_key; /* List hash */
struct ea_list *next; /* In case we have an override list */
byte flags; /* Flags: EALF_... */
byte rfu;
@@ -158,10 +154,17 @@ typedef struct ea_list {
eattr attrs[0]; /* Attribute definitions themselves */
} ea_list;
+struct ea_storage {
+ struct ea_storage *next_hash; /* Next in hash chain */
+ struct ea_storage **pprev_hash; /* Previous in hash chain */
+ u32 uc; /* Use count */
+ u32 hash_key; /* List hash */
+ ea_list l[0]; /* The list itself */
+};
+
#define EALF_SORTED 1 /* Attributes are sorted by code */
#define EALF_BISECT 2 /* Use interval bisection for searching */
#define EALF_CACHED 4 /* List is cached */
-#define EALF_OVERLAY 8 /* List is an overlay in the same table */
struct ea_class {
#define EA_CLASS_INSIDE \
@@ -417,9 +420,19 @@ static inline int rte_dest(const rte *r)
void rta_init(void);
ea_list *ea_lookup(ea_list *, int overlay); /* Get a cached (and normalized) variant of this attribute list */
static inline int ea_is_cached(const ea_list *r) { return r->flags & EALF_CACHED; }
-static inline ea_list *ea_clone(ea_list *r) { r->uc++; return r; }
-void ea__free(ea_list *r);
-static inline void ea_free(ea_list *r) { if (r && !--r->uc) ea__free(r); }
+static inline struct ea_storage *ea_get_storage(ea_list *r)
+{
+ ASSERT_DIE(ea_is_cached(r));
+ return SKIP_BACK(struct ea_storage, l, r);
+}
+
+static inline ea_list *ea_clone(ea_list *r) { ea_get_storage(r)->uc++; return r; }
+void ea__free(struct ea_storage *r);
+static inline void ea_free(ea_list *l) {
+ if (!l) return;
+ struct ea_storage *r = ea_get_storage(l);
+ if (!--r->uc) ea__free(r);
+}
void ea_dump(ea_list *);
void ea_dump_all(void);