@@ -430,17 +430,8 @@ consider_local_datapath(struct controller_ctx *ctx,
if (redirect_chassis &&
redirect_chassis_contains(redirect_chassis, chassis_rec)) {
- struct redirect_chassis *rc;
- LIST_FOR_EACH (rc, node, redirect_chassis) {
- if (!strcmp(rc->chassis_id, chassis_rec->name)) {
- /* sb_rec_port_binding->chassis should reflect master */
- our_chassis = true;
- break;
- }
- if (sset_contains(active_tunnels, rc->chassis_id)) {
- break;
- }
- }
+ our_chassis = redirect_chassis_is_active(
+ redirect_chassis, chassis_rec, active_tunnels);
add_local_datapath(ldatapaths, lports, binding_rec->datapath,
false, local_datapaths, our_chassis);
}
@@ -491,7 +482,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *chassis_rec,
const struct ldatapath_index *ldatapaths,
const struct lport_index *lports, struct hmap *local_datapaths,
- struct sset *local_lports)
+ struct sset *local_lports, struct sset *active_tunnels)
{
if (!chassis_rec) {
return;
@@ -500,13 +491,12 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
const struct sbrec_port_binding *binding_rec;
struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface);
struct sset egress_ifaces = SSET_INITIALIZER(&egress_ifaces);
- struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels);
struct hmap qos_map;
hmap_init(&qos_map);
if (br_int) {
get_local_iface_ids(br_int, &lport_to_iface, local_lports,
- &egress_ifaces, &active_tunnels);
+ &egress_ifaces, active_tunnels);
}
/* Run through each binding record to see if it is resident on this
@@ -517,7 +507,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
chassis_rec, binding_rec,
sset_is_empty(&egress_ifaces) ? NULL :
&qos_map, local_datapaths, &lport_to_iface,
- local_lports, &active_tunnels);
+ local_lports, active_tunnels);
}
if (!sset_is_empty(&egress_ifaces)
@@ -530,7 +520,6 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
shash_destroy(&lport_to_iface);
sset_destroy(&egress_ifaces);
- sset_destroy(&active_tunnels);
hmap_destroy(&qos_map);
}
@@ -32,7 +32,7 @@ void binding_register_ovs_idl(struct ovsdb_idl *);
void binding_run(struct controller_ctx *, const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *, const struct ldatapath_index *,
const struct lport_index *, struct hmap *local_datapaths,
- struct sset *all_lports);
+ struct sset *all_lports, struct sset *active_tunnels);
void bfd_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *chassis_rec,
struct hmap *local_datapaths);
@@ -53,6 +53,7 @@ struct lookup_port_aux {
struct condition_aux {
const struct lport_index *lports;
const struct sbrec_chassis *chassis;
+ const struct sset *active_tunnels;
};
static void consider_logical_flow(const struct lport_index *lports,
@@ -65,7 +66,8 @@ static void consider_logical_flow(const struct lport_index *lports,
struct hmap *dhcpv6_opts,
uint32_t *conj_id_ofs,
const struct shash *addr_sets,
- struct hmap *flow_table);
+ struct hmap *flow_table,
+ struct sset *active_tunnels);
static bool
lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp)
@@ -96,10 +98,23 @@ is_chassis_resident_cb(const void *c_aux_, const char *port_name)
const struct sbrec_port_binding *pb
= lport_lookup_by_name(c_aux->lports, port_name);
- if (pb && pb->chassis && pb->chassis == c_aux->chassis) {
- return true;
+ if (!pb) {
+ return false;
+ }
+ if (strcmp(pb->type, "chassisredirect")) {
+ /* for non-chassisredirect ports */
+ return pb->chassis && pb->chassis == c_aux->chassis;
} else {
- return pb_redirect_chassis_contains(pb, c_aux->chassis);
+ struct ovs_list *redirect_chassis;
+ redirect_chassis = parse_redirect_chassis(pb);
+ if (redirect_chassis) {
+ bool active = redirect_chassis_is_active(redirect_chassis,
+ c_aux->chassis,
+ c_aux->active_tunnels);
+ redirect_chassis_destroy(redirect_chassis);
+ return active;
+ }
+ return false;
}
}
@@ -127,7 +142,8 @@ add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports,
struct group_table *group_table,
const struct sbrec_chassis *chassis,
const struct shash *addr_sets,
- struct hmap *flow_table)
+ struct hmap *flow_table,
+ struct sset *active_tunnels)
{
uint32_t conj_id_ofs = 1;
const struct sbrec_logical_flow *lflow;
@@ -151,7 +167,7 @@ add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports,
consider_logical_flow(lports, mcgroups, lflow, local_datapaths,
group_table, chassis,
&dhcp_opts, &dhcpv6_opts, &conj_id_ofs,
- addr_sets, flow_table);
+ addr_sets, flow_table, active_tunnels);
}
dhcp_opts_destroy(&dhcp_opts);
@@ -169,7 +185,8 @@ consider_logical_flow(const struct lport_index *lports,
struct hmap *dhcpv6_opts,
uint32_t *conj_id_ofs,
const struct shash *addr_sets,
- struct hmap *flow_table)
+ struct hmap *flow_table,
+ struct sset *active_tunnels)
{
/* Determine translation of logical table IDs to physical table IDs. */
bool ingress = !strcmp(lflow->pipeline, "ingress");
@@ -266,7 +283,7 @@ consider_logical_flow(const struct lport_index *lports,
return;
}
- struct condition_aux cond_aux = { lports, chassis };
+ struct condition_aux cond_aux = { lports, chassis, active_tunnels};
expr = expr_simplify(expr, is_chassis_resident_cb, &cond_aux);
expr = expr_normalize(expr);
uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
@@ -395,10 +412,11 @@ lflow_run(struct controller_ctx *ctx,
const struct hmap *local_datapaths,
struct group_table *group_table,
const struct shash *addr_sets,
- struct hmap *flow_table)
+ struct hmap *flow_table,
+ struct sset *active_tunnels)
{
add_logical_flows(ctx, lports, mcgroups, local_datapaths, group_table,
- chassis, addr_sets, flow_table);
+ chassis, addr_sets, flow_table, active_tunnels);
add_neighbor_flows(ctx, lports, flow_table);
}
@@ -42,6 +42,7 @@ struct lport_index;
struct mcgroup_index;
struct sbrec_chassis;
struct simap;
+struct sset;
struct uuid;
/* OpenFlow table numbers.
@@ -69,7 +70,8 @@ void lflow_run(struct controller_ctx *,
const struct hmap *local_datapaths,
struct group_table *group_table,
const struct shash *addr_sets,
- struct hmap *flow_table);
+ struct hmap *flow_table,
+ struct sset *active_tunnels);
void lflow_destroy(void);
#endif /* ovn/lflow.h */
@@ -15,11 +15,11 @@
#include <config.h>
+#include "lib/sset.h"
#include "lport.h"
#include "hash.h"
#include "openvswitch/vlog.h"
#include "ovn/lib/ovn-sb-idl.h"
-
VLOG_DEFINE_THIS_MODULE(lport);
static struct ldatapath *ldatapath_lookup_by_key__(
@@ -356,3 +356,44 @@ pb_redirect_chassis_contains(const struct sbrec_port_binding *binding,
redirect_chassis_destroy(redirect_chassis);
return contained;
}
+
+bool
+redirect_chassis_is_active(const struct ovs_list *redirect_chassis,
+ const struct sbrec_chassis *local_chassis,
+ const struct sset *active_tunnels)
+{
+ struct redirect_chassis *rc;
+
+ if (!redirect_chassis) {
+ return false;
+ }
+ /* if there's only one chassis, and local chassis is on the list
+ * it's not HA and it's the equivalent of being active */
+ if (ovs_list_is_short(redirect_chassis) &&
+ redirect_chassis_contains(redirect_chassis, local_chassis)) {
+ return true;
+ }
+
+ /* if there are no other tunnels active, we assume that the
+ * connection providing tunneling is down, hence we're down */
+ if (sset_is_empty(active_tunnels)) {
+ return false;
+ }
+
+ /* redirect_chassis is an ordered list, by priority, of chassis
+ * hosting the redirect of the port */
+ LIST_FOR_EACH (rc, node, redirect_chassis) {
+ /* if we found the chassis on the list, and we didn't exit before
+ * on the active_tunnels check for other higher priority chassis
+ * being active, then this chassis is master. */
+ if (!strcmp(rc->chassis_id, local_chassis->name)) {
+ return true;
+ }
+ /* if we find this specific chassis on the list to have an active
+ * tunnel, then 'local_chassis' is not master */
+ if (sset_contains(active_tunnels, rc->chassis_id)) {
+ return false;
+ }
+ }
+ return false;
+}
@@ -25,6 +25,8 @@ struct ovsdb_idl;
struct sbrec_chassis;
struct sbrec_datapath_binding;
struct sbrec_port_binding;
+struct sset;
+
/* Database indexes.
* =================
@@ -120,5 +122,8 @@ void redirect_chassis_destroy(struct ovs_list *list);
bool pb_redirect_chassis_contains(
const struct sbrec_port_binding *binding,
const struct sbrec_chassis *chassis);
-
+bool redirect_chassis_is_active(
+ const struct ovs_list *redirect_chassis,
+ const struct sbrec_chassis *local_chassis,
+ const struct sset *active_tunnels);
#endif /* ovn/lport.h */
@@ -613,6 +613,7 @@ main(int argc, char *argv[])
* l2gateway ports for which options:l2gateway-chassis designates the
* local hypervisor, and localnet ports. */
struct sset local_lports = SSET_INITIALIZER(&local_lports);
+ struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels);
const struct ovsrec_bridge *br_int = get_br_int(&ctx);
const char *chassis_id = get_chassis_id(ctx.ovs_idl);
@@ -629,7 +630,7 @@ main(int argc, char *argv[])
chassis = chassis_run(&ctx, chassis_id, br_int);
encaps_run(&ctx, br_int, chassis_id);
binding_run(&ctx, br_int, chassis, &ldatapaths, &lports,
- &local_datapaths, &local_lports);
+ &local_datapaths, &local_lports, &active_tunnels);
}
if (br_int && chassis) {
@@ -651,7 +652,7 @@ main(int argc, char *argv[])
struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
lflow_run(&ctx, chassis, &lports, &mcgroups,
&local_datapaths, &group_table,
- &addr_sets, &flow_table);
+ &addr_sets, &flow_table, &active_tunnels);
bfd_run(&ctx, br_int, chassis, &local_datapaths);
physical_run(&ctx, mff_ovn_geneve,
@@ -705,6 +706,7 @@ main(int argc, char *argv[])
ldatapath_index_destroy(&ldatapaths);
sset_destroy(&local_lports);
+ sset_destroy(&active_tunnels);
struct local_datapath *cur_node, *next_node;
HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, &local_datapaths) {