@@ -3343,6 +3343,318 @@ en_bfd_chassis_cleanup(void *data OVS_UNUSED){
sset_destroy(&bfd_chassis->bfd_chassis);
}
+static void *
+en_nat_addresses_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ struct ed_type_nat_addresses *data = xzalloc(sizeof *data);
+ shash_init(&data->nat_addresses);
+ sset_init(&data->localnet_vifs);
+ sset_init(&data->local_l3gw_ports);
+ sset_init(&data->nat_ip_keys);
+ return data;
+}
+
+/* Extracts the mac, IPv4 and IPv6 addresses, and logical port from
+ * 'addresses' which should be of the format 'MAC [IP1 IP2 ..]
+ * [is_chassis_resident("LPORT_NAME")]', where IPn should be a valid IPv4
+ * or IPv6 address, and stores them in the 'ipv4_addrs' and 'ipv6_addrs'
+ * fields of 'laddrs'. The logical port name is stored in 'lport'.
+ *
+ * Returns true if at least 'MAC' is found in 'address', false otherwise.
+ *
+ * The caller must call destroy_lport_addresses() and free(*lport). */
+static bool
+extract_addresses_with_port(const char *addresses,
+ struct lport_addresses *laddrs,
+ char **lport)
+{
+ int ofs;
+ if (!extract_addresses(addresses, laddrs, &ofs)) {
+ return false;
+ } else if (!addresses[ofs]) {
+ return true;
+ }
+
+ struct lexer lexer;
+ lexer_init(&lexer, addresses + ofs);
+ lexer_get(&lexer);
+
+ if (lexer.error || lexer.token.type != LEX_T_ID
+ || !lexer_match_id(&lexer, "is_chassis_resident")) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", addresses);
+ lexer_destroy(&lexer);
+ return true;
+ }
+
+ if (!lexer_match(&lexer, LEX_T_LPAREN)) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_INFO_RL(&rl, "Syntax error: expecting '(' after "
+ "'is_chassis_resident' in address '%s'", addresses);
+ lexer_destroy(&lexer);
+ return false;
+ }
+
+ if (lexer.token.type != LEX_T_STRING) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_INFO_RL(&rl,
+ "Syntax error: expecting quoted string after "
+ "'is_chassis_resident' in address '%s'", addresses);
+ lexer_destroy(&lexer);
+ return false;
+ }
+
+ *lport = xstrdup(lexer.token.s);
+
+ lexer_get(&lexer);
+ if (!lexer_match(&lexer, LEX_T_RPAREN)) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_INFO_RL(&rl, "Syntax error: expecting ')' after quoted string in "
+ "'is_chassis_resident()' in address '%s'",
+ addresses);
+ lexer_destroy(&lexer);
+ return false;
+ }
+
+ lexer_destroy(&lexer);
+ return true;
+}
+
+static void
+consider_nat_address(struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const char *nat_address,
+ const struct sbrec_port_binding *pb,
+ struct sset *nat_address_keys,
+ const struct sbrec_chassis *chassis,
+ const struct sset *active_tunnels,
+ struct shash *nat_addresses)
+{
+ struct lport_addresses *laddrs = xmalloc(sizeof *laddrs);
+ char *lport = NULL;
+ if (!extract_addresses_with_port(nat_address, laddrs, &lport)
+ || (!lport && !strcmp(pb->type, "patch"))
+ || (lport && !lport_is_chassis_resident(
+ sbrec_port_binding_by_name, chassis,
+ active_tunnels, lport))) {
+ destroy_lport_addresses(laddrs);
+ free(laddrs);
+ free(lport);
+ return;
+ }
+ free(lport);
+
+ int i;
+ for (i = 0; i < laddrs->n_ipv4_addrs; i++) {
+ char *name = xasprintf("%s-%s", pb->logical_port,
+ laddrs->ipv4_addrs[i].addr_s);
+ sset_add(nat_address_keys, name);
+ free(name);
+ }
+ if (laddrs->n_ipv4_addrs == 0) {
+ char *name = xasprintf("%s-noip", pb->logical_port);
+ sset_add(nat_address_keys, name);
+ free(name);
+ }
+ shash_add(nat_addresses, pb->logical_port, laddrs);
+}
+
+static void
+get_nat_addresses_and_keys(struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ struct sset *nat_address_keys,
+ struct sset *local_l3gw_ports,
+ const struct sbrec_chassis *chassis,
+ const struct sset *active_tunnels,
+ struct shash *nat_addresses)
+{
+ const char *gw_port;
+ SSET_FOR_EACH(gw_port, local_l3gw_ports) {
+ const struct sbrec_port_binding *pb;
+
+ pb = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
+ if (!pb) {
+ continue;
+ }
+
+ if (pb->n_nat_addresses) {
+ for (int i = 0; i < pb->n_nat_addresses; i++) {
+ consider_nat_address(sbrec_port_binding_by_name,
+ pb->nat_addresses[i], pb,
+ nat_address_keys, chassis,
+ active_tunnels,
+ nat_addresses);
+ }
+ } else {
+ /* Continue to support options:nat-addresses for version
+ * upgrade. */
+ const char *nat_addresses_options = smap_get(&pb->options,
+ "nat-addresses");
+ if (nat_addresses_options) {
+ consider_nat_address(sbrec_port_binding_by_name,
+ nat_addresses_options, pb,
+ nat_address_keys, chassis,
+ active_tunnels,
+ nat_addresses);
+ }
+ }
+ }
+}
+
+/* Get localnet vifs, local l3gw ports and ofport for localnet patch ports. */
+static void
+get_localnet_vifs_l3gwports(
+ struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
+ struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const struct ovsrec_bridge *br_int,
+ const struct sbrec_chassis *chassis,
+ const struct hmap *local_datapaths,
+ struct sset *localnet_vifs,
+ struct sset *local_l3gw_ports)
+{
+ for (int i = 0; i < br_int->n_ports; i++) {
+ const struct ovsrec_port *port_rec = br_int->ports[i];
+ if (!strcmp(port_rec->name, br_int->name)) {
+ continue;
+ }
+ const char *tunnel_id = smap_get(&port_rec->external_ids,
+ "ovn-chassis-id");
+ if (tunnel_id &&
+ encaps_tunnel_id_match(tunnel_id, chassis->name, NULL, NULL)) {
+ continue;
+ }
+ const char *localnet = smap_get(&port_rec->external_ids,
+ "ovn-localnet-port");
+ if (localnet) {
+ continue;
+ }
+ for (int j = 0; j < port_rec->n_interfaces; j++) {
+ const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
+ if (!iface_rec->n_ofport) {
+ continue;
+ }
+ /* Get localnet vif. */
+ const char *iface_id = smap_get(&iface_rec->external_ids,
+ "iface-id");
+ if (!iface_id) {
+ continue;
+ }
+ const struct sbrec_port_binding *pb
+ = lport_lookup_by_name(sbrec_port_binding_by_name, iface_id);
+ if (!pb || pb->chassis != chassis) {
+ continue;
+ }
+ if (!iface_rec->link_state ||
+ strcmp(iface_rec->link_state, "up")) {
+ continue;
+ }
+ struct local_datapath *ld
+ = get_local_datapath(local_datapaths,
+ pb->datapath->tunnel_key);
+ if (ld && ld->localnet_port) {
+ sset_add(localnet_vifs, iface_id);
+ }
+ }
+ }
+
+ struct sbrec_port_binding *target = sbrec_port_binding_index_init_row(
+ sbrec_port_binding_by_datapath);
+
+ const struct local_datapath *ld;
+ HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
+ const struct sbrec_port_binding *pb;
+
+ if (!ld->localnet_port) {
+ continue;
+ }
+
+ /* Get l3gw ports. Consider port bindings with type "l3gateway"
+ * that connect to gateway routers (if local), and consider port
+ * bindings of type "patch" since they might connect to
+ * distributed gateway ports with NAT addresses. */
+
+ sbrec_port_binding_index_set_datapath(target, ld->datapath);
+ SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
+ sbrec_port_binding_by_datapath) {
+ if ((!strcmp(pb->type, "l3gateway") && pb->chassis == chassis)
+ || !strcmp(pb->type, "patch")) {
+ sset_add(local_l3gw_ports, pb->logical_port);
+ }
+ }
+ }
+ sbrec_port_binding_index_destroy_row(target);
+}
+
+static void
+en_nat_addresses_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+ struct ed_type_nat_addresses *nat_addresses = data;
+ const struct ovsrec_open_vswitch_table *ovs_table =
+ EN_OVSDB_GET(engine_get_input("OVS_open_vswitch", node));
+ const char *chassis_id = get_ovs_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
+ = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+
+ struct ovsdb_idl_index *sbrec_pb_by_datapath =
+ engine_ovsdb_node_get_index(
+ engine_get_input("SB_port_binding", node),
+ "datapath");
+ struct ovsdb_idl_index *sbrec_pb_by_name =
+ engine_ovsdb_node_get_index(
+ engine_get_input("SB_port_binding", node),
+ "name");
+ const struct ovsrec_bridge_table *bridge_table =
+ EN_OVSDB_GET(engine_get_input("OVS_bridge", node));
+ const struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table);
+
+ struct ed_type_runtime_data *rt_data =
+ engine_get_input_data("runtime_data", node);
+ const struct hmap *local_datapaths = &rt_data->local_datapaths;
+ const struct sset *active_tunnels = &rt_data->active_tunnels;
+
+ struct shash_node *nat_node;
+ SHASH_FOR_EACH(nat_node, &nat_addresses->nat_addresses) {
+ struct lport_addresses *laddrs = nat_node->data;
+ destroy_lport_addresses(laddrs);
+ free(laddrs);
+ }
+ shash_clear(&nat_addresses->nat_addresses);
+ sset_clear(&nat_addresses->localnet_vifs);
+ sset_clear(&nat_addresses->local_l3gw_ports);
+ sset_clear(&nat_addresses->nat_ip_keys);
+
+ get_localnet_vifs_l3gwports(sbrec_pb_by_datapath,
+ sbrec_pb_by_name,
+ br_int, chassis, local_datapaths,
+ &nat_addresses->localnet_vifs, &nat_addresses->local_l3gw_ports);
+
+ get_nat_addresses_and_keys(sbrec_pb_by_name,
+ &nat_addresses->nat_ip_keys, &nat_addresses->local_l3gw_ports,
+ chassis, active_tunnels,
+ &nat_addresses->nat_addresses);
+
+ engine_set_node_state(node, EN_UPDATED);
+}
+
+static bool
+nat_addresses_change_handler(struct engine_node *node, void *data)
+{
+ en_nat_addresses_run(node, data);
+ return true;
+}
+
+static void
+en_nat_addresses_cleanup(void *data OVS_UNUSED){
+ struct ed_type_nat_addresses *nat_addresses = data;
+ shash_destroy(&nat_addresses->nat_addresses);
+ sset_destroy(&nat_addresses->localnet_vifs);
+ sset_destroy(&nat_addresses->local_l3gw_ports);
+ sset_destroy(&nat_addresses->nat_ip_keys);
+}
+
/* Engine node which is used to handle the Non VIF data like
* - OVS patch ports
* - Tunnel ports and the related chassis information.
@@ -4762,6 +5074,14 @@ controller_output_bfd_chassis_handler(struct engine_node *node,
return true;
}
+static bool
+controller_output_nat_addresses_handler(struct engine_node *node,
+ void *data OVS_UNUSED)
+{
+ engine_set_node_state(node, EN_UPDATED);
+ return true;
+}
+
/* Handles sbrec_chassis changes.
* If a new chassis is added or removed return false, so that
* flows are recomputed. For any updates, there is no need for
@@ -5075,6 +5395,7 @@ main(int argc, char *argv[])
ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lb_data, "lb_data");
ENGINE_NODE(mac_cache, "mac_cache");
ENGINE_NODE(bfd_chassis, "bfd_chassis");
+ ENGINE_NODE(nat_addresses, "nat_addresses");
#define SB_NODE(NAME, NAME_STR) ENGINE_NODE_SB(NAME, NAME_STR);
SB_NODES
@@ -5119,6 +5440,12 @@ main(int argc, char *argv[])
engine_add_input(&en_bfd_chassis, &en_sb_chassis, NULL);
engine_add_input(&en_bfd_chassis, &en_sb_ha_chassis_group, NULL);
+ engine_add_input(&en_nat_addresses, &en_ovs_open_vswitch, NULL);
+ engine_add_input(&en_nat_addresses, &en_ovs_bridge, NULL);
+ engine_add_input(&en_nat_addresses, &en_sb_chassis, NULL);
+ engine_add_input(&en_nat_addresses, &en_sb_port_binding, nat_addresses_change_handler);
+ engine_add_input(&en_nat_addresses, &en_runtime_data, nat_addresses_change_handler);
+
/* Note: The order of inputs is important, all OVS interface changes must
* be handled before any ct_zone changes.
*/
@@ -5277,6 +5604,8 @@ main(int argc, char *argv[])
controller_output_mac_cache_handler);
engine_add_input(&en_controller_output, &en_bfd_chassis,
controller_output_bfd_chassis_handler);
+ engine_add_input(&en_controller_output, &en_nat_addresses,
+ controller_output_nat_addresses_handler);
struct engine_arg engine_arg = {
.sb_idl = ovnsb_idl_loop.idl,
@@ -5323,6 +5652,8 @@ main(int argc, char *argv[])
engine_get_internal_data(&en_ct_zones);
struct ed_type_bfd_chassis *bfd_chassis_data =
engine_get_internal_data(&en_bfd_chassis);
+ struct ed_type_nat_addresses *nat_addresses_data =
+ engine_get_internal_data(&en_nat_addresses);
struct ed_type_runtime_data *runtime_data =
engine_get_internal_data(&en_runtime_data);
struct ed_type_template_vars *template_vars_data =
@@ -5656,6 +5987,7 @@ main(int argc, char *argv[])
}
runtime_data = engine_get_data(&en_runtime_data);
+ nat_addresses_data = engine_get_data(&en_nat_addresses);
if (runtime_data) {
stopwatch_start(PATCH_RUN_STOPWATCH_NAME, time_msec());
patch_run(ovs_idl_txn,
@@ -5703,7 +6035,6 @@ main(int argc, char *argv[])
pinctrl_update(ovnsb_idl_loop.idl);
pinctrl_run(ovnsb_idl_txn,
sbrec_datapath_binding_by_key,
- sbrec_port_binding_by_datapath,
sbrec_port_binding_by_key,
sbrec_port_binding_by_name,
sbrec_mac_binding_by_lport_ip,
@@ -5718,13 +6049,14 @@ main(int argc, char *argv[])
sbrec_mac_binding_table_get(
ovnsb_idl_loop.idl),
sbrec_bfd_table_get(ovnsb_idl_loop.idl),
- br_int, chassis,
+ chassis,
&runtime_data->local_datapaths,
&runtime_data->active_tunnels,
&runtime_data->local_active_ports_ipv6_pd,
&runtime_data->local_active_ports_ras,
ovsrec_open_vswitch_table_get(
- ovs_idl_loop.idl));
+ ovs_idl_loop.idl),
+ nat_addresses_data);
stopwatch_stop(PINCTRL_RUN_STOPWATCH_NAME,
time_msec());
mirror_run(ovs_idl_txn,
@@ -233,14 +233,11 @@ static void destroy_send_garps_rarps(void);
static void send_garp_rarp_wait(long long int send_garp_rarp_time);
static void send_garp_rarp_prepare(
struct ovsdb_idl_txn *ovnsb_idl_txn,
- struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
- const struct ovsrec_bridge *,
- const struct sbrec_chassis *,
const struct hmap *local_datapaths,
- const struct sset *active_tunnels,
- const struct ovsrec_open_vswitch_table *ovs_table)
+ const struct ovsrec_open_vswitch_table *ovs_table,
+ struct ed_type_nat_addresses *nat_addresses)
OVS_REQUIRES(pinctrl_mutex);
static void send_garp_rarp_run(struct rconn *swconn,
long long int *send_garp_rarp_time)
@@ -4134,7 +4131,6 @@ pinctrl_update(const struct ovsdb_idl *idl)
void
pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
- struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_key,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
@@ -4146,13 +4142,13 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
const struct sbrec_service_monitor_table *svc_mon_table,
const struct sbrec_mac_binding_table *mac_binding_table,
const struct sbrec_bfd_table *bfd_table,
- const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *chassis,
const struct hmap *local_datapaths,
const struct sset *active_tunnels,
const struct shash *local_active_ports_ipv6_pd,
const struct shash *local_active_ports_ras,
- const struct ovsrec_open_vswitch_table *ovs_table)
+ const struct ovsrec_open_vswitch_table *ovs_table,
+ struct ed_type_nat_addresses *nat_addresses)
{
ovs_mutex_lock(&pinctrl_mutex);
run_put_mac_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
@@ -4160,10 +4156,11 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
sbrec_mac_binding_by_lport_ip);
run_put_vport_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key,
sbrec_port_binding_by_key, chassis);
- send_garp_rarp_prepare(ovnsb_idl_txn, sbrec_port_binding_by_datapath,
+ send_garp_rarp_prepare(ovnsb_idl_txn,
sbrec_port_binding_by_name,
- sbrec_mac_binding_by_lport_ip, br_int, chassis,
- local_datapaths, active_tunnels, ovs_table);
+ sbrec_mac_binding_by_lport_ip,
+ local_datapaths,
+ ovs_table, nat_addresses);
prepare_ipv6_ras(local_active_ports_ras, sbrec_port_binding_by_name);
prepare_ipv6_prefixd(ovnsb_idl_txn, sbrec_port_binding_by_name,
local_active_ports_ipv6_pd, chassis,
@@ -6289,236 +6286,6 @@ ip_mcast_querier_wait(long long int query_time)
}
}
-/* Get localnet vifs, local l3gw ports and ofport for localnet patch ports. */
-static void
-get_localnet_vifs_l3gwports(
- struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
- struct ovsdb_idl_index *sbrec_port_binding_by_name,
- const struct ovsrec_bridge *br_int,
- const struct sbrec_chassis *chassis,
- const struct hmap *local_datapaths,
- struct sset *localnet_vifs,
- struct sset *local_l3gw_ports)
-{
- for (int i = 0; i < br_int->n_ports; i++) {
- const struct ovsrec_port *port_rec = br_int->ports[i];
- if (!strcmp(port_rec->name, br_int->name)) {
- continue;
- }
- const char *tunnel_id = smap_get(&port_rec->external_ids,
- "ovn-chassis-id");
- if (tunnel_id &&
- encaps_tunnel_id_match(tunnel_id, chassis->name, NULL, NULL)) {
- continue;
- }
- const char *localnet = smap_get(&port_rec->external_ids,
- "ovn-localnet-port");
- if (localnet) {
- continue;
- }
- for (int j = 0; j < port_rec->n_interfaces; j++) {
- const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
- if (!iface_rec->n_ofport) {
- continue;
- }
- /* Get localnet vif. */
- const char *iface_id = smap_get(&iface_rec->external_ids,
- "iface-id");
- if (!iface_id) {
- continue;
- }
- const struct sbrec_port_binding *pb
- = lport_lookup_by_name(sbrec_port_binding_by_name, iface_id);
- if (!pb || pb->chassis != chassis) {
- continue;
- }
- if (!iface_rec->link_state ||
- strcmp(iface_rec->link_state, "up")) {
- continue;
- }
- struct local_datapath *ld
- = get_local_datapath(local_datapaths,
- pb->datapath->tunnel_key);
- if (ld && ld->localnet_port) {
- sset_add(localnet_vifs, iface_id);
- }
- }
- }
-
- struct sbrec_port_binding *target = sbrec_port_binding_index_init_row(
- sbrec_port_binding_by_datapath);
-
- const struct local_datapath *ld;
- HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
- const struct sbrec_port_binding *pb;
-
- if (!ld->localnet_port) {
- continue;
- }
-
- /* Get l3gw ports. Consider port bindings with type "l3gateway"
- * that connect to gateway routers (if local), and consider port
- * bindings of type "patch" since they might connect to
- * distributed gateway ports with NAT addresses. */
-
- sbrec_port_binding_index_set_datapath(target, ld->datapath);
- SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
- sbrec_port_binding_by_datapath) {
- if ((!strcmp(pb->type, "l3gateway") && pb->chassis == chassis)
- || !strcmp(pb->type, "patch")) {
- sset_add(local_l3gw_ports, pb->logical_port);
- }
- }
- }
- sbrec_port_binding_index_destroy_row(target);
-}
-
-
-/* Extracts the mac, IPv4 and IPv6 addresses, and logical port from
- * 'addresses' which should be of the format 'MAC [IP1 IP2 ..]
- * [is_chassis_resident("LPORT_NAME")]', where IPn should be a valid IPv4
- * or IPv6 address, and stores them in the 'ipv4_addrs' and 'ipv6_addrs'
- * fields of 'laddrs'. The logical port name is stored in 'lport'.
- *
- * Returns true if at least 'MAC' is found in 'address', false otherwise.
- *
- * The caller must call destroy_lport_addresses() and free(*lport). */
-static bool
-extract_addresses_with_port(const char *addresses,
- struct lport_addresses *laddrs,
- char **lport)
-{
- int ofs;
- if (!extract_addresses(addresses, laddrs, &ofs)) {
- return false;
- } else if (!addresses[ofs]) {
- return true;
- }
-
- struct lexer lexer;
- lexer_init(&lexer, addresses + ofs);
- lexer_get(&lexer);
-
- if (lexer.error || lexer.token.type != LEX_T_ID
- || !lexer_match_id(&lexer, "is_chassis_resident")) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", addresses);
- lexer_destroy(&lexer);
- return true;
- }
-
- if (!lexer_match(&lexer, LEX_T_LPAREN)) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_INFO_RL(&rl, "Syntax error: expecting '(' after "
- "'is_chassis_resident' in address '%s'", addresses);
- lexer_destroy(&lexer);
- return false;
- }
-
- if (lexer.token.type != LEX_T_STRING) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_INFO_RL(&rl,
- "Syntax error: expecting quoted string after "
- "'is_chassis_resident' in address '%s'", addresses);
- lexer_destroy(&lexer);
- return false;
- }
-
- *lport = xstrdup(lexer.token.s);
-
- lexer_get(&lexer);
- if (!lexer_match(&lexer, LEX_T_RPAREN)) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_INFO_RL(&rl, "Syntax error: expecting ')' after quoted string in "
- "'is_chassis_resident()' in address '%s'",
- addresses);
- lexer_destroy(&lexer);
- return false;
- }
-
- lexer_destroy(&lexer);
- return true;
-}
-
-static void
-consider_nat_address(struct ovsdb_idl_index *sbrec_port_binding_by_name,
- const char *nat_address,
- const struct sbrec_port_binding *pb,
- struct sset *nat_address_keys,
- const struct sbrec_chassis *chassis,
- const struct sset *active_tunnels,
- struct shash *nat_addresses)
-{
- struct lport_addresses *laddrs = xmalloc(sizeof *laddrs);
- char *lport = NULL;
- if (!extract_addresses_with_port(nat_address, laddrs, &lport)
- || (!lport && !strcmp(pb->type, "patch"))
- || (lport && !lport_is_chassis_resident(
- sbrec_port_binding_by_name, chassis,
- active_tunnels, lport))) {
- destroy_lport_addresses(laddrs);
- free(laddrs);
- free(lport);
- return;
- }
- free(lport);
-
- int i;
- for (i = 0; i < laddrs->n_ipv4_addrs; i++) {
- char *name = xasprintf("%s-%s", pb->logical_port,
- laddrs->ipv4_addrs[i].addr_s);
- sset_add(nat_address_keys, name);
- free(name);
- }
- if (laddrs->n_ipv4_addrs == 0) {
- char *name = xasprintf("%s-noip", pb->logical_port);
- sset_add(nat_address_keys, name);
- free(name);
- }
- shash_add(nat_addresses, pb->logical_port, laddrs);
-}
-
-static void
-get_nat_addresses_and_keys(struct ovsdb_idl_index *sbrec_port_binding_by_name,
- struct sset *nat_address_keys,
- struct sset *local_l3gw_ports,
- const struct sbrec_chassis *chassis,
- const struct sset *active_tunnels,
- struct shash *nat_addresses)
-{
- const char *gw_port;
- SSET_FOR_EACH(gw_port, local_l3gw_ports) {
- const struct sbrec_port_binding *pb;
-
- pb = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
- if (!pb) {
- continue;
- }
-
- if (pb->n_nat_addresses) {
- for (int i = 0; i < pb->n_nat_addresses; i++) {
- consider_nat_address(sbrec_port_binding_by_name,
- pb->nat_addresses[i], pb,
- nat_address_keys, chassis,
- active_tunnels,
- nat_addresses);
- }
- } else {
- /* Continue to support options:nat-addresses for version
- * upgrade. */
- const char *nat_addresses_options = smap_get(&pb->options,
- "nat-addresses");
- if (nat_addresses_options) {
- consider_nat_address(sbrec_port_binding_by_name,
- nat_addresses_options, pb,
- nat_address_keys, chassis,
- active_tunnels,
- nat_addresses);
- }
- }
- }
-}
-
static void
send_garp_rarp_wait(long long int send_garp_rarp_time)
{
@@ -6555,96 +6322,65 @@ send_garp_rarp_run(struct rconn *swconn, long long int *send_garp_rarp_time)
* thread context. */
static void
send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn,
- struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
- const struct ovsrec_bridge *br_int,
- const struct sbrec_chassis *chassis,
const struct hmap *local_datapaths,
- const struct sset *active_tunnels,
- const struct ovsrec_open_vswitch_table *ovs_table)
+ const struct ovsrec_open_vswitch_table *ovs_table,
+ struct ed_type_nat_addresses *nat_addresses)
OVS_REQUIRES(pinctrl_mutex)
{
- struct sset localnet_vifs = SSET_INITIALIZER(&localnet_vifs);
- struct sset local_l3gw_ports = SSET_INITIALIZER(&local_l3gw_ports);
- struct sset nat_ip_keys = SSET_INITIALIZER(&nat_ip_keys);
- struct shash nat_addresses;
- unsigned long long garp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT;
- bool garp_continuous = false;
- const struct ovsrec_open_vswitch *cfg =
- ovsrec_open_vswitch_table_first(ovs_table);
- if (cfg) {
- garp_max_timeout = smap_get_ullong(
- &cfg->external_ids, "garp-max-timeout-sec", 0) * 1000;
- garp_continuous = !!garp_max_timeout;
- if (!garp_max_timeout) {
- garp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT;
- }
- }
-
- shash_init(&nat_addresses);
-
- get_localnet_vifs_l3gwports(sbrec_port_binding_by_datapath,
- sbrec_port_binding_by_name,
- br_int, chassis, local_datapaths,
- &localnet_vifs, &local_l3gw_ports);
-
- get_nat_addresses_and_keys(sbrec_port_binding_by_name,
- &nat_ip_keys, &local_l3gw_ports,
- chassis, active_tunnels,
- &nat_addresses);
- /* For deleted ports and deleted nat ips, remove from
- * send_garp_rarp_data. */
- struct shash_node *iter;
- SHASH_FOR_EACH_SAFE (iter, &send_garp_rarp_data) {
- if (!sset_contains(&localnet_vifs, iter->name) &&
- !sset_contains(&nat_ip_keys, iter->name)) {
- send_garp_rarp_delete(iter->name);
+ if (nat_addresses) {
+ unsigned long long garp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT;
+ bool garp_continuous = false;
+
+ const struct ovsrec_open_vswitch *cfg =
+ ovsrec_open_vswitch_table_first(ovs_table);
+ if (cfg) {
+ garp_max_timeout = smap_get_ullong(
+ &cfg->external_ids, "garp-max-timeout-sec", 0) * 1000;
+ garp_continuous = !!garp_max_timeout;
+ if (!garp_max_timeout) {
+ garp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT;
+ }
}
- }
-
- /* Update send_garp_rarp_data. */
- const char *iface_id;
- SSET_FOR_EACH (iface_id, &localnet_vifs) {
- const struct sbrec_port_binding *pb = lport_lookup_by_name(
- sbrec_port_binding_by_name, iface_id);
- if (pb && !smap_get_bool(&pb->options, "disable_garp_rarp", false)) {
- send_garp_rarp_update(ovnsb_idl_txn,
- sbrec_mac_binding_by_lport_ip,
- local_datapaths, pb, &nat_addresses,
- garp_max_timeout, garp_continuous);
+ /* For deleted ports and deleted nat ips, remove from
+ * send_garp_rarp_data. */
+ struct shash_node *iter;
+ SHASH_FOR_EACH_SAFE (iter, &send_garp_rarp_data) {
+ if (!sset_contains(&nat_addresses->localnet_vifs, iter->name) &&
+ !sset_contains(&nat_addresses->nat_ip_keys, iter->name)) {
+ send_garp_rarp_delete(iter->name);
+ }
}
- }
-
- /* Update send_garp_rarp_data for nat-addresses. */
- const char *gw_port;
- SSET_FOR_EACH (gw_port, &local_l3gw_ports) {
- const struct sbrec_port_binding *pb
- = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
- if (pb && !smap_get_bool(&pb->options, "disable_garp_rarp", false)) {
- send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip,
- local_datapaths, pb, &nat_addresses,
- garp_max_timeout, garp_continuous);
+ /* Update send_garp_rarp_data. */
+ const char *iface_id;
+ SSET_FOR_EACH (iface_id, &nat_addresses->localnet_vifs) {
+ const struct sbrec_port_binding *pb = lport_lookup_by_name(
+ sbrec_port_binding_by_name, iface_id);
+ if (pb && !smap_get_bool(&pb->options, "disable_garp_rarp", false)) {
+ send_garp_rarp_update(ovnsb_idl_txn,
+ sbrec_mac_binding_by_lport_ip,
+ local_datapaths, pb, &nat_addresses->nat_addresses,
+ garp_max_timeout, garp_continuous);
+ }
}
- }
- /* pinctrl_handler thread will send the GARPs. */
-
- sset_destroy(&localnet_vifs);
- sset_destroy(&local_l3gw_ports);
+ /* Update send_garp_rarp_data for nat-addresses. */
+ const char *gw_port;
+ SSET_FOR_EACH (gw_port, &nat_addresses->local_l3gw_ports) {
+ const struct sbrec_port_binding *pb
+ = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
+ if (pb && !smap_get_bool(&pb->options, "disable_garp_rarp", false)) {
+ send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip,
+ local_datapaths, pb, &nat_addresses->nat_addresses,
+ garp_max_timeout, garp_continuous);
+ }
+ }
- SHASH_FOR_EACH_SAFE (iter, &nat_addresses) {
- struct lport_addresses *laddrs = iter->data;
- destroy_lport_addresses(laddrs);
- shash_delete(&nat_addresses, iter);
- free(laddrs);
+ /* pinctrl_handler thread will send the GARPs. */
+ garp_rarp_max_timeout = garp_max_timeout;
+ garp_rarp_continuous = garp_continuous;
}
- shash_destroy(&nat_addresses);
-
- sset_destroy(&nat_ip_keys);
-
- garp_rarp_max_timeout = garp_max_timeout;
- garp_rarp_continuous = garp_continuous;
}
static bool
@@ -20,6 +20,7 @@
#include <stdint.h>
#include "lib/sset.h"
+#include "openvswitch/shash.h"
#include "openvswitch/list.h"
#include "openvswitch/meta-flow.h"
@@ -39,10 +40,16 @@ struct sbrec_bfd_table;
struct sbrec_port_binding;
struct sbrec_mac_binding_table;
+struct ed_type_nat_addresses {
+ struct shash nat_addresses;
+ struct sset localnet_vifs;
+ struct sset local_l3gw_ports;
+ struct sset nat_ip_keys;
+};
+
void pinctrl_init(void);
void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
- struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_key,
struct ovsdb_idl_index *sbrec_port_binding_by_name,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
@@ -54,12 +61,13 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
const struct sbrec_service_monitor_table *,
const struct sbrec_mac_binding_table *,
const struct sbrec_bfd_table *,
- const struct ovsrec_bridge *, const struct sbrec_chassis *,
+ const struct sbrec_chassis *,
const struct hmap *local_datapaths,
const struct sset *active_tunnels,
const struct shash *local_active_ports_ipv6_pd,
const struct shash *local_active_ports_ras,
- const struct ovsrec_open_vswitch_table *ovs_table);
+ const struct ovsrec_open_vswitch_table *ovs_table,
+ struct ed_type_nat_addresses *nat_addresses);
void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn);
void pinctrl_destroy(void);