]>
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 | ||
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 | ||
43 | VLOG_DEFINE_THIS_MODULE(bundles); | |
44 | ||
777af88d AC |
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; | |
ff09bc08 | 54 | bundle->state = BS_OPEN; |
777af88d AC |
55 | |
56 | list_init(&bundle->msg_list); | |
57 | ||
58 | return bundle; | |
59 | } | |
60 | ||
ff09bc08 | 61 | void |
1f42be1c JR |
62 | ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle, |
63 | bool success) | |
777af88d | 64 | { |
7ac27a04 | 65 | struct ofp_bundle_entry *msg; |
777af88d | 66 | |
7ac27a04 | 67 | LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) { |
1f42be1c JR |
68 | if (success && msg->type == OFPTYPE_FLOW_MOD) { |
69 | /* Tell connmgr about successful flow mods. */ | |
8be00367 | 70 | ofconn_report_flow_mod(ofconn, msg->ofm.fm.command); |
1f42be1c | 71 | } |
7ac27a04 | 72 | ofp_bundle_entry_free(msg); |
777af88d AC |
73 | } |
74 | ||
ff09bc08 | 75 | ofconn_remove_bundle(ofconn, bundle); |
7ac27a04 | 76 | free(bundle); |
777af88d AC |
77 | } |
78 | ||
777af88d AC |
79 | enum ofperr |
80 | ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags) | |
81 | { | |
777af88d | 82 | struct ofp_bundle *bundle; |
ff09bc08 | 83 | enum ofperr error; |
777af88d | 84 | |
ff09bc08 | 85 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
86 | |
87 | if (bundle) { | |
88 | VLOG_INFO("Bundle %x already exists.", id); | |
1f42be1c | 89 | ofp_bundle_remove__(ofconn, bundle, false); |
777af88d AC |
90 | |
91 | return OFPERR_OFPBFC_BAD_ID; | |
92 | } | |
93 | ||
777af88d | 94 | bundle = ofp_bundle_create(id, flags); |
ff09bc08 JR |
95 | error = ofconn_insert_bundle(ofconn, bundle); |
96 | if (error) { | |
97 | free(bundle); | |
98 | } | |
777af88d | 99 | |
ff09bc08 | 100 | return error; |
777af88d AC |
101 | } |
102 | ||
103 | enum ofperr | |
104 | ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags) | |
105 | { | |
777af88d AC |
106 | struct ofp_bundle *bundle; |
107 | ||
ff09bc08 | 108 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
109 | |
110 | if (!bundle) { | |
111 | return OFPERR_OFPBFC_BAD_ID; | |
112 | } | |
113 | ||
114 | if (bundle->state == BS_CLOSED) { | |
1f42be1c | 115 | ofp_bundle_remove__(ofconn, bundle, false); |
777af88d AC |
116 | return OFPERR_OFPBFC_BUNDLE_CLOSED; |
117 | } | |
118 | ||
119 | if (bundle->flags != flags) { | |
1f42be1c | 120 | ofp_bundle_remove__(ofconn, bundle, false); |
777af88d AC |
121 | return OFPERR_OFPBFC_BAD_FLAGS; |
122 | } | |
123 | ||
124 | bundle->state = BS_CLOSED; | |
125 | return 0; | |
126 | } | |
127 | ||
777af88d AC |
128 | enum ofperr |
129 | ofp_bundle_discard(struct ofconn *ofconn, uint32_t id) | |
130 | { | |
777af88d AC |
131 | struct ofp_bundle *bundle; |
132 | ||
ff09bc08 | 133 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
134 | |
135 | if (!bundle) { | |
136 | return OFPERR_OFPBFC_BAD_ID; | |
137 | } | |
138 | ||
1f42be1c | 139 | ofp_bundle_remove__(ofconn, bundle, false); |
777af88d AC |
140 | |
141 | return 0; | |
142 | } | |
143 | ||
144 | enum ofperr | |
7ac27a04 JR |
145 | ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags, |
146 | struct ofp_bundle_entry *bmsg) | |
777af88d | 147 | { |
777af88d | 148 | struct ofp_bundle *bundle; |
777af88d | 149 | |
ff09bc08 | 150 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
151 | |
152 | if (!bundle) { | |
ff09bc08 | 153 | enum ofperr error; |
777af88d | 154 | |
ff09bc08 JR |
155 | bundle = ofp_bundle_create(id, flags); |
156 | error = ofconn_insert_bundle(ofconn, bundle); | |
157 | if (error) { | |
158 | free(bundle); | |
159 | return error; | |
160 | } | |
7b334c5c | 161 | } else if (bundle->state == BS_CLOSED) { |
1f42be1c | 162 | ofp_bundle_remove__(ofconn, bundle, false); |
777af88d | 163 | return OFPERR_OFPBFC_BUNDLE_CLOSED; |
7ac27a04 | 164 | } else if (flags != bundle->flags) { |
1f42be1c | 165 | ofp_bundle_remove__(ofconn, bundle, false); |
7b334c5c | 166 | return OFPERR_OFPBFC_BAD_FLAGS; |
777af88d AC |
167 | } |
168 | ||
777af88d AC |
169 | list_push_back(&bundle->msg_list, &bmsg->node); |
170 | return 0; | |
171 | } |