@@ -3,6 +3,8 @@ OVN v21.12.3 - xx xxx xxxx
- A new ACL option, "log-related" has been added that allows for reply and
related traffic to be logged for an ACL in addition to the traffic that
directly matches the ACL.
+ - Add "garp-max-timeout-sec" config option to vswitchd external-ids to
+ cap the time between when ovn-controller sends gARP packets.
OVN v21.12.2 - 03 Jun 2022
--------------------------
@@ -338,6 +338,17 @@
of how many entries there are in the cache. By default this is set to
30000 (30 seconds).
</dd>
+ <dt><code>external_ids:garp-max-timeout-sec</code></dt>
+ <dd>
+ When used, this configuration value specifies the maximum timeout
+ (in seconds) between two consecutive GARP packets sent by
+ <code>ovn-controller</code>.
+ <code>ovn-controller</code> by default sends just 4 GARP packets
+ with an exponential backoff timeout.
+ Setting <code>external_ids:garp-max-timeout-sec</code> allows to
+ cap for the exponential backoff used by <code>ovn-controller</code>
+ to send GARPs packets.
+ </dd>
</dl>
<p>
@@ -3888,7 +3888,9 @@ main(int argc, char *argv[])
&runtime_data->local_datapaths,
&runtime_data->active_tunnels,
&runtime_data->local_active_ports_ipv6_pd,
- &runtime_data->local_active_ports_ras);
+ &runtime_data->local_active_ports_ras,
+ ovsrec_open_vswitch_table_get(
+ ovs_idl_loop.idl));
stopwatch_stop(PINCTRL_RUN_STOPWATCH_NAME,
time_msec());
/* Updating monitor conditions if runtime data or
@@ -164,6 +164,10 @@ static struct ovs_mutex pinctrl_mutex = OVS_MUTEX_INITIALIZER;
static struct seq *pinctrl_handler_seq;
static struct seq *pinctrl_main_seq;
+#define GARP_RARP_DEF_MAX_TIMEOUT 16000
+static long long int garp_rarp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT;
+static bool garp_rarp_continuous;
+
static void *pinctrl_handler(void *arg);
struct pinctrl {
@@ -209,7 +213,8 @@ static void send_garp_rarp_prepare(
const struct ovsrec_bridge *,
const struct sbrec_chassis *,
const struct hmap *local_datapaths,
- const struct sset *active_tunnels)
+ const struct sset *active_tunnels,
+ const struct ovsrec_open_vswitch_table *ovs_table)
OVS_REQUIRES(pinctrl_mutex);
static void send_garp_rarp_run(struct rconn *swconn,
long long int *send_garp_rarp_time)
@@ -3475,7 +3480,8 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
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 shash *local_active_ports_ras,
+ const struct ovsrec_open_vswitch_table *ovs_table)
{
ovs_mutex_lock(&pinctrl_mutex);
pinctrl_set_br_int_name_(br_int->name);
@@ -3487,7 +3493,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
send_garp_rarp_prepare(ovnsb_idl_txn, sbrec_port_binding_by_datapath,
sbrec_port_binding_by_name,
sbrec_mac_binding_by_lport_ip, br_int, chassis,
- local_datapaths, active_tunnels);
+ local_datapaths, active_tunnels, ovs_table);
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,
@@ -4330,7 +4336,8 @@ struct garp_rarp_data {
struct eth_addr ea; /* Ethernet address of port. */
ovs_be32 ipv4; /* Ipv4 address of port. */
long long int announce_time; /* Next announcement in ms. */
- int backoff; /* Backoff for the next announcement. */
+ int backoff; /* Backoff timeout for the next
+ * announcement (in msecs). */
uint32_t dp_key; /* Datapath used to output this GARP. */
uint32_t port_key; /* Port to inject the GARP into. */
};
@@ -4359,7 +4366,7 @@ add_garp_rarp(const char *name, const struct eth_addr ea, ovs_be32 ip,
garp_rarp->ea = ea;
garp_rarp->ipv4 = ip;
garp_rarp->announce_time = time_msec() + 1000;
- garp_rarp->backoff = 1;
+ garp_rarp->backoff = 1000; /* msec. */
garp_rarp->dp_key = dp_key;
garp_rarp->port_key = port_key;
shash_add(&send_garp_rarp_data, name, garp_rarp);
@@ -4375,7 +4382,9 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn,
struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
const struct hmap *local_datapaths,
const struct sbrec_port_binding *binding_rec,
- struct shash *nat_addresses)
+ struct shash *nat_addresses,
+ long long int garp_max_timeout,
+ bool garp_continuous)
{
volatile struct garp_rarp_data *garp_rarp = NULL;
@@ -4401,6 +4410,12 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn,
if (garp_rarp) {
garp_rarp->dp_key = binding_rec->datapath->tunnel_key;
garp_rarp->port_key = binding_rec->tunnel_key;
+ if (garp_max_timeout != garp_rarp_max_timeout ||
+ garp_continuous != garp_rarp_continuous) {
+ /* reset backoff */
+ garp_rarp->announce_time = time_msec() + 1000;
+ garp_rarp->backoff = 1000; /* msec. */
+ }
} else {
add_garp_rarp(name, laddrs->ea,
laddrs->ipv4_addrs[i].addr,
@@ -4425,6 +4440,12 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn,
if (garp_rarp) {
garp_rarp->dp_key = binding_rec->datapath->tunnel_key;
garp_rarp->port_key = binding_rec->tunnel_key;
+ if (garp_max_timeout != garp_rarp_max_timeout ||
+ garp_continuous != garp_rarp_continuous) {
+ /* reset backoff */
+ garp_rarp->announce_time = time_msec() + 1000;
+ garp_rarp->backoff = 1000; /* msec. */
+ }
} else {
add_garp_rarp(name, laddrs->ea,
0, binding_rec->datapath->tunnel_key,
@@ -4444,6 +4465,12 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn,
if (garp_rarp) {
garp_rarp->dp_key = binding_rec->datapath->tunnel_key;
garp_rarp->port_key = binding_rec->tunnel_key;
+ if (garp_max_timeout != garp_rarp_max_timeout ||
+ garp_continuous != garp_rarp_continuous) {
+ /* reset backoff */
+ garp_rarp->announce_time = time_msec() + 1000;
+ garp_rarp->backoff = 1000; /* msec. */
+ }
return;
}
@@ -4529,13 +4556,15 @@ send_garp_rarp(struct rconn *swconn, struct garp_rarp_data *garp_rarp,
ofpbuf_uninit(&ofpacts);
/* Set the next announcement. At most 5 announcements are sent for a
- * vif. */
- if (garp_rarp->backoff < 16) {
- garp_rarp->backoff *= 2;
- garp_rarp->announce_time = current_time + garp_rarp->backoff * 1000;
+ * vif if garp_rarp_max_timeout is not specified otherwise cap the max
+ * timeout to garp_rarp_max_timeout. */
+ if (garp_rarp_continuous || garp_rarp->backoff < garp_rarp_max_timeout) {
+ garp_rarp->announce_time = current_time + garp_rarp->backoff;
} else {
garp_rarp->announce_time = LLONG_MAX;
}
+ garp_rarp->backoff = MIN(garp_rarp_max_timeout, garp_rarp->backoff * 2);
+
return garp_rarp->announce_time;
}
@@ -5778,13 +5807,26 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn,
const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *chassis,
const struct hmap *local_datapaths,
- const struct sset *active_tunnels)
+ const struct sset *active_tunnels,
+ const struct ovsrec_open_vswitch_table *ovs_table)
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);
@@ -5813,8 +5855,10 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn,
const struct sbrec_port_binding *pb = lport_lookup_by_name(
sbrec_port_binding_by_name, iface_id);
if (pb) {
- send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip,
- local_datapaths, pb, &nat_addresses);
+ send_garp_rarp_update(ovnsb_idl_txn,
+ sbrec_mac_binding_by_lport_ip,
+ local_datapaths, pb, &nat_addresses,
+ garp_max_timeout, garp_continuous);
}
}
@@ -5825,7 +5869,8 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn,
= lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
if (pb) {
send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip,
- local_datapaths, pb, &nat_addresses);
+ local_datapaths, pb, &nat_addresses,
+ garp_max_timeout, garp_continuous);
}
}
@@ -5843,6 +5888,9 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn,
shash_destroy(&nat_addresses);
sset_destroy(&nat_ip_keys);
+
+ garp_rarp_max_timeout = garp_max_timeout;
+ garp_rarp_continuous = garp_continuous;
}
static bool
@@ -28,6 +28,7 @@ struct lport_index;
struct ovsdb_idl_index;
struct ovsdb_idl_txn;
struct ovsrec_bridge;
+struct ovsrec_open_vswitch_table;
struct sbrec_chassis;
struct sbrec_dns_table;
struct sbrec_controller_event_table;
@@ -52,7 +53,8 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
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 shash *local_active_ports_ras,
+ const struct ovsrec_open_vswitch_table *ovs_table);
void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn);
void pinctrl_destroy(void);
void pinctrl_set_br_int_name(char *br_int_name);