summaryrefslogtreecommitdiff
path: root/ovn/northd/ovn-northd.8.xml
blob: 22edba9c4f19960ae92962767fe7de82232e33b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
<?xml version="1.0" encoding="utf-8"?>
<manpage program="ovn-northd" section="8" title="ovn-northd">
    <h1>Name</h1>
    <p>ovn-northd -- Open Virtual Network central control daemon</p>

    <h1>Synopsis</h1>
    <p><code>ovn-northd</code> [<var>options</var>]</p>

    <h1>Description</h1>
    <p>
      <code>ovn-northd</code> is a centralized daemon responsible for
      translating the high-level OVN configuration into logical
      configuration consumable by daemons such as
      <code>ovn-controller</code>.  It translates the logical network
      configuration in terms of conventional network concepts, taken
      from the OVN Northbound Database (see <code>ovn-nb</code>(5)),
      into logical datapath flows in the OVN Southbound Database (see
      <code>ovn-sb</code>(5)) below it.
    </p>

    <h1>Configuration</h1>
    <p>
      <code>ovn-northd</code> requires a connection to the Northbound
      and Southbound databases.  The defaults are <code>ovnnb_db.sock</code>
      and <code>ovnsb_db.sock</code> respectively
      in the local Open vSwitch's "run" directory.  This may be
      overridden with the following commands:
    </p>
    <ul>
      <li>
        <p>
          <code>--ovnnb-db=<var>database</var></code>
        </p>
        <p>
          The database containing the OVN Northbound Database.
        </p>
      </li>
      <li>
        <p>
          <code>--ovnsb-db=<var>database</var></code>
        </p>
        <p>
          The database containing the OVN Southbound Database.
        </p>
      </li>
    </ul>
    <p>
      The <var>database</var> argument must take one of the following forms:
    </p>
    <ul>
      <li>
        <p>
          <code>ssl:<var>ip</var>:<var>port</var></code>
        </p>
        <p>
          The specified SSL <var>port</var> on the host at the given
          <var>ip</var>, which must be expressed as an IP address (not a DNS
          name) in IPv4 or IPv6 address format.  If <var>ip</var> is an IPv6
          address, then wrap <var>ip</var> with square brackets, e.g.:
          <code>ssl:[::1]:6640</code>.  The <code>--private-key</code>,
          <code>--certificate</code>, and <code>--ca-cert</code> options are
          mandatory when this form is used.
        </p>
      </li>
      <li>
        <p>
          <code>tcp:<var>ip</var>:<var>port</var></code>
        </p>
        <p>
          Connect to the given TCP <var>port</var> on <var>ip</var>, where
          <var>ip</var> can be IPv4 or IPv6 address. If <var>ip</var> is an
          IPv6 address, then wrap <var>ip</var> with square brackets, e.g.:
          <code>tcp:[::1]:6640</code>.
        </p>
      </li>
      <li>
        <p>
          <code>unix:<var>file</var></code>
        </p>
        <p>
          On POSIX, connect to the Unix domain server socket named
          <var>file</var>.
        </p>
        <p>
          On Windows, connect to a localhost TCP port whose value is written
          in <var>file</var>.
        </p>
      </li>
    </ul>

    <h1>Runtime Management Commands</h1>
    <p>
      <code>ovs-appctl</code> can send commands to a running
      <code>ovn-northd</code> process.  The currently supported commands
      are described below.
      <dl>
      <dt><code>exit</code></dt>
      <dd>
        Causes <code>ovn-northd</code> to gracefully terminate.
      </dd>
      </dl>
    </p>

    <h1>Logical Flow Table Structure</h1>

    <p>
      One of the main purposes of <code>ovn-northd</code> is to populate the
      <code>Logical_Flow</code> table in the <code>OVN_Southbound</code>
      database.  This section describes how <code>ovn-northd</code> does this
      for switch and router logical datapaths.
    </p>

    <h2>Logical Switch Datapaths</h2>

    <h3>Ingress Table 0: Admission Control and Ingress Port Security - L2</h3>

    <p>
      Ingress table 0 contains these logical flows:
    </p>

    <ul>
      <li>
        Priority 100 flows to drop packets with VLAN tags or multicast Ethernet
        source addresses.
      </li>

      <li>
        Priority 50 flows that implement ingress port security for each enabled
        logical port.  For logical ports on which port security is enabled,
        these match the <code>inport</code> and the valid <code>eth.src</code>
        address(es) and advance only those packets to the next flow table.  For
        logical ports on which port security is not enabled, these advance all
        packets that match the <code>inport</code>.
      </li>
    </ul>

    <p>
      There are no flows for disabled logical ports because the default-drop
      behavior of logical flow tables causes packets that ingress from them to
      be dropped.
    </p>

    <h3>Ingress Table 1: Ingress Port Security - IP</h3>

    <p>
      Ingress table 1 contains these logical flows:
    </p>

    <ul>
      <li>
        <p>
          For each element in the port security set having one or more IPv4 or
          IPv6 addresses (or both),
        </p>

        <ul>
          <li>
            Priority 90 flow to allow IPv4 traffic if it has IPv4 addresses
            which match the <code>inport</code>, valid <code>eth.src</code>
            and valid <code>ip4.src</code> address(es).
          </li>

          <li>
            Priority 90 flow to allow IPv4 DHCP discovery traffic if it has a
            valid <code>eth.src</code>. This is necessary since DHCP discovery
            messages are sent from the unspecified IPv4 address (0.0.0.0) since
            the IPv4 address has not yet been assigned.
          </li>

          <li>
            Priority 90 flow to allow IPv6 traffic if it has IPv6 addresses
            which match the <code>inport</code>, valid <code>eth.src</code> and
            valid <code>ip6.src</code> address(es).
          </li>

          <li>
            Priority 90 flow to allow IPv6 DAD (Duplicate Address Detection)
            traffic if it has a valid <code>eth.src</code>. This is is
            necessary since DAD include requires joining an multicast group and
            sending neighbor solicitations for the newly assigned address. Since
            no address is yet assigned, these are sent from the unspecified
            IPv6 address (::).
          </li>

          <li>
            Priority 80 flow to drop IP (both IPv4 and IPv6) traffic which
            match the <code>inport</code> and valid <code>eth.src</code>.
          </li>
        </ul>
      </li>

      <li>
        One priority-0 fallback flow that matches all packets and advances to
        table 2.
      </li>
    </ul>

    <h3>Ingress Table 2: Ingress Port Security - Neighbor discovery</h3>

    <p>
      Ingress table 2 contains these logical flows:
    </p>

    <ul>
      <li>
        <p>
          For each element in the port security set,
        </p>

        <ul>
          <li>
            Priority 90 flow to allow ARP traffic which match the
            <code>inport</code> and valid <code>eth.src</code> and
            <code>arp.sha</code>. If the element has one or more
            IPv4 addresses, then it also matches the valid
            <code>arp.spa</code>.
          </li>

          <li>
            Priority 90 flow to allow IPv6 Neighbor Solicitation and
            Advertisement traffic which match the <code>inport</code>,
            valid <code>eth.src</code> and
            <code>nd.sll</code>/<code>nd.tll</code>.
            If the element has one or more IPv6 addresses, then it also
            matches the valid <code>nd.target</code> address(es) for Neighbor
            Advertisement traffic.
          </li>

          <li>
            Priority 80 flow to drop ARP and IPv6 Neighbor Solicitation and
            Advertisement traffic which match the <code>inport</code> and
            valid <code>eth.src</code>.
          </li>
        </ul>
      </li>

      <li>
        One priority-0 fallback flow that matches all packets and advances to
        table 3.
      </li>
    </ul>

    <h3>Ingress Table 3: <code>from-lport</code> Pre-ACLs</h3>

    <p>
      Ingress table 3 prepares flows for possible stateful ACL processing
      in table 4.  It contains a priority-0 flow that simply moves
      traffic to table 4.  If stateful ACLs are used in the logical
      datapath, a priority-100 flow is added that sends IP packets to
      the connection tracker before advancing to table 4.
    </p>

    <h3>Ingress table 4: <code>from-lport</code> ACLs</h3>

    <p>
      Logical flows in this table closely reproduce those in the
      <code>ACL</code> table in the <code>OVN_Northbound</code> database
      for the <code>from-lport</code> direction.  <code>allow</code>
      ACLs translate into logical flows with the <code>next;</code>
      action, <code>allow-related</code> ACLs translate into logical
      flows with the <code>ct_commit; next;</code> actions, other ACLs
      translate to <code>drop;</code>.  The <code>priority</code> values
      from the <code>ACL</code> table have a limited range and have 1000
      added to them to leave room for OVN default flows at both higher
      and lower priorities.
    </p>

    <p>
      Ingress table 4 also contains a priority 0 flow with action
      <code>next;</code>, so that ACLs allow packets by default.  If the
      logical datapath has a statetful ACL, the following flows will
      also be added:
    </p>

    <ul>
      <li>
        A priority-1 flow to commit IP traffic to the connection
        tracker.  This is needed for the default allow policy because,
        while the initiater's direction may not have any stateful rules,
        the server's may and then its return traffic would not be known
        and marked as invalid.
      </li>

      <li>
        A priority-65535 flow that allows any traffic that has been
        committed to the connection tracker (i.e., established flows).
      </li>

      <li>
        A priority-65535 flow that allows any traffic that is considered
        related to a committed flow in the connection tracker (e.g., an
        ICMP Port Unreachable from a non-listening UDP port).
      </li>

      <li>
        A priority-65535 flow that drops all traffic marked by the
        connection tracker as invalid.
      </li>
    </ul>

    <h3>Ingress Table 5: ARP responder</h3>

    <p>
      This table implements ARP responder for known IPs.  It contains these
      logical flows:
    </p>

    <ul>
      <li>
        Priority-100 flows to skip ARP responder if inport is of type
        <code>localnet</code>, and advances directly to table 6.
      </li>

      <li>
        <p>
          Priority-50 flows that matches ARP requests to each known IP address
          <var>A</var> of logical port <var>P</var>, and respond with ARP
          replies directly with corresponding Ethernet address <var>E</var>:
        </p>

        <pre>
eth.dst = eth.src;
eth.src = <var>E</var>;
arp.op = 2; /* ARP reply. */
arp.tha = arp.sha;
arp.sha = <var>E</var>;
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = <var>P</var>;
inport = ""; /* Allow sending out inport. */
output;
        </pre>

        <p>
          These flows are omitted for logical ports (other than router ports)
          that are down.
        </p>
      </li>

      <li>
        One priority-0 fallback flow that matches all packets and advances to
        table 6.
      </li>
    </ul>

    <h3>Ingress Table 6: Destination Lookup</h3>

    <p>
      This table implements switching behavior.  It contains these logical
      flows:
    </p>

    <ul>
      <li>
        A priority-100 flow that outputs all packets with an Ethernet broadcast
        or multicast <code>eth.dst</code> to the <code>MC_FLOOD</code>
        multicast group, which <code>ovn-northd</code> populates with all
        enabled logical ports.
      </li>

      <li>
        One priority-50 flow that matches each known Ethernet address against
        <code>eth.dst</code> and outputs the packet to the single associated
        output port.
      </li>

      <li>
        One priority-0 fallback flow that matches all packets and outputs them
        to the <code>MC_UNKNOWN</code> multicast group, which
        <code>ovn-northd</code> populates with all enabled logical ports that
        accept unknown destination packets.  As a small optimization, if no
        logical ports accept unknown destination packets,
        <code>ovn-northd</code> omits this multicast group and logical flow.
      </li>
    </ul>

    <h3>Egress Table 0: <code>to-lport</code> Pre-ACLs</h3>

    <p>
      This is similar to ingress table 3 except for <code>to-lport</code>
      traffic.
    </p>

    <h3>Egress Table 1: <code>to-lport</code> ACLs</h3>

    <p>
      This is similar to ingress table 4 except for <code>to-lport</code> ACLs.
    </p>

    <h3>Egress Table 2: Egress Port Security - IP</h3>

    <p>
      This is similar to the ingress port security logic in table 1 except
      that <code>outport</code>, <code>eth.dst</code>, <code>ip4.dst</code>
      and <code>ip6.dst</code> are checked instead of <code>inport</code>,
      <code>eth.src</code>, <code>ip4.src</code> and <code>ip6.src</code>
    </p>

    <h3>Egress Table 3: Egress Port Security - L2</h3>

    <p>
      This is similar to the ingress port security logic in ingress table 0,
      but with important differences.  Most obviously, <code>outport</code> and
      <code>eth.dst</code> are checked instead of <code>inport</code> and
      <code>eth.src</code>.  Second, packets directed to broadcast or multicast
      <code>eth.dst</code> are always accepted instead of being subject to the
      port security rules; this is implemented through a priority-100 flow that
      matches on <code>eth.mcast</code> with action <code>output;</code>.
      Finally, to ensure that even broadcast and multicast packets are not
      delivered to disabled logical ports, a priority-150 flow for each
      disabled logical <code>outport</code> overrides the priority-100 flow
      with a <code>drop;</code> action.
    </p>

    <h2>Logical Router Datapaths</h2>

    <p>
      Logical router datapaths will only exist for <ref table="Logical_Router"
      db="OVN_Northbound"/> rows in the <ref db="OVN_Northbound"/> database
      that do not have <ref column="enabled" table="Logical_Router"
      db="OVN_Northbound"/> set to <code>false</code>
    </p>

    <h3>Ingress Table 0: L2 Admission Control</h3>

    <p>
      This table drops packets that the router shouldn't see at all based on
      their Ethernet headers.  It contains the following flows:
    </p>

    <ul>
      <li>
        Priority-100 flows to drop packets with VLAN tags or multicast Ethernet
        source addresses.
      </li>

      <li>
        For each enabled router port <var>P</var> with Ethernet address
        <var>E</var>, a priority-50 flow that matches <code>inport ==
        <var>P</var> &amp;&amp; (eth.mcast || eth.dst ==
        <var>E</var></code>), with action <code>next;</code>.
      </li>
    </ul>

    <p>
      Other packets are implicitly dropped.
    </p>

    <h3>Ingress Table 1: IP Input</h3>

    <p>
      This table is the core of the logical router datapath functionality.  It
      contains the following flows to implement very basic IP host
      functionality.
    </p>

    <ul>
      <li>
        <p>
          L3 admission control: A priority-100 flow drops packets that match
          any of the following:
        </p>

        <ul>
          <li>
            <code>ip4.src[28..31] == 0xe</code> (multicast source)
          </li>
          <li>
            <code>ip4.src == 255.255.255.255</code> (broadcast source)
          </li>
          <li>
            <code>ip4.src == 127.0.0.0/8 || ip4.dst == 127.0.0.0/8</code>
            (localhost source or destination)
          </li>
          <li>
            <code>ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8</code> (zero
            network source or destination)
          </li>
          <li>
            <code>ip4.src</code> is any IP address owned by the router.
          </li>
          <li>
            <code>ip4.src</code> is the broadcast address of any IP network
            known to the router.
          </li>
        </ul>
      </li>

      <li>
        <p>
          ICMP echo reply.  These flows reply to ICMP echo requests received
          for the router's IP address.  Let <var>A</var> be an IP address or
          broadcast address owned by a router port.  Then, for each
          <var>A</var>, a priority-90 flow matches on <code>ip4.dst ==
          <var>A</var></code> and <code>icmp4.type == 8 &amp;&amp; icmp4.code
          == 0</code> (ICMP echo request).  These flows use the following
          actions where, if <var>A</var> is unicast, then <var>S</var> is
          <var>A</var>, and if <var>A</var> is broadcast, <var>S</var> is the
          router's IP address in <var>A</var>'s network:
        </p>

        <pre>
ip4.dst = ip4.src;
ip4.src = <var>S</var>;
ip.ttl = 255;
icmp4.type = 0;
inport = ""; /* Allow sending out inport. */
next;
        </pre>

        <p>
          Similar flows match on <code>ip4.dst == 255.255.255.255</code> and
          each individual <code>inport</code>, and use the same actions in
          which <var>S</var> is a function of <code>inport</code>.
        </p>
      </li>

      <li>
        <p>
          Reply to ARP requests.
        </p>

        <p>
          These flows reply to ARP requests for the router's own IP address.
          For each router port <var>P</var> that owns IP address <var>A</var>
          and Ethernet address <var>E</var>, a priority-90 flow matches
          <code>inport == <var>P</var> &amp;&amp; arp.op == 1 &amp;&amp;
          arp.tpa == <var>A</var></code> (ARP request) with the following
          actions:
        </p>

        <pre>
eth.dst = eth.src;
eth.src = <var>E</var>;
arp.op = 2; /* ARP reply. */
arp.tha = arp.sha;
arp.sha = <var>E</var>;
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = <var>P</var>;
inport = ""; /* Allow sending out inport. */
output;
        </pre>
      </li>

      <li>
        <p>
          These flows reply to ARP requests for the virtual IP addresses
          configured in the router for DNAT. For a configured DNAT IP address
          <var>A</var>, for each router port <var>P</var> with Ethernet
          address <var>E</var>, a priority-90 flow matches
          <code>inport == <var>P</var> &amp;&amp; arp.op == 1 &amp;&amp;
          arp.tpa == <var>A</var></code> (ARP request)
          with the following actions:
        </p>

        <pre>
eth.dst = eth.src;
eth.src = <var>E</var>;
arp.op = 2; /* ARP reply. */
arp.tha = arp.sha;
arp.sha = <var>E</var>;
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = <var>P</var>;
inport = ""; /* Allow sending out inport. */
output;
        </pre>
      </li>

      <li>
        ARP reply handling.  These flows use ARP replies to populate the
        logical router's ARP table.  A priority-90 flow with match <code>arp.op
        == 2</code> has actions <code>put_arp(inport, arp.spa,
        arp.sha);</code>.
      </li>

      <li>
        <p>
          UDP port unreachable.  Priority-80 flows generate ICMP port
          unreachable messages in reply to UDP datagrams directed to the
          router's IP address.  The logical router doesn't accept any UDP
          traffic so it always generates such a reply.
        </p>

        <p>
          These flows should not match IP fragments with nonzero offset.
        </p>

        <p>
          Details TBD.  Not yet implemented.
        </p>
      </li>

      <li>
        <p>
          TCP reset.  Priority-80 flows generate TCP reset messages in reply to
          TCP datagrams directed to the router's IP address.  The logical
          router doesn't accept any TCP traffic so it always generates such a
          reply.
        </p>

        <p>
          These flows should not match IP fragments with nonzero offset.
        </p>

        <p>
          Details TBD.  Not yet implemented.
        </p>
      </li>

      <li>
        <p>
          Protocol unreachable.  Priority-70 flows generate ICMP protocol
          unreachable messages in reply to packets directed to the router's IP
          address on IP protocols other than UDP, TCP, and ICMP.
        </p>

        <p>
          These flows should not match IP fragments with nonzero offset.
        </p>

        <p>
          Details TBD.  Not yet implemented.
        </p>
      </li>

      <li>
        Drop other IP traffic to this router.  These flows drop any other
        traffic destined to an IP address of this router that is not already
        handled by one of the flows above, which amounts to ICMP (other than
        echo requests) and fragments with nonzero offsets.  For each IP address
        <var>A</var> owned by the router, a priority-60 flow matches
        <code>ip4.dst == <var>A</var></code> and drops the traffic.
      </li>
    </ul>

    <p>
      The flows above handle all of the traffic that might be directed to the
      router itself.  The following flows (with lower priorities) handle the
      remaining traffic, potentially for forwarding:
    </p>

    <ul>
      <li>
        Drop Ethernet local broadcast.  A priority-50 flow with match
        <code>eth.bcast</code> drops traffic destined to the local Ethernet
        broadcast address.  By definition this traffic should not be forwarded.
      </li>

      <li>
        Drop IP multicast.  A priority-50 flow with match
        <code>ip4.mcast</code> drops IP multicast traffic.
      </li>

      <li>
        <p>
          ICMP time exceeded.  For each router port <var>P</var>, whose IP
          address is <var>A</var>, a priority-40 flow with match <code>inport
          == <var>P</var> &amp;&amp; ip.ttl == {0, 1} &amp;&amp;
          !ip.later_frag</code> matches packets whose TTL has expired, with the
          following actions to send an ICMP time exceeded reply:
        </p>

        <pre>
icmp4 {
    icmp4.type = 11; /* Time exceeded. */
    icmp4.code = 0;  /* TTL exceeded in transit. */
    ip4.dst = ip4.src;
    ip4.src = <var>A</var>;
    ip.ttl = 255;
    next;
};
        </pre>

        <p>
          Not yet implemented.
        </p>
      </li>

      <li>
        TTL discard.  A priority-30 flow with match <code>ip.ttl == {0,
        1}</code> and actions <code>drop;</code> drops other packets whose TTL
        has expired, that should not receive a ICMP error reply (i.e. fragments
        with nonzero offset).
      </li>

      <li>
        Next table.  A priority-0 flows match all packets that aren't already
        handled and uses actions <code>next;</code> to feed them to the ingress
        table for routing.
      </li>
    </ul>

    <h3>Ingress Table 2: UNSNAT</h3>

    <p>
      This is for already established connections' reverse traffic.
      i.e., SNAT has already been done in egress pipeline and now the
      packet has entered the ingress pipeline as part of a reply.  It is
      unSNATted here.
    </p>

    <ul>
      <li>
        <p>
          For each configuration in the OVN Northbound database, that asks
          to change the source IP address of a packet from <var>A</var> to
          <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;
          ip4.dst == <var>B</var></code> with an action
          <code>ct_snat; next;</code>.
        </p>

        <p>
          A priority-0 logical flow with match <code>1</code> has actions
          <code>next;</code>.
        </p>
      </li>
    </ul>

    <h3>Ingress Table 3: DNAT</h3>

    <p>
      Packets enter the pipeline with destination IP address that needs to
      be DNATted from a virtual IP address to a real IP address.  Packets
      in the reverse direction needs to be unDNATed.
    </p>
    <ul>
      <li>
        <p>
          For each configuration in the OVN Northbound database, that asks
          to change the destination IP address of a packet from <var>A</var> to
          <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;
          ip4.dst == <var>A</var></code> with an action <code>inport = "";
          ct_dnat(<var>B</var>);</code>.
        </p>

        <p>
          For all IP packets of a Gateway router, a priority-50 flow with an
          action <code>inport = ""; ct_dnat;</code>.
        </p>

        <p>
          A priority-0 logical flow with match <code>1</code> has actions
          <code>next;</code>.
        </p>
      </li>
    </ul>

    <h3>Ingress Table 4: IP Routing</h3>

    <p>
      A packet that arrives at this table is an IP packet that should be routed
      to the address in <code>ip4.dst</code>.  This table implements IP
      routing, setting <code>reg0</code> to the next-hop IP address (leaving
      <code>ip4.dst</code>, the packet's final destination, unchanged) and
      advances to the next table for ARP resolution.  It also sets
      <code>reg1</code> to the IP address owned by the selected router port
      (which is used later in table 6 as the IP source address for an ARP
      request, if needed).
    </p>

    <p>
      This table contains the following logical flows:
    </p>

    <ul>
      <li>
        <p>
          Routing table.  For each route to IPv4 network <var>N</var> with
          netmask <var>M</var>, on router port <var>P</var> with IP address
          <var>A</var> and Ethernet
          address <var>E</var>, a logical flow with match <code>ip4.dst ==
          <var>N</var>/<var>M</var></code>, whose priority is the number of
          1-bits in <var>M</var>, has the following actions:
        </p>

        <pre>
ip.ttl--;
reg0 = <var>G</var>;
reg1 = <var>A</var>;
eth.src = <var>E</var>;
outport = <var>P</var>;
next;
        </pre>

        <p>
          (Ingress table 1 already verified that <code>ip.ttl--;</code> will
          not yield a TTL exceeded error.)
        </p>

        <p>
          If the route has a gateway, <var>G</var> is the gateway IP address.
          Instead, if the route is from a configured static route, <var>G</var>
          is the next hop IP address.  Else it is <code>ip4.dst</code>.
        </p>
      </li>

      <li>
        <p>
          Destination unreachable.  For each router port <var>P</var>, which
          owns IP address <var>A</var>, a priority-0 logical flow with match
          <code>in_port == <var>P</var> &amp;&amp; !ip.later_frag &amp;&amp;
          !icmp</code> has the following actions:
        </p>

        <pre>
icmp4 {
    icmp4.type = 3; /* Destination unreachable. */
    icmp4.code = 0; /* Network unreachable. */
    ip4.dst = ip4.src;
    ip4.src = <var>A</var>;
    ip.ttl = 255;
    next(2);
};
        </pre>

        <p>
          (The <code>!icmp</code> check prevents recursion if the destination
          unreachable message itself cannot be routed.)
        </p>

        <p>
          These flows are omitted if the logical router has a default route,
          that is, a route with netmask 0.0.0.0.
        </p>
      </li>
    </ul>

    <h3>Ingress Table 5: ARP Resolution</h3>

    <p>
      Any packet that reaches this table is an IP packet whose next-hop IP
      address is in <code>reg0</code>.  (<code>ip4.dst</code> is the final
      destination.)  This table resolves the IP address in <code>reg0</code>
      into an output port in <code>outport</code> and an Ethernet address in
      <code>eth.dst</code>, using the following flows:
    </p>

    <ul>
      <li>
        <p>
          Static MAC bindings.  MAC bindings can be known statically based on
          data in the <code>OVN_Northbound</code> database.  For router ports
          connected to logical switches, MAC bindings can be known statically
          from the <code>addresses</code> column in the
          <code>Logical_Switch_Port</code> table.  For router ports
          connected to other logical routers, MAC bindings can be known
          statically from the <code>mac</code> and <code>network</code>
          column in the <code>Logical_Router_Port</code> table.
        </p>

        <p>
          For each IP address <var>A</var> whose host is known to have Ethernet
          address <var>E</var> on router port <var>P</var>, a priority-100 flow
          with match <code>outport === <var>P</var> &amp;&amp; reg0 ==
          <var>A</var></code> has actions <code>eth.dst = <var>E</var>;
          next;</code>.
        </p>

        <p>
          For each logical router port with an IP address <var>A</var> and
          a mac address of <var>E</var> that is reachable via a different
          logical router port <var>P</var>, a priority-100 flow with
          match <code>outport === <var>P</var> &amp;&amp; reg0 ==
          <var>A</var></code> has actions <code>eth.dst = <var>E</var>;
          next;</code>.
        </p>
      </li>

      <li>
        <p>
          Dynamic MAC bindings.  This flows resolves MAC-to-IP bindings that
          have become known dynamically through ARP.  (The next table will
          issue an ARP request for cases where the binding is not yet known.)
        </p>

        <p>
          A priority-0 logical flow with match <code>1</code> has actions
          <code>get_arp(outport, reg0); next;</code>.
        </p>
      </li>
    </ul>

    <h3>Ingress Table 6: ARP Request</h3>

    <p>
      In the common case where the Ethernet destination has been resolved, this
      table outputs the packet.  Otherwise, it composes and sends an ARP
      request.  It holds the following flows:
    </p>

    <ul>
      <li>
        <p>
          Unknown MAC address.  A priority-100 flow with match <code>eth.dst ==
          00:00:00:00:00:00</code> has the following actions:
        </p>

        <pre>
arp {
    eth.dst = ff:ff:ff:ff:ff:ff;
    arp.spa = reg1;
    arp.op = 1;  /* ARP request. */
    output;
};
        </pre>

        <p>
          (Ingress table 4 initialized <code>reg1</code> with the IP address
          owned by <code>outport</code>.)
        </p>

        <p>
          The IP packet that triggers the ARP request is dropped.
        </p>
      </li>

      <li>
        Known MAC address.  A priority-0 flow with match <code>1</code> has
        actions <code>output;</code>.
      </li>
    </ul>

    <h3>Egress Table 0: SNAT</h3>

    <p>
      Packets that are configured to be SNATed get their source IP address
      changed based on the configuration in the OVN Northbound database.
    </p>
    <ul>
      <li>
        <p>
          For each configuration in the OVN Northbound database, that asks
          to change the source IP address of a packet from an IP address of
          <var>A</var> or to change the source IP address of a packet that
          belongs to network <var>A</var> to <var>B</var>, a flow matches
          <code>ip &amp;&amp; ip4.src == <var>A</var></code> with an action
          <code>ct_snat(<var>B</var>);</code>.  The priority of the flow
          is calculated based on the mask of <var>A</var>, with matches
          having larger masks getting higher priorities.
        </p>
        <p>
          A priority-0 logical flow with match <code>1</code> has actions
          <code>next;</code>.
        </p>
      </li>
    </ul>

    <h3>Egress Table 1: Delivery</h3>

    <p>
      Packets that reach this table are ready for delivery.  It contains
      priority-100 logical flows that match packets on each enabled logical
      router port, with action <code>output;</code>.
    </p>

</manpage>