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.
18 #include "dynamic-string.h"
20 #include "ofp-actions.h"
22 #include "openvswitch/vlog.h"
23 #include "ovn/controller/ovn-controller.h"
24 #include "ovn/lib/actions.h"
25 #include "ovn/lib/expr.h"
26 #include "ovn/lib/ovn-sb-idl.h"
29 VLOG_DEFINE_THIS_MODULE(lflow
);
33 /* Contains "struct expr_symbol"s for fields supported by OVN lflows. */
34 static struct shash symtab
;
37 add_logical_register(struct shash
*symtab
, enum mf_field_id id
)
41 snprintf(name
, sizeof name
, "reg%d", id
- MFF_REG0
);
42 expr_symtab_add_field(symtab
, name
, id
, NULL
, false);
50 /* Reserve a pair of registers for the logical inport and outport. A full
51 * 32-bit register each is bigger than we need, but the expression code
52 * doesn't yet support string fields that occupy less than a full OXM. */
53 expr_symtab_add_string(&symtab
, "inport", MFF_LOG_INPORT
, NULL
);
54 expr_symtab_add_string(&symtab
, "outport", MFF_LOG_OUTPORT
, NULL
);
56 /* Logical registers. */
57 #define MFF_LOG_REG(ID) add_logical_register(&symtab, ID);
62 expr_symtab_add_field(&symtab
, "eth.src", MFF_ETH_SRC
, NULL
, false);
63 expr_symtab_add_field(&symtab
, "eth.dst", MFF_ETH_DST
, NULL
, false);
64 expr_symtab_add_field(&symtab
, "eth.type", MFF_ETH_TYPE
, NULL
, true);
66 expr_symtab_add_field(&symtab
, "vlan.tci", MFF_VLAN_TCI
, NULL
, false);
67 expr_symtab_add_predicate(&symtab
, "vlan.present", "vlan.tci[12]");
68 expr_symtab_add_subfield(&symtab
, "vlan.pcp", "vlan.present",
70 expr_symtab_add_subfield(&symtab
, "vlan.vid", "vlan.present",
73 expr_symtab_add_predicate(&symtab
, "ip4", "eth.type == 0x800");
74 expr_symtab_add_predicate(&symtab
, "ip6", "eth.type == 0x86dd");
75 expr_symtab_add_predicate(&symtab
, "ip", "ip4 || ip6");
76 expr_symtab_add_field(&symtab
, "ip.proto", MFF_IP_PROTO
, "ip", true);
77 expr_symtab_add_field(&symtab
, "ip.dscp", MFF_IP_DSCP
, "ip", false);
78 expr_symtab_add_field(&symtab
, "ip.ecn", MFF_IP_ECN
, "ip", false);
79 expr_symtab_add_field(&symtab
, "ip.ttl", MFF_IP_TTL
, "ip", false);
81 expr_symtab_add_field(&symtab
, "ip4.src", MFF_IPV4_SRC
, "ip4", false);
82 expr_symtab_add_field(&symtab
, "ip4.dst", MFF_IPV4_DST
, "ip4", false);
84 expr_symtab_add_predicate(&symtab
, "icmp4", "ip4 && ip.proto == 1");
85 expr_symtab_add_field(&symtab
, "icmp4.type", MFF_ICMPV4_TYPE
, "icmp4",
87 expr_symtab_add_field(&symtab
, "icmp4.code", MFF_ICMPV4_CODE
, "icmp4",
90 expr_symtab_add_field(&symtab
, "ip6.src", MFF_IPV6_SRC
, "ip6", false);
91 expr_symtab_add_field(&symtab
, "ip6.dst", MFF_IPV6_DST
, "ip6", false);
92 expr_symtab_add_field(&symtab
, "ip6.label", MFF_IPV6_LABEL
, "ip6", false);
94 expr_symtab_add_predicate(&symtab
, "icmp6", "ip6 && ip.proto == 58");
95 expr_symtab_add_field(&symtab
, "icmp6.type", MFF_ICMPV6_TYPE
, "icmp6",
97 expr_symtab_add_field(&symtab
, "icmp6.code", MFF_ICMPV6_CODE
, "icmp6",
100 expr_symtab_add_predicate(&symtab
, "icmp", "icmp4 || icmp6");
102 expr_symtab_add_field(&symtab
, "ip.frag", MFF_IP_FRAG
, "ip", false);
103 expr_symtab_add_predicate(&symtab
, "ip.is_frag", "ip.frag[0]");
104 expr_symtab_add_predicate(&symtab
, "ip.later_frag", "ip.frag[1]");
105 expr_symtab_add_predicate(&symtab
, "ip.first_frag",
106 "ip.is_frag && !ip.later_frag");
108 expr_symtab_add_predicate(&symtab
, "arp", "eth.type == 0x806");
109 expr_symtab_add_field(&symtab
, "arp.op", MFF_ARP_OP
, "arp", false);
110 expr_symtab_add_field(&symtab
, "arp.spa", MFF_ARP_SPA
, "arp", false);
111 expr_symtab_add_field(&symtab
, "arp.sha", MFF_ARP_SHA
, "arp", false);
112 expr_symtab_add_field(&symtab
, "arp.tpa", MFF_ARP_TPA
, "arp", false);
113 expr_symtab_add_field(&symtab
, "arp.tha", MFF_ARP_THA
, "arp", false);
115 expr_symtab_add_predicate(&symtab
, "nd",
116 "icmp6.type == {135, 136} && icmp6.code == 0");
117 expr_symtab_add_field(&symtab
, "nd.target", MFF_ND_TARGET
, "nd", false);
118 expr_symtab_add_field(&symtab
, "nd.sll", MFF_ND_SLL
,
119 "nd && icmp6.type == 135", false);
120 expr_symtab_add_field(&symtab
, "nd.tll", MFF_ND_TLL
,
121 "nd && icmp6.type == 136", false);
123 expr_symtab_add_predicate(&symtab
, "tcp", "ip.proto == 6");
124 expr_symtab_add_field(&symtab
, "tcp.src", MFF_TCP_SRC
, "tcp", false);
125 expr_symtab_add_field(&symtab
, "tcp.dst", MFF_TCP_DST
, "tcp", false);
126 expr_symtab_add_field(&symtab
, "tcp.flags", MFF_TCP_FLAGS
, "tcp", false);
128 expr_symtab_add_predicate(&symtab
, "udp", "ip.proto == 17");
129 expr_symtab_add_field(&symtab
, "udp.src", MFF_UDP_SRC
, "udp", false);
130 expr_symtab_add_field(&symtab
, "udp.dst", MFF_UDP_DST
, "udp", false);
132 expr_symtab_add_predicate(&symtab
, "sctp", "ip.proto == 132");
133 expr_symtab_add_field(&symtab
, "sctp.src", MFF_SCTP_SRC
, "sctp", false);
134 expr_symtab_add_field(&symtab
, "sctp.dst", MFF_SCTP_DST
, "sctp", false);
137 /* Logical datapaths and logical port numbers. */
139 /* A logical datapath.
141 * 'ports' maps 'logical_port' names to 'tunnel_key' values in the OVN_SB
142 * Port_Binding table within the logical datapath. */
143 struct logical_datapath
{
144 struct hmap_node hmap_node
; /* Indexed on 'uuid'. */
145 struct uuid uuid
; /* UUID from Datapath_Binding row. */
146 uint32_t tunnel_key
; /* 'tunnel_key' from Datapath_Binding row. */
147 struct simap ports
; /* Logical port name to port number. */
150 /* Contains "struct logical_datapath"s. */
151 static struct hmap logical_datapaths
= HMAP_INITIALIZER(&logical_datapaths
);
153 /* Finds and returns the logical_datapath for 'binding', or NULL if no such
154 * logical_datapath exists. */
155 static struct logical_datapath
*
156 ldp_lookup(const struct sbrec_datapath_binding
*binding
)
158 struct logical_datapath
*ldp
;
159 HMAP_FOR_EACH_IN_BUCKET (ldp
, hmap_node
, uuid_hash(&binding
->header_
.uuid
),
160 &logical_datapaths
) {
161 if (uuid_equals(&ldp
->uuid
, &binding
->header_
.uuid
)) {
168 /* Creates a new logical_datapath for the given 'binding'. */
169 static struct logical_datapath
*
170 ldp_create(const struct sbrec_datapath_binding
*binding
)
172 struct logical_datapath
*ldp
;
174 ldp
= xmalloc(sizeof *ldp
);
175 hmap_insert(&logical_datapaths
, &ldp
->hmap_node
,
176 uuid_hash(&binding
->header_
.uuid
));
177 ldp
->uuid
= binding
->header_
.uuid
;
178 ldp
->tunnel_key
= binding
->tunnel_key
;
179 simap_init(&ldp
->ports
);
183 static struct logical_datapath
*
184 ldp_lookup_or_create(const struct sbrec_datapath_binding
*binding
)
186 struct logical_datapath
*ldp
= ldp_lookup(binding
);
187 return ldp
? ldp
: ldp_create(binding
);
191 ldp_free(struct logical_datapath
*ldp
)
193 simap_destroy(&ldp
->ports
);
194 hmap_remove(&logical_datapaths
, &ldp
->hmap_node
);
198 /* Iterates through all of the records in the Port_Binding table, updating the
199 * table of logical_datapaths to match the values found in active
202 ldp_run(struct controller_ctx
*ctx
)
204 struct logical_datapath
*ldp
;
205 HMAP_FOR_EACH (ldp
, hmap_node
, &logical_datapaths
) {
206 simap_clear(&ldp
->ports
);
209 const struct sbrec_port_binding
*binding
;
210 SBREC_PORT_BINDING_FOR_EACH (binding
, ctx
->ovnsb_idl
) {
211 struct logical_datapath
*ldp
= ldp_lookup_or_create(binding
->datapath
);
213 simap_put(&ldp
->ports
, binding
->logical_port
, binding
->tunnel_key
);
216 const struct sbrec_multicast_group
*mc
;
217 SBREC_MULTICAST_GROUP_FOR_EACH (mc
, ctx
->ovnsb_idl
) {
218 struct logical_datapath
*ldp
= ldp_lookup_or_create(mc
->datapath
);
219 simap_put(&ldp
->ports
, mc
->name
, mc
->tunnel_key
);
222 struct logical_datapath
*next_ldp
;
223 HMAP_FOR_EACH_SAFE (ldp
, next_ldp
, hmap_node
, &logical_datapaths
) {
224 if (simap_is_empty(&ldp
->ports
)) {
233 struct logical_datapath
*ldp
, *next_ldp
;
234 HMAP_FOR_EACH_SAFE (ldp
, next_ldp
, hmap_node
, &logical_datapaths
) {
245 /* Translates logical flows in the Logical_Flow table in the OVN_SB database
246 * into OpenFlow flows. See ovn-architecture(7) for more information. */
248 lflow_run(struct controller_ctx
*ctx
, struct hmap
*flow_table
)
250 struct hmap flows
= HMAP_INITIALIZER(&flows
);
251 uint32_t conj_id_ofs
= 1;
255 const struct sbrec_logical_flow
*lflow
;
256 SBREC_LOGICAL_FLOW_FOR_EACH (lflow
, ctx
->ovnsb_idl
) {
257 /* Find the "struct logical_datapath" asssociated with this
258 * Logical_Flow row. If there's no such struct, that must be because
259 * no logical ports are bound to that logical datapath, so there's no
260 * point in maintaining any flows for it anyway, so skip it. */
261 const struct logical_datapath
*ldp
;
262 ldp
= ldp_lookup(lflow
->logical_datapath
);
267 /* Determine translation of logical table IDs to physical table IDs. */
268 bool ingress
= !strcmp(lflow
->pipeline
, "ingress");
269 uint8_t first_ptable
= (ingress
270 ? OFTABLE_LOG_INGRESS_PIPELINE
271 : OFTABLE_LOG_EGRESS_PIPELINE
);
272 uint8_t ptable
= first_ptable
+ lflow
->table_id
;
273 uint8_t output_ptable
= (ingress
274 ? OFTABLE_REMOTE_OUTPUT
275 : OFTABLE_LOG_TO_PHY
);
277 /* Translate OVN actions into OpenFlow actions.
279 * XXX Deny changes to 'outport' in egress pipeline. */
280 uint64_t ofpacts_stub
[64 / 8];
281 struct ofpbuf ofpacts
;
282 struct expr
*prereqs
;
285 ofpbuf_use_stub(&ofpacts
, ofpacts_stub
, sizeof ofpacts_stub
);
286 error
= actions_parse_string(lflow
->actions
, &symtab
, &ldp
->ports
,
287 first_ptable
, LOG_PIPELINE_LEN
,
288 lflow
->table_id
, output_ptable
,
291 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
292 VLOG_WARN_RL(&rl
, "error parsing actions \"%s\": %s",
293 lflow
->actions
, error
);
298 /* Translate OVN match into table of OpenFlow matches. */
302 expr
= expr_parse_string(lflow
->match
, &symtab
, &error
);
305 expr
= expr_combine(EXPR_T_AND
, expr
, prereqs
);
308 expr
= expr_annotate(expr
, &symtab
, &error
);
311 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
312 VLOG_WARN_RL(&rl
, "error parsing match \"%s\": %s",
313 lflow
->match
, error
);
314 expr_destroy(prereqs
);
315 ofpbuf_uninit(&ofpacts
);
320 expr
= expr_simplify(expr
);
321 expr
= expr_normalize(expr
);
322 uint32_t n_conjs
= expr_to_matches(expr
, &ldp
->ports
, &matches
);
325 /* Prepare the OpenFlow matches for adding to the flow table. */
326 struct expr_match
*m
;
327 HMAP_FOR_EACH (m
, hmap_node
, &matches
) {
328 match_set_metadata(&m
->match
, htonll(ldp
->tunnel_key
));
329 if (m
->match
.wc
.masks
.conj_id
) {
330 m
->match
.flow
.conj_id
+= conj_id_ofs
;
333 ofctrl_add_flow(flow_table
, ptable
, lflow
->priority
,
334 &m
->match
, &ofpacts
);
336 uint64_t conj_stubs
[64 / 8];
339 ofpbuf_use_stub(&conj
, conj_stubs
, sizeof conj_stubs
);
340 for (int i
= 0; i
< m
->n
; i
++) {
341 const struct cls_conjunction
*src
= &m
->conjunctions
[i
];
342 struct ofpact_conjunction
*dst
;
344 dst
= ofpact_put_CONJUNCTION(&conj
);
345 dst
->id
= src
->id
+ conj_id_ofs
;
346 dst
->clause
= src
->clause
;
347 dst
->n_clauses
= src
->n_clauses
;
349 ofctrl_add_flow(flow_table
, ptable
, lflow
->priority
,
351 ofpbuf_uninit(&conj
);
356 expr_matches_destroy(&matches
);
357 ofpbuf_uninit(&ofpacts
);
358 conj_id_ofs
+= n_conjs
;
365 expr_symtab_destroy(&symtab
);