pkg-config: Fix Cflags in package-config files
[cascardo/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  * Copyright (c) 2014 Nicira, Inc.
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"
38 #include "openvswitch/vconn.h"
39 #include "openvswitch/vlog.h"
40
41 #include "bundles.h"
42
43 VLOG_DEFINE_THIS_MODULE(bundles);
44
45 enum bundle_state {
46     BS_OPEN,
47     BS_CLOSED
48 };
49
50 struct 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 */
57     struct ovs_list    msg_list;
58 };
59
60 struct bundle_message {
61     struct ofp_header *msg;
62     struct ovs_list   node;  /* Element in 'struct ofp_bundles's msg_list */
63 };
64
65 static uint32_t
66 bundle_hash(uint32_t id)
67 {
68     return hash_int(id, 0);
69 }
70
71 static struct ofp_bundle *
72 ofp_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
85 static struct ofp_bundle *
86 ofp_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
100 static void
101 ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *item)
102 {
103     struct bundle_message *msg, *next;
104     struct hmap *bundles;
105
106     LIST_FOR_EACH_SAFE (msg, next, node, &item->msg_list) {
107         list_remove(&msg->node);
108         free(msg->msg);
109         free(msg);
110     }
111
112     bundles = ofconn_get_bundles(ofconn);
113     hmap_remove(bundles, &item->node);
114
115     free(item);
116 }
117
118 void
119 ofp_bundle_remove_all(struct ofconn *ofconn)
120 {
121     struct ofp_bundle *b, *next;
122     struct hmap *bundles;
123
124     bundles = ofconn_get_bundles(ofconn);
125
126     HMAP_FOR_EACH_SAFE (b, next, node, bundles) {
127         ofp_bundle_remove(ofconn, b);
128     }
129 }
130
131 enum ofperr
132 ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
133 {
134     struct hmap *bundles;
135     struct ofp_bundle *bundle;
136
137     bundles = ofconn_get_bundles(ofconn);
138     bundle = ofp_bundle_find(bundles, id);
139
140     if (bundle) {
141         VLOG_INFO("Bundle %x already exists.", id);
142         ofp_bundle_remove(ofconn, bundle);
143
144         return OFPERR_OFPBFC_BAD_ID;
145     }
146
147     /* XXX: Check the limit of open bundles */
148
149     bundle = ofp_bundle_create(id, flags);
150     bundle->state = BS_OPEN;
151
152     bundles = ofconn_get_bundles(ofconn);
153     hmap_insert(bundles, &bundle->node, bundle_hash(id));
154
155     return 0;
156 }
157
158 enum ofperr
159 ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
160 {
161     struct hmap *bundles;
162     struct ofp_bundle *bundle;
163
164     bundles = ofconn_get_bundles(ofconn);
165     bundle = ofp_bundle_find(bundles, id);
166
167     if (!bundle) {
168         return OFPERR_OFPBFC_BAD_ID;
169     }
170
171     if (bundle->state == BS_CLOSED) {
172         ofp_bundle_remove(ofconn, bundle);
173         return OFPERR_OFPBFC_BUNDLE_CLOSED;
174     }
175
176     if (bundle->flags != flags) {
177         ofp_bundle_remove(ofconn, bundle);
178         return OFPERR_OFPBFC_BAD_FLAGS;
179     }
180
181     bundle->state = BS_CLOSED;
182     return 0;
183 }
184
185 enum ofperr
186 ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
187 {
188     struct hmap *bundles;
189     struct ofp_bundle *bundle;
190     enum ofperr error = 0;
191     struct bundle_message *msg;
192
193     bundles = ofconn_get_bundles(ofconn);
194     bundle = ofp_bundle_find(bundles, id);
195
196     if (!bundle) {
197         return OFPERR_OFPBFC_BAD_ID;
198     }
199     if (bundle->flags != flags) {
200         error = OFPERR_OFPBFC_BAD_FLAGS;
201     } else {
202         LIST_FOR_EACH (msg, node, &bundle->msg_list) {
203             /* XXX: actual commit */
204             error = OFPERR_OFPBFC_MSG_FAILED;
205         }
206     }
207
208     ofp_bundle_remove(ofconn, bundle);
209     return error;
210 }
211
212 enum ofperr
213 ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
214 {
215     struct hmap *bundles;
216     struct ofp_bundle *bundle;
217
218     bundles = ofconn_get_bundles(ofconn);
219     bundle = ofp_bundle_find(bundles, id);
220
221     if (!bundle) {
222         return OFPERR_OFPBFC_BAD_ID;
223     }
224
225     ofp_bundle_remove(ofconn, bundle);
226
227     return 0;
228 }
229
230 enum ofperr
231 ofp_bundle_add_message(struct ofconn *ofconn, struct ofputil_bundle_add_msg *badd)
232 {
233     struct hmap *bundles;
234     struct ofp_bundle *bundle;
235     struct bundle_message *bmsg;
236
237     bundles = ofconn_get_bundles(ofconn);
238     bundle = ofp_bundle_find(bundles, badd->bundle_id);
239
240     if (!bundle) {
241         bundle = ofp_bundle_create(badd->bundle_id, badd->flags);
242         bundle->state = BS_OPEN;
243
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;
252     }
253
254     bmsg = xmalloc(sizeof *bmsg);
255     bmsg->msg = xmemdup(badd->msg, ntohs(badd->msg->length));
256     list_push_back(&bundle->msg_list, &bmsg->node);
257     return 0;
258 }