]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-protocol.c
ofp-util, ofp-parse: Break up into many separate modules.
[mirror_ovs.git] / lib / ofp-protocol.c
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-protocol.h"
19 #include <ctype.h>
20 #include "openvswitch/dynamic-string.h"
21 #include "openvswitch/ofp-flow.h"
22 #include "openvswitch/vlog.h"
23 #include "util.h"
24
25 VLOG_DEFINE_THIS_MODULE(ofp_protocol);
26
27 /* Protocols. */
28
29 struct proto_abbrev {
30 enum ofputil_protocol protocol;
31 const char *name;
32 };
33
34 /* Most users really don't care about some of the differences between
35 * protocols. These abbreviations help with that. */
36 static const struct proto_abbrev proto_abbrevs[] = {
37 { OFPUTIL_P_ANY, "any" },
38 { OFPUTIL_P_OF10_STD_ANY, "OpenFlow10" },
39 { OFPUTIL_P_OF10_NXM_ANY, "NXM" },
40 { OFPUTIL_P_ANY_OXM, "OXM" },
41 };
42 #define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
43
44 enum ofputil_protocol ofputil_flow_dump_protocols[] = {
45 OFPUTIL_P_OF16_OXM,
46 OFPUTIL_P_OF15_OXM,
47 OFPUTIL_P_OF14_OXM,
48 OFPUTIL_P_OF13_OXM,
49 OFPUTIL_P_OF12_OXM,
50 OFPUTIL_P_OF11_STD,
51 OFPUTIL_P_OF10_NXM,
52 OFPUTIL_P_OF10_STD,
53 };
54 size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
55
56 /* Returns the set of ofputil_protocols that are supported with the given
57 * OpenFlow 'version'. 'version' should normally be an 8-bit OpenFlow version
58 * identifier (e.g. 0x01 for OpenFlow 1.0, 0x02 for OpenFlow 1.1). Returns 0
59 * if 'version' is not supported or outside the valid range. */
60 enum ofputil_protocol
61 ofputil_protocols_from_ofp_version(enum ofp_version version)
62 {
63 switch (version) {
64 case OFP10_VERSION:
65 return OFPUTIL_P_OF10_STD_ANY | OFPUTIL_P_OF10_NXM_ANY;
66 case OFP11_VERSION:
67 return OFPUTIL_P_OF11_STD;
68 case OFP12_VERSION:
69 return OFPUTIL_P_OF12_OXM;
70 case OFP13_VERSION:
71 return OFPUTIL_P_OF13_OXM;
72 case OFP14_VERSION:
73 return OFPUTIL_P_OF14_OXM;
74 case OFP15_VERSION:
75 return OFPUTIL_P_OF15_OXM;
76 case OFP16_VERSION:
77 return OFPUTIL_P_OF16_OXM;
78 default:
79 return 0;
80 }
81 }
82
83 /* Returns the ofputil_protocol that is initially in effect on an OpenFlow
84 * connection that has negotiated the given 'version'. 'version' should
85 * normally be an 8-bit OpenFlow version identifier (e.g. 0x01 for OpenFlow
86 * 1.0, 0x02 for OpenFlow 1.1). Returns 0 if 'version' is not supported or
87 * outside the valid range. */
88 enum ofputil_protocol
89 ofputil_protocol_from_ofp_version(enum ofp_version version)
90 {
91 return rightmost_1bit(ofputil_protocols_from_ofp_version(version));
92 }
93
94 /* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION,
95 * etc.) that corresponds to 'protocol'. */
96 enum ofp_version
97 ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
98 {
99 switch (protocol) {
100 case OFPUTIL_P_OF10_STD:
101 case OFPUTIL_P_OF10_STD_TID:
102 case OFPUTIL_P_OF10_NXM:
103 case OFPUTIL_P_OF10_NXM_TID:
104 return OFP10_VERSION;
105 case OFPUTIL_P_OF11_STD:
106 return OFP11_VERSION;
107 case OFPUTIL_P_OF12_OXM:
108 return OFP12_VERSION;
109 case OFPUTIL_P_OF13_OXM:
110 return OFP13_VERSION;
111 case OFPUTIL_P_OF14_OXM:
112 return OFP14_VERSION;
113 case OFPUTIL_P_OF15_OXM:
114 return OFP15_VERSION;
115 case OFPUTIL_P_OF16_OXM:
116 return OFP16_VERSION;
117 }
118
119 OVS_NOT_REACHED();
120 }
121
122 /* Returns a bitmap of OpenFlow versions that are supported by at
123 * least one of the 'protocols'. */
124 uint32_t
125 ofputil_protocols_to_version_bitmap(enum ofputil_protocol protocols)
126 {
127 uint32_t bitmap = 0;
128
129 for (; protocols; protocols = zero_rightmost_1bit(protocols)) {
130 enum ofputil_protocol protocol = rightmost_1bit(protocols);
131
132 bitmap |= 1u << ofputil_protocol_to_ofp_version(protocol);
133 }
134
135 return bitmap;
136 }
137
138 /* Returns the set of protocols that are supported on top of the
139 * OpenFlow versions included in 'bitmap'. */
140 enum ofputil_protocol
141 ofputil_protocols_from_version_bitmap(uint32_t bitmap)
142 {
143 enum ofputil_protocol protocols = 0;
144
145 for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) {
146 enum ofp_version version = rightmost_1bit_idx(bitmap);
147
148 protocols |= ofputil_protocols_from_ofp_version(version);
149 }
150
151 return protocols;
152 }
153
154 /* Returns true if 'protocol' is a single OFPUTIL_P_* value, false
155 * otherwise. */
156 bool
157 ofputil_protocol_is_valid(enum ofputil_protocol protocol)
158 {
159 return protocol & OFPUTIL_P_ANY && is_pow2(protocol);
160 }
161
162 /* Returns the equivalent of 'protocol' with the Nicira flow_mod_table_id
163 * extension turned on or off if 'enable' is true or false, respectively.
164 *
165 * This extension is only useful for protocols whose "standard" version does
166 * not allow specific tables to be modified. In particular, this is true of
167 * OpenFlow 1.0. In later versions of OpenFlow, a flow_mod request always
168 * specifies a table ID and so there is no need for such an extension. When
169 * 'protocol' is such a protocol that doesn't need a flow_mod_table_id
170 * extension, this function just returns its 'protocol' argument unchanged
171 * regardless of the value of 'enable'. */
172 enum ofputil_protocol
173 ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
174 {
175 switch (protocol) {
176 case OFPUTIL_P_OF10_STD:
177 case OFPUTIL_P_OF10_STD_TID:
178 return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD;
179
180 case OFPUTIL_P_OF10_NXM:
181 case OFPUTIL_P_OF10_NXM_TID:
182 return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM;
183
184 case OFPUTIL_P_OF11_STD:
185 return OFPUTIL_P_OF11_STD;
186
187 case OFPUTIL_P_OF12_OXM:
188 return OFPUTIL_P_OF12_OXM;
189
190 case OFPUTIL_P_OF13_OXM:
191 return OFPUTIL_P_OF13_OXM;
192
193 case OFPUTIL_P_OF14_OXM:
194 return OFPUTIL_P_OF14_OXM;
195
196 case OFPUTIL_P_OF15_OXM:
197 return OFPUTIL_P_OF15_OXM;
198
199 case OFPUTIL_P_OF16_OXM:
200 return OFPUTIL_P_OF16_OXM;
201
202 default:
203 OVS_NOT_REACHED();
204 }
205 }
206
207 /* Returns the "base" version of 'protocol'. That is, if 'protocol' includes
208 * some extension to a standard protocol version, the return value is the
209 * standard version of that protocol without any extension. If 'protocol' is a
210 * standard protocol version, returns 'protocol' unchanged. */
211 enum ofputil_protocol
212 ofputil_protocol_to_base(enum ofputil_protocol protocol)
213 {
214 return ofputil_protocol_set_tid(protocol, false);
215 }
216
217 /* Returns 'new_base' with any extensions taken from 'cur'. */
218 enum ofputil_protocol
219 ofputil_protocol_set_base(enum ofputil_protocol cur,
220 enum ofputil_protocol new_base)
221 {
222 bool tid = (cur & OFPUTIL_P_TID) != 0;
223
224 switch (new_base) {
225 case OFPUTIL_P_OF10_STD:
226 case OFPUTIL_P_OF10_STD_TID:
227 return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid);
228
229 case OFPUTIL_P_OF10_NXM:
230 case OFPUTIL_P_OF10_NXM_TID:
231 return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid);
232
233 case OFPUTIL_P_OF11_STD:
234 return ofputil_protocol_set_tid(OFPUTIL_P_OF11_STD, tid);
235
236 case OFPUTIL_P_OF12_OXM:
237 return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);
238
239 case OFPUTIL_P_OF13_OXM:
240 return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid);
241
242 case OFPUTIL_P_OF14_OXM:
243 return ofputil_protocol_set_tid(OFPUTIL_P_OF14_OXM, tid);
244
245 case OFPUTIL_P_OF15_OXM:
246 return ofputil_protocol_set_tid(OFPUTIL_P_OF15_OXM, tid);
247
248 case OFPUTIL_P_OF16_OXM:
249 return ofputil_protocol_set_tid(OFPUTIL_P_OF16_OXM, tid);
250
251 default:
252 OVS_NOT_REACHED();
253 }
254 }
255
256 /* Returns a string form of 'protocol', if a simple form exists (that is, if
257 * 'protocol' is either a single protocol or it is a combination of protocols
258 * that have a single abbreviation). Otherwise, returns NULL. */
259 const char *
260 ofputil_protocol_to_string(enum ofputil_protocol protocol)
261 {
262 const struct proto_abbrev *p;
263
264 /* Use a "switch" statement for single-bit names so that we get a compiler
265 * warning if we forget any. */
266 switch (protocol) {
267 case OFPUTIL_P_OF10_NXM:
268 return "NXM-table_id";
269
270 case OFPUTIL_P_OF10_NXM_TID:
271 return "NXM+table_id";
272
273 case OFPUTIL_P_OF10_STD:
274 return "OpenFlow10-table_id";
275
276 case OFPUTIL_P_OF10_STD_TID:
277 return "OpenFlow10+table_id";
278
279 case OFPUTIL_P_OF11_STD:
280 return "OpenFlow11";
281
282 case OFPUTIL_P_OF12_OXM:
283 return "OXM-OpenFlow12";
284
285 case OFPUTIL_P_OF13_OXM:
286 return "OXM-OpenFlow13";
287
288 case OFPUTIL_P_OF14_OXM:
289 return "OXM-OpenFlow14";
290
291 case OFPUTIL_P_OF15_OXM:
292 return "OXM-OpenFlow15";
293
294 case OFPUTIL_P_OF16_OXM:
295 return "OXM-OpenFlow16";
296 }
297
298 /* Check abbreviations. */
299 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
300 if (protocol == p->protocol) {
301 return p->name;
302 }
303 }
304
305 return NULL;
306 }
307
308 /* Returns a string that represents 'protocols'. The return value might be a
309 * comma-separated list if 'protocols' doesn't have a simple name. The return
310 * value is "none" if 'protocols' is 0.
311 *
312 * The caller must free the returned string (with free()). */
313 char *
314 ofputil_protocols_to_string(enum ofputil_protocol protocols)
315 {
316 struct ds s;
317
318 ovs_assert(!(protocols & ~OFPUTIL_P_ANY));
319 if (protocols == 0) {
320 return xstrdup("none");
321 }
322
323 ds_init(&s);
324 while (protocols) {
325 const struct proto_abbrev *p;
326 int i;
327
328 if (s.length) {
329 ds_put_char(&s, ',');
330 }
331
332 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
333 if ((protocols & p->protocol) == p->protocol) {
334 ds_put_cstr(&s, p->name);
335 protocols &= ~p->protocol;
336 goto match;
337 }
338 }
339
340 for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
341 enum ofputil_protocol bit = 1u << i;
342
343 if (protocols & bit) {
344 ds_put_cstr(&s, ofputil_protocol_to_string(bit));
345 protocols &= ~bit;
346 goto match;
347 }
348 }
349 OVS_NOT_REACHED();
350
351 match: ;
352 }
353 return ds_steal_cstr(&s);
354 }
355
356 static enum ofputil_protocol
357 ofputil_protocol_from_string__(const char *s, size_t n)
358 {
359 const struct proto_abbrev *p;
360 int i;
361
362 for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
363 enum ofputil_protocol bit = 1u << i;
364 const char *name = ofputil_protocol_to_string(bit);
365
366 if (name && n == strlen(name) && !strncasecmp(s, name, n)) {
367 return bit;
368 }
369 }
370
371 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
372 if (n == strlen(p->name) && !strncasecmp(s, p->name, n)) {
373 return p->protocol;
374 }
375 }
376
377 return 0;
378 }
379
380 /* Returns the nonempty set of protocols represented by 's', which can be a
381 * single protocol name or abbreviation or a comma-separated list of them.
382 *
383 * Aborts the program with an error message if 's' is invalid. */
384 enum ofputil_protocol
385 ofputil_protocols_from_string(const char *s)
386 {
387 const char *orig_s = s;
388 enum ofputil_protocol protocols;
389
390 protocols = 0;
391 while (*s) {
392 enum ofputil_protocol p;
393 size_t n;
394
395 n = strcspn(s, ",");
396 if (n == 0) {
397 s++;
398 continue;
399 }
400
401 p = ofputil_protocol_from_string__(s, n);
402 if (!p) {
403 ovs_fatal(0, "%.*s: unknown flow protocol", (int) n, s);
404 }
405 protocols |= p;
406
407 s += n;
408 }
409
410 if (!protocols) {
411 ovs_fatal(0, "%s: no flow protocol specified", orig_s);
412 }
413 return protocols;
414 }
415
416 enum ofp_version
417 ofputil_version_from_string(const char *s)
418 {
419 if (!strcasecmp(s, "OpenFlow10")) {
420 return OFP10_VERSION;
421 }
422 if (!strcasecmp(s, "OpenFlow11")) {
423 return OFP11_VERSION;
424 }
425 if (!strcasecmp(s, "OpenFlow12")) {
426 return OFP12_VERSION;
427 }
428 if (!strcasecmp(s, "OpenFlow13")) {
429 return OFP13_VERSION;
430 }
431 if (!strcasecmp(s, "OpenFlow14")) {
432 return OFP14_VERSION;
433 }
434 if (!strcasecmp(s, "OpenFlow15")) {
435 return OFP15_VERSION;
436 }
437 if (!strcasecmp(s, "OpenFlow16")) {
438 return OFP16_VERSION;
439 }
440 return 0;
441 }
442
443 static bool
444 is_delimiter(unsigned char c)
445 {
446 return isspace(c) || c == ',';
447 }
448
449 uint32_t
450 ofputil_versions_from_string(const char *s)
451 {
452 size_t i = 0;
453 uint32_t bitmap = 0;
454
455 while (s[i]) {
456 size_t j;
457 int version;
458 char *key;
459
460 if (is_delimiter(s[i])) {
461 i++;
462 continue;
463 }
464 j = 0;
465 while (s[i + j] && !is_delimiter(s[i + j])) {
466 j++;
467 }
468 key = xmemdup0(s + i, j);
469 version = ofputil_version_from_string(key);
470 if (!version) {
471 VLOG_FATAL("Unknown OpenFlow version: \"%s\"", key);
472 }
473 free(key);
474 bitmap |= 1u << version;
475 i += j;
476 }
477
478 return bitmap;
479 }
480
481 uint32_t
482 ofputil_versions_from_strings(char ** const s, size_t count)
483 {
484 uint32_t bitmap = 0;
485
486 while (count--) {
487 int version = ofputil_version_from_string(s[count]);
488 if (!version) {
489 VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]);
490 } else {
491 bitmap |= 1u << version;
492 }
493 }
494
495 return bitmap;
496 }
497
498 const char *
499 ofputil_version_to_string(enum ofp_version ofp_version)
500 {
501 switch (ofp_version) {
502 case OFP10_VERSION:
503 return "OpenFlow10";
504 case OFP11_VERSION:
505 return "OpenFlow11";
506 case OFP12_VERSION:
507 return "OpenFlow12";
508 case OFP13_VERSION:
509 return "OpenFlow13";
510 case OFP14_VERSION:
511 return "OpenFlow14";
512 case OFP15_VERSION:
513 return "OpenFlow15";
514 case OFP16_VERSION:
515 return "OpenFlow16";
516 default:
517 OVS_NOT_REACHED();
518 }
519 }
520
521 void
522 ofputil_format_version(struct ds *msg, enum ofp_version version)
523 {
524 ds_put_format(msg, "0x%02x", version);
525 }
526
527 void
528 ofputil_format_version_name(struct ds *msg, enum ofp_version version)
529 {
530 ds_put_cstr(msg, ofputil_version_to_string(version));
531 }
532
533 static void
534 ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap,
535 void (*format_version)(struct ds *msg,
536 enum ofp_version))
537 {
538 while (bitmap) {
539 format_version(msg, raw_ctz(bitmap));
540 bitmap = zero_rightmost_1bit(bitmap);
541 if (bitmap) {
542 ds_put_cstr(msg, ", ");
543 }
544 }
545 }
546
547 void
548 ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap)
549 {
550 ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version);
551 }
552
553 void
554 ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap)
555 {
556 ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version_name);
557 }
558
559 /* Returns an OpenFlow message that, sent on an OpenFlow connection whose
560 * protocol is 'current', at least partly transitions the protocol to 'want'.
561 * Stores in '*next' the protocol that will be in effect on the OpenFlow
562 * connection if the switch processes the returned message correctly. (If
563 * '*next != want' then the caller will have to iterate.)
564 *
565 * If 'current == want', or if it is not possible to transition from 'current'
566 * to 'want' (because, for example, 'current' and 'want' use different OpenFlow
567 * protocol versions), returns NULL and stores 'current' in '*next'. */
568 struct ofpbuf *
569 ofputil_encode_set_protocol(enum ofputil_protocol current,
570 enum ofputil_protocol want,
571 enum ofputil_protocol *next)
572 {
573 enum ofp_version cur_version, want_version;
574 enum ofputil_protocol cur_base, want_base;
575 bool cur_tid, want_tid;
576
577 cur_version = ofputil_protocol_to_ofp_version(current);
578 want_version = ofputil_protocol_to_ofp_version(want);
579 if (cur_version != want_version) {
580 *next = current;
581 return NULL;
582 }
583
584 cur_base = ofputil_protocol_to_base(current);
585 want_base = ofputil_protocol_to_base(want);
586 if (cur_base != want_base) {
587 *next = ofputil_protocol_set_base(current, want_base);
588
589 switch (want_base) {
590 case OFPUTIL_P_OF10_NXM:
591 return ofputil_encode_nx_set_flow_format(NXFF_NXM);
592
593 case OFPUTIL_P_OF10_STD:
594 return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW10);
595
596 case OFPUTIL_P_OF11_STD:
597 case OFPUTIL_P_OF12_OXM:
598 case OFPUTIL_P_OF13_OXM:
599 case OFPUTIL_P_OF14_OXM:
600 case OFPUTIL_P_OF15_OXM:
601 case OFPUTIL_P_OF16_OXM:
602 /* There is only one variant of each OpenFlow 1.1+ protocol, and we
603 * verified above that we're not trying to change versions. */
604 OVS_NOT_REACHED();
605
606 case OFPUTIL_P_OF10_STD_TID:
607 case OFPUTIL_P_OF10_NXM_TID:
608 OVS_NOT_REACHED();
609 }
610 }
611
612 cur_tid = (current & OFPUTIL_P_TID) != 0;
613 want_tid = (want & OFPUTIL_P_TID) != 0;
614 if (cur_tid != want_tid) {
615 *next = ofputil_protocol_set_tid(current, want_tid);
616 return ofputil_make_flow_mod_table_id(want_tid);
617 }
618
619 ovs_assert(current == want);
620
621 *next = current;
622 return NULL;
623 }