X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ovn%2Fcontroller%2Flport.c;fp=ovn%2Fcontroller%2Flport.c;h=2ce638784847f26e3ac222336bf5c0e4c72237ac;hb=4470328bc4e0081479351e39a1964a78fe19be1b;hp=a7ae320bd3aea64ba4875c6db91cb1f61836d177;hpb=40ebbf78eed594c8c9c49f26712f58118c0c9612;p=cascardo%2Fovs.git diff --git a/ovn/controller/lport.c b/ovn/controller/lport.c index a7ae320bd..2ce638784 100644 --- a/ovn/controller/lport.c +++ b/ovn/controller/lport.c @@ -17,6 +17,7 @@ #include "lport.h" #include "hash.h" +#include "lflow.h" #include "openvswitch/vlog.h" #include "ovn/lib/ovn-sb-idl.h" @@ -24,48 +25,108 @@ VLOG_DEFINE_THIS_MODULE(lport); /* A logical port. */ struct lport { - struct hmap_node name_node; /* Index by name. */ - struct hmap_node key_node; /* Index by (dp_key, port_key). */ + struct hmap_node name_node; /* Index by name. */ + struct hmap_node key_node; /* Index by (dp_key, port_key). */ + struct hmap_node uuid_node; /* Index by row uuid. */ + const struct uuid *uuid; const struct sbrec_port_binding *pb; }; +static bool full_lport_rebuild = false; + +void +lport_index_reset(void) +{ + full_lport_rebuild = true; +} + void -lport_index_init(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl) +lport_index_init(struct lport_index *lports) { hmap_init(&lports->by_name); hmap_init(&lports->by_key); + hmap_init(&lports->by_uuid); +} - const struct sbrec_port_binding *pb; - SBREC_PORT_BINDING_FOR_EACH (pb, ovnsb_idl) { - if (lport_lookup_by_name(lports, pb->logical_port)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "duplicate logical port name '%s'", - pb->logical_port); - continue; - } - - struct lport *p = xmalloc(sizeof *p); - hmap_insert(&lports->by_name, &p->name_node, - hash_string(pb->logical_port, 0)); - hmap_insert(&lports->by_key, &p->key_node, - hash_int(pb->tunnel_key, pb->datapath->tunnel_key)); - p->pb = pb; +void +lport_index_remove(struct lport_index *lports, const struct uuid *uuid) +{ + const struct lport *port_ = lport_lookup_by_uuid(lports, uuid); + struct lport *port = CONST_CAST(struct lport *, port_); + if (port) { + hmap_remove(&lports->by_name, &port->name_node); + hmap_remove(&lports->by_key, &port->key_node); + hmap_remove(&lports->by_uuid, &port->uuid_node); + free(port); } } void -lport_index_destroy(struct lport_index *lports) +lport_index_clear(struct lport_index *lports) { /* Destroy all of the "struct lport"s. * - * We don't have to remove the node from both indexes. */ - struct lport *port; - HMAP_FOR_EACH_POP (port, name_node, &lports->by_name) { + * We have to remove the node from all indexes. */ + struct lport *port, *next; + HMAP_FOR_EACH_SAFE (port, next, name_node, &lports->by_name) { + hmap_remove(&lports->by_name, &port->name_node); + hmap_remove(&lports->by_key, &port->key_node); + hmap_remove(&lports->by_uuid, &port->uuid_node); free(port); } +} + +static void +consider_lport_index(struct lport_index *lports, + const struct sbrec_port_binding *pb) +{ + if (lport_lookup_by_name(lports, pb->logical_port)) { + return; + } + + struct lport *p = xmalloc(sizeof *p); + hmap_insert(&lports->by_name, &p->name_node, + hash_string(pb->logical_port, 0)); + hmap_insert(&lports->by_key, &p->key_node, + hash_int(pb->tunnel_key, pb->datapath->tunnel_key)); + hmap_insert(&lports->by_uuid, &p->uuid_node, + uuid_hash(&pb->header_.uuid)); + p->uuid = &pb->header_.uuid; + p->pb = pb; +} + +void +lport_index_fill(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl) +{ + const struct sbrec_port_binding *pb; + if (full_lport_rebuild) { + lport_index_clear(lports); + SBREC_PORT_BINDING_FOR_EACH (pb, ovnsb_idl) { + consider_lport_index(lports, pb); + } + full_lport_rebuild = false; + } else { + SBREC_PORT_BINDING_FOR_EACH_TRACKED (pb, ovnsb_idl) { + bool is_delete = sbrec_port_binding_row_get_seqno(pb, + OVSDB_IDL_CHANGE_DELETE) > 0; + + if (is_delete) { + lport_index_remove(lports, &pb->header_.uuid); + continue; + } + consider_lport_index(lports, pb); + } + } +} + +void +lport_index_destroy(struct lport_index *lports) +{ + lport_index_clear(lports); hmap_destroy(&lports->by_name); hmap_destroy(&lports->by_key); + hmap_destroy(&lports->by_uuid); } /* Finds and returns the lport with the given 'name', or NULL if no such lport @@ -83,6 +144,20 @@ lport_lookup_by_name(const struct lport_index *lports, const char *name) return NULL; } +const struct lport * +lport_lookup_by_uuid(const struct lport_index *lports, + const struct uuid *uuid) +{ + const struct lport *lport; + HMAP_FOR_EACH_WITH_HASH (lport, uuid_node, uuid_hash(uuid), + &lports->by_uuid) { + if (uuid_equals(uuid, lport->uuid)) { + return lport; + } + } + return NULL; +} + const struct sbrec_port_binding * lport_lookup_by_key(const struct lport_index *lports, uint32_t dp_key, uint16_t port_key) @@ -100,43 +175,113 @@ lport_lookup_by_key(const struct lport_index *lports, struct mcgroup { struct hmap_node dp_name_node; /* Index by (logical datapath, name). */ + struct hmap_node uuid_node; /* Index by insert uuid. */ + const struct uuid *uuid; const struct sbrec_multicast_group *mg; }; +static bool full_mc_rebuild = false; + void -mcgroup_index_init(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl) +mcgroup_index_reset(void) { - hmap_init(&mcgroups->by_dp_name); + full_mc_rebuild = true; +} - const struct sbrec_multicast_group *mg; - SBREC_MULTICAST_GROUP_FOR_EACH (mg, ovnsb_idl) { - const struct uuid *dp_uuid = &mg->datapath->header_.uuid; - if (mcgroup_lookup_by_dp_name(mcgroups, mg->datapath, mg->name)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "datapath "UUID_FMT" contains duplicate " - "multicast group '%s'", UUID_ARGS(dp_uuid), mg->name); - continue; - } +void +mcgroup_index_init(struct mcgroup_index *mcgroups) +{ + hmap_init(&mcgroups->by_dp_name); + hmap_init(&mcgroups->by_uuid); +} - struct mcgroup *m = xmalloc(sizeof *m); - hmap_insert(&mcgroups->by_dp_name, &m->dp_name_node, - hash_string(mg->name, uuid_hash(dp_uuid))); - m->mg = mg; +void +mcgroup_index_remove(struct mcgroup_index *mcgroups, const struct uuid *uuid) +{ + const struct mcgroup *mcgroup_ = mcgroup_lookup_by_uuid(mcgroups, uuid); + struct mcgroup *mcgroup = CONST_CAST(struct mcgroup *, mcgroup_); + if (mcgroup) { + hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node); + hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node); + free(mcgroup); } } void -mcgroup_index_destroy(struct mcgroup_index *mcgroups) +mcgroup_index_clear(struct mcgroup_index *mcgroups) { struct mcgroup *mcgroup, *next; HMAP_FOR_EACH_SAFE (mcgroup, next, dp_name_node, &mcgroups->by_dp_name) { hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node); + hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node); free(mcgroup); } +} + +static void +consider_mcgroup_index(struct mcgroup_index *mcgroups, + const struct sbrec_multicast_group *mg) +{ + const struct uuid *dp_uuid = &mg->datapath->header_.uuid; + if (mcgroup_lookup_by_dp_name(mcgroups, mg->datapath, mg->name)) { + return; + } + + struct mcgroup *m = xmalloc(sizeof *m); + hmap_insert(&mcgroups->by_dp_name, &m->dp_name_node, + hash_string(mg->name, uuid_hash(dp_uuid))); + hmap_insert(&mcgroups->by_uuid, &m->uuid_node, + uuid_hash(&mg->header_.uuid)); + m->uuid = &mg->header_.uuid; + m->mg = mg; +} + +void +mcgroup_index_fill(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl) +{ + const struct sbrec_multicast_group *mg; + if (full_mc_rebuild) { + mcgroup_index_clear(mcgroups); + SBREC_MULTICAST_GROUP_FOR_EACH (mg, ovnsb_idl) { + consider_mcgroup_index(mcgroups, mg); + } + full_mc_rebuild = false; + } else { + SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mg, ovnsb_idl) { + bool is_delete = sbrec_multicast_group_row_get_seqno(mg, + OVSDB_IDL_CHANGE_DELETE) > 0; + + if (is_delete) { + mcgroup_index_remove(mcgroups, &mg->header_.uuid); + continue; + } + consider_mcgroup_index(mcgroups, mg); + } + } +} + +void +mcgroup_index_destroy(struct mcgroup_index *mcgroups) +{ + mcgroup_index_clear(mcgroups); hmap_destroy(&mcgroups->by_dp_name); } +const struct mcgroup * +mcgroup_lookup_by_uuid(const struct mcgroup_index *mcgroups, + const struct uuid *uuid) +{ + const struct mcgroup *mcgroup; + HMAP_FOR_EACH_WITH_HASH (mcgroup, uuid_node, uuid_hash(uuid), + &mcgroups->by_uuid) { + if (uuid_equals(mcgroup->uuid, uuid)) { + return mcgroup; + } + } + return NULL; +} + const struct sbrec_multicast_group * mcgroup_lookup_by_dp_name(const struct mcgroup_index *mcgroups, const struct sbrec_datapath_binding *dp,