static void flow_format_mpls(const struct flow *flow, struct ds *s) { if (flow->dl_type == htons(ETH_TYPE_MPLS)) { ds_put_cstr(s, "mpls"); } else if (flow->dl_type == htons(ETH_TYPE_MPLS_MCAST)) { ds_put_cstr(s, "mplsm"); } else { return; } ds_put_format(s, "(label:%"PRIu32",tc:%d,ttl:%d,bos:%d),", mpls_lse_to_label(flow->mpls_lse), mpls_lse_to_tc(flow->mpls_lse), mpls_lse_to_ttl(flow->mpls_lse), mpls_lse_to_bos(flow->mpls_lse)); }
/* Appends a string representation of 'match' to 's'. If 'priority' is * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */ void match_format(const struct match *match, struct ds *s, unsigned int priority) { const struct flow_wildcards *wc = &match->wc; size_t start_len = s->length; const struct flow *f = &match->flow; bool skip_type = false; bool skip_proto = false; int i; BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%u,", priority); } if (wc->masks.skb_mark) { ds_put_format(s, "skb_mark=%#"PRIx32",", f->skb_mark); } if (wc->masks.skb_priority) { ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority); } if (wc->masks.dl_type) { skip_type = true; if (f->dl_type == htons(ETH_TYPE_IP)) { if (wc->masks.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 (wc->masks.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 if (f->dl_type == htons(ETH_TYPE_RARP)) { ds_put_cstr(s, "rarp,"); } else if (f->mpls_depth) { flow_format_mpls(f, s); } else { skip_type = false; } } for (i = 0; i < FLOW_N_REGS; i++) { switch (wc->masks.regs[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->masks.regs[i]); break; } } format_flow_tunnel(s, match); switch (wc->masks.metadata) { case 0: break; case CONSTANT_HTONLL(UINT64_MAX): ds_put_format(s, "metadata=%#"PRIx64",", ntohll(f->metadata)); break; default: ds_put_format(s, "metadata=%#"PRIx64"/%#"PRIx64",", ntohll(f->metadata), ntohll(wc->masks.metadata)); break; } if (wc->masks.in_port) { ds_put_cstr(s, "in_port="); ofputil_format_port(f->in_port, s); ds_put_char(s, ','); } if (wc->masks.vlan_tci) { ovs_be16 vid_mask = wc->masks.vlan_tci & htons(VLAN_VID_MASK); ovs_be16 pcp_mask = wc->masks.vlan_tci & htons(VLAN_PCP_MASK); ovs_be16 cfi = wc->masks.vlan_tci & 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->masks.vlan_tci == 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->masks.vlan_tci)); } } format_eth_masked(s, "dl_src", f->dl_src, wc->masks.dl_src); format_eth_masked(s, "dl_dst", f->dl_dst, wc->masks.dl_dst); if (!skip_type && wc->masks.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->masks.ipv6_src); format_ipv6_netmask(s, "ipv6_dst", &f->ipv6_dst, &wc->masks.ipv6_dst); if (wc->masks.ipv6_label) { if (wc->masks.ipv6_label == htonl(UINT32_MAX)) { ds_put_format(s, "ipv6_label=0x%05"PRIx32",", ntohl(f->ipv6_label)); } else { ds_put_format(s, "ipv6_label=0x%05"PRIx32"/0x%05"PRIx32",", ntohl(f->ipv6_label), ntohl(wc->masks.ipv6_label)); } } } else if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst); } else { format_ip_netmask(s, "nw_src", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst); } if (!skip_proto && wc->masks.nw_proto) { if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { 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) || f->dl_type == htons(ETH_TYPE_RARP)) { format_eth_masked(s, "arp_sha", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "arp_tha", f->arp_tha, wc->masks.arp_tha); } if (wc->masks.nw_tos & IP_DSCP_MASK) { ds_put_format(s, "nw_tos=%"PRIu8",", f->nw_tos & IP_DSCP_MASK); } if (wc->masks.nw_tos & IP_ECN_MASK) { ds_put_format(s, "nw_ecn=%"PRIu8",", f->nw_tos & IP_ECN_MASK); } if (wc->masks.nw_ttl) { ds_put_format(s, "nw_ttl=%"PRIu8",", f->nw_ttl); } if (wc->masks.mpls_lse & htonl(MPLS_LABEL_MASK)) { ds_put_format(s, "mpls_label=%"PRIu32",", mpls_lse_to_label(f->mpls_lse)); } if (wc->masks.mpls_lse & htonl(MPLS_TC_MASK)) { ds_put_format(s, "mpls_tc=%"PRIu8",", mpls_lse_to_tc(f->mpls_lse)); } if (wc->masks.mpls_lse & htonl(MPLS_BOS_MASK)) { ds_put_format(s, "mpls_bos=%"PRIu8",", mpls_lse_to_bos(f->mpls_lse)); } switch (wc->masks.nw_frag) { case FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_ANY ? (f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "first") : (f->nw_frag & FLOW_NW_FRAG_LATER ? "<error>" : "no")); break; case FLOW_NW_FRAG_ANY: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_ANY ? "yes" : "no"); break; case FLOW_NW_FRAG_LATER: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "not_later"); break; } if (f->dl_type == htons(ETH_TYPE_IP) && f->nw_proto == IPPROTO_ICMP) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); } else if (f->dl_type == htons(ETH_TYPE_IPV6) && f->nw_proto == IPPROTO_ICMPV6) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); format_ipv6_netmask(s, "nd_target", &f->nd_target, &wc->masks.nd_target); format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha); } else { format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst); } if (s->length > start_len && ds_last(s) == ',') { s->length--; } }
/* Appends a string representation of 'match' to 's'. If 'priority' is * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */ void match_format(const struct match *match, struct ds *s, unsigned int priority) { const struct flow_wildcards *wc = &match->wc; size_t start_len = s->length; const struct flow *f = &match->flow; bool skip_type = false; bool skip_proto = false; int i; BUILD_ASSERT_DECL(FLOW_WC_SEQ == 26); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%u,", priority); } format_uint32_masked(s, "pkt_mark", f->pkt_mark, wc->masks.pkt_mark); if (wc->masks.recirc_id) { format_uint32_masked(s, "recirc_id", f->recirc_id, wc->masks.recirc_id); } if (f->dp_hash && wc->masks.dp_hash) { format_uint32_masked(s, "dp_hash", f->dp_hash, wc->masks.dp_hash); } if (wc->masks.skb_priority) { ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority); } if (wc->masks.dl_type) { skip_type = true; if (f->dl_type == htons(ETH_TYPE_IP)) { if (wc->masks.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 if (f->nw_proto == IPPROTO_SCTP) { ds_put_cstr(s, "sctp,"); } 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 (wc->masks.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 if (f->nw_proto == IPPROTO_SCTP) { ds_put_cstr(s, "sctp6,"); } 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 if (f->dl_type == htons(ETH_TYPE_RARP)) { ds_put_cstr(s, "rarp,"); } else if (f->dl_type == htons(ETH_TYPE_MPLS)) { ds_put_cstr(s, "mpls,"); } else if (f->dl_type == htons(ETH_TYPE_MPLS_MCAST)) { ds_put_cstr(s, "mplsm,"); } else { skip_type = false; } } for (i = 0; i < FLOW_N_REGS; i++) { #define REGNAME_LEN 20 char regname[REGNAME_LEN]; if (snprintf(regname, REGNAME_LEN, "reg%d", i) >= REGNAME_LEN) { strcpy(regname, "reg?"); } format_uint32_masked(s, regname, f->regs[i], wc->masks.regs[i]); } format_flow_tunnel(s, match); format_be64_masked(s, "metadata", f->metadata, wc->masks.metadata); if (wc->masks.in_port.ofp_port) { ds_put_cstr(s, "in_port="); ofputil_format_port(f->in_port.ofp_port, s); ds_put_char(s, ','); } if (wc->masks.vlan_tci) { ovs_be16 vid_mask = wc->masks.vlan_tci & htons(VLAN_VID_MASK); ovs_be16 pcp_mask = wc->masks.vlan_tci & htons(VLAN_PCP_MASK); ovs_be16 cfi = wc->masks.vlan_tci & 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->masks.vlan_tci == 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->masks.vlan_tci)); } } format_eth_masked(s, "dl_src", f->dl_src, wc->masks.dl_src); format_eth_masked(s, "dl_dst", f->dl_dst, wc->masks.dl_dst); if (!skip_type && wc->masks.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->masks.ipv6_src); format_ipv6_netmask(s, "ipv6_dst", &f->ipv6_dst, &wc->masks.ipv6_dst); if (wc->masks.ipv6_label) { if (wc->masks.ipv6_label == OVS_BE32_MAX) { ds_put_format(s, "ipv6_label=0x%05"PRIx32",", ntohl(f->ipv6_label)); } else { ds_put_format(s, "ipv6_label=0x%05"PRIx32"/0x%05"PRIx32",", ntohl(f->ipv6_label), ntohl(wc->masks.ipv6_label)); } } } else if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst); } else { format_ip_netmask(s, "nw_src", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst); } if (!skip_proto && wc->masks.nw_proto) { if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { 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) || f->dl_type == htons(ETH_TYPE_RARP)) { format_eth_masked(s, "arp_sha", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "arp_tha", f->arp_tha, wc->masks.arp_tha); } if (wc->masks.nw_tos & IP_DSCP_MASK) { ds_put_format(s, "nw_tos=%"PRIu8",", f->nw_tos & IP_DSCP_MASK); } if (wc->masks.nw_tos & IP_ECN_MASK) { ds_put_format(s, "nw_ecn=%"PRIu8",", f->nw_tos & IP_ECN_MASK); } if (wc->masks.nw_ttl) { ds_put_format(s, "nw_ttl=%"PRIu8",", f->nw_ttl); } if (wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) { ds_put_format(s, "mpls_label=%"PRIu32",", mpls_lse_to_label(f->mpls_lse[0])); } if (wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) { ds_put_format(s, "mpls_tc=%"PRIu8",", mpls_lse_to_tc(f->mpls_lse[0])); } if (wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) { ds_put_format(s, "mpls_ttl=%"PRIu8",", mpls_lse_to_ttl(f->mpls_lse[0])); } if (wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) { ds_put_format(s, "mpls_bos=%"PRIu8",", mpls_lse_to_bos(f->mpls_lse[0])); } format_be32_masked(s, "mpls_lse1", f->mpls_lse[1], wc->masks.mpls_lse[1]); format_be32_masked(s, "mpls_lse2", f->mpls_lse[2], wc->masks.mpls_lse[2]); switch (wc->masks.nw_frag) { case FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_ANY ? (f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "first") : (f->nw_frag & FLOW_NW_FRAG_LATER ? "<error>" : "no")); break; case FLOW_NW_FRAG_ANY: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_ANY ? "yes" : "no"); break; case FLOW_NW_FRAG_LATER: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "not_later"); break; } if (f->dl_type == htons(ETH_TYPE_IP) && f->nw_proto == IPPROTO_ICMP) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); //add by ljx // format_be16_masked(s, "icmp_identify", *(ovs_be16*)(&f->ipv6_label), // *(ovs_be16*)&wc->masks.ipv6_label); format_be16_masked(s, "icmp_identify", f->ipv6_label, wc->masks.ipv6_label); } else if (f->dl_type == htons(ETH_TYPE_IPV6) && f->nw_proto == IPPROTO_ICMPV6) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); format_ipv6_netmask(s, "nd_target", &f->nd_target, &wc->masks.nd_target); format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha); } else { format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst); } if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) { uint16_t mask = TCP_FLAGS(wc->masks.tcp_flags); if (mask == TCP_FLAGS(OVS_BE16_MAX)) { ds_put_format(s, "tcp_flags=0x%03"PRIx16",", ntohs(f->tcp_flags)); } else { format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string, ntohs(f->tcp_flags), mask); } } if (s->length > start_len && ds_last(s) == ',') { s->length--; } }