]> git.proxmox.com Git - ovs.git/blame - ofproto/bundles.c
ovsdb-monitor: add ovsdb_monitor_changes
[ovs.git] / ofproto / bundles.c
CommitLineData
777af88d
AC
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>
7b334c5c 4 * Copyright (c) 2014 Nicira, Inc.
777af88d
AC
5 *
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:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
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.
17 */
18
19#include <config.h>
20
21#include "coverage.h"
22#include "fail-open.h"
23#include "in-band.h"
24#include "odp-util.h"
25#include "ofp-actions.h"
26#include "ofp-msgs.h"
27#include "ofp-util.h"
28#include "ofpbuf.h"
29#include "ofproto-provider.h"
30#include "pinsched.h"
31#include "poll-loop.h"
32#include "pktbuf.h"
33#include "rconn.h"
34#include "shash.h"
35#include "simap.h"
36#include "stream.h"
37#include "timeval.h"
4a1f523f 38#include "openvswitch/vconn.h"
e6211adc 39#include "openvswitch/vlog.h"
777af88d
AC
40
41#include "bundles.h"
42
43VLOG_DEFINE_THIS_MODULE(bundles);
44
45enum bundle_state {
46 BS_OPEN,
47 BS_CLOSED
48};
49
50struct ofp_bundle {
51 struct hmap_node node; /* In struct ofconn's "bundles" hmap. */
52 uint32_t id;
53 uint16_t flags;
54 enum bundle_state state;
55
56 /* List of 'struct bundle_message's */
ca6ba700 57 struct ovs_list msg_list;
777af88d
AC
58};
59
60struct bundle_message {
61 struct ofp_header *msg;
ca6ba700 62 struct ovs_list node; /* Element in 'struct ofp_bundles's msg_list */
777af88d
AC
63};
64
65static uint32_t
66bundle_hash(uint32_t id)
67{
68 return hash_int(id, 0);
69}
70
71static struct ofp_bundle *
72ofp_bundle_find(struct hmap *bundles, uint32_t id)
73{
74 struct ofp_bundle *bundle;
75
76 HMAP_FOR_EACH_IN_BUCKET(bundle, node, bundle_hash(id), bundles) {
77 if (bundle->id == id) {
78 return bundle;
79 }
80 }
81
82 return NULL;
83}
84
85static struct ofp_bundle *
86ofp_bundle_create(uint32_t id, uint16_t flags)
87{
88 struct ofp_bundle *bundle;
89
90 bundle = xmalloc(sizeof(*bundle));
91
92 bundle->id = id;
93 bundle->flags = flags;
94
95 list_init(&bundle->msg_list);
96
97 return bundle;
98}
99
100static void
101ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *item)
102{
5f03c983 103 struct bundle_message *msg;
777af88d
AC
104 struct hmap *bundles;
105
5f03c983 106 LIST_FOR_EACH_POP (msg, node, &item->msg_list) {
777af88d
AC
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
117void
118ofp_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
130enum ofperr
131ofp_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
645b8934 146 /* XXX: Check the limit of open bundles */
777af88d
AC
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
157enum ofperr
158ofp_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
184enum ofperr
185ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
186{
187 struct hmap *bundles;
188 struct ofp_bundle *bundle;
d56318cf
JR
189 enum ofperr error = 0;
190 struct bundle_message *msg;
777af88d
AC
191
192 bundles = ofconn_get_bundles(ofconn);
193 bundle = ofp_bundle_find(bundles, id);
194
195 if (!bundle) {
196 return OFPERR_OFPBFC_BAD_ID;
197 }
198 if (bundle->flags != flags) {
d56318cf
JR
199 error = OFPERR_OFPBFC_BAD_FLAGS;
200 } else {
201 LIST_FOR_EACH (msg, node, &bundle->msg_list) {
202 /* XXX: actual commit */
203 error = OFPERR_OFPBFC_MSG_FAILED;
204 }
777af88d
AC
205 }
206
d56318cf
JR
207 ofp_bundle_remove(ofconn, bundle);
208 return error;
777af88d
AC
209}
210
211enum ofperr
212ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
213{
214 struct hmap *bundles;
215 struct ofp_bundle *bundle;
216
217 bundles = ofconn_get_bundles(ofconn);
218 bundle = ofp_bundle_find(bundles, id);
219
220 if (!bundle) {
221 return OFPERR_OFPBFC_BAD_ID;
222 }
223
224 ofp_bundle_remove(ofconn, bundle);
225
226 return 0;
227}
228
229enum ofperr
230ofp_bundle_add_message(struct ofconn *ofconn, struct ofputil_bundle_add_msg *badd)
231{
232 struct hmap *bundles;
233 struct ofp_bundle *bundle;
234 struct bundle_message *bmsg;
235
236 bundles = ofconn_get_bundles(ofconn);
237 bundle = ofp_bundle_find(bundles, badd->bundle_id);
238
239 if (!bundle) {
240 bundle = ofp_bundle_create(badd->bundle_id, badd->flags);
241 bundle->state = BS_OPEN;
242
243 bundles = ofconn_get_bundles(ofconn);
244 hmap_insert(bundles, &bundle->node, bundle_hash(badd->bundle_id));
7b334c5c 245 } else if (bundle->state == BS_CLOSED) {
777af88d
AC
246 ofp_bundle_remove(ofconn, bundle);
247 return OFPERR_OFPBFC_BUNDLE_CLOSED;
7b334c5c
JR
248 } else if (badd->flags != bundle->flags) {
249 ofp_bundle_remove(ofconn, bundle);
250 return OFPERR_OFPBFC_BAD_FLAGS;
777af88d
AC
251 }
252
253 bmsg = xmalloc(sizeof *bmsg);
254 bmsg->msg = xmemdup(badd->msg, ntohs(badd->msg->length));
255 list_push_back(&bundle->msg_list, &bmsg->node);
256 return 0;
257}