]> git.proxmox.com Git - mirror_ovs.git/blame - lib/match.c
classifier: Change type used for priorities from 'unsigned int' to 'int'.
[mirror_ovs.git] / lib / match.c
CommitLineData
81a76618 1/*
8bfd0fda 2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
81a76618
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>
18#include "match.h"
81a76618
BP
19#include <stdlib.h>
20#include "byte-order.h"
21#include "dynamic-string.h"
576ec803 22#include "ofp-util.h"
81a76618
BP
23#include "packets.h"
24
25/* Converts the flow in 'flow' into a match in 'match', with the given
26 * 'wildcards'. */
27void
28match_init(struct match *match,
29 const struct flow *flow, const struct flow_wildcards *wc)
30{
31 match->flow = *flow;
32 match->wc = *wc;
33 match_zero_wildcarded_fields(match);
34}
35
aa6c9932
MM
36/* Converts a flow into a match. It sets the wildcard masks based on
37 * the packet contents. It will not set the mask for fields that do not
38 * make sense for the packet type. */
39void
40match_wc_init(struct match *match, const struct flow *flow)
41{
aa6c9932 42 match->flow = *flow;
aa6c9932 43
78c9486d
JR
44 flow_wildcards_init_for_packet(&match->wc, flow);
45 WC_MASK_FIELD(&match->wc, regs);
46 WC_MASK_FIELD(&match->wc, metadata);
aa6c9932
MM
47}
48
81a76618
BP
49/* Initializes 'match' as a "catch-all" match that matches every packet. */
50void
51match_init_catchall(struct match *match)
52{
53 memset(&match->flow, 0, sizeof match->flow);
54 flow_wildcards_init_catchall(&match->wc);
55}
56
57/* For each bit or field wildcarded in 'match', sets the corresponding bit or
58 * field in 'flow' to all-0-bits. It is important to maintain this invariant
59 * in a match that might be inserted into a classifier.
60 *
61 * It is never necessary to call this function directly for a match that is
62 * initialized or modified only by match_*() functions. It is useful to
63 * restore the invariant in a match whose 'wc' member is modified by hand.
64 */
65void
66match_zero_wildcarded_fields(struct match *match)
67{
68 flow_zero_wildcards(&match->flow, &match->wc);
69}
70
a79f29f2
AZ
71void
72match_set_dp_hash(struct match *match, uint32_t value)
73{
74 match_set_dp_hash_masked(match, value, UINT32_MAX);
75}
76
77void
78match_set_dp_hash_masked(struct match *match, uint32_t value, uint32_t mask)
79{
80 match->wc.masks.dp_hash = mask;
81 match->flow.dp_hash = value & mask;
82}
83
84void
85match_set_recirc_id(struct match *match, uint32_t value)
86{
87 match->flow.recirc_id = value;
88 match->wc.masks.recirc_id = UINT32_MAX;
89}
90
81a76618
BP
91void
92match_set_reg(struct match *match, unsigned int reg_idx, uint32_t value)
93{
94 match_set_reg_masked(match, reg_idx, value, UINT32_MAX);
95}
96
97void
98match_set_reg_masked(struct match *match, unsigned int reg_idx,
99 uint32_t value, uint32_t mask)
100{
cb22974d 101 ovs_assert(reg_idx < FLOW_N_REGS);
81a76618
BP
102 flow_wildcards_set_reg_mask(&match->wc, reg_idx, mask);
103 match->flow.regs[reg_idx] = value & mask;
104}
105
79fe0f46
BP
106void
107match_set_xreg(struct match *match, unsigned int xreg_idx, uint64_t value)
108{
109 match_set_xreg_masked(match, xreg_idx, value, UINT64_MAX);
110}
111
112void
113match_set_xreg_masked(struct match *match, unsigned int xreg_idx,
114 uint64_t value, uint64_t mask)
115{
116 ovs_assert(xreg_idx < FLOW_N_XREGS);
117 flow_wildcards_set_xreg_mask(&match->wc, xreg_idx, mask);
118 flow_set_xreg(&match->flow, xreg_idx, value & mask);
119}
120
81a76618
BP
121void
122match_set_metadata(struct match *match, ovs_be64 metadata)
123{
b8266395 124 match_set_metadata_masked(match, metadata, OVS_BE64_MAX);
81a76618
BP
125}
126
127void
128match_set_metadata_masked(struct match *match,
129 ovs_be64 metadata, ovs_be64 mask)
130{
131 match->wc.masks.metadata = mask;
132 match->flow.metadata = metadata & mask;
133}
134
135void
136match_set_tun_id(struct match *match, ovs_be64 tun_id)
137{
b8266395 138 match_set_tun_id_masked(match, tun_id, OVS_BE64_MAX);
81a76618
BP
139}
140
141void
142match_set_tun_id_masked(struct match *match, ovs_be64 tun_id, ovs_be64 mask)
143{
296e07ac
JG
144 match->wc.masks.tunnel.tun_id = mask;
145 match->flow.tunnel.tun_id = tun_id & mask;
81a76618
BP
146}
147
4fe3445a
PS
148void
149match_set_tun_src(struct match *match, ovs_be32 src)
150{
b8266395 151 match_set_tun_src_masked(match, src, OVS_BE32_MAX);
4fe3445a
PS
152}
153
154void
155match_set_tun_src_masked(struct match *match, ovs_be32 src, ovs_be32 mask)
156{
157 match->wc.masks.tunnel.ip_src = mask;
158 match->flow.tunnel.ip_src = src & mask;
159}
160
161void
162match_set_tun_dst(struct match *match, ovs_be32 dst)
163{
b8266395 164 match_set_tun_dst_masked(match, dst, OVS_BE32_MAX);
4fe3445a
PS
165}
166
167void
168match_set_tun_dst_masked(struct match *match, ovs_be32 dst, ovs_be32 mask)
169{
170 match->wc.masks.tunnel.ip_dst = mask;
171 match->flow.tunnel.ip_dst = dst & mask;
172}
173
174void
175match_set_tun_ttl(struct match *match, uint8_t ttl)
176{
177 match_set_tun_ttl_masked(match, ttl, UINT8_MAX);
178}
179
180void
181match_set_tun_ttl_masked(struct match *match, uint8_t ttl, uint8_t mask)
182{
183 match->wc.masks.tunnel.ip_ttl = mask;
184 match->flow.tunnel.ip_ttl = ttl & mask;
185}
186
187void
188match_set_tun_tos(struct match *match, uint8_t tos)
189{
190 match_set_tun_tos_masked(match, tos, UINT8_MAX);
191}
192
193void
194match_set_tun_tos_masked(struct match *match, uint8_t tos, uint8_t mask)
195{
196 match->wc.masks.tunnel.ip_tos = mask;
197 match->flow.tunnel.ip_tos = tos & mask;
198}
199
200void
201match_set_tun_flags(struct match *match, uint16_t flags)
202{
203 match_set_tun_flags_masked(match, flags, UINT16_MAX);
204}
205
206void
207match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask)
208{
209 match->wc.masks.tunnel.flags = mask;
210 match->flow.tunnel.flags = flags & mask;
211}
212
81a76618 213void
4e022ec0 214match_set_in_port(struct match *match, ofp_port_t ofp_port)
81a76618 215{
4e022ec0
AW
216 match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
217 match->flow.in_port.ofp_port = ofp_port;
81a76618
BP
218}
219
1b567fb9
AA
220void
221match_set_skb_priority(struct match *match, uint32_t skb_priority)
222{
223 match->wc.masks.skb_priority = UINT32_MAX;
224 match->flow.skb_priority = skb_priority;
225}
226
227void
1362e248 228match_set_pkt_mark(struct match *match, uint32_t pkt_mark)
1b567fb9 229{
ac923e91
JG
230 match_set_pkt_mark_masked(match, pkt_mark, UINT32_MAX);
231}
232
233void
234match_set_pkt_mark_masked(struct match *match, uint32_t pkt_mark, uint32_t mask)
235{
236 match->flow.pkt_mark = pkt_mark & mask;
237 match->wc.masks.pkt_mark = mask;
1b567fb9
AA
238}
239
81a76618
BP
240void
241match_set_dl_type(struct match *match, ovs_be16 dl_type)
242{
b8266395 243 match->wc.masks.dl_type = OVS_BE16_MAX;
81a76618
BP
244 match->flow.dl_type = dl_type;
245}
246
247/* Modifies 'value_src' so that the Ethernet address must match 'value_dst'
248 * exactly. 'mask_dst' is set to all 1s. */
249static void
250set_eth(const uint8_t value_src[ETH_ADDR_LEN],
251 uint8_t value_dst[ETH_ADDR_LEN],
252 uint8_t mask_dst[ETH_ADDR_LEN])
253{
254 memcpy(value_dst, value_src, ETH_ADDR_LEN);
255 memset(mask_dst, 0xff, ETH_ADDR_LEN);
256}
257
258/* Modifies 'value_src' so that the Ethernet address must match 'value_src'
259 * after each byte is ANDed with the appropriate byte in 'mask_src'.
260 * 'mask_dst' is set to 'mask_src' */
261static void
262set_eth_masked(const uint8_t value_src[ETH_ADDR_LEN],
263 const uint8_t mask_src[ETH_ADDR_LEN],
264 uint8_t value_dst[ETH_ADDR_LEN],
265 uint8_t mask_dst[ETH_ADDR_LEN])
266{
267 size_t i;
268
269 for (i = 0; i < ETH_ADDR_LEN; i++) {
270 value_dst[i] = value_src[i] & mask_src[i];
271 mask_dst[i] = mask_src[i];
272 }
273}
274
275/* Modifies 'rule' so that the source Ethernet address must match 'dl_src'
276 * exactly. */
277void
278match_set_dl_src(struct match *match, const uint8_t dl_src[ETH_ADDR_LEN])
279{
280 set_eth(dl_src, match->flow.dl_src, match->wc.masks.dl_src);
281}
282
283/* Modifies 'rule' so that the source Ethernet address must match 'dl_src'
284 * after each byte is ANDed with the appropriate byte in 'mask'. */
285void
286match_set_dl_src_masked(struct match *match,
287 const uint8_t dl_src[ETH_ADDR_LEN],
288 const uint8_t mask[ETH_ADDR_LEN])
289{
290 set_eth_masked(dl_src, mask, match->flow.dl_src, match->wc.masks.dl_src);
291}
292
293/* Modifies 'match' so that the Ethernet address must match 'dl_dst'
294 * exactly. */
295void
296match_set_dl_dst(struct match *match, const uint8_t dl_dst[ETH_ADDR_LEN])
297{
298 set_eth(dl_dst, match->flow.dl_dst, match->wc.masks.dl_dst);
299}
300
301/* Modifies 'match' so that the Ethernet address must match 'dl_dst' after each
302 * byte is ANDed with the appropriate byte in 'mask'.
303 *
304 * This function will assert-fail if 'mask' is invalid. Only 'mask' values
305 * accepted by flow_wildcards_is_dl_dst_mask_valid() are allowed. */
306void
307match_set_dl_dst_masked(struct match *match,
308 const uint8_t dl_dst[ETH_ADDR_LEN],
309 const uint8_t mask[ETH_ADDR_LEN])
310{
311 set_eth_masked(dl_dst, mask, match->flow.dl_dst, match->wc.masks.dl_dst);
312}
313
314void
315match_set_dl_tci(struct match *match, ovs_be16 tci)
316{
317 match_set_dl_tci_masked(match, tci, htons(0xffff));
318}
319
320void
321match_set_dl_tci_masked(struct match *match, ovs_be16 tci, ovs_be16 mask)
322{
323 match->flow.vlan_tci = tci & mask;
324 match->wc.masks.vlan_tci = mask;
325}
326
327/* Modifies 'match' so that the VLAN VID is wildcarded. If the PCP is already
328 * wildcarded, then 'match' will match a packet regardless of whether it has an
329 * 802.1Q header or not. */
330void
331match_set_any_vid(struct match *match)
332{
333 if (match->wc.masks.vlan_tci & htons(VLAN_PCP_MASK)) {
334 match->wc.masks.vlan_tci &= ~htons(VLAN_VID_MASK);
335 match->flow.vlan_tci &= ~htons(VLAN_VID_MASK);
336 } else {
337 match_set_dl_tci_masked(match, htons(0), htons(0));
338 }
339}
340
341/* Modifies 'match' depending on 'dl_vlan':
342 *
343 * - If 'dl_vlan' is htons(OFP_VLAN_NONE), makes 'match' match only packets
344 * without an 802.1Q header.
345 *
346 * - Otherwise, makes 'match' match only packets with an 802.1Q header whose
347 * VID equals the low 12 bits of 'dl_vlan'.
348 */
349void
350match_set_dl_vlan(struct match *match, ovs_be16 dl_vlan)
351{
352 flow_set_dl_vlan(&match->flow, dl_vlan);
353 if (dl_vlan == htons(OFP10_VLAN_NONE)) {
b8266395 354 match->wc.masks.vlan_tci = OVS_BE16_MAX;
81a76618
BP
355 } else {
356 match->wc.masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
357 }
358}
359
360/* Sets the VLAN VID that 'match' matches to 'vid', which is interpreted as an
361 * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
362 * plus CFI). */
363void
364match_set_vlan_vid(struct match *match, ovs_be16 vid)
365{
366 match_set_vlan_vid_masked(match, vid, htons(VLAN_VID_MASK | VLAN_CFI));
367}
368
369
370/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
371 * OpenFlow 1.2 "vlan_vid" value, that is, the low 13 bits of 'vlan_tci' (VID
372 * plus CFI), with the corresponding 'mask'. */
373void
374match_set_vlan_vid_masked(struct match *match, ovs_be16 vid, ovs_be16 mask)
375{
376 ovs_be16 pcp_mask = htons(VLAN_PCP_MASK);
377 ovs_be16 vid_mask = htons(VLAN_VID_MASK | VLAN_CFI);
378
379 mask &= vid_mask;
380 flow_set_vlan_vid(&match->flow, vid & mask);
381 match->wc.masks.vlan_tci = mask | (match->wc.masks.vlan_tci & pcp_mask);
382}
383
384/* Modifies 'match' so that the VLAN PCP is wildcarded. If the VID is already
385 * wildcarded, then 'match' will match a packet regardless of whether it has an
386 * 802.1Q header or not. */
387void
388match_set_any_pcp(struct match *match)
389{
390 if (match->wc.masks.vlan_tci & htons(VLAN_VID_MASK)) {
391 match->wc.masks.vlan_tci &= ~htons(VLAN_PCP_MASK);
392 match->flow.vlan_tci &= ~htons(VLAN_PCP_MASK);
393 } else {
394 match_set_dl_tci_masked(match, htons(0), htons(0));
395 }
396}
397
398/* Modifies 'match' so that it matches only packets with an 802.1Q header whose
399 * PCP equals the low 3 bits of 'dl_vlan_pcp'. */
400void
401match_set_dl_vlan_pcp(struct match *match, uint8_t dl_vlan_pcp)
402{
403 flow_set_vlan_pcp(&match->flow, dl_vlan_pcp);
404 match->wc.masks.vlan_tci |= htons(VLAN_CFI | VLAN_PCP_MASK);
405}
406
8bfd0fda
BP
407/* Modifies 'match' so that the MPLS label 'idx' matches 'lse' exactly. */
408void
409match_set_mpls_lse(struct match *match, int idx, ovs_be32 lse)
410{
411 match->wc.masks.mpls_lse[idx] = OVS_BE32_MAX;
412 match->flow.mpls_lse[idx] = lse;
413}
414
b02475c5
SH
415/* Modifies 'match' so that the MPLS label is wildcarded. */
416void
8bfd0fda 417match_set_any_mpls_label(struct match *match, int idx)
b02475c5 418{
8bfd0fda
BP
419 match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_LABEL_MASK);
420 flow_set_mpls_label(&match->flow, idx, htonl(0));
b02475c5
SH
421}
422
423/* Modifies 'match' so that it matches only packets with an MPLS header whose
424 * label equals the low 20 bits of 'mpls_label'. */
425void
8bfd0fda 426match_set_mpls_label(struct match *match, int idx, ovs_be32 mpls_label)
b02475c5 427{
8bfd0fda
BP
428 match->wc.masks.mpls_lse[idx] |= htonl(MPLS_LABEL_MASK);
429 flow_set_mpls_label(&match->flow, idx, mpls_label);
b02475c5
SH
430}
431
432/* Modifies 'match' so that the MPLS TC is wildcarded. */
433void
8bfd0fda 434match_set_any_mpls_tc(struct match *match, int idx)
b02475c5 435{
8bfd0fda
BP
436 match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_TC_MASK);
437 flow_set_mpls_tc(&match->flow, idx, 0);
b02475c5
SH
438}
439
440/* Modifies 'match' so that it matches only packets with an MPLS header whose
441 * Traffic Class equals the low 3 bits of 'mpls_tc'. */
442void
8bfd0fda 443match_set_mpls_tc(struct match *match, int idx, uint8_t mpls_tc)
b02475c5 444{
8bfd0fda
BP
445 match->wc.masks.mpls_lse[idx] |= htonl(MPLS_TC_MASK);
446 flow_set_mpls_tc(&match->flow, idx, mpls_tc);
b02475c5
SH
447}
448
449/* Modifies 'match' so that the MPLS stack flag is wildcarded. */
450void
8bfd0fda 451match_set_any_mpls_bos(struct match *match, int idx)
b02475c5 452{
8bfd0fda
BP
453 match->wc.masks.mpls_lse[idx] &= ~htonl(MPLS_BOS_MASK);
454 flow_set_mpls_bos(&match->flow, idx, 0);
b02475c5
SH
455}
456
457/* Modifies 'match' so that it matches only packets with an MPLS header whose
458 * Stack Flag equals the lower bit of 'mpls_bos' */
459void
8bfd0fda
BP
460match_set_mpls_bos(struct match *match, int idx, uint8_t mpls_bos)
461{
462 match->wc.masks.mpls_lse[idx] |= htonl(MPLS_BOS_MASK);
463 flow_set_mpls_bos(&match->flow, idx, mpls_bos);
464}
465
466/* Modifies 'match' so that the MPLS LSE is wildcarded. */
467void
468match_set_any_mpls_lse(struct match *match, int idx)
b02475c5 469{
8bfd0fda
BP
470 match->wc.masks.mpls_lse[idx] = htonl(0);
471 flow_set_mpls_lse(&match->flow, idx, htonl(0));
b02475c5
SH
472}
473
81a76618
BP
474void
475match_set_tp_src(struct match *match, ovs_be16 tp_src)
476{
b8266395 477 match_set_tp_src_masked(match, tp_src, OVS_BE16_MAX);
81a76618
BP
478}
479
480void
481match_set_tp_src_masked(struct match *match, ovs_be16 port, ovs_be16 mask)
482{
483 match->flow.tp_src = port & mask;
484 match->wc.masks.tp_src = mask;
485}
486
487void
488match_set_tp_dst(struct match *match, ovs_be16 tp_dst)
489{
b8266395 490 match_set_tp_dst_masked(match, tp_dst, OVS_BE16_MAX);
81a76618
BP
491}
492
493void
494match_set_tp_dst_masked(struct match *match, ovs_be16 port, ovs_be16 mask)
495{
496 match->flow.tp_dst = port & mask;
497 match->wc.masks.tp_dst = mask;
498}
499
dc235f7f
JR
500void
501match_set_tcp_flags(struct match *match, ovs_be16 flags)
502{
503 match_set_tcp_flags_masked(match, flags, OVS_BE16_MAX);
504}
505
506void
507match_set_tcp_flags_masked(struct match *match, ovs_be16 flags, ovs_be16 mask)
508{
509 match->flow.tcp_flags = flags & mask;
510 match->wc.masks.tcp_flags = mask;
511}
512
81a76618
BP
513void
514match_set_nw_proto(struct match *match, uint8_t nw_proto)
515{
516 match->flow.nw_proto = nw_proto;
517 match->wc.masks.nw_proto = UINT8_MAX;
518}
519
520void
521match_set_nw_src(struct match *match, ovs_be32 nw_src)
522{
523 match->flow.nw_src = nw_src;
b8266395 524 match->wc.masks.nw_src = OVS_BE32_MAX;
81a76618
BP
525}
526
527void
528match_set_nw_src_masked(struct match *match,
529 ovs_be32 nw_src, ovs_be32 mask)
530{
531 match->flow.nw_src = nw_src & mask;
532 match->wc.masks.nw_src = mask;
533}
534
535void
536match_set_nw_dst(struct match *match, ovs_be32 nw_dst)
537{
538 match->flow.nw_dst = nw_dst;
b8266395 539 match->wc.masks.nw_dst = OVS_BE32_MAX;
81a76618
BP
540}
541
542void
543match_set_nw_dst_masked(struct match *match, ovs_be32 ip, ovs_be32 mask)
544{
545 match->flow.nw_dst = ip & mask;
546 match->wc.masks.nw_dst = mask;
547}
548
549void
550match_set_nw_dscp(struct match *match, uint8_t nw_dscp)
551{
552 match->wc.masks.nw_tos |= IP_DSCP_MASK;
553 match->flow.nw_tos &= ~IP_DSCP_MASK;
554 match->flow.nw_tos |= nw_dscp & IP_DSCP_MASK;
555}
556
557void
558match_set_nw_ecn(struct match *match, uint8_t nw_ecn)
559{
560 match->wc.masks.nw_tos |= IP_ECN_MASK;
561 match->flow.nw_tos &= ~IP_ECN_MASK;
562 match->flow.nw_tos |= nw_ecn & IP_ECN_MASK;
563}
564
565void
566match_set_nw_ttl(struct match *match, uint8_t nw_ttl)
567{
568 match->wc.masks.nw_ttl = UINT8_MAX;
569 match->flow.nw_ttl = nw_ttl;
570}
571
572void
573match_set_nw_frag(struct match *match, uint8_t nw_frag)
574{
575 match->wc.masks.nw_frag |= FLOW_NW_FRAG_MASK;
576 match->flow.nw_frag = nw_frag;
577}
578
579void
580match_set_nw_frag_masked(struct match *match,
581 uint8_t nw_frag, uint8_t mask)
582{
583 match->flow.nw_frag = nw_frag & mask;
584 match->wc.masks.nw_frag = mask;
585}
586
587void
588match_set_icmp_type(struct match *match, uint8_t icmp_type)
589{
590 match_set_tp_src(match, htons(icmp_type));
591}
592
593void
594match_set_icmp_code(struct match *match, uint8_t icmp_code)
595{
596 match_set_tp_dst(match, htons(icmp_code));
597}
598
599void
600match_set_arp_sha(struct match *match, const uint8_t sha[ETH_ADDR_LEN])
601{
602 memcpy(match->flow.arp_sha, sha, ETH_ADDR_LEN);
603 memset(match->wc.masks.arp_sha, UINT8_MAX, ETH_ADDR_LEN);
604}
605
606void
607match_set_arp_sha_masked(struct match *match,
608 const uint8_t arp_sha[ETH_ADDR_LEN],
609 const uint8_t mask[ETH_ADDR_LEN])
610{
611 set_eth_masked(arp_sha, mask,
612 match->flow.arp_sha, match->wc.masks.arp_sha);
613}
614
615void
616match_set_arp_tha(struct match *match, const uint8_t tha[ETH_ADDR_LEN])
617{
618 memcpy(match->flow.arp_tha, tha, ETH_ADDR_LEN);
619 memset(match->wc.masks.arp_tha, UINT8_MAX, ETH_ADDR_LEN);
620}
621
622void
623match_set_arp_tha_masked(struct match *match,
624 const uint8_t arp_tha[ETH_ADDR_LEN],
625 const uint8_t mask[ETH_ADDR_LEN])
626{
627 set_eth_masked(arp_tha, mask,
628 match->flow.arp_tha, match->wc.masks.arp_tha);
629}
630
631void
632match_set_ipv6_src(struct match *match, const struct in6_addr *src)
633{
634 match->flow.ipv6_src = *src;
635 match->wc.masks.ipv6_src = in6addr_exact;
636}
637
638void
639match_set_ipv6_src_masked(struct match *match, const struct in6_addr *src,
640 const struct in6_addr *mask)
641{
642 match->flow.ipv6_src = ipv6_addr_bitand(src, mask);
643 match->wc.masks.ipv6_src = *mask;
644}
645
646void
647match_set_ipv6_dst(struct match *match, const struct in6_addr *dst)
648{
649 match->flow.ipv6_dst = *dst;
650 match->wc.masks.ipv6_dst = in6addr_exact;
651}
652
653void
654match_set_ipv6_dst_masked(struct match *match, const struct in6_addr *dst,
655 const struct in6_addr *mask)
656{
657 match->flow.ipv6_dst = ipv6_addr_bitand(dst, mask);
658 match->wc.masks.ipv6_dst = *mask;
659}
660
661void
662match_set_ipv6_label(struct match *match, ovs_be32 ipv6_label)
663{
b8266395 664 match->wc.masks.ipv6_label = OVS_BE32_MAX;
81a76618
BP
665 match->flow.ipv6_label = ipv6_label;
666}
667
668
669void
670match_set_ipv6_label_masked(struct match *match, ovs_be32 ipv6_label,
671 ovs_be32 mask)
672{
673 match->flow.ipv6_label = ipv6_label & mask;
674 match->wc.masks.ipv6_label = mask;
675}
676
677void
678match_set_nd_target(struct match *match, const struct in6_addr *target)
679{
680 match->flow.nd_target = *target;
681 match->wc.masks.nd_target = in6addr_exact;
682}
683
684void
685match_set_nd_target_masked(struct match *match,
686 const struct in6_addr *target,
687 const struct in6_addr *mask)
688{
689 match->flow.nd_target = ipv6_addr_bitand(target, mask);
690 match->wc.masks.nd_target = *mask;
691}
692
693/* Returns true if 'a' and 'b' wildcard the same fields and have the same
694 * values for fixed fields, otherwise false. */
695bool
696match_equal(const struct match *a, const struct match *b)
697{
698 return (flow_wildcards_equal(&a->wc, &b->wc)
699 && flow_equal(&a->flow, &b->flow));
700}
701
702/* Returns a hash value for the flow and wildcards in 'match', starting from
703 * 'basis'. */
704uint32_t
705match_hash(const struct match *match, uint32_t basis)
706{
707 return flow_wildcards_hash(&match->wc, flow_hash(&match->flow, basis));
708}
709
adcf00ba
AZ
710static bool
711match_has_default_recirc_id(const struct match *m)
712{
713 return m->flow.recirc_id == 0 && (m->wc.masks.recirc_id == UINT32_MAX ||
714 m->wc.masks.recirc_id == 0);
715}
716
717static bool
718match_has_default_dp_hash(const struct match *m)
719{
720 return ((m->flow.dp_hash | m->wc.masks.dp_hash) == 0);
721}
722
723/* Return true if the hidden fields of the match are set to the default values.
724 * The default values equals to those set up by match_init_hidden_fields(). */
725bool
726match_has_default_hidden_fields(const struct match *m)
727{
728 return match_has_default_recirc_id(m) && match_has_default_dp_hash(m);
729}
730
731void
732match_init_hidden_fields(struct match *m)
733{
734 match_set_recirc_id(m, 0);
735 match_set_dp_hash_masked(m, 0, 0);
736}
737
81a76618 738static void
3bd0fd39
WSH
739format_eth_masked(struct ds *s, const char *name,
740 const uint8_t eth[ETH_ADDR_LEN],
741 const uint8_t mask[ETH_ADDR_LEN])
81a76618
BP
742{
743 if (!eth_addr_is_zero(mask)) {
744 ds_put_format(s, "%s=", name);
745 eth_format_masked(eth, mask, s);
746 ds_put_char(s, ',');
747 }
748}
749
750static void
751format_ip_netmask(struct ds *s, const char *name, ovs_be32 ip,
752 ovs_be32 netmask)
753{
754 if (netmask) {
755 ds_put_format(s, "%s=", name);
756 ip_format_masked(ip, netmask, s);
757 ds_put_char(s, ',');
758 }
759}
760
761static void
762format_ipv6_netmask(struct ds *s, const char *name,
763 const struct in6_addr *addr,
764 const struct in6_addr *netmask)
765{
766 if (!ipv6_mask_is_any(netmask)) {
767 ds_put_format(s, "%s=", name);
768 print_ipv6_masked(s, addr, netmask);
769 ds_put_char(s, ',');
770 }
771}
772
81a76618
BP
773static void
774format_be16_masked(struct ds *s, const char *name,
775 ovs_be16 value, ovs_be16 mask)
776{
777 if (mask != htons(0)) {
778 ds_put_format(s, "%s=", name);
b8266395 779 if (mask == OVS_BE16_MAX) {
81a76618
BP
780 ds_put_format(s, "%"PRIu16, ntohs(value));
781 } else {
782 ds_put_format(s, "0x%"PRIx16"/0x%"PRIx16,
783 ntohs(value), ntohs(mask));
784 }
785 ds_put_char(s, ',');
786 }
787}
788
8bfd0fda
BP
789static void
790format_be32_masked(struct ds *s, const char *name,
791 ovs_be32 value, ovs_be32 mask)
792{
793 if (mask != htonl(0)) {
794 ds_put_format(s, "%s=", name);
795 if (mask == OVS_BE32_MAX) {
796 ds_put_format(s, "%"PRIu32, ntohl(value));
797 } else {
798 ds_put_format(s, "0x%"PRIx32"/0x%"PRIx32,
799 ntohl(value), ntohl(mask));
800 }
801 ds_put_char(s, ',');
802 }
803}
804
b60f804e
AZ
805static void
806format_uint32_masked(struct ds *s, const char *name,
807 uint32_t value, uint32_t mask)
808{
809 if (mask) {
810 ds_put_format(s, "%s=%#"PRIx32, name, value);
811 if (mask != UINT32_MAX) {
812 ds_put_format(s, "/%#"PRIx32, mask);
813 }
814 ds_put_char(s, ',');
815 }
816}
817
818static void
819format_be64_masked(struct ds *s, const char *name,
820 ovs_be64 value, ovs_be64 mask)
821{
822 if (mask != htonll(0)) {
823 ds_put_format(s, "%s=%#"PRIx64, name, ntohll(value));
824 if (mask != OVS_BE64_MAX) {
825 ds_put_format(s, "/%#"PRIx64, ntohll(mask));
826 }
827 ds_put_char(s, ',');
828 }
829}
830
4fe3445a
PS
831static void
832format_flow_tunnel(struct ds *s, const struct match *match)
833{
834 const struct flow_wildcards *wc = &match->wc;
835 const struct flow_tnl *tnl = &match->flow.tunnel;
836
b60f804e 837 format_be64_masked(s, "tun_id", tnl->tun_id, wc->masks.tunnel.tun_id);
4fe3445a
PS
838 format_ip_netmask(s, "tun_src", tnl->ip_src, wc->masks.tunnel.ip_src);
839 format_ip_netmask(s, "tun_dst", tnl->ip_dst, wc->masks.tunnel.ip_dst);
840
841 if (wc->masks.tunnel.ip_tos) {
842 ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
843 }
844 if (wc->masks.tunnel.ip_ttl) {
845 ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl);
846 }
847 if (wc->masks.tunnel.flags) {
848 format_flags(s, flow_tun_flag_to_string, tnl->flags, '|');
849 ds_put_char(s, ',');
850 }
851}
852
81a76618
BP
853/* Appends a string representation of 'match' to 's'. If 'priority' is
854 * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
855void
eb391b76 856match_format(const struct match *match, struct ds *s, int priority)
81a76618
BP
857{
858 const struct flow_wildcards *wc = &match->wc;
859 size_t start_len = s->length;
860 const struct flow *f = &match->flow;
861 bool skip_type = false;
862 bool skip_proto = false;
863
864 int i;
865
0e612675 866 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
81a76618
BP
867
868 if (priority != OFP_DEFAULT_PRIORITY) {
eb391b76 869 ds_put_format(s, "priority=%d,", priority);
81a76618
BP
870 }
871
b60f804e 872 format_uint32_masked(s, "pkt_mark", f->pkt_mark, wc->masks.pkt_mark);
1b567fb9 873
a79f29f2
AZ
874 if (wc->masks.recirc_id) {
875 format_uint32_masked(s, "recirc_id", f->recirc_id,
876 wc->masks.recirc_id);
877 }
878
879 if (f->dp_hash && wc->masks.dp_hash) {
880 format_uint32_masked(s, "dp_hash", f->dp_hash,
881 wc->masks.dp_hash);
882 }
883
1b567fb9
AA
884 if (wc->masks.skb_priority) {
885 ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority);
886 }
887
81a76618
BP
888 if (wc->masks.dl_type) {
889 skip_type = true;
890 if (f->dl_type == htons(ETH_TYPE_IP)) {
891 if (wc->masks.nw_proto) {
892 skip_proto = true;
893 if (f->nw_proto == IPPROTO_ICMP) {
894 ds_put_cstr(s, "icmp,");
0e612675
FL
895 } else if (f->nw_proto == IPPROTO_IGMP) {
896 ds_put_cstr(s, "igmp,");
81a76618
BP
897 } else if (f->nw_proto == IPPROTO_TCP) {
898 ds_put_cstr(s, "tcp,");
899 } else if (f->nw_proto == IPPROTO_UDP) {
900 ds_put_cstr(s, "udp,");
0d56eaf2
JS
901 } else if (f->nw_proto == IPPROTO_SCTP) {
902 ds_put_cstr(s, "sctp,");
81a76618
BP
903 } else {
904 ds_put_cstr(s, "ip,");
905 skip_proto = false;
906 }
907 } else {
908 ds_put_cstr(s, "ip,");
909 }
910 } else if (f->dl_type == htons(ETH_TYPE_IPV6)) {
911 if (wc->masks.nw_proto) {
912 skip_proto = true;
913 if (f->nw_proto == IPPROTO_ICMPV6) {
914 ds_put_cstr(s, "icmp6,");
915 } else if (f->nw_proto == IPPROTO_TCP) {
916 ds_put_cstr(s, "tcp6,");
917 } else if (f->nw_proto == IPPROTO_UDP) {
918 ds_put_cstr(s, "udp6,");
0d56eaf2
JS
919 } else if (f->nw_proto == IPPROTO_SCTP) {
920 ds_put_cstr(s, "sctp6,");
81a76618
BP
921 } else {
922 ds_put_cstr(s, "ipv6,");
923 skip_proto = false;
924 }
925 } else {
926 ds_put_cstr(s, "ipv6,");
927 }
928 } else if (f->dl_type == htons(ETH_TYPE_ARP)) {
929 ds_put_cstr(s, "arp,");
8087f5ff
MM
930 } else if (f->dl_type == htons(ETH_TYPE_RARP)) {
931 ds_put_cstr(s, "rarp,");
392c30ba
SH
932 } else if (f->dl_type == htons(ETH_TYPE_MPLS)) {
933 ds_put_cstr(s, "mpls,");
934 } else if (f->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
935 ds_put_cstr(s, "mplsm,");
81a76618
BP
936 } else {
937 skip_type = false;
938 }
939 }
940 for (i = 0; i < FLOW_N_REGS; i++) {
b60f804e
AZ
941 #define REGNAME_LEN 20
942 char regname[REGNAME_LEN];
943 if (snprintf(regname, REGNAME_LEN, "reg%d", i) >= REGNAME_LEN) {
944 strcpy(regname, "reg?");
81a76618 945 }
b60f804e 946 format_uint32_masked(s, regname, f->regs[i], wc->masks.regs[i]);
81a76618 947 }
4fe3445a
PS
948
949 format_flow_tunnel(s, match);
950
b60f804e
AZ
951 format_be64_masked(s, "metadata", f->metadata, wc->masks.metadata);
952
4e022ec0 953 if (wc->masks.in_port.ofp_port) {
576ec803 954 ds_put_cstr(s, "in_port=");
4e022ec0 955 ofputil_format_port(f->in_port.ofp_port, s);
576ec803 956 ds_put_char(s, ',');
81a76618
BP
957 }
958 if (wc->masks.vlan_tci) {
959 ovs_be16 vid_mask = wc->masks.vlan_tci & htons(VLAN_VID_MASK);
960 ovs_be16 pcp_mask = wc->masks.vlan_tci & htons(VLAN_PCP_MASK);
961 ovs_be16 cfi = wc->masks.vlan_tci & htons(VLAN_CFI);
962
963 if (cfi && f->vlan_tci & htons(VLAN_CFI)
964 && (!vid_mask || vid_mask == htons(VLAN_VID_MASK))
965 && (!pcp_mask || pcp_mask == htons(VLAN_PCP_MASK))
966 && (vid_mask || pcp_mask)) {
967 if (vid_mask) {
968 ds_put_format(s, "dl_vlan=%"PRIu16",",
969 vlan_tci_to_vid(f->vlan_tci));
970 }
971 if (pcp_mask) {
972 ds_put_format(s, "dl_vlan_pcp=%d,",
973 vlan_tci_to_pcp(f->vlan_tci));
974 }
975 } else if (wc->masks.vlan_tci == htons(0xffff)) {
976 ds_put_format(s, "vlan_tci=0x%04"PRIx16",", ntohs(f->vlan_tci));
977 } else {
978 ds_put_format(s, "vlan_tci=0x%04"PRIx16"/0x%04"PRIx16",",
979 ntohs(f->vlan_tci), ntohs(wc->masks.vlan_tci));
980 }
981 }
982 format_eth_masked(s, "dl_src", f->dl_src, wc->masks.dl_src);
983 format_eth_masked(s, "dl_dst", f->dl_dst, wc->masks.dl_dst);
984 if (!skip_type && wc->masks.dl_type) {
985 ds_put_format(s, "dl_type=0x%04"PRIx16",", ntohs(f->dl_type));
986 }
987 if (f->dl_type == htons(ETH_TYPE_IPV6)) {
988 format_ipv6_netmask(s, "ipv6_src", &f->ipv6_src, &wc->masks.ipv6_src);
989 format_ipv6_netmask(s, "ipv6_dst", &f->ipv6_dst, &wc->masks.ipv6_dst);
990 if (wc->masks.ipv6_label) {
b8266395 991 if (wc->masks.ipv6_label == OVS_BE32_MAX) {
81a76618
BP
992 ds_put_format(s, "ipv6_label=0x%05"PRIx32",",
993 ntohl(f->ipv6_label));
994 } else {
995 ds_put_format(s, "ipv6_label=0x%05"PRIx32"/0x%05"PRIx32",",
996 ntohl(f->ipv6_label),
997 ntohl(wc->masks.ipv6_label));
998 }
999 }
8087f5ff
MM
1000 } else if (f->dl_type == htons(ETH_TYPE_ARP) ||
1001 f->dl_type == htons(ETH_TYPE_RARP)) {
666d0863
MM
1002 format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src);
1003 format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst);
81a76618
BP
1004 } else {
1005 format_ip_netmask(s, "nw_src", f->nw_src, wc->masks.nw_src);
1006 format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst);
1007 }
1008 if (!skip_proto && wc->masks.nw_proto) {
8087f5ff
MM
1009 if (f->dl_type == htons(ETH_TYPE_ARP) ||
1010 f->dl_type == htons(ETH_TYPE_RARP)) {
81a76618
BP
1011 ds_put_format(s, "arp_op=%"PRIu8",", f->nw_proto);
1012 } else {
1013 ds_put_format(s, "nw_proto=%"PRIu8",", f->nw_proto);
1014 }
1015 }
8087f5ff
MM
1016 if (f->dl_type == htons(ETH_TYPE_ARP) ||
1017 f->dl_type == htons(ETH_TYPE_RARP)) {
81a76618
BP
1018 format_eth_masked(s, "arp_sha", f->arp_sha, wc->masks.arp_sha);
1019 format_eth_masked(s, "arp_tha", f->arp_tha, wc->masks.arp_tha);
1020 }
1021 if (wc->masks.nw_tos & IP_DSCP_MASK) {
1022 ds_put_format(s, "nw_tos=%"PRIu8",", f->nw_tos & IP_DSCP_MASK);
1023 }
1024 if (wc->masks.nw_tos & IP_ECN_MASK) {
1025 ds_put_format(s, "nw_ecn=%"PRIu8",", f->nw_tos & IP_ECN_MASK);
1026 }
1027 if (wc->masks.nw_ttl) {
1028 ds_put_format(s, "nw_ttl=%"PRIu8",", f->nw_ttl);
1029 }
8bfd0fda 1030 if (wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
b02475c5 1031 ds_put_format(s, "mpls_label=%"PRIu32",",
78c9486d 1032 mpls_lse_to_label(f->mpls_lse[0]));
b02475c5 1033 }
8bfd0fda 1034 if (wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
b02475c5 1035 ds_put_format(s, "mpls_tc=%"PRIu8",",
78c9486d 1036 mpls_lse_to_tc(f->mpls_lse[0]));
b02475c5 1037 }
8bfd0fda 1038 if (wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) {
392c30ba 1039 ds_put_format(s, "mpls_ttl=%"PRIu8",",
78c9486d 1040 mpls_lse_to_ttl(f->mpls_lse[0]));
392c30ba 1041 }
8bfd0fda 1042 if (wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
b02475c5 1043 ds_put_format(s, "mpls_bos=%"PRIu8",",
78c9486d 1044 mpls_lse_to_bos(f->mpls_lse[0]));
b02475c5 1045 }
8bfd0fda
BP
1046 format_be32_masked(s, "mpls_lse1", f->mpls_lse[1], wc->masks.mpls_lse[1]);
1047 format_be32_masked(s, "mpls_lse2", f->mpls_lse[2], wc->masks.mpls_lse[2]);
1048
81a76618
BP
1049 switch (wc->masks.nw_frag) {
1050 case FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER:
1051 ds_put_format(s, "nw_frag=%s,",
1052 f->nw_frag & FLOW_NW_FRAG_ANY
1053 ? (f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "first")
1054 : (f->nw_frag & FLOW_NW_FRAG_LATER ? "<error>" : "no"));
1055 break;
1056
1057 case FLOW_NW_FRAG_ANY:
1058 ds_put_format(s, "nw_frag=%s,",
1059 f->nw_frag & FLOW_NW_FRAG_ANY ? "yes" : "no");
1060 break;
1061
1062 case FLOW_NW_FRAG_LATER:
1063 ds_put_format(s, "nw_frag=%s,",
1064 f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "not_later");
1065 break;
1066 }
19564d20
MM
1067 if (f->dl_type == htons(ETH_TYPE_IP) &&
1068 f->nw_proto == IPPROTO_ICMP) {
81a76618
BP
1069 format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src);
1070 format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst);
0e612675
FL
1071 } else if (f->dl_type == htons(ETH_TYPE_IP) &&
1072 f->nw_proto == IPPROTO_IGMP) {
1073 format_be16_masked(s, "igmp_type", f->tp_src, wc->masks.tp_src);
1074 format_be16_masked(s, "igmp_code", f->tp_dst, wc->masks.tp_dst);
19564d20
MM
1075 } else if (f->dl_type == htons(ETH_TYPE_IPV6) &&
1076 f->nw_proto == IPPROTO_ICMPV6) {
81a76618
BP
1077 format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src);
1078 format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst);
1079 format_ipv6_netmask(s, "nd_target", &f->nd_target,
1080 &wc->masks.nd_target);
1081 format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha);
1082 format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha);
1f6d8197 1083 } else {
81a76618
BP
1084 format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src);
1085 format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst);
1086 }
dc235f7f 1087 if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) {
61bf6666 1088 uint16_t mask = TCP_FLAGS(wc->masks.tcp_flags);
ea2735d3 1089
61bf6666 1090 if (mask == TCP_FLAGS(OVS_BE16_MAX)) {
ea2735d3
JR
1091 ds_put_cstr(s, "tcp_flags=");
1092 if (f->tcp_flags) {
1093 format_flags(s, packet_tcp_flag_to_string, ntohs(f->tcp_flags),
1094 '|');
1095 } else {
1096 ds_put_cstr(s, "0"); /* Zero flags. */
1097 }
1098 } else if (mask) {
61bf6666
JR
1099 format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string,
1100 ntohs(f->tcp_flags), mask);
dc235f7f
JR
1101 }
1102 }
81a76618
BP
1103
1104 if (s->length > start_len && ds_last(s) == ',') {
1105 s->length--;
1106 }
1107}
1108
1109/* Converts 'match' to a string and returns the string. If 'priority' is
1110 * different from OFP_DEFAULT_PRIORITY, includes it in the string. The caller
1111 * must free the string (with free()). */
1112char *
eb391b76 1113match_to_string(const struct match *match, int priority)
81a76618
BP
1114{
1115 struct ds s = DS_EMPTY_INITIALIZER;
1116 match_format(match, &s, priority);
1117 return ds_steal_cstr(&s);
1118}
1119
1120void
1121match_print(const struct match *match)
1122{
1123 char *s = match_to_string(match, OFP_DEFAULT_PRIORITY);
1124 puts(s);
1125 free(s);
1126}
5cb7a798
BP
1127\f
1128/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
1129 * with minimatch_destroy(). */
1130void
1131minimatch_init(struct minimatch *dst, const struct match *src)
1132{
5cb7a798 1133 minimask_init(&dst->mask, &src->wc);
df40c152 1134 miniflow_init_with_minimask(&dst->flow, &src->flow, &dst->mask);
5cb7a798
BP
1135}
1136
1137/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
1138 * with minimatch_destroy(). */
1139void
1140minimatch_clone(struct minimatch *dst, const struct minimatch *src)
1141{
1142 miniflow_clone(&dst->flow, &src->flow);
1143 minimask_clone(&dst->mask, &src->mask);
1144}
1145
b2c1f00b
BP
1146/* Initializes 'dst' with the data in 'src', destroying 'src'. The caller must
1147 * eventually free 'dst' with minimatch_destroy(). */
1148void
1149minimatch_move(struct minimatch *dst, struct minimatch *src)
1150{
1151 miniflow_move(&dst->flow, &src->flow);
1152 minimask_move(&dst->mask, &src->mask);
1153}
1154
5cb7a798
BP
1155/* Frees any memory owned by 'match'. Does not free the storage in which
1156 * 'match' itself resides; the caller is responsible for that. */
1157void
1158minimatch_destroy(struct minimatch *match)
1159{
1160 miniflow_destroy(&match->flow);
1161 minimask_destroy(&match->mask);
1162}
1163
1164/* Initializes 'dst' as a copy of 'src'. */
1165void
1166minimatch_expand(const struct minimatch *src, struct match *dst)
1167{
1168 miniflow_expand(&src->flow, &dst->flow);
1169 minimask_expand(&src->mask, &dst->wc);
1170}
1171
1172/* Returns true if 'a' and 'b' match the same packets, false otherwise. */
1173bool
1174minimatch_equal(const struct minimatch *a, const struct minimatch *b)
1175{
1176 return (miniflow_equal(&a->flow, &b->flow)
1177 && minimask_equal(&a->mask, &b->mask));
1178}
1179
df40c152
BP
1180/* Returns true if 'target' satisifies 'match', that is, if each bit for which
1181 * 'match' specifies a particular value has the correct value in 'target'.
1182 *
1183 * This function is equivalent to miniflow_equal_flow_in_minimask(&match->flow,
1184 * target, &match->mask) but it is faster because of the invariant that
1185 * match->flow.map and match->mask.map are the same. */
1186bool
1187minimatch_matches_flow(const struct minimatch *match,
1188 const struct flow *target)
1189{
1190 const uint32_t *target_u32 = (const uint32_t *) target;
27bbe15d
JR
1191 const uint32_t *flowp = miniflow_get_u32_values(&match->flow);
1192 const uint32_t *maskp = miniflow_get_u32_values(&match->mask.masks);
080e28d0 1193 uint64_t map;
df40c152 1194
080e28d0 1195 for (map = match->flow.map; map; map = zero_rightmost_1bit(map)) {
d43d314e 1196 if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) {
080e28d0 1197 return false;
df40c152 1198 }
df40c152
BP
1199 }
1200
1201 return true;
1202}
1203
5cb7a798
BP
1204/* Appends a string representation of 'match' to 's'. If 'priority' is
1205 * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
1206void
eb391b76 1207minimatch_format(const struct minimatch *match, struct ds *s, int priority)
5cb7a798
BP
1208{
1209 struct match megamatch;
1210
1211 minimatch_expand(match, &megamatch);
1212 match_format(&megamatch, s, priority);
1213}
1214
1215/* Converts 'match' to a string and returns the string. If 'priority' is
1216 * different from OFP_DEFAULT_PRIORITY, includes it in the string. The caller
1217 * must free the string (with free()). */
1218char *
eb391b76 1219minimatch_to_string(const struct minimatch *match, int priority)
5cb7a798
BP
1220{
1221 struct match megamatch;
1222
1223 minimatch_expand(match, &megamatch);
1224 return match_to_string(&megamatch, priority);
1225}