Message ID | 20221122034954.1973887-1-numans@ovn.org |
---|---|
State | Accepted |
Headers | show |
Series | northd IP for address sets | expand |
Context | Check | Description |
---|---|---|
ovsrobot/apply-robot | success | apply and check: success |
ovsrobot/github-robot-_Build_and_Test | success | github build: passed |
ovsrobot/github-robot-_ovn-kubernetes | fail | github build: failed |
On Mon, Nov 21, 2022 at 7:50 PM <numans@ovn.org> wrote: > > From: Numan Siddique <numans@ovn.org> > > A sub-engine node 'en_sync_to_sb_addr_set' is added with-in the > 'en_sync_to_sb' node to sync the Address_Set table in the > SB database. To start with, it falls back to full recompute > all the time. Upcoming patch will add the incremental processing > support to sync the SB Address_Set table. > > 'en_sync_to_sb' engine node can be enhanced further to sync other > SB tables like - Port_Group, DHCP_Options, DNS etc. > For the commit title: s/IP/I-P Acked-by: Han Zhou <hzhou@ovn.org> > Acked-by: Mark Michelson <mmichels@redhat.com> > Acked-by: Ales Musil <amusil@redhat.com> > Signed-off-by: Numan Siddique <numans@ovn.org> > --- > lib/ovn-util.c | 30 +++++ > lib/ovn-util.h | 3 + > northd/automake.mk | 4 + > northd/en-northd-output.c | 58 ++++++++++ > northd/en-northd-output.h | 17 +++ > northd/en-northd.c | 4 - > northd/en-sync-sb.c | 233 ++++++++++++++++++++++++++++++++++++++ > northd/en-sync-sb.h | 14 +++ > northd/inc-proc-northd.c | 24 +++- > northd/northd.c | 173 ++-------------------------- > northd/northd.h | 3 +- > 11 files changed, 390 insertions(+), 173 deletions(-) > create mode 100644 northd/en-northd-output.c > create mode 100644 northd/en-northd-output.h > create mode 100644 northd/en-sync-sb.c > create mode 100644 northd/en-sync-sb.h > > diff --git a/lib/ovn-util.c b/lib/ovn-util.c > index 597625a29..868472ace 100644 > --- a/lib/ovn-util.c > +++ b/lib/ovn-util.c > @@ -938,3 +938,33 @@ daemon_started_recently(void) > /* Ensure that at least an amount of time has passed. */ > return time_wall_msec() - startup_ts <= DAEMON_STARTUP_DELAY_MS; > } > + > +/* Builds a unique address set compatible name ([a-zA-Z_.][a-zA-Z_.0-9]*) > + * for the router's load balancer VIP address set, combining the logical > + * router's datapath tunnel key and address family. > + * > + * Also prefixes the name with 'prefix'. > + */ > +static char * > +lr_lb_address_set_name_(uint32_t lr_tunnel_key, const char *prefix, > + int addr_family) > +{ > + return xasprintf("%s_rtr_lb_%"PRIu32"_ip%s", prefix, lr_tunnel_key, > + addr_family == AF_INET ? "4" : "6"); > +} > + > +/* Builds the router's load balancer VIP address set name. */ > +char * > +lr_lb_address_set_name(uint32_t lr_tunnel_key, int addr_family) > +{ > + return lr_lb_address_set_name_(lr_tunnel_key, "", addr_family); > +} > + > +/* Builds a string that refers to the the router's load balancer VIP address > + * set name, that is: $<address_set_name>. > + */ > +char * > +lr_lb_address_set_ref(uint32_t lr_tunnel_key, int addr_family) > +{ > + return lr_lb_address_set_name_(lr_tunnel_key, "$", addr_family); > +} > diff --git a/lib/ovn-util.h b/lib/ovn-util.h > index a1f1cf0ad..809ff1d36 100644 > --- a/lib/ovn-util.h > +++ b/lib/ovn-util.h > @@ -315,4 +315,7 @@ void daemon_started_recently_ignore(void); > bool daemon_started_recently(void); > int64_t daemon_startup_ts(void); > > +char *lr_lb_address_set_name(uint32_t lr_tunnel_key, int addr_family); > +char *lr_lb_address_set_ref(uint32_t lr_tunnel_key, int addr_family); > + > #endif /* OVN_UTIL_H */ > diff --git a/northd/automake.mk b/northd/automake.mk > index 81582867d..b7cfccf36 100644 > --- a/northd/automake.mk > +++ b/northd/automake.mk > @@ -10,6 +10,10 @@ northd_ovn_northd_SOURCES = \ > northd/en-northd.h \ > northd/en-lflow.c \ > northd/en-lflow.h \ > + northd/en-northd-output.c \ > + northd/en-northd-output.h \ > + northd/en-sync-sb.c \ > + northd/en-sync-sb.h \ > northd/inc-proc-northd.c \ > northd/inc-proc-northd.h \ > northd/ipam.c \ > diff --git a/northd/en-northd-output.c b/northd/en-northd-output.c > new file mode 100644 > index 000000000..cdb2f9558 > --- /dev/null > +++ b/northd/en-northd-output.c > @@ -0,0 +1,58 @@ > +/* > + * Licensed under the Apache License, Version 2.0 (the "License"); > + * you may not use this file except in compliance with the License. > + * You may obtain a copy of the License at: > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + * See the License for the specific language governing permissions and > + * limitations under the License. > + */ > + > +#include <config.h> > + > +#include <getopt.h> > +#include <stdlib.h> > +#include <stdio.h> > + > +#include "openvswitch/util.h" > + > +#include "en-northd-output.h" > +#include "lib/inc-proc-eng.h" > + > +void * > +en_northd_output_init(struct engine_node *node OVS_UNUSED, > + struct engine_arg *arg OVS_UNUSED) > +{ > + return NULL; > +} > + > +void > +en_northd_output_run(struct engine_node *node, void *data OVS_UNUSED) > +{ > + engine_set_node_state(node, EN_UPDATED); > +} > + > +void > +en_northd_output_cleanup(void *data OVS_UNUSED) > +{ > + > +} > + > +bool > +northd_output_sync_to_sb_handler(struct engine_node *node, > + void *data OVS_UNUSED) > +{ > + engine_set_node_state(node, EN_UPDATED); > + return true; > +} > + > +bool > +northd_output_lflow_handler(struct engine_node *node, void *data OVS_UNUSED) > +{ > + engine_set_node_state(node, EN_UPDATED); > + return true; > +} > diff --git a/northd/en-northd-output.h b/northd/en-northd-output.h > new file mode 100644 > index 000000000..d0079ea67 > --- /dev/null > +++ b/northd/en-northd-output.h > @@ -0,0 +1,17 @@ > +#ifndef EN_NORTHD_OUTPUT_H > +#define EN_NORTHD_OUTPUT_H 1 > + > +#include "lib/inc-proc-eng.h" > + > +void *en_northd_output_init(struct engine_node *node OVS_UNUSED, > + struct engine_arg *arg OVS_UNUSED); > +void en_northd_output_run(struct engine_node *node OVS_UNUSED, > + void *data OVS_UNUSED); > + > +void en_northd_output_cleanup(void *data); > +bool northd_output_sync_to_sb_handler(struct engine_node *node, > + void *data OVS_UNUSED); > +bool northd_output_lflow_handler(struct engine_node *node, > + void *data OVS_UNUSED); > + > +#endif > diff --git a/northd/en-northd.c b/northd/en-northd.c > index 7fe83db64..93891b0b7 100644 > --- a/northd/en-northd.c > +++ b/northd/en-northd.c > @@ -72,8 +72,6 @@ void en_northd_run(struct engine_node *node, void *data) > EN_OVSDB_GET(engine_get_input("NB_load_balancer_group", node)); > input_data.nbrec_port_group_table = > EN_OVSDB_GET(engine_get_input("NB_port_group", node)); > - input_data.nbrec_address_set_table = > - EN_OVSDB_GET(engine_get_input("NB_address_set", node)); > input_data.nbrec_meter_table = > EN_OVSDB_GET(engine_get_input("NB_meter", node)); > input_data.nbrec_acl_table = > @@ -99,8 +97,6 @@ void en_northd_run(struct engine_node *node, void *data) > EN_OVSDB_GET(engine_get_input("SB_load_balancer", node)); > input_data.sbrec_service_monitor_table = > EN_OVSDB_GET(engine_get_input("SB_service_monitor", node)); > - input_data.sbrec_address_set_table = > - EN_OVSDB_GET(engine_get_input("SB_address_set", node)); > input_data.sbrec_port_group_table = > EN_OVSDB_GET(engine_get_input("SB_port_group", node)); > input_data.sbrec_meter_table = > diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c > new file mode 100644 > index 000000000..6e8182f42 > --- /dev/null > +++ b/northd/en-sync-sb.c > @@ -0,0 +1,233 @@ > +/* > + * Licensed under the Apache License, Version 2.0 (the "License"); > + * you may not use this file except in compliance with the License. > + * You may obtain a copy of the License at: > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + * See the License for the specific language governing permissions and > + * limitations under the License. > + */ > + > +#include <config.h> > + > +#include <getopt.h> > +#include <stdlib.h> > +#include <stdio.h> > + > +#include "lib/svec.h" > +#include "openvswitch/util.h" > + > +#include "en-sync-sb.h" > +#include "lib/inc-proc-eng.h" > +#include "lib/lb.h" > +#include "lib/ovn-nb-idl.h" > +#include "lib/ovn-sb-idl.h" > +#include "lib/ovn-util.h" > +#include "northd.h" > + > +#include "openvswitch/vlog.h" > + > +VLOG_DEFINE_THIS_MODULE(en_sync_to_sb); > + > +static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, > + const char **addrs, size_t n_addrs, > + struct shash *sb_address_sets); > +static void sync_addr_sets(const struct nbrec_address_set_table *, > + const struct nbrec_port_group_table *, > + const struct sbrec_address_set_table *, > + struct ovsdb_idl_txn *ovnsb_txn, > + struct hmap *datapaths); > + > +void * > +en_sync_to_sb_init(struct engine_node *node OVS_UNUSED, > + struct engine_arg *arg OVS_UNUSED) > +{ > + return NULL; > +} > + > +void > +en_sync_to_sb_run(struct engine_node *node, void *data OVS_UNUSED) > +{ > + engine_set_node_state(node, EN_UPDATED); > +} > + > +void > +en_sync_to_sb_cleanup(void *data OVS_UNUSED) > +{ > + > +} > + > +void * > +en_sync_to_sb_addr_set_init(struct engine_node *node OVS_UNUSED, > + struct engine_arg *arg OVS_UNUSED) > +{ > + return NULL; > +} > + > +void > +en_sync_to_sb_addr_set_run(struct engine_node *node, void *data OVS_UNUSED) > +{ > + const struct nbrec_address_set_table *nb_address_set_table = > + EN_OVSDB_GET(engine_get_input("NB_address_set", node)); > + const struct nbrec_port_group_table *nb_port_group_table = > + EN_OVSDB_GET(engine_get_input("NB_port_group", node)); > + const struct sbrec_address_set_table *sb_address_set_table = > + EN_OVSDB_GET(engine_get_input("SB_address_set", node)); > + > + const struct engine_context *eng_ctx = engine_get_context(); > + struct northd_data *northd_data = engine_get_input_data("northd", node); > + > + sync_addr_sets(nb_address_set_table, nb_port_group_table, > + sb_address_set_table, eng_ctx->ovnsb_idl_txn, > + &northd_data->datapaths); > + > + engine_set_node_state(node, EN_UPDATED); > +} > + > +void > +en_sync_to_sb_addr_set_cleanup(void *data OVS_UNUSED) > +{ > + > +} > + > +/* static functions. */ > +static void > +sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, > + const char **addrs, size_t n_addrs, > + struct shash *sb_address_sets) > +{ > + const struct sbrec_address_set *sb_address_set; > + sb_address_set = shash_find_and_delete(sb_address_sets, > + name); > + if (!sb_address_set) { > + sb_address_set = sbrec_address_set_insert(ovnsb_txn); > + sbrec_address_set_set_name(sb_address_set, name); > + } > + > + sbrec_address_set_set_addresses(sb_address_set, > + addrs, n_addrs); > +} > + > +/* OVN_Southbound Address_Set table contains same records as in north > + * bound, plus > + * - the records generated from Port_Group table in north bound. > + * > + * There are 2 records generated from each port group, one for IPv4, and > + * one for IPv6, named in the format: <port group name>_ip4 and > + * <port group name>_ip6 respectively. MAC addresses are ignored. > + * > + * - the records generated for the load balancer VIP addresses which are > + * routable from each logical router. > + * > + * We always update OVN_Southbound to match the Address_Set and Port_Group > + * in OVN_Northbound, so that the address sets used in Logical_Flows in > + * OVN_Southbound is checked against the proper set.*/ > +static void > +sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, > + const struct nbrec_port_group_table *nb_port_group_table, > + const struct sbrec_address_set_table *sb_address_set_table, > + struct ovsdb_idl_txn *ovnsb_txn, struct hmap *datapaths) > +{ > + struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets); > + > + const struct sbrec_address_set *sb_address_set; > + SBREC_ADDRESS_SET_TABLE_FOR_EACH (sb_address_set, > + sb_address_set_table) { > + shash_add(&sb_address_sets, sb_address_set->name, sb_address_set); > + } > + > + /* Service monitor MAC. */ > + const char *svc_monitor_macp = northd_get_svc_monitor_mac(); > + sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc_monitor_macp, 1, > + &sb_address_sets); > + > + /* sync port group generated address sets first */ > + const struct nbrec_port_group *nb_port_group; > + NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_port_group, > + nb_port_group_table) { > + struct svec ipv4_addrs = SVEC_EMPTY_INITIALIZER; > + struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; > + for (size_t i = 0; i < nb_port_group->n_ports; i++) { > + for (size_t j = 0; j < nb_port_group->ports[i]->n_addresses; j++) { > + const char *addrs = nb_port_group->ports[i]->addresses[j]; > + if (!is_dynamic_lsp_address(addrs)) { > + split_addresses(addrs, &ipv4_addrs, &ipv6_addrs); > + } > + } > + if (nb_port_group->ports[i]->dynamic_addresses) { > + split_addresses(nb_port_group->ports[i]->dynamic_addresses, > + &ipv4_addrs, &ipv6_addrs); > + } > + } > + char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); > + char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); > + sync_addr_set(ovnsb_txn, ipv4_addrs_name, > + /* "char **" is not compatible with "const char **" */ > + (const char **) ipv4_addrs.names, > + ipv4_addrs.n, &sb_address_sets); > + sync_addr_set(ovnsb_txn, ipv6_addrs_name, > + /* "char **" is not compatible with "const char **" */ > + (const char **) ipv6_addrs.names, > + ipv6_addrs.n, &sb_address_sets); > + free(ipv4_addrs_name); > + free(ipv6_addrs_name); > + svec_destroy(&ipv4_addrs); > + svec_destroy(&ipv6_addrs); > + } > + > + /* Sync router load balancer VIP generated address sets. */ > + struct ovn_datapath *od; > + HMAP_FOR_EACH (od, key_node, datapaths) { > + if (!od->nbr) { > + continue; > + } > + > + if (sset_count(&od->lb_ips->ips_v4_reachable)) { > + char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key, > + AF_INET); > + const char **ipv4_addrs = > + sset_array(&od->lb_ips->ips_v4_reachable); > + > + sync_addr_set(ovnsb_txn, ipv4_addrs_name, ipv4_addrs, > + sset_count(&od->lb_ips->ips_v4_reachable), > + &sb_address_sets); > + free(ipv4_addrs_name); > + free(ipv4_addrs); > + } > + > + if (sset_count(&od->lb_ips->ips_v6_reachable)) { > + char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key, > + AF_INET6); > + const char **ipv6_addrs = > + sset_array(&od->lb_ips->ips_v6_reachable); > + > + sync_addr_set(ovnsb_txn, ipv6_addrs_name, ipv6_addrs, > + sset_count(&od->lb_ips->ips_v6_reachable), > + &sb_address_sets); > + free(ipv6_addrs_name); > + free(ipv6_addrs); > + } > + } > + > + /* sync user defined address sets, which may overwrite port group > + * generated address sets if same name is used */ > + const struct nbrec_address_set *nb_address_set; > + NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, > + nb_address_set_table) { > + sync_addr_set(ovnsb_txn, nb_address_set->name, > + /* "char **" is not compatible with "const char **" */ > + (const char **) nb_address_set->addresses, > + nb_address_set->n_addresses, &sb_address_sets); > + } > + > + struct shash_node *node; > + SHASH_FOR_EACH_SAFE (node, &sb_address_sets) { > + sbrec_address_set_delete(node->data); > + shash_delete(&sb_address_sets, node); > + } > + shash_destroy(&sb_address_sets); > +} > diff --git a/northd/en-sync-sb.h b/northd/en-sync-sb.h > new file mode 100644 > index 000000000..1b25ff90f > --- /dev/null > +++ b/northd/en-sync-sb.h > @@ -0,0 +1,14 @@ > +#ifndef EN_SYNC_SB_H > +#define EN_SYNC_SB_H 1 > + > +#include "lib/inc-proc-eng.h" > + > +void *en_sync_to_sb_init(struct engine_node *, struct engine_arg *); > +void en_sync_to_sb_run(struct engine_node *, void *data); > +void en_sync_to_sb_cleanup(void *data); > + > +void *en_sync_to_sb_addr_set_init(struct engine_node *, struct engine_arg *); > +void en_sync_to_sb_addr_set_run(struct engine_node *, void *data); > +void en_sync_to_sb_addr_set_cleanup(void *data); > + > +#endif /* end of EN_SYNC_SB_H */ > diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c > index 54e0ad3b0..dbba41127 100644 > --- a/northd/inc-proc-northd.c > +++ b/northd/inc-proc-northd.c > @@ -32,6 +32,8 @@ > #include "inc-proc-northd.h" > #include "en-northd.h" > #include "en-lflow.h" > +#include "en-northd-output.h" > +#include "en-sync-sb.h" > #include "util.h" > > VLOG_DEFINE_THIS_MODULE(inc_proc_northd); > @@ -153,6 +155,9 @@ static ENGINE_NODE(northd, "northd"); > static ENGINE_NODE(lflow, "lflow"); > static ENGINE_NODE(mac_binding_aging, "mac_binding_aging"); > static ENGINE_NODE(mac_binding_aging_waker, "mac_binding_aging_waker"); > +static ENGINE_NODE(northd_output, "northd_output"); > +static ENGINE_NODE(sync_to_sb, "sync_to_sb"); > +static ENGINE_NODE(sync_to_sb_addr_set, "sync_to_sb_addr_set"); > > void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > struct ovsdb_idl_loop *sb) > @@ -164,7 +169,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > engine_add_input(&en_northd, &en_nb_logical_switch, NULL); > engine_add_input(&en_northd, &en_nb_logical_switch_port, NULL); > engine_add_input(&en_northd, &en_nb_forwarding_group, NULL); > - engine_add_input(&en_northd, &en_nb_address_set, NULL); > engine_add_input(&en_northd, &en_nb_port_group, NULL); > engine_add_input(&en_northd, &en_nb_load_balancer, NULL); > engine_add_input(&en_northd, &en_nb_load_balancer_group, NULL); > @@ -191,7 +195,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > engine_add_input(&en_northd, &en_sb_chassis, NULL); > engine_add_input(&en_northd, &en_sb_chassis_private, NULL); > engine_add_input(&en_northd, &en_sb_encap, NULL); > - engine_add_input(&en_northd, &en_sb_address_set, NULL); > engine_add_input(&en_northd, &en_sb_port_group, NULL); > engine_add_input(&en_northd, &en_sb_logical_dp_group, NULL); > engine_add_input(&en_northd, &en_sb_meter, NULL); > @@ -229,6 +232,21 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > * once I-P engine allows multiple root nodes. */ > engine_add_input(&en_lflow, &en_mac_binding_aging, NULL); > > + engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set, NULL); > + engine_add_input(&en_sync_to_sb_addr_set, &en_nb_port_group, NULL); > + engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL); > + engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL); > + > + /* en_sync_to_sb engine node syncs the SB database tables from > + * the NB database tables. > + * Right now this engine only syncs the SB Address_Set table. > + */ > + engine_add_input(&en_sync_to_sb, &en_sync_to_sb_addr_set, NULL); > + engine_add_input(&en_northd_output, &en_sync_to_sb, > + northd_output_sync_to_sb_handler); > + engine_add_input(&en_northd_output, &en_lflow, > + northd_output_lflow_handler); > + > struct engine_arg engine_arg = { > .nb_idl = nb->idl, > .sb_idl = sb->idl, > @@ -249,7 +267,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, > struct ovsdb_idl_index *sbrec_mac_binding_by_datapath > = mac_binding_by_datapath_index_create(sb->idl); > > - engine_init(&en_lflow, &engine_arg); > + engine_init(&en_northd_output, &engine_arg); > > engine_ovsdb_node_add_index(&en_sb_chassis, > "sbrec_chassis_by_name", > diff --git a/northd/northd.c b/northd/northd.c > index 00ff8f933..e5db55451 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -808,37 +808,6 @@ lr_has_lb_vip(struct ovn_datapath *od) > return false; > } > > -/* Builds a unique address set compatible name ([a-zA-Z_.][a-zA-Z_.0-9]*) > - * for the router's load balancer VIP address set, combining the logical > - * router's datapath tunnel key and address family. > - * > - * Also prefixes the name with 'prefix'. > - */ > -static char * > -lr_lb_address_set_name_(const struct ovn_datapath *od, const char *prefix, > - int addr_family) > -{ > - ovs_assert(od->nbr); > - return xasprintf("%s_rtr_lb_%"PRIu32"_ip%s", prefix, od->tunnel_key, > - addr_family == AF_INET ? "4" : "6"); > -} > - > -/* Builds the router's load balancer VIP address set name. */ > -static char * > -lr_lb_address_set_name(const struct ovn_datapath *od, int addr_family) > -{ > - return lr_lb_address_set_name_(od, "", addr_family); > -} > - > -/* Builds a string that refers to the the router's load balancer VIP address > - * set name, that is: $<address_set_name>. > - */ > -static char * > -lr_lb_address_set_ref(const struct ovn_datapath *od, int addr_family) > -{ > - return lr_lb_address_set_name_(od, "$", addr_family); > -} > - > static void > init_lb_for_datapath(struct ovn_datapath *od) > { > @@ -13141,7 +13110,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, > } > > /* Create a single ARP rule for all IPs that are used as VIPs. */ > - char *lb_ips_v4_as = lr_lb_address_set_ref(op->od, AF_INET); > + char *lb_ips_v4_as = lr_lb_address_set_ref(op->od->tunnel_key, > + AF_INET); > build_lrouter_arp_flow(op->od, op, lb_ips_v4_as, > REG_INPORT_ETH_ADDR, > match, false, 90, NULL, lflows); > @@ -13157,7 +13127,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, > } > > /* Create a single ND rule for all IPs that are used as VIPs. */ > - char *lb_ips_v6_as = lr_lb_address_set_ref(op->od, AF_INET6); > + char *lb_ips_v6_as = lr_lb_address_set_ref(op->od->tunnel_key, > + AF_INET6); > build_lrouter_nd_flow(op->od, op, "nd_na", lb_ips_v6_as, NULL, > REG_INPORT_ETH_ADDR, match, false, 90, > NULL, lflows, meter_groups); > @@ -14918,136 +14889,6 @@ void build_lflows(struct lflow_input *input_data, > hmap_destroy(&mcast_groups); > } > > -static void > -sync_address_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, > - const char **addrs, size_t n_addrs, > - struct shash *sb_address_sets) > -{ > - const struct sbrec_address_set *sb_address_set; > - sb_address_set = shash_find_and_delete(sb_address_sets, > - name); > - if (!sb_address_set) { > - sb_address_set = sbrec_address_set_insert(ovnsb_txn); > - sbrec_address_set_set_name(sb_address_set, name); > - } > - > - sbrec_address_set_set_addresses(sb_address_set, > - addrs, n_addrs); > -} > - > -/* OVN_Southbound Address_Set table contains same records as in north > - * bound, plus the records generated from Port_Group table in north bound. > - * > - * There are 2 records generated from each port group, one for IPv4, and > - * one for IPv6, named in the format: <port group name>_ip4 and > - * <port group name>_ip6 respectively. MAC addresses are ignored. > - * > - * We always update OVN_Southbound to match the Address_Set and Port_Group > - * in OVN_Northbound, so that the address sets used in Logical_Flows in > - * OVN_Southbound is checked against the proper set.*/ > -static void > -sync_address_sets(struct northd_input *input_data, > - struct ovsdb_idl_txn *ovnsb_txn, > - struct hmap *datapaths) > -{ > - struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets); > - > - const struct sbrec_address_set *sb_address_set; > - SBREC_ADDRESS_SET_TABLE_FOR_EACH (sb_address_set, > - input_data->sbrec_address_set_table) { > - shash_add(&sb_address_sets, sb_address_set->name, sb_address_set); > - } > - > - /* Service monitor MAC. */ > - const char *svc_monitor_macp = svc_monitor_mac; > - sync_address_set(ovnsb_txn, "svc_monitor_mac", &svc_monitor_macp, 1, > - &sb_address_sets); > - > - /* sync port group generated address sets first */ > - const struct nbrec_port_group *nb_port_group; > - NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_port_group, > - input_data->nbrec_port_group_table) { > - struct svec ipv4_addrs = SVEC_EMPTY_INITIALIZER; > - struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; > - for (size_t i = 0; i < nb_port_group->n_ports; i++) { > - for (size_t j = 0; j < nb_port_group->ports[i]->n_addresses; j++) { > - const char *addrs = nb_port_group->ports[i]->addresses[j]; > - if (!is_dynamic_lsp_address(addrs)) { > - split_addresses(addrs, &ipv4_addrs, &ipv6_addrs); > - } > - } > - if (nb_port_group->ports[i]->dynamic_addresses) { > - split_addresses(nb_port_group->ports[i]->dynamic_addresses, > - &ipv4_addrs, &ipv6_addrs); > - } > - } > - char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); > - char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); > - sync_address_set(ovnsb_txn, ipv4_addrs_name, > - /* "char **" is not compatible with "const char **" */ > - (const char **)ipv4_addrs.names, > - ipv4_addrs.n, &sb_address_sets); > - sync_address_set(ovnsb_txn, ipv6_addrs_name, > - /* "char **" is not compatible with "const char **" */ > - (const char **)ipv6_addrs.names, > - ipv6_addrs.n, &sb_address_sets); > - free(ipv4_addrs_name); > - free(ipv6_addrs_name); > - svec_destroy(&ipv4_addrs); > - svec_destroy(&ipv6_addrs); > - } > - > - /* Sync router load balancer VIP generated address sets. */ > - struct ovn_datapath *od; > - HMAP_FOR_EACH (od, key_node, datapaths) { > - if (!od->nbr) { > - continue; > - } > - > - if (sset_count(&od->lb_ips->ips_v4_reachable)) { > - char *ipv4_addrs_name = lr_lb_address_set_name(od, AF_INET); > - const char **ipv4_addrs = > - sset_array(&od->lb_ips->ips_v4_reachable); > - > - sync_address_set(ovnsb_txn, ipv4_addrs_name, ipv4_addrs, > - sset_count(&od->lb_ips->ips_v4_reachable), > - &sb_address_sets); > - free(ipv4_addrs_name); > - free(ipv4_addrs); > - } > - > - if (sset_count(&od->lb_ips->ips_v6_reachable)) { > - char *ipv6_addrs_name = lr_lb_address_set_name(od, AF_INET6); > - const char **ipv6_addrs = > - sset_array(&od->lb_ips->ips_v6_reachable); > - > - sync_address_set(ovnsb_txn, ipv6_addrs_name, ipv6_addrs, > - sset_count(&od->lb_ips->ips_v6_reachable), > - &sb_address_sets); > - free(ipv6_addrs_name); > - free(ipv6_addrs); > - } > - } > - > - /* sync user defined address sets, which may overwrite port group > - * generated address sets if same name is used */ > - const struct nbrec_address_set *nb_address_set; > - NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, > - input_data->nbrec_address_set_table) { > - sync_address_set(ovnsb_txn, nb_address_set->name, > - /* "char **" is not compatible with "const char **" */ > - (const char **)nb_address_set->addresses, > - nb_address_set->n_addresses, &sb_address_sets); > - } > - > - struct shash_node *node; > - SHASH_FOR_EACH_SAFE (node, &sb_address_sets) { > - sbrec_address_set_delete(node->data); > - shash_delete(&sb_address_sets, node); > - } > - shash_destroy(&sb_address_sets); > -} > - > /* Each port group in Port_Group table in OVN_Northbound has a corresponding > * entry in Port_Group table in OVN_Southbound. In OVN_Northbound the entries > * contains lport uuids, while in OVN_Southbound we store the lport names. > @@ -15918,7 +15759,6 @@ ovnnb_db_run(struct northd_input *input_data, > ovn_update_ipv6_prefix(&data->ports); > > sync_lbs(input_data, ovnsb_txn, &data->datapaths, &data->lbs); > - sync_address_sets(input_data, ovnsb_txn, &data->datapaths); > sync_port_groups(input_data, ovnsb_txn, &data->port_groups); > sync_meters(input_data, ovnsb_txn, &data->meter_groups); > sync_dns_entries(input_data, ovnsb_txn, &data->datapaths); > @@ -16195,3 +16035,8 @@ void northd_run(struct northd_input *input_data, > stopwatch_stop(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec()); > } > > +const char * > +northd_get_svc_monitor_mac(void) > +{ > + return svc_monitor_mac; > +} > diff --git a/northd/northd.h b/northd/northd.h > index da90e2815..ea9bd5797 100644 > --- a/northd/northd.h > +++ b/northd/northd.h > @@ -31,7 +31,6 @@ struct northd_input { > const struct nbrec_load_balancer_group_table > *nbrec_load_balancer_group_table; > const struct nbrec_port_group_table *nbrec_port_group_table; > - const struct nbrec_address_set_table *nbrec_address_set_table; > const struct nbrec_meter_table *nbrec_meter_table; > const struct nbrec_acl_table *nbrec_acl_table; > const struct nbrec_static_mac_binding_table > @@ -47,7 +46,6 @@ struct northd_input { > const struct sbrec_fdb_table *sbrec_fdb_table; > const struct sbrec_load_balancer_table *sbrec_load_balancer_table; > const struct sbrec_service_monitor_table *sbrec_service_monitor_table; > - const struct sbrec_address_set_table *sbrec_address_set_table; > const struct sbrec_port_group_table *sbrec_port_group_table; > const struct sbrec_meter_table *sbrec_meter_table; > const struct sbrec_dns_table *sbrec_dns_table; > @@ -281,4 +279,5 @@ void bfd_cleanup_connections(struct lflow_input *input_data, > struct hmap *bfd_map); > void run_update_worker_pool(int n_threads); > > +const char *northd_get_svc_monitor_mac(void); > #endif /* NORTHD_H */ > -- > 2.38.1 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 597625a29..868472ace 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -938,3 +938,33 @@ daemon_started_recently(void) /* Ensure that at least an amount of time has passed. */ return time_wall_msec() - startup_ts <= DAEMON_STARTUP_DELAY_MS; } + +/* Builds a unique address set compatible name ([a-zA-Z_.][a-zA-Z_.0-9]*) + * for the router's load balancer VIP address set, combining the logical + * router's datapath tunnel key and address family. + * + * Also prefixes the name with 'prefix'. + */ +static char * +lr_lb_address_set_name_(uint32_t lr_tunnel_key, const char *prefix, + int addr_family) +{ + return xasprintf("%s_rtr_lb_%"PRIu32"_ip%s", prefix, lr_tunnel_key, + addr_family == AF_INET ? "4" : "6"); +} + +/* Builds the router's load balancer VIP address set name. */ +char * +lr_lb_address_set_name(uint32_t lr_tunnel_key, int addr_family) +{ + return lr_lb_address_set_name_(lr_tunnel_key, "", addr_family); +} + +/* Builds a string that refers to the the router's load balancer VIP address + * set name, that is: $<address_set_name>. + */ +char * +lr_lb_address_set_ref(uint32_t lr_tunnel_key, int addr_family) +{ + return lr_lb_address_set_name_(lr_tunnel_key, "$", addr_family); +} diff --git a/lib/ovn-util.h b/lib/ovn-util.h index a1f1cf0ad..809ff1d36 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -315,4 +315,7 @@ void daemon_started_recently_ignore(void); bool daemon_started_recently(void); int64_t daemon_startup_ts(void); +char *lr_lb_address_set_name(uint32_t lr_tunnel_key, int addr_family); +char *lr_lb_address_set_ref(uint32_t lr_tunnel_key, int addr_family); + #endif /* OVN_UTIL_H */ diff --git a/northd/automake.mk b/northd/automake.mk index 81582867d..b7cfccf36 100644 --- a/northd/automake.mk +++ b/northd/automake.mk @@ -10,6 +10,10 @@ northd_ovn_northd_SOURCES = \ northd/en-northd.h \ northd/en-lflow.c \ northd/en-lflow.h \ + northd/en-northd-output.c \ + northd/en-northd-output.h \ + northd/en-sync-sb.c \ + northd/en-sync-sb.h \ northd/inc-proc-northd.c \ northd/inc-proc-northd.h \ northd/ipam.c \ diff --git a/northd/en-northd-output.c b/northd/en-northd-output.c new file mode 100644 index 000000000..cdb2f9558 --- /dev/null +++ b/northd/en-northd-output.c @@ -0,0 +1,58 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include <getopt.h> +#include <stdlib.h> +#include <stdio.h> + +#include "openvswitch/util.h" + +#include "en-northd-output.h" +#include "lib/inc-proc-eng.h" + +void * +en_northd_output_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + return NULL; +} + +void +en_northd_output_run(struct engine_node *node, void *data OVS_UNUSED) +{ + engine_set_node_state(node, EN_UPDATED); +} + +void +en_northd_output_cleanup(void *data OVS_UNUSED) +{ + +} + +bool +northd_output_sync_to_sb_handler(struct engine_node *node, + void *data OVS_UNUSED) +{ + engine_set_node_state(node, EN_UPDATED); + return true; +} + +bool +northd_output_lflow_handler(struct engine_node *node, void *data OVS_UNUSED) +{ + engine_set_node_state(node, EN_UPDATED); + return true; +} diff --git a/northd/en-northd-output.h b/northd/en-northd-output.h new file mode 100644 index 000000000..d0079ea67 --- /dev/null +++ b/northd/en-northd-output.h @@ -0,0 +1,17 @@ +#ifndef EN_NORTHD_OUTPUT_H +#define EN_NORTHD_OUTPUT_H 1 + +#include "lib/inc-proc-eng.h" + +void *en_northd_output_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED); +void en_northd_output_run(struct engine_node *node OVS_UNUSED, + void *data OVS_UNUSED); + +void en_northd_output_cleanup(void *data); +bool northd_output_sync_to_sb_handler(struct engine_node *node, + void *data OVS_UNUSED); +bool northd_output_lflow_handler(struct engine_node *node, + void *data OVS_UNUSED); + +#endif diff --git a/northd/en-northd.c b/northd/en-northd.c index 7fe83db64..93891b0b7 100644 --- a/northd/en-northd.c +++ b/northd/en-northd.c @@ -72,8 +72,6 @@ void en_northd_run(struct engine_node *node, void *data) EN_OVSDB_GET(engine_get_input("NB_load_balancer_group", node)); input_data.nbrec_port_group_table = EN_OVSDB_GET(engine_get_input("NB_port_group", node)); - input_data.nbrec_address_set_table = - EN_OVSDB_GET(engine_get_input("NB_address_set", node)); input_data.nbrec_meter_table = EN_OVSDB_GET(engine_get_input("NB_meter", node)); input_data.nbrec_acl_table = @@ -99,8 +97,6 @@ void en_northd_run(struct engine_node *node, void *data) EN_OVSDB_GET(engine_get_input("SB_load_balancer", node)); input_data.sbrec_service_monitor_table = EN_OVSDB_GET(engine_get_input("SB_service_monitor", node)); - input_data.sbrec_address_set_table = - EN_OVSDB_GET(engine_get_input("SB_address_set", node)); input_data.sbrec_port_group_table = EN_OVSDB_GET(engine_get_input("SB_port_group", node)); input_data.sbrec_meter_table = diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c new file mode 100644 index 000000000..6e8182f42 --- /dev/null +++ b/northd/en-sync-sb.c @@ -0,0 +1,233 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include <getopt.h> +#include <stdlib.h> +#include <stdio.h> + +#include "lib/svec.h" +#include "openvswitch/util.h" + +#include "en-sync-sb.h" +#include "lib/inc-proc-eng.h" +#include "lib/lb.h" +#include "lib/ovn-nb-idl.h" +#include "lib/ovn-sb-idl.h" +#include "lib/ovn-util.h" +#include "northd.h" + +#include "openvswitch/vlog.h" + +VLOG_DEFINE_THIS_MODULE(en_sync_to_sb); + +static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, + const char **addrs, size_t n_addrs, + struct shash *sb_address_sets); +static void sync_addr_sets(const struct nbrec_address_set_table *, + const struct nbrec_port_group_table *, + const struct sbrec_address_set_table *, + struct ovsdb_idl_txn *ovnsb_txn, + struct hmap *datapaths); + +void * +en_sync_to_sb_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + return NULL; +} + +void +en_sync_to_sb_run(struct engine_node *node, void *data OVS_UNUSED) +{ + engine_set_node_state(node, EN_UPDATED); +} + +void +en_sync_to_sb_cleanup(void *data OVS_UNUSED) +{ + +} + +void * +en_sync_to_sb_addr_set_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + return NULL; +} + +void +en_sync_to_sb_addr_set_run(struct engine_node *node, void *data OVS_UNUSED) +{ + const struct nbrec_address_set_table *nb_address_set_table = + EN_OVSDB_GET(engine_get_input("NB_address_set", node)); + const struct nbrec_port_group_table *nb_port_group_table = + EN_OVSDB_GET(engine_get_input("NB_port_group", node)); + const struct sbrec_address_set_table *sb_address_set_table = + EN_OVSDB_GET(engine_get_input("SB_address_set", node)); + + const struct engine_context *eng_ctx = engine_get_context(); + struct northd_data *northd_data = engine_get_input_data("northd", node); + + sync_addr_sets(nb_address_set_table, nb_port_group_table, + sb_address_set_table, eng_ctx->ovnsb_idl_txn, + &northd_data->datapaths); + + engine_set_node_state(node, EN_UPDATED); +} + +void +en_sync_to_sb_addr_set_cleanup(void *data OVS_UNUSED) +{ + +} + +/* static functions. */ +static void +sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, + const char **addrs, size_t n_addrs, + struct shash *sb_address_sets) +{ + const struct sbrec_address_set *sb_address_set; + sb_address_set = shash_find_and_delete(sb_address_sets, + name); + if (!sb_address_set) { + sb_address_set = sbrec_address_set_insert(ovnsb_txn); + sbrec_address_set_set_name(sb_address_set, name); + } + + sbrec_address_set_set_addresses(sb_address_set, + addrs, n_addrs); +} + +/* OVN_Southbound Address_Set table contains same records as in north + * bound, plus + * - the records generated from Port_Group table in north bound. + * + * There are 2 records generated from each port group, one for IPv4, and + * one for IPv6, named in the format: <port group name>_ip4 and + * <port group name>_ip6 respectively. MAC addresses are ignored. + * + * - the records generated for the load balancer VIP addresses which are + * routable from each logical router. + * + * We always update OVN_Southbound to match the Address_Set and Port_Group + * in OVN_Northbound, so that the address sets used in Logical_Flows in + * OVN_Southbound is checked against the proper set.*/ +static void +sync_addr_sets(const struct nbrec_address_set_table *nb_address_set_table, + const struct nbrec_port_group_table *nb_port_group_table, + const struct sbrec_address_set_table *sb_address_set_table, + struct ovsdb_idl_txn *ovnsb_txn, struct hmap *datapaths) +{ + struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets); + + const struct sbrec_address_set *sb_address_set; + SBREC_ADDRESS_SET_TABLE_FOR_EACH (sb_address_set, + sb_address_set_table) { + shash_add(&sb_address_sets, sb_address_set->name, sb_address_set); + } + + /* Service monitor MAC. */ + const char *svc_monitor_macp = northd_get_svc_monitor_mac(); + sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc_monitor_macp, 1, + &sb_address_sets); + + /* sync port group generated address sets first */ + const struct nbrec_port_group *nb_port_group; + NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_port_group, + nb_port_group_table) { + struct svec ipv4_addrs = SVEC_EMPTY_INITIALIZER; + struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; + for (size_t i = 0; i < nb_port_group->n_ports; i++) { + for (size_t j = 0; j < nb_port_group->ports[i]->n_addresses; j++) { + const char *addrs = nb_port_group->ports[i]->addresses[j]; + if (!is_dynamic_lsp_address(addrs)) { + split_addresses(addrs, &ipv4_addrs, &ipv6_addrs); + } + } + if (nb_port_group->ports[i]->dynamic_addresses) { + split_addresses(nb_port_group->ports[i]->dynamic_addresses, + &ipv4_addrs, &ipv6_addrs); + } + } + char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); + char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); + sync_addr_set(ovnsb_txn, ipv4_addrs_name, + /* "char **" is not compatible with "const char **" */ + (const char **) ipv4_addrs.names, + ipv4_addrs.n, &sb_address_sets); + sync_addr_set(ovnsb_txn, ipv6_addrs_name, + /* "char **" is not compatible with "const char **" */ + (const char **) ipv6_addrs.names, + ipv6_addrs.n, &sb_address_sets); + free(ipv4_addrs_name); + free(ipv6_addrs_name); + svec_destroy(&ipv4_addrs); + svec_destroy(&ipv6_addrs); + } + + /* Sync router load balancer VIP generated address sets. */ + struct ovn_datapath *od; + HMAP_FOR_EACH (od, key_node, datapaths) { + if (!od->nbr) { + continue; + } + + if (sset_count(&od->lb_ips->ips_v4_reachable)) { + char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key, + AF_INET); + const char **ipv4_addrs = + sset_array(&od->lb_ips->ips_v4_reachable); + + sync_addr_set(ovnsb_txn, ipv4_addrs_name, ipv4_addrs, + sset_count(&od->lb_ips->ips_v4_reachable), + &sb_address_sets); + free(ipv4_addrs_name); + free(ipv4_addrs); + } + + if (sset_count(&od->lb_ips->ips_v6_reachable)) { + char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key, + AF_INET6); + const char **ipv6_addrs = + sset_array(&od->lb_ips->ips_v6_reachable); + + sync_addr_set(ovnsb_txn, ipv6_addrs_name, ipv6_addrs, + sset_count(&od->lb_ips->ips_v6_reachable), + &sb_address_sets); + free(ipv6_addrs_name); + free(ipv6_addrs); + } + } + + /* sync user defined address sets, which may overwrite port group + * generated address sets if same name is used */ + const struct nbrec_address_set *nb_address_set; + NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, + nb_address_set_table) { + sync_addr_set(ovnsb_txn, nb_address_set->name, + /* "char **" is not compatible with "const char **" */ + (const char **) nb_address_set->addresses, + nb_address_set->n_addresses, &sb_address_sets); + } + + struct shash_node *node; + SHASH_FOR_EACH_SAFE (node, &sb_address_sets) { + sbrec_address_set_delete(node->data); + shash_delete(&sb_address_sets, node); + } + shash_destroy(&sb_address_sets); +} diff --git a/northd/en-sync-sb.h b/northd/en-sync-sb.h new file mode 100644 index 000000000..1b25ff90f --- /dev/null +++ b/northd/en-sync-sb.h @@ -0,0 +1,14 @@ +#ifndef EN_SYNC_SB_H +#define EN_SYNC_SB_H 1 + +#include "lib/inc-proc-eng.h" + +void *en_sync_to_sb_init(struct engine_node *, struct engine_arg *); +void en_sync_to_sb_run(struct engine_node *, void *data); +void en_sync_to_sb_cleanup(void *data); + +void *en_sync_to_sb_addr_set_init(struct engine_node *, struct engine_arg *); +void en_sync_to_sb_addr_set_run(struct engine_node *, void *data); +void en_sync_to_sb_addr_set_cleanup(void *data); + +#endif /* end of EN_SYNC_SB_H */ diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index 54e0ad3b0..dbba41127 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -32,6 +32,8 @@ #include "inc-proc-northd.h" #include "en-northd.h" #include "en-lflow.h" +#include "en-northd-output.h" +#include "en-sync-sb.h" #include "util.h" VLOG_DEFINE_THIS_MODULE(inc_proc_northd); @@ -153,6 +155,9 @@ static ENGINE_NODE(northd, "northd"); static ENGINE_NODE(lflow, "lflow"); static ENGINE_NODE(mac_binding_aging, "mac_binding_aging"); static ENGINE_NODE(mac_binding_aging_waker, "mac_binding_aging_waker"); +static ENGINE_NODE(northd_output, "northd_output"); +static ENGINE_NODE(sync_to_sb, "sync_to_sb"); +static ENGINE_NODE(sync_to_sb_addr_set, "sync_to_sb_addr_set"); void inc_proc_northd_init(struct ovsdb_idl_loop *nb, struct ovsdb_idl_loop *sb) @@ -164,7 +169,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_northd, &en_nb_logical_switch, NULL); engine_add_input(&en_northd, &en_nb_logical_switch_port, NULL); engine_add_input(&en_northd, &en_nb_forwarding_group, NULL); - engine_add_input(&en_northd, &en_nb_address_set, NULL); engine_add_input(&en_northd, &en_nb_port_group, NULL); engine_add_input(&en_northd, &en_nb_load_balancer, NULL); engine_add_input(&en_northd, &en_nb_load_balancer_group, NULL); @@ -191,7 +195,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_northd, &en_sb_chassis, NULL); engine_add_input(&en_northd, &en_sb_chassis_private, NULL); engine_add_input(&en_northd, &en_sb_encap, NULL); - engine_add_input(&en_northd, &en_sb_address_set, NULL); engine_add_input(&en_northd, &en_sb_port_group, NULL); engine_add_input(&en_northd, &en_sb_logical_dp_group, NULL); engine_add_input(&en_northd, &en_sb_meter, NULL); @@ -229,6 +232,21 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, * once I-P engine allows multiple root nodes. */ engine_add_input(&en_lflow, &en_mac_binding_aging, NULL); + engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set, NULL); + engine_add_input(&en_sync_to_sb_addr_set, &en_nb_port_group, NULL); + engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL); + engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL); + + /* en_sync_to_sb engine node syncs the SB database tables from + * the NB database tables. + * Right now this engine only syncs the SB Address_Set table. + */ + engine_add_input(&en_sync_to_sb, &en_sync_to_sb_addr_set, NULL); + engine_add_input(&en_northd_output, &en_sync_to_sb, + northd_output_sync_to_sb_handler); + engine_add_input(&en_northd_output, &en_lflow, + northd_output_lflow_handler); + struct engine_arg engine_arg = { .nb_idl = nb->idl, .sb_idl = sb->idl, @@ -249,7 +267,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, struct ovsdb_idl_index *sbrec_mac_binding_by_datapath = mac_binding_by_datapath_index_create(sb->idl); - engine_init(&en_lflow, &engine_arg); + engine_init(&en_northd_output, &engine_arg); engine_ovsdb_node_add_index(&en_sb_chassis, "sbrec_chassis_by_name", diff --git a/northd/northd.c b/northd/northd.c index 00ff8f933..e5db55451 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -808,37 +808,6 @@ lr_has_lb_vip(struct ovn_datapath *od) return false; } -/* Builds a unique address set compatible name ([a-zA-Z_.][a-zA-Z_.0-9]*) - * for the router's load balancer VIP address set, combining the logical - * router's datapath tunnel key and address family. - * - * Also prefixes the name with 'prefix'. - */ -static char * -lr_lb_address_set_name_(const struct ovn_datapath *od, const char *prefix, - int addr_family) -{ - ovs_assert(od->nbr); - return xasprintf("%s_rtr_lb_%"PRIu32"_ip%s", prefix, od->tunnel_key, - addr_family == AF_INET ? "4" : "6"); -} - -/* Builds the router's load balancer VIP address set name. */ -static char * -lr_lb_address_set_name(const struct ovn_datapath *od, int addr_family) -{ - return lr_lb_address_set_name_(od, "", addr_family); -} - -/* Builds a string that refers to the the router's load balancer VIP address - * set name, that is: $<address_set_name>. - */ -static char * -lr_lb_address_set_ref(const struct ovn_datapath *od, int addr_family) -{ - return lr_lb_address_set_name_(od, "$", addr_family); -} - static void init_lb_for_datapath(struct ovn_datapath *od) { @@ -13141,7 +13110,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, } /* Create a single ARP rule for all IPs that are used as VIPs. */ - char *lb_ips_v4_as = lr_lb_address_set_ref(op->od, AF_INET); + char *lb_ips_v4_as = lr_lb_address_set_ref(op->od->tunnel_key, + AF_INET); build_lrouter_arp_flow(op->od, op, lb_ips_v4_as, REG_INPORT_ETH_ADDR, match, false, 90, NULL, lflows); @@ -13157,7 +13127,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, } /* Create a single ND rule for all IPs that are used as VIPs. */ - char *lb_ips_v6_as = lr_lb_address_set_ref(op->od, AF_INET6); + char *lb_ips_v6_as = lr_lb_address_set_ref(op->od->tunnel_key, + AF_INET6); build_lrouter_nd_flow(op->od, op, "nd_na", lb_ips_v6_as, NULL, REG_INPORT_ETH_ADDR, match, false, 90, NULL, lflows, meter_groups); @@ -14918,136 +14889,6 @@ void build_lflows(struct lflow_input *input_data, hmap_destroy(&mcast_groups); } -static void -sync_address_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, - const char **addrs, size_t n_addrs, - struct shash *sb_address_sets) -{ - const struct sbrec_address_set *sb_address_set; - sb_address_set = shash_find_and_delete(sb_address_sets, - name); - if (!sb_address_set) { - sb_address_set = sbrec_address_set_insert(ovnsb_txn); - sbrec_address_set_set_name(sb_address_set, name); - } - - sbrec_address_set_set_addresses(sb_address_set, - addrs, n_addrs); -} - -/* OVN_Southbound Address_Set table contains same records as in north - * bound, plus the records generated from Port_Group table in north bound. - * - * There are 2 records generated from each port group, one for IPv4, and - * one for IPv6, named in the format: <port group name>_ip4 and - * <port group name>_ip6 respectively. MAC addresses are ignored. - * - * We always update OVN_Southbound to match the Address_Set and Port_Group - * in OVN_Northbound, so that the address sets used in Logical_Flows in - * OVN_Southbound is checked against the proper set.*/ -static void -sync_address_sets(struct northd_input *input_data, - struct ovsdb_idl_txn *ovnsb_txn, - struct hmap *datapaths) -{ - struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets); - - const struct sbrec_address_set *sb_address_set; - SBREC_ADDRESS_SET_TABLE_FOR_EACH (sb_address_set, - input_data->sbrec_address_set_table) { - shash_add(&sb_address_sets, sb_address_set->name, sb_address_set); - } - - /* Service monitor MAC. */ - const char *svc_monitor_macp = svc_monitor_mac; - sync_address_set(ovnsb_txn, "svc_monitor_mac", &svc_monitor_macp, 1, - &sb_address_sets); - - /* sync port group generated address sets first */ - const struct nbrec_port_group *nb_port_group; - NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_port_group, - input_data->nbrec_port_group_table) { - struct svec ipv4_addrs = SVEC_EMPTY_INITIALIZER; - struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; - for (size_t i = 0; i < nb_port_group->n_ports; i++) { - for (size_t j = 0; j < nb_port_group->ports[i]->n_addresses; j++) { - const char *addrs = nb_port_group->ports[i]->addresses[j]; - if (!is_dynamic_lsp_address(addrs)) { - split_addresses(addrs, &ipv4_addrs, &ipv6_addrs); - } - } - if (nb_port_group->ports[i]->dynamic_addresses) { - split_addresses(nb_port_group->ports[i]->dynamic_addresses, - &ipv4_addrs, &ipv6_addrs); - } - } - char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); - char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); - sync_address_set(ovnsb_txn, ipv4_addrs_name, - /* "char **" is not compatible with "const char **" */ - (const char **)ipv4_addrs.names, - ipv4_addrs.n, &sb_address_sets); - sync_address_set(ovnsb_txn, ipv6_addrs_name, - /* "char **" is not compatible with "const char **" */ - (const char **)ipv6_addrs.names, - ipv6_addrs.n, &sb_address_sets); - free(ipv4_addrs_name); - free(ipv6_addrs_name); - svec_destroy(&ipv4_addrs); - svec_destroy(&ipv6_addrs); - } - - /* Sync router load balancer VIP generated address sets. */ - struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbr) { - continue; - } - - if (sset_count(&od->lb_ips->ips_v4_reachable)) { - char *ipv4_addrs_name = lr_lb_address_set_name(od, AF_INET); - const char **ipv4_addrs = - sset_array(&od->lb_ips->ips_v4_reachable); - - sync_address_set(ovnsb_txn, ipv4_addrs_name, ipv4_addrs, - sset_count(&od->lb_ips->ips_v4_reachable), - &sb_address_sets); - free(ipv4_addrs_name); - free(ipv4_addrs); - } - - if (sset_count(&od->lb_ips->ips_v6_reachable)) { - char *ipv6_addrs_name = lr_lb_address_set_name(od, AF_INET6); - const char **ipv6_addrs = - sset_array(&od->lb_ips->ips_v6_reachable); - - sync_address_set(ovnsb_txn, ipv6_addrs_name, ipv6_addrs, - sset_count(&od->lb_ips->ips_v6_reachable), - &sb_address_sets); - free(ipv6_addrs_name); - free(ipv6_addrs); - } - } - - /* sync user defined address sets, which may overwrite port group - * generated address sets if same name is used */ - const struct nbrec_address_set *nb_address_set; - NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, - input_data->nbrec_address_set_table) { - sync_address_set(ovnsb_txn, nb_address_set->name, - /* "char **" is not compatible with "const char **" */ - (const char **)nb_address_set->addresses, - nb_address_set->n_addresses, &sb_address_sets); - } - - struct shash_node *node; - SHASH_FOR_EACH_SAFE (node, &sb_address_sets) { - sbrec_address_set_delete(node->data); - shash_delete(&sb_address_sets, node); - } - shash_destroy(&sb_address_sets); -} - /* Each port group in Port_Group table in OVN_Northbound has a corresponding * entry in Port_Group table in OVN_Southbound. In OVN_Northbound the entries * contains lport uuids, while in OVN_Southbound we store the lport names. @@ -15918,7 +15759,6 @@ ovnnb_db_run(struct northd_input *input_data, ovn_update_ipv6_prefix(&data->ports); sync_lbs(input_data, ovnsb_txn, &data->datapaths, &data->lbs); - sync_address_sets(input_data, ovnsb_txn, &data->datapaths); sync_port_groups(input_data, ovnsb_txn, &data->port_groups); sync_meters(input_data, ovnsb_txn, &data->meter_groups); sync_dns_entries(input_data, ovnsb_txn, &data->datapaths); @@ -16195,3 +16035,8 @@ void northd_run(struct northd_input *input_data, stopwatch_stop(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec()); } +const char * +northd_get_svc_monitor_mac(void) +{ + return svc_monitor_mac; +} diff --git a/northd/northd.h b/northd/northd.h index da90e2815..ea9bd5797 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -31,7 +31,6 @@ struct northd_input { const struct nbrec_load_balancer_group_table *nbrec_load_balancer_group_table; const struct nbrec_port_group_table *nbrec_port_group_table; - const struct nbrec_address_set_table *nbrec_address_set_table; const struct nbrec_meter_table *nbrec_meter_table; const struct nbrec_acl_table *nbrec_acl_table; const struct nbrec_static_mac_binding_table @@ -47,7 +46,6 @@ struct northd_input { const struct sbrec_fdb_table *sbrec_fdb_table; const struct sbrec_load_balancer_table *sbrec_load_balancer_table; const struct sbrec_service_monitor_table *sbrec_service_monitor_table; - const struct sbrec_address_set_table *sbrec_address_set_table; const struct sbrec_port_group_table *sbrec_port_group_table; const struct sbrec_meter_table *sbrec_meter_table; const struct sbrec_dns_table *sbrec_dns_table; @@ -281,4 +279,5 @@ void bfd_cleanup_connections(struct lflow_input *input_data, struct hmap *bfd_map); void run_update_worker_pool(int n_threads); +const char *northd_get_svc_monitor_mac(void); #endif /* NORTHD_H */