Line data Source code
1 : /*
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 pollination would be bad.
29 : */
30 : typedef struct bier_fmask_db_t_ {
31 : /**
32 : * hash table for underlying storage
33 : */
34 : uword *bfdb_hash;
35 :
36 : /**
37 : * Pool for memory
38 : */
39 : struct bier_fmask_t_ *bfdb_pool;
40 : } bier_fmask_db_t;
41 :
42 : /**
43 : * Single fmask DB
44 : */
45 : static bier_fmask_db_t bier_fmask_db;
46 :
47 :
48 : u32
49 0 : bier_fmask_get_index (const bier_fmask_t *bfm)
50 : {
51 0 : return (bfm - bier_fmask_db.bfdb_pool);
52 : }
53 :
54 : static void
55 163 : bier_fmask_db_mk_key (index_t bti,
56 : const fib_route_path_t *rpath,
57 : bier_fmask_id_t *key)
58 : {
59 : /*
60 : * Depending on what the ID is there may be padding.
61 : * This key will be memcmp'd in the mhash, so make sure it's all 0
62 : */
63 163 : clib_memset(key, 0, sizeof(*key));
64 :
65 : /*
66 : * Pick the attributes from the path that make the FMask unique
67 : */
68 163 : if (FIB_ROUTE_PATH_UDP_ENCAP & rpath->frp_flags)
69 : {
70 2 : key->bfmi_id = rpath->frp_udp_encap_id;
71 2 : key->bfmi_nh_type = BIER_NH_UDP;
72 : }
73 : else
74 : {
75 161 : memcpy(&key->bfmi_nh, &rpath->frp_addr, sizeof(rpath->frp_addr));
76 161 : key->bfmi_nh_type = BIER_NH_IP;
77 : }
78 163 : if (NULL == rpath->frp_label_stack)
79 : {
80 13 : key->bfmi_hdr_type = BIER_HDR_O_OTHER;
81 : }
82 : else
83 : {
84 150 : key->bfmi_hdr_type = BIER_HDR_O_MPLS;
85 : }
86 163 : key->bfmi_bti = bti;
87 163 : }
88 :
89 : u32
90 81 : bier_fmask_db_find (index_t bti,
91 : const fib_route_path_t *rpath)
92 : {
93 : bier_fmask_id_t fmid;
94 : uword *p;
95 :
96 81 : bier_fmask_db_mk_key(bti, rpath, &fmid);
97 81 : p = hash_get_mem(bier_fmask_db.bfdb_hash, &fmid);
98 :
99 81 : if (NULL != p)
100 : {
101 80 : return (p[0]);
102 : }
103 :
104 1 : return (INDEX_INVALID);
105 : }
106 :
107 : u32
108 82 : bier_fmask_db_find_or_create_and_lock (index_t bti,
109 : const fib_route_path_t *rpath)
110 : {
111 : bier_fmask_id_t fmid;
112 : u32 index;
113 : uword *p;
114 :
115 82 : bier_fmask_db_mk_key(bti, rpath, &fmid);
116 82 : p = hash_get_mem(bier_fmask_db.bfdb_hash, &fmid);
117 :
118 82 : if (NULL == p)
119 : {
120 : bier_fmask_t *bfm;
121 : /*
122 : * adding a new fmask object
123 : */
124 77 : index = bier_fmask_create_and_lock(&fmid, rpath);
125 77 : bfm = bier_fmask_get(index);
126 154 : hash_set_mem(bier_fmask_db.bfdb_hash, bfm->bfm_id, index);
127 : }
128 : else
129 : {
130 5 : index = p[0];
131 5 : bier_fmask_lock(index);
132 : }
133 :
134 82 : return (index);
135 : }
136 :
137 : void
138 77 : bier_fmask_db_remove (const bier_fmask_id_t *fmid)
139 : {
140 : uword *p;
141 :
142 77 : p = hash_get_mem(bier_fmask_db.bfdb_hash, fmid);
143 :
144 77 : if (NULL == p) {
145 : /*
146 : * remove a non-existent entry - oops
147 : */
148 0 : ASSERT (!"remove non-existent fmask");
149 : } else {
150 77 : hash_unset(bier_fmask_db.bfdb_hash, fmid);
151 : }
152 77 : }
153 :
154 : void
155 0 : bier_fmask_db_walk (bier_fmask_walk_fn_t fn, void *ctx)
156 : {
157 : CLIB_UNUSED (bier_fmask_id_t *fmid);
158 : uword *bfmi;
159 :
160 0 : hash_foreach(fmid, bfmi, bier_fmask_db.bfdb_hash,
161 : ({
162 : if (WALK_STOP == fn(*bfmi, ctx))
163 : break;
164 : }));
165 0 : }
166 :
167 : clib_error_t *
168 575 : bier_fmask_db_module_init (vlib_main_t *vm)
169 : {
170 575 : bier_fmask_db.bfdb_hash = hash_create_mem(0,
171 : sizeof(bier_fmask_id_t),
172 : sizeof(index_t));
173 :
174 575 : return (NULL);
175 : }
176 :
177 91007 : VLIB_INIT_FUNCTION (bier_fmask_db_module_init);
|