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