]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ofp-util.c
Add change tracking documentation
[mirror_ovs.git] / lib / ofp-util.c
CommitLineData
fa37b408 1/*
6a5490c6 2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
fa37b408
BP
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>
03e1125c 18#include <ctype.h>
dc4762ed 19#include <errno.h>
fa37b408 20#include <inttypes.h>
6ca00f6f
ETN
21#include <sys/types.h>
22#include <netinet/in.h>
b459a924 23#include <netinet/icmp6.h>
fa37b408 24#include <stdlib.h>
25d436fb 25#include "bitmap.h"
daff3353 26#include "bundle.h"
10a24935 27#include "byte-order.h"
d8ae4d67 28#include "classifier.h"
75a75043 29#include "learn.h"
9e1fd49b 30#include "multipath.h"
6c038611 31#include "netdev.h"
b6c9e612 32#include "nx-match.h"
18ac06d3 33#include "id-pool.h"
d271907f
BW
34#include "openflow/netronome-ext.h"
35#include "openvswitch/dynamic-string.h"
36#include "openvswitch/meta-flow.h"
b598f214 37#include "openvswitch/ofp-actions.h"
d271907f
BW
38#include "openvswitch/ofp-errors.h"
39#include "openvswitch/ofp-msgs.h"
25d436fb 40#include "openvswitch/ofp-print.h"
66bd43fa 41#include "openvswitch/ofp-prop.h"
f4248336 42#include "openvswitch/ofp-util.h"
64c96779 43#include "openvswitch/ofpbuf.h"
d271907f
BW
44#include "openvswitch/type-props.h"
45#include "openvswitch/vlog.h"
fa37b408 46#include "packets.h"
9bfe9334 47#include "pktbuf.h"
fa37b408 48#include "random.h"
6159c531 49#include "tun-metadata.h"
4ffd1b43 50#include "unaligned.h"
d5dc60f0 51#include "uuid.h"
fa37b408 52
d98e6007 53VLOG_DEFINE_THIS_MODULE(ofp_util);
fa37b408
BP
54
55/* Rate limit for OpenFlow message parse errors. These always indicate a bug
56 * in the peer and so there's not much point in showing a lot of them. */
57static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5);
58
de7d3c07
SJ
59static enum ofputil_table_vacancy ofputil_decode_table_vacancy(
60 ovs_be32 config, enum ofp_version);
82c22d34
BP
61static enum ofputil_table_eviction ofputil_decode_table_eviction(
62 ovs_be32 config, enum ofp_version);
63static ovs_be32 ofputil_encode_table_config(enum ofputil_table_miss,
64 enum ofputil_table_eviction,
de7d3c07 65 enum ofputil_table_vacancy,
82c22d34 66 enum ofp_version);
3c1bb396 67
0596e897
BP
68/* Given the wildcard bit count in the least-significant 6 of 'wcbits', returns
69 * an IP netmask with a 1 in each bit that must match and a 0 in each bit that
70 * is wildcarded.
71 *
72 * The bits in 'wcbits' are in the format used in enum ofp_flow_wildcards: 0
73 * is exact match, 1 ignores the LSB, 2 ignores the 2 least-significant bits,
74 * ..., 32 and higher wildcard the entire field. This is the *opposite* of the
75 * usual convention where e.g. /24 indicates that 8 bits (not 24 bits) are
76 * wildcarded. */
77ovs_be32
78ofputil_wcbits_to_netmask(int wcbits)
79{
80 wcbits &= 0x3f;
81 return wcbits < 32 ? htonl(~((1u << wcbits) - 1)) : 0;
82}
83
84/* Given the IP netmask 'netmask', returns the number of bits of the IP address
c08201d6
BP
85 * that it wildcards, that is, the number of 0-bits in 'netmask', a number
86 * between 0 and 32 inclusive.
87 *
88 * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will
89 * still be in the valid range but isn't otherwise meaningful. */
0596e897
BP
90int
91ofputil_netmask_to_wcbits(ovs_be32 netmask)
92{
aad29cd1 93 return 32 - ip_count_cidr_bits(netmask);
0596e897
BP
94}
95
eec25dc1 96/* Converts the OpenFlow 1.0 wildcards in 'ofpfw' (OFPFW10_*) into a
81a76618 97 * flow_wildcards in 'wc' for use in struct match. It is the caller's
eec25dc1
BP
98 * responsibility to handle the special case where the flow match's dl_vlan is
99 * set to OFP_VLAN_NONE. */
7286b1e1 100void
eec25dc1 101ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
d8ae4d67 102{
ffe4c74f 103 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 35);
a877206f 104
81a76618 105 /* Initialize most of wc. */
f9ba8dad 106 flow_wildcards_init_catchall(wc);
bad68a99 107
0bdc4bec 108 if (!(ofpfw & OFPFW10_IN_PORT)) {
4e022ec0 109 wc->masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
27cafc5f 110 }
5d9499c4
BP
111
112 if (!(ofpfw & OFPFW10_NW_TOS)) {
26720e24 113 wc->masks.nw_tos |= IP_DSCP_MASK;
d8ae4d67 114 }
7257b535 115
851d3105 116 if (!(ofpfw & OFPFW10_NW_PROTO)) {
26720e24 117 wc->masks.nw_proto = UINT8_MAX;
851d3105 118 }
26720e24
BP
119 wc->masks.nw_src = ofputil_wcbits_to_netmask(ofpfw
120 >> OFPFW10_NW_SRC_SHIFT);
121 wc->masks.nw_dst = ofputil_wcbits_to_netmask(ofpfw
122 >> OFPFW10_NW_DST_SHIFT);
d8ae4d67 123
eec25dc1 124 if (!(ofpfw & OFPFW10_TP_SRC)) {
b8266395 125 wc->masks.tp_src = OVS_BE16_MAX;
73f33563 126 }
eec25dc1 127 if (!(ofpfw & OFPFW10_TP_DST)) {
b8266395 128 wc->masks.tp_dst = OVS_BE16_MAX;
73f33563
BP
129 }
130
eec25dc1 131 if (!(ofpfw & OFPFW10_DL_SRC)) {
74ff3298 132 WC_MASK_FIELD(wc, dl_src);
73c0ce34 133 }
eec25dc1 134 if (!(ofpfw & OFPFW10_DL_DST)) {
74ff3298 135 WC_MASK_FIELD(wc, dl_dst);
d8ae4d67 136 }
e2170cff 137 if (!(ofpfw & OFPFW10_DL_TYPE)) {
b8266395 138 wc->masks.dl_type = OVS_BE16_MAX;
e2170cff 139 }
d8ae4d67 140
eb6f28db 141 /* VLAN TCI mask. */
eec25dc1 142 if (!(ofpfw & OFPFW10_DL_VLAN_PCP)) {
26720e24 143 wc->masks.vlan_tci |= htons(VLAN_PCP_MASK | VLAN_CFI);
eb6f28db 144 }
eec25dc1 145 if (!(ofpfw & OFPFW10_DL_VLAN)) {
26720e24 146 wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
eb6f28db
BP
147 }
148}
149
81a76618 150/* Converts the ofp10_match in 'ofmatch' into a struct match in 'match'. */
eb6f28db 151void
81a76618
BP
152ofputil_match_from_ofp10_match(const struct ofp10_match *ofmatch,
153 struct match *match)
154{
155 uint32_t ofpfw = ntohl(ofmatch->wildcards) & OFPFW10_ALL;
156
157 /* Initialize match->wc. */
296e07ac 158 memset(&match->flow, 0, sizeof match->flow);
81a76618
BP
159 ofputil_wildcard_from_ofpfw10(ofpfw, &match->wc);
160
161 /* Initialize most of match->flow. */
162 match->flow.nw_src = ofmatch->nw_src;
163 match->flow.nw_dst = ofmatch->nw_dst;
4e022ec0 164 match->flow.in_port.ofp_port = u16_to_ofp(ntohs(ofmatch->in_port));
81a76618
BP
165 match->flow.dl_type = ofputil_dl_type_from_openflow(ofmatch->dl_type);
166 match->flow.tp_src = ofmatch->tp_src;
167 match->flow.tp_dst = ofmatch->tp_dst;
74ff3298
JR
168 match->flow.dl_src = ofmatch->dl_src;
169 match->flow.dl_dst = ofmatch->dl_dst;
81a76618
BP
170 match->flow.nw_tos = ofmatch->nw_tos & IP_DSCP_MASK;
171 match->flow.nw_proto = ofmatch->nw_proto;
d8ae4d67 172
66642cb4 173 /* Translate VLANs. */
0c436519 174 if (!(ofpfw & OFPFW10_DL_VLAN) &&
81a76618 175 ofmatch->dl_vlan == htons(OFP10_VLAN_NONE)) {
47271d0d
BP
176 /* Match only packets without 802.1Q header.
177 *
eec25dc1 178 * When OFPFW10_DL_VLAN_PCP is wildcarded, this is obviously correct.
47271d0d 179 *
eec25dc1 180 * If OFPFW10_DL_VLAN_PCP is matched, the flow match is contradictory,
47271d0d
BP
181 * because we can't have a specific PCP without an 802.1Q header.
182 * However, older versions of OVS treated this as matching packets
183 * withut an 802.1Q header, so we do here too. */
81a76618
BP
184 match->flow.vlan_tci = htons(0);
185 match->wc.masks.vlan_tci = htons(0xffff);
47271d0d
BP
186 } else {
187 ovs_be16 vid, pcp, tci;
bf062576 188 uint16_t hpcp;
47271d0d 189
81a76618 190 vid = ofmatch->dl_vlan & htons(VLAN_VID_MASK);
bf062576
YT
191 hpcp = (ofmatch->dl_vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK;
192 pcp = htons(hpcp);
47271d0d 193 tci = vid | pcp | htons(VLAN_CFI);
81a76618 194 match->flow.vlan_tci = tci & match->wc.masks.vlan_tci;
66642cb4
BP
195 }
196
d8ae4d67 197 /* Clean up. */
81a76618 198 match_zero_wildcarded_fields(match);
d8ae4d67
BP
199}
200
81a76618 201/* Convert 'match' into the OpenFlow 1.0 match structure 'ofmatch'. */
d8ae4d67 202void
81a76618
BP
203ofputil_match_to_ofp10_match(const struct match *match,
204 struct ofp10_match *ofmatch)
d8ae4d67 205{
81a76618 206 const struct flow_wildcards *wc = &match->wc;
eeba8e4f 207 uint32_t ofpfw;
d8ae4d67 208
66642cb4 209 /* Figure out most OpenFlow wildcards. */
27cafc5f 210 ofpfw = 0;
4e022ec0 211 if (!wc->masks.in_port.ofp_port) {
27cafc5f
BP
212 ofpfw |= OFPFW10_IN_PORT;
213 }
26720e24 214 if (!wc->masks.dl_type) {
27cafc5f
BP
215 ofpfw |= OFPFW10_DL_TYPE;
216 }
26720e24 217 if (!wc->masks.nw_proto) {
27cafc5f
BP
218 ofpfw |= OFPFW10_NW_PROTO;
219 }
26720e24 220 ofpfw |= (ofputil_netmask_to_wcbits(wc->masks.nw_src)
eec25dc1 221 << OFPFW10_NW_SRC_SHIFT);
26720e24 222 ofpfw |= (ofputil_netmask_to_wcbits(wc->masks.nw_dst)
eec25dc1 223 << OFPFW10_NW_DST_SHIFT);
26720e24 224 if (!(wc->masks.nw_tos & IP_DSCP_MASK)) {
eec25dc1 225 ofpfw |= OFPFW10_NW_TOS;
d8ae4d67 226 }
26720e24 227 if (!wc->masks.tp_src) {
eec25dc1 228 ofpfw |= OFPFW10_TP_SRC;
73f33563 229 }
26720e24 230 if (!wc->masks.tp_dst) {
eec25dc1 231 ofpfw |= OFPFW10_TP_DST;
73f33563 232 }
26720e24 233 if (eth_addr_is_zero(wc->masks.dl_src)) {
eec25dc1 234 ofpfw |= OFPFW10_DL_SRC;
73c0ce34 235 }
26720e24 236 if (eth_addr_is_zero(wc->masks.dl_dst)) {
eec25dc1 237 ofpfw |= OFPFW10_DL_DST;
73c0ce34 238 }
ff9d3826 239
66642cb4 240 /* Translate VLANs. */
81a76618
BP
241 ofmatch->dl_vlan = htons(0);
242 ofmatch->dl_vlan_pcp = 0;
243 if (match->wc.masks.vlan_tci == htons(0)) {
eec25dc1 244 ofpfw |= OFPFW10_DL_VLAN | OFPFW10_DL_VLAN_PCP;
81a76618
BP
245 } else if (match->wc.masks.vlan_tci & htons(VLAN_CFI)
246 && !(match->flow.vlan_tci & htons(VLAN_CFI))) {
247 ofmatch->dl_vlan = htons(OFP10_VLAN_NONE);
66642cb4 248 } else {
81a76618 249 if (!(match->wc.masks.vlan_tci & htons(VLAN_VID_MASK))) {
eec25dc1 250 ofpfw |= OFPFW10_DL_VLAN;
66642cb4 251 } else {
81a76618 252 ofmatch->dl_vlan = htons(vlan_tci_to_vid(match->flow.vlan_tci));
66642cb4
BP
253 }
254
81a76618 255 if (!(match->wc.masks.vlan_tci & htons(VLAN_PCP_MASK))) {
eec25dc1 256 ofpfw |= OFPFW10_DL_VLAN_PCP;
66642cb4 257 } else {
81a76618 258 ofmatch->dl_vlan_pcp = vlan_tci_to_pcp(match->flow.vlan_tci);
66642cb4
BP
259 }
260 }
261
262 /* Compose most of the match structure. */
81a76618 263 ofmatch->wildcards = htonl(ofpfw);
4e022ec0 264 ofmatch->in_port = htons(ofp_to_u16(match->flow.in_port.ofp_port));
74ff3298
JR
265 ofmatch->dl_src = match->flow.dl_src;
266 ofmatch->dl_dst = match->flow.dl_dst;
81a76618
BP
267 ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
268 ofmatch->nw_src = match->flow.nw_src;
269 ofmatch->nw_dst = match->flow.nw_dst;
270 ofmatch->nw_tos = match->flow.nw_tos & IP_DSCP_MASK;
271 ofmatch->nw_proto = match->flow.nw_proto;
272 ofmatch->tp_src = match->flow.tp_src;
273 ofmatch->tp_dst = match->flow.tp_dst;
274 memset(ofmatch->pad1, '\0', sizeof ofmatch->pad1);
275 memset(ofmatch->pad2, '\0', sizeof ofmatch->pad2);
d8ae4d67
BP
276}
277
aa319503 278enum ofperr
81a76618
BP
279ofputil_pull_ofp11_match(struct ofpbuf *buf, struct match *match,
280 uint16_t *padded_match_len)
aa319503 281{
6fd6ed71 282 struct ofp11_match_header *omh = buf->data;
36a16881 283 uint16_t match_len;
aa319503 284
6fd6ed71 285 if (buf->size < sizeof *omh) {
aa319503
BP
286 return OFPERR_OFPBMC_BAD_LEN;
287 }
288
36a16881
SH
289 match_len = ntohs(omh->length);
290
aa319503 291 switch (ntohs(omh->type)) {
36a16881
SH
292 case OFPMT_STANDARD: {
293 struct ofp11_match *om;
294
6fd6ed71 295 if (match_len != sizeof *om || buf->size < sizeof *om) {
aa319503
BP
296 return OFPERR_OFPBMC_BAD_LEN;
297 }
298 om = ofpbuf_pull(buf, sizeof *om);
36a16881
SH
299 if (padded_match_len) {
300 *padded_match_len = match_len;
301 }
81a76618 302 return ofputil_match_from_ofp11_match(om, match);
36a16881
SH
303 }
304
305 case OFPMT_OXM:
306 if (padded_match_len) {
307 *padded_match_len = ROUND_UP(match_len, 8);
308 }
81a76618 309 return oxm_pull_match(buf, match);
aa319503
BP
310
311 default:
312 return OFPERR_OFPBMC_BAD_TYPE;
313 }
314}
315
3f0f48cf
YT
316/* Converts the ofp11_match in 'ofmatch' into a struct match in 'match'.
317 * Returns 0 if successful, otherwise an OFPERR_* value. */
410698cf 318enum ofperr
81a76618
BP
319ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
320 struct match *match)
410698cf 321{
81a76618 322 uint16_t wc = ntohl(ofmatch->wildcards);
8087f5ff 323 bool ipv4, arp, rarp;
410698cf 324
81a76618 325 match_init_catchall(match);
410698cf
BP
326
327 if (!(wc & OFPFW11_IN_PORT)) {
4e022ec0 328 ofp_port_t ofp_port;
410698cf
BP
329 enum ofperr error;
330
81a76618 331 error = ofputil_port_from_ofp11(ofmatch->in_port, &ofp_port);
410698cf
BP
332 if (error) {
333 return OFPERR_OFPBMC_BAD_VALUE;
334 }
81a76618 335 match_set_in_port(match, ofp_port);
410698cf
BP
336 }
337
74ff3298
JR
338 match_set_dl_src_masked(match, ofmatch->dl_src,
339 eth_addr_invert(ofmatch->dl_src_mask));
340 match_set_dl_dst_masked(match, ofmatch->dl_dst,
341 eth_addr_invert(ofmatch->dl_dst_mask));
410698cf
BP
342
343 if (!(wc & OFPFW11_DL_VLAN)) {
81a76618 344 if (ofmatch->dl_vlan == htons(OFPVID11_NONE)) {
410698cf 345 /* Match only packets without a VLAN tag. */
81a76618 346 match->flow.vlan_tci = htons(0);
b8266395 347 match->wc.masks.vlan_tci = OVS_BE16_MAX;
410698cf 348 } else {
81a76618 349 if (ofmatch->dl_vlan == htons(OFPVID11_ANY)) {
410698cf 350 /* Match any packet with a VLAN tag regardless of VID. */
81a76618
BP
351 match->flow.vlan_tci = htons(VLAN_CFI);
352 match->wc.masks.vlan_tci = htons(VLAN_CFI);
353 } else if (ntohs(ofmatch->dl_vlan) < 4096) {
410698cf 354 /* Match only packets with the specified VLAN VID. */
81a76618
BP
355 match->flow.vlan_tci = htons(VLAN_CFI) | ofmatch->dl_vlan;
356 match->wc.masks.vlan_tci = htons(VLAN_CFI | VLAN_VID_MASK);
410698cf
BP
357 } else {
358 /* Invalid VID. */
359 return OFPERR_OFPBMC_BAD_VALUE;
360 }
361
362 if (!(wc & OFPFW11_DL_VLAN_PCP)) {
81a76618
BP
363 if (ofmatch->dl_vlan_pcp <= 7) {
364 match->flow.vlan_tci |= htons(ofmatch->dl_vlan_pcp
365 << VLAN_PCP_SHIFT);
366 match->wc.masks.vlan_tci |= htons(VLAN_PCP_MASK);
410698cf
BP
367 } else {
368 /* Invalid PCP. */
369 return OFPERR_OFPBMC_BAD_VALUE;
370 }
371 }
372 }
373 }
374
375 if (!(wc & OFPFW11_DL_TYPE)) {
81a76618
BP
376 match_set_dl_type(match,
377 ofputil_dl_type_from_openflow(ofmatch->dl_type));
410698cf
BP
378 }
379
81a76618
BP
380 ipv4 = match->flow.dl_type == htons(ETH_TYPE_IP);
381 arp = match->flow.dl_type == htons(ETH_TYPE_ARP);
8087f5ff 382 rarp = match->flow.dl_type == htons(ETH_TYPE_RARP);
410698cf
BP
383
384 if (ipv4 && !(wc & OFPFW11_NW_TOS)) {
81a76618 385 if (ofmatch->nw_tos & ~IP_DSCP_MASK) {
410698cf
BP
386 /* Invalid TOS. */
387 return OFPERR_OFPBMC_BAD_VALUE;
388 }
389
81a76618 390 match_set_nw_dscp(match, ofmatch->nw_tos);
410698cf
BP
391 }
392
8087f5ff 393 if (ipv4 || arp || rarp) {
410698cf 394 if (!(wc & OFPFW11_NW_PROTO)) {
81a76618 395 match_set_nw_proto(match, ofmatch->nw_proto);
410698cf 396 }
81a76618
BP
397 match_set_nw_src_masked(match, ofmatch->nw_src, ~ofmatch->nw_src_mask);
398 match_set_nw_dst_masked(match, ofmatch->nw_dst, ~ofmatch->nw_dst_mask);
410698cf
BP
399 }
400
401#define OFPFW11_TP_ALL (OFPFW11_TP_SRC | OFPFW11_TP_DST)
402 if (ipv4 && (wc & OFPFW11_TP_ALL) != OFPFW11_TP_ALL) {
81a76618 403 switch (match->flow.nw_proto) {
410698cf
BP
404 case IPPROTO_ICMP:
405 /* "A.2.3 Flow Match Structures" in OF1.1 says:
406 *
407 * The tp_src and tp_dst fields will be ignored unless the
408 * network protocol specified is as TCP, UDP or SCTP.
409 *
410 * but I'm pretty sure we should support ICMP too, otherwise
411 * that's a regression from OF1.0. */
412 if (!(wc & OFPFW11_TP_SRC)) {
81a76618 413 uint16_t icmp_type = ntohs(ofmatch->tp_src);
410698cf 414 if (icmp_type < 0x100) {
81a76618 415 match_set_icmp_type(match, icmp_type);
410698cf
BP
416 } else {
417 return OFPERR_OFPBMC_BAD_FIELD;
418 }
419 }
420 if (!(wc & OFPFW11_TP_DST)) {
81a76618 421 uint16_t icmp_code = ntohs(ofmatch->tp_dst);
410698cf 422 if (icmp_code < 0x100) {
81a76618 423 match_set_icmp_code(match, icmp_code);
410698cf
BP
424 } else {
425 return OFPERR_OFPBMC_BAD_FIELD;
426 }
427 }
428 break;
429
430 case IPPROTO_TCP:
431 case IPPROTO_UDP:
0d56eaf2 432 case IPPROTO_SCTP:
410698cf 433 if (!(wc & (OFPFW11_TP_SRC))) {
81a76618 434 match_set_tp_src(match, ofmatch->tp_src);
410698cf
BP
435 }
436 if (!(wc & (OFPFW11_TP_DST))) {
81a76618 437 match_set_tp_dst(match, ofmatch->tp_dst);
410698cf
BP
438 }
439 break;
440
410698cf
BP
441 default:
442 /* OF1.1 says explicitly to ignore this. */
443 break;
444 }
445 }
446
b02475c5 447 if (eth_type_mpls(match->flow.dl_type)) {
097d4939 448 if (!(wc & OFPFW11_MPLS_LABEL)) {
8bfd0fda 449 match_set_mpls_label(match, 0, ofmatch->mpls_label);
097d4939
JR
450 }
451 if (!(wc & OFPFW11_MPLS_TC)) {
8bfd0fda 452 match_set_mpls_tc(match, 0, ofmatch->mpls_tc);
410698cf
BP
453 }
454 }
455
81a76618
BP
456 match_set_metadata_masked(match, ofmatch->metadata,
457 ~ofmatch->metadata_mask);
410698cf
BP
458
459 return 0;
460}
461
81a76618 462/* Convert 'match' into the OpenFlow 1.1 match structure 'ofmatch'. */
410698cf 463void
81a76618
BP
464ofputil_match_to_ofp11_match(const struct match *match,
465 struct ofp11_match *ofmatch)
410698cf
BP
466{
467 uint32_t wc = 0;
410698cf 468
81a76618
BP
469 memset(ofmatch, 0, sizeof *ofmatch);
470 ofmatch->omh.type = htons(OFPMT_STANDARD);
471 ofmatch->omh.length = htons(OFPMT11_STANDARD_LENGTH);
410698cf 472
4e022ec0 473 if (!match->wc.masks.in_port.ofp_port) {
410698cf
BP
474 wc |= OFPFW11_IN_PORT;
475 } else {
4e022ec0 476 ofmatch->in_port = ofputil_port_to_ofp11(match->flow.in_port.ofp_port);
410698cf
BP
477 }
478
74ff3298
JR
479 ofmatch->dl_src = match->flow.dl_src;
480 ofmatch->dl_src_mask = eth_addr_invert(match->wc.masks.dl_src);
481 ofmatch->dl_dst = match->flow.dl_dst;
482 ofmatch->dl_dst_mask = eth_addr_invert(match->wc.masks.dl_dst);
410698cf 483
81a76618 484 if (match->wc.masks.vlan_tci == htons(0)) {
410698cf 485 wc |= OFPFW11_DL_VLAN | OFPFW11_DL_VLAN_PCP;
81a76618
BP
486 } else if (match->wc.masks.vlan_tci & htons(VLAN_CFI)
487 && !(match->flow.vlan_tci & htons(VLAN_CFI))) {
488 ofmatch->dl_vlan = htons(OFPVID11_NONE);
410698cf
BP
489 wc |= OFPFW11_DL_VLAN_PCP;
490 } else {
81a76618
BP
491 if (!(match->wc.masks.vlan_tci & htons(VLAN_VID_MASK))) {
492 ofmatch->dl_vlan = htons(OFPVID11_ANY);
410698cf 493 } else {
81a76618 494 ofmatch->dl_vlan = htons(vlan_tci_to_vid(match->flow.vlan_tci));
410698cf
BP
495 }
496
81a76618 497 if (!(match->wc.masks.vlan_tci & htons(VLAN_PCP_MASK))) {
410698cf
BP
498 wc |= OFPFW11_DL_VLAN_PCP;
499 } else {
81a76618 500 ofmatch->dl_vlan_pcp = vlan_tci_to_pcp(match->flow.vlan_tci);
410698cf
BP
501 }
502 }
503
81a76618 504 if (!match->wc.masks.dl_type) {
410698cf
BP
505 wc |= OFPFW11_DL_TYPE;
506 } else {
81a76618 507 ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
410698cf
BP
508 }
509
81a76618 510 if (!(match->wc.masks.nw_tos & IP_DSCP_MASK)) {
410698cf
BP
511 wc |= OFPFW11_NW_TOS;
512 } else {
81a76618 513 ofmatch->nw_tos = match->flow.nw_tos & IP_DSCP_MASK;
410698cf
BP
514 }
515
81a76618 516 if (!match->wc.masks.nw_proto) {
410698cf
BP
517 wc |= OFPFW11_NW_PROTO;
518 } else {
81a76618 519 ofmatch->nw_proto = match->flow.nw_proto;
410698cf
BP
520 }
521
81a76618
BP
522 ofmatch->nw_src = match->flow.nw_src;
523 ofmatch->nw_src_mask = ~match->wc.masks.nw_src;
524 ofmatch->nw_dst = match->flow.nw_dst;
525 ofmatch->nw_dst_mask = ~match->wc.masks.nw_dst;
410698cf 526
81a76618 527 if (!match->wc.masks.tp_src) {
410698cf
BP
528 wc |= OFPFW11_TP_SRC;
529 } else {
81a76618 530 ofmatch->tp_src = match->flow.tp_src;
410698cf
BP
531 }
532
81a76618 533 if (!match->wc.masks.tp_dst) {
410698cf
BP
534 wc |= OFPFW11_TP_DST;
535 } else {
81a76618 536 ofmatch->tp_dst = match->flow.tp_dst;
410698cf
BP
537 }
538
8bfd0fda 539 if (!(match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK))) {
097d4939
JR
540 wc |= OFPFW11_MPLS_LABEL;
541 } else {
8bfd0fda
BP
542 ofmatch->mpls_label = htonl(mpls_lse_to_label(
543 match->flow.mpls_lse[0]));
097d4939
JR
544 }
545
8bfd0fda 546 if (!(match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK))) {
097d4939
JR
547 wc |= OFPFW11_MPLS_TC;
548 } else {
8bfd0fda 549 ofmatch->mpls_tc = mpls_lse_to_tc(match->flow.mpls_lse[0]);
097d4939 550 }
410698cf 551
81a76618
BP
552 ofmatch->metadata = match->flow.metadata;
553 ofmatch->metadata_mask = ~match->wc.masks.metadata;
410698cf 554
81a76618 555 ofmatch->wildcards = htonl(wc);
410698cf
BP
556}
557
75fa58f8
BP
558/* Returns the "typical" length of a match for 'protocol', for use in
559 * estimating space to preallocate. */
560int
561ofputil_match_typical_len(enum ofputil_protocol protocol)
562{
563 switch (protocol) {
564 case OFPUTIL_P_OF10_STD:
565 case OFPUTIL_P_OF10_STD_TID:
566 return sizeof(struct ofp10_match);
567
568 case OFPUTIL_P_OF10_NXM:
569 case OFPUTIL_P_OF10_NXM_TID:
570 return NXM_TYPICAL_LEN;
571
572 case OFPUTIL_P_OF11_STD:
573 return sizeof(struct ofp11_match);
574
575 case OFPUTIL_P_OF12_OXM:
576 case OFPUTIL_P_OF13_OXM:
c37c0382 577 case OFPUTIL_P_OF14_OXM:
42dccab5 578 case OFPUTIL_P_OF15_OXM:
b79d45a1 579 case OFPUTIL_P_OF16_OXM:
75fa58f8
BP
580 return NXM_TYPICAL_LEN;
581
582 default:
428b2edd 583 OVS_NOT_REACHED();
75fa58f8
BP
584 }
585}
586
587/* Appends to 'b' an struct ofp11_match_header followed by a match that
588 * expresses 'match' properly for 'protocol', plus enough zero bytes to pad the
589 * data appended out to a multiple of 8. 'protocol' must be one that is usable
590 * in OpenFlow 1.1 or later.
591 *
592 * This function can cause 'b''s data to be reallocated.
593 *
594 * Returns the number of bytes appended to 'b', excluding the padding. Never
595 * returns zero. */
596int
597ofputil_put_ofp11_match(struct ofpbuf *b, const struct match *match,
598 enum ofputil_protocol protocol)
599{
600 switch (protocol) {
601 case OFPUTIL_P_OF10_STD:
602 case OFPUTIL_P_OF10_STD_TID:
603 case OFPUTIL_P_OF10_NXM:
604 case OFPUTIL_P_OF10_NXM_TID:
428b2edd 605 OVS_NOT_REACHED();
75fa58f8
BP
606
607 case OFPUTIL_P_OF11_STD: {
608 struct ofp11_match *om;
609
610 /* Make sure that no padding is needed. */
611 BUILD_ASSERT_DECL(sizeof *om % 8 == 0);
612
613 om = ofpbuf_put_uninit(b, sizeof *om);
614 ofputil_match_to_ofp11_match(match, om);
615 return sizeof *om;
616 }
617
618 case OFPUTIL_P_OF12_OXM:
619 case OFPUTIL_P_OF13_OXM:
c37c0382 620 case OFPUTIL_P_OF14_OXM:
42dccab5 621 case OFPUTIL_P_OF15_OXM:
b79d45a1 622 case OFPUTIL_P_OF16_OXM:
9d84066c
BP
623 return oxm_put_match(b, match,
624 ofputil_protocol_to_ofp_version(protocol));
75fa58f8
BP
625 }
626
428b2edd 627 OVS_NOT_REACHED();
75fa58f8
BP
628}
629
36956a7d 630/* Given a 'dl_type' value in the format used in struct flow, returns the
eec25dc1
BP
631 * corresponding 'dl_type' value for use in an ofp10_match or ofp11_match
632 * structure. */
36956a7d
BP
633ovs_be16
634ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type)
635{
636 return (flow_dl_type == htons(FLOW_DL_TYPE_NONE)
637 ? htons(OFP_DL_TYPE_NOT_ETH_TYPE)
638 : flow_dl_type);
639}
640
eec25dc1 641/* Given a 'dl_type' value in the format used in an ofp10_match or ofp11_match
36956a7d
BP
642 * structure, returns the corresponding 'dl_type' value for use in struct
643 * flow. */
644ovs_be16
645ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type)
646{
647 return (ofp_dl_type == htons(OFP_DL_TYPE_NOT_ETH_TYPE)
648 ? htons(FLOW_DL_TYPE_NONE)
649 : ofp_dl_type);
650}
2e4f5fcf 651\f
27527aa0 652/* Protocols. */
7fa91113 653
27527aa0
BP
654struct proto_abbrev {
655 enum ofputil_protocol protocol;
656 const char *name;
657};
658
659/* Most users really don't care about some of the differences between
aa233d57 660 * protocols. These abbreviations help with that. */
27527aa0 661static const struct proto_abbrev proto_abbrevs[] = {
aa233d57
BP
662 { OFPUTIL_P_ANY, "any" },
663 { OFPUTIL_P_OF10_STD_ANY, "OpenFlow10" },
664 { OFPUTIL_P_OF10_NXM_ANY, "NXM" },
665 { OFPUTIL_P_ANY_OXM, "OXM" },
27527aa0
BP
666};
667#define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
668
669enum ofputil_protocol ofputil_flow_dump_protocols[] = {
b79d45a1 670 OFPUTIL_P_OF16_OXM,
42dccab5 671 OFPUTIL_P_OF15_OXM,
c37c0382 672 OFPUTIL_P_OF14_OXM,
2e1ae200 673 OFPUTIL_P_OF13_OXM,
8d7785bd 674 OFPUTIL_P_OF12_OXM,
75fa58f8 675 OFPUTIL_P_OF11_STD,
85813857
BP
676 OFPUTIL_P_OF10_NXM,
677 OFPUTIL_P_OF10_STD,
27527aa0
BP
678};
679size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
680
4f13da56
BP
681/* Returns the set of ofputil_protocols that are supported with the given
682 * OpenFlow 'version'. 'version' should normally be an 8-bit OpenFlow version
683 * identifier (e.g. 0x01 for OpenFlow 1.0, 0x02 for OpenFlow 1.1). Returns 0
684 * if 'version' is not supported or outside the valid range. */
27527aa0 685enum ofputil_protocol
4f13da56 686ofputil_protocols_from_ofp_version(enum ofp_version version)
27527aa0
BP
687{
688 switch (version) {
2e3fa633 689 case OFP10_VERSION:
4f13da56 690 return OFPUTIL_P_OF10_STD_ANY | OFPUTIL_P_OF10_NXM_ANY;
75fa58f8
BP
691 case OFP11_VERSION:
692 return OFPUTIL_P_OF11_STD;
2e3fa633 693 case OFP12_VERSION:
85813857 694 return OFPUTIL_P_OF12_OXM;
2e1ae200
JR
695 case OFP13_VERSION:
696 return OFPUTIL_P_OF13_OXM;
c37c0382
AC
697 case OFP14_VERSION:
698 return OFPUTIL_P_OF14_OXM;
42dccab5
BP
699 case OFP15_VERSION:
700 return OFPUTIL_P_OF15_OXM;
b79d45a1
BP
701 case OFP16_VERSION:
702 return OFPUTIL_P_OF16_OXM;
2e3fa633
SH
703 default:
704 return 0;
27527aa0
BP
705 }
706}
707
4f13da56
BP
708/* Returns the ofputil_protocol that is initially in effect on an OpenFlow
709 * connection that has negotiated the given 'version'. 'version' should
710 * normally be an 8-bit OpenFlow version identifier (e.g. 0x01 for OpenFlow
711 * 1.0, 0x02 for OpenFlow 1.1). Returns 0 if 'version' is not supported or
712 * outside the valid range. */
713enum ofputil_protocol
714ofputil_protocol_from_ofp_version(enum ofp_version version)
715{
716 return rightmost_1bit(ofputil_protocols_from_ofp_version(version));
717}
718
44d3732d 719/* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION,
2e1ae200 720 * etc.) that corresponds to 'protocol'. */
2e3fa633 721enum ofp_version
9e1fd49b
BP
722ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
723{
724 switch (protocol) {
85813857
BP
725 case OFPUTIL_P_OF10_STD:
726 case OFPUTIL_P_OF10_STD_TID:
727 case OFPUTIL_P_OF10_NXM:
728 case OFPUTIL_P_OF10_NXM_TID:
9e1fd49b 729 return OFP10_VERSION;
75fa58f8
BP
730 case OFPUTIL_P_OF11_STD:
731 return OFP11_VERSION;
85813857 732 case OFPUTIL_P_OF12_OXM:
44d3732d 733 return OFP12_VERSION;
2e1ae200
JR
734 case OFPUTIL_P_OF13_OXM:
735 return OFP13_VERSION;
c37c0382
AC
736 case OFPUTIL_P_OF14_OXM:
737 return OFP14_VERSION;
42dccab5
BP
738 case OFPUTIL_P_OF15_OXM:
739 return OFP15_VERSION;
b79d45a1
BP
740 case OFPUTIL_P_OF16_OXM:
741 return OFP16_VERSION;
9e1fd49b
BP
742 }
743
428b2edd 744 OVS_NOT_REACHED();
9e1fd49b
BP
745}
746
4f13da56
BP
747/* Returns a bitmap of OpenFlow versions that are supported by at
748 * least one of the 'protocols'. */
749uint32_t
750ofputil_protocols_to_version_bitmap(enum ofputil_protocol protocols)
751{
752 uint32_t bitmap = 0;
753
754 for (; protocols; protocols = zero_rightmost_1bit(protocols)) {
755 enum ofputil_protocol protocol = rightmost_1bit(protocols);
756
757 bitmap |= 1u << ofputil_protocol_to_ofp_version(protocol);
758 }
759
760 return bitmap;
761}
762
763/* Returns the set of protocols that are supported on top of the
764 * OpenFlow versions included in 'bitmap'. */
765enum ofputil_protocol
766ofputil_protocols_from_version_bitmap(uint32_t bitmap)
767{
768 enum ofputil_protocol protocols = 0;
769
770 for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) {
771 enum ofp_version version = rightmost_1bit_idx(bitmap);
772
773 protocols |= ofputil_protocols_from_ofp_version(version);
774 }
775
776 return protocols;
777}
778
27527aa0
BP
779/* Returns true if 'protocol' is a single OFPUTIL_P_* value, false
780 * otherwise. */
7fa91113 781bool
27527aa0 782ofputil_protocol_is_valid(enum ofputil_protocol protocol)
7fa91113 783{
27527aa0
BP
784 return protocol & OFPUTIL_P_ANY && is_pow2(protocol);
785}
786
787/* Returns the equivalent of 'protocol' with the Nicira flow_mod_table_id
788 * extension turned on or off if 'enable' is true or false, respectively.
789 *
790 * This extension is only useful for protocols whose "standard" version does
791 * not allow specific tables to be modified. In particular, this is true of
792 * OpenFlow 1.0. In later versions of OpenFlow, a flow_mod request always
793 * specifies a table ID and so there is no need for such an extension. When
794 * 'protocol' is such a protocol that doesn't need a flow_mod_table_id
795 * extension, this function just returns its 'protocol' argument unchanged
796 * regardless of the value of 'enable'. */
797enum ofputil_protocol
798ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
799{
800 switch (protocol) {
85813857
BP
801 case OFPUTIL_P_OF10_STD:
802 case OFPUTIL_P_OF10_STD_TID:
803 return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD;
27527aa0 804
85813857
BP
805 case OFPUTIL_P_OF10_NXM:
806 case OFPUTIL_P_OF10_NXM_TID:
807 return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM;
27527aa0 808
75fa58f8
BP
809 case OFPUTIL_P_OF11_STD:
810 return OFPUTIL_P_OF11_STD;
811
85813857
BP
812 case OFPUTIL_P_OF12_OXM:
813 return OFPUTIL_P_OF12_OXM;
44d3732d 814
2e1ae200
JR
815 case OFPUTIL_P_OF13_OXM:
816 return OFPUTIL_P_OF13_OXM;
817
c37c0382
AC
818 case OFPUTIL_P_OF14_OXM:
819 return OFPUTIL_P_OF14_OXM;
820
42dccab5
BP
821 case OFPUTIL_P_OF15_OXM:
822 return OFPUTIL_P_OF15_OXM;
823
b79d45a1
BP
824 case OFPUTIL_P_OF16_OXM:
825 return OFPUTIL_P_OF16_OXM;
826
27527aa0 827 default:
428b2edd 828 OVS_NOT_REACHED();
7fa91113 829 }
27527aa0 830}
7fa91113 831
27527aa0
BP
832/* Returns the "base" version of 'protocol'. That is, if 'protocol' includes
833 * some extension to a standard protocol version, the return value is the
834 * standard version of that protocol without any extension. If 'protocol' is a
835 * standard protocol version, returns 'protocol' unchanged. */
836enum ofputil_protocol
837ofputil_protocol_to_base(enum ofputil_protocol protocol)
838{
839 return ofputil_protocol_set_tid(protocol, false);
7fa91113
BP
840}
841
27527aa0
BP
842/* Returns 'new_base' with any extensions taken from 'cur'. */
843enum ofputil_protocol
844ofputil_protocol_set_base(enum ofputil_protocol cur,
845 enum ofputil_protocol new_base)
7fa91113 846{
27527aa0
BP
847 bool tid = (cur & OFPUTIL_P_TID) != 0;
848
849 switch (new_base) {
85813857
BP
850 case OFPUTIL_P_OF10_STD:
851 case OFPUTIL_P_OF10_STD_TID:
852 return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid);
27527aa0 853
85813857
BP
854 case OFPUTIL_P_OF10_NXM:
855 case OFPUTIL_P_OF10_NXM_TID:
856 return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid);
27527aa0 857
75fa58f8
BP
858 case OFPUTIL_P_OF11_STD:
859 return ofputil_protocol_set_tid(OFPUTIL_P_OF11_STD, tid);
860
85813857
BP
861 case OFPUTIL_P_OF12_OXM:
862 return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);
44d3732d 863
2e1ae200
JR
864 case OFPUTIL_P_OF13_OXM:
865 return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid);
866
c37c0382
AC
867 case OFPUTIL_P_OF14_OXM:
868 return ofputil_protocol_set_tid(OFPUTIL_P_OF14_OXM, tid);
869
42dccab5
BP
870 case OFPUTIL_P_OF15_OXM:
871 return ofputil_protocol_set_tid(OFPUTIL_P_OF15_OXM, tid);
872
b79d45a1
BP
873 case OFPUTIL_P_OF16_OXM:
874 return ofputil_protocol_set_tid(OFPUTIL_P_OF16_OXM, tid);
875
7fa91113 876 default:
428b2edd 877 OVS_NOT_REACHED();
7fa91113
BP
878 }
879}
880
27527aa0
BP
881/* Returns a string form of 'protocol', if a simple form exists (that is, if
882 * 'protocol' is either a single protocol or it is a combination of protocols
883 * that have a single abbreviation). Otherwise, returns NULL. */
884const char *
885ofputil_protocol_to_string(enum ofputil_protocol protocol)
88ca35ee 886{
27527aa0
BP
887 const struct proto_abbrev *p;
888
889 /* Use a "switch" statement for single-bit names so that we get a compiler
890 * warning if we forget any. */
891 switch (protocol) {
85813857 892 case OFPUTIL_P_OF10_NXM:
27527aa0
BP
893 return "NXM-table_id";
894
85813857 895 case OFPUTIL_P_OF10_NXM_TID:
27527aa0
BP
896 return "NXM+table_id";
897
85813857 898 case OFPUTIL_P_OF10_STD:
27527aa0
BP
899 return "OpenFlow10-table_id";
900
85813857 901 case OFPUTIL_P_OF10_STD_TID:
27527aa0 902 return "OpenFlow10+table_id";
44d3732d 903
75fa58f8
BP
904 case OFPUTIL_P_OF11_STD:
905 return "OpenFlow11";
906
85813857 907 case OFPUTIL_P_OF12_OXM:
e71bff1b 908 return "OXM-OpenFlow12";
2e1ae200
JR
909
910 case OFPUTIL_P_OF13_OXM:
e71bff1b 911 return "OXM-OpenFlow13";
c37c0382
AC
912
913 case OFPUTIL_P_OF14_OXM:
914 return "OXM-OpenFlow14";
42dccab5
BP
915
916 case OFPUTIL_P_OF15_OXM:
917 return "OXM-OpenFlow15";
b79d45a1
BP
918
919 case OFPUTIL_P_OF16_OXM:
920 return "OXM-OpenFlow16";
27527aa0
BP
921 }
922
923 /* Check abbreviations. */
924 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
925 if (protocol == p->protocol) {
926 return p->name;
927 }
928 }
929
930 return NULL;
931}
932
933/* Returns a string that represents 'protocols'. The return value might be a
934 * comma-separated list if 'protocols' doesn't have a simple name. The return
935 * value is "none" if 'protocols' is 0.
936 *
937 * The caller must free the returned string (with free()). */
938char *
939ofputil_protocols_to_string(enum ofputil_protocol protocols)
940{
941 struct ds s;
942
cb22974d 943 ovs_assert(!(protocols & ~OFPUTIL_P_ANY));
27527aa0
BP
944 if (protocols == 0) {
945 return xstrdup("none");
946 }
947
948 ds_init(&s);
949 while (protocols) {
950 const struct proto_abbrev *p;
951 int i;
952
953 if (s.length) {
954 ds_put_char(&s, ',');
955 }
956
957 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
958 if ((protocols & p->protocol) == p->protocol) {
959 ds_put_cstr(&s, p->name);
960 protocols &= ~p->protocol;
961 goto match;
962 }
963 }
964
965 for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
966 enum ofputil_protocol bit = 1u << i;
967
968 if (protocols & bit) {
969 ds_put_cstr(&s, ofputil_protocol_to_string(bit));
970 protocols &= ~bit;
971 goto match;
972 }
973 }
428b2edd 974 OVS_NOT_REACHED();
27527aa0
BP
975
976 match: ;
977 }
978 return ds_steal_cstr(&s);
979}
980
981static enum ofputil_protocol
982ofputil_protocol_from_string__(const char *s, size_t n)
983{
984 const struct proto_abbrev *p;
985 int i;
986
987 for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
988 enum ofputil_protocol bit = 1u << i;
989 const char *name = ofputil_protocol_to_string(bit);
990
991 if (name && n == strlen(name) && !strncasecmp(s, name, n)) {
992 return bit;
993 }
994 }
995
996 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
997 if (n == strlen(p->name) && !strncasecmp(s, p->name, n)) {
998 return p->protocol;
999 }
1000 }
1001
1002 return 0;
1003}
1004
1005/* Returns the nonempty set of protocols represented by 's', which can be a
1006 * single protocol name or abbreviation or a comma-separated list of them.
1007 *
1008 * Aborts the program with an error message if 's' is invalid. */
1009enum ofputil_protocol
1010ofputil_protocols_from_string(const char *s)
1011{
1012 const char *orig_s = s;
1013 enum ofputil_protocol protocols;
1014
1015 protocols = 0;
1016 while (*s) {
1017 enum ofputil_protocol p;
1018 size_t n;
1019
1020 n = strcspn(s, ",");
1021 if (n == 0) {
1022 s++;
1023 continue;
1024 }
1025
1026 p = ofputil_protocol_from_string__(s, n);
1027 if (!p) {
1028 ovs_fatal(0, "%.*s: unknown flow protocol", (int) n, s);
1029 }
1030 protocols |= p;
1031
1032 s += n;
1033 }
1034
1035 if (!protocols) {
1036 ovs_fatal(0, "%s: no flow protocol specified", orig_s);
1037 }
1038 return protocols;
88ca35ee
BP
1039}
1040
9d84066c 1041enum ofp_version
03e1125c
SH
1042ofputil_version_from_string(const char *s)
1043{
1044 if (!strcasecmp(s, "OpenFlow10")) {
1045 return OFP10_VERSION;
1046 }
1047 if (!strcasecmp(s, "OpenFlow11")) {
1048 return OFP11_VERSION;
1049 }
1050 if (!strcasecmp(s, "OpenFlow12")) {
1051 return OFP12_VERSION;
1052 }
2e1ae200
JR
1053 if (!strcasecmp(s, "OpenFlow13")) {
1054 return OFP13_VERSION;
1055 }
c37c0382
AC
1056 if (!strcasecmp(s, "OpenFlow14")) {
1057 return OFP14_VERSION;
1058 }
42dccab5
BP
1059 if (!strcasecmp(s, "OpenFlow15")) {
1060 return OFP15_VERSION;
1061 }
b79d45a1
BP
1062 if (!strcasecmp(s, "OpenFlow16")) {
1063 return OFP16_VERSION;
1064 }
7beaa082 1065 return 0;
03e1125c
SH
1066}
1067
1068static bool
e091ef84 1069is_delimiter(unsigned char c)
03e1125c
SH
1070{
1071 return isspace(c) || c == ',';
1072}
1073
1074uint32_t
1075ofputil_versions_from_string(const char *s)
1076{
1077 size_t i = 0;
1078 uint32_t bitmap = 0;
1079
1080 while (s[i]) {
1081 size_t j;
7beaa082 1082 int version;
03e1125c
SH
1083 char *key;
1084
1085 if (is_delimiter(s[i])) {
1086 i++;
1087 continue;
1088 }
1089 j = 0;
1090 while (s[i + j] && !is_delimiter(s[i + j])) {
1091 j++;
1092 }
1093 key = xmemdup0(s + i, j);
1094 version = ofputil_version_from_string(key);
7beaa082
SH
1095 if (!version) {
1096 VLOG_FATAL("Unknown OpenFlow version: \"%s\"", key);
1097 }
03e1125c
SH
1098 free(key);
1099 bitmap |= 1u << version;
1100 i += j;
1101 }
1102
1103 return bitmap;
1104}
1105
7beaa082
SH
1106uint32_t
1107ofputil_versions_from_strings(char ** const s, size_t count)
1108{
1109 uint32_t bitmap = 0;
1110
1111 while (count--) {
1112 int version = ofputil_version_from_string(s[count]);
1113 if (!version) {
1114 VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]);
1115 } else {
1116 bitmap |= 1u << version;
1117 }
1118 }
1119
1120 return bitmap;
1121}
1122
03e1125c
SH
1123const char *
1124ofputil_version_to_string(enum ofp_version ofp_version)
1125{
1126 switch (ofp_version) {
1127 case OFP10_VERSION:
1128 return "OpenFlow10";
1129 case OFP11_VERSION:
1130 return "OpenFlow11";
1131 case OFP12_VERSION:
1132 return "OpenFlow12";
2e1ae200
JR
1133 case OFP13_VERSION:
1134 return "OpenFlow13";
c37c0382
AC
1135 case OFP14_VERSION:
1136 return "OpenFlow14";
42dccab5
BP
1137 case OFP15_VERSION:
1138 return "OpenFlow15";
b79d45a1
BP
1139 case OFP16_VERSION:
1140 return "OpenFlow16";
03e1125c 1141 default:
428b2edd 1142 OVS_NOT_REACHED();
03e1125c
SH
1143 }
1144}
1145
54834960
EJ
1146bool
1147ofputil_packet_in_format_is_valid(enum nx_packet_in_format packet_in_format)
1148{
1149 switch (packet_in_format) {
6409e008
BP
1150 case NXPIF_STANDARD:
1151 case NXPIF_NXT_PACKET_IN:
1152 case NXPIF_NXT_PACKET_IN2:
54834960
EJ
1153 return true;
1154 }
1155
1156 return false;
1157}
1158
1159const char *
1160ofputil_packet_in_format_to_string(enum nx_packet_in_format packet_in_format)
1161{
1162 switch (packet_in_format) {
6409e008
BP
1163 case NXPIF_STANDARD:
1164 return "standard";
1165 case NXPIF_NXT_PACKET_IN:
1166 return "nxt_packet_in";
1167 case NXPIF_NXT_PACKET_IN2:
1168 return "nxt_packet_in2";
54834960 1169 default:
428b2edd 1170 OVS_NOT_REACHED();
54834960
EJ
1171 }
1172}
1173
1174int
1175ofputil_packet_in_format_from_string(const char *s)
1176{
6409e008
BP
1177 return (!strcmp(s, "standard") || !strcmp(s, "openflow10")
1178 ? NXPIF_STANDARD
1179 : !strcmp(s, "nxt_packet_in") || !strcmp(s, "nxm")
1180 ? NXPIF_NXT_PACKET_IN
1181 : !strcmp(s, "nxt_packet_in2")
1182 ? NXPIF_NXT_PACKET_IN2
54834960
EJ
1183 : -1);
1184}
1185
03e1125c
SH
1186void
1187ofputil_format_version(struct ds *msg, enum ofp_version version)
1188{
8989046d 1189 ds_put_format(msg, "0x%02x", version);
03e1125c
SH
1190}
1191
1192void
1193ofputil_format_version_name(struct ds *msg, enum ofp_version version)
1194{
1195 ds_put_cstr(msg, ofputil_version_to_string(version));
1196}
1197
1198static void
1199ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap,
1200 void (*format_version)(struct ds *msg,
1201 enum ofp_version))
1202{
1203 while (bitmap) {
1204 format_version(msg, raw_ctz(bitmap));
1205 bitmap = zero_rightmost_1bit(bitmap);
1206 if (bitmap) {
1207 ds_put_cstr(msg, ", ");
1208 }
1209 }
1210}
1211
1212void
1213ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap)
1214{
1215 ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version);
1216}
1217
1218void
1219ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap)
1220{
1221 ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version_name);
1222}
1223
de6c85b0
SH
1224static bool
1225ofputil_decode_hello_bitmap(const struct ofp_hello_elem_header *oheh,
0935de41 1226 uint32_t *allowed_versionsp)
de6c85b0
SH
1227{
1228 uint16_t bitmap_len = ntohs(oheh->length) - sizeof *oheh;
db5a1019 1229 const ovs_be32 *bitmap = ALIGNED_CAST(const ovs_be32 *, oheh + 1);
0935de41 1230 uint32_t allowed_versions;
de6c85b0
SH
1231
1232 if (!bitmap_len || bitmap_len % sizeof *bitmap) {
1233 return false;
1234 }
1235
1236 /* Only use the first 32-bit element of the bitmap as that is all the
1237 * current implementation supports. Subsequent elements are ignored which
7e9383cc 1238 * should have no effect on session negotiation until Open vSwitch supports
de6c85b0
SH
1239 * wire-protocol versions greater than 31.
1240 */
0935de41 1241 allowed_versions = ntohl(bitmap[0]);
de6c85b0 1242
0935de41 1243 if (allowed_versions & 1) {
de6c85b0
SH
1244 /* There's no OpenFlow version 0. */
1245 VLOG_WARN_RL(&bad_ofmsg_rl, "peer claims to support invalid OpenFlow "
1246 "version 0x00");
0935de41 1247 allowed_versions &= ~1u;
de6c85b0
SH
1248 }
1249
0935de41 1250 if (!allowed_versions) {
de6c85b0
SH
1251 VLOG_WARN_RL(&bad_ofmsg_rl, "peer does not support any OpenFlow "
1252 "version (between 0x01 and 0x1f)");
1253 return false;
1254 }
1255
0935de41 1256 *allowed_versionsp = allowed_versions;
de6c85b0
SH
1257 return true;
1258}
1259
1260static uint32_t
1261version_bitmap_from_version(uint8_t ofp_version)
1262{
1263 return ((ofp_version < 32 ? 1u << ofp_version : 0) - 1) << 1;
1264}
1265
1266/* Decodes OpenFlow OFPT_HELLO message 'oh', storing into '*allowed_versions'
1267 * the set of OpenFlow versions for which 'oh' announces support.
1268 *
1269 * Because of how OpenFlow defines OFPT_HELLO messages, this function is always
1270 * successful, and thus '*allowed_versions' is always initialized. However, it
1271 * returns false if 'oh' contains some data that could not be fully understood,
1272 * true if 'oh' was completely parsed. */
1273bool
1274ofputil_decode_hello(const struct ofp_header *oh, uint32_t *allowed_versions)
1275{
0a2869d5 1276 struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
de6c85b0
SH
1277 ofpbuf_pull(&msg, sizeof *oh);
1278
1279 *allowed_versions = version_bitmap_from_version(oh->version);
0a2869d5
BP
1280
1281 bool ok = true;
6fd6ed71 1282 while (msg.size) {
de6c85b0
SH
1283 const struct ofp_hello_elem_header *oheh;
1284 unsigned int len;
1285
6fd6ed71 1286 if (msg.size < sizeof *oheh) {
de6c85b0
SH
1287 return false;
1288 }
1289
6fd6ed71 1290 oheh = msg.data;
de6c85b0
SH
1291 len = ntohs(oheh->length);
1292 if (len < sizeof *oheh || !ofpbuf_try_pull(&msg, ROUND_UP(len, 8))) {
1293 return false;
1294 }
1295
1296 if (oheh->type != htons(OFPHET_VERSIONBITMAP)
1297 || !ofputil_decode_hello_bitmap(oheh, allowed_versions)) {
1298 ok = false;
1299 }
1300 }
1301
1302 return ok;
1303}
1304
1305/* Returns true if 'allowed_versions' needs to be accompanied by a version
1306 * bitmap to be correctly expressed in an OFPT_HELLO message. */
5ddea998 1307static bool
de6c85b0
SH
1308should_send_version_bitmap(uint32_t allowed_versions)
1309{
1310 return !is_pow2((allowed_versions >> 1) + 1);
1311}
1312
1313/* Create an OFPT_HELLO message that expresses support for the OpenFlow
1314 * versions in the 'allowed_versions' bitmaps and returns the message. */
1315struct ofpbuf *
1316ofputil_encode_hello(uint32_t allowed_versions)
1317{
1318 enum ofp_version ofp_version;
1319 struct ofpbuf *msg;
1320
1321 ofp_version = leftmost_1bit_idx(allowed_versions);
1322 msg = ofpraw_alloc(OFPRAW_OFPT_HELLO, ofp_version, 0);
1323
1324 if (should_send_version_bitmap(allowed_versions)) {
1325 struct ofp_hello_elem_header *oheh;
1326 uint16_t map_len;
1327
74c4b9c1 1328 map_len = sizeof allowed_versions;
de6c85b0
SH
1329 oheh = ofpbuf_put_zeros(msg, ROUND_UP(map_len + sizeof *oheh, 8));
1330 oheh->type = htons(OFPHET_VERSIONBITMAP);
1331 oheh->length = htons(map_len + sizeof *oheh);
db5a1019 1332 *ALIGNED_CAST(ovs_be32 *, oheh + 1) = htonl(allowed_versions);
1804d25a
BP
1333
1334 ofpmsg_update_length(msg);
de6c85b0
SH
1335 }
1336
1337 return msg;
1338}
1339
27527aa0
BP
1340/* Returns an OpenFlow message that, sent on an OpenFlow connection whose
1341 * protocol is 'current', at least partly transitions the protocol to 'want'.
1342 * Stores in '*next' the protocol that will be in effect on the OpenFlow
1343 * connection if the switch processes the returned message correctly. (If
1344 * '*next != want' then the caller will have to iterate.)
1345 *
e43928f2
BP
1346 * If 'current == want', or if it is not possible to transition from 'current'
1347 * to 'want' (because, for example, 'current' and 'want' use different OpenFlow
1348 * protocol versions), returns NULL and stores 'current' in '*next'. */
27527aa0
BP
1349struct ofpbuf *
1350ofputil_encode_set_protocol(enum ofputil_protocol current,
1351 enum ofputil_protocol want,
1352 enum ofputil_protocol *next)
1353{
e43928f2 1354 enum ofp_version cur_version, want_version;
27527aa0
BP
1355 enum ofputil_protocol cur_base, want_base;
1356 bool cur_tid, want_tid;
1357
e43928f2
BP
1358 cur_version = ofputil_protocol_to_ofp_version(current);
1359 want_version = ofputil_protocol_to_ofp_version(want);
1360 if (cur_version != want_version) {
1361 *next = current;
1362 return NULL;
1363 }
1364
27527aa0
BP
1365 cur_base = ofputil_protocol_to_base(current);
1366 want_base = ofputil_protocol_to_base(want);
1367 if (cur_base != want_base) {
1368 *next = ofputil_protocol_set_base(current, want_base);
1369
1370 switch (want_base) {
85813857 1371 case OFPUTIL_P_OF10_NXM:
27527aa0
BP
1372 return ofputil_encode_nx_set_flow_format(NXFF_NXM);
1373
85813857 1374 case OFPUTIL_P_OF10_STD:
27527aa0
BP
1375 return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW10);
1376
75fa58f8 1377 case OFPUTIL_P_OF11_STD:
85813857 1378 case OFPUTIL_P_OF12_OXM:
2e1ae200 1379 case OFPUTIL_P_OF13_OXM:
c37c0382 1380 case OFPUTIL_P_OF14_OXM:
42dccab5 1381 case OFPUTIL_P_OF15_OXM:
b79d45a1 1382 case OFPUTIL_P_OF16_OXM:
75fa58f8 1383 /* There is only one variant of each OpenFlow 1.1+ protocol, and we
2e1ae200 1384 * verified above that we're not trying to change versions. */
428b2edd 1385 OVS_NOT_REACHED();
44d3732d 1386
85813857
BP
1387 case OFPUTIL_P_OF10_STD_TID:
1388 case OFPUTIL_P_OF10_NXM_TID:
428b2edd 1389 OVS_NOT_REACHED();
27527aa0
BP
1390 }
1391 }
1392
1393 cur_tid = (current & OFPUTIL_P_TID) != 0;
1394 want_tid = (want & OFPUTIL_P_TID) != 0;
1395 if (cur_tid != want_tid) {
1396 *next = ofputil_protocol_set_tid(current, want_tid);
1397 return ofputil_make_flow_mod_table_id(want_tid);
1398 }
1399
cb22974d 1400 ovs_assert(current == want);
27527aa0
BP
1401
1402 *next = current;
1403 return NULL;
88ca35ee
BP
1404}
1405
27527aa0
BP
1406/* Returns an NXT_SET_FLOW_FORMAT message that can be used to set the flow
1407 * format to 'nxff'. */
88ca35ee 1408struct ofpbuf *
27527aa0 1409ofputil_encode_nx_set_flow_format(enum nx_flow_format nxff)
88ca35ee 1410{
73dbf4ab 1411 struct nx_set_flow_format *sff;
88ca35ee
BP
1412 struct ofpbuf *msg;
1413
cb22974d 1414 ovs_assert(ofputil_nx_flow_format_is_valid(nxff));
27527aa0 1415
982697a4
BP
1416 msg = ofpraw_alloc(OFPRAW_NXT_SET_FLOW_FORMAT, OFP10_VERSION, 0);
1417 sff = ofpbuf_put_zeros(msg, sizeof *sff);
27527aa0 1418 sff->format = htonl(nxff);
88ca35ee
BP
1419
1420 return msg;
1421}
1422
27527aa0
BP
1423/* Returns the base protocol if 'flow_format' is a valid NXFF_* value, false
1424 * otherwise. */
1425enum ofputil_protocol
1426ofputil_nx_flow_format_to_protocol(enum nx_flow_format flow_format)
1427{
1428 switch (flow_format) {
1429 case NXFF_OPENFLOW10:
85813857 1430 return OFPUTIL_P_OF10_STD;
27527aa0
BP
1431
1432 case NXFF_NXM:
85813857 1433 return OFPUTIL_P_OF10_NXM;
27527aa0
BP
1434
1435 default:
1436 return 0;
1437 }
1438}
1439
1440/* Returns true if 'flow_format' is a valid NXFF_* value, false otherwise. */
1441bool
1442ofputil_nx_flow_format_is_valid(enum nx_flow_format flow_format)
1443{
1444 return ofputil_nx_flow_format_to_protocol(flow_format) != 0;
1445}
1446
1447/* Returns a string version of 'flow_format', which must be a valid NXFF_*
1448 * value. */
1449const char *
1450ofputil_nx_flow_format_to_string(enum nx_flow_format flow_format)
1451{
1452 switch (flow_format) {
1453 case NXFF_OPENFLOW10:
1454 return "openflow10";
1455 case NXFF_NXM:
1456 return "nxm";
1457 default:
428b2edd 1458 OVS_NOT_REACHED();
27527aa0
BP
1459 }
1460}
1461
54834960 1462struct ofpbuf *
3f4a1939
SH
1463ofputil_make_set_packet_in_format(enum ofp_version ofp_version,
1464 enum nx_packet_in_format packet_in_format)
54834960 1465{
73dbf4ab 1466 struct nx_set_packet_in_format *spif;
54834960
EJ
1467 struct ofpbuf *msg;
1468
3f4a1939 1469 msg = ofpraw_alloc(OFPRAW_NXT_SET_PACKET_IN_FORMAT, ofp_version, 0);
982697a4 1470 spif = ofpbuf_put_zeros(msg, sizeof *spif);
54834960
EJ
1471 spif->format = htonl(packet_in_format);
1472
1473 return msg;
1474}
1475
6c1491fb
BP
1476/* Returns an OpenFlow message that can be used to turn the flow_mod_table_id
1477 * extension on or off (according to 'flow_mod_table_id'). */
1478struct ofpbuf *
1479ofputil_make_flow_mod_table_id(bool flow_mod_table_id)
1480{
73dbf4ab 1481 struct nx_flow_mod_table_id *nfmti;
6c1491fb
BP
1482 struct ofpbuf *msg;
1483
982697a4
BP
1484 msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD_TABLE_ID, OFP10_VERSION, 0);
1485 nfmti = ofpbuf_put_zeros(msg, sizeof *nfmti);
6c1491fb
BP
1486 nfmti->set = flow_mod_table_id;
1487 return msg;
1488}
1489
0fb88c18
BP
1490struct ofputil_flow_mod_flag {
1491 uint16_t raw_flag;
1492 enum ofp_version min_version, max_version;
1493 enum ofputil_flow_mod_flags flag;
1494};
1495
1496static const struct ofputil_flow_mod_flag ofputil_flow_mod_flags[] = {
1497 { OFPFF_SEND_FLOW_REM, OFP10_VERSION, 0, OFPUTIL_FF_SEND_FLOW_REM },
1498 { OFPFF_CHECK_OVERLAP, OFP10_VERSION, 0, OFPUTIL_FF_CHECK_OVERLAP },
1499 { OFPFF10_EMERG, OFP10_VERSION, OFP10_VERSION,
1500 OFPUTIL_FF_EMERG },
1501 { OFPFF12_RESET_COUNTS, OFP12_VERSION, 0, OFPUTIL_FF_RESET_COUNTS },
1502 { OFPFF13_NO_PKT_COUNTS, OFP13_VERSION, 0, OFPUTIL_FF_NO_PKT_COUNTS },
1503 { OFPFF13_NO_BYT_COUNTS, OFP13_VERSION, 0, OFPUTIL_FF_NO_BYT_COUNTS },
1504 { 0, 0, 0, 0 },
1505};
1506
1507static enum ofperr
1508ofputil_decode_flow_mod_flags(ovs_be16 raw_flags_,
1509 enum ofp_flow_mod_command command,
1510 enum ofp_version version,
1511 enum ofputil_flow_mod_flags *flagsp)
1512{
1513 uint16_t raw_flags = ntohs(raw_flags_);
1514 const struct ofputil_flow_mod_flag *f;
1515
1516 *flagsp = 0;
1517 for (f = ofputil_flow_mod_flags; f->raw_flag; f++) {
1518 if (raw_flags & f->raw_flag
1519 && version >= f->min_version
1520 && (!f->max_version || version <= f->max_version)) {
1521 raw_flags &= ~f->raw_flag;
1522 *flagsp |= f->flag;
1523 }
1524 }
1525
1526 /* In OF1.0 and OF1.1, "add" always resets counters, and other commands
1527 * never do.
1528 *
1529 * In OF1.2 and later, OFPFF12_RESET_COUNTS controls whether each command
1530 * resets counters. */
1531 if ((version == OFP10_VERSION || version == OFP11_VERSION)
1532 && command == OFPFC_ADD) {
1533 *flagsp |= OFPUTIL_FF_RESET_COUNTS;
1534 }
1535
1536 return raw_flags ? OFPERR_OFPFMFC_BAD_FLAGS : 0;
1537}
1538
1539static ovs_be16
1540ofputil_encode_flow_mod_flags(enum ofputil_flow_mod_flags flags,
1541 enum ofp_version version)
1542{
1543 const struct ofputil_flow_mod_flag *f;
1544 uint16_t raw_flags;
1545
1546 raw_flags = 0;
1547 for (f = ofputil_flow_mod_flags; f->raw_flag; f++) {
1548 if (f->flag & flags
1549 && version >= f->min_version
1550 && (!f->max_version || version <= f->max_version)) {
1551 raw_flags |= f->raw_flag;
1552 }
1553 }
1554
1555 return htons(raw_flags);
1556}
1557
7fa91113
BP
1558/* Converts an OFPT_FLOW_MOD or NXT_FLOW_MOD message 'oh' into an abstract
1559 * flow_mod in 'fm'. Returns 0 if successful, otherwise an OpenFlow error
1560 * code.
1561 *
f25d0cf3
BP
1562 * Uses 'ofpacts' to store the abstract OFPACT_* version of 'oh''s actions.
1563 * The caller must initialize 'ofpacts' and retains ownership of it.
1564 * 'fm->ofpacts' will point into the 'ofpacts' buffer.
1565 *
1566 * Does not validate the flow_mod actions. The caller should do that, with
1567 * ofpacts_check(). */
90bf1e07 1568enum ofperr
a9a2da38 1569ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
27527aa0 1570 const struct ofp_header *oh,
f25d0cf3 1571 enum ofputil_protocol protocol,
7e9f8266
BP
1572 struct ofpbuf *ofpacts,
1573 ofp_port_t max_port, uint8_t max_table)
2e4f5fcf 1574{
0fb88c18
BP
1575 ovs_be16 raw_flags;
1576 enum ofperr error;
2e4f5fcf 1577
cc40d06b
SH
1578 /* Ignored for non-delete actions */
1579 fm->delete_reason = OFPRR_DELETE;
1580
0a2869d5
BP
1581 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1582 enum ofpraw raw = ofpraw_pull_assert(&b);
aa319503 1583 if (raw == OFPRAW_OFPT11_FLOW_MOD) {
1828ae51 1584 /* Standard OpenFlow 1.1+ flow_mod. */
aa319503 1585 const struct ofp11_flow_mod *ofm;
2e4f5fcf 1586
bbc32a88 1587 ofm = ofpbuf_pull(&b, sizeof *ofm);
2e4f5fcf 1588
81a76618 1589 error = ofputil_pull_ofp11_match(&b, &fm->match, NULL);
aa319503
BP
1590 if (error) {
1591 return error;
1c0b7503
BP
1592 }
1593
2e4f5fcf 1594 /* Translate the message. */
81a76618 1595 fm->priority = ntohs(ofm->priority);
75fa58f8
BP
1596 if (ofm->command == OFPFC_ADD
1597 || (oh->version == OFP11_VERSION
1598 && (ofm->command == OFPFC_MODIFY ||
1599 ofm->command == OFPFC_MODIFY_STRICT)
1600 && ofm->cookie_mask == htonll(0))) {
1601 /* In OpenFlow 1.1 only, a "modify" or "modify-strict" that does
1602 * not match on the cookie is treated as an "add" if there is no
1603 * match. */
aa319503
BP
1604 fm->cookie = htonll(0);
1605 fm->cookie_mask = htonll(0);
1606 fm->new_cookie = ofm->cookie;
1607 } else {
aa319503
BP
1608 fm->cookie = ofm->cookie;
1609 fm->cookie_mask = ofm->cookie_mask;
b8266395 1610 fm->new_cookie = OVS_BE64_MAX;
aa319503 1611 }
23342857 1612 fm->modify_cookie = false;
aa319503 1613 fm->command = ofm->command;
0e197060
BP
1614
1615 /* Get table ID.
1616 *
083761ad
SH
1617 * OF1.1 entirely forbids table_id == OFPTT_ALL.
1618 * OF1.2+ allows table_id == OFPTT_ALL only for deletes. */
aa319503 1619 fm->table_id = ofm->table_id;
083761ad 1620 if (fm->table_id == OFPTT_ALL
0e197060
BP
1621 && (oh->version == OFP11_VERSION
1622 || (ofm->command != OFPFC_DELETE &&
1623 ofm->command != OFPFC_DELETE_STRICT))) {
1624 return OFPERR_OFPFMFC_BAD_TABLE_ID;
1625 }
1626
2e4f5fcf
BP
1627 fm->idle_timeout = ntohs(ofm->idle_timeout);
1628 fm->hard_timeout = ntohs(ofm->hard_timeout);
ca26eb44
RB
1629 if (oh->version >= OFP14_VERSION && ofm->command == OFPFC_ADD) {
1630 fm->importance = ntohs(ofm->importance);
1631 } else {
1632 fm->importance = 0;
1633 }
2e4f5fcf 1634 fm->buffer_id = ntohl(ofm->buffer_id);
aa319503 1635 error = ofputil_port_from_ofp11(ofm->out_port, &fm->out_port);
2e4f5fcf
BP
1636 if (error) {
1637 return error;
1638 }
7395c052 1639
1fe4c0a0
BP
1640 fm->out_group = (ofm->command == OFPFC_DELETE ||
1641 ofm->command == OFPFC_DELETE_STRICT
1642 ? ntohl(ofm->out_group)
30ef36c6 1643 : OFPG_ANY);
0fb88c18 1644 raw_flags = ofm->flags;
aa319503 1645 } else {
0fb88c18
BP
1646 uint16_t command;
1647
aa319503
BP
1648 if (raw == OFPRAW_OFPT10_FLOW_MOD) {
1649 /* Standard OpenFlow 1.0 flow_mod. */
1650 const struct ofp10_flow_mod *ofm;
aa319503
BP
1651
1652 /* Get the ofp10_flow_mod. */
1653 ofm = ofpbuf_pull(&b, sizeof *ofm);
1654
aa319503 1655 /* Translate the rule. */
81a76618
BP
1656 ofputil_match_from_ofp10_match(&ofm->match, &fm->match);
1657 ofputil_normalize_match(&fm->match);
aa319503 1658
81a76618
BP
1659 /* OpenFlow 1.0 says that exact-match rules have to have the
1660 * highest possible priority. */
1661 fm->priority = (ofm->match.wildcards & htonl(OFPFW10_ALL)
1662 ? ntohs(ofm->priority)
1663 : UINT16_MAX);
1664
aa319503
BP
1665 /* Translate the message. */
1666 command = ntohs(ofm->command);
1667 fm->cookie = htonll(0);
1668 fm->cookie_mask = htonll(0);
1669 fm->new_cookie = ofm->cookie;
1670 fm->idle_timeout = ntohs(ofm->idle_timeout);
1671 fm->hard_timeout = ntohs(ofm->hard_timeout);
ca26eb44 1672 fm->importance = 0;
aa319503 1673 fm->buffer_id = ntohl(ofm->buffer_id);
4e022ec0 1674 fm->out_port = u16_to_ofp(ntohs(ofm->out_port));
30ef36c6 1675 fm->out_group = OFPG_ANY;
0fb88c18 1676 raw_flags = ofm->flags;
aa319503
BP
1677 } else if (raw == OFPRAW_NXT_FLOW_MOD) {
1678 /* Nicira extended flow_mod. */
1679 const struct nx_flow_mod *nfm;
aa319503
BP
1680
1681 /* Dissect the message. */
1682 nfm = ofpbuf_pull(&b, sizeof *nfm);
81a76618
BP
1683 error = nx_pull_match(&b, ntohs(nfm->match_len),
1684 &fm->match, &fm->cookie, &fm->cookie_mask);
aa319503
BP
1685 if (error) {
1686 return error;
1687 }
aa319503
BP
1688
1689 /* Translate the message. */
1690 command = ntohs(nfm->command);
1691 if ((command & 0xff) == OFPFC_ADD && fm->cookie_mask) {
1692 /* Flow additions may only set a new cookie, not match an
1693 * existing cookie. */
1694 return OFPERR_NXBRC_NXM_INVALID;
1695 }
81a76618 1696 fm->priority = ntohs(nfm->priority);
aa319503
BP
1697 fm->new_cookie = nfm->cookie;
1698 fm->idle_timeout = ntohs(nfm->idle_timeout);
1699 fm->hard_timeout = ntohs(nfm->hard_timeout);
ca26eb44 1700 fm->importance = 0;
aa319503 1701 fm->buffer_id = ntohl(nfm->buffer_id);
4e022ec0 1702 fm->out_port = u16_to_ofp(ntohs(nfm->out_port));
30ef36c6 1703 fm->out_group = OFPG_ANY;
0fb88c18 1704 raw_flags = nfm->flags;
aa319503 1705 } else {
428b2edd 1706 OVS_NOT_REACHED();
aa319503
BP
1707 }
1708
b8266395 1709 fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX;
aa319503
BP
1710 if (protocol & OFPUTIL_P_TID) {
1711 fm->command = command & 0xff;
1712 fm->table_id = command >> 8;
1713 } else {
1f42be1c
JR
1714 if (command > 0xff) {
1715 VLOG_WARN_RL(&bad_ofmsg_rl, "flow_mod has explicit table_id "
1716 "but flow_mod_table_id extension is not enabled");
1717 }
aa319503
BP
1718 fm->command = command;
1719 fm->table_id = 0xff;
e729e793 1720 }
2e4f5fcf
BP
1721 }
1722
1f42be1c
JR
1723 if (fm->command > OFPFC_DELETE_STRICT) {
1724 return OFPERR_OFPFMFC_BAD_COMMAND;
1725 }
1726
6fd6ed71 1727 error = ofpacts_pull_openflow_instructions(&b, b.size,
8f2cded4
BP
1728 oh->version, ofpacts);
1729 if (error) {
1730 return error;
1731 }
6fd6ed71
PS
1732 fm->ofpacts = ofpacts->data;
1733 fm->ofpacts_len = ofpacts->size;
6c1491fb 1734
0fb88c18
BP
1735 error = ofputil_decode_flow_mod_flags(raw_flags, fm->command,
1736 oh->version, &fm->flags);
1737 if (error) {
1738 return error;
1739 }
1740
1741 if (fm->flags & OFPUTIL_FF_EMERG) {
1742 /* We do not support the OpenFlow 1.0 emergency flow cache, which
1743 * is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
1744 *
1745 * OpenFlow 1.0 specifies the error code to use when idle_timeout
1746 * or hard_timeout is nonzero. Otherwise, there is no good error
1747 * code, so just state that the flow table is full. */
1748 return (fm->hard_timeout || fm->idle_timeout
1749 ? OFPERR_OFPFMFC_BAD_EMERG_TIMEOUT
1750 : OFPERR_OFPFMFC_TABLE_FULL);
1751 }
1752
ba2fe8e9
BP
1753 return ofpacts_check_consistency(fm->ofpacts, fm->ofpacts_len,
1754 &fm->match.flow, max_port,
1755 fm->table_id, max_table, protocol);
2e4f5fcf
BP
1756}
1757
638a19b0
JR
1758static enum ofperr
1759ofputil_pull_bands(struct ofpbuf *msg, size_t len, uint16_t *n_bands,
1760 struct ofpbuf *bands)
1761{
1762 const struct ofp13_meter_band_header *ombh;
1763 struct ofputil_meter_band *mb;
1764 uint16_t n = 0;
1765
1766 ombh = ofpbuf_try_pull(msg, len);
1767 if (!ombh) {
1768 return OFPERR_OFPBRC_BAD_LEN;
1769 }
1770
1771 while (len >= sizeof (struct ofp13_meter_band_drop)) {
1772 size_t ombh_len = ntohs(ombh->len);
0445637d 1773 /* All supported band types have the same length. */
638a19b0
JR
1774 if (ombh_len != sizeof (struct ofp13_meter_band_drop)) {
1775 return OFPERR_OFPBRC_BAD_LEN;
1776 }
1777 mb = ofpbuf_put_uninit(bands, sizeof *mb);
1778 mb->type = ntohs(ombh->type);
f99d6aa0
BP
1779 if (mb->type != OFPMBT13_DROP && mb->type != OFPMBT13_DSCP_REMARK) {
1780 return OFPERR_OFPMMFC_BAD_BAND;
1781 }
638a19b0
JR
1782 mb->rate = ntohl(ombh->rate);
1783 mb->burst_size = ntohl(ombh->burst_size);
1784 mb->prec_level = (mb->type == OFPMBT13_DSCP_REMARK) ?
1785 ((struct ofp13_meter_band_dscp_remark *)ombh)->prec_level : 0;
1786 n++;
1787 len -= ombh_len;
db5a1019
AW
1788 ombh = ALIGNED_CAST(struct ofp13_meter_band_header *,
1789 (char *) ombh + ombh_len);
638a19b0
JR
1790 }
1791 if (len) {
1792 return OFPERR_OFPBRC_BAD_LEN;
1793 }
1794 *n_bands = n;
1795 return 0;
1796}
1797
1798enum ofperr
1799ofputil_decode_meter_mod(const struct ofp_header *oh,
1800 struct ofputil_meter_mod *mm,
1801 struct ofpbuf *bands)
1802{
0a2869d5 1803 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
638a19b0 1804 ofpraw_pull_assert(&b);
0a2869d5 1805 const struct ofp13_meter_mod *omm = ofpbuf_pull(&b, sizeof *omm);
638a19b0
JR
1806
1807 /* Translate the message. */
1808 mm->command = ntohs(omm->command);
142cdb01
BP
1809 if (mm->command != OFPMC13_ADD &&
1810 mm->command != OFPMC13_MODIFY &&
1811 mm->command != OFPMC13_DELETE) {
1812 return OFPERR_OFPMMFC_BAD_COMMAND;
1813 }
638a19b0
JR
1814 mm->meter.meter_id = ntohl(omm->meter_id);
1815
1816 if (mm->command == OFPMC13_DELETE) {
1817 mm->meter.flags = 0;
1818 mm->meter.n_bands = 0;
1819 mm->meter.bands = NULL;
1820 } else {
1821 enum ofperr error;
1822
1823 mm->meter.flags = ntohs(omm->flags);
13b1febe
BP
1824 if (mm->meter.flags & OFPMF13_KBPS &&
1825 mm->meter.flags & OFPMF13_PKTPS) {
1826 return OFPERR_OFPMMFC_BAD_FLAGS;
1827 }
6fd6ed71 1828 mm->meter.bands = bands->data;
638a19b0 1829
6fd6ed71 1830 error = ofputil_pull_bands(&b, b.size, &mm->meter.n_bands, bands);
638a19b0
JR
1831 if (error) {
1832 return error;
1833 }
1834 }
1835 return 0;
1836}
1837
1838void
1839ofputil_decode_meter_request(const struct ofp_header *oh, uint32_t *meter_id)
1840{
1841 const struct ofp13_meter_multipart_request *omr = ofpmsg_body(oh);
1842 *meter_id = ntohl(omr->meter_id);
1843}
1844
1845struct ofpbuf *
1846ofputil_encode_meter_request(enum ofp_version ofp_version,
1847 enum ofputil_meter_request_type type,
1848 uint32_t meter_id)
1849{
1850 struct ofpbuf *msg;
1851
1852 enum ofpraw raw;
1853
1854 switch (type) {
1855 case OFPUTIL_METER_CONFIG:
1856 raw = OFPRAW_OFPST13_METER_CONFIG_REQUEST;
1857 break;
1858 case OFPUTIL_METER_STATS:
1859 raw = OFPRAW_OFPST13_METER_REQUEST;
1860 break;
1861 default:
1862 case OFPUTIL_METER_FEATURES:
1863 raw = OFPRAW_OFPST13_METER_FEATURES_REQUEST;
1864 break;
1865 }
1866
1867 msg = ofpraw_alloc(raw, ofp_version, 0);
1868
1869 if (type != OFPUTIL_METER_FEATURES) {
1870 struct ofp13_meter_multipart_request *omr;
1871 omr = ofpbuf_put_zeros(msg, sizeof *omr);
1872 omr->meter_id = htonl(meter_id);
1873 }
1874 return msg;
1875}
1876
1877static void
1878ofputil_put_bands(uint16_t n_bands, const struct ofputil_meter_band *mb,
1879 struct ofpbuf *msg)
1880{
1881 uint16_t n = 0;
1882
1883 for (n = 0; n < n_bands; ++n) {
0445637d 1884 /* Currently all band types have same size. */
638a19b0
JR
1885 struct ofp13_meter_band_dscp_remark *ombh;
1886 size_t ombh_len = sizeof *ombh;
1887
1888 ombh = ofpbuf_put_zeros(msg, ombh_len);
1889
1890 ombh->type = htons(mb->type);
1891 ombh->len = htons(ombh_len);
1892 ombh->rate = htonl(mb->rate);
1893 ombh->burst_size = htonl(mb->burst_size);
1894 ombh->prec_level = mb->prec_level;
1895
1896 mb++;
1897 }
1898}
1899
1900/* Encode a meter stat for 'mc' and append it to 'replies'. */
1901void
ca6ba700 1902ofputil_append_meter_config(struct ovs_list *replies,
638a19b0
JR
1903 const struct ofputil_meter_config *mc)
1904{
417e7e66 1905 struct ofpbuf *msg = ofpbuf_from_list(ovs_list_back(replies));
6fd6ed71 1906 size_t start_ofs = msg->size;
6a5490c6 1907 struct ofp13_meter_config *reply;
638a19b0 1908
6a5490c6 1909 ofpbuf_put_uninit(msg, sizeof *reply);
638a19b0
JR
1910 ofputil_put_bands(mc->n_bands, mc->bands, msg);
1911
32756a57 1912 reply = ofpbuf_at_assert(msg, start_ofs, sizeof *reply);
6a5490c6
BP
1913 reply->flags = htons(mc->flags);
1914 reply->meter_id = htonl(mc->meter_id);
6fd6ed71 1915 reply->length = htons(msg->size - start_ofs);
638a19b0
JR
1916
1917 ofpmp_postappend(replies, start_ofs);
1918}
1919
1920/* Encode a meter stat for 'ms' and append it to 'replies'. */
1921void
ca6ba700 1922ofputil_append_meter_stats(struct ovs_list *replies,
638a19b0
JR
1923 const struct ofputil_meter_stats *ms)
1924{
1925 struct ofp13_meter_stats *reply;
1926 uint16_t n = 0;
1927 uint16_t len;
1928
1929 len = sizeof *reply + ms->n_bands * sizeof(struct ofp13_meter_band_stats);
1930 reply = ofpmp_append(replies, len);
1931
1932 reply->meter_id = htonl(ms->meter_id);
1933 reply->len = htons(len);
1934 memset(reply->pad, 0, sizeof reply->pad);
1935 reply->flow_count = htonl(ms->flow_count);
1936 reply->packet_in_count = htonll(ms->packet_in_count);
1937 reply->byte_in_count = htonll(ms->byte_in_count);
1938 reply->duration_sec = htonl(ms->duration_sec);
1939 reply->duration_nsec = htonl(ms->duration_nsec);
1940
1941 for (n = 0; n < ms->n_bands; ++n) {
1942 const struct ofputil_meter_band_stats *src = &ms->bands[n];
1943 struct ofp13_meter_band_stats *dst = &reply->band_stats[n];
1944
1945 dst->packet_band_count = htonll(src->packet_count);
1946 dst->byte_band_count = htonll(src->byte_count);
1947 }
1948}
1949
1950/* Converts an OFPMP_METER_CONFIG reply in 'msg' into an abstract
1951 * ofputil_meter_config in 'mc', with mc->bands pointing to bands decoded into
1952 * 'bands'. The caller must have initialized 'bands' and retains ownership of
1953 * it across the call.
1954 *
1955 * Multiple OFPST13_METER_CONFIG replies can be packed into a single OpenFlow
1956 * message. Calling this function multiple times for a single 'msg' iterates
1957 * through the replies. 'bands' is cleared for each reply.
1958 *
1959 * Returns 0 if successful, EOF if no replies were left in this 'msg',
1960 * otherwise a positive errno value. */
1961int
1962ofputil_decode_meter_config(struct ofpbuf *msg,
1963 struct ofputil_meter_config *mc,
1964 struct ofpbuf *bands)
1965{
1966 const struct ofp13_meter_config *omc;
1967 enum ofperr err;
1968
1969 /* Pull OpenFlow headers for the first call. */
6fd6ed71 1970 if (!msg->header) {
638a19b0
JR
1971 ofpraw_pull_assert(msg);
1972 }
1973
6fd6ed71 1974 if (!msg->size) {
638a19b0
JR
1975 return EOF;
1976 }
1977
1978 omc = ofpbuf_try_pull(msg, sizeof *omc);
1979 if (!omc) {
0445637d 1980 VLOG_WARN_RL(&bad_ofmsg_rl,
437d0d22 1981 "OFPMP_METER_CONFIG reply has %"PRIu32" leftover bytes at end",
6fd6ed71 1982 msg->size);
638a19b0
JR
1983 return OFPERR_OFPBRC_BAD_LEN;
1984 }
1985
1986 ofpbuf_clear(bands);
1987 err = ofputil_pull_bands(msg, ntohs(omc->length) - sizeof *omc,
1988 &mc->n_bands, bands);
1989 if (err) {
1990 return err;
1991 }
1992 mc->meter_id = ntohl(omc->meter_id);
1993 mc->flags = ntohs(omc->flags);
6fd6ed71 1994 mc->bands = bands->data;
638a19b0
JR
1995
1996 return 0;
1997}
1998
1999static enum ofperr
2000ofputil_pull_band_stats(struct ofpbuf *msg, size_t len, uint16_t *n_bands,
2001 struct ofpbuf *bands)
2002{
2003 const struct ofp13_meter_band_stats *ombs;
2004 struct ofputil_meter_band_stats *mbs;
2005 uint16_t n, i;
2006
0445637d
JR
2007 ombs = ofpbuf_try_pull(msg, len);
2008 if (!ombs) {
2009 return OFPERR_OFPBRC_BAD_LEN;
2010 }
2011
638a19b0
JR
2012 n = len / sizeof *ombs;
2013 if (len != n * sizeof *ombs) {
2014 return OFPERR_OFPBRC_BAD_LEN;
2015 }
2016
638a19b0
JR
2017 mbs = ofpbuf_put_uninit(bands, len);
2018
2019 for (i = 0; i < n; ++i) {
2020 mbs[i].packet_count = ntohll(ombs[i].packet_band_count);
2021 mbs[i].byte_count = ntohll(ombs[i].byte_band_count);
2022 }
2023 *n_bands = n;
2024 return 0;
2025}
2026
2027/* Converts an OFPMP_METER reply in 'msg' into an abstract
2028 * ofputil_meter_stats in 'ms', with ms->bands pointing to band stats
2029 * decoded into 'bands'.
2030 *
2031 * Multiple OFPMP_METER replies can be packed into a single OpenFlow
2032 * message. Calling this function multiple times for a single 'msg' iterates
2033 * through the replies. 'bands' is cleared for each reply.
2034 *
2035 * Returns 0 if successful, EOF if no replies were left in this 'msg',
2036 * otherwise a positive errno value. */
2037int
2038ofputil_decode_meter_stats(struct ofpbuf *msg,
2039 struct ofputil_meter_stats *ms,
2040 struct ofpbuf *bands)
2041{
2042 const struct ofp13_meter_stats *oms;
638a19b0
JR
2043 enum ofperr err;
2044
2045 /* Pull OpenFlow headers for the first call. */
6fd6ed71 2046 if (!msg->header) {
638a19b0
JR
2047 ofpraw_pull_assert(msg);
2048 }
2049
6fd6ed71 2050 if (!msg->size) {
638a19b0
JR
2051 return EOF;
2052 }
2053
2054 oms = ofpbuf_try_pull(msg, sizeof *oms);
2055 if (!oms) {
0445637d 2056 VLOG_WARN_RL(&bad_ofmsg_rl,
437d0d22 2057 "OFPMP_METER reply has %"PRIu32" leftover bytes at end",
6fd6ed71 2058 msg->size);
638a19b0
JR
2059 return OFPERR_OFPBRC_BAD_LEN;
2060 }
638a19b0
JR
2061
2062 ofpbuf_clear(bands);
0445637d
JR
2063 err = ofputil_pull_band_stats(msg, ntohs(oms->len) - sizeof *oms,
2064 &ms->n_bands, bands);
638a19b0
JR
2065 if (err) {
2066 return err;
2067 }
2068 ms->meter_id = ntohl(oms->meter_id);
2069 ms->flow_count = ntohl(oms->flow_count);
2070 ms->packet_in_count = ntohll(oms->packet_in_count);
2071 ms->byte_in_count = ntohll(oms->byte_in_count);
2072 ms->duration_sec = ntohl(oms->duration_sec);
2073 ms->duration_nsec = ntohl(oms->duration_nsec);
6fd6ed71 2074 ms->bands = bands->data;
638a19b0
JR
2075
2076 return 0;
2077}
2078
2079void
2080ofputil_decode_meter_features(const struct ofp_header *oh,
2081 struct ofputil_meter_features *mf)
2082{
2083 const struct ofp13_meter_features *omf = ofpmsg_body(oh);
2084
2085 mf->max_meters = ntohl(omf->max_meter);
2086 mf->band_types = ntohl(omf->band_types);
2087 mf->capabilities = ntohl(omf->capabilities);
2088 mf->max_bands = omf->max_bands;
2089 mf->max_color = omf->max_color;
2090}
2091
2092struct ofpbuf *
2093ofputil_encode_meter_features_reply(const struct ofputil_meter_features *mf,
2094 const struct ofp_header *request)
2095{
2096 struct ofpbuf *reply;
2097 struct ofp13_meter_features *omf;
2098
2099 reply = ofpraw_alloc_stats_reply(request, 0);
2100 omf = ofpbuf_put_zeros(reply, sizeof *omf);
2101
2102 omf->max_meter = htonl(mf->max_meters);
2103 omf->band_types = htonl(mf->band_types);
2104 omf->capabilities = htonl(mf->capabilities);
2105 omf->max_bands = mf->max_bands;
2106 omf->max_color = mf->max_color;
2107
2108 return reply;
2109}
2110
2111struct ofpbuf *
2112ofputil_encode_meter_mod(enum ofp_version ofp_version,
2113 const struct ofputil_meter_mod *mm)
2114{
2115 struct ofpbuf *msg;
2116
2117 struct ofp13_meter_mod *omm;
2118
2119 msg = ofpraw_alloc(OFPRAW_OFPT13_METER_MOD, ofp_version,
2120 NXM_TYPICAL_LEN + mm->meter.n_bands * 16);
2121 omm = ofpbuf_put_zeros(msg, sizeof *omm);
2122 omm->command = htons(mm->command);
2123 if (mm->command != OFPMC13_DELETE) {
2124 omm->flags = htons(mm->meter.flags);
2125 }
2126 omm->meter_id = htonl(mm->meter.meter_id);
2127
2128 ofputil_put_bands(mm->meter.n_bands, mm->meter.bands, msg);
2129
2130 ofpmsg_update_length(msg);
2131 return msg;
2132}
2133
aa6305ea
SH
2134static ovs_be16
2135ofputil_tid_command(const struct ofputil_flow_mod *fm,
2136 enum ofputil_protocol protocol)
2137{
2138 return htons(protocol & OFPUTIL_P_TID
2139 ? (fm->command & 0xff) | (fm->table_id << 8)
2140 : fm->command);
2141}
2142
2e4f5fcf 2143/* Converts 'fm' into an OFPT_FLOW_MOD or NXT_FLOW_MOD message according to
6cbe2c0f 2144 * 'protocol' and returns the message. */
2e4f5fcf 2145struct ofpbuf *
a9a2da38 2146ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
27527aa0 2147 enum ofputil_protocol protocol)
2e4f5fcf 2148{
0fb88c18
BP
2149 enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
2150 ovs_be16 raw_flags = ofputil_encode_flow_mod_flags(fm->flags, version);
2e4f5fcf
BP
2151 struct ofpbuf *msg;
2152
27527aa0 2153 switch (protocol) {
75fa58f8 2154 case OFPUTIL_P_OF11_STD:
2e1ae200 2155 case OFPUTIL_P_OF12_OXM:
c37c0382 2156 case OFPUTIL_P_OF13_OXM:
42dccab5 2157 case OFPUTIL_P_OF14_OXM:
b79d45a1
BP
2158 case OFPUTIL_P_OF15_OXM:
2159 case OFPUTIL_P_OF16_OXM: {
aa6305ea 2160 struct ofp11_flow_mod *ofm;
75fa58f8 2161 int tailroom;
aa6305ea 2162
75fa58f8 2163 tailroom = ofputil_match_typical_len(protocol) + fm->ofpacts_len;
0fb88c18 2164 msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, version, tailroom);
aa6305ea 2165 ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
75fa58f8
BP
2166 if ((protocol == OFPUTIL_P_OF11_STD
2167 && (fm->command == OFPFC_MODIFY ||
2168 fm->command == OFPFC_MODIFY_STRICT)
2169 && fm->cookie_mask == htonll(0))
2170 || fm->command == OFPFC_ADD) {
a5ff8823
SH
2171 ofm->cookie = fm->new_cookie;
2172 } else {
ba5cc068 2173 ofm->cookie = fm->cookie & fm->cookie_mask;
a5ff8823 2174 }
aa6305ea 2175 ofm->cookie_mask = fm->cookie_mask;
083761ad 2176 if (fm->table_id != OFPTT_ALL
0e197060
BP
2177 || (protocol != OFPUTIL_P_OF11_STD
2178 && (fm->command == OFPFC_DELETE ||
2179 fm->command == OFPFC_DELETE_STRICT))) {
2180 ofm->table_id = fm->table_id;
2181 } else {
2182 ofm->table_id = 0;
2183 }
aa6305ea
SH
2184 ofm->command = fm->command;
2185 ofm->idle_timeout = htons(fm->idle_timeout);
2186 ofm->hard_timeout = htons(fm->hard_timeout);
81a76618 2187 ofm->priority = htons(fm->priority);
aa6305ea
SH
2188 ofm->buffer_id = htonl(fm->buffer_id);
2189 ofm->out_port = ofputil_port_to_ofp11(fm->out_port);
7395c052 2190 ofm->out_group = htonl(fm->out_group);
0fb88c18 2191 ofm->flags = raw_flags;
ca26eb44
RB
2192 if (version >= OFP14_VERSION && fm->command == OFPFC_ADD) {
2193 ofm->importance = htons(fm->importance);
2194 } else {
2195 ofm->importance = 0;
2196 }
75fa58f8 2197 ofputil_put_ofp11_match(msg, &fm->match, protocol);
e3f8f887
JR
2198 ofpacts_put_openflow_instructions(fm->ofpacts, fm->ofpacts_len, msg,
2199 version);
aa6305ea
SH
2200 break;
2201 }
2202
85813857
BP
2203 case OFPUTIL_P_OF10_STD:
2204 case OFPUTIL_P_OF10_STD_TID: {
3f192f23
SH
2205 struct ofp10_flow_mod *ofm;
2206
982697a4
BP
2207 msg = ofpraw_alloc(OFPRAW_OFPT10_FLOW_MOD, OFP10_VERSION,
2208 fm->ofpacts_len);
2209 ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
81a76618 2210 ofputil_match_to_ofp10_match(&fm->match, &ofm->match);
623e1caf 2211 ofm->cookie = fm->new_cookie;
aa6305ea 2212 ofm->command = ofputil_tid_command(fm, protocol);
2e4f5fcf
BP
2213 ofm->idle_timeout = htons(fm->idle_timeout);
2214 ofm->hard_timeout = htons(fm->hard_timeout);
81a76618 2215 ofm->priority = htons(fm->priority);
2e4f5fcf 2216 ofm->buffer_id = htonl(fm->buffer_id);
4e022ec0 2217 ofm->out_port = htons(ofp_to_u16(fm->out_port));
0fb88c18 2218 ofm->flags = raw_flags;
e3f8f887
JR
2219 ofpacts_put_openflow_actions(fm->ofpacts, fm->ofpacts_len, msg,
2220 version);
27527aa0 2221 break;
3f192f23 2222 }
2e4f5fcf 2223
85813857
BP
2224 case OFPUTIL_P_OF10_NXM:
2225 case OFPUTIL_P_OF10_NXM_TID: {
3f192f23
SH
2226 struct nx_flow_mod *nfm;
2227 int match_len;
2228
982697a4
BP
2229 msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD, OFP10_VERSION,
2230 NXM_TYPICAL_LEN + fm->ofpacts_len);
2231 nfm = ofpbuf_put_zeros(msg, sizeof *nfm);
aa6305ea 2232 nfm->command = ofputil_tid_command(fm, protocol);
623e1caf 2233 nfm->cookie = fm->new_cookie;
81a76618 2234 match_len = nx_put_match(msg, &fm->match, fm->cookie, fm->cookie_mask);
6fd6ed71 2235 nfm = msg->msg;
2e4f5fcf
BP
2236 nfm->idle_timeout = htons(fm->idle_timeout);
2237 nfm->hard_timeout = htons(fm->hard_timeout);
81a76618 2238 nfm->priority = htons(fm->priority);
2e4f5fcf 2239 nfm->buffer_id = htonl(fm->buffer_id);
4e022ec0 2240 nfm->out_port = htons(ofp_to_u16(fm->out_port));
0fb88c18 2241 nfm->flags = raw_flags;
2e4f5fcf 2242 nfm->match_len = htons(match_len);
e3f8f887
JR
2243 ofpacts_put_openflow_actions(fm->ofpacts, fm->ofpacts_len, msg,
2244 version);
27527aa0 2245 break;
3f192f23 2246 }
27527aa0
BP
2247
2248 default:
428b2edd 2249 OVS_NOT_REACHED();
2e4f5fcf
BP
2250 }
2251
982697a4 2252 ofpmsg_update_length(msg);
2e4f5fcf
BP
2253 return msg;
2254}
2255
90bf1e07 2256static enum ofperr
0157ad3a
SH
2257ofputil_decode_ofpst10_flow_request(struct ofputil_flow_stats_request *fsr,
2258 const struct ofp10_flow_stats_request *ofsr,
2259 bool aggregate)
2e4f5fcf 2260{
2e4f5fcf 2261 fsr->aggregate = aggregate;
81a76618 2262 ofputil_match_from_ofp10_match(&ofsr->match, &fsr->match);
4e022ec0 2263 fsr->out_port = u16_to_ofp(ntohs(ofsr->out_port));
30ef36c6 2264 fsr->out_group = OFPG_ANY;
2e4f5fcf 2265 fsr->table_id = ofsr->table_id;
e729e793 2266 fsr->cookie = fsr->cookie_mask = htonll(0);
2e4f5fcf
BP
2267
2268 return 0;
2269}
2270
0157ad3a
SH
2271static enum ofperr
2272ofputil_decode_ofpst11_flow_request(struct ofputil_flow_stats_request *fsr,
2273 struct ofpbuf *b, bool aggregate)
2274{
2275 const struct ofp11_flow_stats_request *ofsr;
2276 enum ofperr error;
2277
2278 ofsr = ofpbuf_pull(b, sizeof *ofsr);
2279 fsr->aggregate = aggregate;
2280 fsr->table_id = ofsr->table_id;
2281 error = ofputil_port_from_ofp11(ofsr->out_port, &fsr->out_port);
2282 if (error) {
2283 return error;
2284 }
7395c052 2285 fsr->out_group = ntohl(ofsr->out_group);
0157ad3a
SH
2286 fsr->cookie = ofsr->cookie;
2287 fsr->cookie_mask = ofsr->cookie_mask;
81a76618 2288 error = ofputil_pull_ofp11_match(b, &fsr->match, NULL);
0157ad3a
SH
2289 if (error) {
2290 return error;
2291 }
2292
2293 return 0;
2294}
2295
90bf1e07 2296static enum ofperr
81d1ea94 2297ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
982697a4 2298 struct ofpbuf *b, bool aggregate)
2e4f5fcf
BP
2299{
2300 const struct nx_flow_stats_request *nfsr;
90bf1e07 2301 enum ofperr error;
2e4f5fcf 2302
982697a4 2303 nfsr = ofpbuf_pull(b, sizeof *nfsr);
81a76618 2304 error = nx_pull_match(b, ntohs(nfsr->match_len), &fsr->match,
e729e793 2305 &fsr->cookie, &fsr->cookie_mask);
2e4f5fcf
BP
2306 if (error) {
2307 return error;
2308 }
6fd6ed71 2309 if (b->size) {
90bf1e07 2310 return OFPERR_OFPBRC_BAD_LEN;
2e4f5fcf
BP
2311 }
2312
2313 fsr->aggregate = aggregate;
4e022ec0 2314 fsr->out_port = u16_to_ofp(ntohs(nfsr->out_port));
30ef36c6 2315 fsr->out_group = OFPG_ANY;
2e4f5fcf
BP
2316 fsr->table_id = nfsr->table_id;
2317
2318 return 0;
2319}
2320
e8f9a7bb 2321/* Constructs and returns an OFPT_QUEUE_GET_CONFIG request for the specified
e016fb63
BP
2322 * 'port' and 'queue', suitable for OpenFlow version 'version'.
2323 *
2324 * 'queue' is honored only for OpenFlow 1.4 and later; older versions always
2325 * request all queues. */
e8f9a7bb
VG
2326struct ofpbuf *
2327ofputil_encode_queue_get_config_request(enum ofp_version version,
e016fb63
BP
2328 ofp_port_t port,
2329 uint32_t queue)
e8f9a7bb
VG
2330{
2331 struct ofpbuf *request;
2332
2333 if (version == OFP10_VERSION) {
2334 struct ofp10_queue_get_config_request *qgcr10;
2335
2336 request = ofpraw_alloc(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST,
2337 version, 0);
2338 qgcr10 = ofpbuf_put_zeros(request, sizeof *qgcr10);
2339 qgcr10->port = htons(ofp_to_u16(port));
e016fb63 2340 } else if (version < OFP14_VERSION) {
e8f9a7bb
VG
2341 struct ofp11_queue_get_config_request *qgcr11;
2342
2343 request = ofpraw_alloc(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST,
2344 version, 0);
2345 qgcr11 = ofpbuf_put_zeros(request, sizeof *qgcr11);
2346 qgcr11->port = ofputil_port_to_ofp11(port);
e016fb63
BP
2347 } else {
2348 struct ofp14_queue_desc_request *qdr14;
2349
2350 request = ofpraw_alloc(OFPRAW_OFPST14_QUEUE_DESC_REQUEST,
2351 version, 0);
2352 qdr14 = ofpbuf_put_zeros(request, sizeof *qdr14);
2353 qdr14->port = ofputil_port_to_ofp11(port);
2354 qdr14->queue = htonl(queue);
e8f9a7bb
VG
2355 }
2356
2357 return request;
2358}
2359
2360/* Parses OFPT_QUEUE_GET_CONFIG request 'oh', storing the port specified by the
2361 * request into '*port'. Returns 0 if successful, otherwise an OpenFlow error
2362 * code. */
2363enum ofperr
2364ofputil_decode_queue_get_config_request(const struct ofp_header *oh,
e016fb63 2365 ofp_port_t *port, uint32_t *queue)
e8f9a7bb
VG
2366{
2367 const struct ofp10_queue_get_config_request *qgcr10;
2368 const struct ofp11_queue_get_config_request *qgcr11;
e016fb63 2369 const struct ofp14_queue_desc_request *qdr14;
0a2869d5
BP
2370 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2371 enum ofpraw raw = ofpraw_pull_assert(&b);
e8f9a7bb
VG
2372
2373 switch ((int) raw) {
2374 case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST:
6fd6ed71 2375 qgcr10 = b.data;
e8f9a7bb 2376 *port = u16_to_ofp(ntohs(qgcr10->port));
e016fb63 2377 *queue = OFPQ_ALL;
56085be5 2378 break;
e8f9a7bb
VG
2379
2380 case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST:
6fd6ed71 2381 qgcr11 = b.data;
e016fb63 2382 *queue = OFPQ_ALL;
56085be5
BP
2383 enum ofperr error = ofputil_port_from_ofp11(qgcr11->port, port);
2384 if (error || *port == OFPP_ANY) {
2385 return error;
2386 }
2387 break;
2388
e016fb63
BP
2389 case OFPRAW_OFPST14_QUEUE_DESC_REQUEST:
2390 qdr14 = b.data;
2391 *queue = ntohl(qdr14->queue);
2392 return ofputil_port_from_ofp11(qdr14->port, port);
2393
56085be5
BP
2394 default:
2395 OVS_NOT_REACHED();
e8f9a7bb
VG
2396 }
2397
56085be5
BP
2398 return (ofp_to_u16(*port) < ofp_to_u16(OFPP_MAX)
2399 ? 0
2400 : OFPERR_OFPQOFC_BAD_PORT);
e8f9a7bb
VG
2401}
2402
2403/* Constructs and returns the beginning of a reply to
e016fb63
BP
2404 * OFPT_QUEUE_GET_CONFIG_REQUEST or OFPMP_QUEUE_DESC request 'oh'. The caller
2405 * may append information about individual queues with
2406 * ofputil_append_queue_get_config_reply(). */
2407void
2408ofputil_start_queue_get_config_reply(const struct ofp_header *request,
2409 struct ovs_list *replies)
e8f9a7bb 2410{
e8f9a7bb
VG
2411 struct ofpbuf *reply;
2412 enum ofperr error;
e8f9a7bb 2413 ofp_port_t port;
e016fb63 2414 uint32_t queue;
e8f9a7bb 2415
e016fb63 2416 error = ofputil_decode_queue_get_config_request(request, &port, &queue);
e8f9a7bb
VG
2417 ovs_assert(!error);
2418
e016fb63 2419 enum ofpraw raw = ofpraw_decode_assert(request);
e8f9a7bb
VG
2420 switch ((int) raw) {
2421 case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST:
2422 reply = ofpraw_alloc_reply(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY,
e016fb63
BP
2423 request, 0);
2424 struct ofp10_queue_get_config_reply *qgcr10
2425 = ofpbuf_put_zeros(reply, sizeof *qgcr10);
e8f9a7bb
VG
2426 qgcr10->port = htons(ofp_to_u16(port));
2427 break;
2428
2429 case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST:
2430 reply = ofpraw_alloc_reply(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY,
e016fb63
BP
2431 request, 0);
2432 struct ofp11_queue_get_config_reply *qgcr11
2433 = ofpbuf_put_zeros(reply, sizeof *qgcr11);
e8f9a7bb
VG
2434 qgcr11->port = ofputil_port_to_ofp11(port);
2435 break;
2436
e016fb63
BP
2437 case OFPRAW_OFPST14_QUEUE_DESC_REQUEST:
2438 reply = ofpraw_alloc_stats_reply(request, 0);
2439 break;
2440
e8f9a7bb 2441 default:
428b2edd 2442 OVS_NOT_REACHED();
e8f9a7bb
VG
2443 }
2444
417e7e66
BW
2445 ovs_list_init(replies);
2446 ovs_list_push_back(replies, &reply->list_node);
e8f9a7bb
VG
2447}
2448
2449static void
d2e5fa1f
BP
2450put_ofp10_queue_rate(struct ofpbuf *reply,
2451 enum ofp10_queue_properties property, uint16_t rate)
e8f9a7bb
VG
2452{
2453 if (rate != UINT16_MAX) {
d2e5fa1f 2454 struct ofp10_queue_prop_rate *oqpr;
e8f9a7bb
VG
2455
2456 oqpr = ofpbuf_put_zeros(reply, sizeof *oqpr);
2457 oqpr->prop_header.property = htons(property);
2458 oqpr->prop_header.len = htons(sizeof *oqpr);
2459 oqpr->rate = htons(rate);
2460 }
2461}
2462
e016fb63
BP
2463static void
2464put_ofp14_queue_rate(struct ofpbuf *reply,
2465 enum ofp14_queue_desc_prop_type type, uint16_t rate)
2466{
2467 if (rate != UINT16_MAX) {
2468 ofpprop_put_u16(reply, type, rate);
2469 }
2470}
2471
e8f9a7bb 2472void
e016fb63
BP
2473ofputil_append_queue_get_config_reply(const struct ofputil_queue_config *qc,
2474 struct ovs_list *replies)
e8f9a7bb 2475{
e016fb63 2476 enum ofp_version ofp_version = ofpmp_version(replies);
417e7e66 2477 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
e016fb63
BP
2478 size_t start_ofs = reply->size;
2479 size_t len_ofs;
e8f9a7bb
VG
2480 ovs_be16 *len;
2481
e016fb63
BP
2482 if (ofp_version < OFP14_VERSION) {
2483 if (ofp_version < OFP12_VERSION) {
2484 struct ofp10_packet_queue *opq10;
e8f9a7bb 2485
e016fb63
BP
2486 opq10 = ofpbuf_put_zeros(reply, sizeof *opq10);
2487 opq10->queue_id = htonl(qc->queue);
2488 len_ofs = (char *) &opq10->len - (char *) reply->data;
2489 } else {
2490 struct ofp12_packet_queue *opq12;
e8f9a7bb 2491
e016fb63
BP
2492 opq12 = ofpbuf_put_zeros(reply, sizeof *opq12);
2493 opq12->port = ofputil_port_to_ofp11(qc->port);
2494 opq12->queue_id = htonl(qc->queue);
2495 len_ofs = (char *) &opq12->len - (char *) reply->data;
2496 }
e8f9a7bb 2497
e016fb63
BP
2498 put_ofp10_queue_rate(reply, OFPQT10_MIN_RATE, qc->min_rate);
2499 put_ofp10_queue_rate(reply, OFPQT11_MAX_RATE, qc->max_rate);
2500 } else {
2501 struct ofp14_queue_desc *oqd = ofpbuf_put_zeros(reply, sizeof *oqd);
2502 oqd->port_no = ofputil_port_to_ofp11(qc->port);
2503 oqd->queue_id = htonl(qc->queue);
2504 len_ofs = (char *) &oqd->len - (char *) reply->data;
2505 put_ofp14_queue_rate(reply, OFPQDPT14_MIN_RATE, qc->min_rate);
2506 put_ofp14_queue_rate(reply, OFPQDPT14_MAX_RATE, qc->max_rate);
2507 }
e8f9a7bb
VG
2508
2509 len = ofpbuf_at(reply, len_ofs, sizeof *len);
6fd6ed71 2510 *len = htons(reply->size - start_ofs);
e8f9a7bb 2511
e016fb63
BP
2512 if (ofp_version >= OFP14_VERSION) {
2513 ofpmp_postappend(replies, start_ofs);
e8f9a7bb 2514 }
e8f9a7bb
VG
2515}
2516
2517static enum ofperr
d2e5fa1f
BP
2518parse_ofp10_queue_rate(const struct ofp10_queue_prop_header *hdr,
2519 uint16_t *rate)
e8f9a7bb 2520{
d2e5fa1f 2521 const struct ofp10_queue_prop_rate *oqpr;
e8f9a7bb
VG
2522
2523 if (hdr->len == htons(sizeof *oqpr)) {
d2e5fa1f 2524 oqpr = (const struct ofp10_queue_prop_rate *) hdr;
e8f9a7bb
VG
2525 *rate = ntohs(oqpr->rate);
2526 return 0;
2527 } else {
2528 return OFPERR_OFPBRC_BAD_LEN;
2529 }
2530}
2531
e016fb63
BP
2532static int
2533ofputil_pull_queue_get_config_reply10(struct ofpbuf *msg,
2534 struct ofputil_queue_config *queue)
e8f9a7bb 2535{
e016fb63
BP
2536 const struct ofp_header *oh = msg->header;
2537 unsigned int opq_len; /* Length of protocol-specific queue header. */
2538 unsigned int len; /* Total length of queue + properties. */
e8f9a7bb 2539
e016fb63
BP
2540 /* Obtain the port number from the message header. */
2541 if (oh->version == OFP10_VERSION) {
2542 const struct ofp10_queue_get_config_reply *oqgcr10 = msg->msg;
2543 queue->port = u16_to_ofp(ntohs(oqgcr10->port));
2544 } else {
2545 const struct ofp11_queue_get_config_reply *oqgcr11 = msg->msg;
2546 enum ofperr error = ofputil_port_from_ofp11(oqgcr11->port,
2547 &queue->port);
2548 if (error) {
2549 return error;
2550 }
e8f9a7bb
VG
2551 }
2552
e016fb63 2553 /* Pull off the queue header and get the queue number and length. */
e8f9a7bb
VG
2554 if (oh->version < OFP12_VERSION) {
2555 const struct ofp10_packet_queue *opq10;
e016fb63 2556 opq10 = ofpbuf_try_pull(msg, sizeof *opq10);
e8f9a7bb
VG
2557 if (!opq10) {
2558 return OFPERR_OFPBRC_BAD_LEN;
2559 }
e016fb63 2560 queue->queue = ntohl(opq10->queue_id);
e8f9a7bb
VG
2561 len = ntohs(opq10->len);
2562 opq_len = sizeof *opq10;
2563 } else {
2564 const struct ofp12_packet_queue *opq12;
e016fb63 2565 opq12 = ofpbuf_try_pull(msg, sizeof *opq12);
e8f9a7bb
VG
2566 if (!opq12) {
2567 return OFPERR_OFPBRC_BAD_LEN;
2568 }
e016fb63 2569 queue->queue = ntohl(opq12->queue_id);
e8f9a7bb
VG
2570 len = ntohs(opq12->len);
2571 opq_len = sizeof *opq12;
2572 }
2573
e016fb63
BP
2574 /* Length check. */
2575 if (len < opq_len || len > msg->size + opq_len || len % 8) {
e8f9a7bb
VG
2576 return OFPERR_OFPBRC_BAD_LEN;
2577 }
2578 len -= opq_len;
2579
e016fb63
BP
2580 /* Pull properties. The format of these properties differs from used in
2581 * OF1.4+ so we can't use the common property functions. */
e8f9a7bb 2582 while (len > 0) {
d2e5fa1f 2583 const struct ofp10_queue_prop_header *hdr;
e8f9a7bb
VG
2584 unsigned int property;
2585 unsigned int prop_len;
2586 enum ofperr error = 0;
2587
e016fb63 2588 hdr = ofpbuf_at_assert(msg, 0, sizeof *hdr);
e8f9a7bb 2589 prop_len = ntohs(hdr->len);
e016fb63 2590 if (prop_len < sizeof *hdr || prop_len > msg->size || prop_len % 8) {
e8f9a7bb
VG
2591 return OFPERR_OFPBRC_BAD_LEN;
2592 }
2593
2594 property = ntohs(hdr->property);
2595 switch (property) {
d2e5fa1f
BP
2596 case OFPQT10_MIN_RATE:
2597 error = parse_ofp10_queue_rate(hdr, &queue->min_rate);
e8f9a7bb
VG
2598 break;
2599
d2e5fa1f
BP
2600 case OFPQT11_MAX_RATE:
2601 error = parse_ofp10_queue_rate(hdr, &queue->max_rate);
e8f9a7bb
VG
2602 break;
2603
2604 default:
2605 VLOG_INFO_RL(&bad_ofmsg_rl, "unknown queue property %u", property);
2606 break;
2607 }
2608 if (error) {
2609 return error;
2610 }
2611
e016fb63 2612 ofpbuf_pull(msg, prop_len);
e8f9a7bb
VG
2613 len -= prop_len;
2614 }
2615 return 0;
2616}
2617
e016fb63
BP
2618static int
2619ofputil_pull_queue_get_config_reply14(struct ofpbuf *msg,
2620 struct ofputil_queue_config *queue)
2621{
2622 struct ofp14_queue_desc *oqd14 = ofpbuf_try_pull(msg, sizeof *oqd14);
2623 if (!oqd14) {
2624 return OFPERR_OFPBRC_BAD_LEN;
2625 }
2626 enum ofperr error = ofputil_port_from_ofp11(oqd14->port_no, &queue->port);
2627 if (error) {
2628 return error;
2629 }
2630 queue->queue = ntohl(oqd14->queue_id);
2631
2632 /* Length check. */
2633 unsigned int len = ntohs(oqd14->len);
2634 if (len < sizeof *oqd14 || len > msg->size + sizeof *oqd14 || len % 8) {
2635 return OFPERR_OFPBRC_BAD_LEN;
2636 }
2637 len -= sizeof *oqd14;
2638
0a2869d5
BP
2639 struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
2640 len);
e016fb63
BP
2641 while (properties.size > 0) {
2642 struct ofpbuf payload;
2643 uint64_t type;
2644
2645 error = ofpprop_pull(&properties, &payload, &type);
2646 if (error) {
2647 return error;
2648 }
2649
2650 switch (type) {
2651 case OFPQDPT14_MIN_RATE:
2652 error = ofpprop_parse_u16(&payload, &queue->min_rate);
2653 break;
2654
2655 case OFPQDPT14_MAX_RATE:
2656 error = ofpprop_parse_u16(&payload, &queue->max_rate);
2657 break;
2658
2659 default:
2660 error = OFPPROP_UNKNOWN(true, "queue desc", type);
2661 break;
2662 }
2663
2664 if (error) {
2665 return error;
2666 }
2667 }
2668
2669 return 0;
2670}
2671
2672/* Decodes information about a queue from the OFPT_QUEUE_GET_CONFIG_REPLY in
2673 * 'reply' and stores it in '*queue'. ofputil_decode_queue_get_config_reply()
2674 * must already have pulled off the main header.
2675 *
2676 * This function returns EOF if the last queue has already been decoded, 0 if a
2677 * queue was successfully decoded into '*queue', or an ofperr if there was a
2678 * problem decoding 'reply'. */
2679int
2680ofputil_pull_queue_get_config_reply(struct ofpbuf *msg,
2681 struct ofputil_queue_config *queue)
2682{
2683 enum ofpraw raw;
2684 if (!msg->header) {
2685 /* Pull OpenFlow header. */
2686 raw = ofpraw_pull_assert(msg);
2687
2688 /* Pull protocol-specific ofp_queue_get_config_reply header (OF1.4
2689 * doesn't have one at all). */
2690 if (raw == OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY) {
2691 ofpbuf_pull(msg, sizeof(struct ofp10_queue_get_config_reply));
2692 } else if (raw == OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY) {
2693 ofpbuf_pull(msg, sizeof(struct ofp11_queue_get_config_reply));
2694 } else {
2695 ovs_assert(raw == OFPRAW_OFPST14_QUEUE_DESC_REPLY);
2696 }
2697 } else {
2698 raw = ofpraw_decode_assert(msg->header);
2699 }
2700
2701 queue->min_rate = UINT16_MAX;
2702 queue->max_rate = UINT16_MAX;
2703
2704 if (!msg->size) {
2705 return EOF;
2706 } else if (raw == OFPRAW_OFPST14_QUEUE_DESC_REPLY) {
2707 return ofputil_pull_queue_get_config_reply14(msg, queue);
2708 } else {
2709 return ofputil_pull_queue_get_config_reply10(msg, queue);
2710 }
2711}
2712
2e4f5fcf 2713/* Converts an OFPST_FLOW, OFPST_AGGREGATE, NXST_FLOW, or NXST_AGGREGATE
b78f6b77
BP
2714 * request 'oh', into an abstract flow_stats_request in 'fsr'. Returns 0 if
2715 * successful, otherwise an OpenFlow error code. */
90bf1e07 2716enum ofperr
81d1ea94 2717ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *fsr,
b78f6b77 2718 const struct ofp_header *oh)
2e4f5fcf 2719{
0a2869d5
BP
2720 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2721 enum ofpraw raw = ofpraw_pull_assert(&b);
982697a4 2722 switch ((int) raw) {
cfc23141 2723 case OFPRAW_OFPST10_FLOW_REQUEST:
6fd6ed71 2724 return ofputil_decode_ofpst10_flow_request(fsr, b.data, false);
2e4f5fcf 2725
617da9cd 2726 case OFPRAW_OFPST10_AGGREGATE_REQUEST:
6fd6ed71 2727 return ofputil_decode_ofpst10_flow_request(fsr, b.data, true);
0157ad3a
SH
2728
2729 case OFPRAW_OFPST11_FLOW_REQUEST:
2730 return ofputil_decode_ofpst11_flow_request(fsr, &b, false);
2e4f5fcf 2731
617da9cd
SH
2732 case OFPRAW_OFPST11_AGGREGATE_REQUEST:
2733 return ofputil_decode_ofpst11_flow_request(fsr, &b, true);
2734
982697a4
BP
2735 case OFPRAW_NXST_FLOW_REQUEST:
2736 return ofputil_decode_nxst_flow_request(fsr, &b, false);
2e4f5fcf 2737
982697a4
BP
2738 case OFPRAW_NXST_AGGREGATE_REQUEST:
2739 return ofputil_decode_nxst_flow_request(fsr, &b, true);
2e4f5fcf
BP
2740
2741 default:
2742 /* Hey, the caller lied. */
428b2edd 2743 OVS_NOT_REACHED();
2e4f5fcf
BP
2744 }
2745}
2746
2747/* Converts abstract flow_stats_request 'fsr' into an OFPST_FLOW,
4ffd1b43 2748 * OFPST_AGGREGATE, NXST_FLOW, or NXST_AGGREGATE request 'oh' according to
27527aa0 2749 * 'protocol', and returns the message. */
2e4f5fcf 2750struct ofpbuf *
81d1ea94 2751ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr,
27527aa0 2752 enum ofputil_protocol protocol)
2e4f5fcf
BP
2753{
2754 struct ofpbuf *msg;
982697a4 2755 enum ofpraw raw;
2e4f5fcf 2756
27527aa0 2757 switch (protocol) {
75fa58f8 2758 case OFPUTIL_P_OF11_STD:
2e1ae200 2759 case OFPUTIL_P_OF12_OXM:
c37c0382 2760 case OFPUTIL_P_OF13_OXM:
42dccab5 2761 case OFPUTIL_P_OF14_OXM:
b79d45a1
BP
2762 case OFPUTIL_P_OF15_OXM:
2763 case OFPUTIL_P_OF16_OXM: {
06516c65
SH
2764 struct ofp11_flow_stats_request *ofsr;
2765
2766 raw = (fsr->aggregate
617da9cd 2767 ? OFPRAW_OFPST11_AGGREGATE_REQUEST
cfc23141 2768 : OFPRAW_OFPST11_FLOW_REQUEST);
2e1ae200 2769 msg = ofpraw_alloc(raw, ofputil_protocol_to_ofp_version(protocol),
75fa58f8 2770 ofputil_match_typical_len(protocol));
06516c65
SH
2771 ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr);
2772 ofsr->table_id = fsr->table_id;
2773 ofsr->out_port = ofputil_port_to_ofp11(fsr->out_port);
7395c052 2774 ofsr->out_group = htonl(fsr->out_group);
06516c65
SH
2775 ofsr->cookie = fsr->cookie;
2776 ofsr->cookie_mask = fsr->cookie_mask;
75fa58f8 2777 ofputil_put_ofp11_match(msg, &fsr->match, protocol);
06516c65
SH
2778 break;
2779 }
2780
85813857
BP
2781 case OFPUTIL_P_OF10_STD:
2782 case OFPUTIL_P_OF10_STD_TID: {
e2b9ac44 2783 struct ofp10_flow_stats_request *ofsr;
2e4f5fcf 2784
982697a4 2785 raw = (fsr->aggregate
617da9cd 2786 ? OFPRAW_OFPST10_AGGREGATE_REQUEST
cfc23141 2787 : OFPRAW_OFPST10_FLOW_REQUEST);
982697a4
BP
2788 msg = ofpraw_alloc(raw, OFP10_VERSION, 0);
2789 ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr);
81a76618 2790 ofputil_match_to_ofp10_match(&fsr->match, &ofsr->match);
2e4f5fcf 2791 ofsr->table_id = fsr->table_id;
4e022ec0 2792 ofsr->out_port = htons(ofp_to_u16(fsr->out_port));
27527aa0
BP
2793 break;
2794 }
2795
85813857
BP
2796 case OFPUTIL_P_OF10_NXM:
2797 case OFPUTIL_P_OF10_NXM_TID: {
2e4f5fcf
BP
2798 struct nx_flow_stats_request *nfsr;
2799 int match_len;
2800
982697a4
BP
2801 raw = (fsr->aggregate
2802 ? OFPRAW_NXST_AGGREGATE_REQUEST
2803 : OFPRAW_NXST_FLOW_REQUEST);
06516c65 2804 msg = ofpraw_alloc(raw, OFP10_VERSION, NXM_TYPICAL_LEN);
982697a4 2805 ofpbuf_put_zeros(msg, sizeof *nfsr);
7623f4dd 2806 match_len = nx_put_match(msg, &fsr->match,
e729e793 2807 fsr->cookie, fsr->cookie_mask);
2e4f5fcf 2808
6fd6ed71 2809 nfsr = msg->msg;
4e022ec0 2810 nfsr->out_port = htons(ofp_to_u16(fsr->out_port));
2e4f5fcf
BP
2811 nfsr->match_len = htons(match_len);
2812 nfsr->table_id = fsr->table_id;
27527aa0
BP
2813 break;
2814 }
2815
2816 default:
428b2edd 2817 OVS_NOT_REACHED();
2e4f5fcf
BP
2818 }
2819
2820 return msg;
2821}
d1e2cf21 2822
4ffd1b43 2823/* Converts an OFPST_FLOW or NXST_FLOW reply in 'msg' into an abstract
b78f6b77 2824 * ofputil_flow_stats in 'fs'.
4ffd1b43
BP
2825 *
2826 * Multiple OFPST_FLOW or NXST_FLOW replies can be packed into a single
2827 * OpenFlow message. Calling this function multiple times for a single 'msg'
2828 * iterates through the replies. The caller must initially leave 'msg''s layer
2829 * pointers null and not modify them between calls.
2830 *
f27f2134
BP
2831 * Most switches don't send the values needed to populate fs->idle_age and
2832 * fs->hard_age, so those members will usually be set to 0. If the switch from
2833 * which 'msg' originated is known to implement NXT_FLOW_AGE, then pass
2834 * 'flow_age_extension' as true so that the contents of 'msg' determine the
2835 * 'idle_age' and 'hard_age' members in 'fs'.
2836 *
f25d0cf3
BP
2837 * Uses 'ofpacts' to store the abstract OFPACT_* version of the flow stats
2838 * reply's actions. The caller must initialize 'ofpacts' and retains ownership
2839 * of it. 'fs->ofpacts' will point into the 'ofpacts' buffer.
2840 *
4ffd1b43
BP
2841 * Returns 0 if successful, EOF if no replies were left in this 'msg',
2842 * otherwise a positive errno value. */
2843int
2844ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
f27f2134 2845 struct ofpbuf *msg,
f25d0cf3
BP
2846 bool flow_age_extension,
2847 struct ofpbuf *ofpacts)
4ffd1b43 2848{
0fb88c18 2849 const struct ofp_header *oh;
8f2cded4 2850 size_t instructions_len;
982697a4
BP
2851 enum ofperr error;
2852 enum ofpraw raw;
4ffd1b43 2853
6fd6ed71 2854 error = (msg->header ? ofpraw_decode(&raw, msg->header)
982697a4
BP
2855 : ofpraw_pull(&raw, msg));
2856 if (error) {
2857 return error;
4ffd1b43 2858 }
6fd6ed71 2859 oh = msg->header;
4ffd1b43 2860
6fd6ed71 2861 if (!msg->size) {
4ffd1b43 2862 return EOF;
2e1ae200
JR
2863 } else if (raw == OFPRAW_OFPST11_FLOW_REPLY
2864 || raw == OFPRAW_OFPST13_FLOW_REPLY) {
6ec5f0c5
SH
2865 const struct ofp11_flow_stats *ofs;
2866 size_t length;
2867 uint16_t padded_match_len;
2868
2869 ofs = ofpbuf_try_pull(msg, sizeof *ofs);
2870 if (!ofs) {
437d0d22 2871 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIu32" leftover "
6fd6ed71 2872 "bytes at end", msg->size);
6ec5f0c5
SH
2873 return EINVAL;
2874 }
2875
2876 length = ntohs(ofs->length);
2877 if (length < sizeof *ofs) {
2878 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid "
34582733 2879 "length %"PRIuSIZE, length);
6ec5f0c5
SH
2880 return EINVAL;
2881 }
2882
81a76618 2883 if (ofputil_pull_ofp11_match(msg, &fs->match, &padded_match_len)) {
6ec5f0c5
SH
2884 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad match");
2885 return EINVAL;
2886 }
8f2cded4 2887 instructions_len = length - sizeof *ofs - padded_match_len;
6ec5f0c5 2888
81a76618 2889 fs->priority = ntohs(ofs->priority);
6ec5f0c5
SH
2890 fs->table_id = ofs->table_id;
2891 fs->duration_sec = ntohl(ofs->duration_sec);
2892 fs->duration_nsec = ntohl(ofs->duration_nsec);
2893 fs->idle_timeout = ntohs(ofs->idle_timeout);
2894 fs->hard_timeout = ntohs(ofs->hard_timeout);
ca26eb44
RB
2895 if (oh->version >= OFP14_VERSION) {
2896 fs->importance = ntohs(ofs->importance);
2897 } else {
2898 fs->importance = 0;
2899 }
0fb88c18
BP
2900 if (raw == OFPRAW_OFPST13_FLOW_REPLY) {
2901 error = ofputil_decode_flow_mod_flags(ofs->flags, -1, oh->version,
2902 &fs->flags);
2903 if (error) {
2904 return error;
2905 }
2906 } else {
2907 fs->flags = 0;
2908 }
6ec5f0c5
SH
2909 fs->idle_age = -1;
2910 fs->hard_age = -1;
2911 fs->cookie = ofs->cookie;
2912 fs->packet_count = ntohll(ofs->packet_count);
2913 fs->byte_count = ntohll(ofs->byte_count);
cfc23141 2914 } else if (raw == OFPRAW_OFPST10_FLOW_REPLY) {
e2b9ac44 2915 const struct ofp10_flow_stats *ofs;
4ffd1b43
BP
2916 size_t length;
2917
2918 ofs = ofpbuf_try_pull(msg, sizeof *ofs);
2919 if (!ofs) {
437d0d22 2920 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIu32" leftover "
6fd6ed71 2921 "bytes at end", msg->size);
4ffd1b43
BP
2922 return EINVAL;
2923 }
2924
2925 length = ntohs(ofs->length);
2926 if (length < sizeof *ofs) {
2927 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid "
34582733 2928 "length %"PRIuSIZE, length);
4ffd1b43
BP
2929 return EINVAL;
2930 }
8f2cded4 2931 instructions_len = length - sizeof *ofs;
4ffd1b43
BP
2932
2933 fs->cookie = get_32aligned_be64(&ofs->cookie);
81a76618
BP
2934 ofputil_match_from_ofp10_match(&ofs->match, &fs->match);
2935 fs->priority = ntohs(ofs->priority);
4ffd1b43
BP
2936 fs->table_id = ofs->table_id;
2937 fs->duration_sec = ntohl(ofs->duration_sec);
2938 fs->duration_nsec = ntohl(ofs->duration_nsec);
2939 fs->idle_timeout = ntohs(ofs->idle_timeout);
2940 fs->hard_timeout = ntohs(ofs->hard_timeout);
ca26eb44 2941 fs->importance = 0;
f27f2134
BP
2942 fs->idle_age = -1;
2943 fs->hard_age = -1;
4ffd1b43
BP
2944 fs->packet_count = ntohll(get_32aligned_be64(&ofs->packet_count));
2945 fs->byte_count = ntohll(get_32aligned_be64(&ofs->byte_count));
2e1ae200 2946 fs->flags = 0;
982697a4 2947 } else if (raw == OFPRAW_NXST_FLOW_REPLY) {
4ffd1b43 2948 const struct nx_flow_stats *nfs;
8f2cded4 2949 size_t match_len, length;
4ffd1b43
BP
2950
2951 nfs = ofpbuf_try_pull(msg, sizeof *nfs);
2952 if (!nfs) {
437d0d22 2953 VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply has %"PRIu32" leftover "
6fd6ed71 2954 "bytes at end", msg->size);
4ffd1b43
BP
2955 return EINVAL;
2956 }
2957
2958 length = ntohs(nfs->length);
2959 match_len = ntohs(nfs->match_len);
2960 if (length < sizeof *nfs + ROUND_UP(match_len, 8)) {
34582733
AS
2961 VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply with match_len=%"PRIuSIZE" "
2962 "claims invalid length %"PRIuSIZE, match_len, length);
4ffd1b43
BP
2963 return EINVAL;
2964 }
81a76618 2965 if (nx_pull_match(msg, match_len, &fs->match, NULL, NULL)) {
4ffd1b43
BP
2966 return EINVAL;
2967 }
8f2cded4 2968 instructions_len = length - sizeof *nfs - ROUND_UP(match_len, 8);
4ffd1b43
BP
2969
2970 fs->cookie = nfs->cookie;
2971 fs->table_id = nfs->table_id;
2972 fs->duration_sec = ntohl(nfs->duration_sec);
2973 fs->duration_nsec = ntohl(nfs->duration_nsec);
81a76618 2974 fs->priority = ntohs(nfs->priority);
4ffd1b43
BP
2975 fs->idle_timeout = ntohs(nfs->idle_timeout);
2976 fs->hard_timeout = ntohs(nfs->hard_timeout);
ca26eb44 2977 fs->importance = 0;
f27f2134
BP
2978 fs->idle_age = -1;
2979 fs->hard_age = -1;
2980 if (flow_age_extension) {
2981 if (nfs->idle_age) {
2982 fs->idle_age = ntohs(nfs->idle_age) - 1;
2983 }
2984 if (nfs->hard_age) {
2985 fs->hard_age = ntohs(nfs->hard_age) - 1;
2986 }
2987 }
4ffd1b43
BP
2988 fs->packet_count = ntohll(nfs->packet_count);
2989 fs->byte_count = ntohll(nfs->byte_count);
2e1ae200 2990 fs->flags = 0;
4ffd1b43 2991 } else {
428b2edd 2992 OVS_NOT_REACHED();
4ffd1b43
BP
2993 }
2994
8f2cded4
BP
2995 if (ofpacts_pull_openflow_instructions(msg, instructions_len, oh->version,
2996 ofpacts)) {
2997 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
2998 return EINVAL;
2999 }
6fd6ed71
PS
3000 fs->ofpacts = ofpacts->data;
3001 fs->ofpacts_len = ofpacts->size;
f25d0cf3 3002
4ffd1b43
BP
3003 return 0;
3004}
3005
5e9d0469
BP
3006/* Returns 'count' unchanged except that UINT64_MAX becomes 0.
3007 *
3008 * We use this in situations where OVS internally uses UINT64_MAX to mean
3009 * "value unknown" but OpenFlow 1.0 does not define any unknown value. */
3010static uint64_t
3011unknown_to_zero(uint64_t count)
3012{
3013 return count != UINT64_MAX ? count : 0;
3014}
3015
349adfb2
BP
3016/* Appends an OFPST_FLOW or NXST_FLOW reply that contains the data in 'fs' to
3017 * those already present in the list of ofpbufs in 'replies'. 'replies' should
7395c052 3018 * have been initialized with ofpmp_init(). */
349adfb2
BP
3019void
3020ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
ca6ba700 3021 struct ovs_list *replies)
349adfb2 3022{
417e7e66 3023 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
6fd6ed71 3024 size_t start_ofs = reply->size;
e28ac5cf
BP
3025 enum ofp_version version = ofpmp_version(replies);
3026 enum ofpraw raw = ofpmp_decode_raw(replies);
349adfb2 3027
2e1ae200 3028 if (raw == OFPRAW_OFPST11_FLOW_REPLY || raw == OFPRAW_OFPST13_FLOW_REPLY) {
22a86f18
SH
3029 struct ofp11_flow_stats *ofs;
3030
3031 ofpbuf_put_uninit(reply, sizeof *ofs);
9d84066c 3032 oxm_put_match(reply, &fs->match, version);
e3f8f887
JR
3033 ofpacts_put_openflow_instructions(fs->ofpacts, fs->ofpacts_len, reply,
3034 version);
22a86f18
SH
3035
3036 ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
6fd6ed71 3037 ofs->length = htons(reply->size - start_ofs);
22a86f18
SH
3038 ofs->table_id = fs->table_id;
3039 ofs->pad = 0;
3040 ofs->duration_sec = htonl(fs->duration_sec);
3041 ofs->duration_nsec = htonl(fs->duration_nsec);
81a76618 3042 ofs->priority = htons(fs->priority);
22a86f18
SH
3043 ofs->idle_timeout = htons(fs->idle_timeout);
3044 ofs->hard_timeout = htons(fs->hard_timeout);
ca26eb44
RB
3045 if (version >= OFP14_VERSION) {
3046 ofs->importance = htons(fs->importance);
3047 } else {
3048 ofs->importance = 0;
3049 }
0fb88c18 3050 if (raw == OFPRAW_OFPST13_FLOW_REPLY) {
e3f8f887 3051 ofs->flags = ofputil_encode_flow_mod_flags(fs->flags, version);
0fb88c18
BP
3052 } else {
3053 ofs->flags = 0;
3054 }
22a86f18
SH
3055 memset(ofs->pad2, 0, sizeof ofs->pad2);
3056 ofs->cookie = fs->cookie;
3057 ofs->packet_count = htonll(unknown_to_zero(fs->packet_count));
3058 ofs->byte_count = htonll(unknown_to_zero(fs->byte_count));
3059 } else if (raw == OFPRAW_OFPST10_FLOW_REPLY) {
e2b9ac44 3060 struct ofp10_flow_stats *ofs;
349adfb2 3061
1a59dc2c 3062 ofpbuf_put_uninit(reply, sizeof *ofs);
e3f8f887
JR
3063 ofpacts_put_openflow_actions(fs->ofpacts, fs->ofpacts_len, reply,
3064 version);
1a59dc2c 3065 ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
6fd6ed71 3066 ofs->length = htons(reply->size - start_ofs);
349adfb2
BP
3067 ofs->table_id = fs->table_id;
3068 ofs->pad = 0;
81a76618 3069 ofputil_match_to_ofp10_match(&fs->match, &ofs->match);
349adfb2
BP
3070 ofs->duration_sec = htonl(fs->duration_sec);
3071 ofs->duration_nsec = htonl(fs->duration_nsec);
81a76618 3072 ofs->priority = htons(fs->priority);
349adfb2
BP
3073 ofs->idle_timeout = htons(fs->idle_timeout);
3074 ofs->hard_timeout = htons(fs->hard_timeout);
3075 memset(ofs->pad2, 0, sizeof ofs->pad2);
3076 put_32aligned_be64(&ofs->cookie, fs->cookie);
5e9d0469
BP
3077 put_32aligned_be64(&ofs->packet_count,
3078 htonll(unknown_to_zero(fs->packet_count)));
3079 put_32aligned_be64(&ofs->byte_count,
3080 htonll(unknown_to_zero(fs->byte_count)));
982697a4 3081 } else if (raw == OFPRAW_NXST_FLOW_REPLY) {
349adfb2 3082 struct nx_flow_stats *nfs;
1a59dc2c 3083 int match_len;
349adfb2 3084
1a59dc2c 3085 ofpbuf_put_uninit(reply, sizeof *nfs);
81a76618 3086 match_len = nx_put_match(reply, &fs->match, 0, 0);
e3f8f887
JR
3087 ofpacts_put_openflow_actions(fs->ofpacts, fs->ofpacts_len, reply,
3088 version);
1a59dc2c 3089 nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
6fd6ed71 3090 nfs->length = htons(reply->size - start_ofs);
349adfb2
BP
3091 nfs->table_id = fs->table_id;
3092 nfs->pad = 0;
3093 nfs->duration_sec = htonl(fs->duration_sec);
3094 nfs->duration_nsec = htonl(fs->duration_nsec);
81a76618 3095 nfs->priority = htons(fs->priority);
349adfb2
BP
3096 nfs->idle_timeout = htons(fs->idle_timeout);
3097 nfs->hard_timeout = htons(fs->hard_timeout);
f27f2134
BP
3098 nfs->idle_age = htons(fs->idle_age < 0 ? 0
3099 : fs->idle_age < UINT16_MAX ? fs->idle_age + 1
3100 : UINT16_MAX);
3101 nfs->hard_age = htons(fs->hard_age < 0 ? 0
3102 : fs->hard_age < UINT16_MAX ? fs->hard_age + 1
3103 : UINT16_MAX);
1a59dc2c 3104 nfs->match_len = htons(match_len);
349adfb2
BP
3105 nfs->cookie = fs->cookie;
3106 nfs->packet_count = htonll(fs->packet_count);
3107 nfs->byte_count = htonll(fs->byte_count);
349adfb2 3108 } else {
428b2edd 3109 OVS_NOT_REACHED();
349adfb2 3110 }
f25d0cf3 3111
982697a4 3112 ofpmp_postappend(replies, start_ofs);
349adfb2
BP
3113}
3114
76c93b22 3115/* Converts abstract ofputil_aggregate_stats 'stats' into an OFPST_AGGREGATE or
a814ba0f 3116 * NXST_AGGREGATE reply matching 'request', and returns the message. */
76c93b22
BP
3117struct ofpbuf *
3118ofputil_encode_aggregate_stats_reply(
3119 const struct ofputil_aggregate_stats *stats,
982697a4 3120 const struct ofp_header *request)
76c93b22 3121{
a814ba0f
BP
3122 struct ofp_aggregate_stats_reply *asr;
3123 uint64_t packet_count;
3124 uint64_t byte_count;
76c93b22 3125 struct ofpbuf *msg;
982697a4 3126 enum ofpraw raw;
76c93b22 3127
982697a4 3128 ofpraw_decode(&raw, request);
617da9cd 3129 if (raw == OFPRAW_OFPST10_AGGREGATE_REQUEST) {
a814ba0f
BP
3130 packet_count = unknown_to_zero(stats->packet_count);
3131 byte_count = unknown_to_zero(stats->byte_count);
76c93b22 3132 } else {
a814ba0f
BP
3133 packet_count = stats->packet_count;
3134 byte_count = stats->byte_count;
76c93b22
BP
3135 }
3136
a814ba0f
BP
3137 msg = ofpraw_alloc_stats_reply(request, 0);
3138 asr = ofpbuf_put_zeros(msg, sizeof *asr);
3139 put_32aligned_be64(&asr->packet_count, htonll(packet_count));
3140 put_32aligned_be64(&asr->byte_count, htonll(byte_count));
3141 asr->flow_count = htonl(stats->flow_count);
3142
76c93b22
BP
3143 return msg;
3144}
3145
982697a4
BP
3146enum ofperr
3147ofputil_decode_aggregate_stats_reply(struct ofputil_aggregate_stats *stats,
3148 const struct ofp_header *reply)
3149{
0a2869d5 3150 struct ofpbuf msg = ofpbuf_const_initializer(reply, ntohs(reply->length));
a814ba0f
BP
3151 ofpraw_pull_assert(&msg);
3152
0a2869d5 3153 struct ofp_aggregate_stats_reply *asr = msg.msg;
a814ba0f
BP
3154 stats->packet_count = ntohll(get_32aligned_be64(&asr->packet_count));
3155 stats->byte_count = ntohll(get_32aligned_be64(&asr->byte_count));
3156 stats->flow_count = ntohl(asr->flow_count);
982697a4
BP
3157
3158 return 0;
3159}
3160
b78f6b77
BP
3161/* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh' into an
3162 * abstract ofputil_flow_removed in 'fr'. Returns 0 if successful, otherwise
3163 * an OpenFlow error code. */
90bf1e07 3164enum ofperr
9b045a0c 3165ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
b78f6b77 3166 const struct ofp_header *oh)
9b045a0c 3167{
0a2869d5
BP
3168 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
3169 enum ofpraw raw = ofpraw_pull_assert(&b);
eefbf181
SH
3170 if (raw == OFPRAW_OFPT11_FLOW_REMOVED) {
3171 const struct ofp12_flow_removed *ofr;
3172 enum ofperr error;
3173
3174 ofr = ofpbuf_pull(&b, sizeof *ofr);
3175
81a76618 3176 error = ofputil_pull_ofp11_match(&b, &fr->match, NULL);
eefbf181
SH
3177 if (error) {
3178 return error;
3179 }
3180
81a76618 3181 fr->priority = ntohs(ofr->priority);
eefbf181
SH
3182 fr->cookie = ofr->cookie;
3183 fr->reason = ofr->reason;
95216219 3184 fr->table_id = ofr->table_id;
eefbf181
SH
3185 fr->duration_sec = ntohl(ofr->duration_sec);
3186 fr->duration_nsec = ntohl(ofr->duration_nsec);
3187 fr->idle_timeout = ntohs(ofr->idle_timeout);
3188 fr->hard_timeout = ntohs(ofr->hard_timeout);
3189 fr->packet_count = ntohll(ofr->packet_count);
3190 fr->byte_count = ntohll(ofr->byte_count);
3191 } else if (raw == OFPRAW_OFPT10_FLOW_REMOVED) {
31a9e63f 3192 const struct ofp10_flow_removed *ofr;
9b045a0c 3193
982697a4
BP
3194 ofr = ofpbuf_pull(&b, sizeof *ofr);
3195
81a76618
BP
3196 ofputil_match_from_ofp10_match(&ofr->match, &fr->match);
3197 fr->priority = ntohs(ofr->priority);
9b045a0c
BP
3198 fr->cookie = ofr->cookie;
3199 fr->reason = ofr->reason;
95216219 3200 fr->table_id = 255;
9b045a0c
BP
3201 fr->duration_sec = ntohl(ofr->duration_sec);
3202 fr->duration_nsec = ntohl(ofr->duration_nsec);
3203 fr->idle_timeout = ntohs(ofr->idle_timeout);
fa2bad0f 3204 fr->hard_timeout = 0;
9b045a0c
BP
3205 fr->packet_count = ntohll(ofr->packet_count);
3206 fr->byte_count = ntohll(ofr->byte_count);
982697a4 3207 } else if (raw == OFPRAW_NXT_FLOW_REMOVED) {
9b045a0c 3208 struct nx_flow_removed *nfr;
c2725b60 3209 enum ofperr error;
9b045a0c 3210
9b045a0c 3211 nfr = ofpbuf_pull(&b, sizeof *nfr);
81a76618
BP
3212 error = nx_pull_match(&b, ntohs(nfr->match_len), &fr->match,
3213 NULL, NULL);
9b045a0c
BP
3214 if (error) {
3215 return error;
3216 }
6fd6ed71 3217 if (b.size) {
90bf1e07 3218 return OFPERR_OFPBRC_BAD_LEN;
9b045a0c
BP
3219 }
3220
81a76618 3221 fr->priority = ntohs(nfr->priority);
9b045a0c
BP
3222 fr->cookie = nfr->cookie;
3223 fr->reason = nfr->reason;
745bfd5e 3224 fr->table_id = nfr->table_id ? nfr->table_id - 1 : 255;
9b045a0c
BP
3225 fr->duration_sec = ntohl(nfr->duration_sec);
3226 fr->duration_nsec = ntohl(nfr->duration_nsec);
3227 fr->idle_timeout = ntohs(nfr->idle_timeout);
fa2bad0f 3228 fr->hard_timeout = 0;
9b045a0c
BP
3229 fr->packet_count = ntohll(nfr->packet_count);
3230 fr->byte_count = ntohll(nfr->byte_count);
3231 } else {
428b2edd 3232 OVS_NOT_REACHED();
9b045a0c
BP
3233 }
3234
3235 return 0;
3236}
3237
588cd7b5 3238/* Converts abstract ofputil_flow_removed 'fr' into an OFPT_FLOW_REMOVED or
27527aa0 3239 * NXT_FLOW_REMOVED message 'oh' according to 'protocol', and returns the
588cd7b5
BP
3240 * message. */
3241struct ofpbuf *
3242ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
27527aa0 3243 enum ofputil_protocol protocol)
588cd7b5
BP
3244{
3245 struct ofpbuf *msg;
fa42f4f8
SH
3246 enum ofp_flow_removed_reason reason = fr->reason;
3247
3248 if (reason == OFPRR_METER_DELETE && !(protocol & OFPUTIL_P_OF14_UP)) {
3249 reason = OFPRR_DELETE;
3250 }
588cd7b5 3251
27527aa0 3252 switch (protocol) {
75fa58f8 3253 case OFPUTIL_P_OF11_STD:
2e1ae200 3254 case OFPUTIL_P_OF12_OXM:
c37c0382 3255 case OFPUTIL_P_OF13_OXM:
42dccab5 3256 case OFPUTIL_P_OF14_OXM:
b79d45a1
BP
3257 case OFPUTIL_P_OF15_OXM:
3258 case OFPUTIL_P_OF16_OXM: {
83974732
SH
3259 struct ofp12_flow_removed *ofr;
3260
3261 msg = ofpraw_alloc_xid(OFPRAW_OFPT11_FLOW_REMOVED,
3262 ofputil_protocol_to_ofp_version(protocol),
75fa58f8
BP
3263 htonl(0),
3264 ofputil_match_typical_len(protocol));
83974732
SH
3265 ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
3266 ofr->cookie = fr->cookie;
81a76618 3267 ofr->priority = htons(fr->priority);
fa42f4f8 3268 ofr->reason = reason;
95216219 3269 ofr->table_id = fr->table_id;
83974732
SH
3270 ofr->duration_sec = htonl(fr->duration_sec);
3271 ofr->duration_nsec = htonl(fr->duration_nsec);
3272 ofr->idle_timeout = htons(fr->idle_timeout);
fa2bad0f 3273 ofr->hard_timeout = htons(fr->hard_timeout);
83974732
SH
3274 ofr->packet_count = htonll(fr->packet_count);
3275 ofr->byte_count = htonll(fr->byte_count);
75fa58f8 3276 ofputil_put_ofp11_match(msg, &fr->match, protocol);
83974732
SH
3277 break;
3278 }
3279
85813857
BP
3280 case OFPUTIL_P_OF10_STD:
3281 case OFPUTIL_P_OF10_STD_TID: {
31a9e63f 3282 struct ofp10_flow_removed *ofr;
588cd7b5 3283
982697a4
BP
3284 msg = ofpraw_alloc_xid(OFPRAW_OFPT10_FLOW_REMOVED, OFP10_VERSION,
3285 htonl(0), 0);
3286 ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
81a76618 3287 ofputil_match_to_ofp10_match(&fr->match, &ofr->match);
7fb563b9 3288 ofr->cookie = fr->cookie;
81a76618 3289 ofr->priority = htons(fr->priority);
fa42f4f8 3290 ofr->reason = reason;
588cd7b5
BP
3291 ofr->duration_sec = htonl(fr->duration_sec);
3292 ofr->duration_nsec = htonl(fr->duration_nsec);
3293 ofr->idle_timeout = htons(fr->idle_timeout);
5e9d0469
BP
3294 ofr->packet_count = htonll(unknown_to_zero(fr->packet_count));
3295 ofr->byte_count = htonll(unknown_to_zero(fr->byte_count));
27527aa0
BP
3296 break;
3297 }
3298
85813857
BP
3299 case OFPUTIL_P_OF10_NXM:
3300 case OFPUTIL_P_OF10_NXM_TID: {
588cd7b5
BP
3301 struct nx_flow_removed *nfr;
3302 int match_len;
3303
982697a4
BP
3304 msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_REMOVED, OFP10_VERSION,
3305 htonl(0), NXM_TYPICAL_LEN);
a3358085 3306 ofpbuf_put_zeros(msg, sizeof *nfr);
81a76618 3307 match_len = nx_put_match(msg, &fr->match, 0, 0);
588cd7b5 3308
6fd6ed71 3309 nfr = msg->msg;
588cd7b5 3310 nfr->cookie = fr->cookie;
81a76618 3311 nfr->priority = htons(fr->priority);
fa42f4f8 3312 nfr->reason = reason;
745bfd5e 3313 nfr->table_id = fr->table_id + 1;
588cd7b5
BP
3314 nfr->duration_sec = htonl(fr->duration_sec);
3315 nfr->duration_nsec = htonl(fr->duration_nsec);
3316 nfr->idle_timeout = htons(fr->idle_timeout);
3317 nfr->match_len = htons(match_len);
3318 nfr->packet_count = htonll(fr->packet_count);
3319 nfr->byte_count = htonll(fr->byte_count);
27527aa0
BP
3320 break;
3321 }
3322
3323 default:
428b2edd 3324 OVS_NOT_REACHED();
588cd7b5
BP
3325 }
3326
3327 return msg;
3328}
3329
6409e008
BP
3330/* The caller has done basic initialization of '*pin'; the other output
3331 * arguments needs to be initialized. */
3332static enum ofperr
77ab5fd2 3333decode_nx_packet_in2(const struct ofp_header *oh, bool loose,
6409e008 3334 struct ofputil_packet_in *pin,
77ab5fd2
BP
3335 size_t *total_len, uint32_t *buffer_id,
3336 struct ofpbuf *continuation)
6409e008
BP
3337{
3338 *total_len = 0;
3339 *buffer_id = UINT32_MAX;
3340
3341 struct ofpbuf properties;
3342 ofpbuf_use_const(&properties, oh, ntohs(oh->length));
3343 ofpraw_pull_assert(&properties);
3344
3345 while (properties.size > 0) {
3346 struct ofpbuf payload;
3347 uint64_t type;
3348
3349 enum ofperr error = ofpprop_pull(&properties, &payload, &type);
3350 if (error) {
3351 return error;
3352 }
3353
3354 switch (type) {
3355 case NXPINT_PACKET:
3356 pin->packet = payload.msg;
4adaf182 3357 pin->packet_len = ofpbuf_msgsize(&payload);
6409e008
BP
3358 break;
3359
3360 case NXPINT_FULL_LEN: {
3361 uint32_t u32;
3362 error = ofpprop_parse_u32(&payload, &u32);
3363 *total_len = u32;
3364 break;
3365 }
3366
3367 case NXPINT_BUFFER_ID:
3368 error = ofpprop_parse_u32(&payload, buffer_id);
3369 break;
3370
3371 case NXPINT_TABLE_ID:
3372 error = ofpprop_parse_u8(&payload, &pin->table_id);
3373 break;
3374
3375 case NXPINT_COOKIE:
3376 error = ofpprop_parse_be64(&payload, &pin->cookie);
3377 break;
3378
3379 case NXPINT_REASON: {
3380 uint8_t reason;
3381 error = ofpprop_parse_u8(&payload, &reason);
3382 pin->reason = reason;
3383 break;
3384 }
3385
3386 case NXPINT_METADATA:
3387 error = oxm_decode_match(payload.msg, ofpbuf_msgsize(&payload),
3388 &pin->flow_metadata);
3389 break;
3390
bdcad671
BP
3391 case NXPINT_USERDATA:
3392 pin->userdata = payload.msg;
3393 pin->userdata_len = ofpbuf_msgsize(&payload);
3394 break;
3395
77ab5fd2
BP
3396 case NXPINT_CONTINUATION:
3397 if (continuation) {
3398 error = ofpprop_parse_nested(&payload, continuation);
3399 }
3400 break;
3401
6409e008 3402 default:
77ab5fd2 3403 error = OFPPROP_UNKNOWN(loose, "NX_PACKET_IN2", type);
6409e008
BP
3404 break;
3405 }
3406 if (error) {
3407 return error;
3408 }
3409 }
3410
4adaf182 3411 if (!pin->packet_len) {
6409e008
BP
3412 VLOG_WARN_RL(&bad_ofmsg_rl, "NXT_PACKET_IN2 lacks packet");
3413 return OFPERR_OFPBRC_BAD_LEN;
3414 } else if (!*total_len) {
4adaf182
BP
3415 *total_len = pin->packet_len;
3416 } else if (*total_len < pin->packet_len) {
6409e008
BP
3417 VLOG_WARN_RL(&bad_ofmsg_rl, "NXT_PACKET_IN2 claimed full_len < len");
3418 return OFPERR_OFPBRC_BAD_LEN;
3419 }
3420
3421 return 0;
3422}
3423
9bfe9334 3424/* Decodes the packet-in message starting at 'oh' into '*pin'. Populates
77ab5fd2
BP
3425 * 'pin->packet' and 'pin->packet_len' with the part of the packet actually
3426 * included in the message. If 'total_lenp' is nonnull, populates
3427 * '*total_lenp' with the original length of the packet (which is larger than
3428 * 'packet->len' if only part of the packet was included). If 'buffer_idp' is
3429 * nonnull, stores the packet's buffer ID in '*buffer_idp' (UINT32_MAX if it
9bfe9334
BP
3430 * was not buffered).
3431 *
77ab5fd2
BP
3432 * Populates 'continuation', if nonnull, with the continuation data from the
3433 * packet-in (an empty buffer, if 'oh' did not contain continuation data). The
3434 * format of this data is supposed to be opaque to anything other than
3435 * ovs-vswitchd, so that in any other process the only reasonable use of this
3436 * data is to be copied into an NXT_RESUME message via ofputil_encode_resume().
3437 *
3438 * This function points 'pin->packet' into 'oh', so the caller should not free
3439 * it separately from the original OpenFlow message. This is also true for
3440 * 'pin->userdata' (which could also end up NULL if there is no userdata).
3441 *
9bfe9334 3442 * Returns 0 if successful, otherwise an OpenFlow error code. */
f7cc6bd8 3443enum ofperr
77ab5fd2 3444ofputil_decode_packet_in(const struct ofp_header *oh, bool loose,
9bfe9334 3445 struct ofputil_packet_in *pin,
77ab5fd2
BP
3446 size_t *total_lenp, uint32_t *buffer_idp,
3447 struct ofpbuf *continuation)
65120a8a 3448{
77ab5fd2
BP
3449 uint32_t buffer_id;
3450 size_t total_len;
3451
65120a8a 3452 memset(pin, 0, sizeof *pin);
d4fa4e79 3453 pin->cookie = OVS_BE64_MAX;
77ab5fd2
BP
3454 if (continuation) {
3455 ofpbuf_use_const(continuation, NULL, 0);
3456 }
65120a8a 3457
0a2869d5
BP
3458 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
3459 enum ofpraw raw = ofpraw_pull_assert(&b);
2e1ae200 3460 if (raw == OFPRAW_OFPT13_PACKET_IN || raw == OFPRAW_OFPT12_PACKET_IN) {
43948fa5
BP
3461 const struct ofp12_packet_in *opi = ofpbuf_pull(&b, sizeof *opi);
3462 const ovs_be64 *cookie = (raw == OFPRAW_OFPT13_PACKET_IN
3463 ? ofpbuf_pull(&b, sizeof *cookie)
3464 : NULL);
3465 enum ofperr error = oxm_pull_match_loose(&b, &pin->flow_metadata);
7cfb9651
SH
3466 if (error) {
3467 return error;
3468 }
3469
3470 if (!ofpbuf_try_pull(&b, 2)) {
3471 return OFPERR_OFPBRC_BAD_LEN;
3472 }
3473
43948fa5
BP
3474 pin->reason = opi->reason;
3475 pin->table_id = opi->table_id;
77ab5fd2
BP
3476 buffer_id = ntohl(opi->buffer_id);
3477 total_len = ntohs(opi->total_len);
43948fa5
BP
3478 if (cookie) {
3479 pin->cookie = *cookie;
2e1ae200 3480 }
7cfb9651 3481
50dcbd8e 3482 pin->packet = b.data;
4adaf182 3483 pin->packet_len = b.size;
7cfb9651 3484 } else if (raw == OFPRAW_OFPT10_PACKET_IN) {
31a9e63f 3485 const struct ofp10_packet_in *opi;
982697a4 3486
31a9e63f 3487 opi = ofpbuf_pull(&b, offsetof(struct ofp10_packet_in, data));
65120a8a 3488
95022b47 3489 pin->packet = CONST_CAST(uint8_t *, opi->data);
4adaf182 3490 pin->packet_len = b.size;
65120a8a 3491
50dcbd8e 3492 match_init_catchall(&pin->flow_metadata);
9bfe9334
BP
3493 match_set_in_port(&pin->flow_metadata,
3494 u16_to_ofp(ntohs(opi->in_port)));
65120a8a 3495 pin->reason = opi->reason;
77ab5fd2
BP
3496 buffer_id = ntohl(opi->buffer_id);
3497 total_len = ntohs(opi->total_len);
4d197ebb
BP
3498 } else if (raw == OFPRAW_OFPT11_PACKET_IN) {
3499 const struct ofp11_packet_in *opi;
50dcbd8e 3500 ofp_port_t in_port;
4d197ebb
BP
3501 enum ofperr error;
3502
3503 opi = ofpbuf_pull(&b, sizeof *opi);
3504
6fd6ed71 3505 pin->packet = b.data;
4adaf182 3506 pin->packet_len = b.size;
4d197ebb 3507
77ab5fd2 3508 buffer_id = ntohl(opi->buffer_id);
50dcbd8e 3509 error = ofputil_port_from_ofp11(opi->in_port, &in_port);
4d197ebb
BP
3510 if (error) {
3511 return error;
3512 }
50dcbd8e
JG
3513 match_init_catchall(&pin->flow_metadata);
3514 match_set_in_port(&pin->flow_metadata, in_port);
77ab5fd2 3515 total_len = ntohs(opi->total_len);
4d197ebb
BP
3516 pin->reason = opi->reason;
3517 pin->table_id = opi->table_id;
982697a4 3518 } else if (raw == OFPRAW_NXT_PACKET_IN) {
73dbf4ab 3519 const struct nx_packet_in *npi;
54834960
EJ
3520 int error;
3521
54834960 3522 npi = ofpbuf_pull(&b, sizeof *npi);
50dcbd8e
JG
3523 error = nx_pull_match_loose(&b, ntohs(npi->match_len),
3524 &pin->flow_metadata, NULL, NULL);
54834960
EJ
3525 if (error) {
3526 return error;
3527 }
3528
3529 if (!ofpbuf_try_pull(&b, 2)) {
90bf1e07 3530 return OFPERR_OFPBRC_BAD_LEN;
54834960
EJ
3531 }
3532
54834960
EJ
3533 pin->reason = npi->reason;
3534 pin->table_id = npi->table_id;
3535 pin->cookie = npi->cookie;
3536
77ab5fd2
BP
3537 buffer_id = ntohl(npi->buffer_id);
3538 total_len = ntohs(npi->total_len);
7cfb9651 3539
50dcbd8e 3540 pin->packet = b.data;
4adaf182 3541 pin->packet_len = b.size;
77ab5fd2
BP
3542 } else if (raw == OFPRAW_NXT_PACKET_IN2 || raw == OFPRAW_NXT_RESUME) {
3543 enum ofperr error = decode_nx_packet_in2(oh, loose, pin, &total_len,
3544 &buffer_id, continuation);
3545 if (error) {
3546 return error;
3547 }
65120a8a 3548 } else {
428b2edd 3549 OVS_NOT_REACHED();
65120a8a
EJ
3550 }
3551
77ab5fd2
BP
3552 if (total_lenp) {
3553 *total_lenp = total_len;
3554 }
3555 if (buffer_idp) {
3556 *buffer_idp = buffer_id;
3557 }
3558
65120a8a
EJ
3559 return 0;
3560}
3561
9bfe9334
BP
3562static int
3563encode_packet_in_reason(enum ofp_packet_in_reason reason,
3564 enum ofp_version version)
3565{
3566 switch (reason) {
3567 case OFPR_NO_MATCH:
3568 case OFPR_ACTION:
3569 case OFPR_INVALID_TTL:
3570 return reason;
3571
3572 case OFPR_ACTION_SET:
3573 case OFPR_GROUP:
3574 case OFPR_PACKET_OUT:
3575 return version < OFP14_VERSION ? OFPR_ACTION : reason;
3576
3577 case OFPR_EXPLICIT_MISS:
3578 return version < OFP13_VERSION ? OFPR_ACTION : OFPR_NO_MATCH;
3579
3580 case OFPR_IMPLICIT_MISS:
3581 return OFPR_NO_MATCH;
3582
3583 case OFPR_N_REASONS:
3584 default:
3585 OVS_NOT_REACHED();
3586 }
3587}
3588
77ab5fd2
BP
3589/* Only NXT_PACKET_IN2 (not NXT_RESUME) should include NXCPT_USERDATA, so this
3590 * function omits it. The caller can add it itself if desired. */
3591static void
3592ofputil_put_packet_in(const struct ofputil_packet_in *pin,
3593 enum ofp_version version, uint32_t buffer_id,
3594 size_t include_bytes, struct ofpbuf *msg)
3595{
3596 /* Add packet properties. */
3597 ofpprop_put(msg, NXPINT_PACKET, pin->packet, include_bytes);
3598 if (include_bytes != pin->packet_len) {
3599 ofpprop_put_u32(msg, NXPINT_FULL_LEN, pin->packet_len);
3600 }
3601 if (buffer_id != UINT32_MAX) {
3602 ofpprop_put_u32(msg, NXPINT_BUFFER_ID, buffer_id);
3603 }
3604
3605 /* Add flow properties. */
3606 ofpprop_put_u8(msg, NXPINT_TABLE_ID, pin->table_id);
3607 if (pin->cookie != OVS_BE64_MAX) {
3608 ofpprop_put_be64(msg, NXPINT_COOKIE, pin->cookie);
3609 }
3610
3611 /* Add other properties. */
3612 ofpprop_put_u8(msg, NXPINT_REASON,
3613 encode_packet_in_reason(pin->reason, version));
3614
3615 size_t start = ofpprop_start(msg, NXPINT_METADATA);
3616 oxm_put_raw(msg, &pin->flow_metadata, version);
3617 ofpprop_end(msg, start);
3618}
3619
3620static void
3621put_actions_property(struct ofpbuf *msg, uint64_t prop_type,
3622 enum ofp_version version,
3623 const struct ofpact *actions, size_t actions_len)
3624{
3625 if (actions_len) {
3626 size_t start = ofpprop_start_nested(msg, prop_type);
3627 ofpacts_put_openflow_actions(actions, actions_len, msg, version);
3628 ofpprop_end(msg, start);
3629 }
3630}
3631
3632enum nx_continuation_prop_type {
3633 NXCPT_BRIDGE = 0x8000,
3634 NXCPT_STACK,
3635 NXCPT_MIRRORS,
3636 NXCPT_CONNTRACKED,
3637 NXCPT_TABLE_ID,
3638 NXCPT_COOKIE,
3639 NXCPT_ACTIONS,
3640 NXCPT_ACTION_SET,
3641};
3642
3643/* Only NXT_PACKET_IN2 (not NXT_RESUME) should include NXCPT_USERDATA, so this
3644 * function omits it. The caller can add it itself if desired. */
3645static void
3646ofputil_put_packet_in_private(const struct ofputil_packet_in_private *pin,
3647 enum ofp_version version, uint32_t buffer_id,
3648 size_t include_bytes, struct ofpbuf *msg)
3649{
3650 ofputil_put_packet_in(&pin->public, version, buffer_id,
3651 include_bytes, msg);
3652
3653 size_t continuation_ofs = ofpprop_start_nested(msg, NXPINT_CONTINUATION);
3654 size_t inner_ofs = msg->size;
3655
3656 if (!uuid_is_zero(&pin->bridge)) {
3657 ofpprop_put_uuid(msg, NXCPT_BRIDGE, &pin->bridge);
3658 }
3659
3660 for (size_t i = 0; i < pin->n_stack; i++) {
3661 const union mf_subvalue *s = &pin->stack[i];
3662 size_t ofs;
3663 for (ofs = 0; ofs < sizeof *s; ofs++) {
3664 if (s->u8[ofs]) {
3665 break;
3666 }
3667 }
3668
3669 ofpprop_put(msg, NXCPT_STACK, &s->u8[ofs], sizeof *s - ofs);
3670 }
3671
3672 if (pin->mirrors) {
3673 ofpprop_put_u32(msg, NXCPT_MIRRORS, pin->mirrors);
3674 }
3675
3676 if (pin->conntracked) {
3677 ofpprop_put_flag(msg, NXCPT_CONNTRACKED);
3678 }
3679
3680 if (pin->actions_len) {
3681 /* Divide 'pin->actions' into groups that begins with an
3682 * unroll_xlate action. For each group, emit a NXCPT_TABLE_ID and
3683 * NXCPT_COOKIE property (if either has changed; each is initially
3684 * assumed 0), then a NXCPT_ACTIONS property with the grouped
3685 * actions.
3686 *
3687 * The alternative is to make OFPACT_UNROLL_XLATE public. We can
3688 * always do that later, since this is a private property. */
3689 const struct ofpact *const end = ofpact_end(pin->actions,
3690 pin->actions_len);
3691 const struct ofpact_unroll_xlate *unroll = NULL;
3692 uint8_t table_id = 0;
3693 ovs_be64 cookie = 0;
3694
3695 const struct ofpact *a;
3696 for (a = pin->actions; ; a = ofpact_next(a)) {
3697 if (a == end || a->type == OFPACT_UNROLL_XLATE) {
3698 if (unroll) {
3699 if (table_id != unroll->rule_table_id) {
3700 ofpprop_put_u8(msg, NXCPT_TABLE_ID,
3701 unroll->rule_table_id);
3702 table_id = unroll->rule_table_id;
3703 }
3704 if (cookie != unroll->rule_cookie) {
3705 ofpprop_put_be64(msg, NXCPT_COOKIE,
3706 unroll->rule_cookie);
3707 cookie = unroll->rule_cookie;
3708 }
3709 }
3710
3711 const struct ofpact *start
3712 = unroll ? ofpact_next(&unroll->ofpact) : pin->actions;
3713 put_actions_property(msg, NXCPT_ACTIONS, version,
3714 start, (a - start) * sizeof *a);
3715
3716 if (a == end) {
3717 break;
3718 }
3719 unroll = ofpact_get_UNROLL_XLATE(a);
3720 }
3721 }
3722 }
3723
3724 if (pin->action_set_len) {
3725 size_t start = ofpprop_start_nested(msg, NXCPT_ACTION_SET);
3726 ofpacts_put_openflow_actions(pin->action_set,
3727 pin->action_set_len, msg, version);
3728 ofpprop_end(msg, start);
3729 }
3730
3731 if (msg->size > inner_ofs) {
3732 ofpprop_end(msg, continuation_ofs);
3733 } else {
3734 msg->size = continuation_ofs;
3735 }
3736}
3737
0f83fea0 3738static struct ofpbuf *
9bfe9334
BP
3739ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in *pin,
3740 uint32_t buffer_id)
0f83fea0
BP
3741{
3742 struct ofp10_packet_in *opi;
9bfe9334 3743 struct ofpbuf *msg;
0f83fea0 3744
9bfe9334 3745 msg = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION,
4adaf182 3746 htonl(0), pin->packet_len);
9bfe9334 3747 opi = ofpbuf_put_zeros(msg, offsetof(struct ofp10_packet_in, data));
4adaf182 3748 opi->total_len = htons(pin->packet_len);
50dcbd8e 3749 opi->in_port = htons(ofp_to_u16(pin->flow_metadata.flow.in_port.ofp_port));
9bfe9334
BP
3750 opi->reason = encode_packet_in_reason(pin->reason, OFP10_VERSION);
3751 opi->buffer_id = htonl(buffer_id);
0f83fea0 3752
9bfe9334 3753 return msg;
0f83fea0
BP
3754}
3755
3756static struct ofpbuf *
9bfe9334 3757ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin,
6409e008 3758 enum ofp_version version, uint32_t buffer_id)
0f83fea0
BP
3759{
3760 struct nx_packet_in *npi;
9bfe9334 3761 struct ofpbuf *msg;
0f83fea0
BP
3762 size_t match_len;
3763
0f83fea0 3764 /* The final argument is just an estimate of the space required. */
6409e008 3765 msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN, version,
4adaf182 3766 htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);
9bfe9334
BP
3767 ofpbuf_put_zeros(msg, sizeof *npi);
3768 match_len = nx_put_match(msg, &pin->flow_metadata, 0, 0);
3769 ofpbuf_put_zeros(msg, 2);
3770
3771 npi = msg->msg;
3772 npi->buffer_id = htonl(buffer_id);
4adaf182 3773 npi->total_len = htons(pin->packet_len);
6409e008 3774 npi->reason = encode_packet_in_reason(pin->reason, version);
0f83fea0
BP
3775 npi->table_id = pin->table_id;
3776 npi->cookie = pin->cookie;
3777 npi->match_len = htons(match_len);
3778
9bfe9334 3779 return msg;
0f83fea0
BP
3780}
3781
6409e008 3782static struct ofpbuf *
77ab5fd2 3783ofputil_encode_nx_packet_in2(const struct ofputil_packet_in_private *pin,
6409e008
BP
3784 enum ofp_version version, uint32_t buffer_id,
3785 size_t include_bytes)
3786{
3787 /* 'extra' is just an estimate of the space required. */
77ab5fd2
BP
3788 size_t extra = (pin->public.packet_len
3789 + NXM_TYPICAL_LEN /* flow_metadata */
3790 + pin->n_stack * 16
3791 + pin->actions_len
3792 + pin->action_set_len
3793 + 256); /* fudge factor */
6409e008
BP
3794 struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN2, version,
3795 htonl(0), extra);
3796
77ab5fd2
BP
3797 ofputil_put_packet_in_private(pin, version, buffer_id, include_bytes, msg);
3798 if (pin->public.userdata_len) {
3799 ofpprop_put(msg, NXPINT_USERDATA, pin->public.userdata,
3800 pin->public.userdata_len);
bdcad671
BP
3801 }
3802
6409e008
BP
3803 ofpmsg_update_length(msg);
3804 return msg;
3805}
3806
4d197ebb 3807static struct ofpbuf *
9bfe9334
BP
3808ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin,
3809 uint32_t buffer_id)
4d197ebb
BP
3810{
3811 struct ofp11_packet_in *opi;
9bfe9334 3812 struct ofpbuf *msg;
4d197ebb 3813
9bfe9334 3814 msg = ofpraw_alloc_xid(OFPRAW_OFPT11_PACKET_IN, OFP11_VERSION,
4adaf182 3815 htonl(0), pin->packet_len);
9bfe9334
BP
3816 opi = ofpbuf_put_zeros(msg, sizeof *opi);
3817 opi->buffer_id = htonl(buffer_id);
3818 opi->in_port = ofputil_port_to_ofp11(
3819 pin->flow_metadata.flow.in_port.ofp_port);
4d197ebb 3820 opi->in_phy_port = opi->in_port;
4adaf182 3821 opi->total_len = htons(pin->packet_len);
9bfe9334 3822 opi->reason = encode_packet_in_reason(pin->reason, OFP11_VERSION);
4d197ebb
BP
3823 opi->table_id = pin->table_id;
3824
9bfe9334 3825 return msg;
4d197ebb
BP
3826}
3827
0f83fea0
BP
3828static struct ofpbuf *
3829ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin,
9bfe9334
BP
3830 enum ofp_version version,
3831 uint32_t buffer_id)
0f83fea0 3832{
43948fa5
BP
3833 enum ofpraw raw = (version >= OFP13_VERSION
3834 ? OFPRAW_OFPT13_PACKET_IN
3835 : OFPRAW_OFPT12_PACKET_IN);
3836 struct ofpbuf *msg;
0f83fea0 3837
0f83fea0 3838 /* The final argument is just an estimate of the space required. */
43948fa5 3839 msg = ofpraw_alloc_xid(raw, version,
4adaf182 3840 htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);
0f83fea0 3841
43948fa5 3842 struct ofp12_packet_in *opi = ofpbuf_put_zeros(msg, sizeof *opi);
9bfe9334 3843 opi->buffer_id = htonl(buffer_id);
4adaf182 3844 opi->total_len = htons(pin->packet_len);
9bfe9334 3845 opi->reason = encode_packet_in_reason(pin->reason, version);
43948fa5 3846 opi->table_id = pin->table_id;
9bfe9334 3847
43948fa5
BP
3848 if (version >= OFP13_VERSION) {
3849 ovs_be64 cookie = pin->cookie;
3850 ofpbuf_put(msg, &cookie, sizeof cookie);
0f83fea0
BP
3851 }
3852
43948fa5
BP
3853 oxm_put_match(msg, &pin->flow_metadata, version);
3854 ofpbuf_put_zeros(msg, 2);
43948fa5
BP
3855
3856 return msg;
0f83fea0
BP
3857}
3858
77ab5fd2
BP
3859/* Converts abstract ofputil_packet_in_private 'pin' into a PACKET_IN message
3860 * for 'protocol', using the packet-in format specified by 'packet_in_format'.
9bfe9334
BP
3861 *
3862 * If 'pkt_buf' is nonnull and 'max_len' allows the packet to be buffered, this
3863 * function will attempt to obtain a buffer ID from 'pktbuf' and truncate the
3864 * packet to 'max_len' bytes. Otherwise, or if 'pktbuf' doesn't have a free
77ab5fd2
BP
3865 * buffer, it will send the whole packet without buffering.
3866 *
3867 * This function is really meant only for use by ovs-vswitchd. To any other
3868 * code, the "continuation" data, i.e. the data that is in struct
3869 * ofputil_packet_in_private but not in struct ofputil_packet_in, is supposed
3870 * to be opaque (and it might change from one OVS version to another). Thus,
3871 * if any other code wants to encode a packet-in, it should use a non-"private"
3872 * version of this function. (Such a version doesn't currently exist because
3873 * only ovs-vswitchd currently wants to encode packet-ins. If you need one,
3874 * write it...) */
ebb57021 3875struct ofpbuf *
77ab5fd2
BP
3876ofputil_encode_packet_in_private(const struct ofputil_packet_in_private *pin,
3877 enum ofputil_protocol protocol,
3878 enum nx_packet_in_format packet_in_format,
3879 uint16_t max_len, struct pktbuf *pktbuf)
ebb57021 3880{
9bfe9334
BP
3881 enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
3882
3883 /* Get buffer ID. */
77ab5fd2 3884 ofp_port_t in_port = pin->public.flow_metadata.flow.in_port.ofp_port;
9bfe9334 3885 uint32_t buffer_id = (max_len != OFPCML12_NO_BUFFER && pktbuf
77ab5fd2
BP
3886 ? pktbuf_save(pktbuf, pin->public.packet,
3887 pin->public.packet_len, in_port)
9bfe9334 3888 : UINT32_MAX);
ebb57021 3889
6409e008
BP
3890 /* Calculate the number of bytes of the packet to include in the
3891 * packet-in:
3892 *
3893 * - If not buffered, the whole thing.
3894 *
3895 * - Otherwise, no more than 'max_len' bytes. */
3896 size_t include_bytes = (buffer_id == UINT32_MAX
77ab5fd2
BP
3897 ? pin->public.packet_len
3898 : MIN(max_len, pin->public.packet_len));
6409e008 3899
9bfe9334 3900 struct ofpbuf *msg;
6409e008
BP
3901 switch (packet_in_format) {
3902 case NXPIF_STANDARD:
3903 switch (protocol) {
3904 case OFPUTIL_P_OF10_STD:
3905 case OFPUTIL_P_OF10_STD_TID:
3906 case OFPUTIL_P_OF10_NXM:
3907 case OFPUTIL_P_OF10_NXM_TID:
77ab5fd2 3908 msg = ofputil_encode_ofp10_packet_in(&pin->public, buffer_id);
6409e008 3909 break;
2e1ae200 3910
6409e008 3911 case OFPUTIL_P_OF11_STD:
77ab5fd2 3912 msg = ofputil_encode_ofp11_packet_in(&pin->public, buffer_id);
6409e008
BP
3913 break;
3914
3915 case OFPUTIL_P_OF12_OXM:
3916 case OFPUTIL_P_OF13_OXM:
3917 case OFPUTIL_P_OF14_OXM:
3918 case OFPUTIL_P_OF15_OXM:
b79d45a1 3919 case OFPUTIL_P_OF16_OXM:
77ab5fd2 3920 msg = ofputil_encode_ofp12_packet_in(&pin->public, version, buffer_id);
6409e008
BP
3921 break;
3922
3923 default:
3924 OVS_NOT_REACHED();
3925 }
4d197ebb 3926 break;
d94240ec 3927
6409e008 3928 case NXPIF_NXT_PACKET_IN:
77ab5fd2 3929 msg = ofputil_encode_nx_packet_in(&pin->public, version, buffer_id);
0f83fea0
BP
3930 break;
3931
6409e008
BP
3932 case NXPIF_NXT_PACKET_IN2:
3933 return ofputil_encode_nx_packet_in2(pin, version, buffer_id,
3934 include_bytes);
3935
0f83fea0 3936 default:
428b2edd 3937 OVS_NOT_REACHED();
54834960 3938 }
54834960 3939
77ab5fd2 3940 ofpbuf_put(msg, pin->public.packet, include_bytes);
9bfe9334
BP
3941 ofpmsg_update_length(msg);
3942 return msg;
ebb57021
BP
3943}
3944
5014a89d
BP
3945/* Returns a string form of 'reason'. The return value is either a statically
3946 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
3947 * 'bufsize' should be at least OFPUTIL_PACKET_IN_REASON_BUFSIZE. */
7c1a76a4 3948const char *
5014a89d
BP
3949ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason,
3950 char *reasonbuf, size_t bufsize)
7c1a76a4 3951{
7c1a76a4
BP
3952 switch (reason) {
3953 case OFPR_NO_MATCH:
3954 return "no_match";
3955 case OFPR_ACTION:
3956 return "action";
3957 case OFPR_INVALID_TTL:
3958 return "invalid_ttl";
424467c6
SS
3959 case OFPR_ACTION_SET:
3960 return "action_set";
3961 case OFPR_GROUP:
3962 return "group";
3963 case OFPR_PACKET_OUT:
3964 return "packet_out";
9bfe9334
BP
3965 case OFPR_EXPLICIT_MISS:
3966 case OFPR_IMPLICIT_MISS:
3967 return "";
7c1a76a4
BP
3968
3969 case OFPR_N_REASONS:
3970 default:
5014a89d
BP
3971 snprintf(reasonbuf, bufsize, "%d", (int) reason);
3972 return reasonbuf;
7c1a76a4
BP
3973 }
3974}
3975
3976bool
3977ofputil_packet_in_reason_from_string(const char *s,
3978 enum ofp_packet_in_reason *reason)
3979{
3980 int i;
3981
3982 for (i = 0; i < OFPR_N_REASONS; i++) {
5014a89d
BP
3983 char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
3984 const char *reason_s;
3985
3986 reason_s = ofputil_packet_in_reason_to_string(i, reasonbuf,
3987 sizeof reasonbuf);
3988 if (!strcasecmp(s, reason_s)) {
7c1a76a4
BP
3989 *reason = i;
3990 return true;
3991 }
3992 }
3993 return false;
3994}
3995
77ab5fd2
BP
3996/* Returns a newly allocated NXT_RESUME message for 'pin', with the given
3997 * 'continuation', for 'protocol'. This message is suitable for resuming the
3998 * pipeline traveral of the packet represented by 'pin', if sent to the switch
3999 * from which 'pin' was received. */
4000struct ofpbuf *
4001ofputil_encode_resume(const struct ofputil_packet_in *pin,
4002 const struct ofpbuf *continuation,
4003 enum ofputil_protocol protocol)
4004{
4005 enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
4006 size_t extra = pin->packet_len + NXM_TYPICAL_LEN + continuation->size;
4007 struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_RESUME, version,
4008 0, extra);
4009 ofputil_put_packet_in(pin, version, UINT32_MAX, pin->packet_len, msg);
4010 ofpprop_put_nested(msg, NXPINT_CONTINUATION, continuation);
4011 ofpmsg_update_length(msg);
4012 return msg;
4013}
4014
4015static enum ofperr
4016parse_subvalue_prop(const struct ofpbuf *property, union mf_subvalue *sv)
4017{
4018 unsigned int len = ofpbuf_msgsize(property);
4019 if (len > sizeof *sv) {
4020 VLOG_WARN_RL(&bad_ofmsg_rl, "NXCPT_STACK property has bad length %u",
4021 len);
4022 return OFPERR_OFPBPC_BAD_LEN;
4023 }
4024 memset(sv, 0, sizeof *sv);
4025 memcpy(&sv->u8[sizeof *sv - len], property->msg, len);
4026 return 0;
4027}
4028
4029static enum ofperr
4030parse_actions_property(struct ofpbuf *property, enum ofp_version version,
4031 struct ofpbuf *ofpacts)
4032{
4033 if (!ofpbuf_try_pull(property, ROUND_UP(ofpbuf_headersize(property), 8))) {
4034 VLOG_WARN_RL(&bad_ofmsg_rl, "actions property has bad length %"PRIu32,
4035 property->size);
4036 return OFPERR_OFPBPC_BAD_LEN;
4037 }
4038
4039 return ofpacts_pull_openflow_actions(property, property->size,
4040 version, ofpacts);
4041}
4042
4043/* This is like ofputil_decode_packet_in(), except that it decodes the
4044 * continuation data into 'pin'. The format of this data is supposed to be
4045 * opaque to any process other than ovs-vswitchd, so this function should not
4046 * be used outside ovs-vswitchd.
4047 *
4048 * When successful, 'pin' contains some dynamically allocated data. Call
4049 * ofputil_packet_in_private_destroy() to free this data. */
4050enum ofperr
4051ofputil_decode_packet_in_private(const struct ofp_header *oh, bool loose,
4052 struct ofputil_packet_in_private *pin,
4053 size_t *total_len, uint32_t *buffer_id)
4054{
4055 memset(pin, 0, sizeof *pin);
4056
4057 struct ofpbuf continuation;
4058 enum ofperr error;
4059 error = ofputil_decode_packet_in(oh, loose, &pin->public, total_len,
4060 buffer_id, &continuation);
4061 if (error) {
4062 return error;
4063 }
4064
4065 struct ofpbuf actions, action_set;
4066 ofpbuf_init(&actions, 0);
4067 ofpbuf_init(&action_set, 0);
4068
4069 uint8_t table_id = 0;
4070 ovs_be64 cookie = 0;
4071
4072 size_t allocated_stack = 0;
4073
4074 while (continuation.size > 0) {
4075 struct ofpbuf payload;
4076 uint64_t type;
4077
4078 error = ofpprop_pull(&continuation, &payload, &type);
4079 ovs_assert(!error);
4080
4081 switch (type) {
4082 case NXCPT_BRIDGE:
4083 error = ofpprop_parse_uuid(&payload, &pin->bridge);
4084 break;
4085
4086 case NXCPT_STACK:
4087 if (pin->n_stack >= allocated_stack) {
4088 pin->stack = x2nrealloc(pin->stack, &allocated_stack,
4089 sizeof *pin->stack);
4090 }
4091 error = parse_subvalue_prop(&payload,
4092 &pin->stack[pin->n_stack++]);
4093 break;
4094
4095 case NXCPT_MIRRORS:
4096 error = ofpprop_parse_u32(&payload, &pin->mirrors);
4097 break;
4098
4099 case NXCPT_CONNTRACKED:
4100 pin->conntracked = true;
4101 break;
4102
4103 case NXCPT_TABLE_ID:
4104 error = ofpprop_parse_u8(&payload, &table_id);
4105 break;
4106
4107 case NXCPT_COOKIE:
4108 error = ofpprop_parse_be64(&payload, &cookie);
4109 break;
4110
4111 case NXCPT_ACTIONS: {
4112 struct ofpact_unroll_xlate *unroll
4113 = ofpact_put_UNROLL_XLATE(&actions);
4114 unroll->rule_table_id = table_id;
4115 unroll->rule_cookie = cookie;
4116 error = parse_actions_property(&payload, oh->version, &actions);
4117 break;
4118 }
4119
4120 case NXCPT_ACTION_SET:
4121 error = parse_actions_property(&payload, oh->version, &action_set);
4122 break;
4123
4124 default:
4125 error = OFPPROP_UNKNOWN(loose, "continuation", type);
4126 break;
4127 }
4128 if (error) {
4129 break;
4130 }
4131 }
4132
4133 pin->actions_len = actions.size;
4134 pin->actions = ofpbuf_steal_data(&actions);
4135 pin->action_set_len = action_set.size;
4136 pin->action_set = ofpbuf_steal_data(&action_set);
4137
4138 if (error) {
4139 ofputil_packet_in_private_destroy(pin);
4140 }
4141
4142 return 0;
4143}
4144
4145/* Frees data in 'pin' that is dynamically allocated by
4146 * ofputil_decode_packet_in_private().
4147 *
4148 * 'pin->public' contains some pointer members that
4149 * ofputil_decode_packet_in_private() doesn't initialize to newly allocated
4150 * data, so this function doesn't free those. */
4151void
4152ofputil_packet_in_private_destroy(struct ofputil_packet_in_private *pin)
4153{
4154 if (pin) {
4155 free(pin->stack);
4156 free(pin->actions);
4157 free(pin->action_set);
4158 }
4159}
4160
f25d0cf3
BP
4161/* Converts an OFPT_PACKET_OUT in 'opo' into an abstract ofputil_packet_out in
4162 * 'po'.
4163 *
4164 * Uses 'ofpacts' to store the abstract OFPACT_* version of the packet out
4165 * message's actions. The caller must initialize 'ofpacts' and retains
4166 * ownership of it. 'po->ofpacts' will point into the 'ofpacts' buffer.
4167 *
4168 * Returns 0 if successful, otherwise an OFPERR_* value. */
c6a93eb7
BP
4169enum ofperr
4170ofputil_decode_packet_out(struct ofputil_packet_out *po,
982697a4 4171 const struct ofp_header *oh,
f25d0cf3 4172 struct ofpbuf *ofpacts)
c6a93eb7 4173{
0a2869d5
BP
4174 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
4175 enum ofpraw raw = ofpraw_pull_assert(&b);
982697a4 4176
9abca1e5 4177 ofpbuf_clear(ofpacts);
eb5ee596
SH
4178 if (raw == OFPRAW_OFPT11_PACKET_OUT) {
4179 enum ofperr error;
4180 const struct ofp11_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
4181
4182 po->buffer_id = ntohl(opo->buffer_id);
4183 error = ofputil_port_from_ofp11(opo->in_port, &po->in_port);
4184 if (error) {
4185 return error;
4186 }
4187
e3f8f887
JR
4188 error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
4189 oh->version, ofpacts);
eb5ee596
SH
4190 if (error) {
4191 return error;
4192 }
eb5ee596 4193 } else if (raw == OFPRAW_OFPT10_PACKET_OUT) {
8a6bc7cd 4194 enum ofperr error;
31a9e63f 4195 const struct ofp10_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
8a6bc7cd
SH
4196
4197 po->buffer_id = ntohl(opo->buffer_id);
4e022ec0 4198 po->in_port = u16_to_ofp(ntohs(opo->in_port));
8a6bc7cd 4199
e3f8f887
JR
4200 error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
4201 oh->version, ofpacts);
8a6bc7cd
SH
4202 if (error) {
4203 return error;
4204 }
4205 } else {
428b2edd 4206 OVS_NOT_REACHED();
8a6bc7cd
SH
4207 }
4208
4e022ec0
AW
4209 if (ofp_to_u16(po->in_port) >= ofp_to_u16(OFPP_MAX)
4210 && po->in_port != OFPP_LOCAL
751c7785 4211 && po->in_port != OFPP_NONE && po->in_port != OFPP_CONTROLLER) {
c6a93eb7
BP
4212 VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16,
4213 po->in_port);
2e1bfcb6 4214 return OFPERR_OFPBRC_BAD_PORT;
c6a93eb7
BP
4215 }
4216
6fd6ed71
PS
4217 po->ofpacts = ofpacts->data;
4218 po->ofpacts_len = ofpacts->size;
c6a93eb7
BP
4219
4220 if (po->buffer_id == UINT32_MAX) {
6fd6ed71
PS
4221 po->packet = b.data;
4222 po->packet_len = b.size;
c6a93eb7
BP
4223 } else {
4224 po->packet = NULL;
4225 po->packet_len = 0;
4226 }
4227
4228 return 0;
4229}
6c038611
BP
4230\f
4231/* ofputil_phy_port */
4232
4233/* NETDEV_F_* to and from OFPPF_* and OFPPF10_*. */
4234BUILD_ASSERT_DECL((int) NETDEV_F_10MB_HD == OFPPF_10MB_HD); /* bit 0 */
4235BUILD_ASSERT_DECL((int) NETDEV_F_10MB_FD == OFPPF_10MB_FD); /* bit 1 */
4236BUILD_ASSERT_DECL((int) NETDEV_F_100MB_HD == OFPPF_100MB_HD); /* bit 2 */
4237BUILD_ASSERT_DECL((int) NETDEV_F_100MB_FD == OFPPF_100MB_FD); /* bit 3 */
4238BUILD_ASSERT_DECL((int) NETDEV_F_1GB_HD == OFPPF_1GB_HD); /* bit 4 */
4239BUILD_ASSERT_DECL((int) NETDEV_F_1GB_FD == OFPPF_1GB_FD); /* bit 5 */
4240BUILD_ASSERT_DECL((int) NETDEV_F_10GB_FD == OFPPF_10GB_FD); /* bit 6 */
4241
4242/* NETDEV_F_ bits 11...15 are OFPPF10_ bits 7...11: */
9e1fd49b
BP
4243BUILD_ASSERT_DECL((int) NETDEV_F_COPPER == (OFPPF10_COPPER << 4));
4244BUILD_ASSERT_DECL((int) NETDEV_F_FIBER == (OFPPF10_FIBER << 4));
4245BUILD_ASSERT_DECL((int) NETDEV_F_AUTONEG == (OFPPF10_AUTONEG << 4));
4246BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE == (OFPPF10_PAUSE << 4));
4247BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE_ASYM == (OFPPF10_PAUSE_ASYM << 4));
6c038611 4248
9e1fd49b
BP
4249static enum netdev_features
4250netdev_port_features_from_ofp10(ovs_be32 ofp10_)
6c038611
BP
4251{
4252 uint32_t ofp10 = ntohl(ofp10_);
4253 return (ofp10 & 0x7f) | ((ofp10 & 0xf80) << 4);
4254}
4255
9e1fd49b
BP
4256static ovs_be32
4257netdev_port_features_to_ofp10(enum netdev_features features)
6c038611
BP
4258{
4259 return htonl((features & 0x7f) | ((features & 0xf800) >> 4));
4260}
c6a93eb7 4261
9e1fd49b
BP
4262BUILD_ASSERT_DECL((int) NETDEV_F_10MB_HD == OFPPF_10MB_HD); /* bit 0 */
4263BUILD_ASSERT_DECL((int) NETDEV_F_10MB_FD == OFPPF_10MB_FD); /* bit 1 */
4264BUILD_ASSERT_DECL((int) NETDEV_F_100MB_HD == OFPPF_100MB_HD); /* bit 2 */
4265BUILD_ASSERT_DECL((int) NETDEV_F_100MB_FD == OFPPF_100MB_FD); /* bit 3 */
4266BUILD_ASSERT_DECL((int) NETDEV_F_1GB_HD == OFPPF_1GB_HD); /* bit 4 */
4267BUILD_ASSERT_DECL((int) NETDEV_F_1GB_FD == OFPPF_1GB_FD); /* bit 5 */
4268BUILD_ASSERT_DECL((int) NETDEV_F_10GB_FD == OFPPF_10GB_FD); /* bit 6 */
4269BUILD_ASSERT_DECL((int) NETDEV_F_40GB_FD == OFPPF11_40GB_FD); /* bit 7 */
4270BUILD_ASSERT_DECL((int) NETDEV_F_100GB_FD == OFPPF11_100GB_FD); /* bit 8 */
4271BUILD_ASSERT_DECL((int) NETDEV_F_1TB_FD == OFPPF11_1TB_FD); /* bit 9 */
4272BUILD_ASSERT_DECL((int) NETDEV_F_OTHER == OFPPF11_OTHER); /* bit 10 */
4273BUILD_ASSERT_DECL((int) NETDEV_F_COPPER == OFPPF11_COPPER); /* bit 11 */
4274BUILD_ASSERT_DECL((int) NETDEV_F_FIBER == OFPPF11_FIBER); /* bit 12 */
4275BUILD_ASSERT_DECL((int) NETDEV_F_AUTONEG == OFPPF11_AUTONEG); /* bit 13 */
4276BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE == OFPPF11_PAUSE); /* bit 14 */
4277BUILD_ASSERT_DECL((int) NETDEV_F_PAUSE_ASYM == OFPPF11_PAUSE_ASYM);/* bit 15 */
4278
4279static enum netdev_features
4280netdev_port_features_from_ofp11(ovs_be32 ofp11)
4281{
4282 return ntohl(ofp11) & 0xffff;
4283}
4284
4285static ovs_be32
4286netdev_port_features_to_ofp11(enum netdev_features features)
4287{
4288 return htonl(features & 0xffff);
4289}
4290
4291static enum ofperr
4292ofputil_decode_ofp10_phy_port(struct ofputil_phy_port *pp,
4293 const struct ofp10_phy_port *opp)
4294{
4e022ec0 4295 pp->port_no = u16_to_ofp(ntohs(opp->port_no));
74ff3298 4296 pp->hw_addr = opp->hw_addr;
9e1fd49b
BP
4297 ovs_strlcpy(pp->name, opp->name, OFP_MAX_PORT_NAME_LEN);
4298
4299 pp->config = ntohl(opp->config) & OFPPC10_ALL;
4300 pp->state = ntohl(opp->state) & OFPPS10_ALL;
4301
4302 pp->curr = netdev_port_features_from_ofp10(opp->curr);
4303 pp->advertised = netdev_port_features_from_ofp10(opp->advertised);
4304 pp->supported = netdev_port_features_from_ofp10(opp->supported);
4305 pp->peer = netdev_port_features_from_ofp10(opp->peer);
4306
d02a5f8e
BP
4307 pp->curr_speed = netdev_features_to_bps(pp->curr, 0) / 1000;
4308 pp->max_speed = netdev_features_to_bps(pp->supported, 0) / 1000;
9e1fd49b
BP
4309
4310 return 0;
4311}
4312
4313static enum ofperr
4314ofputil_decode_ofp11_port(struct ofputil_phy_port *pp,
4315 const struct ofp11_port *op)
4316{
4317 enum ofperr error;
4318
9e1fd49b
BP
4319 error = ofputil_port_from_ofp11(op->port_no, &pp->port_no);
4320 if (error) {
4321 return error;
4322 }
74ff3298 4323 pp->hw_addr = op->hw_addr;
9e1fd49b
BP
4324 ovs_strlcpy(pp->name, op->name, OFP_MAX_PORT_NAME_LEN);
4325
4326 pp->config = ntohl(op->config) & OFPPC11_ALL;
646f2b37 4327 pp->state = ntohl(op->state) & OFPPS11_ALL;
9e1fd49b
BP
4328
4329 pp->curr = netdev_port_features_from_ofp11(op->curr);
4330 pp->advertised = netdev_port_features_from_ofp11(op->advertised);
4331 pp->supported = netdev_port_features_from_ofp11(op->supported);
4332 pp->peer = netdev_port_features_from_ofp11(op->peer);
4333
4334 pp->curr_speed = ntohl(op->curr_speed);
4335 pp->max_speed = ntohl(op->max_speed);
4336
4337 return 0;
4338}
4339
8c3cc785
BP
4340static enum ofperr
4341parse_ofp14_port_ethernet_property(const struct ofpbuf *payload,
4342 struct ofputil_phy_port *pp)
4343{
6fd6ed71 4344 struct ofp14_port_desc_prop_ethernet *eth = payload->data;
8c3cc785 4345
6fd6ed71 4346 if (payload->size != sizeof *eth) {
8c3cc785
BP
4347 return OFPERR_OFPBPC_BAD_LEN;
4348 }
4349
4350 pp->curr = netdev_port_features_from_ofp11(eth->curr);
4351 pp->advertised = netdev_port_features_from_ofp11(eth->advertised);
4352 pp->supported = netdev_port_features_from_ofp11(eth->supported);
4353 pp->peer = netdev_port_features_from_ofp11(eth->peer);
4354
4355 pp->curr_speed = ntohl(eth->curr_speed);
4356 pp->max_speed = ntohl(eth->max_speed);
4357
4358 return 0;
4359}
4360
4361static enum ofperr
4362ofputil_pull_ofp14_port(struct ofputil_phy_port *pp, struct ofpbuf *msg)
4363{
0a2869d5 4364 struct ofp14_port *op = ofpbuf_try_pull(msg, sizeof *op);
8c3cc785
BP
4365 if (!op) {
4366 return OFPERR_OFPBRC_BAD_LEN;
4367 }
4368
0a2869d5 4369 size_t len = ntohs(op->length);
6fd6ed71 4370 if (len < sizeof *op || len - sizeof *op > msg->size) {
8c3cc785
BP
4371 return OFPERR_OFPBRC_BAD_LEN;
4372 }
4373 len -= sizeof *op;
8c3cc785 4374
0a2869d5 4375 enum ofperr error = ofputil_port_from_ofp11(op->port_no, &pp->port_no);
8c3cc785
BP
4376 if (error) {
4377 return error;
4378 }
74ff3298 4379 pp->hw_addr = op->hw_addr;
8c3cc785
BP
4380 ovs_strlcpy(pp->name, op->name, OFP_MAX_PORT_NAME_LEN);
4381
4382 pp->config = ntohl(op->config) & OFPPC11_ALL;
4383 pp->state = ntohl(op->state) & OFPPS11_ALL;
4384
0a2869d5
BP
4385 struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
4386 len);
6fd6ed71 4387 while (properties.size > 0) {
8c3cc785
BP
4388 struct ofpbuf payload;
4389 enum ofperr error;
34a543e3 4390 uint64_t type;
8c3cc785 4391
c5562271 4392 error = ofpprop_pull(&properties, &payload, &type);
8c3cc785
BP
4393 if (error) {
4394 return error;
4395 }
4396
4397 switch (type) {
4398 case OFPPDPT14_ETHERNET:
4399 error = parse_ofp14_port_ethernet_property(&payload, pp);
4400 break;
4401
4402 default:
34a543e3 4403 error = OFPPROP_UNKNOWN(true, "port", type);
8c3cc785
BP
4404 break;
4405 }
4406
4407 if (error) {
4408 return error;
4409 }
4410 }
4411
4412 return 0;
4413}
4414
9e1fd49b
BP
4415static void
4416ofputil_encode_ofp10_phy_port(const struct ofputil_phy_port *pp,
4417 struct ofp10_phy_port *opp)
4418{
4419 memset(opp, 0, sizeof *opp);
4420
4e022ec0 4421 opp->port_no = htons(ofp_to_u16(pp->port_no));
74ff3298 4422 opp->hw_addr = pp->hw_addr;
9e1fd49b
BP
4423 ovs_strlcpy(opp->name, pp->name, OFP_MAX_PORT_NAME_LEN);
4424
4425 opp->config = htonl(pp->config & OFPPC10_ALL);
4426 opp->state = htonl(pp->state & OFPPS10_ALL);
4427
4428 opp->curr = netdev_port_features_to_ofp10(pp->curr);
4429 opp->advertised = netdev_port_features_to_ofp10(pp->advertised);
4430 opp->supported = netdev_port_features_to_ofp10(pp->supported);
4431 opp->peer = netdev_port_features_to_ofp10(pp->peer);
4432}
4433
4434static void
4435ofputil_encode_ofp11_port(const struct ofputil_phy_port *pp,
4436 struct ofp11_port *op)
4437{
4438 memset(op, 0, sizeof *op);
4439
4440 op->port_no = ofputil_port_to_ofp11(pp->port_no);
74ff3298 4441 op->hw_addr = pp->hw_addr;
9e1fd49b
BP
4442 ovs_strlcpy(op->name, pp->name, OFP_MAX_PORT_NAME_LEN);
4443
4444 op->config = htonl(pp->config & OFPPC11_ALL);
4445 op->state = htonl(pp->state & OFPPS11_ALL);
4446
4447 op->curr = netdev_port_features_to_ofp11(pp->curr);
4448 op->advertised = netdev_port_features_to_ofp11(pp->advertised);
4449 op->supported = netdev_port_features_to_ofp11(pp->supported);
4450 op->peer = netdev_port_features_to_ofp11(pp->peer);
4451
4452 op->curr_speed = htonl(pp->curr_speed);
4453 op->max_speed = htonl(pp->max_speed);
4454}
4455
8c3cc785
BP
4456static void
4457ofputil_put_ofp14_port(const struct ofputil_phy_port *pp,
4458 struct ofpbuf *b)
4459{
4460 struct ofp14_port *op;
4461 struct ofp14_port_desc_prop_ethernet *eth;
4462
4463 ofpbuf_prealloc_tailroom(b, sizeof *op + sizeof *eth);
4464
4465 op = ofpbuf_put_zeros(b, sizeof *op);
4466 op->port_no = ofputil_port_to_ofp11(pp->port_no);
4467 op->length = htons(sizeof *op + sizeof *eth);
74ff3298 4468 op->hw_addr = pp->hw_addr;
8c3cc785
BP
4469 ovs_strlcpy(op->name, pp->name, sizeof op->name);
4470 op->config = htonl(pp->config & OFPPC11_ALL);
4471 op->state = htonl(pp->state & OFPPS11_ALL);
4472
303721ee 4473 eth = ofpprop_put_zeros(b, OFPPDPT14_ETHERNET, sizeof *eth);
8c3cc785
BP
4474 eth->curr = netdev_port_features_to_ofp11(pp->curr);
4475 eth->advertised = netdev_port_features_to_ofp11(pp->advertised);
4476 eth->supported = netdev_port_features_to_ofp11(pp->supported);
4477 eth->peer = netdev_port_features_to_ofp11(pp->peer);
4478 eth->curr_speed = htonl(pp->curr_speed);
4479 eth->max_speed = htonl(pp->max_speed);
4480}
4481
9e1fd49b 4482static void
2e3fa633
SH
4483ofputil_put_phy_port(enum ofp_version ofp_version,
4484 const struct ofputil_phy_port *pp, struct ofpbuf *b)
9e1fd49b 4485{
2e3fa633
SH
4486 switch (ofp_version) {
4487 case OFP10_VERSION: {
6b0f20ac
BP
4488 struct ofp10_phy_port *opp = ofpbuf_put_uninit(b, sizeof *opp);
4489 ofputil_encode_ofp10_phy_port(pp, opp);
2e3fa633
SH
4490 break;
4491 }
4492
4493 case OFP11_VERSION:
2e1ae200
JR
4494 case OFP12_VERSION:
4495 case OFP13_VERSION: {
6b0f20ac
BP
4496 struct ofp11_port *op = ofpbuf_put_uninit(b, sizeof *op);
4497 ofputil_encode_ofp11_port(pp, op);
2e3fa633
SH
4498 break;
4499 }
4500
c37c0382 4501 case OFP14_VERSION:
42dccab5 4502 case OFP15_VERSION:
b79d45a1 4503 case OFP16_VERSION:
8c3cc785 4504 ofputil_put_ofp14_port(pp, b);
c37c0382
AC
4505 break;
4506
2e3fa633 4507 default:
428b2edd 4508 OVS_NOT_REACHED();
9e1fd49b
BP
4509 }
4510}
2be393ed 4511
70ae4f93
BP
4512enum ofperr
4513ofputil_decode_port_desc_stats_request(const struct ofp_header *request,
4514 ofp_port_t *port)
4515{
0a2869d5
BP
4516 struct ofpbuf b = ofpbuf_const_initializer(request,
4517 ntohs(request->length));
4518 enum ofpraw raw = ofpraw_pull_assert(&b);
70ae4f93
BP
4519 if (raw == OFPRAW_OFPST10_PORT_DESC_REQUEST) {
4520 *port = OFPP_ANY;
4521 return 0;
4522 } else if (raw == OFPRAW_OFPST15_PORT_DESC_REQUEST) {
4523 ovs_be32 *ofp11_port;
4524
4525 ofp11_port = ofpbuf_pull(&b, sizeof *ofp11_port);
4526 return ofputil_port_from_ofp11(*ofp11_port, port);
4527 } else {
4528 OVS_NOT_REACHED();
4529 }
4530}
4531
4532struct ofpbuf *
4533ofputil_encode_port_desc_stats_request(enum ofp_version ofp_version,
4534 ofp_port_t port)
4535{
4536 struct ofpbuf *request;
70ae4f93
BP
4537
4538 switch (ofp_version) {
4539 case OFP10_VERSION:
4540 case OFP11_VERSION:
4541 case OFP12_VERSION:
4542 case OFP13_VERSION:
4543 case OFP14_VERSION:
4544 request = ofpraw_alloc(OFPRAW_OFPST10_PORT_DESC_REQUEST,
4545 ofp_version, 0);
4546 break;
b79d45a1
BP
4547 case OFP15_VERSION:
4548 case OFP16_VERSION:{
7448d548 4549 struct ofp15_port_desc_request *req;
70ae4f93
BP
4550 request = ofpraw_alloc(OFPRAW_OFPST15_PORT_DESC_REQUEST,
4551 ofp_version, 0);
7448d548
MT
4552 req = ofpbuf_put_zeros(request, sizeof *req);
4553 req->port_no = ofputil_port_to_ofp11(port);
70ae4f93 4554 break;
7448d548 4555 }
70ae4f93
BP
4556 default:
4557 OVS_NOT_REACHED();
4558 }
4559
4560 return request;
4561}
4562
2be393ed 4563void
e28ac5cf 4564ofputil_append_port_desc_stats_reply(const struct ofputil_phy_port *pp,
ca6ba700 4565 struct ovs_list *replies)
2be393ed 4566{
417e7e66 4567 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
6fd6ed71 4568 size_t start_ofs = reply->size;
c37c0382 4569
6b0f20ac
BP
4570 ofputil_put_phy_port(ofpmp_version(replies), pp, reply);
4571 ofpmp_postappend(replies, start_ofs);
2be393ed 4572}
9e1fd49b 4573\f
ad99e2ed
BP
4574/* ofputil_switch_config */
4575
4576/* Decodes 'oh', which must be an OFPT_GET_CONFIG_REPLY or OFPT_SET_CONFIG
4577 * message, into 'config'. Returns false if 'oh' contained any flags that
4578 * aren't specified in its version of OpenFlow, true otherwise. */
4579static bool
4580ofputil_decode_switch_config(const struct ofp_header *oh,
4581 struct ofputil_switch_config *config)
4582{
0a2869d5 4583 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
ad99e2ed 4584 ofpraw_pull_assert(&b);
ad99e2ed 4585
0a2869d5 4586 const struct ofp_switch_config *osc = ofpbuf_pull(&b, sizeof *osc);
ad99e2ed
BP
4587 config->frag = ntohs(osc->flags) & OFPC_FRAG_MASK;
4588 config->miss_send_len = ntohs(osc->miss_send_len);
4589
4590 ovs_be16 valid_mask = htons(OFPC_FRAG_MASK);
4591 if (oh->version < OFP13_VERSION) {
4592 const ovs_be16 ttl_bit = htons(OFPC_INVALID_TTL_TO_CONTROLLER);
4593 valid_mask |= ttl_bit;
4594 config->invalid_ttl_to_controller = (osc->flags & ttl_bit) != 0;
4595 } else {
4596 config->invalid_ttl_to_controller = -1;
4597 }
4598
4599 return !(osc->flags & ~valid_mask);
4600}
4601
4602void
4603ofputil_decode_get_config_reply(const struct ofp_header *oh,
4604 struct ofputil_switch_config *config)
4605{
4606 ofputil_decode_switch_config(oh, config);
4607}
4608
4609enum ofperr
4610ofputil_decode_set_config(const struct ofp_header *oh,
4611 struct ofputil_switch_config *config)
4612{
4613 return (ofputil_decode_switch_config(oh, config)
4614 ? 0
4615 : OFPERR_OFPSCFC_BAD_FLAGS);
4616}
4617
4618static struct ofpbuf *
4619ofputil_put_switch_config(const struct ofputil_switch_config *config,
4620 struct ofpbuf *b)
4621{
4622 const struct ofp_header *oh = b->data;
4623 struct ofp_switch_config *osc = ofpbuf_put_zeros(b, sizeof *osc);
4624 osc->flags = htons(config->frag);
4625 if (config->invalid_ttl_to_controller > 0 && oh->version < OFP13_VERSION) {
4626 osc->flags |= htons(OFPC_INVALID_TTL_TO_CONTROLLER);
4627 }
4628 osc->miss_send_len = htons(config->miss_send_len);
4629 return b;
4630}
4631
4632struct ofpbuf *
4633ofputil_encode_get_config_reply(const struct ofp_header *request,
4634 const struct ofputil_switch_config *config)
4635{
4636 struct ofpbuf *b = ofpraw_alloc_reply(OFPRAW_OFPT_GET_CONFIG_REPLY,
4637 request, 0);
4638 return ofputil_put_switch_config(config, b);
4639}
4640
4641struct ofpbuf *
4642ofputil_encode_set_config(const struct ofputil_switch_config *config,
4643 enum ofp_version version)
4644{
4645 struct ofpbuf *b = ofpraw_alloc(OFPRAW_OFPT_SET_CONFIG, version, 0);
4646 return ofputil_put_switch_config(config, b);
4647}
4648\f
9e1fd49b
BP
4649/* ofputil_switch_features */
4650
4651#define OFPC_COMMON (OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
60202987 4652 OFPC_IP_REASM | OFPC_QUEUE_STATS)
9e1fd49b
BP
4653BUILD_ASSERT_DECL((int) OFPUTIL_C_FLOW_STATS == OFPC_FLOW_STATS);
4654BUILD_ASSERT_DECL((int) OFPUTIL_C_TABLE_STATS == OFPC_TABLE_STATS);
4655BUILD_ASSERT_DECL((int) OFPUTIL_C_PORT_STATS == OFPC_PORT_STATS);
4656BUILD_ASSERT_DECL((int) OFPUTIL_C_IP_REASM == OFPC_IP_REASM);
4657BUILD_ASSERT_DECL((int) OFPUTIL_C_QUEUE_STATS == OFPC_QUEUE_STATS);
4658BUILD_ASSERT_DECL((int) OFPUTIL_C_ARP_MATCH_IP == OFPC_ARP_MATCH_IP);
4659
60202987
SH
4660static uint32_t
4661ofputil_capabilities_mask(enum ofp_version ofp_version)
4662{
0746a84f 4663 /* Handle capabilities whose bit is unique for all OpenFlow versions */
60202987
SH
4664 switch (ofp_version) {
4665 case OFP10_VERSION:
4666 case OFP11_VERSION:
4667 return OFPC_COMMON | OFPC_ARP_MATCH_IP;
4668 case OFP12_VERSION:
2e1ae200 4669 case OFP13_VERSION:
c37c0382 4670 case OFP14_VERSION:
42dccab5 4671 case OFP15_VERSION:
b79d45a1 4672 case OFP16_VERSION:
18cc69d9 4673 return OFPC_COMMON | OFPC12_PORT_BLOCKED;
60202987
SH
4674 default:
4675 /* Caller needs to check osf->header.version itself */
4676 return 0;
4677 }
4678}
4679
667bb1fb
BP
4680/* Pulls an OpenFlow "switch_features" structure from 'b' and decodes it into
4681 * an abstract representation in '*features', readying 'b' to iterate over the
4682 * OpenFlow port structures following 'osf' with later calls to
4683 * ofputil_pull_phy_port(). Returns 0 if successful, otherwise an OFPERR_*
4684 * value. */
9e1fd49b 4685enum ofperr
667bb1fb
BP
4686ofputil_pull_switch_features(struct ofpbuf *b,
4687 struct ofputil_switch_features *features)
9e1fd49b 4688{
667bb1fb
BP
4689 const struct ofp_header *oh = b->data;
4690 enum ofpraw raw = ofpraw_pull_assert(b);
4691 const struct ofp_switch_features *osf = ofpbuf_pull(b, sizeof *osf);
9e1fd49b
BP
4692 features->datapath_id = ntohll(osf->datapath_id);
4693 features->n_buffers = ntohl(osf->n_buffers);
4694 features->n_tables = osf->n_tables;
2e1ae200 4695 features->auxiliary_id = 0;
9e1fd49b 4696
60202987
SH
4697 features->capabilities = ntohl(osf->capabilities) &
4698 ofputil_capabilities_mask(oh->version);
9e1fd49b 4699
982697a4 4700 if (raw == OFPRAW_OFPT10_FEATURES_REPLY) {
9e1fd49b
BP
4701 if (osf->capabilities & htonl(OFPC10_STP)) {
4702 features->capabilities |= OFPUTIL_C_STP;
4703 }
08d1e234
BP
4704 features->ofpacts = ofpact_bitmap_from_openflow(osf->actions,
4705 OFP10_VERSION);
2e1ae200
JR
4706 } else if (raw == OFPRAW_OFPT11_FEATURES_REPLY
4707 || raw == OFPRAW_OFPT13_FEATURES_REPLY) {
9e1fd49b
BP
4708 if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) {
4709 features->capabilities |= OFPUTIL_C_GROUP_STATS;
4710 }
08d1e234 4711 features->ofpacts = 0;
2e1ae200
JR
4712 if (raw == OFPRAW_OFPT13_FEATURES_REPLY) {
4713 features->auxiliary_id = osf->auxiliary_id;
4714 }
9e1fd49b
BP
4715 } else {
4716 return OFPERR_OFPBRC_BAD_VERSION;
4717 }
4718
4719 return 0;
4720}
4721
fca6d553
BP
4722/* In OpenFlow 1.0, 1.1, and 1.2, an OFPT_FEATURES_REPLY message lists all the
4723 * switch's ports, unless there are too many to fit. In OpenFlow 1.3 and
4724 * later, an OFPT_FEATURES_REPLY does not list ports at all.
4725 *
4726 * Given a buffer 'b' that contains a Features Reply message, this message
4727 * checks if it contains a complete list of the switch's ports. Returns true,
4728 * if so. Returns false if the list is missing (OF1.3+) or incomplete
4729 * (OF1.0/1.1/1.2), and in the latter case removes all of the ports from the
4730 * message.
4731 *
4732 * When this function returns false, the caller should send an OFPST_PORT_DESC
4733 * stats request to get the ports. */
347b7ac4 4734bool
fca6d553 4735ofputil_switch_features_has_ports(struct ofpbuf *b)
347b7ac4 4736{
6fd6ed71 4737 struct ofp_header *oh = b->data;
13e1aff8 4738 size_t phy_port_size;
347b7ac4 4739
fca6d553 4740 if (oh->version >= OFP13_VERSION) {
13e1aff8 4741 /* OpenFlow 1.3+ never has ports in the feature reply. */
fca6d553 4742 return false;
13e1aff8
BP
4743 }
4744
4745 phy_port_size = (oh->version == OFP10_VERSION
4746 ? sizeof(struct ofp10_phy_port)
4747 : sizeof(struct ofp11_port));
4748 if (ntohs(oh->length) + phy_port_size <= UINT16_MAX) {
4749 /* There's room for additional ports in the feature reply.
4750 * Assume that the list is complete. */
347b7ac4
JP
4751 return true;
4752 }
13e1aff8
BP
4753
4754 /* The feature reply has no room for more ports. Probably the list is
4755 * truncated. Drop the ports and tell the caller to retrieve them with
4756 * OFPST_PORT_DESC. */
6fd6ed71 4757 b->size = sizeof *oh + sizeof(struct ofp_switch_features);
13e1aff8
BP
4758 ofpmsg_update_length(b);
4759 return false;
347b7ac4
JP
4760}
4761
9e1fd49b
BP
4762/* Returns a buffer owned by the caller that encodes 'features' in the format
4763 * required by 'protocol' with the given 'xid'. The caller should append port
4764 * information to the buffer with subsequent calls to
4765 * ofputil_put_switch_features_port(). */
4766struct ofpbuf *
4767ofputil_encode_switch_features(const struct ofputil_switch_features *features,
4768 enum ofputil_protocol protocol, ovs_be32 xid)
4769{
4770 struct ofp_switch_features *osf;
4771 struct ofpbuf *b;
2e3fa633
SH
4772 enum ofp_version version;
4773 enum ofpraw raw;
982697a4
BP
4774
4775 version = ofputil_protocol_to_ofp_version(protocol);
2e3fa633
SH
4776 switch (version) {
4777 case OFP10_VERSION:
4778 raw = OFPRAW_OFPT10_FEATURES_REPLY;
4779 break;
4780 case OFP11_VERSION:
4781 case OFP12_VERSION:
4782 raw = OFPRAW_OFPT11_FEATURES_REPLY;
4783 break;
2e1ae200 4784 case OFP13_VERSION:
c37c0382 4785 case OFP14_VERSION:
42dccab5 4786 case OFP15_VERSION:
b79d45a1 4787 case OFP16_VERSION:
2e1ae200
JR
4788 raw = OFPRAW_OFPT13_FEATURES_REPLY;
4789 break;
2e3fa633 4790 default:
428b2edd 4791 OVS_NOT_REACHED();
2e3fa633
SH
4792 }
4793 b = ofpraw_alloc_xid(raw, version, xid, 0);
982697a4 4794 osf = ofpbuf_put_zeros(b, sizeof *osf);
9e1fd49b
BP
4795 osf->datapath_id = htonll(features->datapath_id);
4796 osf->n_buffers = htonl(features->n_buffers);
4797 osf->n_tables = features->n_tables;
4798
4799 osf->capabilities = htonl(features->capabilities & OFPC_COMMON);
60202987
SH
4800 osf->capabilities = htonl(features->capabilities &
4801 ofputil_capabilities_mask(version));
2e3fa633
SH
4802 switch (version) {
4803 case OFP10_VERSION:
9e1fd49b
BP
4804 if (features->capabilities & OFPUTIL_C_STP) {
4805 osf->capabilities |= htonl(OFPC10_STP);
4806 }
08d1e234
BP
4807 osf->actions = ofpact_bitmap_to_openflow(features->ofpacts,
4808 OFP10_VERSION);
2e3fa633 4809 break;
2e1ae200 4810 case OFP13_VERSION:
c37c0382 4811 case OFP14_VERSION:
42dccab5 4812 case OFP15_VERSION:
b79d45a1 4813 case OFP16_VERSION:
2e1ae200
JR
4814 osf->auxiliary_id = features->auxiliary_id;
4815 /* fall through */
2e3fa633
SH
4816 case OFP11_VERSION:
4817 case OFP12_VERSION:
9e1fd49b
BP
4818 if (features->capabilities & OFPUTIL_C_GROUP_STATS) {
4819 osf->capabilities |= htonl(OFPC11_GROUP_STATS);
4820 }
2e3fa633
SH
4821 break;
4822 default:
428b2edd 4823 OVS_NOT_REACHED();
9e1fd49b
BP
4824 }
4825
4826 return b;
4827}
4828
4829/* Encodes 'pp' into the format required by the switch_features message already
4830 * in 'b', which should have been returned by ofputil_encode_switch_features(),
4831 * and appends the encoded version to 'b'. */
4832void
4833ofputil_put_switch_features_port(const struct ofputil_phy_port *pp,
4834 struct ofpbuf *b)
4835{
6fd6ed71 4836 const struct ofp_header *oh = b->data;
9e1fd49b 4837
e0c91c0c 4838 if (oh->version < OFP13_VERSION) {
6b0f20ac
BP
4839 /* Try adding a port description to the message, but drop it again if
4840 * the buffer overflows. (This possibility for overflow is why
4841 * OpenFlow 1.3+ moved port descriptions into a multipart message.) */
6fd6ed71 4842 size_t start_ofs = b->size;
e0c91c0c 4843 ofputil_put_phy_port(oh->version, pp, b);
6fd6ed71
PS
4844 if (b->size > UINT16_MAX) {
4845 b->size = start_ofs;
6b0f20ac 4846 }
e0c91c0c 4847 }
9e1fd49b
BP
4848}
4849\f
4850/* ofputil_port_status */
4851
4852/* Decodes the OpenFlow "port status" message in '*ops' into an abstract form
4853 * in '*ps'. Returns 0 if successful, otherwise an OFPERR_* value. */
4854enum ofperr
982697a4 4855ofputil_decode_port_status(const struct ofp_header *oh,
9e1fd49b
BP
4856 struct ofputil_port_status *ps)
4857{
0a2869d5 4858 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
982697a4 4859 ofpraw_pull_assert(&b);
982697a4 4860
0a2869d5 4861 const struct ofp_port_status *ops = ofpbuf_pull(&b, sizeof *ops);
9e1fd49b
BP
4862 if (ops->reason != OFPPR_ADD &&
4863 ops->reason != OFPPR_DELETE &&
4864 ops->reason != OFPPR_MODIFY) {
4865 return OFPERR_NXBRC_BAD_REASON;
4866 }
4867 ps->reason = ops->reason;
4868
0a2869d5 4869 int retval = ofputil_pull_phy_port(oh->version, &b, &ps->desc);
cb22974d 4870 ovs_assert(retval != EOF);
9e1fd49b
BP
4871 return retval;
4872}
4873
4874/* Converts the abstract form of a "port status" message in '*ps' into an
4875 * OpenFlow message suitable for 'protocol', and returns that encoded form in
4876 * a buffer owned by the caller. */
4877struct ofpbuf *
4878ofputil_encode_port_status(const struct ofputil_port_status *ps,
4879 enum ofputil_protocol protocol)
4880{
4881 struct ofp_port_status *ops;
4882 struct ofpbuf *b;
2e3fa633
SH
4883 enum ofp_version version;
4884 enum ofpraw raw;
982697a4
BP
4885
4886 version = ofputil_protocol_to_ofp_version(protocol);
2e3fa633
SH
4887 switch (version) {
4888 case OFP10_VERSION:
4889 raw = OFPRAW_OFPT10_PORT_STATUS;
4890 break;
4891
4892 case OFP11_VERSION:
4893 case OFP12_VERSION:
2e1ae200 4894 case OFP13_VERSION:
2e3fa633
SH
4895 raw = OFPRAW_OFPT11_PORT_STATUS;
4896 break;
4897
8c3cc785 4898 case OFP14_VERSION:
42dccab5 4899 case OFP15_VERSION:
b79d45a1 4900 case OFP16_VERSION:
8c3cc785
BP
4901 raw = OFPRAW_OFPT14_PORT_STATUS;
4902 break;
4903
2e3fa633 4904 default:
428b2edd 4905 OVS_NOT_REACHED();
2e3fa633
SH
4906 }
4907
4908 b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
982697a4 4909 ops = ofpbuf_put_zeros(b, sizeof *ops);
9e1fd49b 4910 ops->reason = ps->reason;
982697a4
BP
4911 ofputil_put_phy_port(version, &ps->desc, b);
4912 ofpmsg_update_length(b);
9e1fd49b
BP
4913 return b;
4914}
918f2b82 4915
9e1fd49b
BP
4916/* ofputil_port_mod */
4917
18cc69d9
BP
4918static enum ofperr
4919parse_port_mod_ethernet_property(struct ofpbuf *property,
4920 struct ofputil_port_mod *pm)
4921{
b611d3ac
BP
4922 ovs_be32 advertise;
4923 enum ofperr error;
18cc69d9 4924
b611d3ac
BP
4925 error = ofpprop_parse_be32(property, &advertise);
4926 if (!error) {
4927 pm->advertise = netdev_port_features_from_ofp11(advertise);
18cc69d9 4928 }
b611d3ac 4929 return error;
18cc69d9
BP
4930}
4931
9e1fd49b
BP
4932/* Decodes the OpenFlow "port mod" message in '*oh' into an abstract form in
4933 * '*pm'. Returns 0 if successful, otherwise an OFPERR_* value. */
4934enum ofperr
4935ofputil_decode_port_mod(const struct ofp_header *oh,
18cc69d9 4936 struct ofputil_port_mod *pm, bool loose)
9e1fd49b 4937{
0a2869d5
BP
4938 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
4939 enum ofpraw raw = ofpraw_pull_assert(&b);
982697a4 4940 if (raw == OFPRAW_OFPT10_PORT_MOD) {
6fd6ed71 4941 const struct ofp10_port_mod *opm = b.data;
9e1fd49b 4942
4e022ec0 4943 pm->port_no = u16_to_ofp(ntohs(opm->port_no));
74ff3298 4944 pm->hw_addr = opm->hw_addr;
9e1fd49b
BP
4945 pm->config = ntohl(opm->config) & OFPPC10_ALL;
4946 pm->mask = ntohl(opm->mask) & OFPPC10_ALL;
4947 pm->advertise = netdev_port_features_from_ofp10(opm->advertise);
982697a4 4948 } else if (raw == OFPRAW_OFPT11_PORT_MOD) {
6fd6ed71 4949 const struct ofp11_port_mod *opm = b.data;
9e1fd49b
BP
4950 enum ofperr error;
4951
9e1fd49b
BP
4952 error = ofputil_port_from_ofp11(opm->port_no, &pm->port_no);
4953 if (error) {
4954 return error;
4955 }
4956
74ff3298 4957 pm->hw_addr = opm->hw_addr;
9e1fd49b
BP
4958 pm->config = ntohl(opm->config) & OFPPC11_ALL;
4959 pm->mask = ntohl(opm->mask) & OFPPC11_ALL;
4960 pm->advertise = netdev_port_features_from_ofp11(opm->advertise);
18cc69d9
BP
4961 } else if (raw == OFPRAW_OFPT14_PORT_MOD) {
4962 const struct ofp14_port_mod *opm = ofpbuf_pull(&b, sizeof *opm);
4963 enum ofperr error;
4964
4965 memset(pm, 0, sizeof *pm);
4966
4967 error = ofputil_port_from_ofp11(opm->port_no, &pm->port_no);
4968 if (error) {
4969 return error;
4970 }
4971
74ff3298 4972 pm->hw_addr = opm->hw_addr;
18cc69d9
BP
4973 pm->config = ntohl(opm->config) & OFPPC11_ALL;
4974 pm->mask = ntohl(opm->mask) & OFPPC11_ALL;
4975
6fd6ed71 4976 while (b.size > 0) {
18cc69d9
BP
4977 struct ofpbuf property;
4978 enum ofperr error;
34a543e3 4979 uint64_t type;
18cc69d9 4980
c5562271 4981 error = ofpprop_pull(&b, &property, &type);
18cc69d9
BP
4982 if (error) {
4983 return error;
4984 }
4985
4986 switch (type) {
4987 case OFPPMPT14_ETHERNET:
4988 error = parse_port_mod_ethernet_property(&property, pm);
4989 break;
4990
4991 default:
34a543e3 4992 error = OFPPROP_UNKNOWN(loose, "port_mod", type);
18cc69d9
BP
4993 break;
4994 }
4995
4996 if (error) {
4997 return error;
4998 }
4999 }
9e1fd49b 5000 } else {
982697a4 5001 return OFPERR_OFPBRC_BAD_TYPE;
9e1fd49b
BP
5002 }
5003
5004 pm->config &= pm->mask;
5005 return 0;
5006}
5007
5008/* Converts the abstract form of a "port mod" message in '*pm' into an OpenFlow
5009 * message suitable for 'protocol', and returns that encoded form in a buffer
5010 * owned by the caller. */
5011struct ofpbuf *
5012ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
5013 enum ofputil_protocol protocol)
5014{
2e3fa633 5015 enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
9e1fd49b
BP
5016 struct ofpbuf *b;
5017
2e3fa633
SH
5018 switch (ofp_version) {
5019 case OFP10_VERSION: {
9e1fd49b
BP
5020 struct ofp10_port_mod *opm;
5021
982697a4
BP
5022 b = ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD, ofp_version, 0);
5023 opm = ofpbuf_put_zeros(b, sizeof *opm);
4e022ec0 5024 opm->port_no = htons(ofp_to_u16(pm->port_no));
74ff3298 5025 opm->hw_addr = pm->hw_addr;
9e1fd49b
BP
5026 opm->config = htonl(pm->config & OFPPC10_ALL);
5027 opm->mask = htonl(pm->mask & OFPPC10_ALL);
5028 opm->advertise = netdev_port_features_to_ofp10(pm->advertise);
2e3fa633
SH
5029 break;
5030 }
5031
5fe7c919 5032 case OFP11_VERSION:
2e1ae200
JR
5033 case OFP12_VERSION:
5034 case OFP13_VERSION: {
9e1fd49b
BP
5035 struct ofp11_port_mod *opm;
5036
982697a4
BP
5037 b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0);
5038 opm = ofpbuf_put_zeros(b, sizeof *opm);
026a5179 5039 opm->port_no = ofputil_port_to_ofp11(pm->port_no);
74ff3298 5040 opm->hw_addr = pm->hw_addr;
9e1fd49b
BP
5041 opm->config = htonl(pm->config & OFPPC11_ALL);
5042 opm->mask = htonl(pm->mask & OFPPC11_ALL);
5043 opm->advertise = netdev_port_features_to_ofp11(pm->advertise);
2e3fa633
SH
5044 break;
5045 }
42dccab5 5046 case OFP14_VERSION:
b79d45a1
BP
5047 case OFP15_VERSION:
5048 case OFP16_VERSION: {
18cc69d9
BP
5049 struct ofp14_port_mod *opm;
5050
b611d3ac 5051 b = ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD, ofp_version, 0);
18cc69d9
BP
5052 opm = ofpbuf_put_zeros(b, sizeof *opm);
5053 opm->port_no = ofputil_port_to_ofp11(pm->port_no);
74ff3298 5054 opm->hw_addr = pm->hw_addr;
18cc69d9
BP
5055 opm->config = htonl(pm->config & OFPPC11_ALL);
5056 opm->mask = htonl(pm->mask & OFPPC11_ALL);
5057
5058 if (pm->advertise) {
b611d3ac
BP
5059 ofpprop_put_be32(b, OFPPMPT14_ETHERNET,
5060 netdev_port_features_to_ofp11(pm->advertise));
18cc69d9 5061 }
c37c0382 5062 break;
18cc69d9 5063 }
918f2b82 5064 default:
428b2edd 5065 OVS_NOT_REACHED();
918f2b82
AZ
5066 }
5067
5068 return b;
5069}
72b25867
BP
5070\f
5071/* Table features. */
918f2b82 5072
5deff5aa 5073static enum ofperr
9a4eddbb 5074pull_table_feature_property(struct ofpbuf *msg, struct ofpbuf *payload,
34a543e3 5075 uint64_t *typep)
5deff5aa 5076{
9a4eddbb 5077 enum ofperr error;
5deff5aa 5078
c5562271 5079 error = ofpprop_pull(msg, payload, typep);
9a4eddbb 5080 if (payload && !error) {
b611d3ac 5081 ofpbuf_pull(payload, (char *)payload->msg - (char *)payload->header);
5deff5aa 5082 }
9a4eddbb 5083 return error;
5deff5aa
AW
5084}
5085
5086static enum ofperr
08d1e234
BP
5087parse_action_bitmap(struct ofpbuf *payload, enum ofp_version ofp_version,
5088 uint64_t *ofpacts)
5deff5aa 5089{
08d1e234 5090 uint32_t types = 0;
5deff5aa 5091
6fd6ed71 5092 while (payload->size > 0) {
08d1e234 5093 enum ofperr error;
34a543e3 5094 uint64_t type;
08d1e234 5095
34a543e3 5096 error = ofpprop_pull__(payload, NULL, 1, 0x10000, &type);
5deff5aa
AW
5097 if (error) {
5098 return error;
5099 }
08d1e234
BP
5100 if (type < CHAR_BIT * sizeof types) {
5101 types |= 1u << type;
5deff5aa
AW
5102 }
5103 }
08d1e234
BP
5104
5105 *ofpacts = ofpact_bitmap_from_openflow(htonl(types), ofp_version);
5deff5aa
AW
5106 return 0;
5107}
5108
5109static enum ofperr
5110parse_instruction_ids(struct ofpbuf *payload, bool loose, uint32_t *insts)
5111{
5112 *insts = 0;
6fd6ed71 5113 while (payload->size > 0) {
5deff5aa
AW
5114 enum ovs_instruction_type inst;
5115 enum ofperr error;
34a543e3 5116 uint64_t ofpit;
5deff5aa 5117
72b25867
BP
5118 /* OF1.3 and OF1.4 aren't clear about padding in the instruction IDs.
5119 * It seems clear that they aren't padded to 8 bytes, though, because
5120 * both standards say that "non-experimenter instructions are 4 bytes"
5121 * and do not mention any padding before the first instruction ID.
5122 * (There wouldn't be any point in padding to 8 bytes if the IDs were
5123 * aligned on an odd 4-byte boundary.)
5124 *
5125 * Anyway, we just assume they're all glommed together on byte
5126 * boundaries. */
34a543e3 5127 error = ofpprop_pull__(payload, NULL, 1, 0x10000, &ofpit);
5deff5aa
AW
5128 if (error) {
5129 return error;
5130 }
5131
5132 error = ovs_instruction_type_from_inst_type(&inst, ofpit);
5133 if (!error) {
5134 *insts |= 1u << inst;
5135 } else if (!loose) {
5136 return error;
5137 }
5138 }
5139 return 0;
5140}
5141
5142static enum ofperr
5143parse_table_features_next_table(struct ofpbuf *payload,
5144 unsigned long int *next_tables)
5145{
5146 size_t i;
5147
5148 memset(next_tables, 0, bitmap_n_bytes(255));
6fd6ed71
PS
5149 for (i = 0; i < payload->size; i++) {
5150 uint8_t id = ((const uint8_t *) payload->data)[i];
5deff5aa 5151 if (id >= 255) {
9a4eddbb 5152 return OFPERR_OFPBPC_BAD_VALUE;
5deff5aa
AW
5153 }
5154 bitmap_set1(next_tables, id);
5155 }
5156 return 0;
5157}
5158
5deff5aa
AW
5159static enum ofperr
5160parse_oxms(struct ofpbuf *payload, bool loose,
abadfcb0 5161 struct mf_bitmap *exactp, struct mf_bitmap *maskedp)
5deff5aa 5162{
abadfcb0
BP
5163 struct mf_bitmap exact = MF_BITMAP_INITIALIZER;
5164 struct mf_bitmap masked = MF_BITMAP_INITIALIZER;
5deff5aa 5165
6fd6ed71 5166 while (payload->size > 0) {
5deff5aa
AW
5167 const struct mf_field *field;
5168 enum ofperr error;
5169 bool hasmask;
5170
178742f9 5171 error = nx_pull_header(payload, &field, &hasmask);
5deff5aa 5172 if (!error) {
abadfcb0 5173 bitmap_set1(hasmask ? masked.bm : exact.bm, field->id);
5deff5aa
AW
5174 } else if (error != OFPERR_OFPBMC_BAD_FIELD || !loose) {
5175 return error;
5176 }
5177 }
5178 if (exactp) {
5179 *exactp = exact;
abadfcb0 5180 } else if (!bitmap_is_all_zeros(exact.bm, MFF_N_IDS)) {
5deff5aa
AW
5181 return OFPERR_OFPBMC_BAD_MASK;
5182 }
5183 if (maskedp) {
5184 *maskedp = masked;
abadfcb0 5185 } else if (!bitmap_is_all_zeros(masked.bm, MFF_N_IDS)) {
5deff5aa
AW
5186 return OFPERR_OFPBMC_BAD_MASK;
5187 }
5188 return 0;
5189}
5190
5191/* Converts an OFPMP_TABLE_FEATURES request or reply in 'msg' into an abstract
5192 * ofputil_table_features in 'tf'.
5193 *
5194 * If 'loose' is true, this function ignores properties and values that it does
5195 * not understand, as a controller would want to do when interpreting
5196 * capabilities provided by a switch. If 'loose' is false, this function
5197 * treats unknown properties and values as an error, as a switch would want to
5198 * do when interpreting a configuration request made by a controller.
5199 *
5200 * A single OpenFlow message can specify features for multiple tables. Calling
5201 * this function multiple times for a single 'msg' iterates through the tables
5202 * in the message. The caller must initially leave 'msg''s layer pointers null
5203 * and not modify them between calls.
5204 *
5205 * Returns 0 if successful, EOF if no tables were left in this 'msg', otherwise
5206 * a positive "enum ofperr" value. */
5207int
5208ofputil_decode_table_features(struct ofpbuf *msg,
5209 struct ofputil_table_features *tf, bool loose)
5210{
3c1bb396
BP
5211 memset(tf, 0, sizeof *tf);
5212
6fd6ed71 5213 if (!msg->header) {
5deff5aa
AW
5214 ofpraw_pull_assert(msg);
5215 }
5216
6fd6ed71 5217 if (!msg->size) {
5deff5aa
AW
5218 return EOF;
5219 }
5220
0a2869d5
BP
5221 const struct ofp_header *oh = msg->header;
5222 struct ofp13_table_features *otf = msg->data;
6fd6ed71 5223 if (msg->size < sizeof *otf) {
9a4eddbb 5224 return OFPERR_OFPBPC_BAD_LEN;
5deff5aa
AW
5225 }
5226
0a2869d5 5227 unsigned int len = ntohs(otf->length);
6fd6ed71 5228 if (len < sizeof *otf || len % 8 || len > msg->size) {
9a4eddbb 5229 return OFPERR_OFPBPC_BAD_LEN;
5deff5aa 5230 }
5deff5aa
AW
5231
5232 tf->table_id = otf->table_id;
5233 if (tf->table_id == OFPTT_ALL) {
5234 return OFPERR_OFPTFFC_BAD_TABLE;
5235 }
5236
5237 ovs_strlcpy(tf->name, otf->name, OFP_MAX_TABLE_NAME_LEN);
5238 tf->metadata_match = otf->metadata_match;
5239 tf->metadata_write = otf->metadata_write;
82c22d34
BP
5240 tf->miss_config = OFPUTIL_TABLE_MISS_DEFAULT;
5241 if (oh->version >= OFP14_VERSION) {
5242 uint32_t caps = ntohl(otf->capabilities);
5243 tf->supports_eviction = (caps & OFPTC14_EVICTION) != 0;
5244 tf->supports_vacancy_events = (caps & OFPTC14_VACANCY_EVENTS) != 0;
5245 } else {
5246 tf->supports_eviction = -1;
5247 tf->supports_vacancy_events = -1;
5248 }
5deff5aa
AW
5249 tf->max_entries = ntohl(otf->max_entries);
5250
0a2869d5
BP
5251 struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
5252 len);
5253 ofpbuf_pull(&properties, sizeof *otf);
6fd6ed71 5254 while (properties.size > 0) {
5deff5aa
AW
5255 struct ofpbuf payload;
5256 enum ofperr error;
34a543e3 5257 uint64_t type;
5deff5aa 5258
ae665de5 5259 error = pull_table_feature_property(&properties, &payload, &type);
5deff5aa
AW
5260 if (error) {
5261 return error;
5262 }
5263
5264 switch ((enum ofp13_table_feature_prop_type) type) {
5265 case OFPTFPT13_INSTRUCTIONS:
5266 error = parse_instruction_ids(&payload, loose,
5267 &tf->nonmiss.instructions);
5268 break;
5269 case OFPTFPT13_INSTRUCTIONS_MISS:
5270 error = parse_instruction_ids(&payload, loose,
5271 &tf->miss.instructions);
5272 break;
5273
5274 case OFPTFPT13_NEXT_TABLES:
5275 error = parse_table_features_next_table(&payload,
5276 tf->nonmiss.next);
5277 break;
5278 case OFPTFPT13_NEXT_TABLES_MISS:
5279 error = parse_table_features_next_table(&payload, tf->miss.next);
5280 break;
5281
5282 case OFPTFPT13_WRITE_ACTIONS:
08d1e234
BP
5283 error = parse_action_bitmap(&payload, oh->version,
5284 &tf->nonmiss.write.ofpacts);
5deff5aa
AW
5285 break;
5286 case OFPTFPT13_WRITE_ACTIONS_MISS:
08d1e234
BP
5287 error = parse_action_bitmap(&payload, oh->version,
5288 &tf->miss.write.ofpacts);
5deff5aa
AW
5289 break;
5290
5291 case OFPTFPT13_APPLY_ACTIONS:
08d1e234
BP
5292 error = parse_action_bitmap(&payload, oh->version,
5293 &tf->nonmiss.apply.ofpacts);
5deff5aa
AW
5294 break;
5295 case OFPTFPT13_APPLY_ACTIONS_MISS:
08d1e234
BP
5296 error = parse_action_bitmap(&payload, oh->version,
5297 &tf->miss.apply.ofpacts);
5deff5aa
AW
5298 break;
5299
5300 case OFPTFPT13_MATCH:
5301 error = parse_oxms(&payload, loose, &tf->match, &tf->mask);
5302 break;
5303 case OFPTFPT13_WILDCARDS:
5304 error = parse_oxms(&payload, loose, &tf->wildcard, NULL);
5305 break;
5306
5307 case OFPTFPT13_WRITE_SETFIELD:
5308 error = parse_oxms(&payload, loose,
5309 &tf->nonmiss.write.set_fields, NULL);
5310 break;
5311 case OFPTFPT13_WRITE_SETFIELD_MISS:
5312 error = parse_oxms(&payload, loose,
5313 &tf->miss.write.set_fields, NULL);
5314 break;
5315 case OFPTFPT13_APPLY_SETFIELD:
5316 error = parse_oxms(&payload, loose,
5317 &tf->nonmiss.apply.set_fields, NULL);
5318 break;
5319 case OFPTFPT13_APPLY_SETFIELD_MISS:
5320 error = parse_oxms(&payload, loose,
5321 &tf->miss.apply.set_fields, NULL);
5322 break;
5323
5324 case OFPTFPT13_EXPERIMENTER:
5325 case OFPTFPT13_EXPERIMENTER_MISS:
9a4eddbb 5326 default:
34a543e3 5327 error = OFPPROP_UNKNOWN(loose, "table features", type);
5deff5aa
AW
5328 break;
5329 }
5330 if (error) {
5331 return error;
5332 }
5333 }
5334
5335 /* Fix inconsistencies:
5336 *
e7227821
BP
5337 * - Turn on 'match' bits that are set in 'mask', because maskable
5338 * fields are matchable.
5deff5aa
AW
5339 *
5340 * - Turn on 'wildcard' bits that are set in 'mask', because a field
e7227821
BP
5341 * that is arbitrarily maskable can be wildcarded entirely.
5342 *
5343 * - Turn off 'wildcard' bits that are not in 'match', because a field
5344 * must be matchable for it to be meaningfully wildcarded. */
5345 bitmap_or(tf->match.bm, tf->mask.bm, MFF_N_IDS);
abadfcb0 5346 bitmap_or(tf->wildcard.bm, tf->mask.bm, MFF_N_IDS);
e7227821 5347 bitmap_and(tf->wildcard.bm, tf->match.bm, MFF_N_IDS);
5deff5aa
AW
5348
5349 return 0;
5350}
5351
5352/* Encodes and returns a request to obtain the table features of a switch.
5353 * The message is encoded for OpenFlow version 'ofp_version'. */
5354struct ofpbuf *
5355ofputil_encode_table_features_request(enum ofp_version ofp_version)
5356{
5357 struct ofpbuf *request = NULL;
5358
5359 switch (ofp_version) {
5360 case OFP10_VERSION:
5361 case OFP11_VERSION:
5362 case OFP12_VERSION:
5363 ovs_fatal(0, "dump-table-features needs OpenFlow 1.3 or later "
5364 "(\'-O OpenFlow13\')");
5365 case OFP13_VERSION:
5366 case OFP14_VERSION:
42dccab5 5367 case OFP15_VERSION:
b79d45a1 5368 case OFP16_VERSION:
5deff5aa
AW
5369 request = ofpraw_alloc(OFPRAW_OFPST13_TABLE_FEATURES_REQUEST,
5370 ofp_version, 0);
5371 break;
5372 default:
5373 OVS_NOT_REACHED();
5374 }
5375
5376 return request;
5377}
5378
3c4e10fb
BP
5379static void
5380put_fields_property(struct ofpbuf *reply,
5381 const struct mf_bitmap *fields,
5382 const struct mf_bitmap *masks,
5383 enum ofp13_table_feature_prop_type property,
5384 enum ofp_version version)
5385{
5386 size_t start_ofs;
5387 int field;
5388
c5562271 5389 start_ofs = ofpprop_start(reply, property);
3c4e10fb 5390 BITMAP_FOR_EACH_1 (field, MFF_N_IDS, fields->bm) {
178742f9
BP
5391 nx_put_header(reply, field, version,
5392 masks && bitmap_is_set(masks->bm, field));
3c4e10fb 5393 }
c5562271 5394 ofpprop_end(reply, start_ofs);
3c4e10fb
BP
5395}
5396
5397static void
5398put_table_action_features(struct ofpbuf *reply,
5399 const struct ofputil_table_action_features *taf,
5400 enum ofp13_table_feature_prop_type actions_type,
5401 enum ofp13_table_feature_prop_type set_fields_type,
5402 int miss_offset, enum ofp_version version)
5403{
c5562271
BP
5404 ofpprop_put_bitmap(reply, actions_type + miss_offset,
5405 ntohl(ofpact_bitmap_to_openflow(taf->ofpacts,
5406 version)));
3c4e10fb
BP
5407 put_fields_property(reply, &taf->set_fields, NULL,
5408 set_fields_type + miss_offset, version);
5409}
5410
5411static void
5412put_table_instruction_features(
5413 struct ofpbuf *reply, const struct ofputil_table_instruction_features *tif,
5414 int miss_offset, enum ofp_version version)
5415{
5416 size_t start_ofs;
5417 uint8_t table_id;
5418
c5562271
BP
5419 ofpprop_put_bitmap(reply, OFPTFPT13_INSTRUCTIONS + miss_offset,
5420 ntohl(ovsinst_bitmap_to_openflow(tif->instructions,
5421 version)));
3c4e10fb 5422
c5562271 5423 start_ofs = ofpprop_start(reply, OFPTFPT13_NEXT_TABLES + miss_offset);
3c4e10fb
BP
5424 BITMAP_FOR_EACH_1 (table_id, 255, tif->next) {
5425 ofpbuf_put(reply, &table_id, 1);
5426 }
c5562271 5427 ofpprop_end(reply, start_ofs);
3c4e10fb
BP
5428
5429 put_table_action_features(reply, &tif->write,
5430 OFPTFPT13_WRITE_ACTIONS,
5431 OFPTFPT13_WRITE_SETFIELD, miss_offset, version);
5432 put_table_action_features(reply, &tif->apply,
5433 OFPTFPT13_APPLY_ACTIONS,
5434 OFPTFPT13_APPLY_SETFIELD, miss_offset, version);
5435}
5436
5437void
5438ofputil_append_table_features_reply(const struct ofputil_table_features *tf,
ca6ba700 5439 struct ovs_list *replies)
3c4e10fb 5440{
417e7e66 5441 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
3c4e10fb 5442 enum ofp_version version = ofpmp_version(replies);
6fd6ed71 5443 size_t start_ofs = reply->size;
3c4e10fb
BP
5444 struct ofp13_table_features *otf;
5445
5446 otf = ofpbuf_put_zeros(reply, sizeof *otf);
5447 otf->table_id = tf->table_id;
5448 ovs_strlcpy(otf->name, tf->name, sizeof otf->name);
5449 otf->metadata_match = tf->metadata_match;
5450 otf->metadata_write = tf->metadata_write;
82c22d34
BP
5451 if (version >= OFP14_VERSION) {
5452 if (tf->supports_eviction) {
5453 otf->capabilities |= htonl(OFPTC14_EVICTION);
5454 }
5455 if (tf->supports_vacancy_events) {
5456 otf->capabilities |= htonl(OFPTC14_VACANCY_EVENTS);
5457 }
5458 }
3c4e10fb
BP
5459 otf->max_entries = htonl(tf->max_entries);
5460
5461 put_table_instruction_features(reply, &tf->nonmiss, 0, version);
5462 put_table_instruction_features(reply, &tf->miss, 1, version);
5463
5464 put_fields_property(reply, &tf->match, &tf->mask,
5465 OFPTFPT13_MATCH, version);
5466 put_fields_property(reply, &tf->wildcard, NULL,
5467 OFPTFPT13_WILDCARDS, version);
5468
5469 otf = ofpbuf_at_assert(reply, start_ofs, sizeof *otf);
6fd6ed71 5470 otf->length = htons(reply->size - start_ofs);
3c4e10fb
BP
5471 ofpmp_postappend(replies, start_ofs);
5472}
5473
bab86012
SJ
5474static enum ofperr
5475parse_table_desc_vacancy_property(struct ofpbuf *property,
5476 struct ofputil_table_desc *td)
5477{
5478 struct ofp14_table_mod_prop_vacancy *otv = property->data;
5479
5480 if (property->size != sizeof *otv) {
5481 return OFPERR_OFPBPC_BAD_LEN;
5482 }
5483
5484 td->table_vacancy.vacancy_down = otv->vacancy_down;
5485 td->table_vacancy.vacancy_up = otv->vacancy_up;
5486 td->table_vacancy.vacancy = otv->vacancy;
5487 return 0;
5488}
5489
03c72922
BP
5490/* Decodes the next OpenFlow "table desc" message (of possibly several) from
5491 * 'msg' into an abstract form in '*td'. Returns 0 if successful, EOF if the
5492 * last "table desc" in 'msg' was already decoded, otherwise an OFPERR_*
5493 * value. */
5494int
5495ofputil_decode_table_desc(struct ofpbuf *msg,
5496 struct ofputil_table_desc *td,
5497 enum ofp_version version)
5498{
03c72922
BP
5499 memset(td, 0, sizeof *td);
5500
5501 if (!msg->header) {
5502 ofpraw_pull_assert(msg);
5503 }
5504
5505 if (!msg->size) {
5506 return EOF;
5507 }
5508
0a2869d5 5509 struct ofp14_table_desc *otd = ofpbuf_try_pull(msg, sizeof *otd);
03c72922
BP
5510 if (!otd) {
5511 VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply has %"PRIu32" "
5512 "leftover bytes at end", msg->size);
5513 return OFPERR_OFPBRC_BAD_LEN;
5514 }
5515
5516 td->table_id = otd->table_id;
0a2869d5 5517 size_t length = ntohs(otd->length);
03c72922
BP
5518 if (length < sizeof *otd || length - sizeof *otd > msg->size) {
5519 VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply claims invalid "
5520 "length %"PRIuSIZE, length);
5521 return OFPERR_OFPBRC_BAD_LEN;
5522 }
5523 length -= sizeof *otd;
03c72922
BP
5524
5525 td->eviction = ofputil_decode_table_eviction(otd->config, version);
bab86012 5526 td->vacancy = ofputil_decode_table_vacancy(otd->config, version);
03c72922
BP
5527 td->eviction_flags = UINT32_MAX;
5528
0a2869d5
BP
5529 struct ofpbuf properties = ofpbuf_const_initializer(
5530 ofpbuf_pull(msg, length), length);
03c72922
BP
5531 while (properties.size > 0) {
5532 struct ofpbuf payload;
5533 enum ofperr error;
34a543e3 5534 uint64_t type;
03c72922 5535
c5562271 5536 error = ofpprop_pull(&properties, &payload, &type);
03c72922
BP
5537 if (error) {
5538 return error;
5539 }
5540
5541 switch (type) {
5542 case OFPTMPT14_EVICTION:
b611d3ac 5543 error = ofpprop_parse_u32(&payload, &td->eviction_flags);
03c72922
BP
5544 break;
5545
bab86012
SJ
5546 case OFPTMPT14_VACANCY:
5547 error = parse_table_desc_vacancy_property(&payload, td);
5548 break;
5549
03c72922 5550 default:
34a543e3 5551 error = OFPPROP_UNKNOWN(true, "table_desc", type);
03c72922
BP
5552 break;
5553 }
5554
5555 if (error) {
5556 return error;
5557 }
5558 }
5559
5560 return 0;
5561}
5562
5563/* Encodes and returns a request to obtain description of tables of a switch.
5564 * The message is encoded for OpenFlow version 'ofp_version'. */
5565struct ofpbuf *
5566ofputil_encode_table_desc_request(enum ofp_version ofp_version)
5567{
5568 struct ofpbuf *request = NULL;
5569
5570 if (ofp_version >= OFP14_VERSION) {
5571 request = ofpraw_alloc(OFPRAW_OFPST14_TABLE_DESC_REQUEST,
5572 ofp_version, 0);
5573 } else {
5574 ovs_fatal(0, "dump-table-desc needs OpenFlow 1.4 or later "
5575 "(\'-O OpenFlow14\')");
5576 }
5577
5578 return request;
5579}
5580
5581/* Function to append Table desc information in a reply list. */
5582void
5583ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
5584 struct ovs_list *replies,
5585 enum ofp_version version)
5586{
417e7e66 5587 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
03c72922
BP
5588 size_t start_otd;
5589 struct ofp14_table_desc *otd;
5590
5591 start_otd = reply->size;
5592 ofpbuf_put_zeros(reply, sizeof *otd);
5593 if (td->eviction_flags != UINT32_MAX) {
b611d3ac 5594 ofpprop_put_u32(reply, OFPTMPT14_EVICTION, td->eviction_flags);
03c72922 5595 }
bab86012
SJ
5596 if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
5597 struct ofp14_table_mod_prop_vacancy *otv;
5598
303721ee 5599 otv = ofpprop_put_zeros(reply, OFPTMPT14_VACANCY, sizeof *otv);
bab86012
SJ
5600 otv->vacancy_down = td->table_vacancy.vacancy_down;
5601 otv->vacancy_up = td->table_vacancy.vacancy_up;
5602 otv->vacancy = td->table_vacancy.vacancy;
5603 }
03c72922
BP
5604
5605 otd = ofpbuf_at_assert(reply, start_otd, sizeof *otd);
5606 otd->length = htons(reply->size - start_otd);
5607 otd->table_id = td->table_id;
5608 otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
de7d3c07
SJ
5609 td->eviction, td->vacancy,
5610 version);
03c72922
BP
5611 ofpmp_postappend(replies, start_otd);
5612}
5613
de7d3c07
SJ
5614/* This function parses Vacancy property, and decodes the
5615 * ofp14_table_mod_prop_vacancy in ofputil_table_mod.
5616 * Returns OFPERR_OFPBPC_BAD_VALUE error code when vacancy_down is
5617 * greater than vacancy_up and also when current vacancy has non-zero
5618 * value. Returns 0 on success. */
5619static enum ofperr
5620parse_table_mod_vacancy_property(struct ofpbuf *property,
5621 struct ofputil_table_mod *tm)
5622{
5623 struct ofp14_table_mod_prop_vacancy *otv = property->data;
5624
5625 if (property->size != sizeof *otv) {
5626 return OFPERR_OFPBPC_BAD_LEN;
5627 }
5628 tm->table_vacancy.vacancy_down = otv->vacancy_down;
5629 tm->table_vacancy.vacancy_up = otv->vacancy_up;
5630 if (tm->table_vacancy.vacancy_down > tm->table_vacancy.vacancy_up) {
c5562271
BP
5631 OFPPROP_LOG(&bad_ofmsg_rl, false,
5632 "Value of vacancy_down is greater than vacancy_up");
de7d3c07
SJ
5633 return OFPERR_OFPBPC_BAD_VALUE;
5634 }
5635 if (tm->table_vacancy.vacancy_down > 100 ||
5636 tm->table_vacancy.vacancy_up > 100) {
c5562271
BP
5637 OFPPROP_LOG(&bad_ofmsg_rl, false, "Vacancy threshold percentage "
5638 "should not be greater than 100");
de7d3c07
SJ
5639 return OFPERR_OFPBPC_BAD_VALUE;
5640 }
5641 tm->table_vacancy.vacancy = otv->vacancy;
5642 if (tm->table_vacancy.vacancy) {
c5562271
BP
5643 OFPPROP_LOG(&bad_ofmsg_rl, false,
5644 "Vacancy value should be zero for table-mod messages");
de7d3c07
SJ
5645 return OFPERR_OFPBPC_BAD_VALUE;
5646 }
5647 return 0;
5648}
5649
5650/* Given 'config', taken from an OpenFlow 'version' message that specifies
5651 * table configuration (a table mod, table stats, or table features message),
5652 * returns the table vacancy configuration that it specifies.
5653 *
5654 * Only OpenFlow 1.4 and later specify table vacancy configuration this way,
5655 * so for other 'version' this function always returns
5656 * OFPUTIL_TABLE_VACANCY_DEFAULT. */
5657static enum ofputil_table_vacancy
5658ofputil_decode_table_vacancy(ovs_be32 config, enum ofp_version version)
5659{
5660 return (version < OFP14_VERSION ? OFPUTIL_TABLE_VACANCY_DEFAULT
5661 : config & htonl(OFPTC14_VACANCY_EVENTS) ? OFPUTIL_TABLE_VACANCY_ON
5662 : OFPUTIL_TABLE_VACANCY_OFF);
5663}
5664
3c1bb396
BP
5665/* Given 'config', taken from an OpenFlow 'version' message that specifies
5666 * table configuration (a table mod, table stats, or table features message),
82c22d34
BP
5667 * returns the table eviction configuration that it specifies.
5668 *
5669 * Only OpenFlow 1.4 and later specify table eviction configuration this way,
5670 * so for other 'version' values this function always returns
5671 * OFPUTIL_TABLE_EVICTION_DEFAULT. */
5672static enum ofputil_table_eviction
5673ofputil_decode_table_eviction(ovs_be32 config, enum ofp_version version)
5674{
5675 return (version < OFP14_VERSION ? OFPUTIL_TABLE_EVICTION_DEFAULT
5676 : config & htonl(OFPTC14_EVICTION) ? OFPUTIL_TABLE_EVICTION_ON
5677 : OFPUTIL_TABLE_EVICTION_OFF);
5678}
5679
5680/* Returns a bitmap of OFPTC* values suitable for 'config' fields in various
5681 * OpenFlow messages of the given 'version', based on the provided 'miss' and
5682 * 'eviction' values. */
5683static ovs_be32
5684ofputil_encode_table_config(enum ofputil_table_miss miss,
5685 enum ofputil_table_eviction eviction,
de7d3c07 5686 enum ofputil_table_vacancy vacancy,
82c22d34
BP
5687 enum ofp_version version)
5688{
de7d3c07 5689 uint32_t config = 0;
82c22d34
BP
5690 /* See the section "OFPTC_* Table Configuration" in DESIGN.md for more
5691 * information on the crazy evolution of this field. */
5692 switch (version) {
5693 case OFP10_VERSION:
5694 /* OpenFlow 1.0 didn't have such a field, any value ought to do. */
5695 return htonl(0);
5696
5697 case OFP11_VERSION:
5698 case OFP12_VERSION:
5699 /* OpenFlow 1.1 and 1.2 define only OFPTC11_TABLE_MISS_*. */
5700 switch (miss) {
5701 case OFPUTIL_TABLE_MISS_DEFAULT:
5702 /* Really this shouldn't be used for encoding (the caller should
5703 * provide a specific value) but I can't imagine that defaulting to
5704 * the fall-through case here will hurt. */
5705 case OFPUTIL_TABLE_MISS_CONTROLLER:
5706 default:
5707 return htonl(OFPTC11_TABLE_MISS_CONTROLLER);
5708 case OFPUTIL_TABLE_MISS_CONTINUE:
5709 return htonl(OFPTC11_TABLE_MISS_CONTINUE);
5710 case OFPUTIL_TABLE_MISS_DROP:
5711 return htonl(OFPTC11_TABLE_MISS_DROP);
5712 }
5713 OVS_NOT_REACHED();
5714
5715 case OFP13_VERSION:
5716 /* OpenFlow 1.3 removed OFPTC11_TABLE_MISS_* and didn't define any new
5717 * flags, so this is correct. */
5718 return htonl(0);
5719
5720 case OFP14_VERSION:
5721 case OFP15_VERSION:
b79d45a1 5722 case OFP16_VERSION:
de7d3c07
SJ
5723 /* OpenFlow 1.4 introduced OFPTC14_EVICTION and
5724 * OFPTC14_VACANCY_EVENTS. */
5725 if (eviction == OFPUTIL_TABLE_EVICTION_ON) {
5726 config |= OFPTC14_EVICTION;
5727 }
5728 if (vacancy == OFPUTIL_TABLE_VACANCY_ON) {
5729 config |= OFPTC14_VACANCY_EVENTS;
5730 }
5731 return htonl(config);
82c22d34
BP
5732 }
5733
5734 OVS_NOT_REACHED();
5735}
5736
5737/* Given 'config', taken from an OpenFlow 'version' message that specifies
5738 * table configuration (a table mod, table stats, or table features message),
5739 * returns the table miss configuration that it specifies.
5740 *
5741 * Only OpenFlow 1.1 and 1.2 specify table miss configurations this way, so for
5742 * other 'version' values this function always returns
5743 * OFPUTIL_TABLE_MISS_DEFAULT. */
3c1bb396 5744static enum ofputil_table_miss
82c22d34 5745ofputil_decode_table_miss(ovs_be32 config_, enum ofp_version version)
3c1bb396
BP
5746{
5747 uint32_t config = ntohl(config_);
5748
82c22d34 5749 if (version == OFP11_VERSION || version == OFP12_VERSION) {
3c1bb396
BP
5750 switch (config & OFPTC11_TABLE_MISS_MASK) {
5751 case OFPTC11_TABLE_MISS_CONTROLLER:
5752 return OFPUTIL_TABLE_MISS_CONTROLLER;
5753
5754 case OFPTC11_TABLE_MISS_CONTINUE:
5755 return OFPUTIL_TABLE_MISS_CONTINUE;
5756
5757 case OFPTC11_TABLE_MISS_DROP:
5758 return OFPUTIL_TABLE_MISS_DROP;
5759
5760 default:
5761 VLOG_WARN_RL(&bad_ofmsg_rl, "bad table miss config %d", config);
5762 return OFPUTIL_TABLE_MISS_CONTROLLER;
5763 }
5764 } else {
5765 return OFPUTIL_TABLE_MISS_DEFAULT;
5766 }
5767}
5768
918f2b82
AZ
5769/* Decodes the OpenFlow "table mod" message in '*oh' into an abstract form in
5770 * '*pm'. Returns 0 if successful, otherwise an OFPERR_* value. */
5771enum ofperr
5772ofputil_decode_table_mod(const struct ofp_header *oh,
5773 struct ofputil_table_mod *pm)
5774{
82c22d34
BP
5775 memset(pm, 0, sizeof *pm);
5776 pm->miss = OFPUTIL_TABLE_MISS_DEFAULT;
5777 pm->eviction = OFPUTIL_TABLE_EVICTION_DEFAULT;
5778 pm->eviction_flags = UINT32_MAX;
de7d3c07 5779 pm->vacancy = OFPUTIL_TABLE_VACANCY_DEFAULT;
918f2b82 5780
0a2869d5
BP
5781 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
5782 enum ofpraw raw = ofpraw_pull_assert(&b);
918f2b82 5783 if (raw == OFPRAW_OFPT11_TABLE_MOD) {
6fd6ed71 5784 const struct ofp11_table_mod *otm = b.data;
918f2b82
AZ
5785
5786 pm->table_id = otm->table_id;
82c22d34 5787 pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
37ab26e8
BP
5788 } else if (raw == OFPRAW_OFPT14_TABLE_MOD) {
5789 const struct ofp14_table_mod *otm = ofpbuf_pull(&b, sizeof *otm);
5790
5791 pm->table_id = otm->table_id;
82c22d34
BP
5792 pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
5793 pm->eviction = ofputil_decode_table_eviction(otm->config, oh->version);
de7d3c07 5794 pm->vacancy = ofputil_decode_table_vacancy(otm->config, oh->version);
82c22d34
BP
5795 while (b.size > 0) {
5796 struct ofpbuf property;
5797 enum ofperr error;
34a543e3 5798 uint64_t type;
82c22d34 5799
c5562271 5800 error = ofpprop_pull(&b, &property, &type);
82c22d34
BP
5801 if (error) {
5802 return error;
5803 }
5804
5805 switch (type) {
5806 case OFPTMPT14_EVICTION:
b611d3ac 5807 error = ofpprop_parse_u32(&property, &pm->eviction);
82c22d34
BP
5808 break;
5809
de7d3c07
SJ
5810 case OFPTMPT14_VACANCY:
5811 error = parse_table_mod_vacancy_property(&property, pm);
5812 break;
5813
82c22d34
BP
5814 default:
5815 error = OFPERR_OFPBRC_BAD_TYPE;
5816 break;
5817 }
5818
5819 if (error) {
5820 return error;
5821 }
5822 }
918f2b82
AZ
5823 } else {
5824 return OFPERR_OFPBRC_BAD_TYPE;
5825 }
5826
5827 return 0;
5828}
5829
82c22d34
BP
5830/* Converts the abstract form of a "table mod" message in '*tm' into an
5831 * OpenFlow message suitable for 'protocol', and returns that encoded form in a
5832 * buffer owned by the caller. */
918f2b82 5833struct ofpbuf *
82c22d34 5834ofputil_encode_table_mod(const struct ofputil_table_mod *tm,
918f2b82
AZ
5835 enum ofputil_protocol protocol)
5836{
5837 enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
5838 struct ofpbuf *b;
5839
5840 switch (ofp_version) {
5841 case OFP10_VERSION: {
5842 ovs_fatal(0, "table mod needs OpenFlow 1.1 or later "
5843 "(\'-O OpenFlow11\')");
5844 break;
5845 }
5846 case OFP11_VERSION:
5847 case OFP12_VERSION:
5848 case OFP13_VERSION: {
5849 struct ofp11_table_mod *otm;
2e3fa633 5850
918f2b82
AZ
5851 b = ofpraw_alloc(OFPRAW_OFPT11_TABLE_MOD, ofp_version, 0);
5852 otm = ofpbuf_put_zeros(b, sizeof *otm);
82c22d34
BP
5853 otm->table_id = tm->table_id;
5854 otm->config = ofputil_encode_table_config(tm->miss, tm->eviction,
de7d3c07 5855 tm->vacancy, ofp_version);
918f2b82
AZ
5856 break;
5857 }
42dccab5 5858 case OFP14_VERSION:
b79d45a1
BP
5859 case OFP15_VERSION:
5860 case OFP16_VERSION: {
37ab26e8
BP
5861 struct ofp14_table_mod *otm;
5862
5863 b = ofpraw_alloc(OFPRAW_OFPT14_TABLE_MOD, ofp_version, 0);
5864 otm = ofpbuf_put_zeros(b, sizeof *otm);
82c22d34
BP
5865 otm->table_id = tm->table_id;
5866 otm->config = ofputil_encode_table_config(tm->miss, tm->eviction,
de7d3c07 5867 tm->vacancy, ofp_version);
82c22d34
BP
5868
5869 if (tm->eviction_flags != UINT32_MAX) {
b611d3ac 5870 ofpprop_put_u32(b, OFPTMPT14_EVICTION, tm->eviction_flags);
82c22d34 5871 }
de7d3c07 5872 if (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
303721ee
BP
5873 struct ofp14_table_mod_prop_vacancy *otv;
5874
5875 otv = ofpprop_put_zeros(b, OFPTMPT14_VACANCY, sizeof *otv);
de7d3c07
SJ
5876 otv->vacancy_down = tm->table_vacancy.vacancy_down;
5877 otv->vacancy_up = tm->table_vacancy.vacancy_up;
5878 }
c37c0382 5879 break;
37ab26e8 5880 }
2e3fa633 5881 default:
428b2edd 5882 OVS_NOT_REACHED();
9e1fd49b
BP
5883 }
5884
5885 return b;
5886}
2b07c8b1 5887\f
6ea4776b
JR
5888/* ofputil_role_request */
5889
5890/* Decodes the OpenFlow "role request" or "role reply" message in '*oh' into
5891 * an abstract form in '*rr'. Returns 0 if successful, otherwise an
5892 * OFPERR_* value. */
5893enum ofperr
5894ofputil_decode_role_message(const struct ofp_header *oh,
5895 struct ofputil_role_request *rr)
5896{
0a2869d5
BP
5897 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
5898 enum ofpraw raw = ofpraw_pull_assert(&b);
f4f1ea7e
BP
5899 if (raw == OFPRAW_OFPT12_ROLE_REQUEST ||
5900 raw == OFPRAW_OFPT12_ROLE_REPLY) {
6fd6ed71 5901 const struct ofp12_role_request *orr = b.msg;
6ea4776b 5902
f4f1ea7e
BP
5903 if (orr->role != htonl(OFPCR12_ROLE_NOCHANGE) &&
5904 orr->role != htonl(OFPCR12_ROLE_EQUAL) &&
5905 orr->role != htonl(OFPCR12_ROLE_MASTER) &&
5906 orr->role != htonl(OFPCR12_ROLE_SLAVE)) {
5907 return OFPERR_OFPRRFC_BAD_ROLE;
6ea4776b
JR
5908 }
5909
f4f1ea7e 5910 rr->role = ntohl(orr->role);
147cc9d3
BP
5911 if (raw == OFPRAW_OFPT12_ROLE_REQUEST
5912 ? orr->role == htonl(OFPCR12_ROLE_NOCHANGE)
b8266395 5913 : orr->generation_id == OVS_BE64_MAX) {
f4f1ea7e
BP
5914 rr->have_generation_id = false;
5915 rr->generation_id = 0;
5916 } else {
5917 rr->have_generation_id = true;
5918 rr->generation_id = ntohll(orr->generation_id);
5919 }
5920 } else if (raw == OFPRAW_NXT_ROLE_REQUEST ||
5921 raw == OFPRAW_NXT_ROLE_REPLY) {
6fd6ed71 5922 const struct nx_role_request *nrr = b.msg;
f4f1ea7e
BP
5923
5924 BUILD_ASSERT(NX_ROLE_OTHER + 1 == OFPCR12_ROLE_EQUAL);
5925 BUILD_ASSERT(NX_ROLE_MASTER + 1 == OFPCR12_ROLE_MASTER);
5926 BUILD_ASSERT(NX_ROLE_SLAVE + 1 == OFPCR12_ROLE_SLAVE);
5927
5928 if (nrr->role != htonl(NX_ROLE_OTHER) &&
5929 nrr->role != htonl(NX_ROLE_MASTER) &&
5930 nrr->role != htonl(NX_ROLE_SLAVE)) {
5931 return OFPERR_OFPRRFC_BAD_ROLE;
5932 }
6ea4776b 5933
f4f1ea7e
BP
5934 rr->role = ntohl(nrr->role) + 1;
5935 rr->have_generation_id = false;
5936 rr->generation_id = 0;
5937 } else {
428b2edd 5938 OVS_NOT_REACHED();
6ea4776b
JR
5939 }
5940
6ea4776b
JR
5941 return 0;
5942}
5943
5944/* Returns an encoded form of a role reply suitable for the "request" in a
5945 * buffer owned by the caller. */
5946struct ofpbuf *
5947ofputil_encode_role_reply(const struct ofp_header *request,
f4f1ea7e 5948 const struct ofputil_role_request *rr)
6ea4776b 5949{
6ea4776b 5950 struct ofpbuf *buf;
6ea4776b
JR
5951 enum ofpraw raw;
5952
f4f1ea7e 5953 raw = ofpraw_decode_assert(request);
6ea4776b 5954 if (raw == OFPRAW_OFPT12_ROLE_REQUEST) {
f4f1ea7e 5955 struct ofp12_role_request *orr;
6ea4776b 5956
f4f1ea7e
BP
5957 buf = ofpraw_alloc_reply(OFPRAW_OFPT12_ROLE_REPLY, request, 0);
5958 orr = ofpbuf_put_zeros(buf, sizeof *orr);
6ea4776b 5959
147cc9d3
BP
5960 orr->role = htonl(rr->role);
5961 orr->generation_id = htonll(rr->have_generation_id
5962 ? rr->generation_id
5963 : UINT64_MAX);
f4f1ea7e
BP
5964 } else if (raw == OFPRAW_NXT_ROLE_REQUEST) {
5965 struct nx_role_request *nrr;
5966
5967 BUILD_ASSERT(NX_ROLE_OTHER == OFPCR12_ROLE_EQUAL - 1);
5968 BUILD_ASSERT(NX_ROLE_MASTER == OFPCR12_ROLE_MASTER - 1);
5969 BUILD_ASSERT(NX_ROLE_SLAVE == OFPCR12_ROLE_SLAVE - 1);
5970
5971 buf = ofpraw_alloc_reply(OFPRAW_NXT_ROLE_REPLY, request, 0);
5972 nrr = ofpbuf_put_zeros(buf, sizeof *nrr);
5973 nrr->role = htonl(rr->role - 1);
5974 } else {
428b2edd 5975 OVS_NOT_REACHED();
6ea4776b 5976 }
6ea4776b
JR
5977
5978 return buf;
5979}
5980\f
6751a4b4
BP
5981/* Encodes "role status" message 'status' for sending in the given
5982 * 'protocol'. Returns the role status message, if 'protocol' supports them,
5983 * otherwise a null pointer. */
00467f73
AC
5984struct ofpbuf *
5985ofputil_encode_role_status(const struct ofputil_role_status *status,
5986 enum ofputil_protocol protocol)
5987{
00467f73 5988 enum ofp_version version;
00467f73
AC
5989
5990 version = ofputil_protocol_to_ofp_version(protocol);
6751a4b4
BP
5991 if (version >= OFP14_VERSION) {
5992 struct ofp14_role_status *rstatus;
5993 struct ofpbuf *buf;
5994
5995 buf = ofpraw_alloc_xid(OFPRAW_OFPT14_ROLE_STATUS, version, htonl(0),
5996 0);
5997 rstatus = ofpbuf_put_zeros(buf, sizeof *rstatus);
5998 rstatus->role = htonl(status->role);
5999 rstatus->reason = status->reason;
6000 rstatus->generation_id = htonll(status->generation_id);
6001
6002 return buf;
6003 } else {
6004 return NULL;
6005 }
00467f73
AC
6006}
6007
6008enum ofperr
6009ofputil_decode_role_status(const struct ofp_header *oh,
6010 struct ofputil_role_status *rs)
6011{
0a2869d5
BP
6012 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
6013 enum ofpraw raw = ofpraw_pull_assert(&b);
00467f73
AC
6014 ovs_assert(raw == OFPRAW_OFPT14_ROLE_STATUS);
6015
0a2869d5 6016 const struct ofp14_role_status *r = b.msg;
00467f73
AC
6017 if (r->role != htonl(OFPCR12_ROLE_NOCHANGE) &&
6018 r->role != htonl(OFPCR12_ROLE_EQUAL) &&
6019 r->role != htonl(OFPCR12_ROLE_MASTER) &&
6020 r->role != htonl(OFPCR12_ROLE_SLAVE)) {
6021 return OFPERR_OFPRRFC_BAD_ROLE;
6022 }
6023
6024 rs->role = ntohl(r->role);
6025 rs->generation_id = ntohll(r->generation_id);
6026 rs->reason = r->reason;
6027
6028 return 0;
6029}
6030
3c35db62
NR
6031/* Encodes 'rf' according to 'protocol', and returns the encoded message.
6032 * 'protocol' must be for OpenFlow 1.4 or later. */
6033struct ofpbuf *
6034ofputil_encode_requestforward(const struct ofputil_requestforward *rf,
6035 enum ofputil_protocol protocol)
6036{
6037 enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
6038 struct ofpbuf *inner;
6039
6040 switch (rf->reason) {
6041 case OFPRFR_GROUP_MOD:
6042 inner = ofputil_encode_group_mod(ofp_version, rf->group_mod);
6043 break;
6044
6045 case OFPRFR_METER_MOD:
6046 inner = ofputil_encode_meter_mod(ofp_version, rf->meter_mod);
6047 break;
6048
d18cc1ee 6049 case OFPRFR_N_REASONS:
3c35db62
NR
6050 default:
6051 OVS_NOT_REACHED();
6052 }
6053
6054 struct ofp_header *inner_oh = inner->data;
6055 inner_oh->xid = rf->xid;
6056 inner_oh->length = htons(inner->size);
6057
6058 struct ofpbuf *outer = ofpraw_alloc_xid(OFPRAW_OFPT14_REQUESTFORWARD,
6059 ofp_version, htonl(0),
6060 inner->size);
6061 ofpbuf_put(outer, inner->data, inner->size);
6062 ofpbuf_delete(inner);
6063
6064 return outer;
6065}
6066
6067/* Decodes OFPT_REQUESTFORWARD message 'outer'. On success, puts the decoded
6068 * form into '*rf' and returns 0, and the caller is later responsible for
6069 * freeing the content of 'rf', with ofputil_destroy_requestforward(rf). On
6070 * failure, returns an ofperr and '*rf' is indeterminate. */
6071enum ofperr
6072ofputil_decode_requestforward(const struct ofp_header *outer,
6073 struct ofputil_requestforward *rf)
6074{
0a2869d5 6075 struct ofpbuf b = ofpbuf_const_initializer(outer, ntohs(outer->length));
3c35db62
NR
6076
6077 /* Skip past outer message. */
6078 enum ofpraw outer_raw = ofpraw_pull_assert(&b);
6079 ovs_assert(outer_raw == OFPRAW_OFPT14_REQUESTFORWARD);
6080
6081 /* Validate inner message. */
6082 if (b.size < sizeof(struct ofp_header)) {
6083 return OFPERR_OFPBFC_MSG_BAD_LEN;
6084 }
6085 const struct ofp_header *inner = b.data;
6086 unsigned int inner_len = ntohs(inner->length);
6087 if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) {
6088 return OFPERR_OFPBFC_MSG_BAD_LEN;
6089 }
6090 if (inner->version != outer->version) {
6091 return OFPERR_OFPBRC_BAD_VERSION;
6092 }
6093
6094 /* Parse inner message. */
6095 enum ofptype type;
0a2869d5 6096 enum ofperr error = ofptype_decode(&type, inner);
3c35db62
NR
6097 if (error) {
6098 return error;
6099 }
6100
6101 rf->xid = inner->xid;
6102 if (type == OFPTYPE_GROUP_MOD) {
6103 rf->reason = OFPRFR_GROUP_MOD;
6104 rf->group_mod = xmalloc(sizeof *rf->group_mod);
6105 error = ofputil_decode_group_mod(inner, rf->group_mod);
6106 if (error) {
6107 free(rf->group_mod);
6108 return error;
6109 }
6110 } else if (type == OFPTYPE_METER_MOD) {
6111 rf->reason = OFPRFR_METER_MOD;
6112 rf->meter_mod = xmalloc(sizeof *rf->meter_mod);
6113 ofpbuf_init(&rf->bands, 64);
6114 error = ofputil_decode_meter_mod(inner, rf->meter_mod, &rf->bands);
6115 if (error) {
6116 free(rf->meter_mod);
6117 ofpbuf_uninit(&rf->bands);
6118 return error;
6119 }
6120 } else {
6121 return OFPERR_OFPBFC_MSG_UNSUP;
6122 }
6123
6124 return 0;
6125}
6126
6127/* Frees the content of 'rf', which should have been initialized through a
6128 * successful call to ofputil_decode_requestforward(). */
6129void
6130ofputil_destroy_requestforward(struct ofputil_requestforward *rf)
6131{
6132 if (!rf) {
6133 return;
6134 }
6135
6136 switch (rf->reason) {
6137 case OFPRFR_GROUP_MOD:
6138 ofputil_uninit_group_mod(rf->group_mod);
6139 free(rf->group_mod);
6140 break;
6141
6142 case OFPRFR_METER_MOD:
6143 ofpbuf_uninit(&rf->bands);
6144 free(rf->meter_mod);
d18cc1ee
AA
6145 break;
6146
6147 case OFPRFR_N_REASONS:
6148 OVS_NOT_REACHED();
3c35db62
NR
6149 }
6150}
6151
307975da
SH
6152/* Table stats. */
6153
3c1bb396
BP
6154/* OpenFlow 1.0 and 1.1 don't distinguish between a field that cannot be
6155 * matched and a field that must be wildcarded. This function returns a bitmap
6156 * that contains both kinds of fields. */
6157static struct mf_bitmap
6158wild_or_nonmatchable_fields(const struct ofputil_table_features *features)
6159{
6160 struct mf_bitmap wc = features->match;
6161 bitmap_not(wc.bm, MFF_N_IDS);
6162 bitmap_or(wc.bm, features->wildcard.bm, MFF_N_IDS);
6163 return wc;
6164}
6165
6166struct ofp10_wc_map {
6167 enum ofp10_flow_wildcards wc10;
6168 enum mf_field_id mf;
6169};
6170
6171static const struct ofp10_wc_map ofp10_wc_map[] = {
6172 { OFPFW10_IN_PORT, MFF_IN_PORT },
6173 { OFPFW10_DL_VLAN, MFF_VLAN_VID },
6174 { OFPFW10_DL_SRC, MFF_ETH_SRC },
6175 { OFPFW10_DL_DST, MFF_ETH_DST},
6176 { OFPFW10_DL_TYPE, MFF_ETH_TYPE },
6177 { OFPFW10_NW_PROTO, MFF_IP_PROTO },
6178 { OFPFW10_TP_SRC, MFF_TCP_SRC },
6179 { OFPFW10_TP_DST, MFF_TCP_DST },
6180 { OFPFW10_NW_SRC_MASK, MFF_IPV4_SRC },
6181 { OFPFW10_NW_DST_MASK, MFF_IPV4_DST },
6182 { OFPFW10_DL_VLAN_PCP, MFF_VLAN_PCP },
6183 { OFPFW10_NW_TOS, MFF_IP_DSCP },
6184};
6185
6186static ovs_be32
6187mf_bitmap_to_of10(const struct mf_bitmap *fields)
6188{
6189 const struct ofp10_wc_map *p;
6190 uint32_t wc10 = 0;
6191
6192 for (p = ofp10_wc_map; p < &ofp10_wc_map[ARRAY_SIZE(ofp10_wc_map)]; p++) {
6193 if (bitmap_is_set(fields->bm, p->mf)) {
6194 wc10 |= p->wc10;
6195 }
6196 }
6197 return htonl(wc10);
6198}
6199
6200static struct mf_bitmap
6201mf_bitmap_from_of10(ovs_be32 wc10_)
6202{
6203 struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
6204 const struct ofp10_wc_map *p;
6205 uint32_t wc10 = ntohl(wc10_);
6206
6207 for (p = ofp10_wc_map; p < &ofp10_wc_map[ARRAY_SIZE(ofp10_wc_map)]; p++) {
6208 if (wc10 & p->wc10) {
6209 bitmap_set1(fields.bm, p->mf);
6210 }
6211 }
6212 return fields;
6213}
6214
307975da 6215static void
3c1bb396
BP
6216ofputil_put_ofp10_table_stats(const struct ofputil_table_stats *stats,
6217 const struct ofputil_table_features *features,
307975da
SH
6218 struct ofpbuf *buf)
6219{
3c1bb396 6220 struct mf_bitmap wc = wild_or_nonmatchable_fields(features);
307975da 6221 struct ofp10_table_stats *out;
307975da 6222
3bdc692b 6223 out = ofpbuf_put_zeros(buf, sizeof *out);
3c1bb396
BP
6224 out->table_id = features->table_id;
6225 ovs_strlcpy(out->name, features->name, sizeof out->name);
6226 out->wildcards = mf_bitmap_to_of10(&wc);
6227 out->max_entries = htonl(features->max_entries);
6228 out->active_count = htonl(stats->active_count);
6229 put_32aligned_be64(&out->lookup_count, htonll(stats->lookup_count));
6230 put_32aligned_be64(&out->matched_count, htonll(stats->matched_count));
6231}
6232
6233struct ofp11_wc_map {
6234 enum ofp11_flow_match_fields wc11;
6235 enum mf_field_id mf;
6236};
6237
6238static const struct ofp11_wc_map ofp11_wc_map[] = {
6239 { OFPFMF11_IN_PORT, MFF_IN_PORT },
6240 { OFPFMF11_DL_VLAN, MFF_VLAN_VID },
6241 { OFPFMF11_DL_VLAN_PCP, MFF_VLAN_PCP },
6242 { OFPFMF11_DL_TYPE, MFF_ETH_TYPE },
6243 { OFPFMF11_NW_TOS, MFF_IP_DSCP },
6244 { OFPFMF11_NW_PROTO, MFF_IP_PROTO },
6245 { OFPFMF11_TP_SRC, MFF_TCP_SRC },
6246 { OFPFMF11_TP_DST, MFF_TCP_DST },
6247 { OFPFMF11_MPLS_LABEL, MFF_MPLS_LABEL },
6248 { OFPFMF11_MPLS_TC, MFF_MPLS_TC },
6249 /* I don't know what OFPFMF11_TYPE means. */
6250 { OFPFMF11_DL_SRC, MFF_ETH_SRC },
6251 { OFPFMF11_DL_DST, MFF_ETH_DST },
6252 { OFPFMF11_NW_SRC, MFF_IPV4_SRC },
6253 { OFPFMF11_NW_DST, MFF_IPV4_DST },
6254 { OFPFMF11_METADATA, MFF_METADATA },
6255};
6256
6257static ovs_be32
6258mf_bitmap_to_of11(const struct mf_bitmap *fields)
6259{
6260 const struct ofp11_wc_map *p;
6261 uint32_t wc11 = 0;
6262
6263 for (p = ofp11_wc_map; p < &ofp11_wc_map[ARRAY_SIZE(ofp11_wc_map)]; p++) {
6264 if (bitmap_is_set(fields->bm, p->mf)) {
6265 wc11 |= p->wc11;
307975da
SH
6266 }
6267 }
3c1bb396 6268 return htonl(wc11);
307975da
SH
6269}
6270
3c1bb396
BP
6271static struct mf_bitmap
6272mf_bitmap_from_of11(ovs_be32 wc11_)
6273{
6274 struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
6275 const struct ofp11_wc_map *p;
6276 uint32_t wc11 = ntohl(wc11_);
6277
6278 for (p = ofp11_wc_map; p < &ofp11_wc_map[ARRAY_SIZE(ofp11_wc_map)]; p++) {
6279 if (wc11 & p->wc11) {
6280 bitmap_set1(fields.bm, p->mf);
307975da
SH
6281 }
6282 }
3c1bb396 6283 return fields;
307975da
SH
6284}
6285
6286static void
3c1bb396
BP
6287ofputil_put_ofp11_table_stats(const struct ofputil_table_stats *stats,
6288 const struct ofputil_table_features *features,
307975da
SH
6289 struct ofpbuf *buf)
6290{
3c1bb396 6291 struct mf_bitmap wc = wild_or_nonmatchable_fields(features);
307975da
SH
6292 struct ofp11_table_stats *out;
6293
3bdc692b 6294 out = ofpbuf_put_zeros(buf, sizeof *out);
3c1bb396
BP
6295 out->table_id = features->table_id;
6296 ovs_strlcpy(out->name, features->name, sizeof out->name);
6297 out->wildcards = mf_bitmap_to_of11(&wc);
6298 out->match = mf_bitmap_to_of11(&features->match);
6299 out->instructions = ovsinst_bitmap_to_openflow(
6300 features->nonmiss.instructions, OFP11_VERSION);
6301 out->write_actions = ofpact_bitmap_to_openflow(
6302 features->nonmiss.write.ofpacts, OFP11_VERSION);
6303 out->apply_actions = ofpact_bitmap_to_openflow(
6304 features->nonmiss.apply.ofpacts, OFP11_VERSION);
6305 out->config = htonl(features->miss_config);
6306 out->max_entries = htonl(features->max_entries);
6307 out->active_count = htonl(stats->active_count);
6308 out->lookup_count = htonll(stats->lookup_count);
6309 out->matched_count = htonll(stats->matched_count);
08d1e234
BP
6310}
6311
6240624b 6312static void
3c1bb396
BP
6313ofputil_put_ofp12_table_stats(const struct ofputil_table_stats *stats,
6314 const struct ofputil_table_features *features,
6240624b
BP
6315 struct ofpbuf *buf)
6316{
08d1e234 6317 struct ofp12_table_stats *out;
6240624b 6318
08d1e234 6319 out = ofpbuf_put_zeros(buf, sizeof *out);
3c1bb396
BP
6320 out->table_id = features->table_id;
6321 ovs_strlcpy(out->name, features->name, sizeof out->name);
178742f9
BP
6322 out->match = oxm_bitmap_from_mf_bitmap(&features->match, OFP12_VERSION);
6323 out->wildcards = oxm_bitmap_from_mf_bitmap(&features->wildcard,
3c1bb396
BP
6324 OFP12_VERSION);
6325 out->write_actions = ofpact_bitmap_to_openflow(
6326 features->nonmiss.write.ofpacts, OFP12_VERSION);
6327 out->apply_actions = ofpact_bitmap_to_openflow(
6328 features->nonmiss.apply.ofpacts, OFP12_VERSION);
178742f9 6329 out->write_setfields = oxm_bitmap_from_mf_bitmap(
3c1bb396 6330 &features->nonmiss.write.set_fields, OFP12_VERSION);
178742f9 6331 out->apply_setfields = oxm_bitmap_from_mf_bitmap(
3c1bb396
BP
6332 &features->nonmiss.apply.set_fields, OFP12_VERSION);
6333 out->metadata_match = features->metadata_match;
6334 out->metadata_write = features->metadata_write;
6335 out->instructions = ovsinst_bitmap_to_openflow(
6336 features->nonmiss.instructions, OFP12_VERSION);
82c22d34
BP
6337 out->config = ofputil_encode_table_config(features->miss_config,
6338 OFPUTIL_TABLE_EVICTION_DEFAULT,
de7d3c07 6339 OFPUTIL_TABLE_VACANCY_DEFAULT,
82c22d34 6340 OFP12_VERSION);
3c1bb396
BP
6341 out->max_entries = htonl(features->max_entries);
6342 out->active_count = htonl(stats->active_count);
6343 out->lookup_count = htonll(stats->lookup_count);
6344 out->matched_count = htonll(stats->matched_count);
6240624b
BP
6345}
6346
2e1ae200 6347static void
3c1bb396 6348ofputil_put_ofp13_table_stats(const struct ofputil_table_stats *stats,
2e1ae200
JR
6349 struct ofpbuf *buf)
6350{
6351 struct ofp13_table_stats *out;
6352
3c1bb396
BP
6353 out = ofpbuf_put_zeros(buf, sizeof *out);
6354 out->table_id = stats->table_id;
6355 out->active_count = htonl(stats->active_count);
6356 out->lookup_count = htonll(stats->lookup_count);
6357 out->matched_count = htonll(stats->matched_count);
2e1ae200
JR
6358}
6359
307975da 6360struct ofpbuf *
3c1bb396 6361ofputil_encode_table_stats_reply(const struct ofp_header *request)
307975da 6362{
3c1bb396
BP
6363 return ofpraw_alloc_stats_reply(request, 0);
6364}
307975da 6365
3c1bb396
BP
6366void
6367ofputil_append_table_stats_reply(struct ofpbuf *reply,
6368 const struct ofputil_table_stats *stats,
6369 const struct ofputil_table_features *features)
6370{
6fd6ed71 6371 struct ofp_header *oh = reply->header;
307975da 6372
3c1bb396 6373 ovs_assert(stats->table_id == features->table_id);
307975da 6374
3c1bb396
BP
6375 switch ((enum ofp_version) oh->version) {
6376 case OFP10_VERSION:
6377 ofputil_put_ofp10_table_stats(stats, features, reply);
6378 break;
307975da 6379
3c1bb396
BP
6380 case OFP11_VERSION:
6381 ofputil_put_ofp11_table_stats(stats, features, reply);
6382 break;
307975da 6383
3c1bb396
BP
6384 case OFP12_VERSION:
6385 ofputil_put_ofp12_table_stats(stats, features, reply);
6386 break;
2e1ae200 6387
3c1bb396
BP
6388 case OFP13_VERSION:
6389 case OFP14_VERSION:
6390 case OFP15_VERSION:
b79d45a1 6391 case OFP16_VERSION:
3c1bb396
BP
6392 ofputil_put_ofp13_table_stats(stats, reply);
6393 break;
6394
6395 default:
6396 OVS_NOT_REACHED();
307975da 6397 }
3c1bb396 6398}
307975da 6399
3c1bb396
BP
6400static int
6401ofputil_decode_ofp10_table_stats(struct ofpbuf *msg,
6402 struct ofputil_table_stats *stats,
6403 struct ofputil_table_features *features)
6404{
6405 struct ofp10_table_stats *ots;
6406
6407 ots = ofpbuf_try_pull(msg, sizeof *ots);
6408 if (!ots) {
6409 return OFPERR_OFPBRC_BAD_LEN;
6410 }
6411
6412 features->table_id = ots->table_id;
6413 ovs_strlcpy(features->name, ots->name, sizeof features->name);
6414 features->max_entries = ntohl(ots->max_entries);
6415 features->match = features->wildcard = mf_bitmap_from_of10(ots->wildcards);
6416
6417 stats->table_id = ots->table_id;
6418 stats->active_count = ntohl(ots->active_count);
6419 stats->lookup_count = ntohll(get_32aligned_be64(&ots->lookup_count));
6420 stats->matched_count = ntohll(get_32aligned_be64(&ots->matched_count));
6421
6422 return 0;
6423}
6424
6425static int
6426ofputil_decode_ofp11_table_stats(struct ofpbuf *msg,
6427 struct ofputil_table_stats *stats,
6428 struct ofputil_table_features *features)
6429{
6430 struct ofp11_table_stats *ots;
6431
6432 ots = ofpbuf_try_pull(msg, sizeof *ots);
6433 if (!ots) {
6434 return OFPERR_OFPBRC_BAD_LEN;
6435 }
6436
6437 features->table_id = ots->table_id;
6438 ovs_strlcpy(features->name, ots->name, sizeof features->name);
6439 features->max_entries = ntohl(ots->max_entries);
6440 features->nonmiss.instructions = ovsinst_bitmap_from_openflow(
6441 ots->instructions, OFP11_VERSION);
6442 features->nonmiss.write.ofpacts = ofpact_bitmap_from_openflow(
6443 ots->write_actions, OFP11_VERSION);
6444 features->nonmiss.apply.ofpacts = ofpact_bitmap_from_openflow(
6445 ots->write_actions, OFP11_VERSION);
6446 features->miss = features->nonmiss;
82c22d34
BP
6447 features->miss_config = ofputil_decode_table_miss(ots->config,
6448 OFP11_VERSION);
3c1bb396
BP
6449 features->match = mf_bitmap_from_of11(ots->match);
6450 features->wildcard = mf_bitmap_from_of11(ots->wildcards);
6451 bitmap_or(features->match.bm, features->wildcard.bm, MFF_N_IDS);
6452
6453 stats->table_id = ots->table_id;
6454 stats->active_count = ntohl(ots->active_count);
6455 stats->lookup_count = ntohll(ots->lookup_count);
6456 stats->matched_count = ntohll(ots->matched_count);
6457
6458 return 0;
6459}
6460
6461static int
6462ofputil_decode_ofp12_table_stats(struct ofpbuf *msg,
6463 struct ofputil_table_stats *stats,
6464 struct ofputil_table_features *features)
6465{
6466 struct ofp12_table_stats *ots;
6467
6468 ots = ofpbuf_try_pull(msg, sizeof *ots);
6469 if (!ots) {
6470 return OFPERR_OFPBRC_BAD_LEN;
6471 }
6472
6473 features->table_id = ots->table_id;
6474 ovs_strlcpy(features->name, ots->name, sizeof features->name);
6475 features->metadata_match = ots->metadata_match;
6476 features->metadata_write = ots->metadata_write;
82c22d34
BP
6477 features->miss_config = ofputil_decode_table_miss(ots->config,
6478 OFP12_VERSION);
3c1bb396
BP
6479 features->max_entries = ntohl(ots->max_entries);
6480
6481 features->nonmiss.instructions = ovsinst_bitmap_from_openflow(
6482 ots->instructions, OFP12_VERSION);
6483 features->nonmiss.write.ofpacts = ofpact_bitmap_from_openflow(
6484 ots->write_actions, OFP12_VERSION);
6485 features->nonmiss.apply.ofpacts = ofpact_bitmap_from_openflow(
6486 ots->apply_actions, OFP12_VERSION);
178742f9 6487 features->nonmiss.write.set_fields = oxm_bitmap_to_mf_bitmap(
3c1bb396 6488 ots->write_setfields, OFP12_VERSION);
178742f9 6489 features->nonmiss.apply.set_fields = oxm_bitmap_to_mf_bitmap(
3c1bb396
BP
6490 ots->apply_setfields, OFP12_VERSION);
6491 features->miss = features->nonmiss;
6492
178742f9
BP
6493 features->match = oxm_bitmap_to_mf_bitmap(ots->match, OFP12_VERSION);
6494 features->wildcard = oxm_bitmap_to_mf_bitmap(ots->wildcards,
6495 OFP12_VERSION);
3c1bb396
BP
6496 bitmap_or(features->match.bm, features->wildcard.bm, MFF_N_IDS);
6497
6498 stats->table_id = ots->table_id;
6499 stats->active_count = ntohl(ots->active_count);
6500 stats->lookup_count = ntohll(ots->lookup_count);
6501 stats->matched_count = ntohll(ots->matched_count);
6502
6503 return 0;
6504}
6505
6506static int
6507ofputil_decode_ofp13_table_stats(struct ofpbuf *msg,
6508 struct ofputil_table_stats *stats,
6509 struct ofputil_table_features *features)
6510{
6511 struct ofp13_table_stats *ots;
6512
6513 ots = ofpbuf_try_pull(msg, sizeof *ots);
6514 if (!ots) {
6515 return OFPERR_OFPBRC_BAD_LEN;
6516 }
6517
6518 features->table_id = ots->table_id;
6519
6520 stats->table_id = ots->table_id;
6521 stats->active_count = ntohl(ots->active_count);
6522 stats->lookup_count = ntohll(ots->lookup_count);
6523 stats->matched_count = ntohll(ots->matched_count);
6524
6525 return 0;
6526}
6527
6528int
6529ofputil_decode_table_stats_reply(struct ofpbuf *msg,
6530 struct ofputil_table_stats *stats,
6531 struct ofputil_table_features *features)
6532{
6533 const struct ofp_header *oh;
6534
6fd6ed71 6535 if (!msg->header) {
3c1bb396
BP
6536 ofpraw_pull_assert(msg);
6537 }
6fd6ed71 6538 oh = msg->header;
3c1bb396 6539
6fd6ed71 6540 if (!msg->size) {
3c1bb396
BP
6541 return EOF;
6542 }
6543
6544 memset(stats, 0, sizeof *stats);
6545 memset(features, 0, sizeof *features);
82c22d34
BP
6546 features->supports_eviction = -1;
6547 features->supports_vacancy_events = -1;
3c1bb396
BP
6548
6549 switch ((enum ofp_version) oh->version) {
6550 case OFP10_VERSION:
6551 return ofputil_decode_ofp10_table_stats(msg, stats, features);
6552
6553 case OFP11_VERSION:
6554 return ofputil_decode_ofp11_table_stats(msg, stats, features);
6555
6556 case OFP12_VERSION:
6557 return ofputil_decode_ofp12_table_stats(msg, stats, features);
6558
6559 case OFP13_VERSION:
6560 case OFP14_VERSION:
6561 case OFP15_VERSION:
b79d45a1 6562 case OFP16_VERSION:
3c1bb396
BP
6563 return ofputil_decode_ofp13_table_stats(msg, stats, features);
6564
6565 default:
6566 OVS_NOT_REACHED();
6567 }
307975da
SH
6568}
6569\f
2b07c8b1
BP
6570/* ofputil_flow_monitor_request */
6571
6572/* Converts an NXST_FLOW_MONITOR request in 'msg' into an abstract
6573 * ofputil_flow_monitor_request in 'rq'.
6574 *
6575 * Multiple NXST_FLOW_MONITOR requests can be packed into a single OpenFlow
6576 * message. Calling this function multiple times for a single 'msg' iterates
6577 * through the requests. The caller must initially leave 'msg''s layer
6578 * pointers null and not modify them between calls.
6579 *
6580 * Returns 0 if successful, EOF if no requests were left in this 'msg',
6581 * otherwise an OFPERR_* value. */
6582int
6583ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq,
6584 struct ofpbuf *msg)
6585{
6586 struct nx_flow_monitor_request *nfmr;
6587 uint16_t flags;
6588
6fd6ed71 6589 if (!msg->header) {
982697a4 6590 ofpraw_pull_assert(msg);
2b07c8b1
BP
6591 }
6592
6fd6ed71 6593 if (!msg->size) {
2b07c8b1
BP
6594 return EOF;
6595 }
6596
6597 nfmr = ofpbuf_try_pull(msg, sizeof *nfmr);
6598 if (!nfmr) {
437d0d22 6599 VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR request has %"PRIu32" "
6fd6ed71 6600 "leftover bytes at end", msg->size);
2b07c8b1
BP
6601 return OFPERR_OFPBRC_BAD_LEN;
6602 }
6603
6604 flags = ntohs(nfmr->flags);
6605 if (!(flags & (NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY))
6606 || flags & ~(NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE
6607 | NXFMF_MODIFY | NXFMF_ACTIONS | NXFMF_OWN)) {
6608 VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR has bad flags %#"PRIx16,
6609 flags);
04f9f286 6610 return OFPERR_OFPMOFC_BAD_FLAGS;
2b07c8b1
BP
6611 }
6612
6613 if (!is_all_zeros(nfmr->zeros, sizeof nfmr->zeros)) {
6614 return OFPERR_NXBRC_MUST_BE_ZERO;
6615 }
6616
6617 rq->id = ntohl(nfmr->id);
6618 rq->flags = flags;
4e022ec0 6619 rq->out_port = u16_to_ofp(ntohs(nfmr->out_port));
2b07c8b1
BP
6620 rq->table_id = nfmr->table_id;
6621
81a76618 6622 return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL, NULL);
2b07c8b1
BP
6623}
6624
6625void
6626ofputil_append_flow_monitor_request(
6627 const struct ofputil_flow_monitor_request *rq, struct ofpbuf *msg)
6628{
6629 struct nx_flow_monitor_request *nfmr;
6630 size_t start_ofs;
6631 int match_len;
6632
6fd6ed71 6633 if (!msg->size) {
982697a4 6634 ofpraw_put(OFPRAW_NXST_FLOW_MONITOR_REQUEST, OFP10_VERSION, msg);
2b07c8b1
BP
6635 }
6636
6fd6ed71 6637 start_ofs = msg->size;
2b07c8b1 6638 ofpbuf_put_zeros(msg, sizeof *nfmr);
7623f4dd 6639 match_len = nx_put_match(msg, &rq->match, htonll(0), htonll(0));
2b07c8b1
BP
6640
6641 nfmr = ofpbuf_at_assert(msg, start_ofs, sizeof *nfmr);
6642 nfmr->id = htonl(rq->id);
6643 nfmr->flags = htons(rq->flags);
4e022ec0 6644 nfmr->out_port = htons(ofp_to_u16(rq->out_port));
2b07c8b1
BP
6645 nfmr->match_len = htons(match_len);
6646 nfmr->table_id = rq->table_id;
6647}
6648
6649/* Converts an NXST_FLOW_MONITOR reply (also known as a flow update) in 'msg'
6650 * into an abstract ofputil_flow_update in 'update'. The caller must have
81a76618 6651 * initialized update->match to point to space allocated for a match.
2b07c8b1
BP
6652 *
6653 * Uses 'ofpacts' to store the abstract OFPACT_* version of the update's
6654 * actions (except for NXFME_ABBREV, which never includes actions). The caller
6655 * must initialize 'ofpacts' and retains ownership of it. 'update->ofpacts'
6656 * will point into the 'ofpacts' buffer.
6657 *
6658 * Multiple flow updates can be packed into a single OpenFlow message. Calling
6659 * this function multiple times for a single 'msg' iterates through the
6660 * updates. The caller must initially leave 'msg''s layer pointers null and
6661 * not modify them between calls.
6662 *
6663 * Returns 0 if successful, EOF if no updates were left in this 'msg',
6664 * otherwise an OFPERR_* value. */
6665int
6666ofputil_decode_flow_update(struct ofputil_flow_update *update,
6667 struct ofpbuf *msg, struct ofpbuf *ofpacts)
6668{
6669 struct nx_flow_update_header *nfuh;
6670 unsigned int length;
e3f8f887 6671 struct ofp_header *oh;
2b07c8b1 6672
6fd6ed71 6673 if (!msg->header) {
982697a4 6674 ofpraw_pull_assert(msg);
2b07c8b1
BP
6675 }
6676
9abca1e5 6677 ofpbuf_clear(ofpacts);
6fd6ed71 6678 if (!msg->size) {
2b07c8b1
BP
6679 return EOF;
6680 }
6681
6fd6ed71 6682 if (msg->size < sizeof(struct nx_flow_update_header)) {
2b07c8b1
BP
6683 goto bad_len;
6684 }
6685
6fd6ed71 6686 oh = msg->header;
e3f8f887 6687
6fd6ed71 6688 nfuh = msg->data;
2b07c8b1
BP
6689 update->event = ntohs(nfuh->event);
6690 length = ntohs(nfuh->length);
6fd6ed71 6691 if (length > msg->size || length % 8) {
2b07c8b1
BP
6692 goto bad_len;
6693 }
6694
6695 if (update->event == NXFME_ABBREV) {
6696 struct nx_flow_update_abbrev *nfua;
6697
6698 if (length != sizeof *nfua) {
6699 goto bad_len;
6700 }
6701
6702 nfua = ofpbuf_pull(msg, sizeof *nfua);
6703 update->xid = nfua->xid;
6704 return 0;
6705 } else if (update->event == NXFME_ADDED
6706 || update->event == NXFME_DELETED
6707 || update->event == NXFME_MODIFIED) {
6708 struct nx_flow_update_full *nfuf;
6709 unsigned int actions_len;
6710 unsigned int match_len;
6711 enum ofperr error;
6712
6713 if (length < sizeof *nfuf) {
6714 goto bad_len;
6715 }
6716
6717 nfuf = ofpbuf_pull(msg, sizeof *nfuf);
6718 match_len = ntohs(nfuf->match_len);
6719 if (sizeof *nfuf + match_len > length) {
6720 goto bad_len;
6721 }
6722
6723 update->reason = ntohs(nfuf->reason);
6724 update->idle_timeout = ntohs(nfuf->idle_timeout);
6725 update->hard_timeout = ntohs(nfuf->hard_timeout);
6726 update->table_id = nfuf->table_id;
6727 update->cookie = nfuf->cookie;
81a76618 6728 update->priority = ntohs(nfuf->priority);
2b07c8b1 6729
81a76618 6730 error = nx_pull_match(msg, match_len, update->match, NULL, NULL);
2b07c8b1
BP
6731 if (error) {
6732 return error;
6733 }
6734
6735 actions_len = length - sizeof *nfuf - ROUND_UP(match_len, 8);
e3f8f887
JR
6736 error = ofpacts_pull_openflow_actions(msg, actions_len, oh->version,
6737 ofpacts);
2b07c8b1
BP
6738 if (error) {
6739 return error;
6740 }
6741
6fd6ed71
PS
6742 update->ofpacts = ofpacts->data;
6743 update->ofpacts_len = ofpacts->size;
2b07c8b1
BP
6744 return 0;
6745 } else {
6746 VLOG_WARN_RL(&bad_ofmsg_rl,
6747 "NXST_FLOW_MONITOR reply has bad event %"PRIu16,
6748 ntohs(nfuh->event));
15549878 6749 return OFPERR_NXBRC_FM_BAD_EVENT;
2b07c8b1
BP
6750 }
6751
6752bad_len:
437d0d22 6753 VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has %"PRIu32" "
6fd6ed71 6754 "leftover bytes at end", msg->size);
2b07c8b1
BP
6755 return OFPERR_OFPBRC_BAD_LEN;
6756}
6757
6758uint32_t
6759ofputil_decode_flow_monitor_cancel(const struct ofp_header *oh)
6760{
982697a4
BP
6761 const struct nx_flow_monitor_cancel *cancel = ofpmsg_body(oh);
6762
6763 return ntohl(cancel->id);
2b07c8b1 6764}
9e1fd49b 6765
2b07c8b1
BP
6766struct ofpbuf *
6767ofputil_encode_flow_monitor_cancel(uint32_t id)
6768{
6769 struct nx_flow_monitor_cancel *nfmc;
6770 struct ofpbuf *msg;
6771
982697a4
BP
6772 msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MONITOR_CANCEL, OFP10_VERSION, 0);
6773 nfmc = ofpbuf_put_uninit(msg, sizeof *nfmc);
2b07c8b1
BP
6774 nfmc->id = htonl(id);
6775 return msg;
6776}
6777
6778void
ca6ba700 6779ofputil_start_flow_update(struct ovs_list *replies)
2b07c8b1
BP
6780{
6781 struct ofpbuf *msg;
6782
982697a4
BP
6783 msg = ofpraw_alloc_xid(OFPRAW_NXST_FLOW_MONITOR_REPLY, OFP10_VERSION,
6784 htonl(0), 1024);
2b07c8b1 6785
417e7e66
BW
6786 ovs_list_init(replies);
6787 ovs_list_push_back(replies, &msg->list_node);
2b07c8b1
BP
6788}
6789
6790void
6791ofputil_append_flow_update(const struct ofputil_flow_update *update,
ca6ba700 6792 struct ovs_list *replies)
2b07c8b1 6793{
e28ac5cf 6794 enum ofp_version version = ofpmp_version(replies);
2b07c8b1
BP
6795 struct nx_flow_update_header *nfuh;
6796 struct ofpbuf *msg;
6797 size_t start_ofs;
6798
417e7e66 6799 msg = ofpbuf_from_list(ovs_list_back(replies));
6fd6ed71 6800 start_ofs = msg->size;
2b07c8b1
BP
6801
6802 if (update->event == NXFME_ABBREV) {
6803 struct nx_flow_update_abbrev *nfua;
6804
6805 nfua = ofpbuf_put_zeros(msg, sizeof *nfua);
6806 nfua->xid = update->xid;
6807 } else {
6808 struct nx_flow_update_full *nfuf;
6809 int match_len;
6810
6811 ofpbuf_put_zeros(msg, sizeof *nfuf);
7623f4dd 6812 match_len = nx_put_match(msg, update->match, htonll(0), htonll(0));
e3f8f887
JR
6813 ofpacts_put_openflow_actions(update->ofpacts, update->ofpacts_len, msg,
6814 version);
2b07c8b1
BP
6815 nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
6816 nfuf->reason = htons(update->reason);
81a76618 6817 nfuf->priority = htons(update->priority);
2b07c8b1
BP
6818 nfuf->idle_timeout = htons(update->idle_timeout);
6819 nfuf->hard_timeout = htons(update->hard_timeout);
6820 nfuf->match_len = htons(match_len);
6821 nfuf->table_id = update->table_id;
6822 nfuf->cookie = update->cookie;
6823 }
6824
6825 nfuh = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuh);
6fd6ed71 6826 nfuh->length = htons(msg->size - start_ofs);
2b07c8b1
BP
6827 nfuh->event = htons(update->event);
6828
982697a4 6829 ofpmp_postappend(replies, start_ofs);
2b07c8b1
BP
6830}
6831\f
c6a93eb7 6832struct ofpbuf *
de0f3156
SH
6833ofputil_encode_packet_out(const struct ofputil_packet_out *po,
6834 enum ofputil_protocol protocol)
c6a93eb7 6835{
de0f3156 6836 enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
c6a93eb7
BP
6837 struct ofpbuf *msg;
6838 size_t size;
6839
982697a4 6840 size = po->ofpacts_len;
c6a93eb7
BP
6841 if (po->buffer_id == UINT32_MAX) {
6842 size += po->packet_len;
6843 }
6844
de0f3156
SH
6845 switch (ofp_version) {
6846 case OFP10_VERSION: {
31a9e63f 6847 struct ofp10_packet_out *opo;
de0f3156
SH
6848 size_t actions_ofs;
6849
6850 msg = ofpraw_alloc(OFPRAW_OFPT10_PACKET_OUT, OFP10_VERSION, size);
6851 ofpbuf_put_zeros(msg, sizeof *opo);
6fd6ed71 6852 actions_ofs = msg->size;
e3f8f887
JR
6853 ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
6854 ofp_version);
de0f3156 6855
6fd6ed71 6856 opo = msg->msg;
de0f3156 6857 opo->buffer_id = htonl(po->buffer_id);
4e022ec0 6858 opo->in_port = htons(ofp_to_u16(po->in_port));
6fd6ed71 6859 opo->actions_len = htons(msg->size - actions_ofs);
de0f3156
SH
6860 break;
6861 }
f25d0cf3 6862
de0f3156 6863 case OFP11_VERSION:
2e1ae200 6864 case OFP12_VERSION:
c37c0382 6865 case OFP13_VERSION:
42dccab5 6866 case OFP14_VERSION:
b79d45a1
BP
6867 case OFP15_VERSION:
6868 case OFP16_VERSION: {
7c1b1a0d
SH
6869 struct ofp11_packet_out *opo;
6870 size_t len;
6871
6872 msg = ofpraw_alloc(OFPRAW_OFPT11_PACKET_OUT, ofp_version, size);
6873 ofpbuf_put_zeros(msg, sizeof *opo);
e3f8f887
JR
6874 len = ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
6875 ofp_version);
6fd6ed71 6876 opo = msg->msg;
7c1b1a0d
SH
6877 opo->buffer_id = htonl(po->buffer_id);
6878 opo->in_port = ofputil_port_to_ofp11(po->in_port);
6879 opo->actions_len = htons(len);
6880 break;
6881 }
6882
de0f3156 6883 default:
428b2edd 6884 OVS_NOT_REACHED();
de0f3156 6885 }
f25d0cf3 6886
c6a93eb7
BP
6887 if (po->buffer_id == UINT32_MAX) {
6888 ofpbuf_put(msg, po->packet, po->packet_len);
6889 }
f25d0cf3 6890
982697a4 6891 ofpmsg_update_length(msg);
c6a93eb7
BP
6892
6893 return msg;
6894}
d1e2cf21 6895\f
fa37b408
BP
6896/* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
6897struct ofpbuf *
1a126c0c 6898make_echo_request(enum ofp_version ofp_version)
fa37b408 6899{
1a126c0c 6900 return ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, ofp_version,
982697a4 6901 htonl(0), 0);
fa37b408
BP
6902}
6903
6904/* Creates and returns an OFPT_ECHO_REPLY message matching the
6905 * OFPT_ECHO_REQUEST message in 'rq'. */
6906struct ofpbuf *
6907make_echo_reply(const struct ofp_header *rq)
6908{
0a2869d5 6909 struct ofpbuf rq_buf = ofpbuf_const_initializer(rq, ntohs(rq->length));
982697a4
BP
6910 ofpraw_pull_assert(&rq_buf);
6911
0a2869d5
BP
6912 struct ofpbuf *reply = ofpraw_alloc_reply(OFPRAW_OFPT_ECHO_REPLY,
6913 rq, rq_buf.size);
6fd6ed71 6914 ofpbuf_put(reply, rq_buf.data, rq_buf.size);
982697a4 6915 return reply;
fa37b408
BP
6916}
6917
efb80167 6918struct ofpbuf *
a0ae0b6e 6919ofputil_encode_barrier_request(enum ofp_version ofp_version)
efb80167 6920{
a0ae0b6e
SH
6921 enum ofpraw type;
6922
6923 switch (ofp_version) {
b79d45a1 6924 case OFP16_VERSION:
42dccab5 6925 case OFP15_VERSION:
c37c0382 6926 case OFP14_VERSION:
2e1ae200 6927 case OFP13_VERSION:
a0ae0b6e
SH
6928 case OFP12_VERSION:
6929 case OFP11_VERSION:
6930 type = OFPRAW_OFPT11_BARRIER_REQUEST;
6931 break;
6932
6933 case OFP10_VERSION:
6934 type = OFPRAW_OFPT10_BARRIER_REQUEST;
6935 break;
6936
6937 default:
428b2edd 6938 OVS_NOT_REACHED();
a0ae0b6e
SH
6939 }
6940
6941 return ofpraw_alloc(type, ofp_version, 0);
efb80167
BP
6942}
6943
7257b535 6944const char *
ad99e2ed 6945ofputil_frag_handling_to_string(enum ofputil_frag_handling frag)
7257b535 6946{
ad99e2ed
BP
6947 switch (frag) {
6948 case OFPUTIL_FRAG_NORMAL: return "normal";
6949 case OFPUTIL_FRAG_DROP: return "drop";
6950 case OFPUTIL_FRAG_REASM: return "reassemble";
6951 case OFPUTIL_FRAG_NX_MATCH: return "nx-match";
7257b535
BP
6952 }
6953
428b2edd 6954 OVS_NOT_REACHED();
7257b535
BP
6955}
6956
6957bool
ad99e2ed
BP
6958ofputil_frag_handling_from_string(const char *s,
6959 enum ofputil_frag_handling *frag)
7257b535
BP
6960{
6961 if (!strcasecmp(s, "normal")) {
ad99e2ed 6962 *frag = OFPUTIL_FRAG_NORMAL;
7257b535 6963 } else if (!strcasecmp(s, "drop")) {
ad99e2ed 6964 *frag = OFPUTIL_FRAG_DROP;
7257b535 6965 } else if (!strcasecmp(s, "reassemble")) {
ad99e2ed 6966 *frag = OFPUTIL_FRAG_REASM;
7257b535 6967 } else if (!strcasecmp(s, "nx-match")) {
ad99e2ed 6968 *frag = OFPUTIL_FRAG_NX_MATCH;
7257b535
BP
6969 } else {
6970 return false;
6971 }
6972 return true;
6973}
6974
7b7503ea
BP
6975/* Converts the OpenFlow 1.1+ port number 'ofp11_port' into an OpenFlow 1.0
6976 * port number and stores the latter in '*ofp10_port', for the purpose of
6977 * decoding OpenFlow 1.1+ protocol messages. Returns 0 if successful,
bc146369 6978 * otherwise an OFPERR_* number. On error, stores OFPP_NONE in '*ofp10_port'.
7b7503ea
BP
6979 *
6980 * See the definition of OFP11_MAX for an explanation of the mapping. */
6981enum ofperr
4e022ec0 6982ofputil_port_from_ofp11(ovs_be32 ofp11_port, ofp_port_t *ofp10_port)
7b7503ea
BP
6983{
6984 uint32_t ofp11_port_h = ntohl(ofp11_port);
6985
4e022ec0
AW
6986 if (ofp11_port_h < ofp_to_u16(OFPP_MAX)) {
6987 *ofp10_port = u16_to_ofp(ofp11_port_h);
7b7503ea 6988 return 0;
4e022ec0
AW
6989 } else if (ofp11_port_h >= ofp11_to_u32(OFPP11_MAX)) {
6990 *ofp10_port = u16_to_ofp(ofp11_port_h - OFPP11_OFFSET);
7b7503ea
BP
6991 return 0;
6992 } else {
bc146369 6993 *ofp10_port = OFPP_NONE;
7b7503ea
BP
6994 VLOG_WARN_RL(&bad_ofmsg_rl, "port %"PRIu32" is outside the supported "
6995 "range 0 through %d or 0x%"PRIx32" through 0x%"PRIx32,
4e022ec0
AW
6996 ofp11_port_h, ofp_to_u16(OFPP_MAX) - 1,
6997 ofp11_to_u32(OFPP11_MAX), UINT32_MAX);
7b7503ea
BP
6998 return OFPERR_OFPBAC_BAD_OUT_PORT;
6999 }
7000}
7001
7002/* Returns the OpenFlow 1.1+ port number equivalent to the OpenFlow 1.0 port
7003 * number 'ofp10_port', for encoding OpenFlow 1.1+ protocol messages.
7004 *
7005 * See the definition of OFP11_MAX for an explanation of the mapping. */
7006ovs_be32
4e022ec0 7007ofputil_port_to_ofp11(ofp_port_t ofp10_port)
7b7503ea 7008{
4e022ec0
AW
7009 return htonl(ofp_to_u16(ofp10_port) < ofp_to_u16(OFPP_MAX)
7010 ? ofp_to_u16(ofp10_port)
7011 : ofp_to_u16(ofp10_port) + OFPP11_OFFSET);
7b7503ea
BP
7012}
7013
39dc9082
BP
7014#define OFPUTIL_NAMED_PORTS \
7015 OFPUTIL_NAMED_PORT(IN_PORT) \
7016 OFPUTIL_NAMED_PORT(TABLE) \
7017 OFPUTIL_NAMED_PORT(NORMAL) \
7018 OFPUTIL_NAMED_PORT(FLOOD) \
7019 OFPUTIL_NAMED_PORT(ALL) \
7020 OFPUTIL_NAMED_PORT(CONTROLLER) \
7021 OFPUTIL_NAMED_PORT(LOCAL) \
c61f3870
BP
7022 OFPUTIL_NAMED_PORT(ANY) \
7023 OFPUTIL_NAMED_PORT(UNSET)
7f05e7ab
JR
7024
7025/* For backwards compatibility, so that "none" is recognized as OFPP_ANY */
7026#define OFPUTIL_NAMED_PORTS_WITH_NONE \
7027 OFPUTIL_NAMED_PORTS \
39dc9082
BP
7028 OFPUTIL_NAMED_PORT(NONE)
7029
8010100b
BP
7030/* Stores the port number represented by 's' into '*portp'. 's' may be an
7031 * integer or, for reserved ports, the standard OpenFlow name for the port
7032 * (e.g. "LOCAL").
c6100d92 7033 *
8010100b
BP
7034 * Returns true if successful, false if 's' is not a valid OpenFlow port number
7035 * or name. The caller should issue an error message in this case, because
7036 * this function usually does not. (This gives the caller an opportunity to
7037 * look up the port name another way, e.g. by contacting the switch and listing
7038 * the names of all its ports).
c6100d92
BP
7039 *
7040 * This function accepts OpenFlow 1.0 port numbers. It also accepts a subset
7041 * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit
7042 * range as described in include/openflow/openflow-1.1.h. */
8010100b 7043bool
4e022ec0 7044ofputil_port_from_string(const char *s, ofp_port_t *portp)
39dc9082 7045{
5b23ff7e 7046 unsigned int port32; /* int is at least 32 bits wide. */
c6100d92 7047
5b23ff7e
JR
7048 if (*s == '-') {
7049 VLOG_WARN("Negative value %s is not a valid port number.", s);
7050 return false;
7051 }
8010100b 7052 *portp = 0;
c6100d92 7053 if (str_to_uint(s, 10, &port32)) {
4e022ec0
AW
7054 if (port32 < ofp_to_u16(OFPP_MAX)) {
7055 /* Pass. */
7056 } else if (port32 < ofp_to_u16(OFPP_FIRST_RESV)) {
c6100d92
BP
7057 VLOG_WARN("port %u is a reserved OF1.0 port number that will "
7058 "be translated to %u when talking to an OF1.1 or "
7059 "later controller", port32, port32 + OFPP11_OFFSET);
4e022ec0 7060 } else if (port32 <= ofp_to_u16(OFPP_LAST_RESV)) {
28b11432
BP
7061 char name[OFP_MAX_PORT_NAME_LEN];
7062
7063 ofputil_port_to_string(u16_to_ofp(port32), name, sizeof name);
7064 VLOG_WARN_ONCE("referring to port %s as %"PRIu32" is deprecated "
7065 "for compatibility with OpenFlow 1.1 and later",
7066 name, port32);
4e022ec0 7067 } else if (port32 < ofp11_to_u32(OFPP11_MAX)) {
c6100d92 7068 VLOG_WARN("port %u is outside the supported range 0 through "
d047fd17 7069 "%"PRIx16" or 0x%x through 0x%"PRIx32, port32,
4e022ec0 7070 UINT16_MAX, ofp11_to_u32(OFPP11_MAX), UINT32_MAX);
8010100b 7071 return false;
c6100d92 7072 } else {
4e022ec0 7073 port32 -= OFPP11_OFFSET;
c6100d92 7074 }
4e022ec0
AW
7075
7076 *portp = u16_to_ofp(port32);
7077 return true;
c6100d92
BP
7078 } else {
7079 struct pair {
7080 const char *name;
4e022ec0 7081 ofp_port_t value;
c6100d92
BP
7082 };
7083 static const struct pair pairs[] = {
39dc9082 7084#define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME},
7f05e7ab 7085 OFPUTIL_NAMED_PORTS_WITH_NONE
39dc9082 7086#undef OFPUTIL_NAMED_PORT
c6100d92
BP
7087 };
7088 const struct pair *p;
39dc9082 7089
c6100d92
BP
7090 for (p = pairs; p < &pairs[ARRAY_SIZE(pairs)]; p++) {
7091 if (!strcasecmp(s, p->name)) {
8010100b
BP
7092 *portp = p->value;
7093 return true;
c6100d92 7094 }
39dc9082 7095 }
8010100b 7096 return false;
39dc9082 7097 }
39dc9082
BP
7098}
7099
7100/* Appends to 's' a string representation of the OpenFlow port number 'port'.
7101 * Most ports' string representation is just the port number, but for special
7102 * ports, e.g. OFPP_LOCAL, it is the name, e.g. "LOCAL". */
7103void
4e022ec0 7104ofputil_format_port(ofp_port_t port, struct ds *s)
39dc9082 7105{
28b11432
BP
7106 char name[OFP_MAX_PORT_NAME_LEN];
7107
7108 ofputil_port_to_string(port, name, sizeof name);
7109 ds_put_cstr(s, name);
7110}
39dc9082 7111
28b11432
BP
7112/* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string
7113 * representation of OpenFlow port number 'port'. Most ports are represented
7114 * as just the port number, but special ports, e.g. OFPP_LOCAL, are represented
7115 * by name, e.g. "LOCAL". */
7116void
7117ofputil_port_to_string(ofp_port_t port,
7118 char namebuf[OFP_MAX_PORT_NAME_LEN], size_t bufsize)
7119{
39dc9082 7120 switch (port) {
28b11432
BP
7121#define OFPUTIL_NAMED_PORT(NAME) \
7122 case OFPP_##NAME: \
7123 ovs_strlcpy(namebuf, #NAME, bufsize); \
7124 break;
39dc9082
BP
7125 OFPUTIL_NAMED_PORTS
7126#undef OFPUTIL_NAMED_PORT
7127
7128 default:
28b11432
BP
7129 snprintf(namebuf, bufsize, "%"PRIu16, port);
7130 break;
39dc9082 7131 }
39dc9082
BP
7132}
7133
7395c052
NZ
7134/* Stores the group id represented by 's' into '*group_idp'. 's' may be an
7135 * integer or, for reserved group IDs, the standard OpenFlow name for the group
7136 * (either "ANY" or "ALL").
7137 *
7138 * Returns true if successful, false if 's' is not a valid OpenFlow group ID or
7139 * name. */
7140bool
7141ofputil_group_from_string(const char *s, uint32_t *group_idp)
7142{
7143 if (!strcasecmp(s, "any")) {
30ef36c6 7144 *group_idp = OFPG_ANY;
7395c052 7145 } else if (!strcasecmp(s, "all")) {
30ef36c6 7146 *group_idp = OFPG_ALL;
7395c052
NZ
7147 } else if (!str_to_uint(s, 10, group_idp)) {
7148 VLOG_WARN("%s is not a valid group ID. (Valid group IDs are "
7149 "32-bit nonnegative integers or the keywords ANY or "
7150 "ALL.)", s);
7151 return false;
7152 }
7153
7154 return true;
7155}
7156
7157/* Appends to 's' a string representation of the OpenFlow group ID 'group_id'.
7158 * Most groups' string representation is just the number, but for special
30ef36c6 7159 * groups, e.g. OFPG_ALL, it is the name, e.g. "ALL". */
7395c052
NZ
7160void
7161ofputil_format_group(uint32_t group_id, struct ds *s)
7162{
7163 char name[MAX_GROUP_NAME_LEN];
7164
7165 ofputil_group_to_string(group_id, name, sizeof name);
7166 ds_put_cstr(s, name);
7167}
7168
7169
7170/* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string
7171 * representation of OpenFlow group ID 'group_id'. Most group are represented
30ef36c6 7172 * as just their number, but special groups, e.g. OFPG_ALL, are represented
7395c052
NZ
7173 * by name, e.g. "ALL". */
7174void
7175ofputil_group_to_string(uint32_t group_id,
7176 char namebuf[MAX_GROUP_NAME_LEN + 1], size_t bufsize)
7177{
7178 switch (group_id) {
30ef36c6 7179 case OFPG_ALL:
7395c052
NZ
7180 ovs_strlcpy(namebuf, "ALL", bufsize);
7181 break;
7182
30ef36c6 7183 case OFPG_ANY:
7395c052
NZ
7184 ovs_strlcpy(namebuf, "ANY", bufsize);
7185 break;
7186
7187 default:
7188 snprintf(namebuf, bufsize, "%"PRIu32, group_id);
7189 break;
7190 }
7191}
7192
2be393ed
JP
7193/* Given a buffer 'b' that contains an array of OpenFlow ports of type
7194 * 'ofp_version', tries to pull the first element from the array. If
7195 * successful, initializes '*pp' with an abstract representation of the
7196 * port and returns 0. If no ports remain to be decoded, returns EOF.
7197 * On an error, returns a positive OFPERR_* value. */
7198int
2e3fa633 7199ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b,
2be393ed
JP
7200 struct ofputil_phy_port *pp)
7201{
8c3cc785
BP
7202 memset(pp, 0, sizeof *pp);
7203
2e3fa633
SH
7204 switch (ofp_version) {
7205 case OFP10_VERSION: {
2be393ed
JP
7206 const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp);
7207 return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF;
2e3fa633
SH
7208 }
7209 case OFP11_VERSION:
2e1ae200
JR
7210 case OFP12_VERSION:
7211 case OFP13_VERSION: {
2be393ed
JP
7212 const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op);
7213 return op ? ofputil_decode_ofp11_port(pp, op) : EOF;
7214 }
c37c0382 7215 case OFP14_VERSION:
42dccab5 7216 case OFP15_VERSION:
b79d45a1 7217 case OFP16_VERSION:
6fd6ed71 7218 return b->size ? ofputil_pull_ofp14_port(pp, b) : EOF;
2e3fa633 7219 default:
428b2edd 7220 OVS_NOT_REACHED();
2e3fa633 7221 }
2be393ed
JP
7222}
7223
3cbd9931 7224static void
81a76618 7225ofputil_normalize_match__(struct match *match, bool may_log)
b459a924
BP
7226{
7227 enum {
7228 MAY_NW_ADDR = 1 << 0, /* nw_src, nw_dst */
7229 MAY_TP_ADDR = 1 << 1, /* tp_src, tp_dst */
7230 MAY_NW_PROTO = 1 << 2, /* nw_proto */
a61680c6 7231 MAY_IPVx = 1 << 3, /* tos, frag, ttl */
b459a924
BP
7232 MAY_ARP_SHA = 1 << 4, /* arp_sha */
7233 MAY_ARP_THA = 1 << 5, /* arp_tha */
d78477ec 7234 MAY_IPV6 = 1 << 6, /* ipv6_src, ipv6_dst, ipv6_label */
b02475c5
SH
7235 MAY_ND_TARGET = 1 << 7, /* nd_target */
7236 MAY_MPLS = 1 << 8, /* mpls label and tc */
b459a924
BP
7237 } may_match;
7238
7239 struct flow_wildcards wc;
7240
7241 /* Figure out what fields may be matched. */
81a76618 7242 if (match->flow.dl_type == htons(ETH_TYPE_IP)) {
9e44d715 7243 may_match = MAY_NW_PROTO | MAY_IPVx | MAY_NW_ADDR;
81a76618
BP
7244 if (match->flow.nw_proto == IPPROTO_TCP ||
7245 match->flow.nw_proto == IPPROTO_UDP ||
0d56eaf2 7246 match->flow.nw_proto == IPPROTO_SCTP ||
81a76618 7247 match->flow.nw_proto == IPPROTO_ICMP) {
b459a924
BP
7248 may_match |= MAY_TP_ADDR;
7249 }
81a76618 7250 } else if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
d78477ec 7251 may_match = MAY_NW_PROTO | MAY_IPVx | MAY_IPV6;
81a76618 7252 if (match->flow.nw_proto == IPPROTO_TCP ||
0d56eaf2
JS
7253 match->flow.nw_proto == IPPROTO_UDP ||
7254 match->flow.nw_proto == IPPROTO_SCTP) {
b459a924 7255 may_match |= MAY_TP_ADDR;
81a76618 7256 } else if (match->flow.nw_proto == IPPROTO_ICMPV6) {
b459a924 7257 may_match |= MAY_TP_ADDR;
81a76618 7258 if (match->flow.tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
b459a924 7259 may_match |= MAY_ND_TARGET | MAY_ARP_SHA;
81a76618 7260 } else if (match->flow.tp_src == htons(ND_NEIGHBOR_ADVERT)) {
b459a924
BP
7261 may_match |= MAY_ND_TARGET | MAY_ARP_THA;
7262 }
7263 }
8087f5ff
MM
7264 } else if (match->flow.dl_type == htons(ETH_TYPE_ARP) ||
7265 match->flow.dl_type == htons(ETH_TYPE_RARP)) {
27527aa0 7266 may_match = MAY_NW_PROTO | MAY_NW_ADDR | MAY_ARP_SHA | MAY_ARP_THA;
b02475c5
SH
7267 } else if (eth_type_mpls(match->flow.dl_type)) {
7268 may_match = MAY_MPLS;
1c0b7503 7269 } else {
b459a924
BP
7270 may_match = 0;
7271 }
7272
7273 /* Clear the fields that may not be matched. */
81a76618 7274 wc = match->wc;
b459a924 7275 if (!(may_match & MAY_NW_ADDR)) {
26720e24 7276 wc.masks.nw_src = wc.masks.nw_dst = htonl(0);
b459a924
BP
7277 }
7278 if (!(may_match & MAY_TP_ADDR)) {
26720e24 7279 wc.masks.tp_src = wc.masks.tp_dst = htons(0);
b459a924
BP
7280 }
7281 if (!(may_match & MAY_NW_PROTO)) {
26720e24 7282 wc.masks.nw_proto = 0;
b459a924 7283 }
9e44d715 7284 if (!(may_match & MAY_IPVx)) {
26720e24
BP
7285 wc.masks.nw_tos = 0;
7286 wc.masks.nw_ttl = 0;
b459a924
BP
7287 }
7288 if (!(may_match & MAY_ARP_SHA)) {
74ff3298 7289 WC_UNMASK_FIELD(&wc, arp_sha);
b459a924
BP
7290 }
7291 if (!(may_match & MAY_ARP_THA)) {
74ff3298 7292 WC_UNMASK_FIELD(&wc, arp_tha);
b459a924 7293 }
d78477ec 7294 if (!(may_match & MAY_IPV6)) {
26720e24
BP
7295 wc.masks.ipv6_src = wc.masks.ipv6_dst = in6addr_any;
7296 wc.masks.ipv6_label = htonl(0);
b459a924
BP
7297 }
7298 if (!(may_match & MAY_ND_TARGET)) {
26720e24 7299 wc.masks.nd_target = in6addr_any;
b459a924 7300 }
b02475c5 7301 if (!(may_match & MAY_MPLS)) {
8bfd0fda 7302 memset(wc.masks.mpls_lse, 0, sizeof wc.masks.mpls_lse);
b02475c5 7303 }
b459a924
BP
7304
7305 /* Log any changes. */
81a76618 7306 if (!flow_wildcards_equal(&wc, &match->wc)) {
3cbd9931 7307 bool log = may_log && !VLOG_DROP_INFO(&bad_ofmsg_rl);
81a76618 7308 char *pre = log ? match_to_string(match, OFP_DEFAULT_PRIORITY) : NULL;
b459a924 7309
81a76618
BP
7310 match->wc = wc;
7311 match_zero_wildcarded_fields(match);
b459a924
BP
7312
7313 if (log) {
81a76618 7314 char *post = match_to_string(match, OFP_DEFAULT_PRIORITY);
b459a924
BP
7315 VLOG_INFO("normalization changed ofp_match, details:");
7316 VLOG_INFO(" pre: %s", pre);
7317 VLOG_INFO("post: %s", post);
7318 free(pre);
7319 free(post);
7320 }
fa37b408 7321 }
3f09c339 7322}
26c112c2 7323
81a76618 7324/* "Normalizes" the wildcards in 'match'. That means:
3cbd9931
BP
7325 *
7326 * 1. If the type of level N is known, then only the valid fields for that
7327 * level may be specified. For example, ARP does not have a TOS field,
81a76618 7328 * so nw_tos must be wildcarded if 'match' specifies an ARP flow.
3cbd9931 7329 * Similarly, IPv4 does not have any IPv6 addresses, so ipv6_src and
81a76618 7330 * ipv6_dst (and other fields) must be wildcarded if 'match' specifies an
3cbd9931
BP
7331 * IPv4 flow.
7332 *
7333 * 2. If the type of level N is not known (or not understood by Open
7334 * vSwitch), then no fields at all for that level may be specified. For
7335 * example, Open vSwitch does not understand SCTP, an L4 protocol, so the
81a76618 7336 * L4 fields tp_src and tp_dst must be wildcarded if 'match' specifies an
3cbd9931
BP
7337 * SCTP flow.
7338 *
81a76618 7339 * If this function changes 'match', it logs a rate-limited informational
3cbd9931
BP
7340 * message. */
7341void
81a76618 7342ofputil_normalize_match(struct match *match)
3cbd9931 7343{
81a76618 7344 ofputil_normalize_match__(match, true);
3cbd9931
BP
7345}
7346
81a76618
BP
7347/* Same as ofputil_normalize_match() without the logging. Thus, this function
7348 * is suitable for a program's internal use, whereas ofputil_normalize_match()
3cbd9931
BP
7349 * sense for use on flows received from elsewhere (so that a bug in the program
7350 * that sent them can be reported and corrected). */
7351void
81a76618 7352ofputil_normalize_match_quiet(struct match *match)
3cbd9931 7353{
81a76618 7354 ofputil_normalize_match__(match, false);
3cbd9931
BP
7355}
7356
0ff22822
BP
7357/* Parses a key or a key-value pair from '*stringp'.
7358 *
7359 * On success: Stores the key into '*keyp'. Stores the value, if present, into
7360 * '*valuep', otherwise an empty string. Advances '*stringp' past the end of
7361 * the key-value pair, preparing it for another call. '*keyp' and '*valuep'
7362 * are substrings of '*stringp' created by replacing some of its bytes by null
7363 * terminators. Returns true.
7364 *
7365 * If '*stringp' is just white space or commas, sets '*keyp' and '*valuep' to
7366 * NULL and returns false. */
7367bool
7368ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
7369{
7370 char *pos, *key, *value;
7371 size_t key_len;
7372
7373 pos = *stringp;
7374 pos += strspn(pos, ", \t\r\n");
7375 if (*pos == '\0') {
7376 *keyp = *valuep = NULL;
7377 return false;
7378 }
7379
7380 key = pos;
7381 key_len = strcspn(pos, ":=(, \t\r\n");
7382 if (key[key_len] == ':' || key[key_len] == '=') {
7383 /* The value can be separated by a colon. */
7384 size_t value_len;
7385
7386 value = key + key_len + 1;
7387 value_len = strcspn(value, ", \t\r\n");
7388 pos = value + value_len + (value[value_len] != '\0');
7389 value[value_len] = '\0';
7390 } else if (key[key_len] == '(') {
7391 /* The value can be surrounded by balanced parentheses. The outermost
7392 * set of parentheses is removed. */
7393 int level = 1;
7394 size_t value_len;
7395
7396 value = key + key_len + 1;
7397 for (value_len = 0; level > 0; value_len++) {
7398 switch (value[value_len]) {
7399 case '\0':
33cadc50
BP
7400 level = 0;
7401 break;
0ff22822
BP
7402
7403 case '(':
7404 level++;
7405 break;
7406
7407 case ')':
7408 level--;
7409 break;
7410 }
7411 }
7412 value[value_len - 1] = '\0';
7413 pos = value + value_len;
7414 } else {
7415 /* There might be no value at all. */
7416 value = key + key_len; /* Will become the empty string below. */
7417 pos = key + key_len + (key[key_len] != '\0');
7418 }
7419 key[key_len] = '\0';
7420
7421 *stringp = pos;
7422 *keyp = key;
7423 *valuep = value;
7424 return true;
7425}
f8e4867e
SH
7426
7427/* Encode a dump ports request for 'port', the encoded message
0746a84f 7428 * will be for OpenFlow version 'ofp_version'. Returns message
f8e4867e
SH
7429 * as a struct ofpbuf. Returns encoded message on success, NULL on error */
7430struct ofpbuf *
4e022ec0 7431ofputil_encode_dump_ports_request(enum ofp_version ofp_version, ofp_port_t port)
f8e4867e
SH
7432{
7433 struct ofpbuf *request;
7434
7435 switch (ofp_version) {
7436 case OFP10_VERSION: {
7437 struct ofp10_port_stats_request *req;
7438 request = ofpraw_alloc(OFPRAW_OFPST10_PORT_REQUEST, ofp_version, 0);
7439 req = ofpbuf_put_zeros(request, sizeof *req);
4e022ec0 7440 req->port_no = htons(ofp_to_u16(port));
f8e4867e
SH
7441 break;
7442 }
7443 case OFP11_VERSION:
2e1ae200 7444 case OFP12_VERSION:
c37c0382 7445 case OFP13_VERSION:
42dccab5 7446 case OFP14_VERSION:
b79d45a1
BP
7447 case OFP15_VERSION:
7448 case OFP16_VERSION: {
f8e4867e
SH
7449 struct ofp11_port_stats_request *req;
7450 request = ofpraw_alloc(OFPRAW_OFPST11_PORT_REQUEST, ofp_version, 0);
7451 req = ofpbuf_put_zeros(request, sizeof *req);
7452 req->port_no = ofputil_port_to_ofp11(port);
7453 break;
7454 }
7455 default:
428b2edd 7456 OVS_NOT_REACHED();
f8e4867e
SH
7457 }
7458
7459 return request;
7460}
7461
7462static void
7463ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops,
7464 struct ofp10_port_stats *ps10)
7465{
4e022ec0 7466 ps10->port_no = htons(ofp_to_u16(ops->port_no));
f8e4867e
SH
7467 memset(ps10->pad, 0, sizeof ps10->pad);
7468 put_32aligned_be64(&ps10->rx_packets, htonll(ops->stats.rx_packets));
7469 put_32aligned_be64(&ps10->tx_packets, htonll(ops->stats.tx_packets));
7470 put_32aligned_be64(&ps10->rx_bytes, htonll(ops->stats.rx_bytes));
7471 put_32aligned_be64(&ps10->tx_bytes, htonll(ops->stats.tx_bytes));
7472 put_32aligned_be64(&ps10->rx_dropped, htonll(ops->stats.rx_dropped));
7473 put_32aligned_be64(&ps10->tx_dropped, htonll(ops->stats.tx_dropped));
7474 put_32aligned_be64(&ps10->rx_errors, htonll(ops->stats.rx_errors));
7475 put_32aligned_be64(&ps10->tx_errors, htonll(ops->stats.tx_errors));
7476 put_32aligned_be64(&ps10->rx_frame_err, htonll(ops->stats.rx_frame_errors));
7477 put_32aligned_be64(&ps10->rx_over_err, htonll(ops->stats.rx_over_errors));
7478 put_32aligned_be64(&ps10->rx_crc_err, htonll(ops->stats.rx_crc_errors));
7479 put_32aligned_be64(&ps10->collisions, htonll(ops->stats.collisions));
7480}
7481
7482static void
7483ofputil_port_stats_to_ofp11(const struct ofputil_port_stats *ops,
7484 struct ofp11_port_stats *ps11)
7485{
7486 ps11->port_no = ofputil_port_to_ofp11(ops->port_no);
7487 memset(ps11->pad, 0, sizeof ps11->pad);
7488 ps11->rx_packets = htonll(ops->stats.rx_packets);
7489 ps11->tx_packets = htonll(ops->stats.tx_packets);
7490 ps11->rx_bytes = htonll(ops->stats.rx_bytes);
7491 ps11->tx_bytes = htonll(ops->stats.tx_bytes);
7492 ps11->rx_dropped = htonll(ops->stats.rx_dropped);
7493 ps11->tx_dropped = htonll(ops->stats.tx_dropped);
7494 ps11->rx_errors = htonll(ops->stats.rx_errors);
7495 ps11->tx_errors = htonll(ops->stats.tx_errors);
7496 ps11->rx_frame_err = htonll(ops->stats.rx_frame_errors);
7497 ps11->rx_over_err = htonll(ops->stats.rx_over_errors);
7498 ps11->rx_crc_err = htonll(ops->stats.rx_crc_errors);
7499 ps11->collisions = htonll(ops->stats.collisions);
7500}
7501
2e1ae200
JR
7502static void
7503ofputil_port_stats_to_ofp13(const struct ofputil_port_stats *ops,
7504 struct ofp13_port_stats *ps13)
7505{
7506 ofputil_port_stats_to_ofp11(ops, &ps13->ps);
65e0be10
BP
7507 ps13->duration_sec = htonl(ops->duration_sec);
7508 ps13->duration_nsec = htonl(ops->duration_nsec);
2e1ae200
JR
7509}
7510
5469537b
BP
7511static void
7512ofputil_append_ofp14_port_stats(const struct ofputil_port_stats *ops,
ca6ba700 7513 struct ovs_list *replies)
5469537b
BP
7514{
7515 struct ofp14_port_stats_prop_ethernet *eth;
7516 struct ofp14_port_stats *ps14;
7517 struct ofpbuf *reply;
7518
7519 reply = ofpmp_reserve(replies, sizeof *ps14 + sizeof *eth);
7520
7521 ps14 = ofpbuf_put_uninit(reply, sizeof *ps14);
7522 ps14->length = htons(sizeof *ps14 + sizeof *eth);
7523 memset(ps14->pad, 0, sizeof ps14->pad);
7524 ps14->port_no = ofputil_port_to_ofp11(ops->port_no);
7525 ps14->duration_sec = htonl(ops->duration_sec);
7526 ps14->duration_nsec = htonl(ops->duration_nsec);
7527 ps14->rx_packets = htonll(ops->stats.rx_packets);
7528 ps14->tx_packets = htonll(ops->stats.tx_packets);
7529 ps14->rx_bytes = htonll(ops->stats.rx_bytes);
7530 ps14->tx_bytes = htonll(ops->stats.tx_bytes);
7531 ps14->rx_dropped = htonll(ops->stats.rx_dropped);
7532 ps14->tx_dropped = htonll(ops->stats.tx_dropped);
7533 ps14->rx_errors = htonll(ops->stats.rx_errors);
7534 ps14->tx_errors = htonll(ops->stats.tx_errors);
7535
303721ee 7536 eth = ofpprop_put_zeros(reply, OFPPSPT14_ETHERNET, sizeof *eth);
5469537b
BP
7537 eth->rx_frame_err = htonll(ops->stats.rx_frame_errors);
7538 eth->rx_over_err = htonll(ops->stats.rx_over_errors);
7539 eth->rx_crc_err = htonll(ops->stats.rx_crc_errors);
7540 eth->collisions = htonll(ops->stats.collisions);
7541}
2e1ae200 7542
ad4c35fe 7543/* Encode a ports stat for 'ops' and append it to 'replies'. */
f8e4867e 7544void
ca6ba700 7545ofputil_append_port_stat(struct ovs_list *replies,
f8e4867e
SH
7546 const struct ofputil_port_stats *ops)
7547{
e28ac5cf 7548 switch (ofpmp_version(replies)) {
2e1ae200
JR
7549 case OFP13_VERSION: {
7550 struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply);
7551 ofputil_port_stats_to_ofp13(ops, reply);
7552 break;
7553 }
f8e4867e
SH
7554 case OFP12_VERSION:
7555 case OFP11_VERSION: {
7556 struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply);
7557 ofputil_port_stats_to_ofp11(ops, reply);
7558 break;
7559 }
7560
7561 case OFP10_VERSION: {
7562 struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply);
7563 ofputil_port_stats_to_ofp10(ops, reply);
7564 break;
7565 }
7566
c37c0382 7567 case OFP14_VERSION:
42dccab5 7568 case OFP15_VERSION:
b79d45a1 7569 case OFP16_VERSION:
5469537b 7570 ofputil_append_ofp14_port_stats(ops, replies);
c37c0382
AC
7571 break;
7572
f8e4867e 7573 default:
428b2edd 7574 OVS_NOT_REACHED();
f8e4867e
SH
7575 }
7576}
7577
7578static enum ofperr
7579ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
7580 const struct ofp10_port_stats *ps10)
7581{
7582 memset(ops, 0, sizeof *ops);
7583
4e022ec0 7584 ops->port_no = u16_to_ofp(ntohs(ps10->port_no));
f8e4867e
SH
7585 ops->stats.rx_packets = ntohll(get_32aligned_be64(&ps10->rx_packets));
7586 ops->stats.tx_packets = ntohll(get_32aligned_be64(&ps10->tx_packets));
7587 ops->stats.rx_bytes = ntohll(get_32aligned_be64(&ps10->rx_bytes));
7588 ops->stats.tx_bytes = ntohll(get_32aligned_be64(&ps10->tx_bytes));
7589 ops->stats.rx_dropped = ntohll(get_32aligned_be64(&ps10->rx_dropped));
7590 ops->stats.tx_dropped = ntohll(get_32aligned_be64(&ps10->tx_dropped));
7591 ops->stats.rx_errors = ntohll(get_32aligned_be64(&ps10->rx_errors));
7592 ops->stats.tx_errors = ntohll(get_32aligned_be64(&ps10->tx_errors));
7593 ops->stats.rx_frame_errors =
7594 ntohll(get_32aligned_be64(&ps10->rx_frame_err));
7595 ops->stats.rx_over_errors = ntohll(get_32aligned_be64(&ps10->rx_over_err));
7596 ops->stats.rx_crc_errors = ntohll(get_32aligned_be64(&ps10->rx_crc_err));
7597 ops->stats.collisions = ntohll(get_32aligned_be64(&ps10->collisions));
65e0be10 7598 ops->duration_sec = ops->duration_nsec = UINT32_MAX;
f8e4867e
SH
7599
7600 return 0;
7601}
7602
7603static enum ofperr
7604ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops,
7605 const struct ofp11_port_stats *ps11)
7606{
7607 enum ofperr error;
7608
7609 memset(ops, 0, sizeof *ops);
7610 error = ofputil_port_from_ofp11(ps11->port_no, &ops->port_no);
7611 if (error) {
7612 return error;
7613 }
7614
7615 ops->stats.rx_packets = ntohll(ps11->rx_packets);
7616 ops->stats.tx_packets = ntohll(ps11->tx_packets);
7617 ops->stats.rx_bytes = ntohll(ps11->rx_bytes);
7618 ops->stats.tx_bytes = ntohll(ps11->tx_bytes);
7619 ops->stats.rx_dropped = ntohll(ps11->rx_dropped);
7620 ops->stats.tx_dropped = ntohll(ps11->tx_dropped);
7621 ops->stats.rx_errors = ntohll(ps11->rx_errors);
7622 ops->stats.tx_errors = ntohll(ps11->tx_errors);
7623 ops->stats.rx_frame_errors = ntohll(ps11->rx_frame_err);
7624 ops->stats.rx_over_errors = ntohll(ps11->rx_over_err);
7625 ops->stats.rx_crc_errors = ntohll(ps11->rx_crc_err);
7626 ops->stats.collisions = ntohll(ps11->collisions);
65e0be10 7627 ops->duration_sec = ops->duration_nsec = UINT32_MAX;
f8e4867e
SH
7628
7629 return 0;
7630}
7631
2e1ae200
JR
7632static enum ofperr
7633ofputil_port_stats_from_ofp13(struct ofputil_port_stats *ops,
7634 const struct ofp13_port_stats *ps13)
7635{
65e0be10 7636 enum ofperr error = ofputil_port_stats_from_ofp11(ops, &ps13->ps);
2e1ae200 7637 if (!error) {
65e0be10
BP
7638 ops->duration_sec = ntohl(ps13->duration_sec);
7639 ops->duration_nsec = ntohl(ps13->duration_nsec);
2e1ae200 7640 }
2e1ae200
JR
7641 return error;
7642}
7643
5469537b
BP
7644static enum ofperr
7645parse_ofp14_port_stats_ethernet_property(const struct ofpbuf *payload,
7646 struct ofputil_port_stats *ops)
be0c30df 7647{
6fd6ed71 7648 const struct ofp14_port_stats_prop_ethernet *eth = payload->data;
5469537b 7649
6fd6ed71 7650 if (payload->size != sizeof *eth) {
5469537b
BP
7651 return OFPERR_OFPBPC_BAD_LEN;
7652 }
7653
7654 ops->stats.rx_frame_errors = ntohll(eth->rx_frame_err);
7655 ops->stats.rx_over_errors = ntohll(eth->rx_over_err);
7656 ops->stats.rx_crc_errors = ntohll(eth->rx_crc_err);
7657 ops->stats.collisions = ntohll(eth->collisions);
7658
7659 return 0;
7660}
7661
7662static enum ofperr
7663ofputil_pull_ofp14_port_stats(struct ofputil_port_stats *ops,
7664 struct ofpbuf *msg)
7665{
0a2869d5 7666 const struct ofp14_port_stats *ps14 = ofpbuf_try_pull(msg, sizeof *ps14);
5469537b
BP
7667 if (!ps14) {
7668 return OFPERR_OFPBRC_BAD_LEN;
7669 }
7670
0a2869d5 7671 size_t len = ntohs(ps14->length);
6fd6ed71 7672 if (len < sizeof *ps14 || len - sizeof *ps14 > msg->size) {
5469537b 7673 return OFPERR_OFPBRC_BAD_LEN;
be0c30df 7674 }
5469537b 7675 len -= sizeof *ps14;
5469537b 7676
0a2869d5 7677 enum ofperr error = ofputil_port_from_ofp11(ps14->port_no, &ops->port_no);
5469537b
BP
7678 if (error) {
7679 return error;
7680 }
7681
7682 ops->duration_sec = ntohl(ps14->duration_sec);
7683 ops->duration_nsec = ntohl(ps14->duration_nsec);
7684 ops->stats.rx_packets = ntohll(ps14->rx_packets);
7685 ops->stats.tx_packets = ntohll(ps14->tx_packets);
7686 ops->stats.rx_bytes = ntohll(ps14->rx_bytes);
7687 ops->stats.tx_bytes = ntohll(ps14->tx_bytes);
7688 ops->stats.rx_dropped = ntohll(ps14->rx_dropped);
7689 ops->stats.tx_dropped = ntohll(ps14->tx_dropped);
7690 ops->stats.rx_errors = ntohll(ps14->rx_errors);
7691 ops->stats.tx_errors = ntohll(ps14->tx_errors);
7692 ops->stats.rx_frame_errors = UINT64_MAX;
7693 ops->stats.rx_over_errors = UINT64_MAX;
7694 ops->stats.rx_crc_errors = UINT64_MAX;
7695 ops->stats.collisions = UINT64_MAX;
7696
0a2869d5
BP
7697 struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
7698 len);
6fd6ed71 7699 while (properties.size > 0) {
5469537b
BP
7700 struct ofpbuf payload;
7701 enum ofperr error;
34a543e3 7702 uint64_t type;
5469537b 7703
c5562271 7704 error = ofpprop_pull(&properties, &payload, &type);
5469537b
BP
7705 if (error) {
7706 return error;
7707 }
7708
7709 switch (type) {
7710 case OFPPSPT14_ETHERNET:
7711 error = parse_ofp14_port_stats_ethernet_property(&payload, ops);
7712 break;
7713
7714 default:
34a543e3 7715 error = OFPPROP_UNKNOWN(true, "port stats", type);
5469537b
BP
7716 break;
7717 }
7718
7719 if (error) {
7720 return error;
7721 }
7722 }
7723
7724 return 0;
be0c30df 7725}
2e1ae200 7726
f8e4867e
SH
7727/* Returns the number of port stats elements in OFPTYPE_PORT_STATS_REPLY
7728 * message 'oh'. */
7729size_t
7730ofputil_count_port_stats(const struct ofp_header *oh)
7731{
0a2869d5 7732 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
f8e4867e 7733 ofpraw_pull_assert(&b);
0a2869d5
BP
7734
7735 for (size_t n = 0; ; n++) {
7736 struct ofputil_port_stats ps;
7737 if (ofputil_decode_port_stats(&ps, &b)) {
7738 return n;
7739 }
5469537b 7740 }
f8e4867e
SH
7741}
7742
7743/* Converts an OFPST_PORT_STATS reply in 'msg' into an abstract
7744 * ofputil_port_stats in 'ps'.
7745 *
7746 * Multiple OFPST_PORT_STATS replies can be packed into a single OpenFlow
7747 * message. Calling this function multiple times for a single 'msg' iterates
7748 * through the replies. The caller must initially leave 'msg''s layer pointers
7749 * null and not modify them between calls.
7750 *
7751 * Returns 0 if successful, EOF if no replies were left in this 'msg',
7752 * otherwise a positive errno value. */
7753int
7754ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
7755{
7756 enum ofperr error;
7757 enum ofpraw raw;
7758
6fd6ed71 7759 error = (msg->header ? ofpraw_decode(&raw, msg->header)
f8e4867e
SH
7760 : ofpraw_pull(&raw, msg));
7761 if (error) {
7762 return error;
7763 }
7764
6fd6ed71 7765 if (!msg->size) {
f8e4867e 7766 return EOF;
5469537b
BP
7767 } else if (raw == OFPRAW_OFPST14_PORT_REPLY) {
7768 return ofputil_pull_ofp14_port_stats(ps, msg);
2e1ae200
JR
7769 } else if (raw == OFPRAW_OFPST13_PORT_REPLY) {
7770 const struct ofp13_port_stats *ps13;
7771
7772 ps13 = ofpbuf_try_pull(msg, sizeof *ps13);
7773 if (!ps13) {
7774 goto bad_len;
7775 }
7776 return ofputil_port_stats_from_ofp13(ps, ps13);
f8e4867e
SH
7777 } else if (raw == OFPRAW_OFPST11_PORT_REPLY) {
7778 const struct ofp11_port_stats *ps11;
7779
7780 ps11 = ofpbuf_try_pull(msg, sizeof *ps11);
7781 if (!ps11) {
2e1ae200 7782 goto bad_len;
f8e4867e
SH
7783 }
7784 return ofputil_port_stats_from_ofp11(ps, ps11);
7785 } else if (raw == OFPRAW_OFPST10_PORT_REPLY) {
7786 const struct ofp10_port_stats *ps10;
7787
7788 ps10 = ofpbuf_try_pull(msg, sizeof *ps10);
7789 if (!ps10) {
2e1ae200 7790 goto bad_len;
f8e4867e
SH
7791 }
7792 return ofputil_port_stats_from_ofp10(ps, ps10);
7793 } else {
428b2edd 7794 OVS_NOT_REACHED();
f8e4867e
SH
7795 }
7796
2e1ae200 7797 bad_len:
437d0d22 7798 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %"PRIu32" leftover "
6fd6ed71 7799 "bytes at end", msg->size);
2e1ae200 7800 return OFPERR_OFPBRC_BAD_LEN;
f8e4867e
SH
7801}
7802
7803/* Parse a port status request message into a 16 bit OpenFlow 1.0
7804 * port number and stores the latter in '*ofp10_port'.
7805 * Returns 0 if successful, otherwise an OFPERR_* number. */
7806enum ofperr
7807ofputil_decode_port_stats_request(const struct ofp_header *request,
4e022ec0 7808 ofp_port_t *ofp10_port)
f8e4867e
SH
7809{
7810 switch ((enum ofp_version)request->version) {
b79d45a1 7811 case OFP16_VERSION:
42dccab5 7812 case OFP15_VERSION:
5469537b 7813 case OFP14_VERSION:
2e1ae200 7814 case OFP13_VERSION:
f8e4867e
SH
7815 case OFP12_VERSION:
7816 case OFP11_VERSION: {
7817 const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request);
7818 return ofputil_port_from_ofp11(psr11->port_no, ofp10_port);
7819 }
7820
7821 case OFP10_VERSION: {
7822 const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request);
4e022ec0 7823 *ofp10_port = u16_to_ofp(ntohs(psr10->port_no));
f8e4867e
SH
7824 return 0;
7825 }
7826
7827 default:
428b2edd 7828 OVS_NOT_REACHED();
f8e4867e
SH
7829 }
7830}
64626975 7831
7395c052
NZ
7832/* Frees all of the "struct ofputil_bucket"s in the 'buckets' list. */
7833void
ca6ba700 7834ofputil_bucket_list_destroy(struct ovs_list *buckets)
7395c052 7835{
5f03c983 7836 struct ofputil_bucket *bucket;
7395c052 7837
5f03c983 7838 LIST_FOR_EACH_POP (bucket, list_node, buckets) {
7395c052
NZ
7839 free(bucket->ofpacts);
7840 free(bucket);
7841 }
7842}
7843
103b4866
SH
7844/* Clones 'bucket' and its ofpacts data */
7845static struct ofputil_bucket *
7846ofputil_bucket_clone_data(const struct ofputil_bucket *bucket)
7847{
7848 struct ofputil_bucket *new;
7849
7850 new = xmemdup(bucket, sizeof *bucket);
7851 new->ofpacts = xmemdup(bucket->ofpacts, bucket->ofpacts_len);
7852
7853 return new;
7854}
7855
7856/* Clones each of the buckets in the list 'src' appending them
7857 * in turn to 'dest' which should be an initialised list.
7858 * An exception is that if the pointer value of a bucket in 'src'
7859 * matches 'skip' then it is not cloned or appended to 'dest'.
7860 * This allows all of 'src' or 'all of 'src' except 'skip' to
7861 * be cloned and appended to 'dest'. */
7862void
ca6ba700 7863ofputil_bucket_clone_list(struct ovs_list *dest, const struct ovs_list *src,
103b4866
SH
7864 const struct ofputil_bucket *skip)
7865{
7866 struct ofputil_bucket *bucket;
7867
7868 LIST_FOR_EACH (bucket, list_node, src) {
7869 struct ofputil_bucket *new_bucket;
7870
7871 if (bucket == skip) {
7872 continue;
7873 }
7874
7875 new_bucket = ofputil_bucket_clone_data(bucket);
417e7e66 7876 ovs_list_push_back(dest, &new_bucket->list_node);
103b4866
SH
7877 }
7878}
7879
7880/* Find a bucket in the list 'buckets' whose bucket id is 'bucket_id'
7881 * Returns the first bucket found or NULL if no buckets are found. */
7882struct ofputil_bucket *
ca6ba700 7883ofputil_bucket_find(const struct ovs_list *buckets, uint32_t bucket_id)
103b4866
SH
7884{
7885 struct ofputil_bucket *bucket;
7886
7887 if (bucket_id > OFPG15_BUCKET_MAX) {
7888 return NULL;
7889 }
7890
7891 LIST_FOR_EACH (bucket, list_node, buckets) {
7892 if (bucket->bucket_id == bucket_id) {
7893 return bucket;
7894 }
7895 }
7896
7897 return NULL;
7898}
7899
7900/* Returns true if more than one bucket in the list 'buckets'
7901 * have the same bucket id. Returns false otherwise. */
18ac06d3 7902bool
ca6ba700 7903ofputil_bucket_check_duplicate_id(const struct ovs_list *buckets)
18ac06d3
SH
7904{
7905 struct ofputil_bucket *i, *j;
7906
7907 LIST_FOR_EACH (i, list_node, buckets) {
7908 LIST_FOR_EACH_REVERSE (j, list_node, buckets) {
7909 if (i == j) {
7910 break;
7911 }
7912 if (i->bucket_id == j->bucket_id) {
7913 return true;
7914 }
7915 }
7916 }
7917
7918 return false;
7919}
7920
103b4866
SH
7921/* Returns the bucket at the front of the list 'buckets'.
7922 * Undefined if 'buckets is empty. */
7923struct ofputil_bucket *
ca6ba700 7924ofputil_bucket_list_front(const struct ovs_list *buckets)
103b4866
SH
7925{
7926 static struct ofputil_bucket *bucket;
7927
417e7e66 7928 ASSIGN_CONTAINER(bucket, ovs_list_front(buckets), list_node);
103b4866
SH
7929
7930 return bucket;
7931}
7932
7933/* Returns the bucket at the back of the list 'buckets'.
7934 * Undefined if 'buckets is empty. */
7935struct ofputil_bucket *
ca6ba700 7936ofputil_bucket_list_back(const struct ovs_list *buckets)
103b4866
SH
7937{
7938 static struct ofputil_bucket *bucket;
7939
417e7e66 7940 ASSIGN_CONTAINER(bucket, ovs_list_back(buckets), list_node);
103b4866
SH
7941
7942 return bucket;
7943}
7944
7395c052
NZ
7945/* Returns an OpenFlow group stats request for OpenFlow version 'ofp_version',
7946 * that requests stats for group 'group_id'. (Use OFPG_ALL to request stats
7947 * for all groups.)
7948 *
7949 * Group statistics include packet and byte counts for each group. */
7950struct ofpbuf *
7951ofputil_encode_group_stats_request(enum ofp_version ofp_version,
7952 uint32_t group_id)
7953{
7954 struct ofpbuf *request;
7955
7956 switch (ofp_version) {
7957 case OFP10_VERSION:
7958 ovs_fatal(0, "dump-group-stats needs OpenFlow 1.1 or later "
7959 "(\'-O OpenFlow11\')");
7960 case OFP11_VERSION:
7961 case OFP12_VERSION:
c37c0382 7962 case OFP13_VERSION:
42dccab5 7963 case OFP14_VERSION:
b79d45a1
BP
7964 case OFP15_VERSION:
7965 case OFP16_VERSION: {
7395c052
NZ
7966 struct ofp11_group_stats_request *req;
7967 request = ofpraw_alloc(OFPRAW_OFPST11_GROUP_REQUEST, ofp_version, 0);
7968 req = ofpbuf_put_zeros(request, sizeof *req);
7969 req->group_id = htonl(group_id);
7970 break;
7971 }
7972 default:
428b2edd 7973 OVS_NOT_REACHED();
7395c052
NZ
7974 }
7975
7976 return request;
7977}
7978
bc65c25a
SH
7979void
7980ofputil_uninit_group_desc(struct ofputil_group_desc *gd)
7981{
7982 ofputil_bucket_list_destroy(&gd->buckets);
7983 free(&gd->props.fields);
7984}
7985
19187a71
BP
7986/* Decodes the OpenFlow group description request in 'oh', returning the group
7987 * whose description is requested, or OFPG_ALL if stats for all groups was
7988 * requested. */
7989uint32_t
7990ofputil_decode_group_desc_request(const struct ofp_header *oh)
7991{
0a2869d5
BP
7992 struct ofpbuf request = ofpbuf_const_initializer(oh, ntohs(oh->length));
7993 enum ofpraw raw = ofpraw_pull_assert(&request);
19187a71
BP
7994 if (raw == OFPRAW_OFPST11_GROUP_DESC_REQUEST) {
7995 return OFPG_ALL;
7996 } else if (raw == OFPRAW_OFPST15_GROUP_DESC_REQUEST) {
7997 ovs_be32 *group_id = ofpbuf_pull(&request, sizeof *group_id);
7998 return ntohl(*group_id);
7999 } else {
8000 OVS_NOT_REACHED();
8001 }
8002}
8003
7395c052 8004/* Returns an OpenFlow group description request for OpenFlow version
19187a71
BP
8005 * 'ofp_version', that requests stats for group 'group_id'. Use OFPG_ALL to
8006 * request stats for all groups (OpenFlow 1.4 and earlier always request all
8007 * groups).
7395c052
NZ
8008 *
8009 * Group descriptions include the bucket and action configuration for each
8010 * group. */
8011struct ofpbuf *
19187a71
BP
8012ofputil_encode_group_desc_request(enum ofp_version ofp_version,
8013 uint32_t group_id)
7395c052
NZ
8014{
8015 struct ofpbuf *request;
8016
8017 switch (ofp_version) {
8018 case OFP10_VERSION:
8019 ovs_fatal(0, "dump-groups needs OpenFlow 1.1 or later "
8020 "(\'-O OpenFlow11\')");
8021 case OFP11_VERSION:
8022 case OFP12_VERSION:
c37c0382
AC
8023 case OFP13_VERSION:
8024 case OFP14_VERSION:
19187a71
BP
8025 request = ofpraw_alloc(OFPRAW_OFPST11_GROUP_DESC_REQUEST,
8026 ofp_version, 0);
8027 break;
b79d45a1
BP
8028 case OFP15_VERSION:
8029 case OFP16_VERSION: {
d4d3f33e 8030 struct ofp15_group_desc_request *req;
19187a71
BP
8031 request = ofpraw_alloc(OFPRAW_OFPST15_GROUP_DESC_REQUEST,
8032 ofp_version, 0);
d4d3f33e
MT
8033 req = ofpbuf_put_zeros(request, sizeof *req);
8034 req->group_id = htonl(group_id);
7395c052 8035 break;
d4d3f33e 8036 }
7395c052 8037 default:
428b2edd 8038 OVS_NOT_REACHED();
7395c052
NZ
8039 }
8040
8041 return request;
8042}
8043
dcbe78ad 8044static void
63759e71
AZ
8045ofputil_group_bucket_counters_to_ofp11(const struct ofputil_group_stats *gs,
8046 struct ofp11_bucket_counter bucket_cnts[])
7395c052 8047{
7395c052
NZ
8048 int i;
8049
dcbe78ad
AZ
8050 for (i = 0; i < gs->n_buckets; i++) {
8051 bucket_cnts[i].packet_count = htonll(gs->bucket_stats[i].packet_count);
8052 bucket_cnts[i].byte_count = htonll(gs->bucket_stats[i].byte_count);
7395c052 8053 }
7395c052
NZ
8054}
8055
8056static void
dcbe78ad 8057ofputil_group_stats_to_ofp11(const struct ofputil_group_stats *gs,
63759e71
AZ
8058 struct ofp11_group_stats *gs11, size_t length,
8059 struct ofp11_bucket_counter bucket_cnts[])
7395c052 8060{
63759e71
AZ
8061 memset(gs11, 0, sizeof *gs11);
8062 gs11->length = htons(length);
8063 gs11->group_id = htonl(gs->group_id);
8064 gs11->ref_count = htonl(gs->ref_count);
8065 gs11->packet_count = htonll(gs->packet_count);
8066 gs11->byte_count = htonll(gs->byte_count);
8067 ofputil_group_bucket_counters_to_ofp11(gs, bucket_cnts);
dcbe78ad 8068}
7395c052 8069
dcbe78ad
AZ
8070static void
8071ofputil_group_stats_to_ofp13(const struct ofputil_group_stats *gs,
63759e71
AZ
8072 struct ofp13_group_stats *gs13, size_t length,
8073 struct ofp11_bucket_counter bucket_cnts[])
dcbe78ad 8074{
63759e71 8075 ofputil_group_stats_to_ofp11(gs, &gs13->gs, length, bucket_cnts);
dcbe78ad
AZ
8076 gs13->duration_sec = htonl(gs->duration_sec);
8077 gs13->duration_nsec = htonl(gs->duration_nsec);
63759e71 8078
7395c052
NZ
8079}
8080
dcbe78ad 8081/* Encodes 'gs' properly for the format of the list of group statistics
7395c052
NZ
8082 * replies already begun in 'replies' and appends it to the list. 'replies'
8083 * must have originally been initialized with ofpmp_init(). */
8084void
ca6ba700 8085ofputil_append_group_stats(struct ovs_list *replies,
dcbe78ad 8086 const struct ofputil_group_stats *gs)
7395c052 8087{
63759e71
AZ
8088 size_t bucket_counter_size;
8089 struct ofp11_bucket_counter *bucket_counters;
dcbe78ad 8090 size_t length;
7395c052 8091
63759e71
AZ
8092 bucket_counter_size = gs->n_buckets * sizeof(struct ofp11_bucket_counter);
8093
e28ac5cf 8094 switch (ofpmp_version(replies)) {
7395c052 8095 case OFP11_VERSION:
dcbe78ad 8096 case OFP12_VERSION:{
63759e71 8097 struct ofp11_group_stats *gs11;
dcbe78ad 8098
63759e71
AZ
8099 length = sizeof *gs11 + bucket_counter_size;
8100 gs11 = ofpmp_append(replies, length);
8101 bucket_counters = (struct ofp11_bucket_counter *)(gs11 + 1);
8102 ofputil_group_stats_to_ofp11(gs, gs11, length, bucket_counters);
dcbe78ad
AZ
8103 break;
8104 }
7395c052
NZ
8105
8106 case OFP13_VERSION:
42dccab5 8107 case OFP14_VERSION:
b79d45a1
BP
8108 case OFP15_VERSION:
8109 case OFP16_VERSION: {
63759e71 8110 struct ofp13_group_stats *gs13;
7395c052 8111
63759e71
AZ
8112 length = sizeof *gs13 + bucket_counter_size;
8113 gs13 = ofpmp_append(replies, length);
8114 bucket_counters = (struct ofp11_bucket_counter *)(gs13 + 1);
8115 ofputil_group_stats_to_ofp13(gs, gs13, length, bucket_counters);
dcbe78ad
AZ
8116 break;
8117 }
c37c0382 8118
7395c052
NZ
8119 case OFP10_VERSION:
8120 default:
428b2edd 8121 OVS_NOT_REACHED();
7395c052
NZ
8122 }
8123}
7395c052
NZ
8124/* Returns an OpenFlow group features request for OpenFlow version
8125 * 'ofp_version'. */
8126struct ofpbuf *
8127ofputil_encode_group_features_request(enum ofp_version ofp_version)
8128{
8129 struct ofpbuf *request = NULL;
8130
8131 switch (ofp_version) {
8132 case OFP10_VERSION:
8133 case OFP11_VERSION:
8134 ovs_fatal(0, "dump-group-features needs OpenFlow 1.2 or later "
8135 "(\'-O OpenFlow12\')");
8136 case OFP12_VERSION:
c37c0382
AC
8137 case OFP13_VERSION:
8138 case OFP14_VERSION:
42dccab5 8139 case OFP15_VERSION:
b79d45a1 8140 case OFP16_VERSION:
7395c052 8141 request = ofpraw_alloc(OFPRAW_OFPST12_GROUP_FEATURES_REQUEST,
c37c0382 8142 ofp_version, 0);
7395c052 8143 break;
7395c052 8144 default:
428b2edd 8145 OVS_NOT_REACHED();
7395c052
NZ
8146 }
8147
8148 return request;
8149}
8150
8151/* Returns a OpenFlow message that encodes 'features' properly as a reply to
8152 * group features request 'request'. */
8153struct ofpbuf *
8154ofputil_encode_group_features_reply(
8155 const struct ofputil_group_features *features,
8156 const struct ofp_header *request)
8157{
8158 struct ofp12_group_features_stats *ogf;
8159 struct ofpbuf *reply;
08d1e234 8160 int i;
7395c052
NZ
8161
8162 reply = ofpraw_alloc_xid(OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
8163 request->version, request->xid, 0);
8164 ogf = ofpbuf_put_zeros(reply, sizeof *ogf);
8165 ogf->types = htonl(features->types);
8166 ogf->capabilities = htonl(features->capabilities);
08d1e234
BP
8167 for (i = 0; i < OFPGT12_N_TYPES; i++) {
8168 ogf->max_groups[i] = htonl(features->max_groups[i]);
8169 ogf->actions[i] = ofpact_bitmap_to_openflow(features->ofpacts[i],
8170 request->version);
8171 }
7395c052
NZ
8172
8173 return reply;
8174}
8175
8176/* Decodes group features reply 'oh' into 'features'. */
8177void
8178ofputil_decode_group_features_reply(const struct ofp_header *oh,
8179 struct ofputil_group_features *features)
8180{
8181 const struct ofp12_group_features_stats *ogf = ofpmsg_body(oh);
08d1e234 8182 int i;
7395c052
NZ
8183
8184 features->types = ntohl(ogf->types);
8185 features->capabilities = ntohl(ogf->capabilities);
08d1e234
BP
8186 for (i = 0; i < OFPGT12_N_TYPES; i++) {
8187 features->max_groups[i] = ntohl(ogf->max_groups[i]);
8188 features->ofpacts[i] = ofpact_bitmap_from_openflow(
8189 ogf->actions[i], oh->version);
8190 }
7395c052
NZ
8191}
8192
8193/* Parse a group status request message into a 32 bit OpenFlow 1.1
8194 * group ID and stores the latter in '*group_id'.
8195 * Returns 0 if successful, otherwise an OFPERR_* number. */
8196enum ofperr
8197ofputil_decode_group_stats_request(const struct ofp_header *request,
8198 uint32_t *group_id)
8199{
8200 const struct ofp11_group_stats_request *gsr11 = ofpmsg_body(request);
8201 *group_id = ntohl(gsr11->group_id);
8202 return 0;
8203}
8204
8205/* Converts a group stats reply in 'msg' into an abstract ofputil_group_stats
646b2a9c
SH
8206 * in 'gs'. Assigns freshly allocated memory to gs->bucket_stats for the
8207 * caller to eventually free.
7395c052
NZ
8208 *
8209 * Multiple group stats replies can be packed into a single OpenFlow message.
8210 * Calling this function multiple times for a single 'msg' iterates through the
8211 * replies. The caller must initially leave 'msg''s layer pointers null and
8212 * not modify them between calls.
8213 *
8214 * Returns 0 if successful, EOF if no replies were left in this 'msg',
8215 * otherwise a positive errno value. */
8216int
8217ofputil_decode_group_stats_reply(struct ofpbuf *msg,
8218 struct ofputil_group_stats *gs)
8219{
8220 struct ofp11_bucket_counter *obc;
8221 struct ofp11_group_stats *ogs11;
8222 enum ofpraw raw;
8223 enum ofperr error;
8224 size_t base_len;
8225 size_t length;
8226 size_t i;
8227
646b2a9c 8228 gs->bucket_stats = NULL;
6fd6ed71 8229 error = (msg->header ? ofpraw_decode(&raw, msg->header)
7395c052
NZ
8230 : ofpraw_pull(&raw, msg));
8231 if (error) {
8232 return error;
8233 }
8234
6fd6ed71 8235 if (!msg->size) {
7395c052
NZ
8236 return EOF;
8237 }
8238
8239 if (raw == OFPRAW_OFPST11_GROUP_REPLY) {
8240 base_len = sizeof *ogs11;
8241 ogs11 = ofpbuf_try_pull(msg, sizeof *ogs11);
8242 gs->duration_sec = gs->duration_nsec = UINT32_MAX;
8243 } else if (raw == OFPRAW_OFPST13_GROUP_REPLY) {
8244 struct ofp13_group_stats *ogs13;
8245
8246 base_len = sizeof *ogs13;
8247 ogs13 = ofpbuf_try_pull(msg, sizeof *ogs13);
8248 if (ogs13) {
8249 ogs11 = &ogs13->gs;
8250 gs->duration_sec = ntohl(ogs13->duration_sec);
8251 gs->duration_nsec = ntohl(ogs13->duration_nsec);
8252 } else {
8253 ogs11 = NULL;
8254 }
8255 } else {
428b2edd 8256 OVS_NOT_REACHED();
7395c052
NZ
8257 }
8258
8259 if (!ogs11) {
437d0d22 8260 VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIu32" leftover bytes at end",
6fd6ed71 8261 ofpraw_get_name(raw), msg->size);
7395c052
NZ
8262 return OFPERR_OFPBRC_BAD_LEN;
8263 }
8264 length = ntohs(ogs11->length);
8265 if (length < sizeof base_len) {
34582733 8266 VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply claims invalid length %"PRIuSIZE,
7395c052
NZ
8267 ofpraw_get_name(raw), length);
8268 return OFPERR_OFPBRC_BAD_LEN;
8269 }
8270
8271 gs->group_id = ntohl(ogs11->group_id);
8272 gs->ref_count = ntohl(ogs11->ref_count);
8273 gs->packet_count = ntohll(ogs11->packet_count);
8274 gs->byte_count = ntohll(ogs11->byte_count);
8275
8276 gs->n_buckets = (length - base_len) / sizeof *obc;
8277 obc = ofpbuf_try_pull(msg, gs->n_buckets * sizeof *obc);
8278 if (!obc) {
437d0d22 8279 VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIu32" leftover bytes at end",
6fd6ed71 8280 ofpraw_get_name(raw), msg->size);
7395c052
NZ
8281 return OFPERR_OFPBRC_BAD_LEN;
8282 }
8283
646b2a9c 8284 gs->bucket_stats = xmalloc(gs->n_buckets * sizeof *gs->bucket_stats);
7395c052
NZ
8285 for (i = 0; i < gs->n_buckets; i++) {
8286 gs->bucket_stats[i].packet_count = ntohll(obc[i].packet_count);
8287 gs->bucket_stats[i].byte_count = ntohll(obc[i].byte_count);
8288 }
8289
8290 return 0;
8291}
8292
5097fee5
SH
8293static void
8294ofputil_put_ofp11_bucket(const struct ofputil_bucket *bucket,
8295 struct ofpbuf *openflow, enum ofp_version ofp_version)
8296{
8297 struct ofp11_bucket *ob;
8298 size_t start;
8299
6fd6ed71 8300 start = openflow->size;
5097fee5
SH
8301 ofpbuf_put_zeros(openflow, sizeof *ob);
8302 ofpacts_put_openflow_actions(bucket->ofpacts, bucket->ofpacts_len,
8303 openflow, ofp_version);
8304 ob = ofpbuf_at_assert(openflow, start, sizeof *ob);
6fd6ed71 8305 ob->len = htons(openflow->size - start);
5097fee5
SH
8306 ob->weight = htons(bucket->weight);
8307 ob->watch_port = ofputil_port_to_ofp11(bucket->watch_port);
8308 ob->watch_group = htonl(bucket->watch_group);
8309}
8310
18ac06d3
SH
8311static void
8312ofputil_put_ofp15_bucket(const struct ofputil_bucket *bucket,
8313 uint32_t bucket_id, enum ofp11_group_type group_type,
8314 struct ofpbuf *openflow, enum ofp_version ofp_version)
8315{
8316 struct ofp15_bucket *ob;
8317 size_t start, actions_start, actions_len;
8318
6fd6ed71 8319 start = openflow->size;
18ac06d3
SH
8320 ofpbuf_put_zeros(openflow, sizeof *ob);
8321
6fd6ed71 8322 actions_start = openflow->size;
18ac06d3
SH
8323 ofpacts_put_openflow_actions(bucket->ofpacts, bucket->ofpacts_len,
8324 openflow, ofp_version);
6fd6ed71 8325 actions_len = openflow->size - actions_start;
18ac06d3
SH
8326
8327 if (group_type == OFPGT11_SELECT) {
b611d3ac 8328 ofpprop_put_u16(openflow, OFPGBPT15_WEIGHT, bucket->weight);
18ac06d3
SH
8329 }
8330 if (bucket->watch_port != OFPP_ANY) {
b611d3ac
BP
8331 ofpprop_put_be32(openflow, OFPGBPT15_WATCH_PORT,
8332 ofputil_port_to_ofp11(bucket->watch_port));
18ac06d3
SH
8333 }
8334 if (bucket->watch_group != OFPG_ANY) {
b611d3ac 8335 ofpprop_put_u32(openflow, OFPGBPT15_WATCH_GROUP, bucket->watch_group);
18ac06d3
SH
8336 }
8337
8338 ob = ofpbuf_at_assert(openflow, start, sizeof *ob);
6fd6ed71 8339 ob->len = htons(openflow->size - start);
79870963 8340 ob->action_array_len = htons(actions_len);
18ac06d3
SH
8341 ob->bucket_id = htonl(bucket_id);
8342}
8343
53eb84a5
SH
8344static void
8345ofputil_put_group_prop_ntr_selection_method(enum ofp_version ofp_version,
8346 const struct ofputil_group_props *gp,
8347 struct ofpbuf *openflow)
8348{
8349 struct ntr_group_prop_selection_method *prop;
8350 size_t start;
8351
8352 start = openflow->size;
8353 ofpbuf_put_zeros(openflow, sizeof *prop);
8354 oxm_put_field_array(openflow, &gp->fields, ofp_version);
8355 prop = ofpbuf_at_assert(openflow, start, sizeof *prop);
8356 prop->type = htons(OFPGPT15_EXPERIMENTER);
8357 prop->experimenter = htonl(NTR_VENDOR_ID);
8358 prop->exp_type = htonl(NTRT_SELECTION_METHOD);
8359 strcpy(prop->selection_method, gp->selection_method);
8360 prop->selection_method_param = htonll(gp->selection_method_param);
c5562271 8361 ofpprop_end(openflow, start);
53eb84a5
SH
8362}
8363
5be50252
SH
8364static void
8365ofputil_append_ofp11_group_desc_reply(const struct ofputil_group_desc *gds,
1667bb34 8366 const struct ovs_list *buckets,
ca6ba700 8367 struct ovs_list *replies,
5be50252 8368 enum ofp_version version)
7395c052 8369{
417e7e66 8370 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
7395c052
NZ
8371 struct ofp11_group_desc_stats *ogds;
8372 struct ofputil_bucket *bucket;
8373 size_t start_ogds;
8374
6fd6ed71 8375 start_ogds = reply->size;
7395c052
NZ
8376 ofpbuf_put_zeros(reply, sizeof *ogds);
8377 LIST_FOR_EACH (bucket, list_node, buckets) {
5097fee5 8378 ofputil_put_ofp11_bucket(bucket, reply, version);
7395c052
NZ
8379 }
8380 ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
6fd6ed71 8381 ogds->length = htons(reply->size - start_ogds);
7395c052
NZ
8382 ogds->type = gds->type;
8383 ogds->group_id = htonl(gds->group_id);
8384
8385 ofpmp_postappend(replies, start_ogds);
8386}
8387
18ac06d3
SH
8388static void
8389ofputil_append_ofp15_group_desc_reply(const struct ofputil_group_desc *gds,
1667bb34 8390 const struct ovs_list *buckets,
ca6ba700 8391 struct ovs_list *replies,
18ac06d3
SH
8392 enum ofp_version version)
8393{
417e7e66 8394 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
18ac06d3
SH
8395 struct ofp15_group_desc_stats *ogds;
8396 struct ofputil_bucket *bucket;
8397 size_t start_ogds, start_buckets;
8398
6fd6ed71 8399 start_ogds = reply->size;
18ac06d3 8400 ofpbuf_put_zeros(reply, sizeof *ogds);
6fd6ed71 8401 start_buckets = reply->size;
18ac06d3
SH
8402 LIST_FOR_EACH (bucket, list_node, buckets) {
8403 ofputil_put_ofp15_bucket(bucket, bucket->bucket_id,
8404 gds->type, reply, version);
8405 }
8406 ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
18ac06d3
SH
8407 ogds->type = gds->type;
8408 ogds->group_id = htonl(gds->group_id);
6fd6ed71 8409 ogds->bucket_list_len = htons(reply->size - start_buckets);
18ac06d3 8410
53eb84a5
SH
8411 /* Add group properties */
8412 if (gds->props.selection_method[0]) {
8413 ofputil_put_group_prop_ntr_selection_method(version, &gds->props,
8414 reply);
8415 }
ef5774e3 8416 ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
3986cae6 8417 ogds->length = htons(reply->size - start_ogds);
53eb84a5 8418
18ac06d3
SH
8419 ofpmp_postappend(replies, start_ogds);
8420}
8421
5be50252
SH
8422/* Appends a group stats reply that contains the data in 'gds' to those already
8423 * present in the list of ofpbufs in 'replies'. 'replies' should have been
8424 * initialized with ofpmp_init(). */
8425void
8426ofputil_append_group_desc_reply(const struct ofputil_group_desc *gds,
1667bb34 8427 const struct ovs_list *buckets,
ca6ba700 8428 struct ovs_list *replies)
5be50252
SH
8429{
8430 enum ofp_version version = ofpmp_version(replies);
8431
8432 switch (version)
8433 {
8434 case OFP11_VERSION:
8435 case OFP12_VERSION:
8436 case OFP13_VERSION:
8437 case OFP14_VERSION:
5be50252
SH
8438 ofputil_append_ofp11_group_desc_reply(gds, buckets, replies, version);
8439 break;
8440
18ac06d3 8441 case OFP15_VERSION:
b79d45a1 8442 case OFP16_VERSION:
18ac06d3
SH
8443 ofputil_append_ofp15_group_desc_reply(gds, buckets, replies, version);
8444 break;
8445
5be50252
SH
8446 case OFP10_VERSION:
8447 default:
8448 OVS_NOT_REACHED();
8449 }
8450}
8451
7395c052 8452static enum ofperr
655ed3ae 8453ofputil_pull_ofp11_buckets(struct ofpbuf *msg, size_t buckets_length,
ca6ba700 8454 enum ofp_version version, struct ovs_list *buckets)
7395c052
NZ
8455{
8456 struct ofp11_bucket *ob;
18ac06d3 8457 uint32_t bucket_id = 0;
7395c052 8458
417e7e66 8459 ovs_list_init(buckets);
7395c052
NZ
8460 while (buckets_length > 0) {
8461 struct ofputil_bucket *bucket;
8462 struct ofpbuf ofpacts;
8463 enum ofperr error;
8464 size_t ob_len;
8465
8466 ob = (buckets_length >= sizeof *ob
8467 ? ofpbuf_try_pull(msg, sizeof *ob)
8468 : NULL);
8469 if (!ob) {
34582733 8470 VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %"PRIuSIZE" leftover bytes",
7395c052 8471 buckets_length);
e27e4ce9 8472 return OFPERR_OFPGMFC_BAD_BUCKET;
7395c052
NZ
8473 }
8474
8475 ob_len = ntohs(ob->len);
8476 if (ob_len < sizeof *ob) {
8477 VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
34582733 8478 "%"PRIuSIZE" is not valid", ob_len);
7395c052
NZ
8479 return OFPERR_OFPGMFC_BAD_BUCKET;
8480 } else if (ob_len > buckets_length) {
8481 VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
34582733 8482 "%"PRIuSIZE" exceeds remaining buckets data size %"PRIuSIZE,
7395c052
NZ
8483 ob_len, buckets_length);
8484 return OFPERR_OFPGMFC_BAD_BUCKET;
8485 }
8486 buckets_length -= ob_len;
8487
8488 ofpbuf_init(&ofpacts, 0);
e3f8f887
JR
8489 error = ofpacts_pull_openflow_actions(msg, ob_len - sizeof *ob,
8490 version, &ofpacts);
7395c052
NZ
8491 if (error) {
8492 ofpbuf_uninit(&ofpacts);
8493 ofputil_bucket_list_destroy(buckets);
8494 return error;
8495 }
8496
8497 bucket = xzalloc(sizeof *bucket);
8498 bucket->weight = ntohs(ob->weight);
8499 error = ofputil_port_from_ofp11(ob->watch_port, &bucket->watch_port);
8500 if (error) {
8501 ofpbuf_uninit(&ofpacts);
8502 ofputil_bucket_list_destroy(buckets);
8503 return OFPERR_OFPGMFC_BAD_WATCH;
8504 }
8505 bucket->watch_group = ntohl(ob->watch_group);
18ac06d3
SH
8506 bucket->bucket_id = bucket_id++;
8507
7395c052 8508 bucket->ofpacts = ofpbuf_steal_data(&ofpacts);
6fd6ed71 8509 bucket->ofpacts_len = ofpacts.size;
417e7e66 8510 ovs_list_push_back(buckets, &bucket->list_node);
7395c052
NZ
8511 }
8512
8513 return 0;
8514}
8515
18ac06d3
SH
8516static enum ofperr
8517ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length,
64e8c446
BP
8518 enum ofp_version version, uint8_t group_type,
8519 struct ovs_list *buckets)
18ac06d3
SH
8520{
8521 struct ofp15_bucket *ob;
8522
417e7e66 8523 ovs_list_init(buckets);
18ac06d3
SH
8524 while (buckets_length > 0) {
8525 struct ofputil_bucket *bucket = NULL;
8526 struct ofpbuf ofpacts;
8527 enum ofperr err = OFPERR_OFPGMFC_BAD_BUCKET;
18ac06d3
SH
8528 size_t ob_len, actions_len, properties_len;
8529 ovs_be32 watch_port = ofputil_port_to_ofp11(OFPP_ANY);
8530 ovs_be32 watch_group = htonl(OFPG_ANY);
64e8c446 8531 ovs_be16 weight = htons(group_type == OFPGT11_SELECT ? 1 : 0);
18ac06d3
SH
8532
8533 ofpbuf_init(&ofpacts, 0);
8534
8535 ob = ofpbuf_try_pull(msg, sizeof *ob);
8536 if (!ob) {
8537 VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %"PRIuSIZE
8538 " leftover bytes", buckets_length);
8539 goto err;
8540 }
8541
8542 ob_len = ntohs(ob->len);
79870963 8543 actions_len = ntohs(ob->action_array_len);
18ac06d3
SH
8544
8545 if (ob_len < sizeof *ob) {
8546 VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
8547 "%"PRIuSIZE" is not valid", ob_len);
8548 goto err;
8549 } else if (ob_len > buckets_length) {
8550 VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length "
8551 "%"PRIuSIZE" exceeds remaining buckets data size %"
8552 PRIuSIZE, ob_len, buckets_length);
8553 goto err;
8554 } else if (actions_len > ob_len - sizeof *ob) {
8555 VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket actions "
8556 "length %"PRIuSIZE" exceeds remaining bucket "
8557 "data size %"PRIuSIZE, actions_len,
8558 ob_len - sizeof *ob);
8559 goto err;
8560 }
8561 buckets_length -= ob_len;
8562
8563 err = ofpacts_pull_openflow_actions(msg, actions_len, version,
8564 &ofpacts);
8565 if (err) {
8566 goto err;
8567 }
8568
8569 properties_len = ob_len - sizeof *ob - actions_len;
0a2869d5
BP
8570 struct ofpbuf properties = ofpbuf_const_initializer(
8571 ofpbuf_pull(msg, properties_len), properties_len);
6fd6ed71 8572 while (properties.size > 0) {
18ac06d3 8573 struct ofpbuf payload;
34a543e3 8574 uint64_t type;
18ac06d3 8575
c5562271 8576 err = ofpprop_pull(&properties, &payload, &type);
18ac06d3
SH
8577 if (err) {
8578 goto err;
8579 }
8580
8581 switch (type) {
8582 case OFPGBPT15_WEIGHT:
b611d3ac 8583 err = ofpprop_parse_be16(&payload, &weight);
18ac06d3
SH
8584 break;
8585
8586 case OFPGBPT15_WATCH_PORT:
b611d3ac 8587 err = ofpprop_parse_be32(&payload, &watch_port);
18ac06d3
SH
8588 break;
8589
8590 case OFPGBPT15_WATCH_GROUP:
b611d3ac 8591 err = ofpprop_parse_be32(&payload, &watch_group);
18ac06d3
SH
8592 break;
8593
8594 default:
34a543e3 8595 err = OFPPROP_UNKNOWN(false, "group bucket", type);
18ac06d3
SH
8596 break;
8597 }
8598
8599 if (err) {
8600 goto err;
8601 }
8602 }
8603
8604 bucket = xzalloc(sizeof *bucket);
8605
8606 bucket->weight = ntohs(weight);
8607 err = ofputil_port_from_ofp11(watch_port, &bucket->watch_port);
8608 if (err) {
8609 err = OFPERR_OFPGMFC_BAD_WATCH;
8610 goto err;
8611 }
8612 bucket->watch_group = ntohl(watch_group);
8613 bucket->bucket_id = ntohl(ob->bucket_id);
8614 if (bucket->bucket_id > OFPG15_BUCKET_MAX) {
8615 VLOG_WARN_RL(&bad_ofmsg_rl, "bucket id (%u) is out of range",
8616 bucket->bucket_id);
8617 err = OFPERR_OFPGMFC_BAD_BUCKET;
8618 goto err;
8619 }
8620
8621 bucket->ofpacts = ofpbuf_steal_data(&ofpacts);
6fd6ed71 8622 bucket->ofpacts_len = ofpacts.size;
417e7e66 8623 ovs_list_push_back(buckets, &bucket->list_node);
18ac06d3
SH
8624
8625 continue;
8626
8627 err:
8628 free(bucket);
8629 ofpbuf_uninit(&ofpacts);
8630 ofputil_bucket_list_destroy(buckets);
8631 return err;
8632 }
8633
8634 if (ofputil_bucket_check_duplicate_id(buckets)) {
8635 VLOG_WARN_RL(&bad_ofmsg_rl, "Duplicate bucket id");
8636 ofputil_bucket_list_destroy(buckets);
8637 return OFPERR_OFPGMFC_BAD_BUCKET;
8638 }
8639
8640 return 0;
8641}
8642
bc65c25a
SH
8643static void
8644ofputil_init_group_properties(struct ofputil_group_props *gp)
8645{
8646 memset(gp, 0, sizeof *gp);
8647}
8648
8649static enum ofperr
8650parse_group_prop_ntr_selection_method(struct ofpbuf *payload,
8651 enum ofp11_group_type group_type,
8652 enum ofp15_group_mod_command group_cmd,
8653 struct ofputil_group_props *gp)
8654{
8655 struct ntr_group_prop_selection_method *prop = payload->data;
8656 size_t fields_len, method_len;
8657 enum ofperr error;
8658
8659 switch (group_type) {
8660 case OFPGT11_SELECT:
8661 break;
8662 case OFPGT11_ALL:
8663 case OFPGT11_INDIRECT:
8664 case OFPGT11_FF:
c5562271
BP
8665 OFPPROP_LOG(&bad_ofmsg_rl, false, "ntr selection method property is "
8666 "only allowed for select groups");
bc65c25a
SH
8667 return OFPERR_OFPBPC_BAD_VALUE;
8668 default:
8669 OVS_NOT_REACHED();
8670 }
8671
8672 switch (group_cmd) {
8673 case OFPGC15_ADD:
8674 case OFPGC15_MODIFY:
8675 break;
8676 case OFPGC15_DELETE:
8677 case OFPGC15_INSERT_BUCKET:
8678 case OFPGC15_REMOVE_BUCKET:
c5562271
BP
8679 OFPPROP_LOG(&bad_ofmsg_rl, false, "ntr selection method property is "
8680 "only allowed for add and delete group modifications");
bc65c25a
SH
8681 return OFPERR_OFPBPC_BAD_VALUE;
8682 default:
8683 OVS_NOT_REACHED();
8684 }
8685
8686 if (payload->size < sizeof *prop) {
c5562271
BP
8687 OFPPROP_LOG(&bad_ofmsg_rl, false, "ntr selection method property "
8688 "length %u is not valid", payload->size);
bc65c25a
SH
8689 return OFPERR_OFPBPC_BAD_LEN;
8690 }
8691
8692 method_len = strnlen(prop->selection_method, NTR_MAX_SELECTION_METHOD_LEN);
8693
8694 if (method_len == NTR_MAX_SELECTION_METHOD_LEN) {
c5562271
BP
8695 OFPPROP_LOG(&bad_ofmsg_rl, false,
8696 "ntr selection method is not null terminated");
bc65c25a
SH
8697 return OFPERR_OFPBPC_BAD_VALUE;
8698 }
8699
0c4b9393 8700 if (strcmp("hash", prop->selection_method)) {
c5562271
BP
8701 OFPPROP_LOG(&bad_ofmsg_rl, false,
8702 "ntr selection method '%s' is not supported",
8703 prop->selection_method);
0c4b9393
SH
8704 return OFPERR_OFPBPC_BAD_VALUE;
8705 }
bc65c25a
SH
8706
8707 strcpy(gp->selection_method, prop->selection_method);
8708 gp->selection_method_param = ntohll(prop->selection_method_param);
8709
8710 if (!method_len && gp->selection_method_param) {
c5562271
BP
8711 OFPPROP_LOG(&bad_ofmsg_rl, false, "ntr selection method parameter is "
8712 "non-zero but selection method is empty");
bc65c25a
SH
8713 return OFPERR_OFPBPC_BAD_VALUE;
8714 }
8715
8716 ofpbuf_pull(payload, sizeof *prop);
8717
8718 fields_len = ntohs(prop->length) - sizeof *prop;
8719 if (!method_len && fields_len) {
c5562271
BP
8720 OFPPROP_LOG(&bad_ofmsg_rl, false, "ntr selection method parameter is "
8721 "zero but fields are provided");
bc65c25a
SH
8722 return OFPERR_OFPBPC_BAD_VALUE;
8723 }
8724
8725 error = oxm_pull_field_array(payload->data, fields_len,
8726 &gp->fields);
8727 if (error) {
c5562271
BP
8728 OFPPROP_LOG(&bad_ofmsg_rl, false,
8729 "ntr selection method fields are invalid");
bc65c25a
SH
8730 return error;
8731 }
8732
8733 return 0;
8734}
8735
bc65c25a
SH
8736static enum ofperr
8737parse_ofp15_group_properties(struct ofpbuf *msg,
8738 enum ofp11_group_type group_type,
8739 enum ofp15_group_mod_command group_cmd,
8740 struct ofputil_group_props *gp,
8741 size_t properties_len)
8742{
0a2869d5
BP
8743 struct ofpbuf properties = ofpbuf_const_initializer(
8744 ofpbuf_pull(msg, properties_len), properties_len);
bc65c25a
SH
8745 while (properties.size > 0) {
8746 struct ofpbuf payload;
8747 enum ofperr error;
34a543e3 8748 uint64_t type;
bc65c25a 8749
c5562271 8750 error = ofpprop_pull(&properties, &payload, &type);
bc65c25a
SH
8751 if (error) {
8752 return error;
8753 }
8754
8755 switch (type) {
34a543e3
BP
8756 case OFPPROP_EXP(NTR_VENDOR_ID, NTRT_SELECTION_METHOD):
8757 case OFPPROP_EXP(NTR_COMPAT_VENDOR_ID, NTRT_SELECTION_METHOD):
8758 error = parse_group_prop_ntr_selection_method(&payload, group_type,
8759 group_cmd, gp);
bc65c25a
SH
8760 break;
8761
8762 default:
34a543e3 8763 error = OFPPROP_UNKNOWN(false, "group", type);
bc65c25a
SH
8764 break;
8765 }
8766
8767 if (error) {
8768 return error;
8769 }
8770 }
8771
8772 return 0;
8773}
8774
975910f2
SH
8775static int
8776ofputil_decode_ofp11_group_desc_reply(struct ofputil_group_desc *gd,
8777 struct ofpbuf *msg,
8778 enum ofp_version version)
7395c052
NZ
8779{
8780 struct ofp11_group_desc_stats *ogds;
8781 size_t length;
8782
6fd6ed71 8783 if (!msg->header) {
7395c052
NZ
8784 ofpraw_pull_assert(msg);
8785 }
8786
6fd6ed71 8787 if (!msg->size) {
7395c052
NZ
8788 return EOF;
8789 }
8790
8791 ogds = ofpbuf_try_pull(msg, sizeof *ogds);
8792 if (!ogds) {
437d0d22 8793 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIu32" "
6fd6ed71 8794 "leftover bytes at end", msg->size);
7395c052
NZ
8795 return OFPERR_OFPBRC_BAD_LEN;
8796 }
8797 gd->type = ogds->type;
8798 gd->group_id = ntohl(ogds->group_id);
8799
8800 length = ntohs(ogds->length);
6fd6ed71 8801 if (length < sizeof *ogds || length - sizeof *ogds > msg->size) {
7395c052 8802 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid "
34582733 8803 "length %"PRIuSIZE, length);
7395c052
NZ
8804 return OFPERR_OFPBRC_BAD_LEN;
8805 }
8806
655ed3ae
SH
8807 return ofputil_pull_ofp11_buckets(msg, length - sizeof *ogds, version,
8808 &gd->buckets);
7395c052
NZ
8809}
8810
18ac06d3
SH
8811static int
8812ofputil_decode_ofp15_group_desc_reply(struct ofputil_group_desc *gd,
8813 struct ofpbuf *msg,
8814 enum ofp_version version)
8815{
8816 struct ofp15_group_desc_stats *ogds;
8817 uint16_t length, bucket_list_len;
bc65c25a 8818 int error;
18ac06d3 8819
6fd6ed71 8820 if (!msg->header) {
18ac06d3
SH
8821 ofpraw_pull_assert(msg);
8822 }
8823
6fd6ed71 8824 if (!msg->size) {
18ac06d3
SH
8825 return EOF;
8826 }
8827
8828 ogds = ofpbuf_try_pull(msg, sizeof *ogds);
8829 if (!ogds) {
8830 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIu32" "
6fd6ed71 8831 "leftover bytes at end", msg->size);
18ac06d3
SH
8832 return OFPERR_OFPBRC_BAD_LEN;
8833 }
8834 gd->type = ogds->type;
8835 gd->group_id = ntohl(ogds->group_id);
8836
8837 length = ntohs(ogds->length);
6fd6ed71 8838 if (length < sizeof *ogds || length - sizeof *ogds > msg->size) {
18ac06d3
SH
8839 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid "
8840 "length %u", length);
8841 return OFPERR_OFPBRC_BAD_LEN;
8842 }
8843
8844 bucket_list_len = ntohs(ogds->bucket_list_len);
8845 if (length < bucket_list_len + sizeof *ogds) {
8846 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid "
8847 "bucket list length %u", bucket_list_len);
8848 return OFPERR_OFPBRC_BAD_LEN;
8849 }
64e8c446 8850 error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, version, gd->type,
bc65c25a
SH
8851 &gd->buckets);
8852 if (error) {
8853 return error;
8854 }
18ac06d3 8855
bc65c25a
SH
8856 /* By definition group desc messages don't have a group mod command.
8857 * However, parse_group_prop_ntr_selection_method() checks to make sure
8858 * that the command is OFPGC15_ADD or OFPGC15_DELETE to guard
8859 * against group mod messages with other commands supplying
8860 * a NTR selection method group experimenter property.
8861 * Such properties are valid for group desc replies so
8862 * claim that the group mod command is OFPGC15_ADD to
8863 * satisfy the check in parse_group_prop_ntr_selection_method() */
8864 return parse_ofp15_group_properties(msg, gd->type, OFPGC15_ADD, &gd->props,
3986cae6 8865 length - sizeof *ogds - bucket_list_len);
18ac06d3
SH
8866}
8867
975910f2
SH
8868/* Converts a group description reply in 'msg' into an abstract
8869 * ofputil_group_desc in 'gd'.
8870 *
8871 * Multiple group description replies can be packed into a single OpenFlow
8872 * message. Calling this function multiple times for a single 'msg' iterates
8873 * through the replies. The caller must initially leave 'msg''s layer pointers
8874 * null and not modify them between calls.
8875 *
8876 * Returns 0 if successful, EOF if no replies were left in this 'msg',
8877 * otherwise a positive errno value. */
8878int
8879ofputil_decode_group_desc_reply(struct ofputil_group_desc *gd,
8880 struct ofpbuf *msg, enum ofp_version version)
8881{
bc65c25a
SH
8882 ofputil_init_group_properties(&gd->props);
8883
975910f2
SH
8884 switch (version)
8885 {
8886 case OFP11_VERSION:
8887 case OFP12_VERSION:
8888 case OFP13_VERSION:
8889 case OFP14_VERSION:
975910f2
SH
8890 return ofputil_decode_ofp11_group_desc_reply(gd, msg, version);
8891
18ac06d3 8892 case OFP15_VERSION:
b79d45a1 8893 case OFP16_VERSION:
18ac06d3
SH
8894 return ofputil_decode_ofp15_group_desc_reply(gd, msg, version);
8895
975910f2
SH
8896 case OFP10_VERSION:
8897 default:
8898 OVS_NOT_REACHED();
8899 }
8900}
8901
bc65c25a
SH
8902void
8903ofputil_uninit_group_mod(struct ofputil_group_mod *gm)
8904{
8905 ofputil_bucket_list_destroy(&gm->buckets);
8906}
8907
4498bea5
SH
8908static struct ofpbuf *
8909ofputil_encode_ofp11_group_mod(enum ofp_version ofp_version,
8910 const struct ofputil_group_mod *gm)
7395c052
NZ
8911{
8912 struct ofpbuf *b;
8913 struct ofp11_group_mod *ogm;
8914 size_t start_ogm;
7395c052 8915 struct ofputil_bucket *bucket;
7395c052 8916
4498bea5 8917 b = ofpraw_alloc(OFPRAW_OFPT11_GROUP_MOD, ofp_version, 0);
6fd6ed71 8918 start_ogm = b->size;
4498bea5
SH
8919 ofpbuf_put_zeros(b, sizeof *ogm);
8920
8921 LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
8922 ofputil_put_ofp11_bucket(bucket, b, ofp_version);
8923 }
8924 ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm);
8925 ogm->command = htons(gm->command);
8926 ogm->type = gm->type;
8927 ogm->group_id = htonl(gm->group_id);
8928
8929 return b;
8930}
8931
18ac06d3
SH
8932static struct ofpbuf *
8933ofputil_encode_ofp15_group_mod(enum ofp_version ofp_version,
8934 const struct ofputil_group_mod *gm)
8935{
8936 struct ofpbuf *b;
8937 struct ofp15_group_mod *ogm;
8938 size_t start_ogm;
8939 struct ofputil_bucket *bucket;
8940 struct id_pool *bucket_ids = NULL;
8941
8942 b = ofpraw_alloc(OFPRAW_OFPT15_GROUP_MOD, ofp_version, 0);
6fd6ed71 8943 start_ogm = b->size;
18ac06d3
SH
8944 ofpbuf_put_zeros(b, sizeof *ogm);
8945
8946 LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
8947 uint32_t bucket_id;
8948
8949 /* Generate a bucket id if none was supplied */
8950 if (bucket->bucket_id > OFPG15_BUCKET_MAX) {
8951 if (!bucket_ids) {
8952 const struct ofputil_bucket *bkt;
8953
8954 bucket_ids = id_pool_create(0, OFPG15_BUCKET_MAX + 1);
8955
8956 /* Mark all bucket_ids that are present in gm
8957 * as used in the pool. */
8958 LIST_FOR_EACH_REVERSE (bkt, list_node, &gm->buckets) {
8959 if (bkt == bucket) {
8960 break;
8961 }
8962 if (bkt->bucket_id <= OFPG15_BUCKET_MAX) {
8963 id_pool_add(bucket_ids, bkt->bucket_id);
8964 }
8965 }
8966 }
8967
8968 if (!id_pool_alloc_id(bucket_ids, &bucket_id)) {
8969 OVS_NOT_REACHED();
8970 }
8971 } else {
8972 bucket_id = bucket->bucket_id;
8973 }
8974
8975 ofputil_put_ofp15_bucket(bucket, bucket_id, gm->type, b, ofp_version);
8976 }
8977 ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm);
8978 ogm->command = htons(gm->command);
8979 ogm->type = gm->type;
8980 ogm->group_id = htonl(gm->group_id);
8981 ogm->command_bucket_id = htonl(gm->command_bucket_id);
6fd6ed71 8982 ogm->bucket_array_len = htons(b->size - start_ogm - sizeof *ogm);
18ac06d3 8983
53eb84a5
SH
8984 /* Add group properties */
8985 if (gm->props.selection_method[0]) {
8986 ofputil_put_group_prop_ntr_selection_method(ofp_version, &gm->props, b);
8987 }
8988
18ac06d3
SH
8989 id_pool_destroy(bucket_ids);
8990 return b;
8991}
8992
d4b1d0ca 8993static void
9dd30b05
BP
8994bad_group_cmd(enum ofp15_group_mod_command cmd)
8995{
d4b1d0ca
SH
8996 const char *opt_version;
8997 const char *version;
8998 const char *cmd_str;
8999
9000 switch (cmd) {
9001 case OFPGC15_ADD:
9002 case OFPGC15_MODIFY:
9003 case OFPGC15_DELETE:
9004 version = "1.1";
9005 opt_version = "11";
9006 break;
9007
9008 case OFPGC15_INSERT_BUCKET:
9009 case OFPGC15_REMOVE_BUCKET:
9010 version = "1.5";
9011 opt_version = "15";
9dd30b05 9012 break;
d4b1d0ca
SH
9013
9014 default:
9015 OVS_NOT_REACHED();
9016 }
9017
9018 switch (cmd) {
9019 case OFPGC15_ADD:
9020 cmd_str = "add-group";
9021 break;
9022
9023 case OFPGC15_MODIFY:
9024 cmd_str = "mod-group";
9025 break;
9026
9027 case OFPGC15_DELETE:
9028 cmd_str = "del-group";
9029 break;
9030
9031 case OFPGC15_INSERT_BUCKET:
9032 cmd_str = "insert-bucket";
9033 break;
9034
9035 case OFPGC15_REMOVE_BUCKET:
9dd30b05 9036 cmd_str = "remove-bucket";
d4b1d0ca
SH
9037 break;
9038
9039 default:
9040 OVS_NOT_REACHED();
9041 }
9042
9043 ovs_fatal(0, "%s needs OpenFlow %s or later (\'-O OpenFlow%s\')",
9044 cmd_str, version, opt_version);
9045
9046}
9047
4498bea5
SH
9048/* Converts abstract group mod 'gm' into a message for OpenFlow version
9049 * 'ofp_version' and returns the message. */
9050struct ofpbuf *
9051ofputil_encode_group_mod(enum ofp_version ofp_version,
9052 const struct ofputil_group_mod *gm)
9053{
d4b1d0ca 9054
7395c052 9055 switch (ofp_version) {
d4b1d0ca
SH
9056 case OFP10_VERSION:
9057 bad_group_cmd(gm->command);
7395c052
NZ
9058
9059 case OFP11_VERSION:
9060 case OFP12_VERSION:
c37c0382
AC
9061 case OFP13_VERSION:
9062 case OFP14_VERSION:
d4b1d0ca
SH
9063 if (gm->command > OFPGC11_DELETE) {
9064 bad_group_cmd(gm->command);
9065 }
4498bea5 9066 return ofputil_encode_ofp11_group_mod(ofp_version, gm);
7395c052 9067
18ac06d3 9068 case OFP15_VERSION:
b79d45a1 9069 case OFP16_VERSION:
18ac06d3
SH
9070 return ofputil_encode_ofp15_group_mod(ofp_version, gm);
9071
7395c052 9072 default:
428b2edd 9073 OVS_NOT_REACHED();
7395c052 9074 }
7395c052
NZ
9075}
9076
aead63f2
SH
9077static enum ofperr
9078ofputil_pull_ofp11_group_mod(struct ofpbuf *msg, enum ofp_version ofp_version,
9079 struct ofputil_group_mod *gm)
9080{
9081 const struct ofp11_group_mod *ogm;
08ba0810 9082 enum ofperr error;
aead63f2
SH
9083
9084 ogm = ofpbuf_pull(msg, sizeof *ogm);
9085 gm->command = ntohs(ogm->command);
9086 gm->type = ogm->type;
9087 gm->group_id = ntohl(ogm->group_id);
18ac06d3 9088 gm->command_bucket_id = OFPG15_BUCKET_ALL;
aead63f2 9089
6fd6ed71 9090 error = ofputil_pull_ofp11_buckets(msg, msg->size, ofp_version,
08ba0810
BP
9091 &gm->buckets);
9092
9093 /* OF1.3.5+ prescribes an error when an OFPGC_DELETE includes buckets. */
9094 if (!error
9095 && ofp_version >= OFP13_VERSION
9096 && gm->command == OFPGC11_DELETE
417e7e66 9097 && !ovs_list_is_empty(&gm->buckets)) {
08ba0810
BP
9098 error = OFPERR_OFPGMFC_INVALID_GROUP;
9099 }
9100
9101 return error;
aead63f2
SH
9102}
9103
18ac06d3
SH
9104static enum ofperr
9105ofputil_pull_ofp15_group_mod(struct ofpbuf *msg, enum ofp_version ofp_version,
9106 struct ofputil_group_mod *gm)
9107{
9108 const struct ofp15_group_mod *ogm;
9109 uint16_t bucket_list_len;
9110 enum ofperr error = OFPERR_OFPGMFC_BAD_BUCKET;
9111
9112 ogm = ofpbuf_pull(msg, sizeof *ogm);
9113 gm->command = ntohs(ogm->command);
9114 gm->type = ogm->type;
9115 gm->group_id = ntohl(ogm->group_id);
9116
9117 gm->command_bucket_id = ntohl(ogm->command_bucket_id);
9118 switch (gm->command) {
9119 case OFPGC15_REMOVE_BUCKET:
9120 if (gm->command_bucket_id == OFPG15_BUCKET_ALL) {
9121 error = 0;
9122 }
9123 /* Fall through */
9124 case OFPGC15_INSERT_BUCKET:
9125 if (gm->command_bucket_id <= OFPG15_BUCKET_MAX ||
9126 gm->command_bucket_id == OFPG15_BUCKET_FIRST
9127 || gm->command_bucket_id == OFPG15_BUCKET_LAST) {
9128 error = 0;
9129 }
9130 break;
9131
9132 case OFPGC11_ADD:
9133 case OFPGC11_MODIFY:
9134 case OFPGC11_DELETE:
9135 default:
9136 if (gm->command_bucket_id == OFPG15_BUCKET_ALL) {
9137 error = 0;
9138 }
9139 break;
9140 }
9141 if (error) {
9142 VLOG_WARN_RL(&bad_ofmsg_rl,
9143 "group command bucket id (%u) is out of range",
9144 gm->command_bucket_id);
9145 return OFPERR_OFPGMFC_BAD_BUCKET;
9146 }
9147
79870963 9148 bucket_list_len = ntohs(ogm->bucket_array_len);
bc65c25a 9149 error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, ofp_version,
64e8c446 9150 gm->type, &gm->buckets);
bc65c25a
SH
9151 if (error) {
9152 return error;
18ac06d3
SH
9153 }
9154
bc65c25a
SH
9155 return parse_ofp15_group_properties(msg, gm->type, gm->command, &gm->props,
9156 msg->size);
18ac06d3
SH
9157}
9158
7395c052
NZ
9159/* Converts OpenFlow group mod message 'oh' into an abstract group mod in
9160 * 'gm'. Returns 0 if successful, otherwise an OpenFlow error code. */
9161enum ofperr
9162ofputil_decode_group_mod(const struct ofp_header *oh,
9163 struct ofputil_group_mod *gm)
9164{
0a2869d5 9165 ofputil_init_group_properties(&gm->props);
7395c052 9166
0a2869d5
BP
9167 enum ofp_version ofp_version = oh->version;
9168 struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
7395c052
NZ
9169 ofpraw_pull_assert(&msg);
9170
0a2869d5 9171 enum ofperr err;
aead63f2
SH
9172 switch (ofp_version)
9173 {
9174 case OFP11_VERSION:
9175 case OFP12_VERSION:
9176 case OFP13_VERSION:
9177 case OFP14_VERSION:
aead63f2
SH
9178 err = ofputil_pull_ofp11_group_mod(&msg, ofp_version, gm);
9179 break;
9180
18ac06d3 9181 case OFP15_VERSION:
b79d45a1 9182 case OFP16_VERSION:
18ac06d3
SH
9183 err = ofputil_pull_ofp15_group_mod(&msg, ofp_version, gm);
9184 break;
9185
aead63f2
SH
9186 case OFP10_VERSION:
9187 default:
9188 OVS_NOT_REACHED();
9189 }
e57681e5
SH
9190 if (err) {
9191 return err;
9192 }
9193
e1799eb7
SH
9194 switch (gm->type) {
9195 case OFPGT11_INDIRECT:
beaa2b87
LS
9196 if (gm->command != OFPGC11_DELETE
9197 && !ovs_list_is_singleton(&gm->buckets) ) {
290eada7 9198 return OFPERR_OFPGMFC_INVALID_GROUP;
e1799eb7
SH
9199 }
9200 break;
9201 case OFPGT11_ALL:
9202 case OFPGT11_SELECT:
9203 case OFPGT11_FF:
9204 break;
9205 default:
09d4b951 9206 return OFPERR_OFPGMFC_BAD_TYPE;
65075b99
SH
9207 }
9208
9209 switch (gm->command) {
9210 case OFPGC11_ADD:
9211 case OFPGC11_MODIFY:
9212 case OFPGC11_DELETE:
9213 case OFPGC15_INSERT_BUCKET:
9214 break;
9215 case OFPGC15_REMOVE_BUCKET:
417e7e66 9216 if (!ovs_list_is_empty(&gm->buckets)) {
65075b99
SH
9217 return OFPERR_OFPGMFC_BAD_BUCKET;
9218 }
9219 break;
9220 default:
09d4b951 9221 return OFPERR_OFPGMFC_BAD_COMMAND;
e1799eb7
SH
9222 }
9223
0a2869d5 9224 struct ofputil_bucket *bucket;
e57681e5 9225 LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
64e8c446
BP
9226 if (bucket->weight && gm->type != OFPGT11_SELECT) {
9227 return OFPERR_OFPGMFC_INVALID_GROUP;
9228 }
9229
e57681e5
SH
9230 switch (gm->type) {
9231 case OFPGT11_ALL:
9232 case OFPGT11_INDIRECT:
9233 if (ofputil_bucket_has_liveness(bucket)) {
9234 return OFPERR_OFPGMFC_WATCH_UNSUPPORTED;
9235 }
9236 break;
9237 case OFPGT11_SELECT:
9238 break;
9239 case OFPGT11_FF:
9240 if (!ofputil_bucket_has_liveness(bucket)) {
9241 return OFPERR_OFPGMFC_INVALID_GROUP;
9242 }
9243 break;
9244 default:
896313f3
FL
9245 /* Returning BAD TYPE to be consistent
9246 * though gm->type has been checked already. */
9247 return OFPERR_OFPGMFC_BAD_TYPE;
e57681e5
SH
9248 }
9249 }
9250
9251 return 0;
7395c052
NZ
9252}
9253
64626975
SH
9254/* Parse a queue status request message into 'oqsr'.
9255 * Returns 0 if successful, otherwise an OFPERR_* number. */
9256enum ofperr
9257ofputil_decode_queue_stats_request(const struct ofp_header *request,
9258 struct ofputil_queue_stats_request *oqsr)
9259{
9260 switch ((enum ofp_version)request->version) {
b79d45a1 9261 case OFP16_VERSION:
42dccab5 9262 case OFP15_VERSION:
c37c0382 9263 case OFP14_VERSION:
2e1ae200 9264 case OFP13_VERSION:
64626975
SH
9265 case OFP12_VERSION:
9266 case OFP11_VERSION: {
9267 const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request);
9268 oqsr->queue_id = ntohl(qsr11->queue_id);
9269 return ofputil_port_from_ofp11(qsr11->port_no, &oqsr->port_no);
9270 }
9271
9272 case OFP10_VERSION: {
7f05e7ab
JR
9273 const struct ofp10_queue_stats_request *qsr10 = ofpmsg_body(request);
9274 oqsr->queue_id = ntohl(qsr10->queue_id);
4e022ec0 9275 oqsr->port_no = u16_to_ofp(ntohs(qsr10->port_no));
7f05e7ab
JR
9276 /* OF 1.0 uses OFPP_ALL for OFPP_ANY */
9277 if (oqsr->port_no == OFPP_ALL) {
9278 oqsr->port_no = OFPP_ANY;
9279 }
64626975
SH
9280 return 0;
9281 }
9282
9283 default:
428b2edd 9284 OVS_NOT_REACHED();
64626975
SH
9285 }
9286}
9287
0746a84f
BP
9288/* Encode a queue stats request for 'oqsr', the encoded message
9289 * will be for OpenFlow version 'ofp_version'. Returns message
9290 * as a struct ofpbuf. Returns encoded message on success, NULL on error. */
64626975
SH
9291struct ofpbuf *
9292ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
9293 const struct ofputil_queue_stats_request *oqsr)
9294{
9295 struct ofpbuf *request;
9296
9297 switch (ofp_version) {
9298 case OFP11_VERSION:
2e1ae200 9299 case OFP12_VERSION:
c37c0382 9300 case OFP13_VERSION:
42dccab5 9301 case OFP14_VERSION:
b79d45a1
BP
9302 case OFP15_VERSION:
9303 case OFP16_VERSION: {
64626975
SH
9304 struct ofp11_queue_stats_request *req;
9305 request = ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST, ofp_version, 0);
9306 req = ofpbuf_put_zeros(request, sizeof *req);
9307 req->port_no = ofputil_port_to_ofp11(oqsr->port_no);
9308 req->queue_id = htonl(oqsr->queue_id);
9309 break;
9310 }
9311 case OFP10_VERSION: {
9312 struct ofp10_queue_stats_request *req;
9313 request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST, ofp_version, 0);
9314 req = ofpbuf_put_zeros(request, sizeof *req);
7f05e7ab 9315 /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */
4e022ec0
AW
9316 req->port_no = htons(ofp_to_u16(oqsr->port_no == OFPP_ANY
9317 ? OFPP_ALL : oqsr->port_no));
64626975
SH
9318 req->queue_id = htonl(oqsr->queue_id);
9319 break;
9320 }
9321 default:
428b2edd 9322 OVS_NOT_REACHED();
64626975
SH
9323 }
9324
9325 return request;
9326}
9327
9328/* Returns the number of queue stats elements in OFPTYPE_QUEUE_STATS_REPLY
9329 * message 'oh'. */
9330size_t
9331ofputil_count_queue_stats(const struct ofp_header *oh)
9332{
0a2869d5 9333 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
64626975 9334 ofpraw_pull_assert(&b);
0a2869d5
BP
9335
9336 for (size_t n = 0; ; n++) {
9337 struct ofputil_queue_stats qs;
9338 if (ofputil_decode_queue_stats(&qs, &b)) {
9339 return n;
9340 }
1bb2cdbe 9341 }
64626975
SH
9342}
9343
9344static enum ofperr
9345ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats *oqs,
9346 const struct ofp10_queue_stats *qs10)
9347{
4e022ec0 9348 oqs->port_no = u16_to_ofp(ntohs(qs10->port_no));
64626975 9349 oqs->queue_id = ntohl(qs10->queue_id);
6dc34a0d
BP
9350 oqs->tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes));
9351 oqs->tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets));
9352 oqs->tx_errors = ntohll(get_32aligned_be64(&qs10->tx_errors));
9353 oqs->duration_sec = oqs->duration_nsec = UINT32_MAX;
64626975
SH
9354
9355 return 0;
9356}
9357
9358static enum ofperr
9359ofputil_queue_stats_from_ofp11(struct ofputil_queue_stats *oqs,
9360 const struct ofp11_queue_stats *qs11)
9361{
9362 enum ofperr error;
9363
9364 error = ofputil_port_from_ofp11(qs11->port_no, &oqs->port_no);
9365 if (error) {
9366 return error;
9367 }
9368
9369 oqs->queue_id = ntohl(qs11->queue_id);
6dc34a0d
BP
9370 oqs->tx_bytes = ntohll(qs11->tx_bytes);
9371 oqs->tx_packets = ntohll(qs11->tx_packets);
9372 oqs->tx_errors = ntohll(qs11->tx_errors);
9373 oqs->duration_sec = oqs->duration_nsec = UINT32_MAX;
64626975
SH
9374
9375 return 0;
9376}
9377
2e1ae200
JR
9378static enum ofperr
9379ofputil_queue_stats_from_ofp13(struct ofputil_queue_stats *oqs,
9380 const struct ofp13_queue_stats *qs13)
9381{
6dc34a0d 9382 enum ofperr error = ofputil_queue_stats_from_ofp11(oqs, &qs13->qs);
2e1ae200 9383 if (!error) {
6dc34a0d
BP
9384 oqs->duration_sec = ntohl(qs13->duration_sec);
9385 oqs->duration_nsec = ntohl(qs13->duration_nsec);
2e1ae200
JR
9386 }
9387
9388 return error;
9389}
9390
1bb2cdbe
BP
9391static enum ofperr
9392ofputil_pull_ofp14_queue_stats(struct ofputil_queue_stats *oqs,
9393 struct ofpbuf *msg)
9394{
9395 const struct ofp14_queue_stats *qs14;
9396 size_t len;
9397
9398 qs14 = ofpbuf_try_pull(msg, sizeof *qs14);
9399 if (!qs14) {
9400 return OFPERR_OFPBRC_BAD_LEN;
9401 }
9402
9403 len = ntohs(qs14->length);
6fd6ed71 9404 if (len < sizeof *qs14 || len - sizeof *qs14 > msg->size) {
1bb2cdbe
BP
9405 return OFPERR_OFPBRC_BAD_LEN;
9406 }
9407 ofpbuf_pull(msg, len - sizeof *qs14);
9408
9409 /* No properties yet defined, so ignore them for now. */
9410
9411 return ofputil_queue_stats_from_ofp13(oqs, &qs14->qs);
9412}
9413
64626975
SH
9414/* Converts an OFPST_QUEUE_STATS reply in 'msg' into an abstract
9415 * ofputil_queue_stats in 'qs'.
9416 *
9417 * Multiple OFPST_QUEUE_STATS replies can be packed into a single OpenFlow
9418 * message. Calling this function multiple times for a single 'msg' iterates
9419 * through the replies. The caller must initially leave 'msg''s layer pointers
9420 * null and not modify them between calls.
9421 *
9422 * Returns 0 if successful, EOF if no replies were left in this 'msg',
9423 * otherwise a positive errno value. */
9424int
9425ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg)
9426{
9427 enum ofperr error;
9428 enum ofpraw raw;
9429
6fd6ed71 9430 error = (msg->header ? ofpraw_decode(&raw, msg->header)
64626975
SH
9431 : ofpraw_pull(&raw, msg));
9432 if (error) {
9433 return error;
9434 }
9435
6fd6ed71 9436 if (!msg->size) {
64626975 9437 return EOF;
1bb2cdbe
BP
9438 } else if (raw == OFPRAW_OFPST14_QUEUE_REPLY) {
9439 return ofputil_pull_ofp14_queue_stats(qs, msg);
2e1ae200
JR
9440 } else if (raw == OFPRAW_OFPST13_QUEUE_REPLY) {
9441 const struct ofp13_queue_stats *qs13;
9442
9443 qs13 = ofpbuf_try_pull(msg, sizeof *qs13);
9444 if (!qs13) {
9445 goto bad_len;
9446 }
9447 return ofputil_queue_stats_from_ofp13(qs, qs13);
64626975
SH
9448 } else if (raw == OFPRAW_OFPST11_QUEUE_REPLY) {
9449 const struct ofp11_queue_stats *qs11;
9450
9451 qs11 = ofpbuf_try_pull(msg, sizeof *qs11);
9452 if (!qs11) {
2e1ae200 9453 goto bad_len;
64626975
SH
9454 }
9455 return ofputil_queue_stats_from_ofp11(qs, qs11);
9456 } else if (raw == OFPRAW_OFPST10_QUEUE_REPLY) {
9457 const struct ofp10_queue_stats *qs10;
9458
9459 qs10 = ofpbuf_try_pull(msg, sizeof *qs10);
9460 if (!qs10) {
2e1ae200 9461 goto bad_len;
64626975
SH
9462 }
9463 return ofputil_queue_stats_from_ofp10(qs, qs10);
9464 } else {
428b2edd 9465 OVS_NOT_REACHED();
64626975 9466 }
2e1ae200
JR
9467
9468 bad_len:
437d0d22 9469 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %"PRIu32" leftover "
6fd6ed71 9470 "bytes at end", msg->size);
2e1ae200 9471 return OFPERR_OFPBRC_BAD_LEN;
64626975
SH
9472}
9473
9474static void
9475ofputil_queue_stats_to_ofp10(const struct ofputil_queue_stats *oqs,
9476 struct ofp10_queue_stats *qs10)
9477{
4e022ec0 9478 qs10->port_no = htons(ofp_to_u16(oqs->port_no));
64626975
SH
9479 memset(qs10->pad, 0, sizeof qs10->pad);
9480 qs10->queue_id = htonl(oqs->queue_id);
6dc34a0d
BP
9481 put_32aligned_be64(&qs10->tx_bytes, htonll(oqs->tx_bytes));
9482 put_32aligned_be64(&qs10->tx_packets, htonll(oqs->tx_packets));
9483 put_32aligned_be64(&qs10->tx_errors, htonll(oqs->tx_errors));
64626975
SH
9484}
9485
9486static void
9487ofputil_queue_stats_to_ofp11(const struct ofputil_queue_stats *oqs,
9488 struct ofp11_queue_stats *qs11)
9489{
9490 qs11->port_no = ofputil_port_to_ofp11(oqs->port_no);
9491 qs11->queue_id = htonl(oqs->queue_id);
6dc34a0d
BP
9492 qs11->tx_bytes = htonll(oqs->tx_bytes);
9493 qs11->tx_packets = htonll(oqs->tx_packets);
9494 qs11->tx_errors = htonll(oqs->tx_errors);
64626975
SH
9495}
9496
2e1ae200
JR
9497static void
9498ofputil_queue_stats_to_ofp13(const struct ofputil_queue_stats *oqs,
9499 struct ofp13_queue_stats *qs13)
9500{
9501 ofputil_queue_stats_to_ofp11(oqs, &qs13->qs);
6dc34a0d
BP
9502 if (oqs->duration_sec != UINT32_MAX) {
9503 qs13->duration_sec = htonl(oqs->duration_sec);
9504 qs13->duration_nsec = htonl(oqs->duration_nsec);
9505 } else {
b8266395
BP
9506 qs13->duration_sec = OVS_BE32_MAX;
9507 qs13->duration_nsec = OVS_BE32_MAX;
6dc34a0d 9508 }
2e1ae200
JR
9509}
9510
1bb2cdbe
BP
9511static void
9512ofputil_queue_stats_to_ofp14(const struct ofputil_queue_stats *oqs,
9513 struct ofp14_queue_stats *qs14)
9514{
9515 qs14->length = htons(sizeof *qs14);
9516 memset(qs14->pad, 0, sizeof qs14->pad);
9517 ofputil_queue_stats_to_ofp13(oqs, &qs14->qs);
9518}
9519
9520
64626975
SH
9521/* Encode a queue stat for 'oqs' and append it to 'replies'. */
9522void
ca6ba700 9523ofputil_append_queue_stat(struct ovs_list *replies,
64626975
SH
9524 const struct ofputil_queue_stats *oqs)
9525{
e28ac5cf 9526 switch (ofpmp_version(replies)) {
2e1ae200
JR
9527 case OFP13_VERSION: {
9528 struct ofp13_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
9529 ofputil_queue_stats_to_ofp13(oqs, reply);
9530 break;
9531 }
9532
64626975
SH
9533 case OFP12_VERSION:
9534 case OFP11_VERSION: {
2e1ae200 9535 struct ofp11_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
64626975
SH
9536 ofputil_queue_stats_to_ofp11(oqs, reply);
9537 break;
9538 }
9539
9540 case OFP10_VERSION: {
2e1ae200 9541 struct ofp10_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
64626975
SH
9542 ofputil_queue_stats_to_ofp10(oqs, reply);
9543 break;
9544 }
9545
42dccab5 9546 case OFP14_VERSION:
b79d45a1
BP
9547 case OFP15_VERSION:
9548 case OFP16_VERSION: {
1bb2cdbe
BP
9549 struct ofp14_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
9550 ofputil_queue_stats_to_ofp14(oqs, reply);
c37c0382 9551 break;
1bb2cdbe 9552 }
c37c0382 9553
64626975 9554 default:
428b2edd 9555 OVS_NOT_REACHED();
64626975
SH
9556 }
9557}
777af88d
AC
9558
9559enum ofperr
9560ofputil_decode_bundle_ctrl(const struct ofp_header *oh,
9561 struct ofputil_bundle_ctrl_msg *msg)
9562{
0a2869d5
BP
9563 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
9564 enum ofpraw raw = ofpraw_pull_assert(&b);
06d4d4b6
JR
9565 ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_CONTROL
9566 || raw == OFPRAW_ONFT13_BUNDLE_CONTROL);
777af88d 9567
0a2869d5 9568 const struct ofp14_bundle_ctrl_msg *m = b.msg;
777af88d
AC
9569 msg->bundle_id = ntohl(m->bundle_id);
9570 msg->type = ntohs(m->type);
9571 msg->flags = ntohs(m->flags);
9572
9573 return 0;
9574}
9575
db5076ee
JR
9576struct ofpbuf *
9577ofputil_encode_bundle_ctrl_request(enum ofp_version ofp_version,
9578 struct ofputil_bundle_ctrl_msg *bc)
9579{
9580 struct ofpbuf *request;
9581 struct ofp14_bundle_ctrl_msg *m;
9582
9583 switch (ofp_version) {
9584 case OFP10_VERSION:
9585 case OFP11_VERSION:
9586 case OFP12_VERSION:
06d4d4b6 9587 ovs_fatal(0, "bundles need OpenFlow 1.3 or later "
db5076ee 9588 "(\'-O OpenFlow14\')");
06d4d4b6 9589 case OFP13_VERSION:
db5076ee
JR
9590 case OFP14_VERSION:
9591 case OFP15_VERSION:
b79d45a1 9592 case OFP16_VERSION:
06d4d4b6
JR
9593 request = ofpraw_alloc(ofp_version == OFP13_VERSION
9594 ? OFPRAW_ONFT13_BUNDLE_CONTROL
9595 : OFPRAW_OFPT14_BUNDLE_CONTROL, ofp_version, 0);
db5076ee
JR
9596 m = ofpbuf_put_zeros(request, sizeof *m);
9597
9598 m->bundle_id = htonl(bc->bundle_id);
9599 m->type = htons(bc->type);
9600 m->flags = htons(bc->flags);
9601 break;
9602 default:
9603 OVS_NOT_REACHED();
9604 }
9605
9606 return request;
9607}
9608
777af88d
AC
9609struct ofpbuf *
9610ofputil_encode_bundle_ctrl_reply(const struct ofp_header *oh,
9611 struct ofputil_bundle_ctrl_msg *msg)
9612{
9613 struct ofpbuf *buf;
9614 struct ofp14_bundle_ctrl_msg *m;
9615
06d4d4b6
JR
9616 buf = ofpraw_alloc_reply(oh->version == OFP13_VERSION
9617 ? OFPRAW_ONFT13_BUNDLE_CONTROL
9618 : OFPRAW_OFPT14_BUNDLE_CONTROL, oh, 0);
777af88d
AC
9619 m = ofpbuf_put_zeros(buf, sizeof *m);
9620
9621 m->bundle_id = htonl(msg->bundle_id);
9622 m->type = htons(msg->type);
9623 m->flags = htons(msg->flags);
9624
9625 return buf;
9626}
9627
c25ce22d
JR
9628/* Return true for bundlable state change requests, false for other messages.
9629 */
9630static bool
9631ofputil_is_bundlable(enum ofptype type)
9632{
9633 switch (type) {
9634 /* Minimum required by OpenFlow 1.4. */
9635 case OFPTYPE_PORT_MOD:
9636 case OFPTYPE_FLOW_MOD:
9637 return true;
9638
9639 /* Nice to have later. */
9640 case OFPTYPE_FLOW_MOD_TABLE_ID:
9641 case OFPTYPE_GROUP_MOD:
9642 case OFPTYPE_TABLE_MOD:
9643 case OFPTYPE_METER_MOD:
9644 case OFPTYPE_PACKET_OUT:
4e548ad9 9645 case OFPTYPE_NXT_TLV_TABLE_MOD:
c25ce22d
JR
9646
9647 /* Not to be bundlable. */
9648 case OFPTYPE_ECHO_REQUEST:
9649 case OFPTYPE_FEATURES_REQUEST:
9650 case OFPTYPE_GET_CONFIG_REQUEST:
9651 case OFPTYPE_SET_CONFIG:
9652 case OFPTYPE_BARRIER_REQUEST:
9653 case OFPTYPE_ROLE_REQUEST:
9654 case OFPTYPE_ECHO_REPLY:
9655 case OFPTYPE_SET_FLOW_FORMAT:
9656 case OFPTYPE_SET_PACKET_IN_FORMAT:
9657 case OFPTYPE_SET_CONTROLLER_ID:
9658 case OFPTYPE_FLOW_AGE:
9659 case OFPTYPE_FLOW_MONITOR_CANCEL:
9660 case OFPTYPE_SET_ASYNC_CONFIG:
9661 case OFPTYPE_GET_ASYNC_REQUEST:
9662 case OFPTYPE_DESC_STATS_REQUEST:
9663 case OFPTYPE_FLOW_STATS_REQUEST:
9664 case OFPTYPE_AGGREGATE_STATS_REQUEST:
9665 case OFPTYPE_TABLE_STATS_REQUEST:
9666 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
03c72922 9667 case OFPTYPE_TABLE_DESC_REQUEST:
c25ce22d
JR
9668 case OFPTYPE_PORT_STATS_REQUEST:
9669 case OFPTYPE_QUEUE_STATS_REQUEST:
9670 case OFPTYPE_PORT_DESC_STATS_REQUEST:
9671 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
9672 case OFPTYPE_METER_STATS_REQUEST:
9673 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
9674 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
9675 case OFPTYPE_GROUP_STATS_REQUEST:
9676 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
9677 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
9678 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
9679 case OFPTYPE_BUNDLE_CONTROL:
9680 case OFPTYPE_BUNDLE_ADD_MESSAGE:
9681 case OFPTYPE_HELLO:
9682 case OFPTYPE_ERROR:
9683 case OFPTYPE_FEATURES_REPLY:
9684 case OFPTYPE_GET_CONFIG_REPLY:
9685 case OFPTYPE_PACKET_IN:
9686 case OFPTYPE_FLOW_REMOVED:
9687 case OFPTYPE_PORT_STATUS:
9688 case OFPTYPE_BARRIER_REPLY:
9689 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
9690 case OFPTYPE_DESC_STATS_REPLY:
9691 case OFPTYPE_FLOW_STATS_REPLY:
9692 case OFPTYPE_QUEUE_STATS_REPLY:
9693 case OFPTYPE_PORT_STATS_REPLY:
9694 case OFPTYPE_TABLE_STATS_REPLY:
9695 case OFPTYPE_AGGREGATE_STATS_REPLY:
9696 case OFPTYPE_PORT_DESC_STATS_REPLY:
9697 case OFPTYPE_ROLE_REPLY:
9698 case OFPTYPE_FLOW_MONITOR_PAUSED:
9699 case OFPTYPE_FLOW_MONITOR_RESUMED:
9700 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
9701 case OFPTYPE_GET_ASYNC_REPLY:
9702 case OFPTYPE_GROUP_STATS_REPLY:
9703 case OFPTYPE_GROUP_DESC_STATS_REPLY:
9704 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
9705 case OFPTYPE_METER_STATS_REPLY:
9706 case OFPTYPE_METER_CONFIG_STATS_REPLY:
9707 case OFPTYPE_METER_FEATURES_STATS_REPLY:
9708 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
03c72922 9709 case OFPTYPE_TABLE_DESC_REPLY:
c25ce22d 9710 case OFPTYPE_ROLE_STATUS:
3c35db62 9711 case OFPTYPE_REQUESTFORWARD:
6c6eedc5 9712 case OFPTYPE_TABLE_STATUS:
4e548ad9
ML
9713 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
9714 case OFPTYPE_NXT_TLV_TABLE_REPLY:
77ab5fd2 9715 case OFPTYPE_NXT_RESUME:
c25ce22d
JR
9716 break;
9717 }
9718
9719 return false;
9720}
9721
777af88d
AC
9722enum ofperr
9723ofputil_decode_bundle_add(const struct ofp_header *oh,
7ac27a04 9724 struct ofputil_bundle_add_msg *msg,
0a2869d5 9725 enum ofptype *typep)
777af88d 9726{
0a2869d5
BP
9727 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
9728 enum ofpraw raw = ofpraw_pull_assert(&b);
06d4d4b6
JR
9729 ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE
9730 || raw == OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE);
777af88d 9731
0a2869d5 9732 const struct ofp14_bundle_ctrl_msg *m = ofpbuf_pull(&b, sizeof *m);
777af88d
AC
9733 msg->bundle_id = ntohl(m->bundle_id);
9734 msg->flags = ntohs(m->flags);
9735
6fd6ed71 9736 msg->msg = b.data;
46be7132 9737 if (msg->msg->version != oh->version) {
bc02606a 9738 return OFPERR_OFPBFC_BAD_VERSION;
46be7132 9739 }
0a2869d5 9740 size_t inner_len = ntohs(msg->msg->length);
6fd6ed71 9741 if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) {
777af88d
AC
9742 return OFPERR_OFPBFC_MSG_BAD_LEN;
9743 }
be6f6393
JR
9744 if (msg->msg->xid != oh->xid) {
9745 return OFPERR_OFPBFC_MSG_BAD_XID;
9746 }
777af88d 9747
c25ce22d 9748 /* Reject unbundlable messages. */
0a2869d5
BP
9749 enum ofptype type;
9750 enum ofperr error = ofptype_decode(&type, msg->msg);
c25ce22d
JR
9751 if (error) {
9752 VLOG_WARN_RL(&bad_ofmsg_rl, "OFPT14_BUNDLE_ADD_MESSAGE contained "
9753 "message is unparsable (%s)", ofperr_get_name(error));
9754 return OFPERR_OFPBFC_MSG_UNSUP; /* 'error' would be confusing. */
9755 }
9756
0a2869d5 9757 if (!ofputil_is_bundlable(type)) {
44648b0f 9758 VLOG_WARN_RL(&bad_ofmsg_rl, "%s message not allowed inside "
0a2869d5 9759 "OFPT14_BUNDLE_ADD_MESSAGE", ofptype_get_name(type));
c25ce22d
JR
9760 return OFPERR_OFPBFC_MSG_UNSUP;
9761 }
0a2869d5
BP
9762 if (typep) {
9763 *typep = type;
9764 }
c25ce22d 9765
777af88d
AC
9766 return 0;
9767}
9768
9769struct ofpbuf *
9770ofputil_encode_bundle_add(enum ofp_version ofp_version,
9771 struct ofputil_bundle_add_msg *msg)
9772{
9773 struct ofpbuf *request;
9774 struct ofp14_bundle_ctrl_msg *m;
9775
7b3dca89 9776 /* Must use the same xid as the embedded message. */
06d4d4b6
JR
9777 request = ofpraw_alloc_xid(ofp_version == OFP13_VERSION
9778 ? OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE
9779 : OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE, ofp_version,
7b3dca89 9780 msg->msg->xid, 0);
777af88d
AC
9781 m = ofpbuf_put_zeros(request, sizeof *m);
9782
9783 m->bundle_id = htonl(msg->bundle_id);
9784 m->flags = htons(msg->flags);
9785 ofpbuf_put(request, msg->msg, ntohs(msg->msg->length));
9786
9787 return request;
9788}
6159c531
JG
9789
9790static void
4e548ad9 9791encode_tlv_table_mappings(struct ofpbuf *b, struct ovs_list *mappings)
6159c531 9792{
4e548ad9 9793 struct ofputil_tlv_map *map;
6159c531
JG
9794
9795 LIST_FOR_EACH (map, list_node, mappings) {
4e548ad9 9796 struct nx_tlv_map *nx_map;
6159c531
JG
9797
9798 nx_map = ofpbuf_put_zeros(b, sizeof *nx_map);
9799 nx_map->option_class = htons(map->option_class);
9800 nx_map->option_type = map->option_type;
9801 nx_map->option_len = map->option_len;
9802 nx_map->index = htons(map->index);
9803 }
9804}
9805
9806struct ofpbuf *
4e548ad9
ML
9807ofputil_encode_tlv_table_mod(enum ofp_version ofp_version,
9808 struct ofputil_tlv_table_mod *ttm)
6159c531
JG
9809{
9810 struct ofpbuf *b;
4e548ad9 9811 struct nx_tlv_table_mod *nx_ttm;
6159c531 9812
4e548ad9
ML
9813 b = ofpraw_alloc(OFPRAW_NXT_TLV_TABLE_MOD, ofp_version, 0);
9814 nx_ttm = ofpbuf_put_zeros(b, sizeof *nx_ttm);
9815 nx_ttm->command = htons(ttm->command);
9816 encode_tlv_table_mappings(b, &ttm->mappings);
6159c531
JG
9817
9818 return b;
9819}
9820
9821static enum ofperr
4e548ad9 9822decode_tlv_table_mappings(struct ofpbuf *msg, unsigned int max_fields,
dfe5044c 9823 struct ovs_list *mappings)
6159c531 9824{
417e7e66 9825 ovs_list_init(mappings);
6159c531
JG
9826
9827 while (msg->size) {
4e548ad9
ML
9828 struct nx_tlv_map *nx_map;
9829 struct ofputil_tlv_map *map;
6159c531
JG
9830
9831 nx_map = ofpbuf_pull(msg, sizeof *nx_map);
9832 map = xmalloc(sizeof *map);
417e7e66 9833 ovs_list_push_back(mappings, &map->list_node);
6159c531
JG
9834
9835 map->option_class = ntohs(nx_map->option_class);
9836 map->option_type = nx_map->option_type;
9837
9838 map->option_len = nx_map->option_len;
4e548ad9 9839 if (map->option_len % 4 || map->option_len > TLV_MAX_OPT_SIZE) {
6159c531 9840 VLOG_WARN_RL(&bad_ofmsg_rl,
4e548ad9 9841 "tlv table option length (%u) is not a valid option size",
6159c531 9842 map->option_len);
4e548ad9
ML
9843 ofputil_uninit_tlv_table(mappings);
9844 return OFPERR_NXTTMFC_BAD_OPT_LEN;
6159c531
JG
9845 }
9846
9847 map->index = ntohs(nx_map->index);
dfe5044c 9848 if (map->index >= max_fields) {
6159c531 9849 VLOG_WARN_RL(&bad_ofmsg_rl,
4e548ad9 9850 "tlv table field index (%u) is too large (max %u)",
dfe5044c 9851 map->index, max_fields - 1);
4e548ad9
ML
9852 ofputil_uninit_tlv_table(mappings);
9853 return OFPERR_NXTTMFC_BAD_FIELD_IDX;
6159c531
JG
9854 }
9855 }
9856
9857 return 0;
9858}
9859
9860enum ofperr
4e548ad9
ML
9861ofputil_decode_tlv_table_mod(const struct ofp_header *oh,
9862 struct ofputil_tlv_table_mod *ttm)
6159c531 9863{
0a2869d5 9864 struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
6159c531
JG
9865 ofpraw_pull_assert(&msg);
9866
0a2869d5 9867 struct nx_tlv_table_mod *nx_ttm = ofpbuf_pull(&msg, sizeof *nx_ttm);
4e548ad9
ML
9868 ttm->command = ntohs(nx_ttm->command);
9869 if (ttm->command > NXTTMC_CLEAR) {
6159c531 9870 VLOG_WARN_RL(&bad_ofmsg_rl,
4e548ad9
ML
9871 "tlv table mod command (%u) is out of range",
9872 ttm->command);
9873 return OFPERR_NXTTMFC_BAD_COMMAND;
6159c531
JG
9874 }
9875
4e548ad9
ML
9876 return decode_tlv_table_mappings(&msg, TUN_METADATA_NUM_OPTS,
9877 &ttm->mappings);
6159c531
JG
9878}
9879
9880struct ofpbuf *
4e548ad9
ML
9881ofputil_encode_tlv_table_reply(const struct ofp_header *oh,
9882 struct ofputil_tlv_table_reply *ttr)
6159c531
JG
9883{
9884 struct ofpbuf *b;
4e548ad9 9885 struct nx_tlv_table_reply *nx_ttr;
6159c531 9886
4e548ad9
ML
9887 b = ofpraw_alloc_reply(OFPRAW_NXT_TLV_TABLE_REPLY, oh, 0);
9888 nx_ttr = ofpbuf_put_zeros(b, sizeof *nx_ttr);
9889 nx_ttr->max_option_space = htonl(ttr->max_option_space);
9890 nx_ttr->max_fields = htons(ttr->max_fields);
6159c531 9891
4e548ad9 9892 encode_tlv_table_mappings(b, &ttr->mappings);
6159c531
JG
9893
9894 return b;
9895}
9896
4e548ad9 9897/* Decodes the NXT_TLV_TABLE_REPLY message in 'oh' into '*ttr'. Returns 0
dfe5044c
BP
9898 * if successful, otherwise an ofperr.
9899 *
4e548ad9
ML
9900 * The decoder verifies that the indexes in 'ttr->mappings' are less than
9901 * 'ttr->max_fields', but the caller must ensure, if necessary, that they are
dfe5044c 9902 * less than TUN_METADATA_NUM_OPTS. */
6159c531 9903enum ofperr
4e548ad9
ML
9904ofputil_decode_tlv_table_reply(const struct ofp_header *oh,
9905 struct ofputil_tlv_table_reply *ttr)
6159c531 9906{
0a2869d5 9907 struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
6159c531
JG
9908 ofpraw_pull_assert(&msg);
9909
0a2869d5 9910 struct nx_tlv_table_reply *nx_ttr = ofpbuf_pull(&msg, sizeof *nx_ttr);
4e548ad9
ML
9911 ttr->max_option_space = ntohl(nx_ttr->max_option_space);
9912 ttr->max_fields = ntohs(nx_ttr->max_fields);
6159c531 9913
4e548ad9 9914 return decode_tlv_table_mappings(&msg, ttr->max_fields, &ttr->mappings);
6159c531
JG
9915}
9916
9917void
4e548ad9 9918ofputil_uninit_tlv_table(struct ovs_list *mappings)
6159c531 9919{
4e548ad9 9920 struct ofputil_tlv_map *map;
6159c531
JG
9921
9922 LIST_FOR_EACH_POP (map, list_node, mappings) {
9923 free(map);
9924 }
9925}
98090482 9926
2da7974c
BP
9927const char *
9928ofputil_async_msg_type_to_string(enum ofputil_async_msg_type type)
9929{
9930 switch (type) {
9931 case OAM_PACKET_IN: return "PACKET_IN";
9932 case OAM_PORT_STATUS: return "PORT_STATUS";
9933 case OAM_FLOW_REMOVED: return "FLOW_REMOVED";
9934 case OAM_ROLE_STATUS: return "ROLE_STATUS";
9935 case OAM_TABLE_STATUS: return "TABLE_STATUS";
9936 case OAM_REQUESTFORWARD: return "REQUESTFORWARD";
9937
9938 case OAM_N_TYPES:
9939 default:
9940 OVS_NOT_REACHED();
9941 }
9942}
9943
8fd0bb60
BP
9944struct ofp14_async_prop {
9945 uint64_t prop_type;
9946 enum ofputil_async_msg_type oam;
9947 bool master;
9948 uint32_t allowed10, allowed14;
9949};
9950
9951#define AP_PAIR(SLAVE_PROP_TYPE, OAM, A10, A14) \
9952 { SLAVE_PROP_TYPE, OAM, false, A10, (A14) ? (A14) : (A10) }, \
9953 { (SLAVE_PROP_TYPE + 1), OAM, true, A10, (A14) ? (A14) : (A10) }
9954
9955static const struct ofp14_async_prop async_props[] = {
9956 AP_PAIR( 0, OAM_PACKET_IN, OFPR10_BITS, OFPR14_BITS),
9957 AP_PAIR( 2, OAM_PORT_STATUS, (1 << OFPPR_N_REASONS) - 1, 0),
9958 AP_PAIR( 4, OAM_FLOW_REMOVED, (1 << OVS_OFPRR_NONE) - 1, 0),
9959 AP_PAIR( 6, OAM_ROLE_STATUS, (1 << OFPCRR_N_REASONS) - 1, 0),
9960 AP_PAIR( 8, OAM_TABLE_STATUS, OFPTR_BITS, 0),
9961 AP_PAIR(10, OAM_REQUESTFORWARD, (1 << OFPRFR_N_REASONS) - 1, 0),
9962};
9963
9964#define FOR_EACH_ASYNC_PROP(VAR) \
9965 for (const struct ofp14_async_prop *VAR = async_props; \
9966 VAR < &async_props[ARRAY_SIZE(async_props)]; VAR++)
9967
9968static const struct ofp14_async_prop *
9969get_ofp14_async_config_prop_by_prop_type(uint64_t prop_type)
9970{
9971 FOR_EACH_ASYNC_PROP (ap) {
9972 if (prop_type == ap->prop_type) {
9973 return ap;
9974 }
9975 }
9976 return NULL;
9977}
9978
9979static const struct ofp14_async_prop *
9980get_ofp14_async_config_prop_by_oam(enum ofputil_async_msg_type oam,
9981 bool master)
9982{
9983 FOR_EACH_ASYNC_PROP (ap) {
9984 if (ap->oam == oam && ap->master == master) {
9985 return ap;
9986 }
9987 }
9988 return NULL;
9989}
9990
9991static uint32_t
9992ofp14_async_prop_allowed(const struct ofp14_async_prop *prop,
9993 enum ofp_version version)
9994{
9995 return version >= OFP14_VERSION ? prop->allowed14 : prop->allowed10;
9996}
9997
9998static ovs_be32
9999encode_async_mask(const struct ofputil_async_cfg *src,
10000 const struct ofp14_async_prop *ap,
10001 enum ofp_version version)
10002{
10003 uint32_t mask = ap->master ? src->master[ap->oam] : src->slave[ap->oam];
10004 return htonl(mask & ofp14_async_prop_allowed(ap, version));
10005}
10006
10007static enum ofperr
10008decode_async_mask(ovs_be32 src,
10009 const struct ofp14_async_prop *ap, enum ofp_version version,
10010 bool loose, struct ofputil_async_cfg *dst)
10011{
10012 uint32_t mask = ntohl(src);
10013 uint32_t allowed = ofp14_async_prop_allowed(ap, version);
10014 if (mask & ~allowed) {
10015 OFPPROP_LOG(&bad_ofmsg_rl, loose,
10016 "bad value %#x for %s (allowed mask %#x)",
10017 mask, ofputil_async_msg_type_to_string(ap->oam),
10018 allowed);
10019 mask &= allowed;
10020 if (!loose) {
10021 return OFPERR_OFPACFC_INVALID;
10022 }
10023 }
10024
9bfe9334
BP
10025 if (ap->oam == OAM_PACKET_IN) {
10026 if (mask & (1u << OFPR_NO_MATCH)) {
10027 mask |= 1u << OFPR_EXPLICIT_MISS;
10028 if (version < OFP13_VERSION) {
10029 mask |= 1u << OFPR_IMPLICIT_MISS;
10030 }
10031 }
10032 }
10033
8fd0bb60
BP
10034 uint32_t *array = ap->master ? dst->master : dst->slave;
10035 array[ap->oam] = mask;
10036 return 0;
10037}
10038
10039static enum ofperr
10040parse_async_tlv(const struct ofpbuf *property,
10041 const struct ofp14_async_prop *ap,
10042 struct ofputil_async_cfg *ac,
10043 enum ofp_version version, bool loose)
10044{
10045 enum ofperr error;
10046 ovs_be32 mask;
10047
10048 error = ofpprop_parse_be32(property, &mask);
10049 if (error) {
10050 return error;
10051 }
10052
10053 if (ofpprop_is_experimenter(ap->prop_type)) {
10054 /* For experimenter properties, whether a property is for the master or
10055 * slave role is indicated by both 'type' and 'exp_type' in struct
10056 * ofp_prop_experimenter. Check that these are consistent. */
10057 const struct ofp_prop_experimenter *ope = property->data;
10058 bool should_be_master = ope->type == htons(0xffff);
10059 if (should_be_master != ap->master) {
10060 VLOG_WARN_RL(&bad_ofmsg_rl, "async property type %#"PRIx16" "
10061 "indicates %s role but exp_type %"PRIu32" indicates "
10062 "%s role",
10063 ntohs(ope->type),
10064 should_be_master ? "master" : "slave",
10065 ntohl(ope->exp_type),
10066 ap->master ? "master" : "slave");
10067 return OFPERR_OFPBPC_BAD_EXP_TYPE;
10068 }
10069 }
10070
10071 return decode_async_mask(mask, ap, version, loose, ac);
10072}
10073
10074static void
10075decode_legacy_async_masks(const ovs_be32 masks[2],
10076 enum ofputil_async_msg_type oam,
10077 enum ofp_version version,
10078 struct ofputil_async_cfg *dst)
10079{
10080 for (int i = 0; i < 2; i++) {
10081 bool master = i == 0;
10082 const struct ofp14_async_prop *ap
10083 = get_ofp14_async_config_prop_by_oam(oam, master);
10084 decode_async_mask(masks[i], ap, version, true, dst);
10085 }
10086}
10087
98090482 10088/* Decodes the OpenFlow "set async config" request and "get async config
a930d4c5 10089 * reply" message in '*oh' into an abstract form in 'ac'.
98090482 10090 *
5876b4db
BP
10091 * Some versions of the "set async config" request change only some of the
10092 * settings and leave the others alone. This function uses 'basis' as the
10093 * initial state for decoding these. Other versions of the request change all
10094 * the settings; this function ignores 'basis' when decoding these.
10095 *
98090482
NR
10096 * If 'loose' is true, this function ignores properties and values that it does
10097 * not understand, as a controller would want to do when interpreting
10098 * capabilities provided by a switch. If 'loose' is false, this function
10099 * treats unknown properties and values as an error, as a switch would want to
10100 * do when interpreting a configuration request made by a controller.
10101 *
d18cc1ee
AA
10102 * Returns 0 if successful, otherwise an OFPERR_* value.
10103 *
10104 * Returns error code OFPERR_OFPACFC_INVALID if the value of mask is not in
10105 * the valid range of mask.
10106 *
10107 * Returns error code OFPERR_OFPACFC_UNSUPPORTED if the configuration is not
10108 * supported.*/
98090482 10109enum ofperr
a930d4c5 10110ofputil_decode_set_async_config(const struct ofp_header *oh, bool loose,
5876b4db 10111 const struct ofputil_async_cfg *basis,
a930d4c5 10112 struct ofputil_async_cfg *ac)
98090482 10113{
0a2869d5
BP
10114 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
10115 enum ofpraw raw = ofpraw_pull_assert(&b);
98090482
NR
10116
10117 if (raw == OFPRAW_OFPT13_SET_ASYNC ||
10118 raw == OFPRAW_NXT_SET_ASYNC_CONFIG ||
10119 raw == OFPRAW_OFPT13_GET_ASYNC_REPLY) {
10120 const struct nx_async_config *msg = ofpmsg_body(oh);
10121
5876b4db 10122 *ac = OFPUTIL_ASYNC_CFG_INIT;
8fd0bb60
BP
10123 decode_legacy_async_masks(msg->packet_in_mask, OAM_PACKET_IN,
10124 oh->version, ac);
10125 decode_legacy_async_masks(msg->port_status_mask, OAM_PORT_STATUS,
10126 oh->version, ac);
10127 decode_legacy_async_masks(msg->flow_removed_mask, OAM_FLOW_REMOVED,
10128 oh->version, ac);
98090482 10129 } else if (raw == OFPRAW_OFPT14_SET_ASYNC ||
af7bc161
BP
10130 raw == OFPRAW_OFPT14_GET_ASYNC_REPLY ||
10131 raw == OFPRAW_NXT_SET_ASYNC_CONFIG2) {
5876b4db 10132 *ac = *basis;
98090482 10133 while (b.size > 0) {
98090482
NR
10134 struct ofpbuf property;
10135 enum ofperr error;
34a543e3 10136 uint64_t type;
98090482 10137
34a543e3 10138 error = ofpprop_pull__(&b, &property, 8, 0xfffe, &type);
98090482
NR
10139 if (error) {
10140 return error;
10141 }
10142
8fd0bb60
BP
10143 const struct ofp14_async_prop *ap
10144 = get_ofp14_async_config_prop_by_prop_type(type);
10145 error = (ap
10146 ? parse_async_tlv(&property, ap, ac, oh->version, loose)
10147 : OFPPROP_UNKNOWN(loose, "async config", type));
b611d3ac 10148 if (error) {
8fd0bb60
BP
10149 /* Most messages use OFPBPC_BAD_TYPE but async has its own (who
10150 * knows why, it's OpenFlow. */
10151 if (error == OFPERR_OFPBPC_BAD_TYPE) {
10152 error = OFPERR_OFPACFC_UNSUPPORTED;
d18cc1ee 10153 }
98090482
NR
10154 return error;
10155 }
10156 }
10157 } else {
10158 return OFPERR_OFPBRC_BAD_VERSION;
10159 }
10160 return 0;
10161}
10162
8fd0bb60
BP
10163static void
10164encode_legacy_async_masks(const struct ofputil_async_cfg *ac,
10165 enum ofputil_async_msg_type oam,
10166 enum ofp_version version,
10167 ovs_be32 masks[2])
98090482 10168{
8fd0bb60
BP
10169 for (int i = 0; i < 2; i++) {
10170 bool master = i == 0;
10171 const struct ofp14_async_prop *ap
10172 = get_ofp14_async_config_prop_by_oam(oam, master);
10173 masks[i] = encode_async_mask(ac, ap, version);
10174 }
10175}
98090482 10176
8fd0bb60
BP
10177static void
10178ofputil_put_async_config__(const struct ofputil_async_cfg *ac,
10179 struct ofpbuf *buf, bool tlv,
10180 enum ofp_version version, uint32_t oams)
10181{
10182 if (!tlv) {
10183 struct nx_async_config *msg = ofpbuf_put_zeros(buf, sizeof *msg);
10184 encode_legacy_async_masks(ac, OAM_PACKET_IN, version,
10185 msg->packet_in_mask);
10186 encode_legacy_async_masks(ac, OAM_PORT_STATUS, version,
10187 msg->port_status_mask);
10188 encode_legacy_async_masks(ac, OAM_FLOW_REMOVED, version,
10189 msg->flow_removed_mask);
10190 } else {
10191 FOR_EACH_ASYNC_PROP (ap) {
10192 if (oams & (1u << ap->oam)) {
10193 size_t ofs = buf->size;
10194 ofpprop_put_be32(buf, ap->prop_type,
10195 encode_async_mask(ac, ap, version));
10196
10197 /* For experimenter properties, we need to use type 0xfffe for
10198 * master and 0xffff for slaves. */
10199 if (ofpprop_is_experimenter(ap->prop_type)) {
10200 struct ofp_prop_experimenter *ope
10201 = ofpbuf_at_assert(buf, ofs, sizeof *ope);
10202 ope->type = ap->master ? htons(0xffff) : htons(0xfffe);
10203 }
10204 }
98090482 10205 }
98090482 10206 }
98090482
NR
10207}
10208
8fd0bb60
BP
10209/* Encodes and returns a reply to the OFPT_GET_ASYNC_REQUEST in 'oh' that
10210 * states that the asynchronous message configuration is 'ac'. */
98090482 10211struct ofpbuf *
af7bc161
BP
10212ofputil_encode_get_async_reply(const struct ofp_header *oh,
10213 const struct ofputil_async_cfg *ac)
98090482
NR
10214{
10215 struct ofpbuf *buf;
98090482 10216
8fd0bb60
BP
10217 enum ofpraw raw = (oh->version < OFP14_VERSION
10218 ? OFPRAW_OFPT13_GET_ASYNC_REPLY
10219 : OFPRAW_OFPT14_GET_ASYNC_REPLY);
10220 struct ofpbuf *reply = ofpraw_alloc_reply(raw, oh, 0);
10221 ofputil_put_async_config__(ac, reply,
10222 raw == OFPRAW_OFPT14_GET_ASYNC_REPLY,
10223 oh->version, UINT32_MAX);
10224 return reply;
98090482
NR
10225
10226 return buf;
10227}
a930d4c5 10228
af7bc161
BP
10229/* Encodes and returns a message, in a format appropriate for OpenFlow version
10230 * 'ofp_version', that sets the asynchronous message configuration to 'ac'.
10231 *
10232 * Specify 'oams' as a bitmap of OAM_* that indicate the asynchronous messages
10233 * to configure. OF1.0 through OF1.3 can't natively configure a subset of
10234 * messages, so more messages than requested may be configured. OF1.0 through
10235 * OF1.3 also can't configure OVS extension OAM_* values, so if 'oam' includes
10236 * any extensions then this function encodes an Open vSwitch extension message
10237 * that does support configuring OVS extension OAM_*. */
10238struct ofpbuf *
10239ofputil_encode_set_async_config(const struct ofputil_async_cfg *ac,
10240 uint32_t oams, enum ofp_version ofp_version)
10241{
10242 enum ofpraw raw = (ofp_version >= OFP14_VERSION ? OFPRAW_OFPT14_SET_ASYNC
10243 : oams & OAM_EXTENSIONS ? OFPRAW_NXT_SET_ASYNC_CONFIG2
10244 : ofp_version >= OFP13_VERSION ? OFPRAW_OFPT13_SET_ASYNC
10245 : OFPRAW_NXT_SET_ASYNC_CONFIG);
10246 struct ofpbuf *request = ofpraw_alloc(raw, ofp_version, 0);
10247 ofputil_put_async_config__(ac, request,
10248 (raw == OFPRAW_OFPT14_SET_ASYNC ||
10249 raw == OFPRAW_NXT_SET_ASYNC_CONFIG2),
10250 ofp_version, oams);
10251 return request;
10252}
10253
a930d4c5
BP
10254struct ofputil_async_cfg
10255ofputil_async_cfg_default(enum ofp_version version)
10256{
9bfe9334
BP
10257 /* We enable all of the OF1.4 reasons regardless of 'version' because the
10258 * reasons added in OF1.4 just are just refinements of the OFPR_ACTION
10259 * introduced in OF1.0, breaking it into more specific categories. When we
10260 * encode these for earlier OpenFlow versions, we translate them into
10261 * OFPR_ACTION. */
10262 uint32_t pin = OFPR14_BITS & ~(1u << OFPR_INVALID_TTL);
10263 pin |= 1u << OFPR_EXPLICIT_MISS;
10264 if (version <= OFP12_VERSION) {
10265 pin |= 1u << OFPR_IMPLICIT_MISS;
10266 }
10267
a930d4c5 10268 return (struct ofputil_async_cfg) {
9bfe9334 10269 .master[OAM_PACKET_IN] = pin,
a930d4c5
BP
10270
10271 .master[OAM_FLOW_REMOVED]
10272 = (version >= OFP14_VERSION ? OFPRR14_BITS : OFPRR10_BITS),
10273
10274 .master[OAM_PORT_STATUS] = OFPPR_BITS,
10275 .slave[OAM_PORT_STATUS] = OFPPR_BITS,
10276 };
10277}
6c6eedc5
SJ
10278
10279static void
10280ofputil_put_ofp14_table_desc(const struct ofputil_table_desc *td,
10281 struct ofpbuf *b, enum ofp_version version)
10282{
10283 struct ofp14_table_desc *otd;
10284 struct ofp14_table_mod_prop_vacancy *otv;
10285 size_t start_otd;
10286
10287 start_otd = b->size;
10288 ofpbuf_put_zeros(b, sizeof *otd);
10289
10290 ofpprop_put_u32(b, OFPTMPT14_EVICTION, td->eviction_flags);
10291
10292 otv = ofpbuf_put_zeros(b, sizeof *otv);
10293 otv->type = htons(OFPTMPT14_VACANCY);
10294 otv->length = htons(sizeof *otv);
10295 otv->vacancy_down = td->table_vacancy.vacancy_down;
10296 otv->vacancy_up = td->table_vacancy.vacancy_up;
10297 otv->vacancy = td->table_vacancy.vacancy;
10298
10299 otd = ofpbuf_at_assert(b, start_otd, sizeof *otd);
10300 otd->length = htons(b->size - start_otd);
10301 otd->table_id = td->table_id;
10302 otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
10303 td->eviction, td->vacancy,
10304 version);
10305}
10306
10307/* Converts the abstract form of a "table status" message in '*ts' into an
10308 * OpenFlow message suitable for 'protocol', and returns that encoded form in
10309 * a buffer owned by the caller. */
10310struct ofpbuf *
10311ofputil_encode_table_status(const struct ofputil_table_status *ts,
10312 enum ofputil_protocol protocol)
10313{
10314 enum ofp_version version;
10315 struct ofpbuf *b;
10316
10317 version = ofputil_protocol_to_ofp_version(protocol);
10318 if (version >= OFP14_VERSION) {
10319 enum ofpraw raw;
10320 struct ofp14_table_status *ots;
10321
10322 raw = OFPRAW_OFPT14_TABLE_STATUS;
10323 b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
10324 ots = ofpbuf_put_zeros(b, sizeof *ots);
10325 ots->reason = ts->reason;
10326 ofputil_put_ofp14_table_desc(&ts->desc, b, version);
10327 ofpmsg_update_length(b);
10328 return b;
10329 } else {
10330 return NULL;
10331 }
10332}
10333
10334/* Decodes the OpenFlow "table status" message in '*ots' into an abstract form
10335 * in '*ts'. Returns 0 if successful, otherwise an OFPERR_* value. */
10336enum ofperr
10337ofputil_decode_table_status(const struct ofp_header *oh,
10338 struct ofputil_table_status *ts)
10339{
10340 const struct ofp14_table_status *ots;
10341 struct ofpbuf b;
10342 enum ofperr error;
10343 enum ofpraw raw;
10344
10345 ofpbuf_use_const(&b, oh, ntohs(oh->length));
10346 raw = ofpraw_pull_assert(&b);
10347 ots = ofpbuf_pull(&b, sizeof *ots);
10348
10349 if (raw == OFPRAW_OFPT14_TABLE_STATUS) {
10350 if (ots->reason != OFPTR_VACANCY_DOWN
10351 && ots->reason != OFPTR_VACANCY_UP) {
10352 return OFPERR_OFPBPC_BAD_VALUE;
10353 }
10354 ts->reason = ots->reason;
10355
10356 error = ofputil_decode_table_desc(&b, &ts->desc, oh->version);
10357 return error;
10358 } else {
10359 return OFPERR_OFPBRC_BAD_VERSION;
10360 }
10361
10362 return 0;
10363}