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