Branch data Line data Source code
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 "bundles.h"
22 : : #include "coverage.h"
23 : : #include "fail-open.h"
24 : : #include "in-band.h"
25 : : #include "odp-util.h"
26 : : #include "ofproto-provider.h"
27 : : #include "openvswitch/ofp-actions.h"
28 : : #include "openvswitch/ofp-msgs.h"
29 : : #include "openvswitch/ofp-util.h"
30 : : #include "openvswitch/ofpbuf.h"
31 : : #include "openvswitch/vconn.h"
32 : : #include "openvswitch/vlog.h"
33 : : #include "pinsched.h"
34 : : #include "poll-loop.h"
35 : : #include "rconn.h"
36 : : #include "openvswitch/shash.h"
37 : : #include "simap.h"
38 : : #include "stream.h"
39 : : #include "timeval.h"
40 : :
41 : 1288 : VLOG_DEFINE_THIS_MODULE(bundles);
42 : :
43 : : static struct ofp_bundle *
44 : 127 : ofp_bundle_create(uint32_t id, uint16_t flags)
45 : : {
46 : : struct ofp_bundle *bundle;
47 : :
48 : 127 : bundle = xmalloc(sizeof(*bundle));
49 : :
50 : 127 : bundle->id = id;
51 : 127 : bundle->flags = flags;
52 : 127 : bundle->state = BS_OPEN;
53 : :
54 : 127 : ovs_list_init(&bundle->msg_list);
55 : :
56 : 127 : return bundle;
57 : : }
58 : :
59 : : void
60 : 127 : ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle,
61 : : bool success)
62 : : {
63 : : struct ofp_bundle_entry *msg;
64 : :
65 [ + + ]: 835 : LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
66 [ + + ][ + + ]: 708 : if (success && msg->type == OFPTYPE_FLOW_MOD) {
67 : : /* Tell connmgr about successful flow mods. */
68 : 644 : ofconn_report_flow_mod(ofconn, msg->ofm.command);
69 : : }
70 : 708 : ofp_bundle_entry_free(msg);
71 : : }
72 : :
73 : 127 : ofconn_remove_bundle(ofconn, bundle);
74 : 127 : free(bundle);
75 : 127 : }
76 : :
77 : : enum ofperr
78 : 129 : ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
79 : : {
80 : : struct ofp_bundle *bundle;
81 : : enum ofperr error;
82 : :
83 : 129 : bundle = ofconn_get_bundle(ofconn, id);
84 : :
85 [ + + ]: 129 : if (bundle) {
86 [ + - ]: 2 : VLOG_INFO("Bundle %x already exists.", id);
87 : 2 : ofp_bundle_remove__(ofconn, bundle, false);
88 : :
89 : 2 : return OFPERR_OFPBFC_BAD_ID;
90 : : }
91 : :
92 : 127 : bundle = ofp_bundle_create(id, flags);
93 : 127 : error = ofconn_insert_bundle(ofconn, bundle);
94 [ - + ]: 127 : if (error) {
95 : 0 : free(bundle);
96 : : }
97 : :
98 : 127 : return error;
99 : : }
100 : :
101 : : enum ofperr
102 : 8 : ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
103 : : {
104 : : struct ofp_bundle *bundle;
105 : :
106 : 8 : bundle = ofconn_get_bundle(ofconn, id);
107 : :
108 [ + + ]: 8 : if (!bundle) {
109 : 2 : return OFPERR_OFPBFC_BAD_ID;
110 : : }
111 : :
112 [ + + ]: 6 : if (bundle->state == BS_CLOSED) {
113 : 2 : ofp_bundle_remove__(ofconn, bundle, false);
114 : 2 : return OFPERR_OFPBFC_BUNDLE_CLOSED;
115 : : }
116 : :
117 [ + + ]: 4 : if (bundle->flags != flags) {
118 : 2 : ofp_bundle_remove__(ofconn, bundle, false);
119 : 2 : return OFPERR_OFPBFC_BAD_FLAGS;
120 : : }
121 : :
122 : 2 : bundle->state = BS_CLOSED;
123 : 2 : return 0;
124 : : }
125 : :
126 : : enum ofperr
127 : 5 : ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
128 : : {
129 : : struct ofp_bundle *bundle;
130 : :
131 : 5 : bundle = ofconn_get_bundle(ofconn, id);
132 : :
133 [ + + ]: 5 : if (!bundle) {
134 : 2 : return OFPERR_OFPBFC_BAD_ID;
135 : : }
136 : :
137 : 3 : ofp_bundle_remove__(ofconn, bundle, false);
138 : :
139 : 3 : return 0;
140 : : }
141 : :
142 : : enum ofperr
143 : 708 : ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
144 : : struct ofp_bundle_entry *bmsg)
145 : : {
146 : : struct ofp_bundle *bundle;
147 : :
148 : 708 : bundle = ofconn_get_bundle(ofconn, id);
149 : :
150 [ - + ]: 708 : if (!bundle) {
151 : : enum ofperr error;
152 : :
153 : 0 : bundle = ofp_bundle_create(id, flags);
154 : 0 : error = ofconn_insert_bundle(ofconn, bundle);
155 [ # # ]: 0 : if (error) {
156 : 0 : free(bundle);
157 : 0 : return error;
158 : : }
159 [ - + ]: 708 : } else if (bundle->state == BS_CLOSED) {
160 : 0 : ofp_bundle_remove__(ofconn, bundle, false);
161 : 0 : return OFPERR_OFPBFC_BUNDLE_CLOSED;
162 [ - + ]: 708 : } else if (flags != bundle->flags) {
163 : 0 : ofp_bundle_remove__(ofconn, bundle, false);
164 : 0 : return OFPERR_OFPBFC_BAD_FLAGS;
165 : : }
166 : :
167 : 708 : ovs_list_push_back(&bundle->msg_list, &bmsg->node);
168 : 708 : return 0;
169 : : }
|