0f57e581a5ca9745e816086134b8ef271e3c4969
[cascardo/ovs.git] / ovn / northd / ovn-northd.c
1 /*
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at:
5  *
6  *     http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14
15 #include <config.h>
16
17 #include <getopt.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20
21 #include "command-line.h"
22 #include "daemon.h"
23 #include "dirs.h"
24 #include "dynamic-string.h"
25 #include "fatal-signal.h"
26 #include "hash.h"
27 #include "hmap.h"
28 #include "json.h"
29 #include "ovn/lib/lex.h"
30 #include "ovn/lib/ovn-nb-idl.h"
31 #include "ovn/lib/ovn-sb-idl.h"
32 #include "poll-loop.h"
33 #include "smap.h"
34 #include "stream.h"
35 #include "stream-ssl.h"
36 #include "unixctl.h"
37 #include "util.h"
38 #include "uuid.h"
39 #include "openvswitch/vlog.h"
40
41 VLOG_DEFINE_THIS_MODULE(ovn_northd);
42
43 static unixctl_cb_func ovn_northd_exit;
44
45 struct northd_context {
46     struct ovsdb_idl *ovnnb_idl;
47     struct ovsdb_idl *ovnsb_idl;
48     struct ovsdb_idl_txn *ovnnb_txn;
49     struct ovsdb_idl_txn *ovnsb_txn;
50 };
51
52 static const char *ovnnb_db;
53 static const char *ovnsb_db;
54
55 static const char *default_db(void);
56
57
58 /* Ingress pipeline stages.
59  *
60  * These must be listed in the order that the stages will be executed. */
61 #define INGRESS_STAGES                         \
62     INGRESS_STAGE(PORT_SEC, port_sec)          \
63     INGRESS_STAGE(ACL, acl)                    \
64     INGRESS_STAGE(L2_LKUP, l2_lkup)
65
66 enum ingress_stage {
67 #define INGRESS_STAGE(NAME, STR) S_IN_##NAME,
68     INGRESS_STAGES
69 #undef INGRESS_STAGE
70     INGRESS_N_STAGES
71 };
72
73 /* Egress pipeline stages.
74  *
75  * These must be listed in the order that the stages will be executed. */
76 #define EGRESS_STAGES                         \
77     EGRESS_STAGE(ACL, acl)                    \
78     EGRESS_STAGE(PORT_SEC, port_sec)
79
80 enum egress_stage {
81 #define EGRESS_STAGE(NAME, STR) S_OUT_##NAME,
82     EGRESS_STAGES
83 #undef EGRESS_STAGE
84     EGRESS_N_STAGES
85 };
86
87 static void
88 usage(void)
89 {
90     printf("\
91 %s: OVN northbound management daemon\n\
92 usage: %s [OPTIONS]\n\
93 \n\
94 Options:\n\
95   --ovnnb-db=DATABASE       connect to ovn-nb database at DATABASE\n\
96                             (default: %s)\n\
97   --ovnsb-db=DATABASE       connect to ovn-sb database at DATABASE\n\
98                             (default: %s)\n\
99   -h, --help                display this help message\n\
100   -o, --options             list available options\n\
101   -V, --version             display version information\n\
102 ", program_name, program_name, default_db(), default_db());
103     daemon_usage();
104     vlog_usage();
105     stream_usage("database", true, true, false);
106 }
107 \f
108 struct tnlid_node {
109     struct hmap_node hmap_node;
110     uint32_t tnlid;
111 };
112
113 static void
114 destroy_tnlids(struct hmap *tnlids)
115 {
116     struct tnlid_node *node, *next;
117     HMAP_FOR_EACH_SAFE (node, next, hmap_node, tnlids) {
118         hmap_remove(tnlids, &node->hmap_node);
119         free(node);
120     }
121     hmap_destroy(tnlids);
122 }
123
124 static void
125 add_tnlid(struct hmap *set, uint32_t tnlid)
126 {
127     struct tnlid_node *node = xmalloc(sizeof *node);
128     hmap_insert(set, &node->hmap_node, hash_int(tnlid, 0));
129     node->tnlid = tnlid;
130 }
131
132 static bool
133 tnlid_in_use(const struct hmap *set, uint32_t tnlid)
134 {
135     const struct tnlid_node *node;
136     HMAP_FOR_EACH_IN_BUCKET (node, hmap_node, hash_int(tnlid, 0), set) {
137         if (node->tnlid == tnlid) {
138             return true;
139         }
140     }
141     return false;
142 }
143
144 static uint32_t
145 allocate_tnlid(struct hmap *set, const char *name, uint32_t max,
146                uint32_t *hint)
147 {
148     for (uint32_t tnlid = *hint + 1; tnlid != *hint;
149          tnlid = tnlid + 1 <= max ? tnlid + 1 : 1) {
150         if (!tnlid_in_use(set, tnlid)) {
151             add_tnlid(set, tnlid);
152             *hint = tnlid;
153             return tnlid;
154         }
155     }
156
157     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
158     VLOG_WARN_RL(&rl, "all %s tunnel ids exhausted", name);
159     return 0;
160 }
161 \f
162 /* The 'key' comes from nb->header_.uuid or sb->external_ids:logical-switch. */
163 struct ovn_datapath {
164     struct hmap_node key_node;  /* Index on 'key'. */
165     struct uuid key;            /* nb->header_.uuid. */
166
167     const struct nbrec_logical_switch *nb;   /* May be NULL. */
168     const struct sbrec_datapath_binding *sb; /* May be NULL. */
169
170     struct ovs_list list;       /* In list of similar records. */
171
172     struct hmap port_tnlids;
173     uint32_t port_key_hint;
174
175     bool has_unknown;
176 };
177
178 static struct ovn_datapath *
179 ovn_datapath_create(struct hmap *datapaths, const struct uuid *key,
180                     const struct nbrec_logical_switch *nb,
181                     const struct sbrec_datapath_binding *sb)
182 {
183     struct ovn_datapath *od = xzalloc(sizeof *od);
184     od->key = *key;
185     od->sb = sb;
186     od->nb = nb;
187     hmap_init(&od->port_tnlids);
188     od->port_key_hint = 0;
189     hmap_insert(datapaths, &od->key_node, uuid_hash(&od->key));
190     return od;
191 }
192
193 static void
194 ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od)
195 {
196     if (od) {
197         /* Don't remove od->list.  It is used within build_datapaths() as a
198          * private list and once we've exited that function it is not safe to
199          * use it. */
200         hmap_remove(datapaths, &od->key_node);
201         destroy_tnlids(&od->port_tnlids);
202         free(od);
203     }
204 }
205
206 static struct ovn_datapath *
207 ovn_datapath_find(struct hmap *datapaths, const struct uuid *uuid)
208 {
209     struct ovn_datapath *od;
210
211     HMAP_FOR_EACH_WITH_HASH (od, key_node, uuid_hash(uuid), datapaths) {
212         if (uuid_equals(uuid, &od->key)) {
213             return od;
214         }
215     }
216     return NULL;
217 }
218
219 static struct ovn_datapath *
220 ovn_datapath_from_sbrec(struct hmap *datapaths,
221                         const struct sbrec_datapath_binding *sb)
222 {
223     struct uuid key;
224
225     if (!smap_get_uuid(&sb->external_ids, "logical-switch", &key)) {
226         return NULL;
227     }
228     return ovn_datapath_find(datapaths, &key);
229 }
230
231 static void
232 join_datapaths(struct northd_context *ctx, struct hmap *datapaths,
233                struct ovs_list *sb_only, struct ovs_list *nb_only,
234                struct ovs_list *both)
235 {
236     hmap_init(datapaths);
237     list_init(sb_only);
238     list_init(nb_only);
239     list_init(both);
240
241     const struct sbrec_datapath_binding *sb, *sb_next;
242     SBREC_DATAPATH_BINDING_FOR_EACH_SAFE (sb, sb_next, ctx->ovnsb_idl) {
243         struct uuid key;
244         if (!smap_get_uuid(&sb->external_ids, "logical-switch", &key)) {
245             ovsdb_idl_txn_add_comment(ctx->ovnsb_txn,
246                                       "deleting Datapath_Binding "UUID_FMT" that "
247                                       "lacks external-ids:logical-switch",
248                          UUID_ARGS(&sb->header_.uuid));
249             sbrec_datapath_binding_delete(sb);
250             continue;
251         }
252
253         if (ovn_datapath_find(datapaths, &key)) {
254             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
255             VLOG_INFO_RL(&rl, "deleting Datapath_Binding "UUID_FMT" with "
256                          "duplicate external-ids:logical-switch "UUID_FMT,
257                          UUID_ARGS(&sb->header_.uuid), UUID_ARGS(&key));
258             sbrec_datapath_binding_delete(sb);
259             continue;
260         }
261
262         struct ovn_datapath *od = ovn_datapath_create(datapaths, &key,
263                                                       NULL, sb);
264         list_push_back(sb_only, &od->list);
265     }
266
267     const struct nbrec_logical_switch *nb;
268     NBREC_LOGICAL_SWITCH_FOR_EACH (nb, ctx->ovnnb_idl) {
269         struct ovn_datapath *od = ovn_datapath_find(datapaths,
270                                                     &nb->header_.uuid);
271         if (od) {
272             od->nb = nb;
273             list_remove(&od->list);
274             list_push_back(both, &od->list);
275         } else {
276             od = ovn_datapath_create(datapaths, &nb->header_.uuid, nb, NULL);
277             list_push_back(nb_only, &od->list);
278         }
279     }
280 }
281
282 static uint32_t
283 ovn_datapath_allocate_key(struct hmap *dp_tnlids)
284 {
285     static uint32_t hint;
286     return allocate_tnlid(dp_tnlids, "datapath", (1u << 24) - 1, &hint);
287 }
288
289 static void
290 build_datapaths(struct northd_context *ctx, struct hmap *datapaths)
291 {
292     struct ovs_list sb_only, nb_only, both;
293
294     join_datapaths(ctx, datapaths, &sb_only, &nb_only, &both);
295
296     if (!list_is_empty(&nb_only)) {
297         /* First index the in-use datapath tunnel IDs. */
298         struct hmap dp_tnlids = HMAP_INITIALIZER(&dp_tnlids);
299         struct ovn_datapath *od;
300         LIST_FOR_EACH (od, list, &both) {
301             add_tnlid(&dp_tnlids, od->sb->tunnel_key);
302         }
303
304         /* Add southbound record for each unmatched northbound record. */
305         LIST_FOR_EACH (od, list, &nb_only) {
306             uint16_t tunnel_key = ovn_datapath_allocate_key(&dp_tnlids);
307             if (!tunnel_key) {
308                 break;
309             }
310
311             od->sb = sbrec_datapath_binding_insert(ctx->ovnsb_txn);
312
313             char uuid_s[UUID_LEN + 1];
314             sprintf(uuid_s, UUID_FMT, UUID_ARGS(&od->nb->header_.uuid));
315             const struct smap id = SMAP_CONST1(&id, "logical-switch", uuid_s);
316             sbrec_datapath_binding_set_external_ids(od->sb, &id);
317
318             sbrec_datapath_binding_set_tunnel_key(od->sb, tunnel_key);
319         }
320         destroy_tnlids(&dp_tnlids);
321     }
322
323     /* Delete southbound records without northbound matches. */
324     struct ovn_datapath *od, *next;
325     LIST_FOR_EACH_SAFE (od, next, list, &sb_only) {
326         list_remove(&od->list);
327         sbrec_datapath_binding_delete(od->sb);
328         ovn_datapath_destroy(datapaths, od);
329     }
330 }
331 \f
332 struct ovn_port {
333     struct hmap_node key_node;  /* Index on 'key'. */
334     const char *key;            /* nb->name and sb->logical_port */
335
336     const struct nbrec_logical_port *nb; /* May be NULL. */
337     const struct sbrec_port_binding *sb; /* May be NULL. */
338
339     struct ovn_datapath *od;
340
341     struct ovs_list list;       /* In list of similar records. */
342 };
343
344 static struct ovn_port *
345 ovn_port_create(struct hmap *ports, const char *key,
346                 const struct nbrec_logical_port *nb,
347                 const struct sbrec_port_binding *sb)
348 {
349     struct ovn_port *op = xzalloc(sizeof *op);
350     op->key = key;
351     op->sb = sb;
352     op->nb = nb;
353     hmap_insert(ports, &op->key_node, hash_string(op->key, 0));
354     return op;
355 }
356
357 static void
358 ovn_port_destroy(struct hmap *ports, struct ovn_port *port)
359 {
360     if (port) {
361         /* Don't remove port->list.  It is used within build_ports() as a
362          * private list and once we've exited that function it is not safe to
363          * use it. */
364         hmap_remove(ports, &port->key_node);
365         free(port);
366     }
367 }
368
369 static struct ovn_port *
370 ovn_port_find(struct hmap *ports, const char *name)
371 {
372     struct ovn_port *op;
373
374     HMAP_FOR_EACH_WITH_HASH (op, key_node, hash_string(name, 0), ports) {
375         if (!strcmp(op->key, name)) {
376             return op;
377         }
378     }
379     return NULL;
380 }
381
382 static uint32_t
383 ovn_port_allocate_key(struct ovn_datapath *od)
384 {
385     return allocate_tnlid(&od->port_tnlids, "port",
386                           (1u << 15) - 1, &od->port_key_hint);
387 }
388
389 static void
390 join_logical_ports(struct northd_context *ctx,
391                    struct hmap *datapaths, struct hmap *ports,
392                    struct ovs_list *sb_only, struct ovs_list *nb_only,
393                    struct ovs_list *both)
394 {
395     hmap_init(ports);
396     list_init(sb_only);
397     list_init(nb_only);
398     list_init(both);
399
400     const struct sbrec_port_binding *sb;
401     SBREC_PORT_BINDING_FOR_EACH (sb, ctx->ovnsb_idl) {
402         struct ovn_port *op = ovn_port_create(ports, sb->logical_port,
403                                               NULL, sb);
404         list_push_back(sb_only, &op->list);
405     }
406
407     struct ovn_datapath *od;
408     HMAP_FOR_EACH (od, key_node, datapaths) {
409         for (size_t i = 0; i < od->nb->n_ports; i++) {
410             const struct nbrec_logical_port *nb = od->nb->ports[i];
411             struct ovn_port *op = ovn_port_find(ports, nb->name);
412             if (op) {
413                 op->nb = nb;
414                 list_remove(&op->list);
415                 list_push_back(both, &op->list);
416             } else {
417                 op = ovn_port_create(ports, nb->name, nb, NULL);
418                 list_push_back(nb_only, &op->list);
419             }
420             op->od = od;
421         }
422     }
423 }
424
425 static void
426 ovn_port_update_sbrec(const struct ovn_port *op)
427 {
428     sbrec_port_binding_set_type(op->sb, op->nb->type);
429     sbrec_port_binding_set_options(op->sb, &op->nb->options);
430     sbrec_port_binding_set_datapath(op->sb, op->od->sb);
431     sbrec_port_binding_set_parent_port(op->sb, op->nb->parent_name);
432     sbrec_port_binding_set_tag(op->sb, op->nb->tag, op->nb->n_tag);
433     sbrec_port_binding_set_mac(op->sb, (const char **) op->nb->macs,
434                                op->nb->n_macs);
435 }
436
437 static void
438 build_ports(struct northd_context *ctx, struct hmap *datapaths,
439             struct hmap *ports)
440 {
441     struct ovs_list sb_only, nb_only, both;
442
443     join_logical_ports(ctx, datapaths, ports, &sb_only, &nb_only, &both);
444
445     /* For logical ports that are in both databases, update the southbound
446      * record based on northbound data.  Also index the in-use tunnel_keys. */
447     struct ovn_port *op, *next;
448     LIST_FOR_EACH_SAFE (op, next, list, &both) {
449         ovn_port_update_sbrec(op);
450
451         add_tnlid(&op->od->port_tnlids, op->sb->tunnel_key);
452         if (op->sb->tunnel_key > op->od->port_key_hint) {
453             op->od->port_key_hint = op->sb->tunnel_key;
454         }
455     }
456
457     /* Add southbound record for each unmatched northbound record. */
458     LIST_FOR_EACH_SAFE (op, next, list, &nb_only) {
459         uint16_t tunnel_key = ovn_port_allocate_key(op->od);
460         if (!tunnel_key) {
461             continue;
462         }
463
464         op->sb = sbrec_port_binding_insert(ctx->ovnsb_txn);
465         ovn_port_update_sbrec(op);
466
467         sbrec_port_binding_set_logical_port(op->sb, op->key);
468         sbrec_port_binding_set_tunnel_key(op->sb, tunnel_key);
469     }
470
471     /* Delete southbound records without northbound matches. */
472     LIST_FOR_EACH_SAFE(op, next, list, &sb_only) {
473         list_remove(&op->list);
474         sbrec_port_binding_delete(op->sb);
475         ovn_port_destroy(ports, op);
476     }
477 }
478 \f
479 #define OVN_MIN_MULTICAST 32768
480 #define OVN_MAX_MULTICAST 65535
481
482 struct multicast_group {
483     const char *name;
484     uint16_t key;               /* OVN_MIN_MULTICAST...OVN_MAX_MULTICAST. */
485 };
486
487 #define MC_FLOOD "_MC_flood"
488 static const struct multicast_group mc_flood = { MC_FLOOD, 65535 };
489
490 #define MC_UNKNOWN "_MC_unknown"
491 static const struct multicast_group mc_unknown = { MC_UNKNOWN, 65534 };
492
493 static bool
494 multicast_group_equal(const struct multicast_group *a,
495                       const struct multicast_group *b)
496 {
497     return !strcmp(a->name, b->name) && a->key == b->key;
498 }
499
500 /* Multicast group entry. */
501 struct ovn_multicast {
502     struct hmap_node hmap_node; /* Index on 'datapath' and 'key'. */
503     struct ovn_datapath *datapath;
504     const struct multicast_group *group;
505
506     struct ovn_port **ports;
507     size_t n_ports, allocated_ports;
508 };
509
510 static uint32_t
511 ovn_multicast_hash(const struct ovn_datapath *datapath,
512                    const struct multicast_group *group)
513 {
514     return hash_pointer(datapath, group->key);
515 }
516
517 static struct ovn_multicast *
518 ovn_multicast_find(struct hmap *mcgroups, struct ovn_datapath *datapath,
519                    const struct multicast_group *group)
520 {
521     struct ovn_multicast *mc;
522
523     HMAP_FOR_EACH_WITH_HASH (mc, hmap_node,
524                              ovn_multicast_hash(datapath, group), mcgroups) {
525         if (mc->datapath == datapath
526             && multicast_group_equal(mc->group, group)) {
527             return mc;
528         }
529     }
530     return NULL;
531 }
532
533 static void
534 ovn_multicast_add(struct hmap *mcgroups, const struct multicast_group *group,
535                   struct ovn_port *port)
536 {
537     struct ovn_datapath *od = port->od;
538     struct ovn_multicast *mc = ovn_multicast_find(mcgroups, od, group);
539     if (!mc) {
540         mc = xmalloc(sizeof *mc);
541         hmap_insert(mcgroups, &mc->hmap_node, ovn_multicast_hash(od, group));
542         mc->datapath = od;
543         mc->group = group;
544         mc->n_ports = 0;
545         mc->allocated_ports = 4;
546         mc->ports = xmalloc(mc->allocated_ports * sizeof *mc->ports);
547     }
548     if (mc->n_ports >= mc->allocated_ports) {
549         mc->ports = x2nrealloc(mc->ports, &mc->allocated_ports,
550                                sizeof *mc->ports);
551     }
552     mc->ports[mc->n_ports++] = port;
553 }
554
555 static void
556 ovn_multicast_destroy(struct hmap *mcgroups, struct ovn_multicast *mc)
557 {
558     if (mc) {
559         hmap_remove(mcgroups, &mc->hmap_node);
560         free(mc->ports);
561         free(mc);
562     }
563 }
564
565 static void
566 ovn_multicast_update_sbrec(const struct ovn_multicast *mc,
567                            const struct sbrec_multicast_group *sb)
568 {
569     struct sbrec_port_binding **ports = xmalloc(mc->n_ports * sizeof *ports);
570     for (size_t i = 0; i < mc->n_ports; i++) {
571         ports[i] = CONST_CAST(struct sbrec_port_binding *, mc->ports[i]->sb);
572     }
573     sbrec_multicast_group_set_ports(sb, ports, mc->n_ports);
574     free(ports);
575 }
576 \f
577 /* Logical flow generation.
578  *
579  * This code generates the Logical_Flow table in the southbound database, as a
580  * function of most of the northbound database.
581  */
582
583 struct ovn_lflow {
584     struct hmap_node hmap_node;
585
586     struct ovn_datapath *od;
587     enum ovn_pipeline { P_IN, P_OUT } pipeline;
588     uint8_t table_id;
589     uint16_t priority;
590     char *match;
591     char *actions;
592 };
593
594 static size_t
595 ovn_lflow_hash(const struct ovn_lflow *lflow)
596 {
597     size_t hash = uuid_hash(&lflow->od->key);
598     hash = hash_2words((lflow->table_id << 16) | lflow->priority, hash);
599     hash = hash_string(lflow->match, hash);
600     return hash_string(lflow->actions, hash);
601 }
602
603 static bool
604 ovn_lflow_equal(const struct ovn_lflow *a, const struct ovn_lflow *b)
605 {
606     return (a->od == b->od
607             && a->pipeline == b->pipeline
608             && a->table_id == b->table_id
609             && a->priority == b->priority
610             && !strcmp(a->match, b->match)
611             && !strcmp(a->actions, b->actions));
612 }
613
614 static void
615 ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od,
616               enum ovn_pipeline pipeline, uint8_t table_id, uint16_t priority,
617               char *match, char *actions)
618 {
619     lflow->od = od;
620     lflow->pipeline = pipeline;
621     lflow->table_id = table_id;
622     lflow->priority = priority;
623     lflow->match = match;
624     lflow->actions = actions;
625 }
626
627 static const char *
628 ingress_stage_to_str(int stage) {
629     switch (stage) {
630 #define INGRESS_STAGE(NAME, STR) case S_IN_##NAME: return #STR;
631     INGRESS_STAGES
632 #undef INGRESS_STAGE
633         default: return "<unknown>";
634     }
635 }
636
637 static const char *
638 egress_stage_to_str(int stage) {
639     switch (stage) {
640 #define EGRESS_STAGE(NAME, STR) case S_OUT_##NAME: return #STR;
641     EGRESS_STAGES
642 #undef EGRESS_STAGE
643         default: return "<unknown>";
644     }
645 }
646
647 /* Adds a row with the specified contents to the Logical_Flow table. */
648 static void
649 ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od,
650               enum ovn_pipeline pipeline, uint8_t table_id, uint16_t priority,
651               const char *match, const char *actions)
652 {
653     struct ovn_lflow *lflow = xmalloc(sizeof *lflow);
654     ovn_lflow_init(lflow, od, pipeline, table_id, priority,
655                    xstrdup(match), xstrdup(actions));
656     hmap_insert(lflow_map, &lflow->hmap_node, ovn_lflow_hash(lflow));
657 }
658
659 static struct ovn_lflow *
660 ovn_lflow_find(struct hmap *lflows, struct ovn_datapath *od,
661                enum ovn_pipeline pipeline, uint8_t table_id, uint16_t priority,
662                const char *match, const char *actions)
663 {
664     struct ovn_lflow target;
665     ovn_lflow_init(&target, od, pipeline, table_id, priority,
666                    CONST_CAST(char *, match), CONST_CAST(char *, actions));
667
668     struct ovn_lflow *lflow;
669     HMAP_FOR_EACH_WITH_HASH (lflow, hmap_node, ovn_lflow_hash(&target),
670                              lflows) {
671         if (ovn_lflow_equal(lflow, &target)) {
672             return lflow;
673         }
674     }
675     return NULL;
676 }
677
678 static void
679 ovn_lflow_destroy(struct hmap *lflows, struct ovn_lflow *lflow)
680 {
681     if (lflow) {
682         hmap_remove(lflows, &lflow->hmap_node);
683         free(lflow->match);
684         free(lflow->actions);
685         free(lflow);
686     }
687 }
688
689 /* Appends port security constraints on L2 address field 'eth_addr_field'
690  * (e.g. "eth.src" or "eth.dst") to 'match'.  'port_security', with
691  * 'n_port_security' elements, is the collection of port_security constraints
692  * from an OVN_NB Logical_Port row. */
693 static void
694 build_port_security(const char *eth_addr_field,
695                     char **port_security, size_t n_port_security,
696                     struct ds *match)
697 {
698     size_t base_len = match->length;
699     ds_put_format(match, " && %s == {", eth_addr_field);
700
701     size_t n = 0;
702     for (size_t i = 0; i < n_port_security; i++) {
703         struct eth_addr ea;
704
705         if (eth_addr_from_string(port_security[i], &ea)) {
706             ds_put_format(match, ETH_ADDR_FMT, ETH_ADDR_ARGS(ea));
707             ds_put_char(match, ' ');
708             n++;
709         }
710     }
711     ds_chomp(match, ' ');
712     ds_put_cstr(match, "}");
713
714     if (!n) {
715         match->length = base_len;
716     }
717 }
718
719 static bool
720 lport_is_enabled(const struct nbrec_logical_port *lport)
721 {
722     return !lport->enabled || *lport->enabled;
723 }
724
725 /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database,
726  * constructing their contents based on the OVN_NB database. */
727 static void
728 build_lflows(struct northd_context *ctx, struct hmap *datapaths,
729              struct hmap *ports)
730 {
731     /* This flow table structure is documented in ovn-northd(8), so please
732      * update ovn-northd.8.xml if you change anything. */
733
734     struct hmap lflows = HMAP_INITIALIZER(&lflows);
735     struct hmap mcgroups = HMAP_INITIALIZER(&mcgroups);
736
737     /* Ingress table 0: Admission control framework (priorities 0 and 100). */
738     struct ovn_datapath *od;
739     HMAP_FOR_EACH (od, key_node, datapaths) {
740         /* Logical VLANs not supported. */
741         ovn_lflow_add(&lflows, od, P_IN, S_IN_PORT_SEC, 100, "vlan.present",
742                       "drop;");
743
744         /* Broadcast/multicast source address is invalid. */
745         ovn_lflow_add(&lflows, od, P_IN, S_IN_PORT_SEC, 100, "eth.src[40]",
746                       "drop;");
747
748         /* Port security flows have priority 50 (see below) and will continue
749          * to the next table if packet source is acceptable. */
750     }
751
752     /* Ingress table 0: Ingress port security (priority 50). */
753     struct ovn_port *op;
754     HMAP_FOR_EACH (op, key_node, ports) {
755         if (!lport_is_enabled(op->nb)) {
756             /* Drop packets from disabled logical ports (since logical flow
757              * tables are default-drop). */
758             continue;
759         }
760
761         struct ds match = DS_EMPTY_INITIALIZER;
762         ds_put_cstr(&match, "inport == ");
763         json_string_escape(op->key, &match);
764         build_port_security("eth.src",
765                             op->nb->port_security, op->nb->n_port_security,
766                             &match);
767         ovn_lflow_add(&lflows, op->od, P_IN, S_IN_PORT_SEC, 50,
768                       ds_cstr(&match), "next;");
769         ds_destroy(&match);
770     }
771
772     /* Ingress table 1: ACLs (any priority). */
773     HMAP_FOR_EACH (od, key_node, datapaths) {
774         for (size_t i = 0; i < od->nb->n_acls; i++) {
775             const struct nbrec_acl *acl = od->nb->acls[i];
776             const char *action;
777
778             if (strcmp(acl->direction, "from-lport")) {
779                 continue;
780             }
781
782             action = (!strcmp(acl->action, "allow") ||
783                       !strcmp(acl->action, "allow-related"))
784                 ? "next;" : "drop;";
785             ovn_lflow_add(&lflows, od, P_IN, S_IN_ACL, acl->priority,
786                           acl->match, action);
787         }
788     }
789     HMAP_FOR_EACH (od, key_node, datapaths) {
790         ovn_lflow_add(&lflows, od, P_IN, S_IN_ACL, 0, "1", "next;");
791     }
792
793     /* Ingress table 2: Destination lookup, broadcast and multicast handling
794      * (priority 100). */
795     HMAP_FOR_EACH (op, key_node, ports) {
796         if (lport_is_enabled(op->nb)) {
797             ovn_multicast_add(&mcgroups, &mc_flood, op);
798         }
799     }
800     HMAP_FOR_EACH (od, key_node, datapaths) {
801         ovn_lflow_add(&lflows, od, P_IN, S_IN_L2_LKUP, 100, "eth.dst[40]",
802                       "outport = \""MC_FLOOD"\"; output;");
803     }
804
805     /* Ingress table 2: Destination lookup, unicast handling (priority 50), */
806     HMAP_FOR_EACH (op, key_node, ports) {
807         for (size_t i = 0; i < op->nb->n_macs; i++) {
808             struct eth_addr mac;
809
810             if (eth_addr_from_string(op->nb->macs[i], &mac)) {
811                 struct ds match, actions;
812
813                 ds_init(&match);
814                 ds_put_format(&match, "eth.dst == %s", op->nb->macs[i]);
815
816                 ds_init(&actions);
817                 ds_put_cstr(&actions, "outport = ");
818                 json_string_escape(op->nb->name, &actions);
819                 ds_put_cstr(&actions, "; output;");
820                 ovn_lflow_add(&lflows, op->od, P_IN, S_IN_L2_LKUP, 50,
821                               ds_cstr(&match), ds_cstr(&actions));
822                 ds_destroy(&actions);
823                 ds_destroy(&match);
824             } else if (!strcmp(op->nb->macs[i], "unknown")) {
825                 if (lport_is_enabled(op->nb)) {
826                     ovn_multicast_add(&mcgroups, &mc_unknown, op);
827                     op->od->has_unknown = true;
828                 }
829             } else {
830                 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
831
832                 VLOG_INFO_RL(&rl, "%s: invalid syntax '%s' in macs column",
833                              op->nb->name, op->nb->macs[i]);
834             }
835         }
836     }
837
838     /* Ingress table 2: Destination lookup for unknown MACs (priority 0). */
839     HMAP_FOR_EACH (od, key_node, datapaths) {
840         if (od->has_unknown) {
841             ovn_lflow_add(&lflows, od, P_IN, S_IN_L2_LKUP, 0, "1",
842                           "outport = \""MC_UNKNOWN"\"; output;");
843         }
844     }
845
846     /* Egress table 0: ACLs (any priority). */
847     HMAP_FOR_EACH (od, key_node, datapaths) {
848         for (size_t i = 0; i < od->nb->n_acls; i++) {
849             const struct nbrec_acl *acl = od->nb->acls[i];
850             const char *action;
851
852             if (strcmp(acl->direction, "to-lport")) {
853                 continue;
854             }
855
856             action = (!strcmp(acl->action, "allow") ||
857                       !strcmp(acl->action, "allow-related"))
858                 ? "next;" : "drop;";
859             ovn_lflow_add(&lflows, od, P_OUT, S_OUT_ACL, acl->priority,
860                           acl->match, action);
861         }
862     }
863     HMAP_FOR_EACH (od, key_node, datapaths) {
864         ovn_lflow_add(&lflows, od, P_OUT, S_OUT_ACL, 0, "1", "next;");
865     }
866
867     /* Egress table 1: Egress port security multicast/broadcast (priority
868      * 100). */
869     HMAP_FOR_EACH (od, key_node, datapaths) {
870         ovn_lflow_add(&lflows, od, P_OUT, S_OUT_PORT_SEC, 100, "eth.dst[40]",
871                       "output;");
872     }
873
874     /* Egress table 1: Egress port security (priorities 50 and 150).
875      *
876      * Priority 50 rules implement port security for enabled logical port.
877      *
878      * Priority 150 rules drop packets to disabled logical ports, so that they
879      * don't even receive multicast or broadcast packets. */
880     HMAP_FOR_EACH (op, key_node, ports) {
881         struct ds match;
882
883         ds_init(&match);
884         ds_put_cstr(&match, "outport == ");
885         json_string_escape(op->key, &match);
886         if (lport_is_enabled(op->nb)) {
887             build_port_security("eth.dst",
888                                 op->nb->port_security, op->nb->n_port_security,
889                                 &match);
890             ovn_lflow_add(&lflows, op->od, P_OUT, S_OUT_PORT_SEC, 50,
891                           ds_cstr(&match), "output;");
892         } else {
893             ovn_lflow_add(&lflows, op->od, P_OUT, S_OUT_PORT_SEC, 150,
894                           ds_cstr(&match), "drop;");
895         }
896
897         ds_destroy(&match);
898     }
899
900     /* Push changes to the Logical_Flow table to database. */
901     const struct sbrec_logical_flow *sbflow, *next_sbflow;
902     SBREC_LOGICAL_FLOW_FOR_EACH_SAFE (sbflow, next_sbflow, ctx->ovnsb_idl) {
903         struct ovn_datapath *od
904             = ovn_datapath_from_sbrec(datapaths, sbflow->logical_datapath);
905         if (!od) {
906             sbrec_logical_flow_delete(sbflow);
907             continue;
908         }
909
910         struct ovn_lflow *lflow = ovn_lflow_find(
911             &lflows, od, (!strcmp(sbflow->pipeline, "ingress") ? P_IN : P_OUT),
912             sbflow->table_id, sbflow->priority,
913             sbflow->match, sbflow->actions);
914         if (lflow) {
915             ovn_lflow_destroy(&lflows, lflow);
916         } else {
917             sbrec_logical_flow_delete(sbflow);
918         }
919     }
920     struct ovn_lflow *lflow, *next_lflow;
921     HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, &lflows) {
922         sbflow = sbrec_logical_flow_insert(ctx->ovnsb_txn);
923         sbrec_logical_flow_set_logical_datapath(sbflow, lflow->od->sb);
924         sbrec_logical_flow_set_pipeline(
925             sbflow, lflow->pipeline == P_IN ? "ingress" : "egress");
926         sbrec_logical_flow_set_table_id(sbflow, lflow->table_id);
927         sbrec_logical_flow_set_priority(sbflow, lflow->priority);
928         sbrec_logical_flow_set_match(sbflow, lflow->match);
929         sbrec_logical_flow_set_actions(sbflow, lflow->actions);
930
931         const struct smap ids = SMAP_CONST1(
932             &ids, "stage-name",
933             (lflow->pipeline == P_IN
934              ? ingress_stage_to_str(lflow->table_id)
935              : egress_stage_to_str(lflow->table_id)));
936         sbrec_logical_flow_set_external_ids(sbflow, &ids);
937
938         ovn_lflow_destroy(&lflows, lflow);
939     }
940     hmap_destroy(&lflows);
941
942     /* Push changes to the Multicast_Group table to database. */
943     const struct sbrec_multicast_group *sbmc, *next_sbmc;
944     SBREC_MULTICAST_GROUP_FOR_EACH_SAFE (sbmc, next_sbmc, ctx->ovnsb_idl) {
945         struct ovn_datapath *od = ovn_datapath_from_sbrec(datapaths,
946                                                           sbmc->datapath);
947         if (!od) {
948             sbrec_multicast_group_delete(sbmc);
949             continue;
950         }
951
952         struct multicast_group group = { .name = sbmc->name,
953                                          .key = sbmc->tunnel_key };
954         struct ovn_multicast *mc = ovn_multicast_find(&mcgroups, od, &group);
955         if (mc) {
956             ovn_multicast_update_sbrec(mc, sbmc);
957             ovn_multicast_destroy(&mcgroups, mc);
958         } else {
959             sbrec_multicast_group_delete(sbmc);
960         }
961     }
962     struct ovn_multicast *mc, *next_mc;
963     HMAP_FOR_EACH_SAFE (mc, next_mc, hmap_node, &mcgroups) {
964         sbmc = sbrec_multicast_group_insert(ctx->ovnsb_txn);
965         sbrec_multicast_group_set_datapath(sbmc, mc->datapath->sb);
966         sbrec_multicast_group_set_name(sbmc, mc->group->name);
967         sbrec_multicast_group_set_tunnel_key(sbmc, mc->group->key);
968         ovn_multicast_update_sbrec(mc, sbmc);
969         ovn_multicast_destroy(&mcgroups, mc);
970     }
971     hmap_destroy(&mcgroups);
972 }
973 \f
974 static void
975 ovnnb_db_changed(struct northd_context *ctx)
976 {
977     VLOG_DBG("ovn-nb db contents have changed.");
978
979     struct hmap datapaths, ports;
980     build_datapaths(ctx, &datapaths);
981     build_ports(ctx, &datapaths, &ports);
982     build_lflows(ctx, &datapaths, &ports);
983
984     struct ovn_datapath *dp, *next_dp;
985     HMAP_FOR_EACH_SAFE (dp, next_dp, key_node, &datapaths) {
986         ovn_datapath_destroy(&datapaths, dp);
987     }
988     hmap_destroy(&datapaths);
989
990     struct ovn_port *port, *next_port;
991     HMAP_FOR_EACH_SAFE (port, next_port, key_node, &ports) {
992         ovn_port_destroy(&ports, port);
993     }
994     hmap_destroy(&ports);
995 }
996
997 /*
998  * The only change we get notified about is if the 'chassis' column of the
999  * 'Port_Binding' table changes.  When this column is not empty, it means we
1000  * need to set the corresponding logical port as 'up' in the northbound DB.
1001  */
1002 static void
1003 ovnsb_db_changed(struct northd_context *ctx)
1004 {
1005     struct hmap lports_hmap;
1006     const struct sbrec_port_binding *sb;
1007     const struct nbrec_logical_port *nb;
1008
1009     struct lport_hash_node {
1010         struct hmap_node node;
1011         const struct nbrec_logical_port *nb;
1012     } *hash_node, *hash_node_next;
1013
1014     VLOG_DBG("Recalculating port up states for ovn-nb db.");
1015
1016     hmap_init(&lports_hmap);
1017
1018     NBREC_LOGICAL_PORT_FOR_EACH(nb, ctx->ovnnb_idl) {
1019         hash_node = xzalloc(sizeof *hash_node);
1020         hash_node->nb = nb;
1021         hmap_insert(&lports_hmap, &hash_node->node, hash_string(nb->name, 0));
1022     }
1023
1024     SBREC_PORT_BINDING_FOR_EACH(sb, ctx->ovnsb_idl) {
1025         nb = NULL;
1026         HMAP_FOR_EACH_WITH_HASH(hash_node, node,
1027                                 hash_string(sb->logical_port, 0),
1028                                 &lports_hmap) {
1029             if (!strcmp(sb->logical_port, hash_node->nb->name)) {
1030                 nb = hash_node->nb;
1031                 break;
1032             }
1033         }
1034
1035         if (!nb) {
1036             /* The logical port doesn't exist for this port binding.  This can
1037              * happen under normal circumstances when ovn-northd hasn't gotten
1038              * around to pruning the Port_Binding yet. */
1039             continue;
1040         }
1041
1042         if (sb->chassis && (!nb->up || !*nb->up)) {
1043             bool up = true;
1044             nbrec_logical_port_set_up(nb, &up, 1);
1045         } else if (!sb->chassis && (!nb->up || *nb->up)) {
1046             bool up = false;
1047             nbrec_logical_port_set_up(nb, &up, 1);
1048         }
1049     }
1050
1051     HMAP_FOR_EACH_SAFE(hash_node, hash_node_next, node, &lports_hmap) {
1052         hmap_remove(&lports_hmap, &hash_node->node);
1053         free(hash_node);
1054     }
1055     hmap_destroy(&lports_hmap);
1056 }
1057 \f
1058
1059 static char *default_db_;
1060
1061 static const char *
1062 default_db(void)
1063 {
1064     if (!default_db_) {
1065         default_db_ = xasprintf("unix:%s/db.sock", ovs_rundir());
1066     }
1067     return default_db_;
1068 }
1069
1070 static void
1071 parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1072 {
1073     enum {
1074         DAEMON_OPTION_ENUMS,
1075         VLOG_OPTION_ENUMS,
1076     };
1077     static const struct option long_options[] = {
1078         {"ovnsb-db", required_argument, NULL, 'd'},
1079         {"ovnnb-db", required_argument, NULL, 'D'},
1080         {"help", no_argument, NULL, 'h'},
1081         {"options", no_argument, NULL, 'o'},
1082         {"version", no_argument, NULL, 'V'},
1083         DAEMON_LONG_OPTIONS,
1084         VLOG_LONG_OPTIONS,
1085         STREAM_SSL_LONG_OPTIONS,
1086         {NULL, 0, NULL, 0},
1087     };
1088     char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
1089
1090     for (;;) {
1091         int c;
1092
1093         c = getopt_long(argc, argv, short_options, long_options, NULL);
1094         if (c == -1) {
1095             break;
1096         }
1097
1098         switch (c) {
1099         DAEMON_OPTION_HANDLERS;
1100         VLOG_OPTION_HANDLERS;
1101         STREAM_SSL_OPTION_HANDLERS;
1102
1103         case 'd':
1104             ovnsb_db = optarg;
1105             break;
1106
1107         case 'D':
1108             ovnnb_db = optarg;
1109             break;
1110
1111         case 'h':
1112             usage();
1113             exit(EXIT_SUCCESS);
1114
1115         case 'o':
1116             ovs_cmdl_print_options(long_options);
1117             exit(EXIT_SUCCESS);
1118
1119         case 'V':
1120             ovs_print_version(0, 0);
1121             exit(EXIT_SUCCESS);
1122
1123         default:
1124             break;
1125         }
1126     }
1127
1128     if (!ovnsb_db) {
1129         ovnsb_db = default_db();
1130     }
1131
1132     if (!ovnnb_db) {
1133         ovnnb_db = default_db();
1134     }
1135
1136     free(short_options);
1137 }
1138
1139 static void
1140 add_column_noalert(struct ovsdb_idl *idl,
1141                    const struct ovsdb_idl_column *column)
1142 {
1143     ovsdb_idl_add_column(idl, column);
1144     ovsdb_idl_omit_alert(idl, column);
1145 }
1146
1147 int
1148 main(int argc, char *argv[])
1149 {
1150     extern struct vlog_module VLM_reconnect;
1151     struct ovsdb_idl *ovnnb_idl, *ovnsb_idl;
1152     unsigned int ovnnb_seqno, ovn_seqno;
1153     int res = EXIT_SUCCESS;
1154     struct northd_context ctx = {
1155         .ovnsb_txn = NULL,
1156     };
1157     bool ovnnb_changes_pending = false;
1158     bool ovn_changes_pending = false;
1159     struct unixctl_server *unixctl;
1160     int retval;
1161     bool exiting;
1162
1163     fatal_ignore_sigpipe();
1164     set_program_name(argv[0]);
1165     service_start(&argc, &argv);
1166     vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
1167     vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
1168     parse_options(argc, argv);
1169
1170     daemonize_start();
1171
1172     retval = unixctl_server_create(NULL, &unixctl);
1173     if (retval) {
1174         exit(EXIT_FAILURE);
1175     }
1176     unixctl_command_register("exit", "", 0, 0, ovn_northd_exit, &exiting);
1177
1178     daemonize_complete();
1179
1180     nbrec_init();
1181     sbrec_init();
1182
1183     /* We want to detect all changes to the ovn-nb db. */
1184     ctx.ovnnb_idl = ovnnb_idl = ovsdb_idl_create(ovnnb_db,
1185             &nbrec_idl_class, true, true);
1186
1187     ctx.ovnsb_idl = ovnsb_idl = ovsdb_idl_create(ovnsb_db,
1188             &sbrec_idl_class, false, true);
1189
1190     ovsdb_idl_add_table(ovnsb_idl, &sbrec_table_logical_flow);
1191     add_column_noalert(ovnsb_idl, &sbrec_logical_flow_col_logical_datapath);
1192     add_column_noalert(ovnsb_idl, &sbrec_logical_flow_col_pipeline);
1193     add_column_noalert(ovnsb_idl, &sbrec_logical_flow_col_table_id);
1194     add_column_noalert(ovnsb_idl, &sbrec_logical_flow_col_priority);
1195     add_column_noalert(ovnsb_idl, &sbrec_logical_flow_col_match);
1196     add_column_noalert(ovnsb_idl, &sbrec_logical_flow_col_actions);
1197
1198     ovsdb_idl_add_table(ovnsb_idl, &sbrec_table_multicast_group);
1199     add_column_noalert(ovnsb_idl, &sbrec_multicast_group_col_datapath);
1200     add_column_noalert(ovnsb_idl, &sbrec_multicast_group_col_tunnel_key);
1201     add_column_noalert(ovnsb_idl, &sbrec_multicast_group_col_name);
1202     add_column_noalert(ovnsb_idl, &sbrec_multicast_group_col_ports);
1203
1204     ovsdb_idl_add_table(ovnsb_idl, &sbrec_table_datapath_binding);
1205     add_column_noalert(ovnsb_idl, &sbrec_datapath_binding_col_tunnel_key);
1206     add_column_noalert(ovnsb_idl, &sbrec_datapath_binding_col_external_ids);
1207
1208     ovsdb_idl_add_table(ovnsb_idl, &sbrec_table_port_binding);
1209     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_datapath);
1210     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_logical_port);
1211     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_tunnel_key);
1212     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_parent_port);
1213     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_tag);
1214     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_type);
1215     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_options);
1216     add_column_noalert(ovnsb_idl, &sbrec_port_binding_col_mac);
1217     ovsdb_idl_add_column(ovnsb_idl, &sbrec_port_binding_col_chassis);
1218
1219     /*
1220      * The loop here just runs the IDL in a loop waiting for the seqno to
1221      * change, which indicates that the contents of the db have changed.
1222      *
1223      * If the contents of the ovn-nb db change, the mappings to the ovn-sb
1224      * db must be recalculated.
1225      *
1226      * If the contents of the ovn-sb db change, it means the 'up' state of
1227      * a port may have changed, as that's the only type of change ovn-northd is
1228      * watching for.
1229      */
1230
1231     ovnnb_seqno = ovsdb_idl_get_seqno(ovnnb_idl);
1232     ovn_seqno = ovsdb_idl_get_seqno(ovnsb_idl);
1233     exiting = false;
1234     while (!exiting) {
1235         ovsdb_idl_run(ovnnb_idl);
1236         ovsdb_idl_run(ovnsb_idl);
1237         unixctl_server_run(unixctl);
1238
1239         if (!ovsdb_idl_is_alive(ovnnb_idl)) {
1240             int retval = ovsdb_idl_get_last_error(ovnnb_idl);
1241             VLOG_ERR("%s: database connection failed (%s)",
1242                     ovnnb_db, ovs_retval_to_string(retval));
1243             res = EXIT_FAILURE;
1244             break;
1245         }
1246
1247         if (!ovsdb_idl_is_alive(ovnsb_idl)) {
1248             int retval = ovsdb_idl_get_last_error(ovnsb_idl);
1249             VLOG_ERR("%s: database connection failed (%s)",
1250                     ovnsb_db, ovs_retval_to_string(retval));
1251             res = EXIT_FAILURE;
1252             break;
1253         }
1254
1255         if (ovnnb_seqno != ovsdb_idl_get_seqno(ovnnb_idl)) {
1256             ovnnb_seqno = ovsdb_idl_get_seqno(ovnnb_idl);
1257             ovnnb_changes_pending = true;
1258         }
1259
1260         if (ovn_seqno != ovsdb_idl_get_seqno(ovnsb_idl)) {
1261             ovn_seqno = ovsdb_idl_get_seqno(ovnsb_idl);
1262             ovn_changes_pending = true;
1263         }
1264
1265         /*
1266          * If there are any pending changes, we delay recalculating the
1267          * necessary updates until after an existing transaction finishes.
1268          * This avoids the possibility of rapid updates causing ovn-northd to
1269          * never be able to successfully make the corresponding updates to the
1270          * other db.  Instead, pending changes are batched up until the next
1271          * time we get a chance to calculate the new state and apply it.
1272          */
1273
1274         if (ovnnb_changes_pending && !ctx.ovnsb_txn) {
1275             /*
1276              * The OVN-nb db contents have changed, so create a transaction for
1277              * updating the OVN-sb DB.
1278              */
1279             ctx.ovnsb_txn = ovsdb_idl_txn_create(ctx.ovnsb_idl);
1280             ovsdb_idl_txn_add_comment(ctx.ovnsb_txn,
1281                                       "ovn-northd: northbound db changed");
1282             ovnnb_db_changed(&ctx);
1283             ovnnb_changes_pending = false;
1284         }
1285
1286         if (ovn_changes_pending && !ctx.ovnnb_txn) {
1287             /*
1288              * The OVN-sb db contents have changed, so create a transaction for
1289              * updating the northbound DB.
1290              */
1291             ctx.ovnnb_txn = ovsdb_idl_txn_create(ctx.ovnnb_idl);
1292             ovsdb_idl_txn_add_comment(ctx.ovnnb_txn,
1293                                       "ovn-northd: southbound db changed");
1294             ovnsb_db_changed(&ctx);
1295             ovn_changes_pending = false;
1296         }
1297
1298         if (ctx.ovnnb_txn) {
1299             enum ovsdb_idl_txn_status txn_status;
1300             txn_status = ovsdb_idl_txn_commit(ctx.ovnnb_txn);
1301             switch (txn_status) {
1302             case TXN_UNCOMMITTED:
1303             case TXN_INCOMPLETE:
1304                 /* Come back around and try to commit this transaction again */
1305                 break;
1306             case TXN_ABORTED:
1307             case TXN_TRY_AGAIN:
1308             case TXN_NOT_LOCKED:
1309             case TXN_ERROR:
1310                 /* Something went wrong, so try creating a new transaction. */
1311                 ovn_changes_pending = true;
1312             case TXN_UNCHANGED:
1313             case TXN_SUCCESS:
1314                 ovsdb_idl_txn_destroy(ctx.ovnnb_txn);
1315                 ctx.ovnnb_txn = NULL;
1316             }
1317         }
1318
1319         if (ctx.ovnsb_txn) {
1320             enum ovsdb_idl_txn_status txn_status;
1321             txn_status = ovsdb_idl_txn_commit(ctx.ovnsb_txn);
1322             switch (txn_status) {
1323             case TXN_UNCOMMITTED:
1324             case TXN_INCOMPLETE:
1325                 /* Come back around and try to commit this transaction again */
1326                 break;
1327             case TXN_ABORTED:
1328             case TXN_TRY_AGAIN:
1329             case TXN_NOT_LOCKED:
1330             case TXN_ERROR:
1331                 /* Something went wrong, so try creating a new transaction. */
1332                 ovnnb_changes_pending = true;
1333             case TXN_UNCHANGED:
1334             case TXN_SUCCESS:
1335                 ovsdb_idl_txn_destroy(ctx.ovnsb_txn);
1336                 ctx.ovnsb_txn = NULL;
1337             }
1338         }
1339
1340         if (ovnnb_seqno == ovsdb_idl_get_seqno(ovnnb_idl) &&
1341                 ovn_seqno == ovsdb_idl_get_seqno(ovnsb_idl)) {
1342             ovsdb_idl_wait(ovnnb_idl);
1343             ovsdb_idl_wait(ovnsb_idl);
1344             if (ctx.ovnnb_txn) {
1345                 ovsdb_idl_txn_wait(ctx.ovnnb_txn);
1346             }
1347             if (ctx.ovnsb_txn) {
1348                 ovsdb_idl_txn_wait(ctx.ovnsb_txn);
1349             }
1350             unixctl_server_wait(unixctl);
1351             if (exiting) {
1352                 poll_immediate_wake();
1353             }
1354             poll_block();
1355         }
1356         if (should_service_stop()) {
1357             exiting = true;
1358         }
1359     }
1360
1361     unixctl_server_destroy(unixctl);
1362     ovsdb_idl_destroy(ovnsb_idl);
1363     ovsdb_idl_destroy(ovnnb_idl);
1364     service_stop();
1365
1366     free(default_db_);
1367
1368     exit(res);
1369 }
1370
1371 static void
1372 ovn_northd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
1373                 const char *argv[] OVS_UNUSED, void *exiting_)
1374 {
1375     bool *exiting = exiting_;
1376     *exiting = true;
1377
1378     unixctl_command_reply(conn, NULL);
1379 }