blob: 37cbb3658974af2f752a560aa72a2271520a4fb0 [file] [log] [blame]
Neale Rannsd792d9c2017-10-21 10:53:20 -07001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/bier/bier_fmask_db.h>
17#include <vnet/bier/bier_fmask.h>
18
19/**
20 * Global Table of fmask objects
21 * The key into this table includes the table's key and the fmask's key,
22 * so there could be a DB per-table. But it is more efficient
23 * at forwarding time to extract the fmask from a single global table
24 * which is hot in dcache.
25 *
26 * The table's key is part of this DB key, since the fmasks therein build up
27 * their forwarding mask based on the routes that resolve through
28 * it, so cross polination would be bad.
29 */
30typedef struct bier_fmask_db_t_ {
31 /**
32 * hash table for underlying storage
33 */
34 mhash_t bfdb_hash;
35
36 /**
37 * Pool for memory
38 */
39 struct bier_fmask_t_ *bfdb_pool;
40} bier_fmask_db_t;
41
42/**
43 * The key used in the fmask DB to compare fmask objects.
44 * There is one global DB, so we need to use the table's ID and the fmasks ID
45 */
46typedef struct bier_fmask_db_key_t_ {
47 bier_fmask_id_t bfmdbk_fm_id;
48 index_t bfmdbk_tbl_id;
49} bier_fmask_db_key_t;
50// TODO packed?
51
52/**
53 * Single fmask DB
54 */
55static bier_fmask_db_t bier_fmask_db;
56
57
58u32
59bier_fmask_get_index (const bier_fmask_t *bfm)
60{
61 return (bfm - bier_fmask_db.bfdb_pool);
62}
63
64u32
65bier_fmask_db_find_or_create_and_lock (index_t bti,
66 const bier_fmask_id_t *fmid,
67 const fib_route_path_t *rpath)
68{
69 bier_fmask_db_key_t key;
70 u32 index;
71 uword *p;
72
73 /*
74 * there be padding in that thar key, and it's
75 * used as a memcmp in the mhash.
76 */
77 memset(&key, 0, sizeof(key));
78 key.bfmdbk_tbl_id = bti;
79 key.bfmdbk_fm_id = *fmid;
80
81 index = INDEX_INVALID;
82 p = mhash_get (&bier_fmask_db.bfdb_hash, &key);
83
84 if (NULL == p)
85 {
86 /*
87 * adding a new fmask object
88 */
89 index = bier_fmask_create_and_lock(fmid, bti, rpath);
90
91 mhash_set (&bier_fmask_db.bfdb_hash, &key, index, 0 /*old_value*/);
92 }
93 else
94 {
95 index = p[0];
96 bier_fmask_lock(index);
97 }
98
99 return (index);
100}
101
102u32
103bier_fmask_db_find (index_t bti,
104 const bier_fmask_id_t *fmid)
105{
106 bier_fmask_db_key_t key;
107 u32 index;
108 uword *p;
109
110 /*
111 * there be padding in that thar key, and it's
112 * used as a memcmp in the mhash.
113 */
114 memset(&key, 0, sizeof(key));
115 key.bfmdbk_tbl_id = bti;
116 key.bfmdbk_fm_id = *fmid;
117
118 index = INDEX_INVALID;
119 p = mhash_get(&bier_fmask_db.bfdb_hash, &key);
120
121 if (NULL != p)
122 {
123 index = p[0];
124 }
125
126 return (index);
127}
128
129void
130bier_fmask_db_remove (index_t bti,
131 const bier_fmask_id_t *fmid)
132{
133 bier_fmask_db_key_t key = {
134 .bfmdbk_tbl_id = bti,
135 .bfmdbk_fm_id = *fmid,
136 };
137 uword *p;
138
139 p = mhash_get (&bier_fmask_db.bfdb_hash, &key);
140
141 if (NULL == p) {
142 /*
143 * remove a non-exitant entry - oops
144 */
145 ASSERT (!"remove non-existant fmask");
146 } else {
147 mhash_unset (&(bier_fmask_db.bfdb_hash), &key, 0);
148 }
149}
150
151clib_error_t *
152bier_fmask_db_module_init (vlib_main_t *vm)
153{
154 mhash_init (&bier_fmask_db.bfdb_hash,
155 sizeof(uword),
156 sizeof(bier_fmask_db_key_t));
157
158 return (NULL);
159}
160
161VLIB_INIT_FUNCTION (bier_fmask_db_module_init);