/* Returns true if 'wc' is exact-match, false if 'wc' wildcards any bits or * fields. */ bool flow_wildcards_is_exact(const struct flow_wildcards *wc) { int i; BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); if (wc->wildcards || wc->tun_id_mask != htonll(UINT64_MAX) || wc->nw_src_mask != htonl(UINT32_MAX) || wc->nw_dst_mask != htonl(UINT32_MAX) || wc->tp_src_mask != htons(UINT16_MAX) || wc->tp_dst_mask != htons(UINT16_MAX) || wc->vlan_tci_mask != htons(UINT16_MAX) || wc->metadata_mask != htonll(UINT64_MAX) || !eth_mask_is_exact(wc->dl_src_mask) || !eth_mask_is_exact(wc->dl_dst_mask) || !eth_mask_is_exact(wc->arp_sha_mask) || !eth_mask_is_exact(wc->arp_tha_mask) || !ipv6_mask_is_exact(&wc->ipv6_src_mask) || !ipv6_mask_is_exact(&wc->ipv6_dst_mask) || wc->ipv6_label_mask != htonl(UINT32_MAX) || !ipv6_mask_is_exact(&wc->nd_target_mask) || wc->nw_frag_mask != UINT8_MAX) { return false; } for (i = 0; i < FLOW_N_REGS; i++) { if (wc->reg_masks[i] != UINT32_MAX) { return false; } } return true; }
void eth_format_masked(const uint8_t eth[ETH_ADDR_LEN], const uint8_t mask[ETH_ADDR_LEN], struct ds *s) { ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth)); if (mask && !eth_mask_is_exact(mask)) { ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(mask)); } }
static void nxm_put_eth_masked(struct ofpbuf *b, uint32_t header, const uint8_t value[ETH_ADDR_LEN], const uint8_t mask[ETH_ADDR_LEN]) { if (!eth_addr_is_zero(mask)) { if (eth_mask_is_exact(mask)) { nxm_put_eth(b, header, value); } else { nxm_put_header(b, NXM_MAKE_WILD_HEADER(header)); ofpbuf_put(b, value, ETH_ADDR_LEN); ofpbuf_put(b, mask, ETH_ADDR_LEN); } } }