Coverage Report

Created: 2025-07-01 06:50

/src/openvswitch/lib/ofp-protocol.c
Line
Count
Source (jump to first uncovered line)
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/ofp-msgs.h"
23
#include "openvswitch/ofpbuf.h"
24
#include "openvswitch/vlog.h"
25
#include "util.h"
26
27
VLOG_DEFINE_THIS_MODULE(ofp_protocol);
28
29
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
30
31
/* Protocols. */
32
33
struct proto_abbrev {
34
    enum ofputil_protocol protocol;
35
    const char *name;
36
};
37
38
/* Most users really don't care about some of the differences between
39
 * protocols.  These abbreviations help with that. */
40
static const struct proto_abbrev proto_abbrevs[] = {
41
    { OFPUTIL_P_ANY,          "any" },
42
    { OFPUTIL_P_OF10_STD_ANY, "OpenFlow10" },
43
    { OFPUTIL_P_OF10_NXM_ANY, "NXM" },
44
    { OFPUTIL_P_ANY_OXM,      "OXM" },
45
};
46
0
#define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
47
48
enum ofputil_protocol ofputil_flow_dump_protocols[] = {
49
    OFPUTIL_P_OF15_OXM,
50
    OFPUTIL_P_OF14_OXM,
51
    OFPUTIL_P_OF13_OXM,
52
    OFPUTIL_P_OF12_OXM,
53
    OFPUTIL_P_OF11_STD,
54
    OFPUTIL_P_OF10_NXM,
55
    OFPUTIL_P_OF10_STD,
56
};
57
size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
58
59
/* Returns the set of ofputil_protocols that are supported with the given
60
 * OpenFlow 'version'.  'version' should normally be an 8-bit OpenFlow version
61
 * identifier (e.g. 0x01 for OpenFlow 1.0, 0x02 for OpenFlow 1.1).  Returns 0
62
 * if 'version' is not supported or outside the valid range.  */
63
enum ofputil_protocol
64
ofputil_protocols_from_ofp_version(enum ofp_version version)
65
0
{
66
0
    switch (version) {
67
0
    case OFP10_VERSION:
68
0
        return OFPUTIL_P_OF10_STD_ANY | OFPUTIL_P_OF10_NXM_ANY;
69
0
    case OFP11_VERSION:
70
0
        return OFPUTIL_P_OF11_STD;
71
0
    case OFP12_VERSION:
72
0
        return OFPUTIL_P_OF12_OXM;
73
0
    case OFP13_VERSION:
74
0
        return OFPUTIL_P_OF13_OXM;
75
0
    case OFP14_VERSION:
76
0
        return OFPUTIL_P_OF14_OXM;
77
0
    case OFP15_VERSION:
78
0
        return OFPUTIL_P_OF15_OXM;
79
0
    default:
80
0
        return 0;
81
0
    }
82
0
}
83
84
/* Returns the ofputil_protocol that is initially in effect on an OpenFlow
85
 * connection that has negotiated the given 'version'.  'version' should
86
 * normally be an 8-bit OpenFlow version identifier (e.g. 0x01 for OpenFlow
87
 * 1.0, 0x02 for OpenFlow 1.1).  Returns 0 if 'version' is not supported or
88
 * outside the valid range.  */
89
enum ofputil_protocol
90
ofputil_protocol_from_ofp_version(enum ofp_version version)
91
0
{
92
0
    return rightmost_1bit(ofputil_protocols_from_ofp_version(version));
93
0
}
94
95
/* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION,
96
 * etc.) that corresponds to 'protocol'. */
97
enum ofp_version
98
ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
99
0
{
100
0
    switch (protocol) {
101
0
    case OFPUTIL_P_OF10_STD:
102
0
    case OFPUTIL_P_OF10_STD_TID:
103
0
    case OFPUTIL_P_OF10_NXM:
104
0
    case OFPUTIL_P_OF10_NXM_TID:
105
0
        return OFP10_VERSION;
106
0
    case OFPUTIL_P_OF11_STD:
107
0
        return OFP11_VERSION;
108
0
    case OFPUTIL_P_OF12_OXM:
109
0
        return OFP12_VERSION;
110
0
    case OFPUTIL_P_OF13_OXM:
111
0
        return OFP13_VERSION;
112
0
    case OFPUTIL_P_OF14_OXM:
113
0
        return OFP14_VERSION;
114
0
    case OFPUTIL_P_OF15_OXM:
115
0
        return OFP15_VERSION;
116
0
    }
117
118
0
    OVS_NOT_REACHED();
119
0
}
120
121
/* Returns a bitmap of OpenFlow versions that are supported by at
122
 * least one of the 'protocols'. */
123
uint32_t
124
ofputil_protocols_to_version_bitmap(enum ofputil_protocol protocols)
125
0
{
126
0
    uint32_t bitmap = 0;
127
128
0
    for (; protocols; protocols = zero_rightmost_1bit(protocols)) {
129
0
        enum ofputil_protocol protocol = rightmost_1bit(protocols);
130
131
0
        bitmap |= 1u << ofputil_protocol_to_ofp_version(protocol);
132
0
    }
133
134
0
    return bitmap;
135
0
}
136
137
/* Returns the set of protocols that are supported on top of the
138
 * OpenFlow versions included in 'bitmap'. */
139
enum ofputil_protocol
140
ofputil_protocols_from_version_bitmap(uint32_t bitmap)
141
0
{
142
0
    enum ofputil_protocol protocols = 0;
143
144
0
    for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) {
145
0
        enum ofp_version version = rightmost_1bit_idx(bitmap);
146
147
0
        protocols |= ofputil_protocols_from_ofp_version(version);
148
0
    }
149
150
0
    return protocols;
151
0
}
152
153
/* Returns true if 'protocol' is a single OFPUTIL_P_* value, false
154
 * otherwise. */
155
bool
156
ofputil_protocol_is_valid(enum ofputil_protocol protocol)
157
0
{
158
0
    return protocol & OFPUTIL_P_ANY && is_pow2(protocol);
159
0
}
160
161
/* Returns the equivalent of 'protocol' with the Nicira flow_mod_table_id
162
 * extension turned on or off if 'enable' is true or false, respectively.
163
 *
164
 * This extension is only useful for protocols whose "standard" version does
165
 * not allow specific tables to be modified.  In particular, this is true of
166
 * OpenFlow 1.0.  In later versions of OpenFlow, a flow_mod request always
167
 * specifies a table ID and so there is no need for such an extension.  When
168
 * 'protocol' is such a protocol that doesn't need a flow_mod_table_id
169
 * extension, this function just returns its 'protocol' argument unchanged
170
 * regardless of the value of 'enable'.  */
171
enum ofputil_protocol
172
ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
173
0
{
174
0
    switch (protocol) {
175
0
    case OFPUTIL_P_OF10_STD:
176
0
    case OFPUTIL_P_OF10_STD_TID:
177
0
        return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD;
178
179
0
    case OFPUTIL_P_OF10_NXM:
180
0
    case OFPUTIL_P_OF10_NXM_TID:
181
0
        return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM;
182
183
0
    case OFPUTIL_P_OF11_STD:
184
0
        return OFPUTIL_P_OF11_STD;
185
186
0
    case OFPUTIL_P_OF12_OXM:
187
0
        return OFPUTIL_P_OF12_OXM;
188
189
0
    case OFPUTIL_P_OF13_OXM:
190
0
        return OFPUTIL_P_OF13_OXM;
191
192
0
    case OFPUTIL_P_OF14_OXM:
193
0
        return OFPUTIL_P_OF14_OXM;
194
195
0
    case OFPUTIL_P_OF15_OXM:
196
0
        return OFPUTIL_P_OF15_OXM;
197
198
0
    default:
199
0
        OVS_NOT_REACHED();
200
0
    }
201
0
}
202
203
/* Returns the "base" version of 'protocol'.  That is, if 'protocol' includes
204
 * some extension to a standard protocol version, the return value is the
205
 * standard version of that protocol without any extension.  If 'protocol' is a
206
 * standard protocol version, returns 'protocol' unchanged. */
207
enum ofputil_protocol
208
ofputil_protocol_to_base(enum ofputil_protocol protocol)
209
0
{
210
0
    return ofputil_protocol_set_tid(protocol, false);
211
0
}
212
213
/* Returns 'new_base' with any extensions taken from 'cur'. */
214
enum ofputil_protocol
215
ofputil_protocol_set_base(enum ofputil_protocol cur,
216
                          enum ofputil_protocol new_base)
217
0
{
218
0
    bool tid = (cur & OFPUTIL_P_TID) != 0;
219
220
0
    switch (new_base) {
221
0
    case OFPUTIL_P_OF10_STD:
222
0
    case OFPUTIL_P_OF10_STD_TID:
223
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid);
224
225
0
    case OFPUTIL_P_OF10_NXM:
226
0
    case OFPUTIL_P_OF10_NXM_TID:
227
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid);
228
229
0
    case OFPUTIL_P_OF11_STD:
230
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF11_STD, tid);
231
232
0
    case OFPUTIL_P_OF12_OXM:
233
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);
234
235
0
    case OFPUTIL_P_OF13_OXM:
236
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid);
237
238
0
    case OFPUTIL_P_OF14_OXM:
239
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF14_OXM, tid);
240
241
0
    case OFPUTIL_P_OF15_OXM:
242
0
        return ofputil_protocol_set_tid(OFPUTIL_P_OF15_OXM, tid);
243
244
0
    default:
245
0
        OVS_NOT_REACHED();
246
0
    }
247
0
}
248
249
/* Returns a string form of 'protocol', if a simple form exists (that is, if
250
 * 'protocol' is either a single protocol or it is a combination of protocols
251
 * that have a single abbreviation).  Otherwise, returns NULL. */
252
const char *
253
ofputil_protocol_to_string(enum ofputil_protocol protocol)
254
0
{
255
0
    const struct proto_abbrev *p;
256
257
    /* Use a "switch" statement for single-bit names so that we get a compiler
258
     * warning if we forget any. */
259
0
    switch (protocol) {
260
0
    case OFPUTIL_P_OF10_NXM:
261
0
        return "NXM-table_id";
262
263
0
    case OFPUTIL_P_OF10_NXM_TID:
264
0
        return "NXM+table_id";
265
266
0
    case OFPUTIL_P_OF10_STD:
267
0
        return "OpenFlow10-table_id";
268
269
0
    case OFPUTIL_P_OF10_STD_TID:
270
0
        return "OpenFlow10+table_id";
271
272
0
    case OFPUTIL_P_OF11_STD:
273
0
        return "OpenFlow11";
274
275
0
    case OFPUTIL_P_OF12_OXM:
276
0
        return "OXM-OpenFlow12";
277
278
0
    case OFPUTIL_P_OF13_OXM:
279
0
        return "OXM-OpenFlow13";
280
281
0
    case OFPUTIL_P_OF14_OXM:
282
0
        return "OXM-OpenFlow14";
283
284
0
    case OFPUTIL_P_OF15_OXM:
285
0
        return "OXM-OpenFlow15";
286
0
    }
287
288
    /* Check abbreviations. */
289
0
    for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
290
0
        if (protocol == p->protocol) {
291
0
            return p->name;
292
0
        }
293
0
    }
294
295
0
    return NULL;
296
0
}
297
298
/* Returns a string that represents 'protocols'.  The return value might be a
299
 * comma-separated list if 'protocols' doesn't have a simple name.  The return
300
 * value is "none" if 'protocols' is 0.
301
 *
302
 * The caller must free the returned string (with free()). */
303
char *
304
ofputil_protocols_to_string(enum ofputil_protocol protocols)
305
0
{
306
0
    struct ds s;
307
308
0
    ovs_assert(!(protocols & ~OFPUTIL_P_ANY));
309
0
    if (protocols == 0) {
310
0
        return xstrdup("none");
311
0
    }
312
313
0
    ds_init(&s);
314
0
    while (protocols) {
315
0
        const struct proto_abbrev *p;
316
0
        int i;
317
318
0
        if (s.length) {
319
0
            ds_put_char(&s, ',');
320
0
        }
321
322
0
        for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
323
0
            if ((protocols & p->protocol) == p->protocol) {
324
0
                ds_put_cstr(&s, p->name);
325
0
                protocols &= ~p->protocol;
326
0
                goto match;
327
0
            }
328
0
        }
329
330
0
        for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
331
0
            enum ofputil_protocol bit = 1u << i;
332
333
0
            if (protocols & bit) {
334
0
                ds_put_cstr(&s, ofputil_protocol_to_string(bit));
335
0
                protocols &= ~bit;
336
0
                goto match;
337
0
            }
338
0
        }
339
0
        OVS_NOT_REACHED();
340
341
0
    match: ;
342
0
    }
343
0
    return ds_steal_cstr(&s);
344
0
}
345
346
static enum ofputil_protocol
347
ofputil_protocol_from_string__(const char *s, size_t n)
348
0
{
349
0
    const struct proto_abbrev *p;
350
0
    int i;
351
352
0
    for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
353
0
        enum ofputil_protocol bit = 1u << i;
354
0
        const char *name = ofputil_protocol_to_string(bit);
355
356
0
        if (name && n == strlen(name) && !strncasecmp(s, name, n)) {
357
0
            return bit;
358
0
        }
359
0
    }
360
361
0
    for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
362
0
        if (n == strlen(p->name) && !strncasecmp(s, p->name, n)) {
363
0
            return p->protocol;
364
0
        }
365
0
    }
366
367
0
    return 0;
368
0
}
369
370
/* Returns the nonempty set of protocols represented by 's', which can be a
371
 * single protocol name or abbreviation or a comma-separated list of them.
372
 *
373
 * Aborts the program with an error message if 's' is invalid. */
374
enum ofputil_protocol
375
ofputil_protocols_from_string(const char *s)
376
0
{
377
0
    const char *orig_s = s;
378
0
    enum ofputil_protocol protocols;
379
380
0
    protocols = 0;
381
0
    while (*s) {
382
0
        enum ofputil_protocol p;
383
0
        size_t n;
384
385
0
        n = strcspn(s, ",");
386
0
        if (n == 0) {
387
0
            s++;
388
0
            continue;
389
0
        }
390
391
0
        p = ofputil_protocol_from_string__(s, n);
392
0
        if (!p) {
393
0
            ovs_fatal(0, "%.*s: unknown flow protocol", (int) n, s);
394
0
        }
395
0
        protocols |= p;
396
397
0
        s += n;
398
0
    }
399
400
0
    if (!protocols) {
401
0
        ovs_fatal(0, "%s: no flow protocol specified", orig_s);
402
0
    }
403
0
    return protocols;
404
0
}
405
406
enum ofp_version
407
ofputil_version_from_string(const char *s)
408
0
{
409
0
    if (!strcasecmp(s, "OpenFlow10")) {
410
0
        return OFP10_VERSION;
411
0
    }
412
0
    if (!strcasecmp(s, "OpenFlow11")) {
413
0
        return OFP11_VERSION;
414
0
    }
415
0
    if (!strcasecmp(s, "OpenFlow12")) {
416
0
        return OFP12_VERSION;
417
0
    }
418
0
    if (!strcasecmp(s, "OpenFlow13")) {
419
0
        return OFP13_VERSION;
420
0
    }
421
0
    if (!strcasecmp(s, "OpenFlow14")) {
422
0
        return OFP14_VERSION;
423
0
    }
424
0
    if (!strcasecmp(s, "OpenFlow15")) {
425
0
        return OFP15_VERSION;
426
0
    }
427
0
    return 0;
428
0
}
429
430
static bool
431
is_delimiter(unsigned char c)
432
0
{
433
0
    return isspace(c) || c == ',';
434
0
}
435
436
uint32_t
437
ofputil_versions_from_string(const char *s)
438
0
{
439
0
    size_t i = 0;
440
0
    uint32_t bitmap = 0;
441
442
0
    while (s[i]) {
443
0
        size_t j;
444
0
        int version;
445
0
        char *key;
446
447
0
        if (is_delimiter(s[i])) {
448
0
            i++;
449
0
            continue;
450
0
        }
451
0
        j = 0;
452
0
        while (s[i + j] && !is_delimiter(s[i + j])) {
453
0
            j++;
454
0
        }
455
0
        key = xmemdup0(s + i, j);
456
0
        version = ofputil_version_from_string(key);
457
0
        if (!version) {
458
0
            VLOG_FATAL("Unknown OpenFlow version: \"%s\"", key);
459
0
        }
460
0
        free(key);
461
0
        bitmap |= 1u << version;
462
0
        i += j;
463
0
    }
464
465
0
    return bitmap;
466
0
}
467
468
uint32_t
469
ofputil_versions_from_strings(char ** const s, size_t count)
470
0
{
471
0
    uint32_t bitmap = 0;
472
473
0
    while (count--) {
474
0
        int version = ofputil_version_from_string(s[count]);
475
0
        if (!version) {
476
0
            VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]);
477
0
        } else {
478
0
            bitmap |= 1u << version;
479
0
        }
480
0
    }
481
482
0
    return bitmap;
483
0
}
484
485
const char *
486
ofputil_version_to_string(enum ofp_version ofp_version)
487
0
{
488
0
    switch (ofp_version) {
489
0
    case OFP10_VERSION:
490
0
        return "OpenFlow10";
491
0
    case OFP11_VERSION:
492
0
        return "OpenFlow11";
493
0
    case OFP12_VERSION:
494
0
        return "OpenFlow12";
495
0
    case OFP13_VERSION:
496
0
        return "OpenFlow13";
497
0
    case OFP14_VERSION:
498
0
        return "OpenFlow14";
499
0
    case OFP15_VERSION:
500
0
        return "OpenFlow15";
501
0
    default:
502
0
        OVS_NOT_REACHED();
503
0
    }
504
0
}
505
506
void
507
ofputil_format_version(struct ds *msg, enum ofp_version version)
508
0
{
509
0
    ds_put_format(msg, "0x%02x", version);
510
0
}
511
512
void
513
ofputil_format_version_name(struct ds *msg, enum ofp_version version)
514
0
{
515
0
    ds_put_cstr(msg, ofputil_version_to_string(version));
516
0
}
517
518
static void
519
ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap,
520
                                void (*format_version)(struct ds *msg,
521
                                                       enum ofp_version))
522
0
{
523
0
    while (bitmap) {
524
0
        format_version(msg, raw_ctz(bitmap));
525
0
        bitmap = zero_rightmost_1bit(bitmap);
526
0
        if (bitmap) {
527
0
            ds_put_cstr(msg, ", ");
528
0
        }
529
0
    }
530
0
}
531
532
void
533
ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap)
534
0
{
535
0
    ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version);
536
0
}
537
538
void
539
ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap)
540
0
{
541
0
    ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version_name);
542
0
}
543

544
/* Returns an OpenFlow message that, sent on an OpenFlow connection whose
545
 * protocol is 'current', at least partly transitions the protocol to 'want'.
546
 * Stores in '*next' the protocol that will be in effect on the OpenFlow
547
 * connection if the switch processes the returned message correctly.  (If
548
 * '*next != want' then the caller will have to iterate.)
549
 *
550
 * If 'current == want', or if it is not possible to transition from 'current'
551
 * to 'want' (because, for example, 'current' and 'want' use different OpenFlow
552
 * protocol versions), returns NULL and stores 'current' in '*next'. */
553
struct ofpbuf *
554
ofputil_encode_set_protocol(enum ofputil_protocol current,
555
                            enum ofputil_protocol want,
556
                            enum ofputil_protocol *next)
557
0
{
558
0
    enum ofp_version cur_version, want_version;
559
0
    enum ofputil_protocol cur_base, want_base;
560
0
    bool cur_tid, want_tid;
561
562
0
    cur_version = ofputil_protocol_to_ofp_version(current);
563
0
    want_version = ofputil_protocol_to_ofp_version(want);
564
0
    if (cur_version != want_version) {
565
0
        *next = current;
566
0
        return NULL;
567
0
    }
568
569
0
    cur_base = ofputil_protocol_to_base(current);
570
0
    want_base = ofputil_protocol_to_base(want);
571
0
    if (cur_base != want_base) {
572
0
        *next = ofputil_protocol_set_base(current, want_base);
573
0
        switch (want_base) {
574
0
        case OFPUTIL_P_OF10_NXM:
575
0
        case OFPUTIL_P_OF10_STD:
576
0
            return ofputil_encode_nx_set_flow_format(want_base);
577
578
0
        case OFPUTIL_P_OF11_STD:
579
0
        case OFPUTIL_P_OF12_OXM:
580
0
        case OFPUTIL_P_OF13_OXM:
581
0
        case OFPUTIL_P_OF14_OXM:
582
0
        case OFPUTIL_P_OF15_OXM:
583
            /* There is only one variant of each OpenFlow 1.1+ protocol, and we
584
             * verified above that we're not trying to change versions. */
585
0
            OVS_NOT_REACHED();
586
587
0
        case OFPUTIL_P_OF10_STD_TID:
588
0
        case OFPUTIL_P_OF10_NXM_TID:
589
0
            OVS_NOT_REACHED();
590
0
        }
591
0
    }
592
593
0
    cur_tid = (current & OFPUTIL_P_TID) != 0;
594
0
    want_tid = (want & OFPUTIL_P_TID) != 0;
595
0
    if (cur_tid != want_tid) {
596
0
        *next = ofputil_protocol_set_tid(current, want_tid);
597
0
        return ofputil_encode_nx_flow_mod_table_id(want_tid);
598
0
    }
599
600
0
    ovs_assert(current == want);
601
602
0
    *next = current;
603
0
    return NULL;
604
0
}
605

606
enum nx_flow_format {
607
    NXFF_OPENFLOW10 = 0,         /* Standard OpenFlow 1.0 compatible. */
608
    NXFF_NXM = 2                 /* Nicira extended match. */
609
};
610
611
/* Returns an NXT_SET_FLOW_FORMAT message that can be used to set the flow
612
 * format to 'protocol'.  */
613
struct ofpbuf *
614
ofputil_encode_nx_set_flow_format(enum ofputil_protocol protocol)
615
0
{
616
0
    struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_SET_FLOW_FORMAT,
617
0
                                      OFP10_VERSION, 0);
618
0
    ovs_be32 *nxff = ofpbuf_put_uninit(msg, sizeof *nxff);
619
0
    if (protocol == OFPUTIL_P_OF10_STD) {
620
0
        *nxff = htonl(NXFF_OPENFLOW10);
621
0
    } else if (protocol == OFPUTIL_P_OF10_NXM) {
622
0
        *nxff = htonl(NXFF_NXM);
623
0
    } else {
624
0
        OVS_NOT_REACHED();
625
0
    }
626
627
0
    return msg;
628
0
}
629
630
/* Returns the protocol specified in the NXT_SET_FLOW_FORMAT message at 'oh'
631
 * (either OFPUTIL_P_OF10_STD or OFPUTIL_P_OF10_NXM) or 0 if the message is
632
 * invalid. */
633
enum ofputil_protocol
634
ofputil_decode_nx_set_flow_format(const struct ofp_header *oh)
635
0
{
636
0
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
637
0
    ovs_assert(ofpraw_pull_assert(&b) == OFPRAW_NXT_SET_FLOW_FORMAT);
638
639
0
    ovs_be32 *flow_formatp = ofpbuf_pull(&b, sizeof *flow_formatp);
640
0
    uint32_t flow_format = ntohl(*flow_formatp);
641
0
    switch (flow_format) {
642
0
    case NXFF_OPENFLOW10:
643
0
        return OFPUTIL_P_OF10_STD;
644
645
0
    case NXFF_NXM:
646
0
        return OFPUTIL_P_OF10_NXM;
647
648
0
    default:
649
0
        VLOG_WARN_RL(&rl, "NXT_SET_FLOW_FORMAT message specified invalid "
650
0
                     "flow format %"PRIu32, flow_format);
651
0
        return 0;
652
0
    }
653
0
}
654

655
/* These functions work with the Open vSwitch extension feature called
656
 * "flow_mod_table_id", which allows a controller to specify the OpenFlow table
657
 * to which a flow should be added, instead of having the switch decide which
658
 * table is most appropriate as required by OpenFlow 1.0.  Because NXM was
659
 * designed as an extension to OpenFlow 1.0, the extension applies equally to
660
 * ofp10_flow_mod and nx_flow_mod.  By default, the extension is disabled.
661
 *
662
 * When this feature is enabled, Open vSwitch treats struct ofp10_flow_mod's
663
 * and struct nx_flow_mod's 16-bit 'command' member as two separate fields.
664
 * The upper 8 bits are used as the table ID, the lower 8 bits specify the
665
 * command as usual.  A table ID of 0xff is treated like a wildcarded table ID.
666
 *
667
 * The specific treatment of the table ID depends on the type of flow mod:
668
 *
669
 *    - OFPFC_ADD: Given a specific table ID, the flow is always placed in that
670
 *      table.  If an identical flow already exists in that table only, then it
671
 *      is replaced.  If the flow cannot be placed in the specified table,
672
 *      either because the table is full or because the table cannot support
673
 *      flows of the given type, the switch replies with an OFPFMFC_TABLE_FULL
674
 *      error.  (A controller can distinguish these cases by comparing the
675
 *      current and maximum number of entries reported in ofp_table_stats.)
676
 *
677
 *      If the table ID is wildcarded, the switch picks an appropriate table
678
 *      itself.  If an identical flow already exist in the selected flow table,
679
 *      then it is replaced.  The choice of table might depend on the flows
680
 *      that are already in the switch; for example, if one table fills up then
681
 *      the switch might fall back to another one.
682
 *
683
 *    - OFPFC_MODIFY, OFPFC_DELETE: Given a specific table ID, only flows
684
 *      within that table are matched and modified or deleted.  If the table ID
685
 *      is wildcarded, flows within any table may be matched and modified or
686
 *      deleted.
687
 *
688
 *    - OFPFC_MODIFY_STRICT, OFPFC_DELETE_STRICT: Given a specific table ID,
689
 *      only a flow within that table may be matched and modified or deleted.
690
 *      If the table ID is wildcarded and exactly one flow within any table
691
 *      matches, then it is modified or deleted; if flows in more than one
692
 *      table match, then none is modified or deleted.
693
 */
694
695
/* Returns an OpenFlow message that can be used to turn the flow_mod_table_id
696
 * extension on or off (according to 'enable'). */
697
struct ofpbuf *
698
ofputil_encode_nx_flow_mod_table_id(bool enable)
699
0
{
700
0
    struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD_TABLE_ID,
701
0
                                      OFP10_VERSION, 0);
702
0
    uint8_t *p = ofpbuf_put_zeros(msg, 8);
703
0
    *p = enable;
704
0
    return msg;
705
0
}
706
707
/* Decodes the NXT_FLOW_MOD_TABLE_ID message at 'oh'.  Returns the message's
708
 * argument, that is, whether the flow_mod_table_id feature should be
709
 * enabled. */
710
bool
711
ofputil_decode_nx_flow_mod_table_id(const struct ofp_header *oh)
712
0
{
713
0
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
714
0
    ovs_assert(ofpraw_pull_assert(&b) == OFPRAW_NXT_FLOW_MOD_TABLE_ID);
715
0
    uint8_t *enable = ofpbuf_pull(&b, 8);
716
0
    return *enable != 0;
717
0
}