2 * Copyright (c) 2013, 2014 Alexandru Copot <alex.mihai.c@gmail.com>, with support from IXIA.
3 * Copyright (c) 2013, 2014 Daniel Baluta <dbaluta@ixiacom.com>
4 * Copyright (c) 2014 Nicira, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include "fail-open.h"
25 #include "ofp-actions.h"
29 #include "ofproto-provider.h"
31 #include "poll-loop.h"
38 #include "openvswitch/vconn.h"
39 #include "openvswitch/vlog.h"
43 VLOG_DEFINE_THIS_MODULE(bundles);
51 struct hmap_node node; /* In struct ofconn's "bundles" hmap. */
54 enum bundle_state state;
56 /* List of 'struct bundle_message's */
57 struct ovs_list msg_list;
60 struct bundle_message {
61 struct ofp_header *msg;
62 struct ovs_list node; /* Element in 'struct ofp_bundles's msg_list */
66 bundle_hash(uint32_t id)
68 return hash_int(id, 0);
71 static struct ofp_bundle *
72 ofp_bundle_find(struct hmap *bundles, uint32_t id)
74 struct ofp_bundle *bundle;
76 HMAP_FOR_EACH_IN_BUCKET(bundle, node, bundle_hash(id), bundles) {
77 if (bundle->id == id) {
85 static struct ofp_bundle *
86 ofp_bundle_create(uint32_t id, uint16_t flags)
88 struct ofp_bundle *bundle;
90 bundle = xmalloc(sizeof(*bundle));
93 bundle->flags = flags;
95 list_init(&bundle->msg_list);
101 ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *item)
103 struct bundle_message *msg, *next;
104 struct hmap *bundles;
106 LIST_FOR_EACH_SAFE (msg, next, node, &item->msg_list) {
107 list_remove(&msg->node);
112 bundles = ofconn_get_bundles(ofconn);
113 hmap_remove(bundles, &item->node);
119 ofp_bundle_remove_all(struct ofconn *ofconn)
121 struct ofp_bundle *b, *next;
122 struct hmap *bundles;
124 bundles = ofconn_get_bundles(ofconn);
126 HMAP_FOR_EACH_SAFE (b, next, node, bundles) {
127 ofp_bundle_remove(ofconn, b);
132 ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
134 struct hmap *bundles;
135 struct ofp_bundle *bundle;
137 bundles = ofconn_get_bundles(ofconn);
138 bundle = ofp_bundle_find(bundles, id);
141 VLOG_INFO("Bundle %x already exists.", id);
142 ofp_bundle_remove(ofconn, bundle);
144 return OFPERR_OFPBFC_BAD_ID;
147 /* XXX: Check the limit of open bundles */
149 bundle = ofp_bundle_create(id, flags);
150 bundle->state = BS_OPEN;
152 bundles = ofconn_get_bundles(ofconn);
153 hmap_insert(bundles, &bundle->node, bundle_hash(id));
159 ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
161 struct hmap *bundles;
162 struct ofp_bundle *bundle;
164 bundles = ofconn_get_bundles(ofconn);
165 bundle = ofp_bundle_find(bundles, id);
168 return OFPERR_OFPBFC_BAD_ID;
171 if (bundle->state == BS_CLOSED) {
172 ofp_bundle_remove(ofconn, bundle);
173 return OFPERR_OFPBFC_BUNDLE_CLOSED;
176 if (bundle->flags != flags) {
177 ofp_bundle_remove(ofconn, bundle);
178 return OFPERR_OFPBFC_BAD_FLAGS;
181 bundle->state = BS_CLOSED;
186 ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
188 struct hmap *bundles;
189 struct ofp_bundle *bundle;
190 enum ofperr error = 0;
191 struct bundle_message *msg;
193 bundles = ofconn_get_bundles(ofconn);
194 bundle = ofp_bundle_find(bundles, id);
197 return OFPERR_OFPBFC_BAD_ID;
199 if (bundle->flags != flags) {
200 error = OFPERR_OFPBFC_BAD_FLAGS;
202 LIST_FOR_EACH (msg, node, &bundle->msg_list) {
203 /* XXX: actual commit */
204 error = OFPERR_OFPBFC_MSG_FAILED;
208 ofp_bundle_remove(ofconn, bundle);
213 ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
215 struct hmap *bundles;
216 struct ofp_bundle *bundle;
218 bundles = ofconn_get_bundles(ofconn);
219 bundle = ofp_bundle_find(bundles, id);
222 return OFPERR_OFPBFC_BAD_ID;
225 ofp_bundle_remove(ofconn, bundle);
231 ofp_bundle_add_message(struct ofconn *ofconn, struct ofputil_bundle_add_msg *badd)
233 struct hmap *bundles;
234 struct ofp_bundle *bundle;
235 struct bundle_message *bmsg;
237 bundles = ofconn_get_bundles(ofconn);
238 bundle = ofp_bundle_find(bundles, badd->bundle_id);
241 bundle = ofp_bundle_create(badd->bundle_id, badd->flags);
242 bundle->state = BS_OPEN;
244 bundles = ofconn_get_bundles(ofconn);
245 hmap_insert(bundles, &bundle->node, bundle_hash(badd->bundle_id));
246 } else if (bundle->state == BS_CLOSED) {
247 ofp_bundle_remove(ofconn, bundle);
248 return OFPERR_OFPBFC_BUNDLE_CLOSED;
249 } else if (badd->flags != bundle->flags) {
250 ofp_bundle_remove(ofconn, bundle);
251 return OFPERR_OFPBFC_BAD_FLAGS;
254 bmsg = xmalloc(sizeof *bmsg);
255 bmsg->msg = xmemdup(badd->msg, ntohs(badd->msg->length));
256 list_push_back(&bundle->msg_list, &bmsg->node);