]>
Commit | Line | Data |
---|---|---|
bce7cf45 BP |
1 | /* Copyright (c) 2015, 2016 Nicira, Inc. |
2 | * | |
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 <config.h> | |
17 | ||
18 | #include "lport.h" | |
19 | #include "hash.h" | |
4470328b | 20 | #include "lflow.h" |
bce7cf45 BP |
21 | #include "openvswitch/vlog.h" |
22 | #include "ovn/lib/ovn-sb-idl.h" | |
23 | ||
24 | VLOG_DEFINE_THIS_MODULE(lport); | |
25 | ||
26 | /* A logical port. */ | |
27 | struct lport { | |
4470328b RM |
28 | struct hmap_node name_node; /* Index by name. */ |
29 | struct hmap_node key_node; /* Index by (dp_key, port_key). */ | |
30 | struct hmap_node uuid_node; /* Index by row uuid. */ | |
8e9f1c13 | 31 | struct uuid uuid; |
bce7cf45 BP |
32 | const struct sbrec_port_binding *pb; |
33 | }; | |
34 | ||
4470328b RM |
35 | static bool full_lport_rebuild = false; |
36 | ||
37 | void | |
38 | lport_index_reset(void) | |
39 | { | |
40 | full_lport_rebuild = true; | |
41 | } | |
42 | ||
bce7cf45 | 43 | void |
4470328b | 44 | lport_index_init(struct lport_index *lports) |
bce7cf45 BP |
45 | { |
46 | hmap_init(&lports->by_name); | |
47 | hmap_init(&lports->by_key); | |
4470328b RM |
48 | hmap_init(&lports->by_uuid); |
49 | } | |
bce7cf45 | 50 | |
70c7cfef | 51 | bool |
4470328b RM |
52 | lport_index_remove(struct lport_index *lports, const struct uuid *uuid) |
53 | { | |
54 | const struct lport *port_ = lport_lookup_by_uuid(lports, uuid); | |
55 | struct lport *port = CONST_CAST(struct lport *, port_); | |
56 | if (port) { | |
57 | hmap_remove(&lports->by_name, &port->name_node); | |
58 | hmap_remove(&lports->by_key, &port->key_node); | |
59 | hmap_remove(&lports->by_uuid, &port->uuid_node); | |
60 | free(port); | |
70c7cfef | 61 | return true; |
bce7cf45 | 62 | } |
70c7cfef | 63 | return false; |
bce7cf45 BP |
64 | } |
65 | ||
66 | void | |
4470328b | 67 | lport_index_clear(struct lport_index *lports) |
bce7cf45 BP |
68 | { |
69 | /* Destroy all of the "struct lport"s. | |
70 | * | |
4470328b RM |
71 | * We have to remove the node from all indexes. */ |
72 | struct lport *port, *next; | |
73 | HMAP_FOR_EACH_SAFE (port, next, name_node, &lports->by_name) { | |
74 | hmap_remove(&lports->by_name, &port->name_node); | |
75 | hmap_remove(&lports->by_key, &port->key_node); | |
76 | hmap_remove(&lports->by_uuid, &port->uuid_node); | |
bce7cf45 BP |
77 | free(port); |
78 | } | |
70c7cfef | 79 | lflow_reset_processing(); |
4470328b RM |
80 | } |
81 | ||
82 | static void | |
83 | consider_lport_index(struct lport_index *lports, | |
84 | const struct sbrec_port_binding *pb) | |
85 | { | |
86 | if (lport_lookup_by_name(lports, pb->logical_port)) { | |
87 | return; | |
88 | } | |
89 | ||
90 | struct lport *p = xmalloc(sizeof *p); | |
91 | hmap_insert(&lports->by_name, &p->name_node, | |
92 | hash_string(pb->logical_port, 0)); | |
93 | hmap_insert(&lports->by_key, &p->key_node, | |
94 | hash_int(pb->tunnel_key, pb->datapath->tunnel_key)); | |
95 | hmap_insert(&lports->by_uuid, &p->uuid_node, | |
96 | uuid_hash(&pb->header_.uuid)); | |
8e9f1c13 | 97 | memcpy(&p->uuid, &pb->header_.uuid, sizeof p->uuid); |
4470328b | 98 | p->pb = pb; |
70c7cfef | 99 | lflow_reset_processing(); |
4470328b RM |
100 | } |
101 | ||
102 | void | |
103 | lport_index_fill(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl) | |
104 | { | |
105 | const struct sbrec_port_binding *pb; | |
106 | if (full_lport_rebuild) { | |
107 | lport_index_clear(lports); | |
108 | SBREC_PORT_BINDING_FOR_EACH (pb, ovnsb_idl) { | |
109 | consider_lport_index(lports, pb); | |
110 | } | |
111 | full_lport_rebuild = false; | |
112 | } else { | |
113 | SBREC_PORT_BINDING_FOR_EACH_TRACKED (pb, ovnsb_idl) { | |
9a33cd70 | 114 | if (sbrec_port_binding_is_deleted(pb)) { |
70c7cfef RM |
115 | while (lport_index_remove(lports, &pb->header_.uuid)) { |
116 | ; | |
117 | } | |
118 | lflow_reset_processing(); | |
9a33cd70 BP |
119 | } else { |
120 | consider_lport_index(lports, pb); | |
4470328b | 121 | } |
4470328b RM |
122 | } |
123 | } | |
124 | } | |
125 | ||
126 | void | |
127 | lport_index_destroy(struct lport_index *lports) | |
128 | { | |
129 | lport_index_clear(lports); | |
bce7cf45 BP |
130 | |
131 | hmap_destroy(&lports->by_name); | |
132 | hmap_destroy(&lports->by_key); | |
4470328b | 133 | hmap_destroy(&lports->by_uuid); |
bce7cf45 BP |
134 | } |
135 | ||
136 | /* Finds and returns the lport with the given 'name', or NULL if no such lport | |
137 | * exists. */ | |
138 | const struct sbrec_port_binding * | |
139 | lport_lookup_by_name(const struct lport_index *lports, const char *name) | |
140 | { | |
141 | const struct lport *lport; | |
142 | HMAP_FOR_EACH_WITH_HASH (lport, name_node, hash_string(name, 0), | |
143 | &lports->by_name) { | |
144 | if (!strcmp(lport->pb->logical_port, name)) { | |
145 | return lport->pb; | |
146 | } | |
147 | } | |
148 | return NULL; | |
149 | } | |
150 | ||
4470328b RM |
151 | const struct lport * |
152 | lport_lookup_by_uuid(const struct lport_index *lports, | |
153 | const struct uuid *uuid) | |
154 | { | |
155 | const struct lport *lport; | |
156 | HMAP_FOR_EACH_WITH_HASH (lport, uuid_node, uuid_hash(uuid), | |
157 | &lports->by_uuid) { | |
8e9f1c13 | 158 | if (uuid_equals(uuid, &lport->uuid)) { |
4470328b RM |
159 | return lport; |
160 | } | |
161 | } | |
162 | return NULL; | |
163 | } | |
164 | ||
bce7cf45 BP |
165 | const struct sbrec_port_binding * |
166 | lport_lookup_by_key(const struct lport_index *lports, | |
167 | uint32_t dp_key, uint16_t port_key) | |
168 | { | |
169 | const struct lport *lport; | |
170 | HMAP_FOR_EACH_WITH_HASH (lport, key_node, hash_int(port_key, dp_key), | |
171 | &lports->by_key) { | |
172 | if (port_key == lport->pb->tunnel_key | |
173 | && dp_key == lport->pb->datapath->tunnel_key) { | |
174 | return lport->pb; | |
175 | } | |
176 | } | |
177 | return NULL; | |
178 | } | |
179 | \f | |
180 | struct mcgroup { | |
181 | struct hmap_node dp_name_node; /* Index by (logical datapath, name). */ | |
4470328b | 182 | struct hmap_node uuid_node; /* Index by insert uuid. */ |
8e9f1c13 | 183 | struct uuid uuid; |
bce7cf45 BP |
184 | const struct sbrec_multicast_group *mg; |
185 | }; | |
186 | ||
4470328b RM |
187 | static bool full_mc_rebuild = false; |
188 | ||
bce7cf45 | 189 | void |
4470328b | 190 | mcgroup_index_reset(void) |
bce7cf45 | 191 | { |
4470328b RM |
192 | full_mc_rebuild = true; |
193 | } | |
bce7cf45 | 194 | |
4470328b RM |
195 | void |
196 | mcgroup_index_init(struct mcgroup_index *mcgroups) | |
197 | { | |
198 | hmap_init(&mcgroups->by_dp_name); | |
199 | hmap_init(&mcgroups->by_uuid); | |
200 | } | |
bce7cf45 | 201 | |
4470328b RM |
202 | void |
203 | mcgroup_index_remove(struct mcgroup_index *mcgroups, const struct uuid *uuid) | |
204 | { | |
205 | const struct mcgroup *mcgroup_ = mcgroup_lookup_by_uuid(mcgroups, uuid); | |
206 | struct mcgroup *mcgroup = CONST_CAST(struct mcgroup *, mcgroup_); | |
207 | if (mcgroup) { | |
208 | hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node); | |
209 | hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node); | |
210 | free(mcgroup); | |
bce7cf45 | 211 | } |
70c7cfef | 212 | lflow_reset_processing(); |
bce7cf45 BP |
213 | } |
214 | ||
215 | void | |
4470328b | 216 | mcgroup_index_clear(struct mcgroup_index *mcgroups) |
bce7cf45 BP |
217 | { |
218 | struct mcgroup *mcgroup, *next; | |
219 | HMAP_FOR_EACH_SAFE (mcgroup, next, dp_name_node, &mcgroups->by_dp_name) { | |
220 | hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node); | |
4470328b | 221 | hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node); |
bce7cf45 BP |
222 | free(mcgroup); |
223 | } | |
4470328b RM |
224 | } |
225 | ||
226 | static void | |
227 | consider_mcgroup_index(struct mcgroup_index *mcgroups, | |
228 | const struct sbrec_multicast_group *mg) | |
229 | { | |
230 | const struct uuid *dp_uuid = &mg->datapath->header_.uuid; | |
231 | if (mcgroup_lookup_by_dp_name(mcgroups, mg->datapath, mg->name)) { | |
232 | return; | |
233 | } | |
234 | ||
235 | struct mcgroup *m = xmalloc(sizeof *m); | |
236 | hmap_insert(&mcgroups->by_dp_name, &m->dp_name_node, | |
237 | hash_string(mg->name, uuid_hash(dp_uuid))); | |
238 | hmap_insert(&mcgroups->by_uuid, &m->uuid_node, | |
239 | uuid_hash(&mg->header_.uuid)); | |
8e9f1c13 | 240 | memcpy(&m->uuid, &mg->header_.uuid, sizeof m->uuid); |
4470328b | 241 | m->mg = mg; |
70c7cfef | 242 | lflow_reset_processing(); |
4470328b RM |
243 | } |
244 | ||
245 | void | |
246 | mcgroup_index_fill(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl) | |
247 | { | |
248 | const struct sbrec_multicast_group *mg; | |
249 | if (full_mc_rebuild) { | |
250 | mcgroup_index_clear(mcgroups); | |
251 | SBREC_MULTICAST_GROUP_FOR_EACH (mg, ovnsb_idl) { | |
252 | consider_mcgroup_index(mcgroups, mg); | |
253 | } | |
254 | full_mc_rebuild = false; | |
255 | } else { | |
256 | SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mg, ovnsb_idl) { | |
9a33cd70 | 257 | if (sbrec_multicast_group_is_deleted(mg)) { |
4470328b | 258 | mcgroup_index_remove(mcgroups, &mg->header_.uuid); |
70c7cfef | 259 | lflow_reset_processing(); |
9a33cd70 BP |
260 | } else { |
261 | consider_mcgroup_index(mcgroups, mg); | |
4470328b | 262 | } |
4470328b RM |
263 | } |
264 | } | |
265 | } | |
266 | ||
267 | void | |
268 | mcgroup_index_destroy(struct mcgroup_index *mcgroups) | |
269 | { | |
270 | mcgroup_index_clear(mcgroups); | |
bce7cf45 BP |
271 | |
272 | hmap_destroy(&mcgroups->by_dp_name); | |
273 | } | |
274 | ||
4470328b RM |
275 | const struct mcgroup * |
276 | mcgroup_lookup_by_uuid(const struct mcgroup_index *mcgroups, | |
277 | const struct uuid *uuid) | |
278 | { | |
279 | const struct mcgroup *mcgroup; | |
280 | HMAP_FOR_EACH_WITH_HASH (mcgroup, uuid_node, uuid_hash(uuid), | |
281 | &mcgroups->by_uuid) { | |
8e9f1c13 | 282 | if (uuid_equals(&mcgroup->uuid, uuid)) { |
4470328b RM |
283 | return mcgroup; |
284 | } | |
285 | } | |
286 | return NULL; | |
287 | } | |
288 | ||
bce7cf45 BP |
289 | const struct sbrec_multicast_group * |
290 | mcgroup_lookup_by_dp_name(const struct mcgroup_index *mcgroups, | |
291 | const struct sbrec_datapath_binding *dp, | |
292 | const char *name) | |
293 | { | |
294 | const struct uuid *dp_uuid = &dp->header_.uuid; | |
295 | const struct mcgroup *mcgroup; | |
296 | HMAP_FOR_EACH_WITH_HASH (mcgroup, dp_name_node, | |
297 | hash_string(name, uuid_hash(dp_uuid)), | |
298 | &mcgroups->by_dp_name) { | |
299 | if (uuid_equals(&mcgroup->mg->datapath->header_.uuid, dp_uuid) | |
300 | && !strcmp(mcgroup->mg->name, name)) { | |
301 | return mcgroup->mg; | |
302 | } | |
303 | } | |
304 | return NULL; | |
305 | } |