BIER
- see draft-ietf-bier-mpls-encapsulation-10
- midpoint, head and tail functions
- supported payload protocols; IPv4 and IPv6 only.
Change-Id: I59d7363bb6fdfdce8e4016a68a9c8f5a5e5791cb
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/bier/bier_fmask_db.c b/src/vnet/bier/bier_fmask_db.c
new file mode 100644
index 0000000..37cbb36
--- /dev/null
+++ b/src/vnet/bier/bier_fmask_db.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/bier/bier_fmask_db.h>
+#include <vnet/bier/bier_fmask.h>
+
+/**
+ * Global Table of fmask objects
+ * The key into this table includes the table's key and the fmask's key,
+ * so there could be a DB per-table. But it is more efficient
+ * at forwarding time to extract the fmask from a single global table
+ * which is hot in dcache.
+ *
+ * The table's key is part of this DB key, since the fmasks therein build up
+ * their forwarding mask based on the routes that resolve through
+ * it, so cross polination would be bad.
+ */
+typedef struct bier_fmask_db_t_ {
+ /**
+ * hash table for underlying storage
+ */
+ mhash_t bfdb_hash;
+
+ /**
+ * Pool for memory
+ */
+ struct bier_fmask_t_ *bfdb_pool;
+} bier_fmask_db_t;
+
+/**
+ * The key used in the fmask DB to compare fmask objects.
+ * There is one global DB, so we need to use the table's ID and the fmasks ID
+ */
+typedef struct bier_fmask_db_key_t_ {
+ bier_fmask_id_t bfmdbk_fm_id;
+ index_t bfmdbk_tbl_id;
+} bier_fmask_db_key_t;
+// TODO packed?
+
+/**
+ * Single fmask DB
+ */
+static bier_fmask_db_t bier_fmask_db;
+
+
+u32
+bier_fmask_get_index (const bier_fmask_t *bfm)
+{
+ return (bfm - bier_fmask_db.bfdb_pool);
+}
+
+u32
+bier_fmask_db_find_or_create_and_lock (index_t bti,
+ const bier_fmask_id_t *fmid,
+ const fib_route_path_t *rpath)
+{
+ bier_fmask_db_key_t key;
+ u32 index;
+ uword *p;
+
+ /*
+ * there be padding in that thar key, and it's
+ * used as a memcmp in the mhash.
+ */
+ memset(&key, 0, sizeof(key));
+ key.bfmdbk_tbl_id = bti;
+ key.bfmdbk_fm_id = *fmid;
+
+ index = INDEX_INVALID;
+ p = mhash_get (&bier_fmask_db.bfdb_hash, &key);
+
+ if (NULL == p)
+ {
+ /*
+ * adding a new fmask object
+ */
+ index = bier_fmask_create_and_lock(fmid, bti, rpath);
+
+ mhash_set (&bier_fmask_db.bfdb_hash, &key, index, 0 /*old_value*/);
+ }
+ else
+ {
+ index = p[0];
+ bier_fmask_lock(index);
+ }
+
+ return (index);
+}
+
+u32
+bier_fmask_db_find (index_t bti,
+ const bier_fmask_id_t *fmid)
+{
+ bier_fmask_db_key_t key;
+ u32 index;
+ uword *p;
+
+ /*
+ * there be padding in that thar key, and it's
+ * used as a memcmp in the mhash.
+ */
+ memset(&key, 0, sizeof(key));
+ key.bfmdbk_tbl_id = bti;
+ key.bfmdbk_fm_id = *fmid;
+
+ index = INDEX_INVALID;
+ p = mhash_get(&bier_fmask_db.bfdb_hash, &key);
+
+ if (NULL != p)
+ {
+ index = p[0];
+ }
+
+ return (index);
+}
+
+void
+bier_fmask_db_remove (index_t bti,
+ const bier_fmask_id_t *fmid)
+{
+ bier_fmask_db_key_t key = {
+ .bfmdbk_tbl_id = bti,
+ .bfmdbk_fm_id = *fmid,
+ };
+ uword *p;
+
+ p = mhash_get (&bier_fmask_db.bfdb_hash, &key);
+
+ if (NULL == p) {
+ /*
+ * remove a non-exitant entry - oops
+ */
+ ASSERT (!"remove non-existant fmask");
+ } else {
+ mhash_unset (&(bier_fmask_db.bfdb_hash), &key, 0);
+ }
+}
+
+clib_error_t *
+bier_fmask_db_module_init (vlib_main_t *vm)
+{
+ mhash_init (&bier_fmask_db.bfdb_hash,
+ sizeof(uword),
+ sizeof(bier_fmask_db_key_t));
+
+ return (NULL);
+}
+
+VLIB_INIT_FUNCTION (bier_fmask_db_module_init);