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, push the in_port to stack and make the
234 * in_port as zero. */
235 struct ofpact_vlan_vid
*vlan_vid
;
236 vlan_vid
= ofpact_put_SET_VLAN_VID(&ofpacts
);
237 vlan_vid
->vlan_vid
= tag
;
238 vlan_vid
->push_vlan_if_needed
= true;
240 struct ofpact_stack
*stack_action
;
241 const struct mf_field
*field
;
242 stack_action
= ofpact_put_STACK_PUSH(&ofpacts
);
243 field
= mf_from_id(MFF_IN_PORT
);
244 stack_action
->subfield
.field
= field
;
245 stack_action
->subfield
.ofs
= 0;
246 stack_action
->subfield
.n_bits
= field
->n_bits
;
248 struct ofpact_set_field
*sf
= ofpact_put_SET_FIELD(&ofpacts
);
249 sf
->field
= mf_from_id(MFF_IN_PORT
);
251 sf
->mask
.be16
= OVS_BE16_MAX
;
253 ofpact_put_OUTPUT(&ofpacts
)->port
= ofport
;
255 /* Revert the tag added to the packets headed to containers
256 * in the previous step. If we don't do this, the packets
257 * that are to be broadcasted to a VM in the same logical
258 * switch will also contain the tag. Also revert the zero'd
260 ofpact_put_STRIP_VLAN(&ofpacts
);
262 struct ofpact_stack
*stack_action
;
263 const struct mf_field
*field
;
264 stack_action
= ofpact_put_STACK_POP(&ofpacts
);
265 field
= mf_from_id(MFF_IN_PORT
);
266 stack_action
->subfield
.field
= field
;
267 stack_action
->subfield
.ofs
= 0;
268 stack_action
->subfield
.n_bits
= field
->n_bits
;
270 ofctrl_add_flow(flow_table
, 64, 50, &match
, &ofpacts
);
273 ofpbuf_uninit(&ofpacts
);
274 simap_destroy(&lport_to_ofport
);
275 simap_destroy(&chassis_to_ofport
);