2 * Copyright (c) 2008-2017 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "openvswitch/ofp-bundle.h"
21 #include "openvswitch/ofp-parse.h"
22 #include "openvswitch/ofp-print.h"
23 #include "openvswitch/ofpbuf.h"
24 #include "openvswitch/vlog.h"
27 VLOG_DEFINE_THIS_MODULE(ofp_bundle
);
31 ofputil_free_bundle_msgs(struct ofputil_bundle_msg
*bms
, size_t n_bms
)
33 for (size_t i
= 0; i
< n_bms
; i
++) {
34 switch ((int)bms
[i
].type
) {
35 case OFPTYPE_FLOW_MOD
:
36 free(CONST_CAST(struct ofpact
*, bms
[i
].fm
.ofpacts
));
37 minimatch_destroy(&bms
[i
].fm
.match
);
39 case OFPTYPE_GROUP_MOD
:
40 ofputil_uninit_group_mod(&bms
[i
].gm
);
42 case OFPTYPE_PACKET_OUT
:
43 free(bms
[i
].po
.ofpacts
);
44 free(CONST_CAST(void *, bms
[i
].po
.packet
));
54 ofputil_encode_bundle_msgs(const struct ofputil_bundle_msg
*bms
,
55 size_t n_bms
, struct ovs_list
*requests
,
56 enum ofputil_protocol protocol
)
58 enum ofp_version version
= ofputil_protocol_to_ofp_version(protocol
);
60 for (size_t i
= 0; i
< n_bms
; i
++) {
61 struct ofpbuf
*request
= NULL
;
63 switch ((int)bms
[i
].type
) {
64 case OFPTYPE_FLOW_MOD
:
65 request
= ofputil_encode_flow_mod(&bms
[i
].fm
, protocol
);
67 case OFPTYPE_GROUP_MOD
:
68 request
= ofputil_encode_group_mod(version
, &bms
[i
].gm
, NULL
, -1);
70 case OFPTYPE_PACKET_OUT
:
71 request
= ofputil_encode_packet_out(&bms
[i
].po
, protocol
);
77 ovs_list_push_back(requests
, &request
->list_node
);
83 ofputil_decode_bundle_ctrl(const struct ofp_header
*oh
,
84 struct ofputil_bundle_ctrl_msg
*msg
)
86 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
87 enum ofpraw raw
= ofpraw_pull_assert(&b
);
88 ovs_assert(raw
== OFPRAW_OFPT14_BUNDLE_CONTROL
89 || raw
== OFPRAW_ONFT13_BUNDLE_CONTROL
);
91 const struct ofp14_bundle_ctrl_msg
*m
= b
.msg
;
92 msg
->bundle_id
= ntohl(m
->bundle_id
);
93 msg
->type
= ntohs(m
->type
);
94 msg
->flags
= ntohs(m
->flags
);
100 ofputil_encode_bundle_ctrl_request(enum ofp_version ofp_version
,
101 struct ofputil_bundle_ctrl_msg
*bc
)
103 struct ofpbuf
*request
;
104 struct ofp14_bundle_ctrl_msg
*m
;
106 switch (ofp_version
) {
110 ovs_fatal(0, "bundles need OpenFlow 1.3 or later "
111 "(\'-O OpenFlow14\')");
115 request
= ofpraw_alloc(ofp_version
== OFP13_VERSION
116 ? OFPRAW_ONFT13_BUNDLE_CONTROL
117 : OFPRAW_OFPT14_BUNDLE_CONTROL
, ofp_version
, 0);
118 m
= ofpbuf_put_zeros(request
, sizeof *m
);
120 m
->bundle_id
= htonl(bc
->bundle_id
);
121 m
->type
= htons(bc
->type
);
122 m
->flags
= htons(bc
->flags
);
132 bundle_flags_to_name(uint32_t bit
)
145 ofputil_format_bundle_ctrl_request(struct ds
*s
,
146 const struct ofputil_bundle_ctrl_msg
*bctrl
)
148 ds_put_char(s
, '\n');
149 ds_put_format(s
, " bundle_id=%#"PRIx32
" type=", bctrl
->bundle_id
);
150 switch (bctrl
->type
) {
151 case OFPBCT_OPEN_REQUEST
:
152 ds_put_cstr(s
, "OPEN_REQUEST");
154 case OFPBCT_OPEN_REPLY
:
155 ds_put_cstr(s
, "OPEN_REPLY");
157 case OFPBCT_CLOSE_REQUEST
:
158 ds_put_cstr(s
, "CLOSE_REQUEST");
160 case OFPBCT_CLOSE_REPLY
:
161 ds_put_cstr(s
, "CLOSE_REPLY");
163 case OFPBCT_COMMIT_REQUEST
:
164 ds_put_cstr(s
, "COMMIT_REQUEST");
166 case OFPBCT_COMMIT_REPLY
:
167 ds_put_cstr(s
, "COMMIT_REPLY");
169 case OFPBCT_DISCARD_REQUEST
:
170 ds_put_cstr(s
, "DISCARD_REQUEST");
172 case OFPBCT_DISCARD_REPLY
:
173 ds_put_cstr(s
, "DISCARD_REPLY");
177 ds_put_cstr(s
, " flags=");
178 ofp_print_bit_names(s
, bctrl
->flags
, bundle_flags_to_name
, ' ');
183 ofputil_encode_bundle_ctrl_reply(const struct ofp_header
*oh
,
184 struct ofputil_bundle_ctrl_msg
*msg
)
187 struct ofp14_bundle_ctrl_msg
*m
;
189 buf
= ofpraw_alloc_reply(oh
->version
== OFP13_VERSION
190 ? OFPRAW_ONFT13_BUNDLE_CONTROL
191 : OFPRAW_OFPT14_BUNDLE_CONTROL
, oh
, 0);
192 m
= ofpbuf_put_zeros(buf
, sizeof *m
);
194 m
->bundle_id
= htonl(msg
->bundle_id
);
195 m
->type
= htons(msg
->type
);
196 m
->flags
= htons(msg
->flags
);
201 /* Return true for bundlable state change requests, false for other messages.
204 ofputil_is_bundlable(enum ofptype type
)
207 /* Minimum required by OpenFlow 1.4. */
208 case OFPTYPE_PORT_MOD
:
209 case OFPTYPE_FLOW_MOD
:
210 /* Other supported types. */
211 case OFPTYPE_GROUP_MOD
:
212 case OFPTYPE_PACKET_OUT
:
215 /* Nice to have later. */
216 case OFPTYPE_FLOW_MOD_TABLE_ID
:
217 case OFPTYPE_TABLE_MOD
:
218 case OFPTYPE_METER_MOD
:
219 case OFPTYPE_NXT_TLV_TABLE_MOD
:
221 /* Not to be bundlable. */
222 case OFPTYPE_ECHO_REQUEST
:
223 case OFPTYPE_FEATURES_REQUEST
:
224 case OFPTYPE_GET_CONFIG_REQUEST
:
225 case OFPTYPE_SET_CONFIG
:
226 case OFPTYPE_BARRIER_REQUEST
:
227 case OFPTYPE_ROLE_REQUEST
:
228 case OFPTYPE_ECHO_REPLY
:
229 case OFPTYPE_SET_FLOW_FORMAT
:
230 case OFPTYPE_SET_PACKET_IN_FORMAT
:
231 case OFPTYPE_SET_CONTROLLER_ID
:
232 case OFPTYPE_FLOW_AGE
:
233 case OFPTYPE_FLOW_MONITOR_CANCEL
:
234 case OFPTYPE_SET_ASYNC_CONFIG
:
235 case OFPTYPE_GET_ASYNC_REQUEST
:
236 case OFPTYPE_DESC_STATS_REQUEST
:
237 case OFPTYPE_FLOW_STATS_REQUEST
:
238 case OFPTYPE_AGGREGATE_STATS_REQUEST
:
239 case OFPTYPE_TABLE_STATS_REQUEST
:
240 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST
:
241 case OFPTYPE_TABLE_DESC_REQUEST
:
242 case OFPTYPE_PORT_STATS_REQUEST
:
243 case OFPTYPE_QUEUE_STATS_REQUEST
:
244 case OFPTYPE_PORT_DESC_STATS_REQUEST
:
245 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST
:
246 case OFPTYPE_METER_STATS_REQUEST
:
247 case OFPTYPE_METER_CONFIG_STATS_REQUEST
:
248 case OFPTYPE_METER_FEATURES_STATS_REQUEST
:
249 case OFPTYPE_GROUP_STATS_REQUEST
:
250 case OFPTYPE_GROUP_DESC_STATS_REQUEST
:
251 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST
:
252 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST
:
253 case OFPTYPE_BUNDLE_CONTROL
:
254 case OFPTYPE_BUNDLE_ADD_MESSAGE
:
257 case OFPTYPE_FEATURES_REPLY
:
258 case OFPTYPE_GET_CONFIG_REPLY
:
259 case OFPTYPE_PACKET_IN
:
260 case OFPTYPE_FLOW_REMOVED
:
261 case OFPTYPE_PORT_STATUS
:
262 case OFPTYPE_BARRIER_REPLY
:
263 case OFPTYPE_QUEUE_GET_CONFIG_REPLY
:
264 case OFPTYPE_DESC_STATS_REPLY
:
265 case OFPTYPE_FLOW_STATS_REPLY
:
266 case OFPTYPE_QUEUE_STATS_REPLY
:
267 case OFPTYPE_PORT_STATS_REPLY
:
268 case OFPTYPE_TABLE_STATS_REPLY
:
269 case OFPTYPE_AGGREGATE_STATS_REPLY
:
270 case OFPTYPE_PORT_DESC_STATS_REPLY
:
271 case OFPTYPE_ROLE_REPLY
:
272 case OFPTYPE_FLOW_MONITOR_PAUSED
:
273 case OFPTYPE_FLOW_MONITOR_RESUMED
:
274 case OFPTYPE_FLOW_MONITOR_STATS_REPLY
:
275 case OFPTYPE_GET_ASYNC_REPLY
:
276 case OFPTYPE_GROUP_STATS_REPLY
:
277 case OFPTYPE_GROUP_DESC_STATS_REPLY
:
278 case OFPTYPE_GROUP_FEATURES_STATS_REPLY
:
279 case OFPTYPE_METER_STATS_REPLY
:
280 case OFPTYPE_METER_CONFIG_STATS_REPLY
:
281 case OFPTYPE_METER_FEATURES_STATS_REPLY
:
282 case OFPTYPE_TABLE_FEATURES_STATS_REPLY
:
283 case OFPTYPE_TABLE_DESC_REPLY
:
284 case OFPTYPE_ROLE_STATUS
:
285 case OFPTYPE_REQUESTFORWARD
:
286 case OFPTYPE_TABLE_STATUS
:
287 case OFPTYPE_NXT_TLV_TABLE_REQUEST
:
288 case OFPTYPE_NXT_TLV_TABLE_REPLY
:
289 case OFPTYPE_NXT_RESUME
:
290 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST
:
291 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY
:
292 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST
:
293 case OFPTYPE_IPFIX_FLOW_STATS_REPLY
:
294 case OFPTYPE_CT_FLUSH_ZONE
:
302 ofputil_decode_bundle_add(const struct ofp_header
*oh
,
303 struct ofputil_bundle_add_msg
*msg
,
306 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
308 /* Pull the outer ofp_header. */
309 enum ofpraw raw
= ofpraw_pull_assert(&b
);
310 ovs_assert(raw
== OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE
311 || raw
== OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE
);
313 /* Pull the bundle_ctrl header. */
314 const struct ofp14_bundle_ctrl_msg
*m
= ofpbuf_pull(&b
, sizeof *m
);
315 msg
->bundle_id
= ntohl(m
->bundle_id
);
316 msg
->flags
= ntohs(m
->flags
);
318 /* Pull the inner ofp_header. */
319 if (b
.size
< sizeof(struct ofp_header
)) {
320 return OFPERR_OFPBFC_MSG_BAD_LEN
;
323 if (msg
->msg
->version
!= oh
->version
) {
324 return OFPERR_OFPBFC_BAD_VERSION
;
326 size_t inner_len
= ntohs(msg
->msg
->length
);
327 if (inner_len
< sizeof(struct ofp_header
) || inner_len
> b
.size
) {
328 return OFPERR_OFPBFC_MSG_BAD_LEN
;
330 if (msg
->msg
->xid
!= oh
->xid
) {
331 return OFPERR_OFPBFC_MSG_BAD_XID
;
334 /* Reject unbundlable messages. */
336 enum ofperr error
= ofptype_decode(&type
, msg
->msg
);
338 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
339 VLOG_WARN_RL(&rl
, "OFPT14_BUNDLE_ADD_MESSAGE contained "
340 "message is unparsable (%s)", ofperr_get_name(error
));
341 return OFPERR_OFPBFC_MSG_UNSUP
; /* 'error' would be confusing. */
344 if (!ofputil_is_bundlable(type
)) {
345 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
346 VLOG_WARN_RL(&rl
, "%s message not allowed inside "
347 "OFPT14_BUNDLE_ADD_MESSAGE", ofptype_get_name(type
));
348 return OFPERR_OFPBFC_MSG_UNSUP
;
358 ofputil_encode_bundle_add(enum ofp_version ofp_version
,
359 struct ofputil_bundle_add_msg
*msg
)
361 struct ofpbuf
*request
;
362 struct ofp14_bundle_ctrl_msg
*m
;
364 /* Must use the same xid as the embedded message. */
365 request
= ofpraw_alloc_xid(ofp_version
== OFP13_VERSION
366 ? OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE
367 : OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE
, ofp_version
,
368 msg
->msg
->xid
, ntohs(msg
->msg
->length
));
369 m
= ofpbuf_put_zeros(request
, sizeof *m
);
371 m
->bundle_id
= htonl(msg
->bundle_id
);
372 m
->flags
= htons(msg
->flags
);
373 ofpbuf_put(request
, msg
->msg
, ntohs(msg
->msg
->length
));
375 ofpmsg_update_length(request
);
379 /* Opens file 'file_name' and reads each line as a flow_mod or a group_mod,
380 * depending on the first keyword on each line. Stores each flow and group
381 * mods in '*bms', an array allocated on the caller's behalf, and the number of
382 * messages in '*n_bms'.
384 * Returns NULL if successful, otherwise a malloc()'d string describing the
385 * error. The caller is responsible for freeing the returned string. */
386 char * OVS_WARN_UNUSED_RESULT
387 parse_ofp_bundle_file(const char *file_name
,
388 const struct ofputil_port_map
*port_map
,
389 const struct ofputil_table_map
*table_map
,
390 struct ofputil_bundle_msg
**bms
, size_t *n_bms
,
391 enum ofputil_protocol
*usable_protocols
)
393 size_t allocated_bms
;
399 *usable_protocols
= OFPUTIL_P_ANY
;
404 stream
= !strcmp(file_name
, "-") ? stdin
: fopen(file_name
, "r");
405 if (stream
== NULL
) {
406 return xasprintf("%s: open failed (%s)",
407 file_name
, ovs_strerror(errno
));
410 allocated_bms
= *n_bms
;
413 while (!ds_get_preprocessed_line(&ds
, stream
, &line_number
)) {
414 enum ofputil_protocol usable
;
415 char *s
= ds_cstr(&ds
);
418 if (*n_bms
>= allocated_bms
) {
419 struct ofputil_bundle_msg
*new_bms
;
421 new_bms
= x2nrealloc(*bms
, &allocated_bms
, sizeof **bms
);
422 for (size_t i
= 0; i
< *n_bms
; i
++) {
423 if (new_bms
[i
].type
== OFPTYPE_GROUP_MOD
) {
424 ovs_list_moved(&new_bms
[i
].gm
.buckets
,
425 &(*bms
)[i
].gm
.buckets
);
431 s
+= strspn(s
, " \t\r\n"); /* Skip white space. */
432 len
= strcspn(s
, ", \t\r\n"); /* Get length of the first token. */
434 if (!strncmp(s
, "flow", len
)) {
436 error
= parse_ofp_flow_mod_str(&(*bms
)[*n_bms
].fm
, s
, port_map
,
437 table_map
, -2, &usable
);
441 (*bms
)[*n_bms
].type
= OFPTYPE_FLOW_MOD
;
442 } else if (!strncmp(s
, "group", len
)) {
444 error
= parse_ofp_group_mod_str(&(*bms
)[*n_bms
].gm
, -2, s
,
445 port_map
, table_map
, &usable
);
449 (*bms
)[*n_bms
].type
= OFPTYPE_GROUP_MOD
;
450 } else if (!strncmp(s
, "packet-out", len
)) {
452 error
= parse_ofp_packet_out_str(&(*bms
)[*n_bms
].po
, s
, port_map
,
457 (*bms
)[*n_bms
].type
= OFPTYPE_PACKET_OUT
;
459 error
= xasprintf("Unsupported bundle message type: %.*s",
464 *usable_protocols
&= usable
; /* Each line can narrow the set. */
469 if (stream
!= stdin
) {
474 char *err_msg
= xasprintf("%s:%d: %s", file_name
, line_number
, error
);
477 ofputil_free_bundle_msgs(*bms
, *n_bms
);
486 ofputil_format_bundle_add(struct ds
*s
,
487 const struct ofputil_bundle_add_msg
*badd
,
488 const struct ofputil_port_map
*port_map
,
489 const struct ofputil_table_map
*table_map
,
492 ds_put_char(s
, '\n');
493 ds_put_format(s
, " bundle_id=%#"PRIx32
, badd
->bundle_id
);
494 ds_put_cstr(s
, " flags=");
495 ofp_print_bit_names(s
, badd
->flags
, bundle_flags_to_name
, ' ');
497 ds_put_char(s
, '\n');
498 char *msg
= ofp_to_string(badd
->msg
, ntohs(badd
->msg
->length
), port_map
,
499 table_map
, verbosity
);
500 ds_put_and_free_cstr(s
, msg
);