]> git.proxmox.com Git - ovs.git/blob - ofproto/bundles.c
lib/stp: Some debugging support.
[ovs.git] / ofproto / bundles.c
1 /*
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 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <config.h>
19
20 #include "coverage.h"
21 #include "fail-open.h"
22 #include "in-band.h"
23 #include "odp-util.h"
24 #include "ofp-actions.h"
25 #include "ofp-msgs.h"
26 #include "ofp-util.h"
27 #include "ofpbuf.h"
28 #include "ofproto-provider.h"
29 #include "pinsched.h"
30 #include "poll-loop.h"
31 #include "pktbuf.h"
32 #include "rconn.h"
33 #include "shash.h"
34 #include "simap.h"
35 #include "stream.h"
36 #include "timeval.h"
37 #include "vconn.h"
38 #include "vlog.h"
39
40 #include "bundles.h"
41
42 VLOG_DEFINE_THIS_MODULE(bundles);
43
44 enum bundle_state {
45 BS_OPEN,
46 BS_CLOSED
47 };
48
49 struct ofp_bundle {
50 struct hmap_node node; /* In struct ofconn's "bundles" hmap. */
51 uint32_t id;
52 uint16_t flags;
53 enum bundle_state state;
54
55 /* List of 'struct bundle_message's */
56 struct list msg_list;
57 };
58
59 struct bundle_message {
60 struct ofp_header *msg;
61 struct list node; /* Element in 'struct ofp_bundles's msg_list */
62 };
63
64 static uint32_t
65 bundle_hash(uint32_t id)
66 {
67 return hash_int(id, 0);
68 }
69
70 static struct ofp_bundle *
71 ofp_bundle_find(struct hmap *bundles, uint32_t id)
72 {
73 struct ofp_bundle *bundle;
74
75 HMAP_FOR_EACH_IN_BUCKET(bundle, node, bundle_hash(id), bundles) {
76 if (bundle->id == id) {
77 return bundle;
78 }
79 }
80
81 return NULL;
82 }
83
84 static struct ofp_bundle *
85 ofp_bundle_create(uint32_t id, uint16_t flags)
86 {
87 struct ofp_bundle *bundle;
88
89 bundle = xmalloc(sizeof(*bundle));
90
91 bundle->id = id;
92 bundle->flags = flags;
93
94 list_init(&bundle->msg_list);
95
96 return bundle;
97 }
98
99 static void
100 ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *item)
101 {
102 struct bundle_message *msg, *next;
103 struct hmap *bundles;
104
105 LIST_FOR_EACH_SAFE (msg, next, node, &item->msg_list) {
106 list_remove(&msg->node);
107 free(msg->msg);
108 free(msg);
109 }
110
111 bundles = ofconn_get_bundles(ofconn);
112 hmap_remove(bundles, &item->node);
113
114 free(item);
115 }
116
117 void
118 ofp_bundle_remove_all(struct ofconn *ofconn)
119 {
120 struct ofp_bundle *b, *next;
121 struct hmap *bundles;
122
123 bundles = ofconn_get_bundles(ofconn);
124
125 HMAP_FOR_EACH_SAFE (b, next, node, bundles) {
126 ofp_bundle_remove(ofconn, b);
127 }
128 }
129
130 enum ofperr
131 ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
132 {
133 struct hmap *bundles;
134 struct ofp_bundle *bundle;
135
136 bundles = ofconn_get_bundles(ofconn);
137 bundle = ofp_bundle_find(bundles, id);
138
139 if (bundle) {
140 VLOG_INFO("Bundle %x already exists.", id);
141 ofp_bundle_remove(ofconn, bundle);
142
143 return OFPERR_OFPBFC_BAD_ID;
144 }
145
146 /* XXX: Check the limit of open bundles */
147
148 bundle = ofp_bundle_create(id, flags);
149 bundle->state = BS_OPEN;
150
151 bundles = ofconn_get_bundles(ofconn);
152 hmap_insert(bundles, &bundle->node, bundle_hash(id));
153
154 return 0;
155 }
156
157 enum ofperr
158 ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
159 {
160 struct hmap *bundles;
161 struct ofp_bundle *bundle;
162
163 bundles = ofconn_get_bundles(ofconn);
164 bundle = ofp_bundle_find(bundles, id);
165
166 if (!bundle) {
167 return OFPERR_OFPBFC_BAD_ID;
168 }
169
170 if (bundle->state == BS_CLOSED) {
171 ofp_bundle_remove(ofconn, bundle);
172 return OFPERR_OFPBFC_BUNDLE_CLOSED;
173 }
174
175 if (bundle->flags != flags) {
176 ofp_bundle_remove(ofconn, bundle);
177 return OFPERR_OFPBFC_BAD_FLAGS;
178 }
179
180 bundle->state = BS_CLOSED;
181 return 0;
182 }
183
184 enum ofperr
185 ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
186 {
187 struct hmap *bundles;
188 struct ofp_bundle *bundle;
189
190 bundles = ofconn_get_bundles(ofconn);
191 bundle = ofp_bundle_find(bundles, id);
192
193 if (!bundle) {
194 return OFPERR_OFPBFC_BAD_ID;
195 }
196 if (bundle->flags != flags) {
197 ofp_bundle_remove(ofconn, bundle);
198 return OFPERR_OFPBFC_BAD_FLAGS;
199 }
200
201 /* XXX: actual commit */
202
203 return OFPERR_OFPBFC_MSG_UNSUP;
204 }
205
206 enum ofperr
207 ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
208 {
209 struct hmap *bundles;
210 struct ofp_bundle *bundle;
211
212 bundles = ofconn_get_bundles(ofconn);
213 bundle = ofp_bundle_find(bundles, id);
214
215 if (!bundle) {
216 return OFPERR_OFPBFC_BAD_ID;
217 }
218
219 ofp_bundle_remove(ofconn, bundle);
220
221 return 0;
222 }
223
224 enum ofperr
225 ofp_bundle_add_message(struct ofconn *ofconn, struct ofputil_bundle_add_msg *badd)
226 {
227 struct hmap *bundles;
228 struct ofp_bundle *bundle;
229 struct bundle_message *bmsg;
230
231 bundles = ofconn_get_bundles(ofconn);
232 bundle = ofp_bundle_find(bundles, badd->bundle_id);
233
234 if (!bundle) {
235 bundle = ofp_bundle_create(badd->bundle_id, badd->flags);
236 bundle->state = BS_OPEN;
237
238 bundles = ofconn_get_bundles(ofconn);
239 hmap_insert(bundles, &bundle->node, bundle_hash(badd->bundle_id));
240 }
241
242 if (bundle->state == BS_CLOSED) {
243 ofp_bundle_remove(ofconn, bundle);
244 return OFPERR_OFPBFC_BUNDLE_CLOSED;
245 }
246
247 bmsg = xmalloc(sizeof *bmsg);
248 bmsg->msg = xmemdup(badd->msg, ntohs(badd->msg->length));
249 list_push_back(&bundle->msg_list, &bmsg->node);
250 return 0;
251 }