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.
19 #include "dynamic-string.h"
22 #include "ofp-actions.h"
24 #include "ofp-print.h"
27 #include "openflow/openflow.h"
28 #include "openvswitch/vlog.h"
29 #include "ovn-controller.h"
31 #include "socket-util.h"
33 VLOG_DEFINE_THIS_MODULE(ofctrl);
35 /* An OpenFlow flow. */
38 struct hmap_node hmap_node; /* In 'desired_flows' or 'installed_flows'. */
44 struct ofpact *ofpacts;
48 static uint32_t ovn_flow_hash(const struct ovn_flow *);
49 static struct ovn_flow *ovn_flow_lookup(struct hmap *flow_table,
50 const struct ovn_flow *target);
51 static char *ovn_flow_to_string(const struct ovn_flow *);
52 static void ovn_flow_log(const struct ovn_flow *, const char *action);
53 static void ovn_flow_destroy(struct ovn_flow *);
55 /* OpenFlow connection to the switch. */
56 static struct rconn *swconn;
58 /* Last seen sequence number for 'swconn'. When this differs from
59 * rconn_get_connection_seqno(rconn), 'swconn' has reconnected. */
60 static unsigned int seqno;
62 /* Counter for in-flight OpenFlow messages on 'swconn'. We only send a new
63 * round of flow table modifications to the switch when the counter falls to
64 * zero, to avoid unbounded buffering. */
65 static struct rconn_packet_counter *tx_counter;
67 /* Flow tables. Each holds "struct ovn_flow"s.
69 * 'desired_flows' is the flow table that we want the switch to have.
70 * 'installed_flows' is the flow table currently installed in the switch. */
71 static struct hmap desired_flows;
72 static struct hmap installed_flows;
74 static void ovn_flow_table_clear(struct hmap *flow_table);
75 static void ovn_flow_table_destroy(struct hmap *flow_table);
77 static void ofctrl_update_flows(void);
78 static void ofctrl_recv(const struct ofpbuf *msg);
83 swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
84 tx_counter = rconn_packet_counter_create();
85 hmap_init(&desired_flows);
86 hmap_init(&installed_flows);
89 /* This function should be called in the main loop after anything that updates
90 * the flow table (e.g. after calls to ofctrl_clear_flows() and
91 * ofctrl_add_flow()). */
93 ofctrl_run(struct controller_ctx *ctx)
96 target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), ctx->br_int_name);
97 if (strcmp(target, rconn_get_target(swconn))) {
98 rconn_connect(swconn, target, target);
104 if (!rconn_is_connected(swconn)) {
107 if (!rconn_packet_counter_n_packets(tx_counter)) {
108 ofctrl_update_flows();
111 for (int i = 0; i < 50; i++) {
112 struct ofpbuf *msg = rconn_recv(swconn);
125 rconn_run_wait(swconn);
126 rconn_recv_wait(swconn);
132 rconn_destroy(swconn);
133 ovn_flow_table_destroy(&installed_flows);
134 ovn_flow_table_destroy(&desired_flows);
135 rconn_packet_counter_destroy(tx_counter);
139 queue_msg(struct ofpbuf *msg)
141 rconn_send(swconn, msg, tx_counter);
145 ofctrl_recv(const struct ofpbuf *msg)
151 if (ofptype_pull(&type, &b)) {
156 case OFPTYPE_ECHO_REQUEST:
157 queue_msg(make_echo_reply(msg->data));
160 case OFPTYPE_ECHO_REPLY:
161 case OFPTYPE_PACKET_IN:
162 case OFPTYPE_PORT_STATUS:
163 case OFPTYPE_FLOW_REMOVED:
169 case OFPTYPE_FEATURES_REQUEST:
170 case OFPTYPE_FEATURES_REPLY:
171 case OFPTYPE_GET_CONFIG_REQUEST:
172 case OFPTYPE_GET_CONFIG_REPLY:
173 case OFPTYPE_SET_CONFIG:
174 case OFPTYPE_PACKET_OUT:
175 case OFPTYPE_FLOW_MOD:
176 case OFPTYPE_GROUP_MOD:
177 case OFPTYPE_PORT_MOD:
178 case OFPTYPE_TABLE_MOD:
179 case OFPTYPE_BARRIER_REQUEST:
180 case OFPTYPE_BARRIER_REPLY:
181 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
182 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
183 case OFPTYPE_DESC_STATS_REQUEST:
184 case OFPTYPE_DESC_STATS_REPLY:
185 case OFPTYPE_FLOW_STATS_REQUEST:
186 case OFPTYPE_FLOW_STATS_REPLY:
187 case OFPTYPE_AGGREGATE_STATS_REQUEST:
188 case OFPTYPE_AGGREGATE_STATS_REPLY:
189 case OFPTYPE_TABLE_STATS_REQUEST:
190 case OFPTYPE_TABLE_STATS_REPLY:
191 case OFPTYPE_PORT_STATS_REQUEST:
192 case OFPTYPE_PORT_STATS_REPLY:
193 case OFPTYPE_QUEUE_STATS_REQUEST:
194 case OFPTYPE_QUEUE_STATS_REPLY:
195 case OFPTYPE_PORT_DESC_STATS_REQUEST:
196 case OFPTYPE_PORT_DESC_STATS_REPLY:
197 case OFPTYPE_ROLE_REQUEST:
198 case OFPTYPE_ROLE_REPLY:
199 case OFPTYPE_ROLE_STATUS:
200 case OFPTYPE_SET_FLOW_FORMAT:
201 case OFPTYPE_FLOW_MOD_TABLE_ID:
202 case OFPTYPE_SET_PACKET_IN_FORMAT:
203 case OFPTYPE_FLOW_AGE:
204 case OFPTYPE_SET_CONTROLLER_ID:
205 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
206 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
207 case OFPTYPE_FLOW_MONITOR_CANCEL:
208 case OFPTYPE_FLOW_MONITOR_PAUSED:
209 case OFPTYPE_FLOW_MONITOR_RESUMED:
210 case OFPTYPE_GET_ASYNC_REQUEST:
211 case OFPTYPE_GET_ASYNC_REPLY:
212 case OFPTYPE_SET_ASYNC_CONFIG:
213 case OFPTYPE_METER_MOD:
214 case OFPTYPE_GROUP_STATS_REQUEST:
215 case OFPTYPE_GROUP_STATS_REPLY:
216 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
217 case OFPTYPE_GROUP_DESC_STATS_REPLY:
218 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
219 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
220 case OFPTYPE_METER_STATS_REQUEST:
221 case OFPTYPE_METER_STATS_REPLY:
222 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
223 case OFPTYPE_METER_CONFIG_STATS_REPLY:
224 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
225 case OFPTYPE_METER_FEATURES_STATS_REPLY:
226 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
227 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
228 case OFPTYPE_BUNDLE_CONTROL:
229 case OFPTYPE_BUNDLE_ADD_MESSAGE:
230 case OFPTYPE_NXT_GENEVE_TABLE_MOD:
231 case OFPTYPE_NXT_GENEVE_TABLE_REQUEST:
232 case OFPTYPE_NXT_GENEVE_TABLE_REPLY:
234 /* Messages that are generally unexpected. */
235 if (VLOG_IS_DBG_ENABLED()) {
236 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
238 char *s = ofp_to_string(msg->data, msg->size, 2);
239 VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s);
245 /* Flow table interface to the rest of ovn-controller. */
247 /* Clears the table of flows desired to be in the switch. Call this before
248 * adding the desired flows (with ofctrl_add_flow()). */
250 ofctrl_clear_flows(void)
252 ovn_flow_table_clear(&desired_flows);
255 /* Adds a flow with the specified 'match' and 'actions' to the OpenFlow table
256 * numbered 'table_id' with the given 'priority'. The caller retains ownership
257 * of 'match' and 'actions'.
259 * This just assembles the desired flow table in memory. Nothing is actually
260 * sent to the switch until a later call to ofctrl_run(). */
262 ofctrl_add_flow(uint8_t table_id, uint16_t priority,
263 const struct match *match, const struct ofpbuf *actions)
265 struct ovn_flow *f = xmalloc(sizeof *f);
266 f->table_id = table_id;
267 f->priority = priority;
269 f->ofpacts = xmemdup(actions->data, actions->size);
270 f->ofpacts_len = actions->size;
272 if (ovn_flow_lookup(&desired_flows, f)) {
273 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
274 if (!VLOG_DROP_INFO(&rl)) {
275 char *s = ovn_flow_to_string(f);
276 VLOG_INFO("dropping duplicate flow: %s", s);
284 hmap_insert(&desired_flows, &f->hmap_node, ovn_flow_hash(f));
289 /* Returns a hash of the key in 'f'. */
291 ovn_flow_hash(const struct ovn_flow *f)
293 return hash_2words((f->table_id << 16) | f->priority,
294 match_hash(&f->match, 0));
298 /* Finds and returns an ovn_flow in 'flow_table' whose key is identical to
299 * 'target''s key, or NULL if there is none. */
300 static struct ovn_flow *
301 ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target)
305 HMAP_FOR_EACH_WITH_HASH (f, hmap_node, target->hmap_node.hash,
307 if (f->table_id == target->table_id
308 && f->priority == target->priority
309 && match_equal(&f->match, &target->match)) {
317 ovn_flow_to_string(const struct ovn_flow *f)
319 struct ds s = DS_EMPTY_INITIALIZER;
320 ds_put_format(&s, "table_id=%"PRIu8", ", f->table_id);
321 ds_put_format(&s, "priority=%"PRIu16", ", f->priority);
322 match_format(&f->match, &s, OFP_DEFAULT_PRIORITY);
323 ds_put_cstr(&s, ", actions=");
324 ofpacts_format(f->ofpacts, f->ofpacts_len, &s);
325 return ds_steal_cstr(&s);
329 ovn_flow_log(const struct ovn_flow *f, const char *action)
331 if (VLOG_IS_DBG_ENABLED()) {
332 char *s = ovn_flow_to_string(f);
333 VLOG_DBG("%s flow: %s", action, s);
339 ovn_flow_destroy(struct ovn_flow *f)
347 /* Flow tables of struct ovn_flow. */
350 ovn_flow_table_clear(struct hmap *flow_table)
352 struct ovn_flow *f, *next;
353 HMAP_FOR_EACH_SAFE (f, next, hmap_node, flow_table) {
354 hmap_remove(flow_table, &f->hmap_node);
359 ovn_flow_table_destroy(struct hmap *flow_table)
361 ovn_flow_table_clear(flow_table);
362 hmap_destroy(flow_table);
365 /* Flow table update. */
368 queue_flow_mod(struct ofputil_flow_mod *fm)
370 fm->buffer_id = UINT32_MAX;
371 fm->out_port = OFPP_ANY;
372 fm->out_group = OFPG_ANY;
373 queue_msg(ofputil_encode_flow_mod(fm, OFPUTIL_P_OF13_OXM));
377 ofctrl_update_flows(void)
379 /* If we've (re)connected, don't make any assumptions about the flows in
380 * the switch: delete all of them. (We'll immediately repopulate it
382 if (seqno != rconn_get_connection_seqno(swconn)) {
383 seqno = rconn_get_connection_seqno(swconn);
385 /* Send a flow_mod to delete all flows. */
386 struct ofputil_flow_mod fm = {
387 .match = MATCH_CATCHALL_INITIALIZER,
388 .table_id = OFPTT_ALL,
389 .command = OFPFC_DELETE,
392 VLOG_DBG("clearing all flows");
394 /* Clear installed_flows, to match the state of the switch. */
395 ovn_flow_table_clear(&installed_flows);
398 /* Iterate through all of the installed flows. If any of them are no
399 * longer desired, delete them; if any of them should have different
400 * actions, update them. */
401 struct ovn_flow *i, *next;
402 HMAP_FOR_EACH_SAFE (i, next, hmap_node, &installed_flows) {
403 struct ovn_flow *d = ovn_flow_lookup(&desired_flows, i);
405 /* Installed flow is no longer desirable. Delete it from the
406 * switch and from installed_flows. */
407 struct ofputil_flow_mod fm;
408 memset(&fm, 0, sizeof fm);
410 fm.priority = i->priority;
411 fm.table_id = i->table_id;
412 fm.command = OFPFC_DELETE_STRICT;
414 ovn_flow_log(i, "removing");
416 hmap_remove(&installed_flows, &i->hmap_node);
419 if (!ofpacts_equal(i->ofpacts, i->ofpacts_len,
420 d->ofpacts, d->ofpacts_len)) {
421 /* Update actions in installed flow. */
422 struct ofputil_flow_mod fm;
423 memset(&fm, 0, sizeof fm);
425 fm.priority = i->priority;
426 fm.table_id = i->table_id;
427 fm.ofpacts = d->ofpacts;
428 fm.ofpacts_len = d->ofpacts_len;
429 fm.command = OFPFC_MODIFY_STRICT;
431 ovn_flow_log(i, "updating");
433 /* Replace 'i''s actions by 'd''s. */
435 i->ofpacts = d->ofpacts;
436 i->ofpacts_len = d->ofpacts_len;
441 hmap_remove(&desired_flows, &d->hmap_node);
446 /* The previous loop removed from desired_flows all of the flows that are
447 * already installed. Thus, any flows remaining in desired_flows need to
448 * be added to the flow table. */
450 HMAP_FOR_EACH_SAFE (d, next, hmap_node, &desired_flows) {
451 /* Send flow_mod to add flow. */
452 struct ofputil_flow_mod fm;
453 memset(&fm, 0, sizeof fm);
455 fm.priority = d->priority;
456 fm.table_id = d->table_id;
457 fm.ofpacts = d->ofpacts;
458 fm.ofpacts_len = d->ofpacts_len;
459 fm.command = OFPFC_ADD;
461 ovn_flow_log(d, "adding");
463 /* Move 'd' from desired_flows to installed_flows. */
464 hmap_remove(&desired_flows, &d->hmap_node);
465 hmap_insert(&installed_flows, &d->hmap_node, d->hmap_node.hash);