226ac72e0f0168e8fb8b20dc464338e6e0abd482
[cascardo/ovs.git] / ovn / controller / physical.c
1 /* Copyright (c) 2015, 2016 Nicira, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17 #include "byte-order.h"
18 #include "flow.h"
19 #include "lflow.h"
20 #include "ofctrl.h"
21 #include "openvswitch/match.h"
22 #include "openvswitch/ofp-actions.h"
23 #include "openvswitch/ofpbuf.h"
24 #include "openvswitch/vlog.h"
25 #include "ovn-controller.h"
26 #include "ovn/lib/ovn-sb-idl.h"
27 #include "ovn/lib/ovn-util.h"
28 #include "physical.h"
29 #include "shash.h"
30 #include "simap.h"
31 #include "smap.h"
32 #include "sset.h"
33 #include "vswitch-idl.h"
34
35 VLOG_DEFINE_THIS_MODULE(physical);
36
37 void
38 physical_register_ovs_idl(struct ovsdb_idl *ovs_idl)
39 {
40     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
41     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
42
43     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port);
44     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name);
45     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces);
46     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_external_ids);
47
48     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface);
49     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name);
50     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_ofport);
51     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
52 }
53
54 static struct simap localvif_to_ofport =
55     SIMAP_INITIALIZER(&localvif_to_ofport);
56 static struct hmap tunnels = HMAP_INITIALIZER(&tunnels);
57
58 /* UUID to identify OF flows not associated with ovsdb rows. */
59 static struct uuid *hc_uuid = NULL;
60
61 /* Maps from a chassis to the OpenFlow port number of the tunnel that can be
62  * used to reach that chassis. */
63 struct chassis_tunnel {
64     struct hmap_node hmap_node;
65     const char *chassis_id;
66     ofp_port_t ofport;
67     enum chassis_tunnel_type type;
68 };
69
70 static struct chassis_tunnel *
71 chassis_tunnel_find(const char *chassis_id)
72 {
73     struct chassis_tunnel *tun;
74     HMAP_FOR_EACH_WITH_HASH (tun, hmap_node, hash_string(chassis_id, 0),
75                              &tunnels) {
76         if (!strcmp(tun->chassis_id, chassis_id)) {
77             return tun;
78         }
79     }
80     return NULL;
81 }
82
83 static void
84 put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
85          struct ofpbuf *ofpacts)
86 {
87     struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts);
88     sf->field = mf_from_id(dst);
89     sf->flow_has_vlan = false;
90
91     ovs_be64 n_value = htonll(value);
92     bitwise_copy(&n_value, 8, 0, &sf->value, sf->field->n_bytes, ofs, n_bits);
93     bitwise_one(&sf->mask, sf->field->n_bytes, ofs, n_bits);
94 }
95
96 static void
97 put_move(enum mf_field_id src, int src_ofs,
98          enum mf_field_id dst, int dst_ofs,
99          int n_bits,
100          struct ofpbuf *ofpacts)
101 {
102     struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
103     move->src.field = mf_from_id(src);
104     move->src.ofs = src_ofs;
105     move->src.n_bits = n_bits;
106     move->dst.field = mf_from_id(dst);
107     move->dst.ofs = dst_ofs;
108     move->dst.n_bits = n_bits;
109 }
110
111 static void
112 put_resubmit(uint8_t table_id, struct ofpbuf *ofpacts)
113 {
114     struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ofpacts);
115     resubmit->in_port = OFPP_IN_PORT;
116     resubmit->table_id = table_id;
117 }
118
119 static void
120 put_encapsulation(enum mf_field_id mff_ovn_geneve,
121                   const struct chassis_tunnel *tun,
122                   const struct sbrec_datapath_binding *datapath,
123                   uint16_t outport, struct ofpbuf *ofpacts)
124 {
125     if (tun->type == GENEVE) {
126         put_load(datapath->tunnel_key, MFF_TUN_ID, 0, 24, ofpacts);
127         put_load(outport, mff_ovn_geneve, 0, 32, ofpacts);
128         put_move(MFF_LOG_INPORT, 0, mff_ovn_geneve, 16, 15, ofpacts);
129     } else if (tun->type == STT) {
130         put_load(datapath->tunnel_key | (outport << 24), MFF_TUN_ID, 0, 64,
131                  ofpacts);
132         put_move(MFF_LOG_INPORT, 0, MFF_TUN_ID, 40, 15, ofpacts);
133     } else if (tun->type == VXLAN) {
134         put_load(datapath->tunnel_key, MFF_TUN_ID, 0, 24, ofpacts);
135     } else {
136         OVS_NOT_REACHED();
137     }
138 }
139
140 static void
141 put_stack(enum mf_field_id field, struct ofpact_stack *stack)
142 {
143     stack->subfield.field = mf_from_id(field);
144     stack->subfield.ofs = 0;
145     stack->subfield.n_bits = stack->subfield.field->n_bits;
146 }
147
148 static const struct sbrec_port_binding*
149 get_localnet_port(struct hmap *local_datapaths, int64_t tunnel_key)
150 {
151     struct local_datapath *ld = get_local_datapath(local_datapaths,
152                                                    tunnel_key);
153     return ld ? ld->localnet_port : NULL;
154 }
155
156 static void
157 consider_port_binding(enum mf_field_id mff_ovn_geneve,
158                       const struct simap *ct_zones,
159                       struct hmap *local_datapaths,
160                       struct hmap *patched_datapaths,
161                       const struct sbrec_port_binding *binding,
162                       struct ofpbuf *ofpacts_p)
163 {
164     /* Skip the port binding if the port is on a datapath that is neither
165      * local nor with any logical patch port connected, because local ports
166      * would never need to talk to those ports.
167      *
168      * Even with this approach there could still be unnecessary port
169      * bindings processed. A better approach would be a kind of "flood
170      * fill" algorithm:
171      *
172      *   1. Initialize set S to the logical datapaths that have a port
173      *      located on the hypervisor.
174      *
175      *   2. For each patch port P in a logical datapath in S, add the
176      *      logical datapath of the remote end of P to S.  Iterate
177      *      until S reaches a fixed point.
178      *
179      * This can be implemented in northd, which can generate the sets and
180      * save it on each port-binding record in SB, and ovn-controller can
181      * use the information directly. However, there can be update storms
182      * when a pair of patch ports are added/removed to connect/disconnect
183      * large lrouters and lswitches. This need to be studied further.
184      */
185     uint32_t dp_key = binding->datapath->tunnel_key;
186     uint32_t port_key = binding->tunnel_key;
187     if (!get_local_datapath(local_datapaths, dp_key)
188         && !get_patched_datapath(patched_datapaths, dp_key)) {
189         return;
190     }
191
192     /* Find the OpenFlow port for the logical port, as 'ofport'.  This is
193      * one of:
194      *
195      *     - If the port is a VIF on the chassis we're managing, the
196      *       OpenFlow port for the VIF.  'tun' will be NULL.
197      *
198      *       The same logic handles logical patch ports, as well as
199      *       localnet patch ports.
200      *
201      *       For a container nested inside a VM and accessible via a VLAN,
202      *       'tag' is the VLAN ID; otherwise 'tag' is 0.
203      *
204      *       For a localnet patch port, if a VLAN ID was configured, 'tag'
205      *       is set to that VLAN ID; otherwise 'tag' is 0.
206      *
207      *     - If the port is on a remote chassis, the OpenFlow port for a
208      *       tunnel to the VIF's remote chassis.  'tun' identifies that
209      *       tunnel.
210      */
211
212     int tag = 0;
213     ofp_port_t ofport;
214     bool is_remote = false;
215     if (binding->parent_port && *binding->parent_port) {
216         if (!binding->tag) {
217             return;
218         }
219         ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
220                                       binding->parent_port));
221         if (ofport) {
222             tag = *binding->tag;
223         }
224     } else {
225         ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
226                                       binding->logical_port));
227         if ((!strcmp(binding->type, "localnet")
228             || !strcmp(binding->type, "l2gateway"))
229             && ofport && binding->tag) {
230             tag = *binding->tag;
231         }
232     }
233
234     const struct chassis_tunnel *tun = NULL;
235     const struct sbrec_port_binding *localnet_port =
236         get_localnet_port(local_datapaths, dp_key);
237     if (!ofport) {
238         /* It is remote port, may be reached by tunnel or localnet port */
239         is_remote = true;
240         if (!binding->chassis) {
241             return;
242         }
243         if (localnet_port) {
244             ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
245                                           localnet_port->logical_port));
246             if (!ofport) {
247                 return;
248             }
249         } else {
250             tun = chassis_tunnel_find(binding->chassis->name);
251             if (!tun) {
252                 return;
253             }
254             ofport = tun->ofport;
255         }
256     }
257
258     struct match match;
259     if (!is_remote) {
260         int zone_id = simap_get(ct_zones, binding->logical_port);
261         /* Packets that arrive from a vif can belong to a VM or
262          * to a container located inside that VM. Packets that
263          * arrive from containers have a tag (vlan) associated with them.
264          */
265
266         /* Table 0, Priority 150 and 100.
267          * ==============================
268          *
269          * Priority 150 is for tagged traffic. This may be containers in a
270          * VM or a VLAN on a local network. For such traffic, match on the
271          * tags and then strip the tag.
272          *
273          * Priority 100 is for traffic belonging to VMs or untagged locally
274          * connected networks.
275          *
276          * For both types of traffic: set MFF_LOG_INPORT to the logical
277          * input port, MFF_LOG_DATAPATH to the logical datapath, and
278          * resubmit into the logical ingress pipeline starting at table
279          * 16. */
280         ofpbuf_clear(ofpacts_p);
281         match_init_catchall(&match);
282         match_set_in_port(&match, ofport);
283
284         /* Match a VLAN tag and strip it, including stripping priority tags
285          * (e.g. VLAN ID 0).  In the latter case we'll add a second flow
286          * for frames that lack any 802.1Q header later. */
287         if (tag || !strcmp(binding->type, "localnet")
288             || !strcmp(binding->type, "l2gateway")) {
289             match_set_dl_vlan(&match, htons(tag));
290             ofpact_put_STRIP_VLAN(ofpacts_p);
291         }
292
293         /* Remember the size with just strip vlan added so far,
294          * as we're going to remove this with ofpbuf_pull() later. */
295         uint32_t ofpacts_orig_size = ofpacts_p->size;
296
297         if (zone_id) {
298             put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p);
299         }
300
301         int zone_id_dnat, zone_id_snat;
302         char *key = xasprintf(UUID_FMT,
303                               UUID_ARGS(&binding->datapath->header_.uuid));
304         char *dnat = alloc_nat_zone_key(key, "dnat");
305         char *snat = alloc_nat_zone_key(key, "snat");
306         free(key);
307
308         zone_id_dnat = simap_get(ct_zones, dnat);
309         if (zone_id_dnat) {
310             put_load(zone_id_dnat, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p);
311         }
312         free(dnat);
313
314         zone_id_snat = simap_get(ct_zones, snat);
315         if (zone_id_snat) {
316             put_load(zone_id_snat, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p);
317         }
318         free(snat);
319
320         /* Set MFF_LOG_DATAPATH and MFF_LOG_INPORT. */
321         put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, ofpacts_p);
322         put_load(port_key, MFF_LOG_INPORT, 0, 32, ofpacts_p);
323
324         /* Resubmit to first logical ingress pipeline table. */
325         put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);
326         ofctrl_add_flow(OFTABLE_PHY_TO_LOG,
327                         tag ? 150 : 100, &match, ofpacts_p,
328                         &binding->header_.uuid);
329
330         if (!tag && (!strcmp(binding->type, "localnet")
331                      || !strcmp(binding->type, "l2gateway"))) {
332
333             /* Add a second flow for frames that lack any 802.1Q
334              * header.  For these, drop the OFPACT_STRIP_VLAN
335              * action. */
336             ofpbuf_pull(ofpacts_p, ofpacts_orig_size);
337             match_set_dl_tci_masked(&match, 0, htons(VLAN_CFI));
338             ofctrl_add_flow(0, 100, &match, ofpacts_p,
339                             &binding->header_.uuid);
340         }
341
342         /* Table 33, priority 100.
343          * =======================
344          *
345          * Implements output to local hypervisor.  Each flow matches a
346          * logical output port on the local hypervisor, and resubmits to
347          * table 34.
348          */
349
350         match_init_catchall(&match);
351         ofpbuf_clear(ofpacts_p);
352
353         /* Match MFF_LOG_DATAPATH, MFF_LOG_OUTPORT. */
354         match_set_metadata(&match, htonll(dp_key));
355         match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
356
357         if (zone_id) {
358             put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p);
359         }
360         if (zone_id_dnat) {
361             put_load(zone_id_dnat, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p);
362         }
363         if (zone_id_snat) {
364             put_load(zone_id_snat, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p);
365         }
366
367         /* Resubmit to table 34. */
368         put_resubmit(OFTABLE_DROP_LOOPBACK, ofpacts_p);
369         ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100,
370                         &match, ofpacts_p, &binding->header_.uuid);
371
372         /* Table 34, Priority 100.
373          * =======================
374          *
375          * Drop packets whose logical inport and outport are the same. */
376         match_init_catchall(&match);
377         ofpbuf_clear(ofpacts_p);
378         match_set_metadata(&match, htonll(dp_key));
379         match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, port_key);
380         match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
381         ofctrl_add_flow(OFTABLE_DROP_LOOPBACK, 100,
382                         &match, ofpacts_p, &binding->header_.uuid);
383
384         /* Table 64, Priority 100.
385          * =======================
386          *
387          * Deliver the packet to the local vif. */
388         match_init_catchall(&match);
389         ofpbuf_clear(ofpacts_p);
390         match_set_metadata(&match, htonll(dp_key));
391         match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
392         if (tag) {
393             /* For containers sitting behind a local vif, tag the packets
394              * before delivering them. */
395             struct ofpact_vlan_vid *vlan_vid;
396             vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts_p);
397             vlan_vid->vlan_vid = tag;
398             vlan_vid->push_vlan_if_needed = true;
399
400             /* A packet might need to hair-pin back into its ingress
401              * OpenFlow port (to a different logical port, which we already
402              * checked back in table 34), so set the in_port to zero. */
403             put_stack(MFF_IN_PORT, ofpact_put_STACK_PUSH(ofpacts_p));
404             put_load(0, MFF_IN_PORT, 0, 16, ofpacts_p);
405         }
406         ofpact_put_OUTPUT(ofpacts_p)->port = ofport;
407         if (tag) {
408             /* Revert the tag added to the packets headed to containers
409              * in the previous step. If we don't do this, the packets
410              * that are to be broadcasted to a VM in the same logical
411              * switch will also contain the tag. Also revert the zero'd
412              * in_port. */
413             ofpact_put_STRIP_VLAN(ofpacts_p);
414             put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p));
415         }
416         ofctrl_add_flow(OFTABLE_LOG_TO_PHY, 100,
417                         &match, ofpacts_p, &binding->header_.uuid);
418     } else if (!tun) {
419         /* Remote port connected by localnet port */
420         /* Table 33, priority 100.
421          * =======================
422          *
423          * Implements switching to localnet port. Each flow matches a
424          * logical output port on remote hypervisor, switch the output port
425          * to connected localnet port and resubmits to same table.
426          */
427
428         match_init_catchall(&match);
429         ofpbuf_clear(ofpacts_p);
430
431         /* Match MFF_LOG_DATAPATH, MFF_LOG_OUTPORT. */
432         match_set_metadata(&match, htonll(dp_key));
433         match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
434
435         put_load(localnet_port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p);
436
437         /* Resubmit to table 33. */
438         put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p);
439         ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100,
440                         &match, ofpacts_p, &binding->header_.uuid);
441     } else {
442         /* Remote port connected by tunnel */
443         /* Table 32, priority 100.
444          * =======================
445          *
446          * Implements output to remote hypervisors.  Each flow matches an
447          * output port that includes a logical port on a remote hypervisor,
448          * and tunnels the packet to that hypervisor.
449          */
450
451         match_init_catchall(&match);
452         ofpbuf_clear(ofpacts_p);
453
454         /* Match MFF_LOG_DATAPATH, MFF_LOG_OUTPORT. */
455         match_set_metadata(&match, htonll(dp_key));
456         match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
457
458         put_encapsulation(mff_ovn_geneve, tun, binding->datapath,
459                           port_key, ofpacts_p);
460
461         /* Output to tunnel. */
462         ofpact_put_OUTPUT(ofpacts_p)->port = ofport;
463         ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 100,
464                         &match, ofpacts_p, &binding->header_.uuid);
465     }
466 }
467
468 static void
469 consider_mc_group(enum mf_field_id mff_ovn_geneve,
470                   const struct simap *ct_zones,
471                   struct hmap *local_datapaths,
472                   const struct sbrec_multicast_group *mc,
473                   struct ofpbuf *ofpacts_p,
474                   struct ofpbuf *remote_ofpacts_p)
475 {
476     struct sset remote_chassis = SSET_INITIALIZER(&remote_chassis);
477     struct match match;
478
479     match_init_catchall(&match);
480     match_set_metadata(&match, htonll(mc->datapath->tunnel_key));
481     match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, mc->tunnel_key);
482
483     /* Go through all of the ports in the multicast group:
484      *
485      *    - For remote ports, add the chassis to 'remote_chassis'.
486      *
487      *    - For local ports (other than logical patch ports), add actions
488      *      to 'ofpacts_p' to set the output port and resubmit.
489      *
490      *    - For logical patch ports, add actions to 'remote_ofpacts_p'
491      *      instead.  (If we put them in 'ofpacts', then the output
492      *      would happen on every hypervisor in the multicast group,
493      *      effectively duplicating the packet.)
494      */
495     ofpbuf_clear(ofpacts_p);
496     ofpbuf_clear(remote_ofpacts_p);
497     for (size_t i = 0; i < mc->n_ports; i++) {
498         struct sbrec_port_binding *port = mc->ports[i];
499
500         if (port->datapath != mc->datapath) {
501             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
502             VLOG_WARN_RL(&rl, UUID_FMT": multicast group contains ports "
503                          "in wrong datapath",
504                          UUID_ARGS(&mc->header_.uuid));
505             continue;
506         }
507
508         int zone_id = simap_get(ct_zones, port->logical_port);
509         if (zone_id) {
510             put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p);
511         }
512
513         if (!strcmp(port->type, "patch")) {
514             put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
515                      remote_ofpacts_p);
516             put_resubmit(OFTABLE_DROP_LOOPBACK, remote_ofpacts_p);
517         } else if (simap_contains(&localvif_to_ofport,
518                            (port->parent_port && *port->parent_port)
519                            ? port->parent_port : port->logical_port)) {
520             put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p);
521             put_resubmit(OFTABLE_DROP_LOOPBACK, ofpacts_p);
522         } else if (port->chassis && !get_localnet_port(local_datapaths,
523                                          mc->datapath->tunnel_key)) {
524             /* Add remote chassis only when localnet port not exist,
525              * otherwise multicast will reach remote ports through localnet
526              * port. */
527             sset_add(&remote_chassis, port->chassis->name);
528         }
529     }
530
531     /* Table 33, priority 100.
532      * =======================
533      *
534      * Handle output to the local logical ports in the multicast group, if
535      * any. */
536     bool local_ports = ofpacts_p->size > 0;
537     if (local_ports) {
538         /* Following delivery to local logical ports, restore the multicast
539          * group as the logical output port. */
540         put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p);
541
542         ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100,
543                         &match, ofpacts_p, &mc->header_.uuid);
544     }
545
546     /* Table 32, priority 100.
547      * =======================
548      *
549      * Handle output to the remote chassis in the multicast group, if
550      * any. */
551     if (!sset_is_empty(&remote_chassis) || remote_ofpacts_p->size > 0) {
552         if (remote_ofpacts_p->size > 0) {
553             /* Following delivery to logical patch ports, restore the
554              * multicast group as the logical output port. */
555             put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
556                      remote_ofpacts_p);
557         }
558
559         const char *chassis;
560         const struct chassis_tunnel *prev = NULL;
561         SSET_FOR_EACH (chassis, &remote_chassis) {
562             const struct chassis_tunnel *tun
563                 = chassis_tunnel_find(chassis);
564             if (!tun) {
565                 continue;
566             }
567
568             if (!prev || tun->type != prev->type) {
569                 put_encapsulation(mff_ovn_geneve, tun, mc->datapath,
570                                   mc->tunnel_key, remote_ofpacts_p);
571                 prev = tun;
572             }
573             ofpact_put_OUTPUT(remote_ofpacts_p)->port = tun->ofport;
574         }
575
576         if (remote_ofpacts_p->size) {
577             if (local_ports) {
578                 put_resubmit(OFTABLE_LOCAL_OUTPUT, remote_ofpacts_p);
579             }
580             ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 100,
581                             &match, remote_ofpacts_p, &mc->header_.uuid);
582         }
583     }
584     sset_destroy(&remote_chassis);
585 }
586
587 void
588 physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
589              const struct ovsrec_bridge *br_int, const char *this_chassis_id,
590              const struct simap *ct_zones,
591              struct hmap *local_datapaths, struct hmap *patched_datapaths)
592 {
593     if (!hc_uuid) {
594         hc_uuid = xmalloc(sizeof(struct uuid));
595         uuid_generate(hc_uuid);
596     }
597
598     for (int i = 0; i < br_int->n_ports; i++) {
599         const struct ovsrec_port *port_rec = br_int->ports[i];
600         if (!strcmp(port_rec->name, br_int->name)) {
601             continue;
602         }
603
604         const char *chassis_id = smap_get(&port_rec->external_ids,
605                                           "ovn-chassis-id");
606         if (chassis_id && !strcmp(chassis_id, this_chassis_id)) {
607             continue;
608         }
609
610         const char *localnet = smap_get(&port_rec->external_ids,
611                                         "ovn-localnet-port");
612         const char *l2gateway = smap_get(&port_rec->external_ids,
613                                         "ovn-l2gateway-port");
614         const char *logpatch = smap_get(&port_rec->external_ids,
615                                         "ovn-logical-patch-port");
616
617         for (int j = 0; j < port_rec->n_interfaces; j++) {
618             const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
619
620             /* Get OpenFlow port number. */
621             if (!iface_rec->n_ofport) {
622                 continue;
623             }
624             int64_t ofport = iface_rec->ofport[0];
625             if (ofport < 1 || ofport > ofp_to_u16(OFPP_MAX)) {
626                 continue;
627             }
628
629             /* Record as patch to local net, logical patch port, chassis, or
630              * local logical port. */
631             bool is_patch = !strcmp(iface_rec->type, "patch");
632             if (is_patch && localnet) {
633                 /* localnet patch ports can be handled just like VIFs. */
634                 simap_put(&localvif_to_ofport, localnet, ofport);
635                 break;
636             } else if (is_patch && l2gateway) {
637                 /* L2 gateway patch ports can be handled just like VIFs. */
638                 simap_put(&localvif_to_ofport, l2gateway, ofport);
639                 break;
640             } else if (is_patch && logpatch) {
641                 /* Logical patch ports can be handled just like VIFs. */
642                 simap_put(&localvif_to_ofport, logpatch, ofport);
643                 break;
644             } else if (chassis_id) {
645                 enum chassis_tunnel_type tunnel_type;
646                 if (!strcmp(iface_rec->type, "geneve")) {
647                     tunnel_type = GENEVE;
648                     if (!mff_ovn_geneve) {
649                         continue;
650                     }
651                 } else if (!strcmp(iface_rec->type, "stt")) {
652                     tunnel_type = STT;
653                 } else if (!strcmp(iface_rec->type, "vxlan")) {
654                     tunnel_type = VXLAN;
655                 } else {
656                     continue;
657                 }
658
659                 struct chassis_tunnel *tun = xmalloc(sizeof *tun);
660                 hmap_insert(&tunnels, &tun->hmap_node,
661                             hash_string(chassis_id, 0));
662                 tun->chassis_id = chassis_id;
663                 tun->ofport = u16_to_ofp(ofport);
664                 tun->type = tunnel_type;
665                 break;
666             } else {
667                 const char *iface_id = smap_get(&iface_rec->external_ids,
668                                                 "iface-id");
669                 if (iface_id) {
670                     simap_put(&localvif_to_ofport, iface_id, ofport);
671                 }
672             }
673         }
674     }
675
676     struct ofpbuf ofpacts;
677     ofpbuf_init(&ofpacts, 0);
678
679     /* Set up flows in table 0 for physical-to-logical translation and in table
680      * 64 for logical-to-physical translation. */
681     const struct sbrec_port_binding *binding;
682     SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
683         consider_port_binding(mff_ovn_geneve, ct_zones,
684                               local_datapaths, patched_datapaths, binding,
685                               &ofpacts);
686     }
687
688     /* Handle output to multicast groups, in tables 32 and 33. */
689     const struct sbrec_multicast_group *mc;
690     struct ofpbuf remote_ofpacts;
691     ofpbuf_init(&remote_ofpacts, 0);
692     SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) {
693         consider_mc_group(mff_ovn_geneve, ct_zones,
694                           local_datapaths, mc, &ofpacts, &remote_ofpacts);
695     }
696
697     ofpbuf_uninit(&remote_ofpacts);
698
699     /* Table 0, priority 100.
700      * ======================
701      *
702      * Process packets that arrive from a remote hypervisor (by matching
703      * on tunnel in_port). */
704
705     /* Add flows for Geneve and STT encapsulations.  These
706      * encapsulations have metadata about the ingress and egress logical
707      * ports.  We set MFF_LOG_DATAPATH, MFF_LOG_INPORT, and
708      * MFF_LOG_OUTPORT from the tunnel key data, then resubmit to table
709      * 33 to handle packets to the local hypervisor. */
710     struct chassis_tunnel *tun;
711     HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
712         struct match match = MATCH_CATCHALL_INITIALIZER;
713         match_set_in_port(&match, tun->ofport);
714
715         ofpbuf_clear(&ofpacts);
716         if (tun->type == GENEVE) {
717             put_move(MFF_TUN_ID, 0,  MFF_LOG_DATAPATH, 0, 24, &ofpacts);
718             put_move(mff_ovn_geneve, 16, MFF_LOG_INPORT, 0, 15,
719                      &ofpacts);
720             put_move(mff_ovn_geneve, 0, MFF_LOG_OUTPORT, 0, 16,
721                      &ofpacts);
722         } else if (tun->type == STT) {
723             put_move(MFF_TUN_ID, 40, MFF_LOG_INPORT,   0, 15, &ofpacts);
724             put_move(MFF_TUN_ID, 24, MFF_LOG_OUTPORT,  0, 16, &ofpacts);
725             put_move(MFF_TUN_ID,  0, MFF_LOG_DATAPATH, 0, 24, &ofpacts);
726         } else if (tun->type == VXLAN) {
727             /* We'll handle VXLAN later. */
728             continue;
729         } else {
730             OVS_NOT_REACHED();
731         }
732
733         put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts);
734
735         ofctrl_add_flow(OFTABLE_PHY_TO_LOG, 100, &match, &ofpacts,
736                         hc_uuid);
737     }
738
739     /* Add flows for VXLAN encapsulations.  Due to the limited amount of
740      * metadata, we only support VXLAN for connections to gateways.  The
741      * VNI is used to populate MFF_LOG_DATAPATH.  The gateway's logical
742      * port is set to MFF_LOG_INPORT.  Then the packet is resubmitted to
743      * table 16 to determine the logical egress port.
744      *
745      * xxx Due to resubmitting to table 16, broadcasts will be re-sent to
746      * xxx all logical ports, including non-local ones which could cause
747      * xxx duplicate packets to be received by multiply-connected gateways. */
748     HMAP_FOR_EACH (tun, hmap_node, &tunnels) {
749         if (tun->type != VXLAN) {
750             continue;
751         }
752
753         SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
754             struct match match = MATCH_CATCHALL_INITIALIZER;
755
756             if (!binding->chassis ||
757                 strcmp(tun->chassis_id, binding->chassis->name)) {
758                 continue;
759             }
760
761             match_set_in_port(&match, tun->ofport);
762             match_set_tun_id(&match, htonll(binding->datapath->tunnel_key));
763
764             ofpbuf_clear(&ofpacts);
765             put_move(MFF_TUN_ID, 0,  MFF_LOG_DATAPATH, 0, 24, &ofpacts);
766             put_load(binding->tunnel_key, MFF_LOG_INPORT, 0, 15, &ofpacts);
767             put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts);
768
769             ofctrl_add_flow(OFTABLE_PHY_TO_LOG, 100, &match, &ofpacts, hc_uuid);
770         }
771     }
772
773     /* Table 32, Priority 0.
774      * =======================
775      *
776      * Resubmit packets that are not directed at tunnels or part of a
777      * multicast group to the local output table. */
778     struct match match;
779     match_init_catchall(&match);
780     ofpbuf_clear(&ofpacts);
781     put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts);
782     ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 0, &match, &ofpacts, hc_uuid);
783
784     /* Table 34, Priority 0.
785      * =======================
786      *
787      * Resubmit packets that don't output to the ingress port (already checked
788      * in table 33) to the logical egress pipeline, clearing the logical
789      * registers (for consistent behavior with packets that get tunneled). */
790     match_init_catchall(&match);
791     ofpbuf_clear(&ofpacts);
792 #define MFF_LOG_REG(ID) put_load(0, ID, 0, 32, &ofpacts);
793     MFF_LOG_REGS;
794 #undef MFF_LOG_REGS
795     put_resubmit(OFTABLE_LOG_EGRESS_PIPELINE, &ofpacts);
796     ofctrl_add_flow(OFTABLE_DROP_LOOPBACK, 0, &match, &ofpacts, hc_uuid);
797
798     ofpbuf_uninit(&ofpacts);
799     simap_clear(&localvif_to_ofport);
800     HMAP_FOR_EACH_POP (tun, hmap_node, &tunnels) {
801         free(tun);
802     }
803     hmap_clear(&tunnels);
804 }