ofproto: Factor out ofproto_rule_insert__().
[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, 2015 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 static struct ofp_bundle *
46 ofp_bundle_create(uint32_t id, uint16_t flags)
47 {
48     struct ofp_bundle *bundle;
49
50     bundle = xmalloc(sizeof(*bundle));
51
52     bundle->id = id;
53     bundle->flags = flags;
54     bundle->state = BS_OPEN;
55
56     list_init(&bundle->msg_list);
57
58     return bundle;
59 }
60
61 void
62 ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle)
63 {
64     struct ofp_bundle_entry *msg;
65
66     LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
67         ofp_bundle_entry_free(msg);
68     }
69
70     ofconn_remove_bundle(ofconn, bundle);
71     free(bundle);
72 }
73
74 enum ofperr
75 ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
76 {
77     struct ofp_bundle *bundle;
78     enum ofperr error;
79
80     bundle = ofconn_get_bundle(ofconn, id);
81
82     if (bundle) {
83         VLOG_INFO("Bundle %x already exists.", id);
84         ofp_bundle_remove__(ofconn, bundle);
85
86         return OFPERR_OFPBFC_BAD_ID;
87     }
88
89     bundle = ofp_bundle_create(id, flags);
90     error = ofconn_insert_bundle(ofconn, bundle);
91     if (error) {
92         free(bundle);
93     }
94
95     return error;
96 }
97
98 enum ofperr
99 ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
100 {
101     struct ofp_bundle *bundle;
102
103     bundle = ofconn_get_bundle(ofconn, id);
104
105     if (!bundle) {
106         return OFPERR_OFPBFC_BAD_ID;
107     }
108
109     if (bundle->state == BS_CLOSED) {
110         ofp_bundle_remove__(ofconn, bundle);
111         return OFPERR_OFPBFC_BUNDLE_CLOSED;
112     }
113
114     if (bundle->flags != flags) {
115         ofp_bundle_remove__(ofconn, bundle);
116         return OFPERR_OFPBFC_BAD_FLAGS;
117     }
118
119     bundle->state = BS_CLOSED;
120     return 0;
121 }
122
123 enum ofperr
124 ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
125 {
126     struct ofp_bundle *bundle;
127     enum ofperr error = 0;
128     struct ofp_bundle_entry *msg;
129
130     bundle = ofconn_get_bundle(ofconn, id);
131
132     if (!bundle) {
133         return OFPERR_OFPBFC_BAD_ID;
134     }
135     if (bundle->flags != flags) {
136         error = OFPERR_OFPBFC_BAD_FLAGS;
137     } else {
138         LIST_FOR_EACH (msg, node, &bundle->msg_list) {
139             /* XXX: actual commit */
140             error = OFPERR_OFPBFC_MSG_FAILED;
141         }
142     }
143
144     ofp_bundle_remove__(ofconn, bundle);
145     return error;
146 }
147
148 enum ofperr
149 ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
150 {
151     struct ofp_bundle *bundle;
152
153     bundle = ofconn_get_bundle(ofconn, id);
154
155     if (!bundle) {
156         return OFPERR_OFPBFC_BAD_ID;
157     }
158
159     ofp_bundle_remove__(ofconn, bundle);
160
161     return 0;
162 }
163
164 enum ofperr
165 ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
166                        struct ofp_bundle_entry *bmsg)
167 {
168     struct ofp_bundle *bundle;
169
170     bundle = ofconn_get_bundle(ofconn, id);
171
172     if (!bundle) {
173         enum ofperr error;
174
175         bundle = ofp_bundle_create(id, flags);
176         error = ofconn_insert_bundle(ofconn, bundle);
177         if (error) {
178             free(bundle);
179             return error;
180         }
181     } else if (bundle->state == BS_CLOSED) {
182         ofp_bundle_remove__(ofconn, bundle);
183         return OFPERR_OFPBFC_BUNDLE_CLOSED;
184     } else if (flags != bundle->flags) {
185         ofp_bundle_remove__(ofconn, bundle);
186         return OFPERR_OFPBFC_BAD_FLAGS;
187     }
188
189     list_push_back(&bundle->msg_list, &bmsg->node);
190     return 0;
191 }