1 /* Copyright (c) 2015, 2016 Nicira, Inc.
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include "openvswitch/vlog.h"
22 #include "ovn/lib/ovn-sb-idl.h"
24 VLOG_DEFINE_THIS_MODULE(lport);
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. */
32 const struct sbrec_port_binding *pb;
35 static bool full_lport_rebuild = false;
38 lport_index_reset(void)
40 full_lport_rebuild = true;
44 lport_index_init(struct lport_index *lports)
46 hmap_init(&lports->by_name);
47 hmap_init(&lports->by_key);
48 hmap_init(&lports->by_uuid);
52 lport_index_remove(struct lport_index *lports, const struct uuid *uuid)
54 const struct lport *port_ = lport_lookup_by_uuid(lports, uuid);
55 struct lport *port = CONST_CAST(struct lport *, 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);
67 lport_index_clear(struct lport_index *lports)
69 /* Destroy all of the "struct lport"s.
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);
79 lflow_reset_processing();
83 consider_lport_index(struct lport_index *lports,
84 const struct sbrec_port_binding *pb)
86 if (lport_lookup_by_name(lports, pb->logical_port)) {
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));
97 memcpy(&p->uuid, &pb->header_.uuid, sizeof p->uuid);
99 lflow_reset_processing();
103 lport_index_fill(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl)
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);
111 full_lport_rebuild = false;
113 SBREC_PORT_BINDING_FOR_EACH_TRACKED (pb, ovnsb_idl) {
114 if (sbrec_port_binding_is_deleted(pb)) {
115 while (lport_index_remove(lports, &pb->header_.uuid)) {
118 lflow_reset_processing();
120 consider_lport_index(lports, pb);
127 lport_index_destroy(struct lport_index *lports)
129 lport_index_clear(lports);
131 hmap_destroy(&lports->by_name);
132 hmap_destroy(&lports->by_key);
133 hmap_destroy(&lports->by_uuid);
136 /* Finds and returns the lport with the given 'name', or NULL if no such lport
138 const struct sbrec_port_binding *
139 lport_lookup_by_name(const struct lport_index *lports, const char *name)
141 const struct lport *lport;
142 HMAP_FOR_EACH_WITH_HASH (lport, name_node, hash_string(name, 0),
144 if (!strcmp(lport->pb->logical_port, name)) {
152 lport_lookup_by_uuid(const struct lport_index *lports,
153 const struct uuid *uuid)
155 const struct lport *lport;
156 HMAP_FOR_EACH_WITH_HASH (lport, uuid_node, uuid_hash(uuid),
158 if (uuid_equals(uuid, &lport->uuid)) {
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)
169 const struct lport *lport;
170 HMAP_FOR_EACH_WITH_HASH (lport, key_node, hash_int(port_key, dp_key),
172 if (port_key == lport->pb->tunnel_key
173 && dp_key == lport->pb->datapath->tunnel_key) {
181 struct hmap_node dp_name_node; /* Index by (logical datapath, name). */
182 struct hmap_node uuid_node; /* Index by insert uuid. */
184 const struct sbrec_multicast_group *mg;
187 static bool full_mc_rebuild = false;
190 mcgroup_index_reset(void)
192 full_mc_rebuild = true;
196 mcgroup_index_init(struct mcgroup_index *mcgroups)
198 hmap_init(&mcgroups->by_dp_name);
199 hmap_init(&mcgroups->by_uuid);
203 mcgroup_index_remove(struct mcgroup_index *mcgroups, const struct uuid *uuid)
205 const struct mcgroup *mcgroup_ = mcgroup_lookup_by_uuid(mcgroups, uuid);
206 struct mcgroup *mcgroup = CONST_CAST(struct mcgroup *, mcgroup_);
208 hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node);
209 hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node);
212 lflow_reset_processing();
216 mcgroup_index_clear(struct mcgroup_index *mcgroups)
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);
221 hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node);
227 consider_mcgroup_index(struct mcgroup_index *mcgroups,
228 const struct sbrec_multicast_group *mg)
230 const struct uuid *dp_uuid = &mg->datapath->header_.uuid;
231 if (mcgroup_lookup_by_dp_name(mcgroups, mg->datapath, mg->name)) {
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));
240 memcpy(&m->uuid, &mg->header_.uuid, sizeof m->uuid);
242 lflow_reset_processing();
246 mcgroup_index_fill(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl)
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);
254 full_mc_rebuild = false;
256 SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mg, ovnsb_idl) {
257 if (sbrec_multicast_group_is_deleted(mg)) {
258 mcgroup_index_remove(mcgroups, &mg->header_.uuid);
259 lflow_reset_processing();
261 consider_mcgroup_index(mcgroups, mg);
268 mcgroup_index_destroy(struct mcgroup_index *mcgroups)
270 mcgroup_index_clear(mcgroups);
272 hmap_destroy(&mcgroups->by_dp_name);
275 const struct mcgroup *
276 mcgroup_lookup_by_uuid(const struct mcgroup_index *mcgroups,
277 const struct uuid *uuid)
279 const struct mcgroup *mcgroup;
280 HMAP_FOR_EACH_WITH_HASH (mcgroup, uuid_node, uuid_hash(uuid),
281 &mcgroups->by_uuid) {
282 if (uuid_equals(&mcgroup->uuid, uuid)) {
289 const struct sbrec_multicast_group *
290 mcgroup_lookup_by_dp_name(const struct mcgroup_index *mcgroups,
291 const struct sbrec_datapath_binding *dp,
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)) {