-/* $OpenBSD: rde.h,v 1.177 2018/07/11 16:34:36 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.178 2018/07/11 19:05:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
struct attr {
LIST_ENTRY(attr) entry;
u_char *data;
+ u_int64_t hash;
int refcnt;
- u_int32_t hash;
u_int16_t len;
u_int8_t flags;
u_int8_t type;
u_int16_t unreach_len;
};
-struct path_table {
- struct aspath_head *path_hashtbl;
- u_int32_t path_hashmask;
-};
-
#define F_ATTR_ORIGIN 0x00001
#define F_ATTR_ASPATH 0x00002
#define F_ATTR_NEXTHOP 0x00004
struct rde_peer *peer;
struct aspath *aspath;
struct nexthop *nexthop; /* may be NULL */
+ u_int64_t hash;
+ u_int32_t flags; /* internally used */
u_int32_t med; /* multi exit disc */
u_int32_t lpref; /* local pref */
u_int32_t weight; /* low prio lpref */
- u_int32_t flags; /* internally used */
u_int16_t rtlabelid; /* route label id */
u_int16_t pftableid; /* pf table id */
u_int8_t origin;
struct attr *attr_optget(const struct rde_aspath *, u_int8_t);
void attr_copy(struct rde_aspath *, const struct rde_aspath *);
int attr_compare(struct rde_aspath *, struct rde_aspath *);
+u_int64_t attr_hash(struct rde_aspath *);
void attr_freeall(struct rde_aspath *);
void attr_free(struct rde_aspath *, struct attr *);
#define attr_optlen(x) \
-/* $OpenBSD: rde_attr.c,v 1.103 2018/07/11 16:34:36 claudio Exp $ */
+/* $OpenBSD: rde_attr.c,v 1.104 2018/07/11 19:05:41 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
struct attr_table {
struct attr_list *hashtbl;
- u_int32_t hashmask;
+ u_int64_t hashmask;
} attrtable;
SIPHASH_KEY attrtablekey;
return (-1);
fatalx("attr_diff: equal attributes encountered");
- return (0);
}
int
return (0);
}
+u_int64_t
+attr_hash(struct rde_aspath *a)
+{
+ u_int64_t hash = 0;
+ u_int8_t l;
+
+ for (l = 0; l < a->others_len; l++)
+ if (a->others[l] != NULL)
+ hash ^= a->others[l]->hash;
+ return (hash);
+}
+
void
attr_free(struct rde_aspath *asp, struct attr *attr)
{
{
struct attr_list *head;
struct attr *a;
- u_int32_t hash;
+ u_int64_t hash;
SIPHASH_CTX ctx;
flags &= ~ATTR_DEFMASK; /* normalize mask */
-/* $OpenBSD: rde_rib.c,v 1.169 2018/07/11 16:34:36 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.170 2018/07/11 19:05:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
/* path specific functions */
static struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *);
-static void path_link(struct rde_aspath *, struct rde_peer *);
+static u_int64_t path_hash(struct rde_aspath *);
+static void path_link(struct rde_aspath *, struct rde_peer *);
-struct path_table pathtable;
+struct path_table {
+ struct aspath_head *path_hashtbl;
+ u_int64_t path_hashmask;
+} pathtable;
SIPHASH_KEY pathtablekey;
-/* XXX the hash should also include communities and the other attrs */
-#define PATH_HASH(x) \
- &pathtable.path_hashtbl[x == NULL ? 0 : \
- SipHash24(&pathtablekey, (x)->data, (x)->len) & \
- pathtable.path_hashmask]
+#define PATH_HASH(x) &pathtable.path_hashtbl[x & pathtable.path_hashmask]
void
path_init(u_int32_t hashsize)
return (attr_compare(a, b));
}
+static u_int64_t
+path_hash(struct rde_aspath *asp)
+{
+ SIPHASH_CTX ctx;
+ u_int64_t hash;
+
+ SipHash24_Init(&ctx, &pathtablekey);
+ SipHash24_Update(&ctx, &asp->origin, sizeof(asp->origin));
+ SipHash24_Update(&ctx, &asp->med, sizeof(asp->med));
+ SipHash24_Update(&ctx, &asp->lpref, sizeof(asp->lpref));
+ SipHash24_Update(&ctx, &asp->weight, sizeof(asp->weight));
+ SipHash24_Update(&ctx, &asp->rtlabelid, sizeof(asp->rtlabelid));
+ SipHash24_Update(&ctx, &asp->pftableid, sizeof(asp->pftableid));
+
+ if (asp->aspath)
+ SipHash24_Update(&ctx, asp->aspath->data, asp->aspath->len);
+
+ hash = attr_hash(asp);
+ SipHash24_Update(&ctx, &hash, sizeof(hash));
+
+ return (SipHash24_End(&ctx));
+}
+
static struct rde_aspath *
path_lookup(struct rde_aspath *aspath, struct rde_peer *peer)
{
struct aspath_head *head;
struct rde_aspath *asp;
+ u_int64_t hash;
- head = PATH_HASH(aspath->aspath);
+ hash = path_hash(aspath);
+ head = PATH_HASH(hash);
LIST_FOREACH(asp, head, path_l) {
- if (peer == asp->peer && path_compare(aspath, asp) == 0)
+ if (asp->hash == hash && peer == asp->peer &&
+ path_compare(aspath, asp) == 0)
return (asp);
}
return (NULL);
{
struct aspath_head *head;
- head = PATH_HASH(asp->aspath);
+ asp->peer = peer;
+
+ asp->hash = path_hash(asp);
+ head = PATH_HASH(asp->hash);
LIST_INSERT_HEAD(head, asp, path_l);
- TAILQ_INSERT_TAIL(&peer->path_h, asp, peer_l);
- asp->peer = peer;
+ TAILQ_INSERT_HEAD(&peer->path_h, asp, peer_l);
nexthop_link(asp);
asp->flags |= F_ATTR_LINKED;
}
rdemem.aspath_refs++;
}
dst->nexthop = nexthop_ref(src->nexthop);
+ dst->hash = 0;
dst->med = src->med;
dst->lpref = src->lpref;
dst->weight = src->weight;
TAILQ_INIT(&asp->updates);
asp->origin = ORIGIN_INCOMPLETE;
asp->lpref = DEFAULT_LPREF;
- /* med = 0 */
- /* weight = 0 */
- /* rtlabel = 0 */
return (asp);
}