- const struct flow_wildcards *wc = &rule->wc;
- size_t start_len = s->length;
- flow_wildcards_t w = wc->wildcards;
- const struct flow *f = &rule->flow;
- bool skip_type = false;
- bool skip_proto = false;
-
- int i;
-
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 3);
-
- if (rule->priority != OFP_DEFAULT_PRIORITY) {
- ds_put_format(s, "priority=%d,", rule->priority);
- }
-
- if (!(w & FWW_DL_TYPE)) {
- skip_type = true;
- if (f->dl_type == htons(ETH_TYPE_IP)) {
- if (!(w & FWW_NW_PROTO)) {
- skip_proto = true;
- if (f->nw_proto == IPPROTO_ICMP) {
- ds_put_cstr(s, "icmp,");
- } else if (f->nw_proto == IPPROTO_TCP) {
- ds_put_cstr(s, "tcp,");
- } else if (f->nw_proto == IPPROTO_UDP) {
- ds_put_cstr(s, "udp,");
- } else {
- ds_put_cstr(s, "ip,");
- skip_proto = false;
- }
- } else {
- ds_put_cstr(s, "ip,");
- }
- } else if (f->dl_type == htons(ETH_TYPE_IPV6)) {
- if (!(w & FWW_NW_PROTO)) {
- skip_proto = true;
- if (f->nw_proto == IPPROTO_ICMPV6) {
- ds_put_cstr(s, "icmp6,");
- } else if (f->nw_proto == IPPROTO_TCP) {
- ds_put_cstr(s, "tcp6,");
- } else if (f->nw_proto == IPPROTO_UDP) {
- ds_put_cstr(s, "udp6,");
- } else {
- ds_put_cstr(s, "ipv6,");
- skip_proto = false;
- }
- } else {
- ds_put_cstr(s, "ipv6,");
- }
- } else if (f->dl_type == htons(ETH_TYPE_ARP)) {
- ds_put_cstr(s, "arp,");
- } else {
- skip_type = false;
- }
- }
- for (i = 0; i < FLOW_N_REGS; i++) {
- switch (wc->reg_masks[i]) {
- case 0:
- break;
- case UINT32_MAX:
- ds_put_format(s, "reg%d=0x%"PRIx32",", i, f->regs[i]);
- break;
- default:
- ds_put_format(s, "reg%d=0x%"PRIx32"/0x%"PRIx32",",
- i, f->regs[i], wc->reg_masks[i]);
- break;
- }
- }
- switch (wc->tun_id_mask) {
- case 0:
- break;
- case CONSTANT_HTONLL(UINT64_MAX):
- ds_put_format(s, "tun_id=%#"PRIx64",", ntohll(f->tun_id));
- break;
- default:
- ds_put_format(s, "tun_id=%#"PRIx64"/%#"PRIx64",",
- ntohll(f->tun_id), ntohll(wc->tun_id_mask));
- break;
- }
- if (!(w & FWW_IN_PORT)) {
- ds_put_format(s, "in_port=%"PRIu16",", f->in_port);
- }
- if (wc->vlan_tci_mask) {
- ovs_be16 vid_mask = wc->vlan_tci_mask & htons(VLAN_VID_MASK);
- ovs_be16 pcp_mask = wc->vlan_tci_mask & htons(VLAN_PCP_MASK);
- ovs_be16 cfi = wc->vlan_tci_mask & htons(VLAN_CFI);
-
- if (cfi && f->vlan_tci & htons(VLAN_CFI)
- && (!vid_mask || vid_mask == htons(VLAN_VID_MASK))
- && (!pcp_mask || pcp_mask == htons(VLAN_PCP_MASK))
- && (vid_mask || pcp_mask)) {
- if (vid_mask) {
- ds_put_format(s, "dl_vlan=%"PRIu16",",
- vlan_tci_to_vid(f->vlan_tci));
- }
- if (pcp_mask) {
- ds_put_format(s, "dl_vlan_pcp=%d,",
- vlan_tci_to_pcp(f->vlan_tci));
- }
- } else if (wc->vlan_tci_mask == htons(0xffff)) {
- ds_put_format(s, "vlan_tci=0x%04"PRIx16",", ntohs(f->vlan_tci));
- } else {
- ds_put_format(s, "vlan_tci=0x%04"PRIx16"/0x%04"PRIx16",",
- ntohs(f->vlan_tci), ntohs(wc->vlan_tci_mask));
- }
- }
- if (!(w & FWW_DL_SRC)) {
- ds_put_format(s, "dl_src="ETH_ADDR_FMT",", ETH_ADDR_ARGS(f->dl_src));
- }
- switch (w & (FWW_DL_DST | FWW_ETH_MCAST)) {
- case 0:
- ds_put_format(s, "dl_dst="ETH_ADDR_FMT",", ETH_ADDR_ARGS(f->dl_dst));
- break;
- case FWW_DL_DST:
- ds_put_format(s, "dl_dst="ETH_ADDR_FMT"/01:00:00:00:00:00,",
- ETH_ADDR_ARGS(f->dl_dst));
- break;
- case FWW_ETH_MCAST:
- ds_put_format(s, "dl_dst="ETH_ADDR_FMT"/fe:ff:ff:ff:ff:ff,",
- ETH_ADDR_ARGS(f->dl_dst));
- break;
- case FWW_DL_DST | FWW_ETH_MCAST:
- break;
- }
- if (!skip_type && !(w & FWW_DL_TYPE)) {
- ds_put_format(s, "dl_type=0x%04"PRIx16",", ntohs(f->dl_type));
- }
- if (f->dl_type == htons(ETH_TYPE_IPV6)) {
- format_ipv6_netmask(s, "ipv6_src", &f->ipv6_src, &wc->ipv6_src_mask);
- format_ipv6_netmask(s, "ipv6_dst", &f->ipv6_dst, &wc->ipv6_dst_mask);
- } else {
- format_ip_netmask(s, "nw_src", f->nw_src, wc->nw_src_mask);
- format_ip_netmask(s, "nw_dst", f->nw_dst, wc->nw_dst_mask);
- }
- if (!skip_proto && !(w & FWW_NW_PROTO)) {
- if (f->dl_type == htons(ETH_TYPE_ARP)) {
- ds_put_format(s, "arp_op=%"PRIu8",", f->nw_proto);
- } else {
- ds_put_format(s, "nw_proto=%"PRIu8",", f->nw_proto);
- }
- }
- if (f->dl_type == htons(ETH_TYPE_ARP)) {
- if (!(w & FWW_ARP_SHA)) {
- ds_put_format(s, "arp_sha="ETH_ADDR_FMT",",
- ETH_ADDR_ARGS(f->arp_sha));
- }
- if (!(w & FWW_ARP_THA)) {
- ds_put_format(s, "arp_tha="ETH_ADDR_FMT",",
- ETH_ADDR_ARGS(f->arp_tha));
- }
- }
- if (wc->tos_frag_mask & IP_DSCP_MASK) {
- ds_put_format(s, "nw_tos=%"PRIu8",", f->tos_frag & IP_DSCP_MASK);
- }
- switch (wc->tos_frag_mask & FLOW_FRAG_MASK) {
- case FLOW_FRAG_ANY | FLOW_FRAG_LATER:
- ds_put_format(s, "frag=%s,",
- f->tos_frag & FLOW_FRAG_ANY
- ? (f->tos_frag & FLOW_FRAG_LATER ? "later" : "first")
- : (f->tos_frag & FLOW_FRAG_LATER ? "<error>" : "no"));
- break;
-
- case FLOW_FRAG_ANY:
- ds_put_format(s, "frag=%s,",
- f->tos_frag & FLOW_FRAG_ANY ? "yes" : "no");
- break;
-
- case FLOW_FRAG_LATER:
- ds_put_format(s, "frag=%s,",
- f->tos_frag & FLOW_FRAG_LATER ? "later" : "not_later");
- break;
- }
- if (f->nw_proto == IPPROTO_ICMP) {
- if (!(w & FWW_TP_SRC)) {
- ds_put_format(s, "icmp_type=%"PRIu16",", ntohs(f->tp_src));
- }
- if (!(w & FWW_TP_DST)) {
- ds_put_format(s, "icmp_code=%"PRIu16",", ntohs(f->tp_dst));
- }
- } else if (f->nw_proto == IPPROTO_ICMPV6) {
- if (!(w & FWW_TP_SRC)) {
- ds_put_format(s, "icmp_type=%"PRIu16",", ntohs(f->tp_src));
- }
- if (!(w & FWW_TP_DST)) {
- ds_put_format(s, "icmp_code=%"PRIu16",", ntohs(f->tp_dst));
- }
- if (!(w & FWW_ND_TARGET)) {
- ds_put_cstr(s, "nd_target=");
- print_ipv6_addr(s, &f->nd_target);
- ds_put_char(s, ',');
- }
- if (!(w & FWW_ARP_SHA)) {
- ds_put_format(s, "nd_sll="ETH_ADDR_FMT",",
- ETH_ADDR_ARGS(f->arp_sha));
- }
- if (!(w & FWW_ARP_THA)) {
- ds_put_format(s, "nd_tll="ETH_ADDR_FMT",",
- ETH_ADDR_ARGS(f->arp_tha));
- }
- } else {
- if (!(w & FWW_TP_SRC)) {
- ds_put_format(s, "tp_src=%"PRIu16",", ntohs(f->tp_src));
- }
- if (!(w & FWW_TP_DST)) {
- ds_put_format(s, "tp_dst=%"PRIu16",", ntohs(f->tp_dst));
- }
- }
-
- if (s->length > start_len && ds_last(s) == ',') {
- s->length--;
- }