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, const struct ovsrec_bridge *br_int,
47 struct hmap *flow_table)
49 struct simap lport_to_ofport = SIMAP_INITIALIZER(&lport_to_ofport);
50 struct simap chassis_to_ofport = SIMAP_INITIALIZER(&chassis_to_ofport);
51 for (int i = 0; i < br_int->n_ports; i++) {
52 const struct ovsrec_port *port_rec = br_int->ports[i];
53 if (!strcmp(port_rec->name, br_int->name)) {
57 const char *chassis_id = smap_get(&port_rec->external_ids,
59 if (chassis_id && !strcmp(chassis_id, ctx->chassis_id)) {
63 for (int j = 0; j < port_rec->n_interfaces; j++) {
64 const struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
66 /* Get OpenFlow port number. */
67 if (!iface_rec->n_ofport) {
70 int64_t ofport = iface_rec->ofport[0];
71 if (ofport < 1 || ofport > ofp_to_u16(OFPP_MAX)) {
75 /* Record as chassis or local logical port. */
77 simap_put(&chassis_to_ofport, chassis_id, ofport);
80 const char *iface_id = smap_get(&iface_rec->external_ids,
83 simap_put(&lport_to_ofport, iface_id, ofport);
89 struct ofpbuf ofpacts;
90 ofpbuf_init(&ofpacts, 0);
92 /* Set up flows in table 0 for physical-to-logical translation and in table
93 * 64 for logical-to-physical translation. */
94 const struct sbrec_binding *binding;
95 SBREC_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
96 /* Find the OpenFlow port for the logical port, as 'ofport'. If it's
97 * on a remote chassis, this is the OpenFlow port for the tunnel to
98 * that chassis (and set 'local' to false). Otherwise, if it's on the
99 * chassis we're managing, this is the OpenFlow port for the vif itself
100 * (and set 'local' to true). When 'parent_port' is set for a binding,
101 * it implies a container sitting inside a VM reachable via a 'tag'.
106 if (binding->parent_port) {
107 ofport = u16_to_ofp(simap_get(&lport_to_ofport,
108 binding->parent_port));
109 if (ofport && binding->tag) {
113 ofport = u16_to_ofp(simap_get(&lport_to_ofport,
114 binding->logical_port));
117 bool local = ofport != 0;
119 if (!binding->chassis) {
122 ofport = u16_to_ofp(simap_get(&chassis_to_ofport,
123 binding->chassis->name));
129 /* Translate the logical datapath into the form we use in
131 uint32_t ldp = ldp_to_integer(&binding->logical_datapath);
138 /* Packets that arrive from a vif can belong to a VM or
139 * to a container located inside that VM. Packets that
140 * arrive from containers have a tag (vlan) associated with them.
143 /* Table 0, Priority 150 and 100.
144 * ==============================
146 * Priority 150 is for traffic belonging to containers. For such
147 * traffic, match on the tags and then strip the tag.
148 * Priority 100 is for traffic belonging to VMs.
150 * For both types of traffic: set MFF_LOG_INPORT to the
151 * logical input port, MFF_METADATA to the logical datapath, and
152 * resubmit into the logical pipeline starting at table 16. */
153 match_init_catchall(&match);
154 ofpbuf_clear(&ofpacts);
155 match_set_in_port(&match, ofport);
157 match_set_dl_vlan(&match, htons(tag));
160 /* Set MFF_METADATA. */
161 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
162 sf->field = mf_from_id(MFF_METADATA);
163 sf->value.be64 = htonll(ldp);
164 sf->mask.be64 = OVS_BE64_MAX;
166 /* Set MFF_LOG_INPORT. */
167 sf = ofpact_put_SET_FIELD(&ofpacts);
168 sf->field = mf_from_id(MFF_LOG_INPORT);
169 sf->value.be32 = htonl(binding->tunnel_key);
170 sf->mask.be32 = OVS_BE32_MAX;
174 ofpact_put_STRIP_VLAN(&ofpacts);
177 /* Resubmit to first logical pipeline table. */
178 struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(&ofpacts);
179 resubmit->in_port = OFPP_IN_PORT;
180 resubmit->table_id = 16;
181 ofctrl_add_flow(flow_table, 0, tag ? 150 : 100, &match, &ofpacts);
183 /* Table 0, Priority 50.
184 * =====================
186 * For packets that arrive from a remote node destined to this
187 * local vif: deliver directly to the vif. If the destination
188 * is a container sitting behind a vif, tag the packets. */
189 match_init_catchall(&match);
190 ofpbuf_clear(&ofpacts);
191 match_set_tun_id(&match, htonll(binding->tunnel_key));
193 struct ofpact_vlan_vid *vlan_vid;
194 vlan_vid = ofpact_put_SET_VLAN_VID(&ofpacts);
195 vlan_vid->vlan_vid = tag;
196 vlan_vid->push_vlan_if_needed = true;
198 ofpact_put_OUTPUT(&ofpacts)->port = ofport;
199 ofctrl_add_flow(flow_table, 0, 50, &match, &ofpacts);
202 /* Table 64, Priority 100.
203 * =======================
205 * Drop packets whose logical inport and outport are the same. */
206 match_init_catchall(&match);
207 ofpbuf_clear(&ofpacts);
208 match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, binding->tunnel_key);
209 match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, binding->tunnel_key);
210 ofctrl_add_flow(flow_table, 64, 100, &match, &ofpacts);
212 /* Table 64, Priority 50.
213 * ======================
215 * For packets to remote machines, send them over a tunnel to the
218 * For packets to local vifs, deliver them directly. */
219 match_init_catchall(&match);
220 ofpbuf_clear(&ofpacts);
221 match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, binding->tunnel_key);
223 /* Set MFF_TUN_ID. */
224 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
225 sf->field = mf_from_id(MFF_TUN_ID);
226 sf->value.be64 = htonll(binding->tunnel_key);
227 sf->mask.be64 = OVS_BE64_MAX;
230 /* For containers sitting behind a local vif, tag the packets
231 * before delivering them. Since there is a possibility of
232 * packets needing to hair-pin back into the same vif from
233 * which it came, make the in_port as zero. */
234 struct ofpact_vlan_vid *vlan_vid;
235 vlan_vid = ofpact_put_SET_VLAN_VID(&ofpacts);
236 vlan_vid->vlan_vid = tag;
237 vlan_vid->push_vlan_if_needed = true;
239 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
240 sf->field = mf_from_id(MFF_IN_PORT);
242 sf->mask.be16 = OVS_BE16_MAX;
244 ofpact_put_OUTPUT(&ofpacts)->port = ofport;
245 ofctrl_add_flow(flow_table, 64, 50, &match, &ofpacts);
248 ofpbuf_uninit(&ofpacts);
249 simap_destroy(&lport_to_ofport);
250 simap_destroy(&chassis_to_ofport);