]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-match.c
cirrus: Use FreeBSD 12.2.
[mirror_ovs.git] / lib / ofp-match.c
1 /*
2 * Copyright (c) 2008-2017 Nicira, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18 #include "openvswitch/ofp-match.h"
19 #include "byte-order.h"
20 #include "flow.h"
21 #include "nx-match.h"
22 #include "openvswitch/match.h"
23 #include "openvswitch/ofp-errors.h"
24 #include "openvswitch/ofp-msgs.h"
25 #include "openvswitch/ofp-port.h"
26 #include "openvswitch/packets.h"
27 #include "openvswitch/vlog.h"
28
29 VLOG_DEFINE_THIS_MODULE(ofp_match);
30
31 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
32
33 /* Given the wildcard bit count in the least-significant 6 of 'wcbits', returns
34 * an IP netmask with a 1 in each bit that must match and a 0 in each bit that
35 * is wildcarded.
36 *
37 * The bits in 'wcbits' are in the format used in enum ofp_flow_wildcards: 0
38 * is exact match, 1 ignores the LSB, 2 ignores the 2 least-significant bits,
39 * ..., 32 and higher wildcard the entire field. This is the *opposite* of the
40 * usual convention where e.g. /24 indicates that 8 bits (not 24 bits) are
41 * wildcarded. */
42 static ovs_be32
43 ofputil_wcbits_to_netmask(int wcbits)
44 {
45 wcbits &= 0x3f;
46 return wcbits < 32 ? htonl(~((1u << wcbits) - 1)) : 0;
47 }
48
49 /* Given the IP netmask 'netmask', returns the number of bits of the IP address
50 * that it wildcards, that is, the number of 0-bits in 'netmask', a number
51 * between 0 and 32 inclusive.
52 *
53 * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will
54 * still be in the valid range but isn't otherwise meaningful. */
55 static int
56 ofputil_netmask_to_wcbits(ovs_be32 netmask)
57 {
58 return 32 - ip_count_cidr_bits(netmask);
59 }
60
61 /* Converts the OpenFlow 1.0 wildcards in 'ofpfw' (OFPFW10_*) into a
62 * flow_wildcards in 'wc' for use in struct match. It is the caller's
63 * responsibility to handle the special case where the flow match's dl_vlan is
64 * set to OFP_VLAN_NONE. */
65 void
66 ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
67 {
68 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
69
70 /* Initialize most of wc. */
71 flow_wildcards_init_catchall(wc);
72
73 if (!(ofpfw & OFPFW10_IN_PORT)) {
74 wc->masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
75 }
76
77 if (!(ofpfw & OFPFW10_NW_TOS)) {
78 wc->masks.nw_tos |= IP_DSCP_MASK;
79 }
80
81 if (!(ofpfw & OFPFW10_NW_PROTO)) {
82 wc->masks.nw_proto = UINT8_MAX;
83 }
84 wc->masks.nw_src = ofputil_wcbits_to_netmask(ofpfw
85 >> OFPFW10_NW_SRC_SHIFT);
86 wc->masks.nw_dst = ofputil_wcbits_to_netmask(ofpfw
87 >> OFPFW10_NW_DST_SHIFT);
88
89 if (!(ofpfw & OFPFW10_TP_SRC)) {
90 wc->masks.tp_src = OVS_BE16_MAX;
91 }
92 if (!(ofpfw & OFPFW10_TP_DST)) {
93 wc->masks.tp_dst = OVS_BE16_MAX;
94 }
95
96 if (!(ofpfw & OFPFW10_DL_SRC)) {
97 WC_MASK_FIELD(wc, dl_src);
98 }
99 if (!(ofpfw & OFPFW10_DL_DST)) {
100 WC_MASK_FIELD(wc, dl_dst);
101 }
102 if (!(ofpfw & OFPFW10_DL_TYPE)) {
103 wc->masks.dl_type = OVS_BE16_MAX;
104 }
105
106 /* VLAN TCI mask. */
107 if (!(ofpfw & OFPFW10_DL_VLAN_PCP)) {
108 wc->masks.vlans[0].tci |= htons(VLAN_PCP_MASK | VLAN_CFI);
109 }
110 if (!(ofpfw & OFPFW10_DL_VLAN)) {
111 wc->masks.vlans[0].tci |= htons(VLAN_VID_MASK | VLAN_CFI);
112 }
113 }
114
115 /* Converts the ofp10_match in 'ofmatch' into a struct match in 'match'. */
116 void
117 ofputil_match_from_ofp10_match(const struct ofp10_match *ofmatch,
118 struct match *match)
119 {
120 uint32_t ofpfw = ntohl(ofmatch->wildcards) & OFPFW10_ALL;
121
122 /* Initialize match->wc. */
123 memset(&match->flow, 0, sizeof match->flow);
124 ofputil_wildcard_from_ofpfw10(ofpfw, &match->wc);
125 memset(&match->tun_md, 0, sizeof match->tun_md);
126
127 /* If any fields, except in_port, are matched, then we also need to match
128 * on the Ethernet packet_type. */
129 const uint32_t ofpfw_data_bits = (OFPFW10_NW_TOS | OFPFW10_NW_PROTO
130 | OFPFW10_TP_SRC | OFPFW10_TP_DST
131 | OFPFW10_DL_SRC | OFPFW10_DL_DST
132 | OFPFW10_DL_TYPE
133 | OFPFW10_DL_VLAN | OFPFW10_DL_VLAN_PCP);
134 if ((ofpfw & ofpfw_data_bits) != ofpfw_data_bits
135 || ofputil_wcbits_to_netmask(ofpfw >> OFPFW10_NW_SRC_SHIFT)
136 || ofputil_wcbits_to_netmask(ofpfw >> OFPFW10_NW_DST_SHIFT)) {
137 match_set_default_packet_type(match);
138 }
139
140 /* Initialize most of match->flow. */
141 match->flow.nw_src = ofmatch->nw_src;
142 match->flow.nw_dst = ofmatch->nw_dst;
143 match->flow.in_port.ofp_port = u16_to_ofp(ntohs(ofmatch->in_port));
144 match->flow.dl_type = ofputil_dl_type_from_openflow(ofmatch->dl_type);
145 match->flow.tp_src = ofmatch->tp_src;
146 match->flow.tp_dst = ofmatch->tp_dst;
147 match->flow.dl_src = ofmatch->dl_src;
148 match->flow.dl_dst = ofmatch->dl_dst;
149 match->flow.nw_tos = ofmatch->nw_tos & IP_DSCP_MASK;
150 match->flow.nw_proto = ofmatch->nw_proto;
151
152 /* Translate VLANs. */
153 if (!(ofpfw & OFPFW10_DL_VLAN) &&
154 ofmatch->dl_vlan == htons(OFP10_VLAN_NONE)) {
155 /* Match only packets without 802.1Q header.
156 *
157 * When OFPFW10_DL_VLAN_PCP is wildcarded, this is obviously correct.
158 *
159 * If OFPFW10_DL_VLAN_PCP is matched, the flow match is contradictory,
160 * because we can't have a specific PCP without an 802.1Q header.
161 * However, older versions of OVS treated this as matching packets
162 * withut an 802.1Q header, so we do here too. */
163 match->flow.vlans[0].tci = htons(0);
164 match->wc.masks.vlans[0].tci = htons(0xffff);
165 } else {
166 ovs_be16 vid, pcp, tci;
167 uint16_t hpcp;
168
169 vid = ofmatch->dl_vlan & htons(VLAN_VID_MASK);
170 hpcp = (ofmatch->dl_vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK;
171 pcp = htons(hpcp);
172 tci = vid | pcp | htons(VLAN_CFI);
173 match->flow.vlans[0].tci = tci & match->wc.masks.vlans[0].tci;
174 }
175
176 /* Clean up. */
177 match_zero_wildcarded_fields(match);
178 }
179
180 /* Convert 'match' into the OpenFlow 1.0 match structure 'ofmatch'. */
181 void
182 ofputil_match_to_ofp10_match(const struct match *match,
183 struct ofp10_match *ofmatch)
184 {
185 const struct flow_wildcards *wc = &match->wc;
186 uint32_t ofpfw;
187
188 /* Figure out most OpenFlow wildcards. */
189 ofpfw = 0;
190 if (!wc->masks.in_port.ofp_port) {
191 ofpfw |= OFPFW10_IN_PORT;
192 }
193 if (!wc->masks.dl_type) {
194 ofpfw |= OFPFW10_DL_TYPE;
195 }
196 if (!wc->masks.nw_proto) {
197 ofpfw |= OFPFW10_NW_PROTO;
198 }
199 ofpfw |= (ofputil_netmask_to_wcbits(wc->masks.nw_src)
200 << OFPFW10_NW_SRC_SHIFT);
201 ofpfw |= (ofputil_netmask_to_wcbits(wc->masks.nw_dst)
202 << OFPFW10_NW_DST_SHIFT);
203 if (!(wc->masks.nw_tos & IP_DSCP_MASK)) {
204 ofpfw |= OFPFW10_NW_TOS;
205 }
206 if (!wc->masks.tp_src) {
207 ofpfw |= OFPFW10_TP_SRC;
208 }
209 if (!wc->masks.tp_dst) {
210 ofpfw |= OFPFW10_TP_DST;
211 }
212 if (eth_addr_is_zero(wc->masks.dl_src)) {
213 ofpfw |= OFPFW10_DL_SRC;
214 }
215 if (eth_addr_is_zero(wc->masks.dl_dst)) {
216 ofpfw |= OFPFW10_DL_DST;
217 }
218
219 /* Translate VLANs. */
220 ofmatch->dl_vlan = htons(0);
221 ofmatch->dl_vlan_pcp = 0;
222 if (match->wc.masks.vlans[0].tci == htons(0)) {
223 ofpfw |= OFPFW10_DL_VLAN | OFPFW10_DL_VLAN_PCP;
224 } else if (match->wc.masks.vlans[0].tci & htons(VLAN_CFI)
225 && !(match->flow.vlans[0].tci & htons(VLAN_CFI))) {
226 ofmatch->dl_vlan = htons(OFP10_VLAN_NONE);
227 } else {
228 if (!(match->wc.masks.vlans[0].tci & htons(VLAN_VID_MASK))) {
229 ofpfw |= OFPFW10_DL_VLAN;
230 } else {
231 ofmatch->dl_vlan =
232 htons(vlan_tci_to_vid(match->flow.vlans[0].tci));
233 }
234
235 if (!(match->wc.masks.vlans[0].tci & htons(VLAN_PCP_MASK))) {
236 ofpfw |= OFPFW10_DL_VLAN_PCP;
237 } else {
238 ofmatch->dl_vlan_pcp = vlan_tci_to_pcp(match->flow.vlans[0].tci);
239 }
240 }
241
242 /* Compose most of the match structure. */
243 ofmatch->wildcards = htonl(ofpfw);
244 ofmatch->in_port = htons(ofp_to_u16(match->flow.in_port.ofp_port));
245 ofmatch->dl_src = match->flow.dl_src;
246 ofmatch->dl_dst = match->flow.dl_dst;
247 ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
248 ofmatch->nw_src = match->flow.nw_src;
249 ofmatch->nw_dst = match->flow.nw_dst;
250 ofmatch->nw_tos = match->flow.nw_tos & IP_DSCP_MASK;
251 ofmatch->nw_proto = match->flow.nw_proto;
252 ofmatch->tp_src = match->flow.tp_src;
253 ofmatch->tp_dst = match->flow.tp_dst;
254 memset(ofmatch->pad1, '\0', sizeof ofmatch->pad1);
255 memset(ofmatch->pad2, '\0', sizeof ofmatch->pad2);
256 }
257
258 enum ofperr
259 ofputil_pull_ofp11_match(struct ofpbuf *buf, const struct tun_table *tun_table,
260 const struct vl_mff_map *vl_mff_map,
261 struct match *match, uint16_t *padded_match_len)
262 {
263 struct ofp11_match_header *omh = buf->data;
264 uint16_t match_len;
265
266 if (buf->size < sizeof *omh) {
267 return OFPERR_OFPBMC_BAD_LEN;
268 }
269
270 match_len = ntohs(omh->length);
271
272 switch (ntohs(omh->type)) {
273 case OFPMT_STANDARD: {
274 struct ofp11_match *om;
275
276 if (match_len != sizeof *om || buf->size < sizeof *om) {
277 return OFPERR_OFPBMC_BAD_LEN;
278 }
279 om = ofpbuf_pull(buf, sizeof *om);
280 if (padded_match_len) {
281 *padded_match_len = match_len;
282 }
283 return ofputil_match_from_ofp11_match(om, match);
284 }
285
286 case OFPMT_OXM:
287 if (padded_match_len) {
288 *padded_match_len = ROUND_UP(match_len, 8);
289 }
290 return oxm_pull_match(buf, false, tun_table, vl_mff_map, match);
291
292 default:
293 return OFPERR_OFPBMC_BAD_TYPE;
294 }
295 }
296
297 /* Converts the ofp11_match in 'ofmatch' into a struct match in 'match'.
298 * Returns 0 if successful, otherwise an OFPERR_* value. */
299 enum ofperr
300 ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
301 struct match *match)
302 {
303 uint16_t wc = ntohl(ofmatch->wildcards);
304 bool ipv4, arp, rarp;
305
306 match_init_catchall(match);
307 match->flow.tunnel.metadata.tab = NULL;
308
309 if (!(wc & OFPFW11_IN_PORT)) {
310 ofp_port_t ofp_port;
311 enum ofperr error;
312
313 error = ofputil_port_from_ofp11(ofmatch->in_port, &ofp_port);
314 if (error) {
315 return OFPERR_OFPBMC_BAD_VALUE;
316 }
317 match_set_in_port(match, ofp_port);
318 }
319
320 struct eth_addr dl_src_mask = eth_addr_invert(ofmatch->dl_src_mask);
321 struct eth_addr dl_dst_mask = eth_addr_invert(ofmatch->dl_dst_mask);
322 if (!eth_addr_is_zero(dl_src_mask) || !eth_addr_is_zero(dl_dst_mask)) {
323 match_set_dl_src_masked(match, ofmatch->dl_src, dl_src_mask);
324 match_set_dl_dst_masked(match, ofmatch->dl_dst, dl_dst_mask);
325 match_set_default_packet_type(match);
326 }
327
328 if (!(wc & OFPFW11_DL_VLAN)) {
329 if (ofmatch->dl_vlan == htons(OFPVID11_NONE)) {
330 /* Match only packets without a VLAN tag. */
331 match->flow.vlans[0].tci = htons(0);
332 match->wc.masks.vlans[0].tci = OVS_BE16_MAX;
333 } else {
334 if (ofmatch->dl_vlan == htons(OFPVID11_ANY)) {
335 /* Match any packet with a VLAN tag regardless of VID. */
336 match->flow.vlans[0].tci = htons(VLAN_CFI);
337 match->wc.masks.vlans[0].tci = htons(VLAN_CFI);
338 } else if (ntohs(ofmatch->dl_vlan) < 4096) {
339 /* Match only packets with the specified VLAN VID. */
340 match->flow.vlans[0].tci = htons(VLAN_CFI) | ofmatch->dl_vlan;
341 match->wc.masks.vlans[0].tci = htons(VLAN_CFI | VLAN_VID_MASK);
342 } else {
343 /* Invalid VID. */
344 return OFPERR_OFPBMC_BAD_VALUE;
345 }
346
347 if (!(wc & OFPFW11_DL_VLAN_PCP)) {
348 if (ofmatch->dl_vlan_pcp <= 7) {
349 match->flow.vlans[0].tci |= htons(ofmatch->dl_vlan_pcp
350 << VLAN_PCP_SHIFT);
351 match->wc.masks.vlans[0].tci |= htons(VLAN_PCP_MASK);
352 } else {
353 /* Invalid PCP. */
354 return OFPERR_OFPBMC_BAD_VALUE;
355 }
356 }
357 }
358 match_set_default_packet_type(match);
359 }
360
361 if (!(wc & OFPFW11_DL_TYPE)) {
362 match_set_dl_type(match,
363 ofputil_dl_type_from_openflow(ofmatch->dl_type));
364 match_set_default_packet_type(match);
365 }
366
367 ipv4 = match->flow.dl_type == htons(ETH_TYPE_IP);
368 arp = match->flow.dl_type == htons(ETH_TYPE_ARP);
369 rarp = match->flow.dl_type == htons(ETH_TYPE_RARP);
370
371 if (ipv4 && !(wc & OFPFW11_NW_TOS)) {
372 if (ofmatch->nw_tos & ~IP_DSCP_MASK) {
373 /* Invalid TOS. */
374 return OFPERR_OFPBMC_BAD_VALUE;
375 }
376
377 match_set_nw_dscp(match, ofmatch->nw_tos);
378 }
379
380 if (ipv4 || arp || rarp) {
381 if (!(wc & OFPFW11_NW_PROTO)) {
382 match_set_nw_proto(match, ofmatch->nw_proto);
383 }
384 match_set_nw_src_masked(match, ofmatch->nw_src, ~ofmatch->nw_src_mask);
385 match_set_nw_dst_masked(match, ofmatch->nw_dst, ~ofmatch->nw_dst_mask);
386 }
387
388 #define OFPFW11_TP_ALL (OFPFW11_TP_SRC | OFPFW11_TP_DST)
389 if (ipv4 && (wc & OFPFW11_TP_ALL) != OFPFW11_TP_ALL) {
390 switch (match->flow.nw_proto) {
391 case IPPROTO_ICMP:
392 /* "A.2.3 Flow Match Structures" in OF1.1 says:
393 *
394 * The tp_src and tp_dst fields will be ignored unless the
395 * network protocol specified is as TCP, UDP or SCTP.
396 *
397 * but I'm pretty sure we should support ICMP too, otherwise
398 * that's a regression from OF1.0. */
399 if (!(wc & OFPFW11_TP_SRC)) {
400 uint16_t icmp_type = ntohs(ofmatch->tp_src);
401 if (icmp_type < 0x100) {
402 match_set_icmp_type(match, icmp_type);
403 } else {
404 return OFPERR_OFPBMC_BAD_FIELD;
405 }
406 }
407 if (!(wc & OFPFW11_TP_DST)) {
408 uint16_t icmp_code = ntohs(ofmatch->tp_dst);
409 if (icmp_code < 0x100) {
410 match_set_icmp_code(match, icmp_code);
411 } else {
412 return OFPERR_OFPBMC_BAD_FIELD;
413 }
414 }
415 break;
416
417 case IPPROTO_TCP:
418 case IPPROTO_UDP:
419 case IPPROTO_SCTP:
420 if (!(wc & (OFPFW11_TP_SRC))) {
421 match_set_tp_src(match, ofmatch->tp_src);
422 }
423 if (!(wc & (OFPFW11_TP_DST))) {
424 match_set_tp_dst(match, ofmatch->tp_dst);
425 }
426 break;
427
428 default:
429 /* OF1.1 says explicitly to ignore this. */
430 break;
431 }
432 }
433
434 if (eth_type_mpls(match->flow.dl_type)) {
435 if (!(wc & OFPFW11_MPLS_LABEL)) {
436 match_set_mpls_label(match, 0, ofmatch->mpls_label);
437 }
438 if (!(wc & OFPFW11_MPLS_TC)) {
439 match_set_mpls_tc(match, 0, ofmatch->mpls_tc);
440 }
441 }
442
443 match_set_metadata_masked(match, ofmatch->metadata,
444 ~ofmatch->metadata_mask);
445
446 return 0;
447 }
448
449 /* Convert 'match' into the OpenFlow 1.1 match structure 'ofmatch'. */
450 void
451 ofputil_match_to_ofp11_match(const struct match *match,
452 struct ofp11_match *ofmatch)
453 {
454 uint32_t wc = 0;
455
456 memset(ofmatch, 0, sizeof *ofmatch);
457 ofmatch->omh.type = htons(OFPMT_STANDARD);
458 ofmatch->omh.length = htons(OFPMT11_STANDARD_LENGTH);
459
460 if (!match->wc.masks.in_port.ofp_port) {
461 wc |= OFPFW11_IN_PORT;
462 } else {
463 ofmatch->in_port = ofputil_port_to_ofp11(match->flow.in_port.ofp_port);
464 }
465
466 ofmatch->dl_src = match->flow.dl_src;
467 ofmatch->dl_src_mask = eth_addr_invert(match->wc.masks.dl_src);
468 ofmatch->dl_dst = match->flow.dl_dst;
469 ofmatch->dl_dst_mask = eth_addr_invert(match->wc.masks.dl_dst);
470
471 if (match->wc.masks.vlans[0].tci == htons(0)) {
472 wc |= OFPFW11_DL_VLAN | OFPFW11_DL_VLAN_PCP;
473 } else if (match->wc.masks.vlans[0].tci & htons(VLAN_CFI)
474 && !(match->flow.vlans[0].tci & htons(VLAN_CFI))) {
475 ofmatch->dl_vlan = htons(OFPVID11_NONE);
476 wc |= OFPFW11_DL_VLAN_PCP;
477 } else {
478 if (!(match->wc.masks.vlans[0].tci & htons(VLAN_VID_MASK))) {
479 ofmatch->dl_vlan = htons(OFPVID11_ANY);
480 } else {
481 ofmatch->dl_vlan =
482 htons(vlan_tci_to_vid(match->flow.vlans[0].tci));
483 }
484
485 if (!(match->wc.masks.vlans[0].tci & htons(VLAN_PCP_MASK))) {
486 wc |= OFPFW11_DL_VLAN_PCP;
487 } else {
488 ofmatch->dl_vlan_pcp = vlan_tci_to_pcp(match->flow.vlans[0].tci);
489 }
490 }
491
492 if (!match->wc.masks.dl_type) {
493 wc |= OFPFW11_DL_TYPE;
494 } else {
495 ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
496 }
497
498 if (!(match->wc.masks.nw_tos & IP_DSCP_MASK)) {
499 wc |= OFPFW11_NW_TOS;
500 } else {
501 ofmatch->nw_tos = match->flow.nw_tos & IP_DSCP_MASK;
502 }
503
504 if (!match->wc.masks.nw_proto) {
505 wc |= OFPFW11_NW_PROTO;
506 } else {
507 ofmatch->nw_proto = match->flow.nw_proto;
508 }
509
510 ofmatch->nw_src = match->flow.nw_src;
511 ofmatch->nw_src_mask = ~match->wc.masks.nw_src;
512 ofmatch->nw_dst = match->flow.nw_dst;
513 ofmatch->nw_dst_mask = ~match->wc.masks.nw_dst;
514
515 if (!match->wc.masks.tp_src) {
516 wc |= OFPFW11_TP_SRC;
517 } else {
518 ofmatch->tp_src = match->flow.tp_src;
519 }
520
521 if (!match->wc.masks.tp_dst) {
522 wc |= OFPFW11_TP_DST;
523 } else {
524 ofmatch->tp_dst = match->flow.tp_dst;
525 }
526
527 if (!(match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK))) {
528 wc |= OFPFW11_MPLS_LABEL;
529 } else {
530 ofmatch->mpls_label = htonl(mpls_lse_to_label(
531 match->flow.mpls_lse[0]));
532 }
533
534 if (!(match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK))) {
535 wc |= OFPFW11_MPLS_TC;
536 } else {
537 ofmatch->mpls_tc = mpls_lse_to_tc(match->flow.mpls_lse[0]);
538 }
539
540 ofmatch->metadata = match->flow.metadata;
541 ofmatch->metadata_mask = ~match->wc.masks.metadata;
542
543 ofmatch->wildcards = htonl(wc);
544 }
545
546 /* Returns the "typical" length of a match for 'protocol', for use in
547 * estimating space to preallocate. */
548 int
549 ofputil_match_typical_len(enum ofputil_protocol protocol)
550 {
551 switch (protocol) {
552 case OFPUTIL_P_OF10_STD:
553 case OFPUTIL_P_OF10_STD_TID:
554 return sizeof(struct ofp10_match);
555
556 case OFPUTIL_P_OF10_NXM:
557 case OFPUTIL_P_OF10_NXM_TID:
558 return NXM_TYPICAL_LEN;
559
560 case OFPUTIL_P_OF11_STD:
561 return sizeof(struct ofp11_match);
562
563 case OFPUTIL_P_OF12_OXM:
564 case OFPUTIL_P_OF13_OXM:
565 case OFPUTIL_P_OF14_OXM:
566 case OFPUTIL_P_OF15_OXM:
567 return NXM_TYPICAL_LEN;
568
569 default:
570 OVS_NOT_REACHED();
571 }
572 }
573
574 /* Appends to 'b' an struct ofp11_match_header followed by a match that
575 * expresses 'match' properly for 'protocol', plus enough zero bytes to pad the
576 * data appended out to a multiple of 8. 'protocol' must be one that is usable
577 * in OpenFlow 1.1 or later.
578 *
579 * This function can cause 'b''s data to be reallocated.
580 *
581 * Returns the number of bytes appended to 'b', excluding the padding. Never
582 * returns zero. */
583 int
584 ofputil_put_ofp11_match(struct ofpbuf *b, const struct match *match,
585 enum ofputil_protocol protocol)
586 {
587 switch (protocol) {
588 case OFPUTIL_P_OF10_STD:
589 case OFPUTIL_P_OF10_STD_TID:
590 case OFPUTIL_P_OF10_NXM:
591 case OFPUTIL_P_OF10_NXM_TID:
592 OVS_NOT_REACHED();
593
594 case OFPUTIL_P_OF11_STD: {
595 struct ofp11_match *om;
596
597 /* Make sure that no padding is needed. */
598 BUILD_ASSERT_DECL(sizeof *om % 8 == 0);
599
600 om = ofpbuf_put_uninit(b, sizeof *om);
601 ofputil_match_to_ofp11_match(match, om);
602 return sizeof *om;
603 }
604
605 case OFPUTIL_P_OF12_OXM:
606 case OFPUTIL_P_OF13_OXM:
607 case OFPUTIL_P_OF14_OXM:
608 case OFPUTIL_P_OF15_OXM:
609 return oxm_put_match(b, match,
610 ofputil_protocol_to_ofp_version(protocol));
611 }
612
613 OVS_NOT_REACHED();
614 }
615
616 /* Given a 'dl_type' value in the format used in struct flow, returns the
617 * corresponding 'dl_type' value for use in an ofp10_match or ofp11_match
618 * structure. */
619 ovs_be16
620 ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type)
621 {
622 return (flow_dl_type == htons(FLOW_DL_TYPE_NONE)
623 ? htons(OFP_DL_TYPE_NOT_ETH_TYPE)
624 : flow_dl_type);
625 }
626
627 /* Given a 'dl_type' value in the format used in an ofp10_match or ofp11_match
628 * structure, returns the corresponding 'dl_type' value for use in struct
629 * flow. */
630 ovs_be16
631 ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type)
632 {
633 return (ofp_dl_type == htons(OFP_DL_TYPE_NOT_ETH_TYPE)
634 ? htons(FLOW_DL_TYPE_NONE)
635 : ofp_dl_type);
636 }
637 \f
638 static void
639 encode_tlv_table_mappings(struct ofpbuf *b, struct ovs_list *mappings)
640 {
641 struct ofputil_tlv_map *map;
642
643 LIST_FOR_EACH (map, list_node, mappings) {
644 struct nx_tlv_map *nx_map;
645
646 nx_map = ofpbuf_put_zeros(b, sizeof *nx_map);
647 nx_map->option_class = htons(map->option_class);
648 nx_map->option_type = map->option_type;
649 nx_map->option_len = map->option_len;
650 nx_map->index = htons(map->index);
651 }
652 }
653
654 struct ofpbuf *
655 ofputil_encode_tlv_table_mod(enum ofp_version ofp_version,
656 struct ofputil_tlv_table_mod *ttm)
657 {
658 struct ofpbuf *b;
659 struct nx_tlv_table_mod *nx_ttm;
660
661 b = ofpraw_alloc(OFPRAW_NXT_TLV_TABLE_MOD, ofp_version, 0);
662 nx_ttm = ofpbuf_put_zeros(b, sizeof *nx_ttm);
663 nx_ttm->command = htons(ttm->command);
664 encode_tlv_table_mappings(b, &ttm->mappings);
665
666 return b;
667 }
668
669 static enum ofperr
670 decode_tlv_table_mappings(struct ofpbuf *msg, unsigned int max_fields,
671 struct ovs_list *mappings)
672 {
673 ovs_list_init(mappings);
674
675 while (msg->size) {
676 struct nx_tlv_map *nx_map;
677 struct ofputil_tlv_map *map;
678
679 nx_map = ofpbuf_pull(msg, sizeof *nx_map);
680 map = xmalloc(sizeof *map);
681 ovs_list_push_back(mappings, &map->list_node);
682
683 map->option_class = ntohs(nx_map->option_class);
684 map->option_type = nx_map->option_type;
685
686 map->option_len = nx_map->option_len;
687 if (map->option_len % 4 || map->option_len > TLV_MAX_OPT_SIZE) {
688 VLOG_WARN_RL(&rl, "tlv table option length (%u) is not a "
689 "valid option size", map->option_len);
690 ofputil_uninit_tlv_table(mappings);
691 return OFPERR_NXTTMFC_BAD_OPT_LEN;
692 }
693
694 map->index = ntohs(nx_map->index);
695 if (map->index >= max_fields) {
696 VLOG_WARN_RL(&rl, "tlv table field index (%u) is too large "
697 "(max %u)", map->index, max_fields - 1);
698 ofputil_uninit_tlv_table(mappings);
699 return OFPERR_NXTTMFC_BAD_FIELD_IDX;
700 }
701 }
702
703 return 0;
704 }
705
706 enum ofperr
707 ofputil_decode_tlv_table_mod(const struct ofp_header *oh,
708 struct ofputil_tlv_table_mod *ttm)
709 {
710 struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
711 ofpraw_pull_assert(&msg);
712
713 struct nx_tlv_table_mod *nx_ttm = ofpbuf_pull(&msg, sizeof *nx_ttm);
714 ttm->command = ntohs(nx_ttm->command);
715 if (ttm->command > NXTTMC_CLEAR) {
716 VLOG_WARN_RL(&rl, "tlv table mod command (%u) is out of range",
717 ttm->command);
718 return OFPERR_NXTTMFC_BAD_COMMAND;
719 }
720
721 return decode_tlv_table_mappings(&msg, TUN_METADATA_NUM_OPTS,
722 &ttm->mappings);
723 }
724
725 static void
726 print_tlv_table(struct ds *s, const struct ovs_list *mappings)
727 {
728 struct ofputil_tlv_map *map;
729
730 ds_put_cstr(s, " mapping table:\n");
731 ds_put_cstr(s, " class type length match field\n");
732 ds_put_cstr(s, " ------ ---- ------ --------------");
733
734 LIST_FOR_EACH (map, list_node, mappings) {
735 ds_put_format(s, "\n %#6"PRIx16" %#4"PRIx8" %6"PRIu8" "
736 "tun_metadata%"PRIu16,
737 map->option_class, map->option_type, map->option_len,
738 map->index);
739 }
740 }
741
742 void
743 ofputil_format_tlv_table_mod(struct ds *s,
744 const struct ofputil_tlv_table_mod *ttm)
745 {
746 ds_put_cstr(s, "\n ");
747
748 switch (ttm->command) {
749 case NXTTMC_ADD:
750 ds_put_cstr(s, "ADD");
751 break;
752 case NXTTMC_DELETE:
753 ds_put_cstr(s, "DEL");
754 break;
755 case NXTTMC_CLEAR:
756 ds_put_cstr(s, "CLEAR");
757 break;
758 }
759
760 if (ttm->command != NXTTMC_CLEAR) {
761 print_tlv_table(s, &ttm->mappings);
762 }
763 }
764
765 struct ofpbuf *
766 ofputil_encode_tlv_table_reply(const struct ofp_header *oh,
767 struct ofputil_tlv_table_reply *ttr)
768 {
769 struct ofpbuf *b;
770 struct nx_tlv_table_reply *nx_ttr;
771
772 b = ofpraw_alloc_reply(OFPRAW_NXT_TLV_TABLE_REPLY, oh, 0);
773 nx_ttr = ofpbuf_put_zeros(b, sizeof *nx_ttr);
774 nx_ttr->max_option_space = htonl(ttr->max_option_space);
775 nx_ttr->max_fields = htons(ttr->max_fields);
776
777 encode_tlv_table_mappings(b, &ttr->mappings);
778
779 return b;
780 }
781
782 /* Decodes the NXT_TLV_TABLE_REPLY message in 'oh' into '*ttr'. Returns 0
783 * if successful, otherwise an ofperr.
784 *
785 * The decoder verifies that the indexes in 'ttr->mappings' are less than
786 * 'ttr->max_fields', but the caller must ensure, if necessary, that they are
787 * less than TUN_METADATA_NUM_OPTS. */
788 enum ofperr
789 ofputil_decode_tlv_table_reply(const struct ofp_header *oh,
790 struct ofputil_tlv_table_reply *ttr)
791 {
792 struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
793 ofpraw_pull_assert(&msg);
794
795 struct nx_tlv_table_reply *nx_ttr = ofpbuf_pull(&msg, sizeof *nx_ttr);
796 ttr->max_option_space = ntohl(nx_ttr->max_option_space);
797 ttr->max_fields = ntohs(nx_ttr->max_fields);
798
799 return decode_tlv_table_mappings(&msg, ttr->max_fields, &ttr->mappings);
800 }
801
802 char * OVS_WARN_UNUSED_RESULT
803 parse_ofp_tlv_table_mod_str(struct ofputil_tlv_table_mod *ttm,
804 uint16_t command, const char *s,
805 enum ofputil_protocol *usable_protocols)
806 {
807 *usable_protocols = OFPUTIL_P_NXM_OXM_ANY;
808
809 ttm->command = command;
810 ovs_list_init(&ttm->mappings);
811
812 while (*s) {
813 struct ofputil_tlv_map *map = xmalloc(sizeof *map);
814 int n;
815
816 if (*s == ',') {
817 s++;
818 }
819
820 ovs_list_push_back(&ttm->mappings, &map->list_node);
821
822 if (!ovs_scan(s, "{class=%"SCNi16",type=%"SCNi8",len=%"SCNi8"}"
823 "->tun_metadata%"SCNi16"%n",
824 &map->option_class, &map->option_type, &map->option_len,
825 &map->index, &n)) {
826 ofputil_uninit_tlv_table(&ttm->mappings);
827 return xstrdup("invalid tlv mapping");
828 }
829
830 s += n;
831 }
832
833 return NULL;
834 }
835
836 void
837 ofputil_format_tlv_table_reply(struct ds *s,
838 const struct ofputil_tlv_table_reply *ttr)
839 {
840 ds_put_char(s, '\n');
841
842 const struct ofputil_tlv_map *map;
843 int allocated_space = 0;
844 LIST_FOR_EACH (map, list_node, &ttr->mappings) {
845 allocated_space += map->option_len;
846 }
847
848 ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n",
849 ttr->max_option_space, ttr->max_fields);
850 ds_put_format(s, " allocated option space=%d\n", allocated_space);
851 ds_put_char(s, '\n');
852 print_tlv_table(s, &ttr->mappings);
853 }
854
855 void
856 ofputil_uninit_tlv_table(struct ovs_list *mappings)
857 {
858 struct ofputil_tlv_map *map;
859
860 LIST_FOR_EACH_POP (map, list_node, mappings) {
861 free(map);
862 }
863 }
864 \f
865 static void
866 ofputil_normalize_match__(struct match *match, bool may_log)
867 {
868 enum {
869 MAY_NW_ADDR = 1 << 0, /* nw_src, nw_dst */
870 MAY_TP_ADDR = 1 << 1, /* tp_src, tp_dst */
871 MAY_NW_PROTO = 1 << 2, /* nw_proto */
872 MAY_IPVx = 1 << 3, /* tos, frag, ttl */
873 MAY_ARP_SHA = 1 << 4, /* arp_sha */
874 MAY_ARP_THA = 1 << 5, /* arp_tha */
875 MAY_IPV6 = 1 << 6, /* ipv6_src, ipv6_dst, ipv6_label */
876 MAY_ND_TARGET = 1 << 7, /* nd_target */
877 MAY_MPLS = 1 << 8, /* mpls label and tc */
878 MAY_ETHER = 1 << 9, /* dl_src, dl_dst */
879 } may_match;
880
881 struct flow_wildcards wc = match->wc;
882 ovs_be16 dl_type;
883
884 /* Figure out what fields may be matched. */
885 /* Check the packet_type first and extract dl_type. */
886 if (wc.masks.packet_type == 0 || match_has_default_packet_type(match)) {
887 may_match = MAY_ETHER;
888 dl_type = match->flow.dl_type;
889 } else if (wc.masks.packet_type == OVS_BE32_MAX &&
890 pt_ns(match->flow.packet_type) == OFPHTN_ETHERTYPE) {
891 may_match = 0;
892 dl_type = pt_ns_type_be(match->flow.packet_type);
893 } else {
894 may_match = 0;
895 dl_type = 0;
896 }
897 if (dl_type == htons(ETH_TYPE_IP)) {
898 may_match |= MAY_NW_PROTO | MAY_IPVx | MAY_NW_ADDR;
899 if (match->flow.nw_proto == IPPROTO_TCP ||
900 match->flow.nw_proto == IPPROTO_UDP ||
901 match->flow.nw_proto == IPPROTO_SCTP ||
902 match->flow.nw_proto == IPPROTO_ICMP) {
903 may_match |= MAY_TP_ADDR;
904 }
905 } else if (dl_type == htons(ETH_TYPE_IPV6)) {
906 may_match |= MAY_NW_PROTO | MAY_IPVx | MAY_IPV6;
907 if (match->flow.nw_proto == IPPROTO_TCP ||
908 match->flow.nw_proto == IPPROTO_UDP ||
909 match->flow.nw_proto == IPPROTO_SCTP) {
910 may_match |= MAY_TP_ADDR;
911 } else if (match->flow.nw_proto == IPPROTO_ICMPV6) {
912 may_match |= MAY_TP_ADDR;
913 if (match->flow.tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
914 may_match |= MAY_ND_TARGET | MAY_ARP_SHA;
915 } else if (match->flow.tp_src == htons(ND_NEIGHBOR_ADVERT)) {
916 may_match |= MAY_ND_TARGET | MAY_ARP_THA;
917 }
918 }
919 } else if (dl_type == htons(ETH_TYPE_ARP) ||
920 dl_type == htons(ETH_TYPE_RARP)) {
921 may_match |= MAY_NW_PROTO | MAY_NW_ADDR | MAY_ARP_SHA | MAY_ARP_THA;
922 } else if (eth_type_mpls(dl_type)) {
923 may_match |= MAY_MPLS;
924 }
925
926 /* Clear the fields that may not be matched. */
927 if (!(may_match & MAY_ETHER)) {
928 wc.masks.dl_src = wc.masks.dl_dst = eth_addr_zero;
929 }
930 if (!(may_match & MAY_NW_ADDR)) {
931 wc.masks.nw_src = wc.masks.nw_dst = htonl(0);
932 }
933 if (!(may_match & MAY_TP_ADDR)) {
934 wc.masks.tp_src = wc.masks.tp_dst = htons(0);
935 }
936 if (!(may_match & MAY_NW_PROTO)) {
937 wc.masks.nw_proto = 0;
938 }
939 if (!(may_match & MAY_IPVx)) {
940 wc.masks.nw_tos = 0;
941 wc.masks.nw_ttl = 0;
942 }
943 if (!(may_match & MAY_ARP_SHA)) {
944 WC_UNMASK_FIELD(&wc, arp_sha);
945 }
946 if (!(may_match & MAY_ARP_THA)) {
947 WC_UNMASK_FIELD(&wc, arp_tha);
948 }
949 if (!(may_match & MAY_IPV6)) {
950 wc.masks.ipv6_src = wc.masks.ipv6_dst = in6addr_any;
951 wc.masks.ipv6_label = htonl(0);
952 }
953 if (!(may_match & MAY_ND_TARGET)) {
954 wc.masks.nd_target = in6addr_any;
955 }
956 if (!(may_match & MAY_MPLS)) {
957 memset(wc.masks.mpls_lse, 0, sizeof wc.masks.mpls_lse);
958 }
959
960 /* Log any changes. */
961 if (!flow_wildcards_equal(&wc, &match->wc)) {
962 bool log = may_log && !VLOG_DROP_INFO(&rl);
963 char *pre = (log
964 ? match_to_string(match, NULL, OFP_DEFAULT_PRIORITY)
965 : NULL);
966
967 match->wc = wc;
968 match_zero_wildcarded_fields(match);
969
970 if (log) {
971 char *post = match_to_string(match, NULL, OFP_DEFAULT_PRIORITY);
972 VLOG_INFO("normalization changed ofp_match, details:");
973 VLOG_INFO(" pre: %s", pre);
974 VLOG_INFO("post: %s", post);
975 free(pre);
976 free(post);
977 }
978 }
979 }
980
981 /* "Normalizes" the wildcards in 'match'. That means:
982 *
983 * 1. If the type of level N is known, then only the valid fields for that
984 * level may be specified. For example, ARP does not have a TOS field,
985 * so nw_tos must be wildcarded if 'match' specifies an ARP flow.
986 * Similarly, IPv4 does not have any IPv6 addresses, so ipv6_src and
987 * ipv6_dst (and other fields) must be wildcarded if 'match' specifies an
988 * IPv4 flow.
989 *
990 * 2. If the type of level N is not known (or not understood by Open
991 * vSwitch), then no fields at all for that level may be specified. For
992 * example, Open vSwitch does not understand SCTP, an L4 protocol, so the
993 * L4 fields tp_src and tp_dst must be wildcarded if 'match' specifies an
994 * SCTP flow.
995 *
996 * If this function changes 'match', it logs a rate-limited informational
997 * message. */
998 void
999 ofputil_normalize_match(struct match *match)
1000 {
1001 ofputil_normalize_match__(match, true);
1002 }
1003
1004 /* Same as ofputil_normalize_match() without the logging. Thus, this function
1005 * is suitable for a program's internal use, whereas ofputil_normalize_match()
1006 * sense for use on flows received from elsewhere (so that a bug in the program
1007 * that sent them can be reported and corrected). */
1008 void
1009 ofputil_normalize_match_quiet(struct match *match)
1010 {
1011 ofputil_normalize_match__(match, false);
1012 }
1013 \f
1014 static void OVS_PRINTF_FORMAT(5, 6)
1015 print_wild(struct ds *string, const char *leader, int is_wild,
1016 int verbosity, const char *format, ...)
1017 {
1018 if (is_wild && verbosity < 2) {
1019 return;
1020 }
1021 ds_put_cstr(string, leader);
1022 if (!is_wild) {
1023 va_list args;
1024
1025 va_start(args, format);
1026 ds_put_format_valist(string, format, args);
1027 va_end(args);
1028 } else {
1029 ds_put_char(string, '*');
1030 }
1031 ds_put_char(string, ',');
1032 }
1033
1034 static void
1035 print_wild_port(struct ds *string, const char *leader, int is_wild,
1036 int verbosity, ofp_port_t port,
1037 const struct ofputil_port_map *port_map)
1038 {
1039 if (is_wild && verbosity < 2) {
1040 return;
1041 }
1042 ds_put_cstr(string, leader);
1043 if (!is_wild) {
1044 ofputil_format_port(port, port_map, string);
1045 } else {
1046 ds_put_char(string, '*');
1047 }
1048 ds_put_char(string, ',');
1049 }
1050
1051 static void
1052 print_ip_netmask(struct ds *string, const char *leader, ovs_be32 ip,
1053 uint32_t wild_bits, int verbosity)
1054 {
1055 if (wild_bits >= 32 && verbosity < 2) {
1056 return;
1057 }
1058 ds_put_cstr(string, leader);
1059 if (wild_bits < 32) {
1060 ds_put_format(string, IP_FMT, IP_ARGS(ip));
1061 if (wild_bits) {
1062 ds_put_format(string, "/%d", 32 - wild_bits);
1063 }
1064 } else {
1065 ds_put_char(string, '*');
1066 }
1067 ds_put_char(string, ',');
1068 }
1069
1070 void
1071 ofp10_match_print(struct ds *f, const struct ofp10_match *om,
1072 const struct ofputil_port_map *port_map, int verbosity)
1073 {
1074 char *s = ofp10_match_to_string(om, port_map, verbosity);
1075 ds_put_cstr(f, s);
1076 free(s);
1077 }
1078
1079 char *
1080 ofp10_match_to_string(const struct ofp10_match *om,
1081 const struct ofputil_port_map *port_map, int verbosity)
1082 {
1083 struct ds f = DS_EMPTY_INITIALIZER;
1084 uint32_t w = ntohl(om->wildcards);
1085 bool skip_type = false;
1086 bool skip_proto = false;
1087
1088 if (!(w & OFPFW10_DL_TYPE)) {
1089 skip_type = true;
1090 if (om->dl_type == htons(ETH_TYPE_IP)) {
1091 if (!(w & OFPFW10_NW_PROTO)) {
1092 skip_proto = true;
1093 if (om->nw_proto == IPPROTO_ICMP) {
1094 ds_put_cstr(&f, "icmp,");
1095 } else if (om->nw_proto == IPPROTO_TCP) {
1096 ds_put_cstr(&f, "tcp,");
1097 } else if (om->nw_proto == IPPROTO_UDP) {
1098 ds_put_cstr(&f, "udp,");
1099 } else if (om->nw_proto == IPPROTO_SCTP) {
1100 ds_put_cstr(&f, "sctp,");
1101 } else {
1102 ds_put_cstr(&f, "ip,");
1103 skip_proto = false;
1104 }
1105 } else {
1106 ds_put_cstr(&f, "ip,");
1107 }
1108 } else if (om->dl_type == htons(ETH_TYPE_ARP)) {
1109 ds_put_cstr(&f, "arp,");
1110 } else if (om->dl_type == htons(ETH_TYPE_RARP)){
1111 ds_put_cstr(&f, "rarp,");
1112 } else if (om->dl_type == htons(ETH_TYPE_MPLS)) {
1113 ds_put_cstr(&f, "mpls,");
1114 } else if (om->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
1115 ds_put_cstr(&f, "mplsm,");
1116 } else {
1117 skip_type = false;
1118 }
1119 }
1120 print_wild_port(&f, "in_port=", w & OFPFW10_IN_PORT, verbosity,
1121 u16_to_ofp(ntohs(om->in_port)), port_map);
1122 print_wild(&f, "dl_vlan=", w & OFPFW10_DL_VLAN, verbosity,
1123 "%d", ntohs(om->dl_vlan));
1124 print_wild(&f, "dl_vlan_pcp=", w & OFPFW10_DL_VLAN_PCP, verbosity,
1125 "%d", om->dl_vlan_pcp);
1126 print_wild(&f, "dl_src=", w & OFPFW10_DL_SRC, verbosity,
1127 ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
1128 print_wild(&f, "dl_dst=", w & OFPFW10_DL_DST, verbosity,
1129 ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst));
1130 if (!skip_type) {
1131 print_wild(&f, "dl_type=", w & OFPFW10_DL_TYPE, verbosity,
1132 "0x%04x", ntohs(om->dl_type));
1133 }
1134 print_ip_netmask(&f, "nw_src=", om->nw_src,
1135 (w & OFPFW10_NW_SRC_MASK) >> OFPFW10_NW_SRC_SHIFT,
1136 verbosity);
1137 print_ip_netmask(&f, "nw_dst=", om->nw_dst,
1138 (w & OFPFW10_NW_DST_MASK) >> OFPFW10_NW_DST_SHIFT,
1139 verbosity);
1140 if (!skip_proto) {
1141 if (om->dl_type == htons(ETH_TYPE_ARP) ||
1142 om->dl_type == htons(ETH_TYPE_RARP)) {
1143 print_wild(&f, "arp_op=", w & OFPFW10_NW_PROTO, verbosity,
1144 "%u", om->nw_proto);
1145 } else {
1146 print_wild(&f, "nw_proto=", w & OFPFW10_NW_PROTO, verbosity,
1147 "%u", om->nw_proto);
1148 }
1149 }
1150 print_wild(&f, "nw_tos=", w & OFPFW10_NW_TOS, verbosity,
1151 "%u", om->nw_tos);
1152 if (om->nw_proto == IPPROTO_ICMP) {
1153 print_wild(&f, "icmp_type=", w & OFPFW10_ICMP_TYPE, verbosity,
1154 "%d", ntohs(om->tp_src));
1155 print_wild(&f, "icmp_code=", w & OFPFW10_ICMP_CODE, verbosity,
1156 "%d", ntohs(om->tp_dst));
1157 } else {
1158 print_wild(&f, "tp_src=", w & OFPFW10_TP_SRC, verbosity,
1159 "%d", ntohs(om->tp_src));
1160 print_wild(&f, "tp_dst=", w & OFPFW10_TP_DST, verbosity,
1161 "%d", ntohs(om->tp_dst));
1162 }
1163 ds_chomp(&f, ',');
1164 return ds_cstr(&f);
1165 }
1166