]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ofp-bundle.c
lldp: increase statsTLVsUnrecognizedTotal on unknown TLV
[mirror_ovs.git] / lib / ofp-bundle.c
CommitLineData
0d71302e
BP
1/*
2 * Copyright (c) 2008-2017 Nicira, Inc.
3 *
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include <config.h>
18#include "openvswitch/ofp-bundle.h"
19#include <errno.h>
20#include <stdlib.h>
21#include "openvswitch/ofp-parse.h"
fe2c69f4 22#include "openvswitch/ofp-print.h"
0d71302e
BP
23#include "openvswitch/ofpbuf.h"
24#include "openvswitch/vlog.h"
25#include "util.h"
26
27VLOG_DEFINE_THIS_MODULE(ofp_bundle);
28
29/* Destroys 'bms'. */
30void
31ofputil_free_bundle_msgs(struct ofputil_bundle_msg *bms, size_t n_bms)
32{
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));
6a6b7060 37 minimatch_destroy(&bms[i].fm.match);
0d71302e
BP
38 break;
39 case OFPTYPE_GROUP_MOD:
40 ofputil_uninit_group_mod(&bms[i].gm);
41 break;
42 case OFPTYPE_PACKET_OUT:
43 free(bms[i].po.ofpacts);
44 free(CONST_CAST(void *, bms[i].po.packet));
45 break;
46 default:
47 break;
48 }
49 }
50 free(bms);
51}
52
53void
54ofputil_encode_bundle_msgs(const struct ofputil_bundle_msg *bms,
55 size_t n_bms, struct ovs_list *requests,
56 enum ofputil_protocol protocol)
57{
58 enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
59
60 for (size_t i = 0; i < n_bms; i++) {
61 struct ofpbuf *request = NULL;
62
63 switch ((int)bms[i].type) {
64 case OFPTYPE_FLOW_MOD:
65 request = ofputil_encode_flow_mod(&bms[i].fm, protocol);
66 break;
67 case OFPTYPE_GROUP_MOD:
f836888d 68 request = ofputil_encode_group_mod(version, &bms[i].gm, NULL, -1);
0d71302e
BP
69 break;
70 case OFPTYPE_PACKET_OUT:
71 request = ofputil_encode_packet_out(&bms[i].po, protocol);
72 break;
73 default:
74 break;
75 }
76 if (request) {
77 ovs_list_push_back(requests, &request->list_node);
78 }
79 }
80}
81
82enum ofperr
83ofputil_decode_bundle_ctrl(const struct ofp_header *oh,
84 struct ofputil_bundle_ctrl_msg *msg)
85{
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);
90
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);
95
96 return 0;
97}
98
99struct ofpbuf *
100ofputil_encode_bundle_ctrl_request(enum ofp_version ofp_version,
101 struct ofputil_bundle_ctrl_msg *bc)
102{
103 struct ofpbuf *request;
104 struct ofp14_bundle_ctrl_msg *m;
105
106 switch (ofp_version) {
107 case OFP10_VERSION:
108 case OFP11_VERSION:
109 case OFP12_VERSION:
110 ovs_fatal(0, "bundles need OpenFlow 1.3 or later "
111 "(\'-O OpenFlow14\')");
112 case OFP13_VERSION:
113 case OFP14_VERSION:
114 case OFP15_VERSION:
0d71302e
BP
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);
119
120 m->bundle_id = htonl(bc->bundle_id);
121 m->type = htons(bc->type);
122 m->flags = htons(bc->flags);
123 break;
124 default:
125 OVS_NOT_REACHED();
126 }
127
128 return request;
129}
130
fe2c69f4
BP
131static const char *
132bundle_flags_to_name(uint32_t bit)
133{
134 switch (bit) {
135 case OFPBF_ATOMIC:
136 return "atomic";
137 case OFPBF_ORDERED:
138 return "ordered";
139 default:
140 return NULL;
141 }
142}
143
144void
145ofputil_format_bundle_ctrl_request(struct ds *s,
146 const struct ofputil_bundle_ctrl_msg *bctrl)
147{
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");
153 break;
154 case OFPBCT_OPEN_REPLY:
155 ds_put_cstr(s, "OPEN_REPLY");
156 break;
157 case OFPBCT_CLOSE_REQUEST:
158 ds_put_cstr(s, "CLOSE_REQUEST");
159 break;
160 case OFPBCT_CLOSE_REPLY:
161 ds_put_cstr(s, "CLOSE_REPLY");
162 break;
163 case OFPBCT_COMMIT_REQUEST:
164 ds_put_cstr(s, "COMMIT_REQUEST");
165 break;
166 case OFPBCT_COMMIT_REPLY:
167 ds_put_cstr(s, "COMMIT_REPLY");
168 break;
169 case OFPBCT_DISCARD_REQUEST:
170 ds_put_cstr(s, "DISCARD_REQUEST");
171 break;
172 case OFPBCT_DISCARD_REPLY:
173 ds_put_cstr(s, "DISCARD_REPLY");
174 break;
175 }
176
177 ds_put_cstr(s, " flags=");
178 ofp_print_bit_names(s, bctrl->flags, bundle_flags_to_name, ' ');
179}
180
181
0d71302e
BP
182struct ofpbuf *
183ofputil_encode_bundle_ctrl_reply(const struct ofp_header *oh,
184 struct ofputil_bundle_ctrl_msg *msg)
185{
186 struct ofpbuf *buf;
187 struct ofp14_bundle_ctrl_msg *m;
188
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);
193
194 m->bundle_id = htonl(msg->bundle_id);
195 m->type = htons(msg->type);
196 m->flags = htons(msg->flags);
197
198 return buf;
199}
200
201/* Return true for bundlable state change requests, false for other messages.
202 */
203static bool
204ofputil_is_bundlable(enum ofptype type)
205{
206 switch (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:
213 return true;
214
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:
220
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:
255 case OFPTYPE_HELLO:
256 case OFPTYPE_ERROR:
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:
295 break;
296 }
297
298 return false;
299}
300
301enum ofperr
302ofputil_decode_bundle_add(const struct ofp_header *oh,
303 struct ofputil_bundle_add_msg *msg,
304 enum ofptype *typep)
305{
306 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
307
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);
312
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);
317
318 /* Pull the inner ofp_header. */
319 if (b.size < sizeof(struct ofp_header)) {
320 return OFPERR_OFPBFC_MSG_BAD_LEN;
321 }
322 msg->msg = b.data;
323 if (msg->msg->version != oh->version) {
324 return OFPERR_OFPBFC_BAD_VERSION;
325 }
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;
329 }
330 if (msg->msg->xid != oh->xid) {
331 return OFPERR_OFPBFC_MSG_BAD_XID;
332 }
333
334 /* Reject unbundlable messages. */
335 enum ofptype type;
336 enum ofperr error = ofptype_decode(&type, msg->msg);
337 if (error) {
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. */
342 }
343
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;
349 }
350 if (typep) {
351 *typep = type;
352 }
353
354 return 0;
355}
356
357struct ofpbuf *
358ofputil_encode_bundle_add(enum ofp_version ofp_version,
359 struct ofputil_bundle_add_msg *msg)
360{
361 struct ofpbuf *request;
362 struct ofp14_bundle_ctrl_msg *m;
363
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);
370
371 m->bundle_id = htonl(msg->bundle_id);
372 m->flags = htons(msg->flags);
373 ofpbuf_put(request, msg->msg, ntohs(msg->msg->length));
374
375 ofpmsg_update_length(request);
376 return request;
377}
378
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'.
383 *
384 * Returns NULL if successful, otherwise a malloc()'d string describing the
385 * error. The caller is responsible for freeing the returned string. */
386char * OVS_WARN_UNUSED_RESULT
387parse_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)
392{
393 size_t allocated_bms;
394 char *error = NULL;
395 int line_number;
396 FILE *stream;
397 struct ds ds;
398
399 *usable_protocols = OFPUTIL_P_ANY;
400
401 *bms = NULL;
402 *n_bms = 0;
403
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));
408 }
409
410 allocated_bms = *n_bms;
411 ds_init(&ds);
412 line_number = 0;
413 while (!ds_get_preprocessed_line(&ds, stream, &line_number)) {
414 enum ofputil_protocol usable;
415 char *s = ds_cstr(&ds);
416 size_t len;
417
418 if (*n_bms >= allocated_bms) {
419 struct ofputil_bundle_msg *new_bms;
420
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);
426 }
427 }
428 *bms = new_bms;
429 }
430
431 s += strspn(s, " \t\r\n"); /* Skip white space. */
432 len = strcspn(s, ", \t\r\n"); /* Get length of the first token. */
433
434 if (!strncmp(s, "flow", len)) {
435 s += len;
436 error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, port_map,
437 table_map, -2, &usable);
438 if (error) {
439 break;
440 }
441 (*bms)[*n_bms].type = OFPTYPE_FLOW_MOD;
442 } else if (!strncmp(s, "group", len)) {
443 s += len;
444 error = parse_ofp_group_mod_str(&(*bms)[*n_bms].gm, -2, s,
445 port_map, table_map, &usable);
446 if (error) {
447 break;
448 }
449 (*bms)[*n_bms].type = OFPTYPE_GROUP_MOD;
450 } else if (!strncmp(s, "packet-out", len)) {
451 s += len;
452 error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, port_map,
453 table_map, &usable);
454 if (error) {
455 break;
456 }
457 (*bms)[*n_bms].type = OFPTYPE_PACKET_OUT;
458 } else {
459 error = xasprintf("Unsupported bundle message type: %.*s",
460 (int)len, s);
461 break;
462 }
463
464 *usable_protocols &= usable; /* Each line can narrow the set. */
465 *n_bms += 1;
466 }
467
468 ds_destroy(&ds);
469 if (stream != stdin) {
470 fclose(stream);
471 }
472
473 if (error) {
474 char *err_msg = xasprintf("%s:%d: %s", file_name, line_number, error);
475 free(error);
476
477 ofputil_free_bundle_msgs(*bms, *n_bms);
478 *bms = NULL;
479 *n_bms = 0;
480 return err_msg;
481 }
482 return NULL;
483}
fe2c69f4
BP
484
485void
486ofputil_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,
490 int verbosity)
491{
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, ' ');
496
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);
501}