1 /* Copyright (c) 2015, 2016 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 "byte-order.h"
25 #include "openflow/openflow.h"
26 #include "openvswitch/dynamic-string.h"
27 #include "openvswitch/list.h"
28 #include "openvswitch/match.h"
29 #include "openvswitch/ofp-actions.h"
30 #include "openvswitch/ofp-msgs.h"
31 #include "openvswitch/ofp-parse.h"
32 #include "openvswitch/ofp-print.h"
33 #include "openvswitch/ofp-util.h"
34 #include "openvswitch/ofpbuf.h"
35 #include "openvswitch/vlog.h"
36 #include "ovn-controller.h"
37 #include "ovn/lib/actions.h"
40 #include "socket-util.h"
42 #include "vswitch-idl.h"
44 VLOG_DEFINE_THIS_MODULE(ofctrl);
46 /* An OpenFlow flow. */
48 struct hmap_node match_hmap_node; /* For match based hashing. */
49 struct hindex_node uuid_hindex_node; /* For uuid based hashing. */
50 struct ovs_list list_node; /* For handling lists of flows. */
57 /* Data. UUID is used for disambiguation. */
59 struct ofpact *ofpacts;
63 static uint32_t ovn_flow_match_hash(const struct ovn_flow *);
64 static void ovn_flow_lookup(struct hmap *, const struct ovn_flow *target,
65 struct ovs_list *answers);
66 static char *ovn_flow_to_string(const struct ovn_flow *);
67 static void ovn_flow_log(const struct ovn_flow *, const char *action);
68 static void ovn_flow_destroy(struct ovn_flow *);
70 static ovs_be32 queue_msg(struct ofpbuf *);
71 static void queue_flow_mod(struct ofputil_flow_mod *);
73 /* OpenFlow connection to the switch. */
74 static struct rconn *swconn;
76 static void queue_group_mod(struct ofputil_group_mod *);
78 /* Last seen sequence number for 'swconn'. When this differs from
79 * rconn_get_connection_seqno(rconn), 'swconn' has reconnected. */
80 static unsigned int seqno;
82 /* Connection state machine. */
85 STATE(S_TLV_TABLE_REQUESTED) \
86 STATE(S_TLV_TABLE_MOD_SENT) \
87 STATE(S_CLEAR_FLOWS) \
90 #define STATE(NAME) NAME,
96 static enum ofctrl_state state;
98 /* Transaction IDs for messages in flight to the switch. */
99 static ovs_be32 xid, xid2;
101 /* Counter for in-flight OpenFlow messages on 'swconn'. We only send a new
102 * round of flow table modifications to the switch when the counter falls to
103 * zero, to avoid unbounded buffering. */
104 static struct rconn_packet_counter *tx_counter;
106 /* Flow table of "struct ovn_flow"s, that holds the flow table currently
107 * installed in the switch. */
108 static struct hmap installed_flows;
110 /* A reference to the group_table. */
111 static struct group_table *groups;
113 /* MFF_* field ID for our Geneve option. In S_TLV_TABLE_MOD_SENT, this is
114 * the option we requested (we don't know whether we obtained it yet). In
115 * S_CLEAR_FLOWS or S_UPDATE_FLOWS, this is really the option we have. */
116 static enum mf_field_id mff_ovn_geneve;
118 static void ovn_flow_table_destroy(void);
120 static void ovn_group_table_clear(struct group_table *group_table,
123 static void ofctrl_recv(const struct ofp_header *, enum ofptype);
125 static struct hmap match_flow_table = HMAP_INITIALIZER(&match_flow_table);
126 static struct hindex uuid_flow_table = HINDEX_INITIALIZER(&uuid_flow_table);
131 swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
132 tx_counter = rconn_packet_counter_create();
133 hmap_init(&installed_flows);
136 /* S_NEW, for a new connection.
138 * Sends NXT_TLV_TABLE_REQUEST and transitions to
139 * S_TLV_TABLE_REQUESTED. */
144 struct ofpbuf *buf = ofpraw_alloc(OFPRAW_NXT_TLV_TABLE_REQUEST,
145 rconn_get_version(swconn), 0);
146 xid = queue_msg(buf);
147 state = S_TLV_TABLE_REQUESTED;
151 recv_S_NEW(const struct ofp_header *oh OVS_UNUSED,
152 enum ofptype type OVS_UNUSED)
157 /* S_TLV_TABLE_REQUESTED, when NXT_TLV_TABLE_REQUEST has been sent
158 * and we're waiting for a reply.
160 * If we receive an NXT_TLV_TABLE_REPLY:
162 * - If it contains our tunnel metadata option, assign its field ID to
163 * mff_ovn_geneve and transition to S_CLEAR_FLOWS.
165 * - Otherwise, if there is an unused tunnel metadata field ID, send
166 * NXT_TLV_TABLE_MOD and OFPT_BARRIER_REQUEST, and transition to
167 * S_TLV_TABLE_MOD_SENT.
169 * - Otherwise, log an error, disable Geneve, and transition to
172 * If we receive an OFPT_ERROR:
174 * - Log an error, disable Geneve, and transition to S_CLEAR_FLOWS. */
177 run_S_TLV_TABLE_REQUESTED(void)
182 recv_S_TLV_TABLE_REQUESTED(const struct ofp_header *oh, enum ofptype type)
184 if (oh->xid != xid) {
185 ofctrl_recv(oh, type);
186 } else if (type == OFPTYPE_NXT_TLV_TABLE_REPLY) {
187 struct ofputil_tlv_table_reply reply;
188 enum ofperr error = ofputil_decode_tlv_table_reply(oh, &reply);
190 VLOG_ERR("failed to decode TLV table request (%s)",
191 ofperr_to_string(error));
195 const struct ofputil_tlv_map *map;
196 uint64_t md_free = UINT64_MAX;
197 BUILD_ASSERT(TUN_METADATA_NUM_OPTS == 64);
199 LIST_FOR_EACH (map, list_node, &reply.mappings) {
200 if (map->option_class == OVN_GENEVE_CLASS
201 && map->option_type == OVN_GENEVE_TYPE
202 && map->option_len == OVN_GENEVE_LEN) {
203 if (map->index >= TUN_METADATA_NUM_OPTS) {
204 VLOG_ERR("desired Geneve tunnel option 0x%"PRIx16","
205 "%"PRIu8",%"PRIu8" already in use with "
206 "unsupported index %"PRIu16,
207 map->option_class, map->option_type,
208 map->option_len, map->index);
211 mff_ovn_geneve = MFF_TUN_METADATA0 + map->index;
212 state = S_CLEAR_FLOWS;
217 if (map->index < TUN_METADATA_NUM_OPTS) {
218 md_free &= ~(UINT64_C(1) << map->index);
222 VLOG_DBG("OVN Geneve option not found");
224 VLOG_ERR("no Geneve options free for use by OVN");
228 unsigned int index = rightmost_1bit_idx(md_free);
229 mff_ovn_geneve = MFF_TUN_METADATA0 + index;
230 struct ofputil_tlv_map tm;
231 tm.option_class = OVN_GENEVE_CLASS;
232 tm.option_type = OVN_GENEVE_TYPE;
233 tm.option_len = OVN_GENEVE_LEN;
236 struct ofputil_tlv_table_mod ttm;
237 ttm.command = NXTTMC_ADD;
238 ovs_list_init(&ttm.mappings);
239 ovs_list_push_back(&ttm.mappings, &tm.list_node);
241 xid = queue_msg(ofputil_encode_tlv_table_mod(OFP13_VERSION, &ttm));
242 xid2 = queue_msg(ofputil_encode_barrier_request(OFP13_VERSION));
243 state = S_TLV_TABLE_MOD_SENT;
244 } else if (type == OFPTYPE_ERROR) {
245 VLOG_ERR("switch refused to allocate Geneve option (%s)",
246 ofperr_to_string(ofperr_decode_msg(oh, NULL)));
249 char *s = ofp_to_string(oh, ntohs(oh->length), 1);
250 VLOG_ERR("unexpected reply to TLV table request (%s)",
259 state = S_CLEAR_FLOWS;
262 /* S_TLV_TABLE_MOD_SENT, when NXT_TLV_TABLE_MOD and OFPT_BARRIER_REQUEST
263 * have been sent and we're waiting for a reply to one or the other.
265 * If we receive an OFPT_ERROR:
267 * - If the error is NXTTMFC_ALREADY_MAPPED or NXTTMFC_DUP_ENTRY, we
268 * raced with some other controller. Transition to S_NEW.
270 * - Otherwise, log an error, disable Geneve, and transition to
273 * If we receive OFPT_BARRIER_REPLY:
275 * - Set the tunnel metadata field ID to the one that we requested.
276 * Transition to S_CLEAR_FLOWS.
280 run_S_TLV_TABLE_MOD_SENT(void)
285 recv_S_TLV_TABLE_MOD_SENT(const struct ofp_header *oh, enum ofptype type)
287 if (oh->xid != xid && oh->xid != xid2) {
288 ofctrl_recv(oh, type);
289 } else if (oh->xid == xid2 && type == OFPTYPE_BARRIER_REPLY) {
290 state = S_CLEAR_FLOWS;
291 } else if (oh->xid == xid && type == OFPTYPE_ERROR) {
292 enum ofperr error = ofperr_decode_msg(oh, NULL);
293 if (error == OFPERR_NXTTMFC_ALREADY_MAPPED ||
294 error == OFPERR_NXTTMFC_DUP_ENTRY) {
295 VLOG_INFO("raced with another controller adding "
296 "Geneve option (%s); trying again",
297 ofperr_to_string(error));
300 VLOG_ERR("error adding Geneve option (%s)",
301 ofperr_to_string(error));
305 char *s = ofp_to_string(oh, ntohs(oh->length), 1);
306 VLOG_ERR("unexpected reply to Geneve option allocation request (%s)",
314 state = S_CLEAR_FLOWS;
317 /* S_CLEAR_FLOWS, after we've established a Geneve metadata field ID and it's
318 * time to set up some flows.
320 * Sends an OFPT_TABLE_MOD to clear all flows, then transitions to
324 run_S_CLEAR_FLOWS(void)
326 /* Send a flow_mod to delete all flows. */
327 struct ofputil_flow_mod fm = {
328 .match = MATCH_CATCHALL_INITIALIZER,
329 .table_id = OFPTT_ALL,
330 .command = OFPFC_DELETE,
333 VLOG_DBG("clearing all flows");
335 struct ofputil_group_mod gm;
336 memset(&gm, 0, sizeof gm);
337 gm.command = OFPGC11_DELETE;
338 gm.group_id = OFPG_ALL;
339 gm.command_bucket_id = OFPG15_BUCKET_ALL;
340 ovs_list_init(&gm.buckets);
341 queue_group_mod(&gm);
342 ofputil_bucket_list_destroy(&gm.buckets);
344 /* Clear installed_flows, to match the state of the switch. */
345 ovn_flow_table_clear();
347 /* Clear existing groups, to match the state of the switch. */
349 ovn_group_table_clear(groups, true);
352 state = S_UPDATE_FLOWS;
356 recv_S_CLEAR_FLOWS(const struct ofp_header *oh, enum ofptype type)
358 ofctrl_recv(oh, type);
361 /* S_UPDATE_FLOWS, for maintaining the flow table over time.
363 * Compare the installed flows to the ones we want. Send OFPT_FLOW_MOD as
366 * This is a terminal state. We only transition out of it if the connection
370 run_S_UPDATE_FLOWS(void)
372 /* Nothing to do here.
374 * Being in this state enables ofctrl_put() to work, however. */
378 recv_S_UPDATE_FLOWS(const struct ofp_header *oh, enum ofptype type)
380 ofctrl_recv(oh, type);
383 /* Runs the OpenFlow state machine against 'br_int', which is local to the
384 * hypervisor on which we are running. Attempts to negotiate a Geneve option
385 * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. If successful,
386 * returns the MFF_* field ID for the option, otherwise returns 0. */
388 ofctrl_run(const struct ovsrec_bridge *br_int)
392 target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name);
393 if (strcmp(target, rconn_get_target(swconn))) {
394 VLOG_INFO("%s: connecting to switch", target);
395 rconn_connect(swconn, target, target);
399 rconn_disconnect(swconn);
404 if (!rconn_is_connected(swconn)) {
407 if (seqno != rconn_get_connection_seqno(swconn)) {
408 seqno = rconn_get_connection_seqno(swconn);
412 enum ofctrl_state old_state;
416 #define STATE(NAME) case NAME: run_##NAME(); break;
422 } while (state != old_state);
424 for (int i = 0; state == old_state && i < 50; i++) {
425 struct ofpbuf *msg = rconn_recv(swconn);
430 const struct ofp_header *oh = msg->data;
434 error = ofptype_decode(&type, oh);
437 #define STATE(NAME) case NAME: recv_##NAME(oh, type); break;
444 char *s = ofp_to_string(oh, ntohs(oh->length), 1);
445 VLOG_WARN("could not decode OpenFlow message (%s): %s",
446 ofperr_to_string(error), s);
453 return (state == S_CLEAR_FLOWS || state == S_UPDATE_FLOWS
454 ? mff_ovn_geneve : 0);
460 rconn_run_wait(swconn);
461 rconn_recv_wait(swconn);
467 rconn_destroy(swconn);
468 ovn_flow_table_destroy();
469 rconn_packet_counter_destroy(tx_counter);
473 queue_msg(struct ofpbuf *msg)
475 const struct ofp_header *oh = msg->data;
476 ovs_be32 xid = oh->xid;
477 rconn_send(swconn, msg, tx_counter);
482 log_openflow_rl(struct vlog_rate_limit *rl, enum vlog_level level,
483 const struct ofp_header *oh, const char *title)
485 if (!vlog_should_drop(&this_module, level, rl)) {
486 char *s = ofp_to_string(oh, ntohs(oh->length), 2);
487 vlog(&this_module, level, "%s: %s", title, s);
493 ofctrl_recv(const struct ofp_header *oh, enum ofptype type)
495 if (type == OFPTYPE_ECHO_REQUEST) {
496 queue_msg(make_echo_reply(oh));
497 } else if (type == OFPTYPE_ERROR) {
498 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
499 log_openflow_rl(&rl, VLL_INFO, oh, "OpenFlow error");
500 } else if (type != OFPTYPE_ECHO_REPLY &&
501 type != OFPTYPE_BARRIER_REPLY &&
502 type != OFPTYPE_PACKET_IN &&
503 type != OFPTYPE_PORT_STATUS &&
504 type != OFPTYPE_FLOW_REMOVED) {
505 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
506 log_openflow_rl(&rl, VLL_DBG, oh, "OpenFlow packet ignored");
510 /* Flow table interfaces to the rest of ovn-controller. */
512 /* Adds a flow to the collection associated with 'uuid'. The flow has the
513 * specified 'match' and 'actions' to the OpenFlow table numbered 'table_id'
514 * with the given 'priority'. The caller retains ownership of 'match' and
517 * Any number of flows may be associated with a given UUID. The flows with a
518 * given UUID must have a unique (table_id, priority, match) tuple. A
519 * duplicate within a generally indicates a bug in the ovn-controller code that
520 * generated it, so this functions logs a warning.
522 * (table_id, priority, match) tuples should also be unique for flows with
523 * different UUIDs, but it doesn't necessarily indicate a bug in
524 * ovn-controller, for two reasons. First, these duplicates could be caused by
525 * logical flows generated by ovn-northd, which aren't ovn-controller's fault;
526 * perhaps something should warn about these but the root cause is different.
527 * Second, these duplicates might be transient, that is, they might go away
528 * before the next call to ofctrl_run() if a call to ofctrl_remove_flows()
529 * removes one or the other.
531 * This just assembles the desired flow tables in memory. Nothing is actually
532 * sent to the switch until a later call to ofctrl_run(). */
534 ofctrl_add_flow(uint8_t table_id, uint16_t priority,
535 const struct match *match, const struct ofpbuf *actions,
536 const struct uuid *uuid)
538 /* Structure that uses table_id+priority+various things as hashes. */
539 struct ovn_flow *f = xmalloc(sizeof *f);
540 f->table_id = table_id;
541 f->priority = priority;
543 f->ofpacts = xmemdup(actions->data, actions->size);
544 f->ofpacts_len = actions->size;
546 f->match_hmap_node.hash = ovn_flow_match_hash(f);
547 f->uuid_hindex_node.hash = uuid_hash(&f->uuid);
549 /* Check to see if other flows exist with the same key (table_id priority,
550 * match criteria) and uuid. If so, discard this flow and log a
552 struct ovs_list existing;
553 ovn_flow_lookup(&match_flow_table, f, &existing);
555 LIST_FOR_EACH (d, list_node, &existing) {
556 if (uuid_equals(&f->uuid, &d->uuid)) {
557 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
558 char *s = ovn_flow_to_string(f);
559 VLOG_WARN_RL(&rl, "found duplicate flow %s for parent "UUID_FMT,
560 s, UUID_ARGS(&f->uuid));
567 /* Otherwise, add the flow. */
568 hmap_insert(&match_flow_table, &f->match_hmap_node,
569 f->match_hmap_node.hash);
570 hindex_insert(&uuid_flow_table, &f->uuid_hindex_node,
571 f->uuid_hindex_node.hash);
574 /* Removes a bundles of flows from the flow table. */
576 ofctrl_remove_flows(const struct uuid *uuid)
578 struct ovn_flow *f, *next;
579 HINDEX_FOR_EACH_WITH_HASH_SAFE (f, next, uuid_hindex_node, uuid_hash(uuid),
581 if (uuid_equals(&f->uuid, uuid)) {
582 hmap_remove(&match_flow_table, &f->match_hmap_node);
583 hindex_remove(&uuid_flow_table, &f->uuid_hindex_node);
589 /* Shortcut to remove all flows matching the supplied UUID and add this
592 ofctrl_set_flow(uint8_t table_id, uint16_t priority,
593 const struct match *match, const struct ofpbuf *actions,
594 const struct uuid *uuid)
596 ofctrl_remove_flows(uuid);
597 ofctrl_add_flow(table_id, priority, match, actions, uuid);
602 /* Duplicate an ovn_flow structure. */
604 ofctrl_dup_flow(struct ovn_flow *src)
606 struct ovn_flow *dst = xmalloc(sizeof *dst);
607 dst->table_id = src->table_id;
608 dst->priority = src->priority;
609 dst->match = src->match;
610 dst->ofpacts = xmemdup(src->ofpacts, src->ofpacts_len);
611 dst->ofpacts_len = src->ofpacts_len;
612 dst->uuid = src->uuid;
613 dst->match_hmap_node.hash = ovn_flow_match_hash(dst);
614 dst->uuid_hindex_node.hash = uuid_hash(&src->uuid);
618 /* Returns a hash of the match key in 'f'. */
620 ovn_flow_match_hash(const struct ovn_flow *f)
622 return hash_2words((f->table_id << 16) | f->priority,
623 match_hash(&f->match, 0));
626 /* Compare two flows and return -1, 0, 1 based on whether a if less than,
627 * equal to or greater than b. */
629 ovn_flow_compare_flows(struct ovn_flow *a, struct ovn_flow *b)
631 return uuid_compare_3way(&a->uuid, &b->uuid);
634 /* Given a list of ovn_flows, goes through the list and returns
635 * a single flow, in a deterministic way. */
636 static struct ovn_flow *
637 ovn_flow_select_from_list(struct ovs_list *flows)
639 struct ovn_flow *candidate;
640 struct ovn_flow *answer = NULL;
641 LIST_FOR_EACH (candidate, list_node, flows) {
642 if (!answer || ovn_flow_compare_flows(candidate, answer) < 0) {
649 /* Initializes and files in the supplied list with ovn_flows from 'flow_table'
650 * whose key is identical to 'target''s key. */
652 ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target,
653 struct ovs_list *answer)
657 ovs_list_init(answer);
658 HMAP_FOR_EACH_WITH_HASH (f, match_hmap_node, target->match_hmap_node.hash,
660 if (f->table_id == target->table_id
661 && f->priority == target->priority
662 && match_equal(&f->match, &target->match)) {
663 ovs_list_push_back(answer, &f->list_node);
669 ovn_flow_to_string(const struct ovn_flow *f)
671 struct ds s = DS_EMPTY_INITIALIZER;
672 ds_put_format(&s, "table_id=%"PRIu8", ", f->table_id);
673 ds_put_format(&s, "priority=%"PRIu16", ", f->priority);
674 match_format(&f->match, &s, OFP_DEFAULT_PRIORITY);
675 ds_put_cstr(&s, ", actions=");
676 ofpacts_format(f->ofpacts, f->ofpacts_len, &s);
677 return ds_steal_cstr(&s);
681 ovn_flow_log(const struct ovn_flow *f, const char *action)
683 if (VLOG_IS_DBG_ENABLED()) {
684 char *s = ovn_flow_to_string(f);
685 VLOG_DBG("%s flow: %s", action, s);
691 ovn_flow_destroy(struct ovn_flow *f)
699 /* Flow tables of struct ovn_flow. */
702 ovn_flow_table_clear(void)
704 struct ovn_flow *f, *next;
705 HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, &match_flow_table) {
706 hmap_remove(&match_flow_table, &f->match_hmap_node);
707 hindex_remove(&uuid_flow_table, &f->uuid_hindex_node);
713 ovn_flow_table_destroy(void)
715 ovn_flow_table_clear();
716 hmap_destroy(&match_flow_table);
717 hindex_destroy(&uuid_flow_table);
720 /* Flow table update. */
723 queue_flow_mod(struct ofputil_flow_mod *fm)
725 fm->buffer_id = UINT32_MAX;
726 fm->out_port = OFPP_ANY;
727 fm->out_group = OFPG_ANY;
728 queue_msg(ofputil_encode_flow_mod(fm, OFPUTIL_P_OF13_OXM));
734 /* Finds and returns a group_info in 'existing_groups' whose key is identical
735 * to 'target''s key, or NULL if there is none. */
736 static struct group_info *
737 ovn_group_lookup(struct hmap *exisiting_groups,
738 const struct group_info *target)
740 struct group_info *e;
742 HMAP_FOR_EACH_WITH_HASH(e, hmap_node, target->hmap_node.hash,
744 if (e->group_id == target->group_id) {
751 /* Clear either desired_groups or existing_groups in group_table. */
753 ovn_group_table_clear(struct group_table *group_table, bool existing)
755 struct group_info *g, *next;
756 struct hmap *target_group = existing
757 ? &group_table->existing_groups
758 : &group_table->desired_groups;
760 HMAP_FOR_EACH_SAFE (g, next, hmap_node, target_group) {
761 hmap_remove(target_group, &g->hmap_node);
762 bitmap_set0(group_table->group_ids, g->group_id);
763 ds_destroy(&g->group);
769 queue_group_mod(struct ofputil_group_mod *gm)
771 queue_msg(ofputil_encode_group_mod(OFP13_VERSION, gm));
775 /* Replaces the flow table on the switch, if possible, by the flows in added
776 * with ofctrl_add_flow().
778 * Replaces the group table on the switch, if possible, by the groups in
779 * 'group_table->desired_groups'. Regardless of whether the group table
780 * is updated, this deletes all the groups from the
781 * 'group_table->desired_groups' and frees them. (The hmap itself isn't
784 * This should be called after ofctrl_run() within the main loop. */
786 ofctrl_put(struct group_table *group_table)
789 groups = group_table;
792 /* The flow table can be updated if the connection to the switch is up and
793 * in the correct state and not backlogged with existing flow_mods. (Our
794 * criteria for being backlogged appear very conservative, but the socket
795 * between ovn-controller and OVS provides some buffering.) */
796 if (state != S_UPDATE_FLOWS
797 || rconn_packet_counter_n_packets(tx_counter)) {
798 ovn_group_table_clear(group_table, false);
802 /* Iterate through all the desired groups. If there are new ones,
803 * add them to the switch. */
804 struct group_info *desired;
805 HMAP_FOR_EACH(desired, hmap_node, &group_table->desired_groups) {
806 if (!ovn_group_lookup(&group_table->existing_groups, desired)) {
807 /* Create and install new group. */
808 struct ofputil_group_mod gm;
809 enum ofputil_protocol usable_protocols;
811 struct ds group_string = DS_EMPTY_INITIALIZER;
812 ds_put_format(&group_string, "group_id=%u,%s",
813 desired->group_id, ds_cstr(&desired->group));
815 error = parse_ofp_group_mod_str(&gm, OFPGC11_ADD,
816 ds_cstr(&group_string),
819 queue_group_mod(&gm);
821 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
822 VLOG_ERR_RL(&rl, "new group %s %s", error,
823 ds_cstr(&group_string));
826 ds_destroy(&group_string);
827 ofputil_bucket_list_destroy(&gm.buckets);
831 /* Iterate through all of the installed flows. If any of them are no
832 * longer desired, delete them; if any of them should have different
833 * actions, update them. */
834 struct ovn_flow *i, *next;
835 HMAP_FOR_EACH_SAFE (i, next, match_hmap_node, &installed_flows) {
836 struct ovs_list matches;
837 ovn_flow_lookup(&match_flow_table, i, &matches);
838 if (ovs_list_is_empty(&matches)) {
839 /* Installed flow is no longer desirable. Delete it from the
840 * switch and from installed_flows. */
841 struct ofputil_flow_mod fm = {
843 .priority = i->priority,
844 .table_id = i->table_id,
845 .command = OFPFC_DELETE_STRICT,
848 ovn_flow_log(i, "removing installed");
850 hmap_remove(&installed_flows, &i->match_hmap_node);
853 /* Since we still have desired flows that match this key,
854 * select one and compare both its actions and uuid.
855 * If the actions aren't the same, queue and update
856 * action for the install flow. If the uuid has changed
857 * update that as well. */
858 struct ovn_flow *d = ovn_flow_select_from_list(&matches);
859 if (!uuid_equals(&i->uuid, &d->uuid)) {
860 /* Update installed flow's UUID. */
863 if (!ofpacts_equal(i->ofpacts, i->ofpacts_len,
864 d->ofpacts, d->ofpacts_len)) {
865 /* Update actions in installed flow. */
866 struct ofputil_flow_mod fm = {
868 .priority = i->priority,
869 .table_id = i->table_id,
870 .ofpacts = d->ofpacts,
871 .ofpacts_len = d->ofpacts_len,
872 .command = OFPFC_MODIFY_STRICT,
875 ovn_flow_log(i, "updating installed");
877 /* Replace 'i''s actions by 'd''s. */
879 i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len);
880 i->ofpacts_len = d->ofpacts_len;
885 /* Iterate through the desired flows and add those that aren't found
886 * in the installed flow table. */
888 HMAP_FOR_EACH (c, match_hmap_node, &match_flow_table) {
889 struct ovs_list matches;
890 ovn_flow_lookup(&installed_flows, c, &matches);
891 if (ovs_list_is_empty(&matches)) {
892 /* We have a key that isn't in the installed flows, so
893 * look back into the desired flow list for all flows
894 * that match this key, and select the one to be installed. */
895 struct ovs_list candidates;
896 ovn_flow_lookup(&match_flow_table, c, &candidates);
897 struct ovn_flow *d = ovn_flow_select_from_list(&candidates);
898 /* Send flow_mod to add flow. */
899 struct ofputil_flow_mod fm = {
901 .priority = d->priority,
902 .table_id = d->table_id,
903 .ofpacts = d->ofpacts,
904 .ofpacts_len = d->ofpacts_len,
905 .command = OFPFC_ADD,
908 ovn_flow_log(d, "adding installed");
910 /* Copy 'd' from 'flow_table' to installed_flows. */
911 struct ovn_flow *new_node = ofctrl_dup_flow(d);
912 hmap_insert(&installed_flows, &new_node->match_hmap_node,
913 new_node->match_hmap_node.hash);
917 /* Iterate through the installed groups from previous runs. If they
918 * are not needed delete them. */
919 struct group_info *installed, *next_group;
920 HMAP_FOR_EACH_SAFE(installed, next_group, hmap_node,
921 &group_table->existing_groups) {
922 if (!ovn_group_lookup(&group_table->desired_groups, installed)) {
923 /* Delete the group. */
924 struct ofputil_group_mod gm;
925 enum ofputil_protocol usable_protocols;
927 struct ds group_string = DS_EMPTY_INITIALIZER;
928 ds_put_format(&group_string, "group_id=%u", installed->group_id);
930 error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE,
931 ds_cstr(&group_string),
934 queue_group_mod(&gm);
936 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
937 VLOG_ERR_RL(&rl, "Error deleting group %d: %s",
938 installed->group_id, error);
941 ds_destroy(&group_string);
942 ofputil_bucket_list_destroy(&gm.buckets);
944 /* Remove 'installed' from 'group_table->existing_groups' */
945 hmap_remove(&group_table->existing_groups, &installed->hmap_node);
946 ds_destroy(&installed->group);
948 /* Dealloc group_id. */
949 bitmap_set0(group_table->group_ids, installed->group_id);
954 /* Move the contents of desired_groups to existing_groups. */
955 HMAP_FOR_EACH_SAFE(desired, next_group, hmap_node,
956 &group_table->desired_groups) {
957 hmap_remove(&group_table->desired_groups, &desired->hmap_node);
958 if (!ovn_group_lookup(&group_table->existing_groups, desired)) {
959 hmap_insert(&group_table->existing_groups, &desired->hmap_node,
960 desired->hmap_node.hash);
962 ds_destroy(&desired->group);