1717
1818#include "lport.h"
1919#include "hash.h"
20+ #include "lflow.h"
2021#include "openvswitch/vlog.h"
2122#include "ovn/lib/ovn-sb-idl.h"
2223
2324VLOG_DEFINE_THIS_MODULE (lport );
2425
2526/* A logical port. */
2627struct lport {
27- struct hmap_node name_node ; /* Index by name. */
28- struct hmap_node key_node ; /* Index by (dp_key, port_key). */
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. */
31+ const struct uuid * uuid ;
2932 const struct sbrec_port_binding * pb ;
3033};
3134
35+ static bool full_lport_rebuild = false;
36+
37+ void
38+ lport_index_reset (void )
39+ {
40+ full_lport_rebuild = true;
41+ }
42+
3243void
33- lport_index_init (struct lport_index * lports , struct ovsdb_idl * ovnsb_idl )
44+ lport_index_init (struct lport_index * lports )
3445{
3546 hmap_init (& lports -> by_name );
3647 hmap_init (& lports -> by_key );
48+ hmap_init (& lports -> by_uuid );
49+ }
3750
38- const struct sbrec_port_binding * pb ;
39- SBREC_PORT_BINDING_FOR_EACH (pb , ovnsb_idl ) {
40- if (lport_lookup_by_name (lports , pb -> logical_port )) {
41- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT (1 , 1 );
42- VLOG_WARN_RL (& rl , "duplicate logical port name '%s'" ,
43- pb -> logical_port );
44- continue ;
45- }
46-
47- struct lport * p = xmalloc (sizeof * p );
48- hmap_insert (& lports -> by_name , & p -> name_node ,
49- hash_string (pb -> logical_port , 0 ));
50- hmap_insert (& lports -> by_key , & p -> key_node ,
51- hash_int (pb -> tunnel_key , pb -> datapath -> tunnel_key ));
52- p -> pb = pb ;
51+ void
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 );
5361 }
5462}
5563
5664void
57- lport_index_destroy (struct lport_index * lports )
65+ lport_index_clear (struct lport_index * lports )
5866{
5967 /* Destroy all of the "struct lport"s.
6068 *
61- * We don't have to remove the node from both indexes. */
62- struct lport * port ;
63- HMAP_FOR_EACH_POP (port , name_node , & lports -> by_name ) {
69+ * We have to remove the node from all indexes. */
70+ struct lport * port , * next ;
71+ HMAP_FOR_EACH_SAFE (port , next , name_node , & lports -> by_name ) {
72+ hmap_remove (& lports -> by_name , & port -> name_node );
73+ hmap_remove (& lports -> by_key , & port -> key_node );
74+ hmap_remove (& lports -> by_uuid , & port -> uuid_node );
6475 free (port );
6576 }
77+ }
78+
79+ static void
80+ consider_lport_index (struct lport_index * lports ,
81+ const struct sbrec_port_binding * pb )
82+ {
83+ if (lport_lookup_by_name (lports , pb -> logical_port )) {
84+ return ;
85+ }
86+
87+ struct lport * p = xmalloc (sizeof * p );
88+ hmap_insert (& lports -> by_name , & p -> name_node ,
89+ hash_string (pb -> logical_port , 0 ));
90+ hmap_insert (& lports -> by_key , & p -> key_node ,
91+ hash_int (pb -> tunnel_key , pb -> datapath -> tunnel_key ));
92+ hmap_insert (& lports -> by_uuid , & p -> uuid_node ,
93+ uuid_hash (& pb -> header_ .uuid ));
94+ p -> uuid = & pb -> header_ .uuid ;
95+ p -> pb = pb ;
96+ }
97+
98+ void
99+ lport_index_fill (struct lport_index * lports , struct ovsdb_idl * ovnsb_idl )
100+ {
101+ const struct sbrec_port_binding * pb ;
102+ if (full_lport_rebuild ) {
103+ lport_index_clear (lports );
104+ SBREC_PORT_BINDING_FOR_EACH (pb , ovnsb_idl ) {
105+ consider_lport_index (lports , pb );
106+ }
107+ full_lport_rebuild = false;
108+ } else {
109+ SBREC_PORT_BINDING_FOR_EACH_TRACKED (pb , ovnsb_idl ) {
110+ bool is_delete = sbrec_port_binding_row_get_seqno (pb ,
111+ OVSDB_IDL_CHANGE_DELETE ) > 0 ;
112+
113+ if (is_delete ) {
114+ lport_index_remove (lports , & pb -> header_ .uuid );
115+ continue ;
116+ }
117+ consider_lport_index (lports , pb );
118+ }
119+ }
120+ }
121+
122+ void
123+ lport_index_destroy (struct lport_index * lports )
124+ {
125+ lport_index_clear (lports );
66126
67127 hmap_destroy (& lports -> by_name );
68128 hmap_destroy (& lports -> by_key );
129+ hmap_destroy (& lports -> by_uuid );
69130}
70131
71132/* 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)
83144 return NULL ;
84145}
85146
147+ const struct lport *
148+ lport_lookup_by_uuid (const struct lport_index * lports ,
149+ const struct uuid * uuid )
150+ {
151+ const struct lport * lport ;
152+ HMAP_FOR_EACH_WITH_HASH (lport , uuid_node , uuid_hash (uuid ),
153+ & lports -> by_uuid ) {
154+ if (uuid_equals (uuid , lport -> uuid )) {
155+ return lport ;
156+ }
157+ }
158+ return NULL ;
159+ }
160+
86161const struct sbrec_port_binding *
87162lport_lookup_by_key (const struct lport_index * lports ,
88163 uint32_t dp_key , uint16_t port_key )
@@ -100,43 +175,113 @@ lport_lookup_by_key(const struct lport_index *lports,
100175
101176struct mcgroup {
102177 struct hmap_node dp_name_node ; /* Index by (logical datapath, name). */
178+ struct hmap_node uuid_node ; /* Index by insert uuid. */
179+ const struct uuid * uuid ;
103180 const struct sbrec_multicast_group * mg ;
104181};
105182
183+ static bool full_mc_rebuild = false;
184+
106185void
107- mcgroup_index_init ( struct mcgroup_index * mcgroups , struct ovsdb_idl * ovnsb_idl )
186+ mcgroup_index_reset ( void )
108187{
109- hmap_init (& mcgroups -> by_dp_name );
188+ full_mc_rebuild = true;
189+ }
110190
111- const struct sbrec_multicast_group * mg ;
112- SBREC_MULTICAST_GROUP_FOR_EACH (mg , ovnsb_idl ) {
113- const struct uuid * dp_uuid = & mg -> datapath -> header_ .uuid ;
114- if (mcgroup_lookup_by_dp_name (mcgroups , mg -> datapath , mg -> name )) {
115- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT (1 , 1 );
116- VLOG_WARN_RL (& rl , "datapath " UUID_FMT " contains duplicate "
117- "multicast group '%s'" , UUID_ARGS (dp_uuid ), mg -> name );
118- continue ;
119- }
191+ void
192+ mcgroup_index_init (struct mcgroup_index * mcgroups )
193+ {
194+ hmap_init (& mcgroups -> by_dp_name );
195+ hmap_init (& mcgroups -> by_uuid );
196+ }
120197
121- struct mcgroup * m = xmalloc (sizeof * m );
122- hmap_insert (& mcgroups -> by_dp_name , & m -> dp_name_node ,
123- hash_string (mg -> name , uuid_hash (dp_uuid )));
124- m -> mg = mg ;
198+ void
199+ mcgroup_index_remove (struct mcgroup_index * mcgroups , const struct uuid * uuid )
200+ {
201+ const struct mcgroup * mcgroup_ = mcgroup_lookup_by_uuid (mcgroups , uuid );
202+ struct mcgroup * mcgroup = CONST_CAST (struct mcgroup * , mcgroup_ );
203+ if (mcgroup ) {
204+ hmap_remove (& mcgroups -> by_dp_name , & mcgroup -> dp_name_node );
205+ hmap_remove (& mcgroups -> by_uuid , & mcgroup -> uuid_node );
206+ free (mcgroup );
125207 }
126208}
127209
128210void
129- mcgroup_index_destroy (struct mcgroup_index * mcgroups )
211+ mcgroup_index_clear (struct mcgroup_index * mcgroups )
130212{
131213 struct mcgroup * mcgroup , * next ;
132214 HMAP_FOR_EACH_SAFE (mcgroup , next , dp_name_node , & mcgroups -> by_dp_name ) {
133215 hmap_remove (& mcgroups -> by_dp_name , & mcgroup -> dp_name_node );
216+ hmap_remove (& mcgroups -> by_uuid , & mcgroup -> uuid_node );
134217 free (mcgroup );
135218 }
219+ }
220+
221+ static void
222+ consider_mcgroup_index (struct mcgroup_index * mcgroups ,
223+ const struct sbrec_multicast_group * mg )
224+ {
225+ const struct uuid * dp_uuid = & mg -> datapath -> header_ .uuid ;
226+ if (mcgroup_lookup_by_dp_name (mcgroups , mg -> datapath , mg -> name )) {
227+ return ;
228+ }
229+
230+ struct mcgroup * m = xmalloc (sizeof * m );
231+ hmap_insert (& mcgroups -> by_dp_name , & m -> dp_name_node ,
232+ hash_string (mg -> name , uuid_hash (dp_uuid )));
233+ hmap_insert (& mcgroups -> by_uuid , & m -> uuid_node ,
234+ uuid_hash (& mg -> header_ .uuid ));
235+ m -> uuid = & mg -> header_ .uuid ;
236+ m -> mg = mg ;
237+ }
238+
239+ void
240+ mcgroup_index_fill (struct mcgroup_index * mcgroups , struct ovsdb_idl * ovnsb_idl )
241+ {
242+ const struct sbrec_multicast_group * mg ;
243+ if (full_mc_rebuild ) {
244+ mcgroup_index_clear (mcgroups );
245+ SBREC_MULTICAST_GROUP_FOR_EACH (mg , ovnsb_idl ) {
246+ consider_mcgroup_index (mcgroups , mg );
247+ }
248+ full_mc_rebuild = false;
249+ } else {
250+ SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mg , ovnsb_idl ) {
251+ bool is_delete = sbrec_multicast_group_row_get_seqno (mg ,
252+ OVSDB_IDL_CHANGE_DELETE ) > 0 ;
253+
254+ if (is_delete ) {
255+ mcgroup_index_remove (mcgroups , & mg -> header_ .uuid );
256+ continue ;
257+ }
258+ consider_mcgroup_index (mcgroups , mg );
259+ }
260+ }
261+ }
262+
263+ void
264+ mcgroup_index_destroy (struct mcgroup_index * mcgroups )
265+ {
266+ mcgroup_index_clear (mcgroups );
136267
137268 hmap_destroy (& mcgroups -> by_dp_name );
138269}
139270
271+ const struct mcgroup *
272+ mcgroup_lookup_by_uuid (const struct mcgroup_index * mcgroups ,
273+ const struct uuid * uuid )
274+ {
275+ const struct mcgroup * mcgroup ;
276+ HMAP_FOR_EACH_WITH_HASH (mcgroup , uuid_node , uuid_hash (uuid ),
277+ & mcgroups -> by_uuid ) {
278+ if (uuid_equals (mcgroup -> uuid , uuid )) {
279+ return mcgroup ;
280+ }
281+ }
282+ return NULL ;
283+ }
284+
140285const struct sbrec_multicast_group *
141286mcgroup_lookup_by_dp_name (const struct mcgroup_index * mcgroups ,
142287 const struct sbrec_datapath_binding * dp ,
0 commit comments