From: RYAN D. MOATS <rmo...@us.ibm.com> Add incremental processing of logical flows in ovn-controller by tracking changes to the match column of the Logical_Flow OVN SB table. Code is included to properly handle the order of checked sequence numbers and rechecking of rows skipped due to a logical_datapath not existing.
Signed-off-by: RYAN D. MOATS <rmo...@us.ibm.com> --- ovn/controller/lflow.c | 49 +++++++++++++++++++++++++++++++++++---- ovn/controller/lflow.h | 5 ++- ovn/controller/ovn-controller.c | 20 ++++++++++++--- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c index d53213c..7ae2c12 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -273,25 +273,60 @@ lflow_init(void) /* Translates logical flows in the Logical_Flow table in the OVN_SB database * into OpenFlow flows. See ovn-architecture(7) for more information. */ -void +unsigned int lflow_run(struct controller_ctx *ctx, struct hmap *flow_table, const struct simap *ct_zones, - struct hmap *local_datapaths) + struct hmap *local_datapaths, + unsigned int seqno) { struct hmap flows = HMAP_INITIALIZER(&flows); uint32_t conj_id_ofs = 1; + unsigned int skipped_seqno; + unsigned int processed_seqno = seqno; + unsigned int last_seqno = 0; ldp_run(ctx); const struct sbrec_logical_flow *lflow; - SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) { - /* Find the "struct logical_datapath" associated with this + SBREC_LOGICAL_FLOW_FOR_EACH_TRACKED (lflow, ctx->ovnsb_idl) { + unsigned int del_seqno = sbrec_logical_flow_row_get_seqno(lflow, + OVSDB_IDL_CHANGE_DELETE); + unsigned int mod_seqno = sbrec_logical_flow_row_get_seqno(lflow, + OVSDB_IDL_CHANGE_MODIFY); + unsigned int ins_seqno = sbrec_logical_flow_row_get_seqno(lflow, + OVSDB_IDL_CHANGE_INSERT); + if (del_seqno < seqno && mod_seqno < seqno && ins_seqno < seqno) { + continue; + } + if (del_seqno > processed_seqno) { + processed_seqno = del_seqno; + } + if (mod_seqno > processed_seqno) { + processed_seqno = mod_seqno; + } + if (ins_seqno > processed_seqno) { + processed_seqno = ins_seqno; + } + + /* Find the "struct logical_datapath" asssociated with this * Logical_Flow row. If there's no such struct, that must be because * no logical ports are bound to that logical datapath, so there's no - * point in maintaining any flows for it anyway, so skip it. */ + * point in maintaining any flows for it anyway, so skip it. + * Further, we have to remember the smallest sequence number of + * a skipped flow to ensure that we return the correct value + * and don't skip things in a later pass */ const struct logical_datapath *ldp; ldp = ldp_lookup(lflow->logical_datapath); if (!ldp) { + if (last_seqno == 0 || (del_seqno > 0 && last_seqno > del_seqno)) { + last_seqno = del_seqno; + } + if (last_seqno == 0 || (mod_seqno > 0 && last_seqno > mod_seqno)) { + last_seqno = mod_seqno; + } + if (last_seqno == 0 || (ins_seqno > 0 && last_seqno > ins_seqno)) { + last_seqno = ins_seqno; + } continue; } @@ -425,6 +460,10 @@ lflow_run(struct controller_ctx *ctx, struct hmap *flow_table, ofpbuf_uninit(&ofpacts); conj_id_ofs += n_conjs; } + if (last_seqno > 0) { + processed_seqno = last_seqno; + } + return(processed_seqno); } void diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h index ccbad30..91320a7 100644 --- a/ovn/controller/lflow.h +++ b/ovn/controller/lflow.h @@ -56,9 +56,10 @@ struct uuid; #define LOG_PIPELINE_LEN 16 void lflow_init(void); -void lflow_run(struct controller_ctx *, struct hmap *flow_table, +unsigned int lflow_run(struct controller_ctx *, struct hmap *flow_table, const struct simap *ct_zones, - struct hmap *local_datapaths); + struct hmap *local_datapaths, + unsigned int seqno); void lflow_destroy(void); #endif /* ovn/lflow.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 3638342..32d2a0e 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -204,6 +204,7 @@ main(int argc, char *argv[]) struct unixctl_server *unixctl; bool exiting; int retval; + unsigned int last_seqno; ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); @@ -257,9 +258,16 @@ main(int argc, char *argv[]) /* Connect to OVN SB database. */ char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl); - struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( - ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true)); - ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl); + struct ovsdb_idl *sb_idl = ovsdb_idl_create(ovnsb_remote, + &sbrec_idl_class, true, true); + /* set to track the southbound idl */ + ovsdb_idl_track_add_column(sb_idl, &sbrec_logical_flow_col_match); + + /*ovsdb_idl_track_add_all(sb_idl);*/ + struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(sb_idl); + + + ovsdb_idl_get_initial_snapshot(sb_idl); /* Initialize connection tracking zones. */ struct simap ct_zones = SIMAP_INITIALIZER(&ct_zones); @@ -271,6 +279,9 @@ main(int argc, char *argv[]) /* Main loop. */ exiting = false; while (!exiting) { + if (last_seqno == 0) { + last_seqno = ovsdb_idl_get_seqno(ovnsb_idl_loop.idl); + } struct controller_ctx ctx = { .ovs_idl = ovs_idl_loop.idl, .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop), @@ -300,7 +311,8 @@ main(int argc, char *argv[]) pinctrl_run(&ctx, br_int); struct hmap flow_table = HMAP_INITIALIZER(&flow_table); - lflow_run(&ctx, &flow_table, &ct_zones, &local_datapaths); + last_seqno = lflow_run(&ctx, &flow_table, &ct_zones, + &local_datapaths, last_seqno); if (chassis_id) { physical_run(&ctx, mff_ovn_geneve, br_int, chassis_id, &ct_zones, &flow_table); -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev