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-util.h"
22 #include <sys/types.h>
23 #include <netinet/in.h>
24 #include <netinet/icmp6.h>
28 #include "byte-order.h"
29 #include "classifier.h"
31 #include "multipath.h"
35 #include "openflow/netronome-ext.h"
36 #include "openvswitch/dynamic-string.h"
37 #include "openvswitch/json.h"
38 #include "openvswitch/meta-flow.h"
39 #include "openvswitch/ofp-actions.h"
40 #include "openvswitch/ofp-errors.h"
41 #include "openvswitch/ofp-msgs.h"
42 #include "openvswitch/ofp-print.h"
43 #include "openvswitch/ofp-prop.h"
44 #include "openvswitch/ofpbuf.h"
45 #include "openvswitch/type-props.h"
46 #include "openvswitch/vlog.h"
47 #include "openflow/intel-ext.h"
50 #include "tun-metadata.h"
51 #include "unaligned.h"
55 VLOG_DEFINE_THIS_MODULE(ofp_util
);
57 /* Rate limit for OpenFlow message parse errors. These always indicate a bug
58 * in the peer and so there's not much point in showing a lot of them. */
59 static struct vlog_rate_limit bad_ofmsg_rl
= VLOG_RATE_LIMIT_INIT(1, 5);
62 ofputil_decode_hello_bitmap(const struct ofp_hello_elem_header
*oheh
,
63 uint32_t *allowed_versionsp
)
65 uint16_t bitmap_len
= ntohs(oheh
->length
) - sizeof *oheh
;
66 const ovs_be32
*bitmap
= ALIGNED_CAST(const ovs_be32
*, oheh
+ 1);
67 uint32_t allowed_versions
;
69 if (!bitmap_len
|| bitmap_len
% sizeof *bitmap
) {
73 /* Only use the first 32-bit element of the bitmap as that is all the
74 * current implementation supports. Subsequent elements are ignored which
75 * should have no effect on session negotiation until Open vSwitch supports
76 * wire-protocol versions greater than 31.
78 allowed_versions
= ntohl(bitmap
[0]);
80 if (allowed_versions
& 1) {
81 /* There's no OpenFlow version 0. */
82 VLOG_WARN_RL(&bad_ofmsg_rl
, "peer claims to support invalid OpenFlow "
84 allowed_versions
&= ~1u;
87 if (!allowed_versions
) {
88 VLOG_WARN_RL(&bad_ofmsg_rl
, "peer does not support any OpenFlow "
89 "version (between 0x01 and 0x1f)");
93 *allowed_versionsp
= allowed_versions
;
98 version_bitmap_from_version(uint8_t ofp_version
)
100 return ((ofp_version
< 32 ? 1u << ofp_version
: 0) - 1) << 1;
103 /* Decodes OpenFlow OFPT_HELLO message 'oh', storing into '*allowed_versions'
104 * the set of OpenFlow versions for which 'oh' announces support.
106 * Because of how OpenFlow defines OFPT_HELLO messages, this function is always
107 * successful, and thus '*allowed_versions' is always initialized. However, it
108 * returns false if 'oh' contains some data that could not be fully understood,
109 * true if 'oh' was completely parsed. */
111 ofputil_decode_hello(const struct ofp_header
*oh
, uint32_t *allowed_versions
)
113 struct ofpbuf msg
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
114 ofpbuf_pull(&msg
, sizeof *oh
);
116 *allowed_versions
= version_bitmap_from_version(oh
->version
);
120 const struct ofp_hello_elem_header
*oheh
;
123 if (msg
.size
< sizeof *oheh
) {
128 len
= ntohs(oheh
->length
);
129 if (len
< sizeof *oheh
|| !ofpbuf_try_pull(&msg
, ROUND_UP(len
, 8))) {
133 if (oheh
->type
!= htons(OFPHET_VERSIONBITMAP
)
134 || !ofputil_decode_hello_bitmap(oheh
, allowed_versions
)) {
142 /* Returns true if 'allowed_versions' needs to be accompanied by a version
143 * bitmap to be correctly expressed in an OFPT_HELLO message. */
145 should_send_version_bitmap(uint32_t allowed_versions
)
147 return !is_pow2((allowed_versions
>> 1) + 1);
150 /* Create an OFPT_HELLO message that expresses support for the OpenFlow
151 * versions in the 'allowed_versions' bitmaps and returns the message. */
153 ofputil_encode_hello(uint32_t allowed_versions
)
155 enum ofp_version ofp_version
;
158 ofp_version
= leftmost_1bit_idx(allowed_versions
);
159 msg
= ofpraw_alloc(OFPRAW_OFPT_HELLO
, ofp_version
, 0);
161 if (should_send_version_bitmap(allowed_versions
)) {
162 struct ofp_hello_elem_header
*oheh
;
165 map_len
= sizeof allowed_versions
;
166 oheh
= ofpbuf_put_zeros(msg
, ROUND_UP(map_len
+ sizeof *oheh
, 8));
167 oheh
->type
= htons(OFPHET_VERSIONBITMAP
);
168 oheh
->length
= htons(map_len
+ sizeof *oheh
);
169 *ALIGNED_CAST(ovs_be32
*, oheh
+ 1) = htonl(allowed_versions
);
171 ofpmsg_update_length(msg
);
178 ofputil_hello_format(struct ds
*string
, const struct ofp_header
*oh
)
180 uint32_t allowed_versions
;
183 ok
= ofputil_decode_hello(oh
, &allowed_versions
);
185 ds_put_cstr(string
, "\n version bitmap: ");
186 ofputil_format_version_bitmap(string
, allowed_versions
);
189 ds_put_cstr(string
, "\n unknown data in hello:\n");
190 ds_put_hex_dump(string
, oh
, ntohs(oh
->length
), 0, true);
194 /* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
196 ofputil_encode_echo_request(enum ofp_version ofp_version
)
198 return ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST
, ofp_version
,
202 /* Creates and returns an OFPT_ECHO_REPLY message matching the
203 * OFPT_ECHO_REQUEST message in 'rq'. */
205 ofputil_encode_echo_reply(const struct ofp_header
*rq
)
207 struct ofpbuf rq_buf
= ofpbuf_const_initializer(rq
, ntohs(rq
->length
));
208 ofpraw_pull_assert(&rq_buf
);
210 struct ofpbuf
*reply
= ofpraw_alloc_reply(OFPRAW_OFPT_ECHO_REPLY
,
212 ofpbuf_put(reply
, rq_buf
.data
, rq_buf
.size
);
217 ofputil_encode_barrier_request(enum ofp_version ofp_version
)
221 switch (ofp_version
) {
227 type
= OFPRAW_OFPT11_BARRIER_REQUEST
;
231 type
= OFPRAW_OFPT10_BARRIER_REQUEST
;
238 return ofpraw_alloc(type
, ofp_version
, 0);