+static bool
+gateway_chassis_equal(const struct nbrec_gateway_chassis *nb_gwc,
+ const struct sbrec_chassis *nb_gwc_c,
+ const struct sbrec_gateway_chassis *sb_gwc)
+{
+ return !strcmp(nb_gwc->name, sb_gwc->name)
+ && !strcmp(nb_gwc_c->name, sb_gwc->chassis->name)
+ && nb_gwc->priority == sb_gwc->priority
+ && smap_equal(&nb_gwc->options, &sb_gwc->options)
+ && smap_equal(&nb_gwc->external_ids, &sb_gwc->external_ids);
+}
+
+static bool
+sbpb_gw_chassis_needs_update(
+ const struct sbrec_port_binding *port_binding,
+ const struct nbrec_logical_router_port *lrp,
+ const struct chassis_index *chassis_index)
+{
+ if (!lrp || !port_binding) {
+ return false;
+ }
+
+ /* These arrays are used to collect valid Gateway_Chassis and valid
+ * Chassis records from the Logical_Router_Port Gateway_Chassis list,
+ * we ignore the ones we can't match on the SBDB */
+ struct nbrec_gateway_chassis **lrp_gwc = xzalloc(lrp->n_gateway_chassis *
+ sizeof *lrp_gwc);
+ const struct sbrec_chassis **lrp_gwc_c = xzalloc(lrp->n_gateway_chassis *
+ sizeof *lrp_gwc_c);
+
+ /* Count the number of gateway chassis chassis names from the logical
+ * router port that we are able to match on the southbound database */
+ int lrp_n_gateway_chassis = 0;
+ int n;
+ for (n = 0; n < lrp->n_gateway_chassis; n++) {
+
+ if (!lrp->gateway_chassis[n]->chassis_name) {
+ continue;
+ }
+
+ const struct sbrec_chassis *chassis =
+ chassis_lookup_by_name(chassis_index,
+ lrp->gateway_chassis[n]->chassis_name);
+
+ if (chassis) {
+ lrp_gwc_c[lrp_n_gateway_chassis] = chassis;
+ lrp_gwc[lrp_n_gateway_chassis] = lrp->gateway_chassis[n];
+ lrp_n_gateway_chassis++;
+ } else {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_WARN_RL(
+ &rl, "Chassis name %s referenced in NBDB via Gateway_Chassis "
+ "on logical router port %s does not exist in SBDB",
+ lrp->gateway_chassis[n]->chassis_name, lrp->name);
+ }
+ }
+
+ /* Basic check, different amount of Gateway_Chassis means that we
+ * need to update southbound database Port_Binding */
+ if (lrp_n_gateway_chassis != port_binding->n_gateway_chassis) {
+ free(lrp_gwc_c);
+ free(lrp_gwc);
+ return true;
+ }
+
+ for (n = 0; n < lrp_n_gateway_chassis; n++) {
+ int i;
+ /* For each of the valid gw chassis on the lrp, check if there's
+ * a match on the Port_Binding list, we assume order is not
+ * persisted */
+ for (i = 0; i < port_binding->n_gateway_chassis; i++) {
+ if (gateway_chassis_equal(lrp_gwc[n],
+ lrp_gwc_c[n],
+ port_binding->gateway_chassis[i])) {
+ break; /* we found a match */
+ }
+ }
+
+ /* if no Port_Binding gateway chassis matched for the entry... */
+ if (i == port_binding->n_gateway_chassis) {
+ free(lrp_gwc_c);
+ free(lrp_gwc);
+ return true; /* found no match for this gateway chassis on lrp */
+ }
+ }
+
+ /* no need for update, all ports matched */
+ free(lrp_gwc_c);
+ free(lrp_gwc);
+ return false;
+}
+
+/* This functions translates the gw chassis on the nb database
+ * to sb database entries, the only difference is that SB database
+ * Gateway_Chassis table references the chassis directly instead
+ * of using the name */