1 /* Copyright (c) 2015 Nicira, Inc.
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "ofp-actions.h"
22 #include "ovn-controller.h"
23 #include "ovn/lib/ovn-sb-idl.h"
26 #include "vswitch-idl.h"
29 physical_init(struct controller_ctx *ctx)
31 ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_bridge);
32 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_bridge_col_ports);
34 ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_port);
35 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_name);
36 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_interfaces);
37 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_port_col_external_ids);
39 ovsdb_idl_add_table(ctx->ovs_idl, &ovsrec_table_interface);
40 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_name);
41 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_ofport);
42 ovsdb_idl_add_column(ctx->ovs_idl, &ovsrec_interface_col_external_ids);
46 physical_run(struct controller_ctx *ctx)
48 struct simap lport_to_ofport = SIMAP_INITIALIZER(&lport_to_ofport);
49 struct simap chassis_to_ofport = SIMAP_INITIALIZER(&chassis_to_ofport);
50 for (int i = 0; i < ctx->br_int->n_ports; i++) {
51 const struct ovsrec_port *port_rec = ctx->br_int->ports[i];
52 if (!strcmp(port_rec->name, ctx->br_int_name)) {
56 const char *chassis_id = smap_get(&port_rec->external_ids,
58 if (chassis_id && !strcmp(chassis_id, ctx->chassis_id)) {
62 for (int j = 0; j < port_rec->n_interfaces; j++) {
63 const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
65 /* Get OpenFlow port number. */
66 if (!iface_rec->n_ofport) {
69 int64_t ofport = iface_rec->ofport[0];
70 if (ofport < 1 || ofport > ofp_to_u16(OFPP_MAX)) {
74 /* Record as chassis or local logical port. */
76 simap_put(&chassis_to_ofport, chassis_id, ofport);
79 const char *iface_id = smap_get(&iface_rec->external_ids,
82 simap_put(&lport_to_ofport, iface_id, ofport);
88 struct ofpbuf ofpacts;
89 ofpbuf_init(&ofpacts, 0);
91 /* Set up flows in table 0 for physical-to-logical translation and in table
92 * 64 for logical-to-physical translation. */
93 const struct sbrec_binding *binding;
94 SBREC_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
95 /* Find the Openflow port for the logical port, as 'ofport'. If it's
96 * on a remote chassis, this is the OpenFlow port for the tunnel to
97 * that chassis (and set 'local' to false). Otherwise, if it's on the
98 * chassis we're managing, this is the OpenFlow port for the vif itself
99 * (and set 'local' to true). */
100 ofp_port_t ofport = u16_to_ofp(simap_get(&lport_to_ofport,
101 binding->logical_port));
102 bool local = ofport != 0;
104 ofport = u16_to_ofp(simap_get(&chassis_to_ofport,
111 /* Translate the logical datapath into the form we use in
113 uint32_t ldp = ldp_to_integer(&binding->logical_datapath);
120 /* Table 0, Priority 100.
121 * ======================
123 * For packets that arrive from a vif: set MFF_LOG_INPORT to the
124 * logical input port, MFF_METADATA to the logical datapath, and
125 * resubmit into the logical pipeline starting at table 16. */
126 match_init_catchall(&match);
127 ofpbuf_clear(&ofpacts);
128 match_set_in_port(&match, ofport);
130 /* Set MFF_METADATA. */
131 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
132 sf->field = mf_from_id(MFF_METADATA);
133 sf->value.be64 = htonll(ldp);
134 sf->mask.be64 = OVS_BE64_MAX;
136 /* Set MFF_LOG_INPORT. */
137 sf = ofpact_put_SET_FIELD(&ofpacts);
138 sf->field = mf_from_id(MFF_LOG_INPORT);
139 sf->value.be32 = htonl(binding->tunnel_key);
140 sf->mask.be32 = OVS_BE32_MAX;
142 /* Resubmit to first logical pipeline table. */
143 struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts);
144 resubmit->in_port = OFPP_IN_PORT;
145 resubmit->table_id = 16;
146 ofctrl_add_flow(0, 100, &match, &ofpacts);
148 /* Table 0, Priority 50.
149 * =====================
151 * For packets that arrive from a remote node destined to this
152 * local vif: deliver directly to the vif. */
153 match_init_catchall(&match);
154 ofpbuf_clear(&ofpacts);
155 match_set_tun_id(&match, htonll(binding->tunnel_key));
156 ofpact_put_OUTPUT(&ofpacts)->port = ofport;
157 ofctrl_add_flow(0, 50, &match, &ofpacts);
160 /* Table 64, Priority 100.
161 * =======================
163 * Drop packets whose logical inport and outport are the same. */
164 match_init_catchall(&match);
165 ofpbuf_clear(&ofpacts);
166 match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, binding->tunnel_key);
167 match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, binding->tunnel_key);
168 ofctrl_add_flow(64, 100, &match, &ofpacts);
170 /* Table 64, Priority 50.
171 * ======================
173 * For packets to remote machines, send them over a tunnel to the
176 * For packets to local vifs, deliver them directly. */
177 match_init_catchall(&match);
178 ofpbuf_clear(&ofpacts);
179 match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, binding->tunnel_key);
181 /* Set MFF_TUN_ID. */
182 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
183 sf->field = mf_from_id(MFF_TUN_ID);
184 sf->value.be64 = htonll(binding->tunnel_key);
185 sf->mask.be64 = OVS_BE64_MAX;
187 ofpact_put_OUTPUT(&ofpacts)->port = ofport;
188 ofctrl_add_flow(64, 50, &match, &ofpacts);
191 ofpbuf_uninit(&ofpacts);
192 simap_destroy(&lport_to_ofport);
193 simap_destroy(&chassis_to_ofport);