Skip to content

Commit

Permalink
ovn-controller: Incremental logical flow processing
Browse files Browse the repository at this point in the history
Implements change handler of flow_output for SB lflow changes.

Signed-off-by: Han Zhou <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
hzhou8 authored and blp committed May 24, 2019
1 parent 0bd4d85 commit e0b9e33
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 1 deletion.
82 changes: 82 additions & 0 deletions ovn/controller/lflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,88 @@ add_logical_flows(
nd_ra_opts_destroy(&nd_ra_opts);
}

bool
lflow_handle_changed_flows(
struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct sbrec_dhcp_options_table *dhcp_options_table,
const struct sbrec_dhcpv6_options_table *dhcpv6_options_table,
const struct sbrec_logical_flow_table *logical_flow_table,
const struct hmap *local_datapaths,
const struct sbrec_chassis *chassis,
const struct shash *addr_sets,
const struct shash *port_groups,
const struct sset *active_tunnels,
const struct sset *local_lport_ids,
struct ovn_desired_flow_table *flow_table,
struct ovn_extend_table *group_table,
struct ovn_extend_table *meter_table,
uint32_t *conj_id_ofs)
{
bool ret = true;
const struct sbrec_logical_flow *lflow;

struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts);
struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts);
const struct sbrec_dhcp_options *dhcp_opt_row;
SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row, dhcp_options_table) {
dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
dhcp_opt_row->type);
}


const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
dhcpv6_options_table) {
dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code,
dhcpv6_opt_row->type);
}

struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
nd_ra_opts_init(&nd_ra_opts);

/* Handle removed flows first, and then other flows, so that when
* the flows being added and removed have same match conditions
* can be processed in the proper order */
SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, logical_flow_table) {
/* Remove any flows that should be removed. */
if (sbrec_logical_flow_is_deleted(lflow)) {
VLOG_DBG("handle deleted lflow "UUID_FMT,
UUID_ARGS(&lflow->header_.uuid));
ofctrl_remove_flows(flow_table, &lflow->header_.uuid);
}
}
SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, logical_flow_table) {
if (!sbrec_logical_flow_is_deleted(lflow)) {
/* Now, add/modify existing flows. If the logical
* flow is a modification, just remove the flows
* for this row, and then add new flows. */
if (!sbrec_logical_flow_is_new(lflow)) {
VLOG_DBG("handle updated lflow "UUID_FMT,
UUID_ARGS(&lflow->header_.uuid));
ofctrl_remove_flows(flow_table, &lflow->header_.uuid);
}
VLOG_DBG("handle new lflow "UUID_FMT,
UUID_ARGS(&lflow->header_.uuid));
if (!consider_logical_flow(sbrec_multicast_group_by_name_datapath,
sbrec_port_binding_by_name,
lflow, local_datapaths,
chassis, &dhcp_opts, &dhcpv6_opts,
&nd_ra_opts, addr_sets, port_groups,
active_tunnels, local_lport_ids,
flow_table, group_table, meter_table,
conj_id_ofs)) {
ret = false;
break;
}
}
}
dhcp_opts_destroy(&dhcp_opts);
dhcp_opts_destroy(&dhcpv6_opts);
nd_ra_opts_destroy(&nd_ra_opts);
return ret;
}

static bool
update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs)
{
Expand Down
17 changes: 17 additions & 0 deletions ovn/controller/lflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,23 @@ void lflow_run(struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
struct ovn_extend_table *meter_table,
uint32_t *conj_id_ofs);

bool lflow_handle_changed_flows(
struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct sbrec_dhcp_options_table *,
const struct sbrec_dhcpv6_options_table *,
const struct sbrec_logical_flow_table *,
const struct hmap *local_datapaths,
const struct sbrec_chassis *,
const struct shash *addr_sets,
const struct shash *port_groups,
const struct sset *active_tunnels,
const struct sset *local_lport_ids,
struct ovn_desired_flow_table *,
struct ovn_extend_table *group_table,
struct ovn_extend_table *meter_table,
uint32_t *conj_id_ofs);

void lflow_destroy(void);

#endif /* ovn/lflow.h */
77 changes: 76 additions & 1 deletion ovn/controller/ovn-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,80 @@ en_flow_output_run(struct engine_node *node)
node->changed = true;
}

static bool
flow_output_sb_logical_flow_handler(struct engine_node *node)
{
struct ed_type_runtime_data *data =
(struct ed_type_runtime_data *)engine_get_input(
"runtime_data", node)->data;
struct hmap *local_datapaths = &data->local_datapaths;
struct sset *local_lport_ids = &data->local_lport_ids;
struct sset *active_tunnels = &data->active_tunnels;
struct shash *addr_sets = &data->addr_sets;
struct shash *port_groups = &data->port_groups;

struct ovsrec_open_vswitch_table *ovs_table =
(struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
engine_get_input("OVS_open_vswitch", node));
struct ovsrec_bridge_table *bridge_table =
(struct ovsrec_bridge_table *)EN_OVSDB_GET(
engine_get_input("OVS_bridge", node));
const struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table);
const char *chassis_id = get_chassis_id(ovs_table);

struct ovsdb_idl_index *sbrec_chassis_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_chassis", node),
"name");
const struct sbrec_chassis *chassis = NULL;
if (chassis_id) {
chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
}

ovs_assert(br_int && chassis);

struct ed_type_flow_output *fo =
(struct ed_type_flow_output *)node->data;
struct ovn_desired_flow_table *flow_table = &fo->flow_table;
struct ovn_extend_table *group_table = &fo->group_table;
struct ovn_extend_table *meter_table = &fo->meter_table;
uint32_t *conj_id_ofs = &fo->conj_id_ofs;

struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
engine_ovsdb_node_get_index(
engine_get_input("SB_multicast_group", node),
"name_datapath");

struct ovsdb_idl_index *sbrec_port_binding_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_port_binding", node),
"name");

struct sbrec_dhcp_options_table *dhcp_table =
(struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
engine_get_input("SB_dhcp_options", node));

struct sbrec_dhcpv6_options_table *dhcpv6_table =
(struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
engine_get_input("SB_dhcpv6_options", node));

struct sbrec_logical_flow_table *logical_flow_table =
(struct sbrec_logical_flow_table *)EN_OVSDB_GET(
engine_get_input("SB_logical_flow", node));

bool handled = lflow_handle_changed_flows(
sbrec_multicast_group_by_name_datapath,
sbrec_port_binding_by_name,
dhcp_table, dhcpv6_table,
logical_flow_table,
local_datapaths, chassis, addr_sets,
port_groups, active_tunnels, local_lport_ids,
flow_table, group_table, meter_table, conj_id_ofs);

node->changed = true;
return handled;
}

struct ovn_controller_exit_args {
bool *exiting;
bool *restart;
Expand Down Expand Up @@ -1143,7 +1217,8 @@ main(int argc, char *argv[])
engine_add_input(&en_flow_output, &en_sb_multicast_group, NULL);
engine_add_input(&en_flow_output, &en_sb_port_binding, NULL);
engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL);
engine_add_input(&en_flow_output, &en_sb_logical_flow, NULL);
engine_add_input(&en_flow_output, &en_sb_logical_flow,
flow_output_sb_logical_flow_handler);
engine_add_input(&en_flow_output, &en_sb_dhcp_options, NULL);
engine_add_input(&en_flow_output, &en_sb_dhcpv6_options, NULL);
engine_add_input(&en_flow_output, &en_sb_dns, NULL);
Expand Down

0 comments on commit e0b9e33

Please sign in to comment.