Skip to content

Commit 670f98c

Browse files
committed
northd: Process ACL changes incrementally.
Any change to ACL would result in full lflow recompute. Instead of that reprocess only the relevant logical switch. In order to get track the relation between ACL and LS from the ACL side we need to store all related ACL uuids in the ls_stateful_record. There isn't any significant memory impact that would happen as result of tracking the uuids for each switch. Tested on database with 76k ACLs and 25k PGs. Reported-at: https://issues.redhat.com/browse/FDP-755 Acked-by: Mark Michelson <mmichels@redhat.com> Acked-by: Dumitru Ceara <dceara@redhat.com> Signed-off-by: Ales Musil <amusil@redhat.com>
1 parent 18edf9c commit 670f98c

4 files changed

Lines changed: 78 additions & 125 deletions

File tree

northd/en-ls-stateful.c

Lines changed: 59 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,13 @@ static void ls_stateful_record_destroy(struct ls_stateful_record *);
6565
static void ls_stateful_record_init(
6666
struct ls_stateful_record *,
6767
const struct ovn_datapath *,
68-
const struct ls_port_group *,
69-
const struct ls_port_group_table *);
70-
static void ls_stateful_record_reinit(
71-
struct ls_stateful_record *,
72-
const struct ovn_datapath *,
73-
const struct ls_port_group *,
7468
const struct ls_port_group_table *);
7569
static bool ls_has_lb_vip(const struct ovn_datapath *);
76-
static void ls_stateful_record_set_acl_flags(
70+
static void ls_stateful_record_set_acls(
7771
struct ls_stateful_record *, const struct ovn_datapath *,
78-
const struct ls_port_group *, const struct ls_port_group_table *);
79-
static bool ls_stateful_record_set_acl_flags_(struct ls_stateful_record *,
80-
struct nbrec_acl **,
81-
size_t n_acls);
72+
const struct ls_port_group_table *);
73+
static void ls_stateful_record_set_acls_(struct ls_stateful_record *,
74+
struct nbrec_acl **, size_t n_acls);
8275
static struct ls_stateful_input ls_stateful_get_input_data(
8376
struct engine_node *);
8477

@@ -148,30 +141,31 @@ ls_stateful_northd_handler(struct engine_node *node, void *data_)
148141
struct ed_type_ls_stateful *data = data_;
149142
struct hmapx_node *hmapx_node;
150143

151-
struct hmapx changed_stateful_od = HMAPX_INITIALIZER(&changed_stateful_od);
152144
HMAPX_FOR_EACH (hmapx_node, &nd_changes->ls_with_changed_lbs) {
153-
hmapx_add(&changed_stateful_od, hmapx_node->data);
154-
}
145+
const struct ovn_datapath *od = hmapx_node->data;
155146

156-
HMAPX_FOR_EACH (hmapx_node, &nd_changes->ls_with_changed_acls) {
157-
hmapx_add(&changed_stateful_od, hmapx_node->data);
147+
struct ls_stateful_record *ls_stateful_rec =
148+
ls_stateful_table_find_(&data->table, od->nbs);
149+
ovs_assert(ls_stateful_rec);
150+
ls_stateful_rec->has_lb_vip = ls_has_lb_vip(od);
151+
152+
/* Add the ls_stateful_rec to the tracking data. */
153+
hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
158154
}
159155

160-
HMAPX_FOR_EACH (hmapx_node, &changed_stateful_od) {
156+
HMAPX_FOR_EACH (hmapx_node, &nd_changes->ls_with_changed_acls) {
161157
const struct ovn_datapath *od = hmapx_node->data;
162158

163-
struct ls_stateful_record *ls_stateful_rec = ls_stateful_table_find_(
164-
&data->table, od->nbs);
159+
struct ls_stateful_record *ls_stateful_rec =
160+
ls_stateful_table_find_(&data->table, od->nbs);
165161
ovs_assert(ls_stateful_rec);
166-
ls_stateful_record_reinit(ls_stateful_rec, od, NULL,
167-
input_data.ls_port_groups);
162+
ls_stateful_record_set_acls(ls_stateful_rec, od,
163+
input_data.ls_port_groups);
168164

169165
/* Add the ls_stateful_rec to the tracking data. */
170166
hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
171167
}
172168

173-
hmapx_destroy(&changed_stateful_od);
174-
175169
if (ls_stateful_has_tracked_data(&data->trk_data)) {
176170
return EN_HANDLED_UPDATED;
177171
}
@@ -189,43 +183,34 @@ ls_stateful_port_group_handler(struct engine_node *node, void *data_)
189183
return EN_UNHANDLED;
190184
}
191185

192-
/* port_group engine node doesn't provide the tracking data yet.
193-
* Loop through all the ls port groups and update the ls_stateful_rec.
194-
* This is still better than returning false. */
195-
struct ls_stateful_input input_data = ls_stateful_get_input_data(node);
196186
struct ed_type_ls_stateful *data = data_;
197-
const struct ls_port_group *ls_pg;
187+
if (ls_stateful_has_tracked_data(&data->trk_data)) {
188+
return EN_HANDLED_UPDATED;
189+
}
190+
return EN_HANDLED_UNCHANGED;
191+
}
198192

199-
LS_PORT_GROUP_TABLE_FOR_EACH (ls_pg, input_data.ls_port_groups) {
200-
struct ls_stateful_record *ls_stateful_rec =
201-
ls_stateful_table_find_(&data->table, ls_pg->nbs);
202-
ovs_assert(ls_stateful_rec);
203-
const struct ovn_datapath *od =
204-
ovn_datapaths_find_by_index(input_data.ls_datapaths,
205-
ls_stateful_rec->ls_index);
206-
bool had_stateful_acl = ls_stateful_rec->has_stateful_acl;
207-
struct acl_tier old_max = ls_stateful_rec->max_acl_tier;
208-
bool had_acls = ls_stateful_rec->has_acls;
209-
bool modified = false;
210-
211-
ls_stateful_record_reinit(ls_stateful_rec, od, ls_pg,
212-
input_data.ls_port_groups);
213-
214-
struct acl_tier new_max = ls_stateful_rec->max_acl_tier;
215-
216-
/* Using memcmp for struct acl_tier is fine since there is no padding
217-
* in the struct. However, if the structure is changed, the memcmp
218-
* may need to be updated to compare individual struct fields.
219-
*/
220-
if ((had_stateful_acl != ls_stateful_rec->has_stateful_acl)
221-
|| (had_acls != ls_stateful_rec->has_acls)
222-
|| memcmp(&old_max, &new_max, sizeof(old_max))) {
223-
modified = true;
193+
enum engine_input_handler_result
194+
ls_stateful_acl_handler(struct engine_node *node, void *data_)
195+
{
196+
struct ed_type_ls_stateful *data = data_;
197+
const struct nbrec_acl_table *nbrec_acl_table =
198+
EN_OVSDB_GET(engine_get_input("NB_acl", node));
199+
200+
const struct nbrec_acl *acl;
201+
NBREC_ACL_TABLE_FOR_EACH_TRACKED (acl, nbrec_acl_table) {
202+
/* The creation and deletion is handled in relation to LS/PG rather
203+
* than the ACL itself. */
204+
if (nbrec_acl_is_new(acl) || nbrec_acl_is_deleted(acl)) {
205+
continue;
224206
}
225207

226-
if (modified) {
227-
/* Add the ls_stateful_rec to the tracking data. */
228-
hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
208+
struct ls_stateful_record *ls_stateful_rec;
209+
LS_STATEFUL_TABLE_FOR_EACH (ls_stateful_rec, &data->table) {
210+
if (uuidset_contains(&ls_stateful_rec->related_acls,
211+
&acl->header_.uuid)) {
212+
hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
213+
}
229214
}
230215
}
231216

@@ -295,7 +280,8 @@ ls_stateful_record_create(struct ls_stateful_table *table,
295280
xzalloc(sizeof *ls_stateful_rec);
296281
ls_stateful_rec->ls_index = od->index;
297282
ls_stateful_rec->nbs_uuid = od->nbs->header_.uuid;
298-
ls_stateful_record_init(ls_stateful_rec, od, NULL, ls_pgs);
283+
uuidset_init(&ls_stateful_rec->related_acls);
284+
ls_stateful_record_init(ls_stateful_rec, od, ls_pgs);
299285
ls_stateful_rec->lflow_ref = lflow_ref_create();
300286

301287
hmap_insert(&table->entries, &ls_stateful_rec->key_node,
@@ -307,27 +293,18 @@ ls_stateful_record_create(struct ls_stateful_table *table,
307293
static void
308294
ls_stateful_record_destroy(struct ls_stateful_record *ls_stateful_rec)
309295
{
296+
uuidset_destroy(&ls_stateful_rec->related_acls);
310297
lflow_ref_destroy(ls_stateful_rec->lflow_ref);
311298
free(ls_stateful_rec);
312299
}
313300

314301
static void
315302
ls_stateful_record_init(struct ls_stateful_record *ls_stateful_rec,
316303
const struct ovn_datapath *od,
317-
const struct ls_port_group *ls_pg,
318304
const struct ls_port_group_table *ls_pgs)
319305
{
320306
ls_stateful_rec->has_lb_vip = ls_has_lb_vip(od);
321-
ls_stateful_record_set_acl_flags(ls_stateful_rec, od, ls_pg, ls_pgs);
322-
}
323-
324-
static void
325-
ls_stateful_record_reinit(struct ls_stateful_record *ls_stateful_rec,
326-
const struct ovn_datapath *od,
327-
const struct ls_port_group *ls_pg,
328-
const struct ls_port_group_table *ls_pgs)
329-
{
330-
ls_stateful_record_init(ls_stateful_rec, od, ls_pg, ls_pgs);
307+
ls_stateful_record_set_acls(ls_stateful_rec, od, ls_pgs);
331308
}
332309

333310
static bool
@@ -365,36 +342,28 @@ ls_has_lb_vip(const struct ovn_datapath *od)
365342
}
366343

367344
static void
368-
ls_stateful_record_set_acl_flags(struct ls_stateful_record *ls_stateful_rec,
369-
const struct ovn_datapath *od,
370-
const struct ls_port_group *ls_pg,
371-
const struct ls_port_group_table *ls_pgs)
345+
ls_stateful_record_set_acls(struct ls_stateful_record *ls_stateful_rec,
346+
const struct ovn_datapath *od,
347+
const struct ls_port_group_table *ls_pgs)
372348
{
373349
ls_stateful_rec->has_stateful_acl = false;
374350
memset(&ls_stateful_rec->max_acl_tier, 0,
375351
sizeof ls_stateful_rec->max_acl_tier);
376352
ls_stateful_rec->has_acls = false;
353+
uuidset_clear(&ls_stateful_rec->related_acls);
377354

378-
if (ls_stateful_record_set_acl_flags_(ls_stateful_rec, od->nbs->acls,
379-
od->nbs->n_acls)) {
380-
return;
381-
}
382-
383-
if (!ls_pg) {
384-
ls_pg = ls_port_group_table_find(ls_pgs, od->nbs);
385-
}
355+
ls_stateful_record_set_acls_(ls_stateful_rec, od->nbs->acls,
356+
od->nbs->n_acls);
386357

358+
struct ls_port_group *ls_pg = ls_port_group_table_find(ls_pgs, od->nbs);
387359
if (!ls_pg) {
388360
return;
389361
}
390362

391363
const struct ls_port_group_record *ls_pg_rec;
392364
HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) {
393-
if (ls_stateful_record_set_acl_flags_(ls_stateful_rec,
394-
ls_pg_rec->nb_pg->acls,
395-
ls_pg_rec->nb_pg->n_acls)) {
396-
return;
397-
}
365+
ls_stateful_record_set_acls_(ls_stateful_rec, ls_pg_rec->nb_pg->acls,
366+
ls_pg_rec->nb_pg->n_acls);
398367
}
399368
}
400369

@@ -421,46 +390,24 @@ update_ls_max_acl_tier(struct ls_stateful_record *ls_stateful_rec,
421390
*tier = MAX(*tier, acl->tier);
422391
}
423392

424-
static bool
425-
ls_acl_tiers_are_maxed_out(struct acl_tier *acl_tier,
426-
uint64_t max_allowed_acl_tier)
427-
{
428-
return acl_tier->ingress_post_lb == max_allowed_acl_tier &&
429-
acl_tier->ingress_pre_lb == max_allowed_acl_tier &&
430-
acl_tier->egress == max_allowed_acl_tier;
431-
}
432-
433-
static bool
434-
ls_stateful_record_set_acl_flags_(struct ls_stateful_record *ls_stateful_rec,
435-
struct nbrec_acl **acls,
436-
size_t n_acls)
393+
static void
394+
ls_stateful_record_set_acls_(struct ls_stateful_record *ls_stateful_rec,
395+
struct nbrec_acl **acls, size_t n_acls)
437396
{
438-
/* A true return indicates that there are no possible ACL flags
439-
* left to set on ls_stateful record. A false return indicates that
440-
* further ACLs should be explored in case more flags need to be
441-
* set on ls_stateful record.
442-
*/
443397
if (!n_acls) {
444-
return false;
398+
return;
445399
}
446400

447401
ls_stateful_rec->has_acls = true;
448402
for (size_t i = 0; i < n_acls; i++) {
449403
const struct nbrec_acl *acl = acls[i];
450404
update_ls_max_acl_tier(ls_stateful_rec, acl);
405+
uuidset_insert(&ls_stateful_rec->related_acls, &acl->header_.uuid);
451406
if (!ls_stateful_rec->has_stateful_acl
452407
&& !strcmp(acl->action, "allow-related")) {
453408
ls_stateful_rec->has_stateful_acl = true;
454409
}
455-
if (ls_stateful_rec->has_stateful_acl &&
456-
ls_acl_tiers_are_maxed_out(
457-
&ls_stateful_rec->max_acl_tier,
458-
nbrec_acl_col_tier.type.key.integer.max)) {
459-
return true;
460-
}
461410
}
462-
463-
return false;
464411
}
465412

466413
static struct ls_stateful_input

northd/en-ls-stateful.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
/* OVS includes. */
2222
#include "lib/hmapx.h"
23+
#include "lib/uuidset.h"
2324
#include "openvswitch/hmap.h"
2425
#include "sset.h"
2526

@@ -54,6 +55,9 @@ struct ls_stateful_record {
5455
bool has_acls;
5556
struct acl_tier max_acl_tier;
5657

58+
/* Set of ACLs that are related to this LS. */
59+
struct uuidset related_acls;
60+
5761
/* 'lflow_ref' is used to reference logical flows generated for
5862
* this ls_stateful record.
5963
*
@@ -109,6 +113,8 @@ enum engine_input_handler_result
109113
ls_stateful_northd_handler(struct engine_node *, void *data);
110114
enum engine_input_handler_result
111115
ls_stateful_port_group_handler(struct engine_node *, void *data);
116+
enum engine_input_handler_result
117+
ls_stateful_acl_handler(struct engine_node *node, void *data);
112118

113119
const struct ls_stateful_record *ls_stateful_table_find(
114120
const struct ls_stateful_table *, const struct nbrec_logical_switch *);

northd/inc-proc-northd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
259259
engine_add_input(&en_ls_stateful, &en_northd, ls_stateful_northd_handler);
260260
engine_add_input(&en_ls_stateful, &en_port_group,
261261
ls_stateful_port_group_handler);
262+
engine_add_input(&en_ls_stateful, &en_nb_acl, ls_stateful_acl_handler);
262263

263264
engine_add_input(&en_mac_binding_aging, &en_sb_mac_binding, NULL);
264265
engine_add_input(&en_mac_binding_aging, &en_northd, NULL);
@@ -330,7 +331,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
330331
engine_add_input(&en_multicast_igmp, &en_sb_multicast_group, NULL);
331332
engine_add_input(&en_multicast_igmp, &en_sb_igmp_group, NULL);
332333

333-
engine_add_input(&en_lflow, &en_nb_acl, NULL);
334334
engine_add_input(&en_lflow, &en_sync_meters, NULL);
335335
engine_add_input(&en_lflow, &en_sb_logical_flow, NULL);
336336
engine_add_input(&en_lflow, &en_sb_multicast_group, NULL);

0 commit comments

Comments
 (0)