Exemplo n.º 1
0
/* Masks the fields in 'wc' that are used by the flow hash 'fields'. */
void
flow_mask_hash_fields(const struct flow *flow, struct flow_wildcards *wc,
                      enum nx_hash_fields fields)
{
    switch (fields) {
    case NX_HASH_FIELDS_ETH_SRC:
        memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
        break;

    case NX_HASH_FIELDS_SYMMETRIC_L4:
        memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
        memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
        if (flow->dl_type == htons(ETH_TYPE_IP)) {
            memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
            memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
        } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
            memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
            memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
        }
        if (is_ip_any(flow)) {
            memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
            memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
            memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
        }
        wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
        break;

    default:
        NOT_REACHED();
    }
}
Exemplo n.º 2
0
/* 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--;
    }
}
Exemplo n.º 3
0
/* Converts a flow into a match.  It sets the wildcard masks based on
 * the packet contents.  It will not set the mask for fields that do not
 * make sense for the packet type. */
void
match_wc_init(struct match *match, const struct flow *flow)
{
    struct flow_wildcards *wc;
    int i;

    match->flow = *flow;
    wc = &match->wc;
    memset(&wc->masks, 0x0, sizeof wc->masks);

    memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);

    if (flow->nw_proto) {
        memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
    }

    if (flow->skb_priority) {
        memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority);
    }

    if (flow->skb_mark) {
        memset(&wc->masks.skb_mark, 0xff, sizeof wc->masks.skb_mark);
    }

    for (i = 0; i < FLOW_N_REGS; i++) {
        if (flow->regs[i]) {
            memset(&wc->masks.regs[i], 0xff, sizeof wc->masks.regs[i]);
        }
    }

    if (flow->tunnel.ip_dst) {
        if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
            memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
        }
        memset(&wc->masks.tunnel.ip_src, 0xff, sizeof wc->masks.tunnel.ip_src);
        memset(&wc->masks.tunnel.ip_dst, 0xff, sizeof wc->masks.tunnel.ip_dst);
        memset(&wc->masks.tunnel.flags, 0xff, sizeof wc->masks.tunnel.flags);
        memset(&wc->masks.tunnel.ip_tos, 0xff, sizeof wc->masks.tunnel.ip_tos);
        memset(&wc->masks.tunnel.ip_ttl, 0xff, sizeof wc->masks.tunnel.ip_ttl);
    } else if (flow->tunnel.tun_id) {
        memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
    }

    memset(&wc->masks.metadata, 0xff, sizeof wc->masks.metadata);
    memset(&wc->masks.in_port, 0xff, sizeof wc->masks.in_port);
    memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
    memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
    memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);

    if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
        memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
        memset(&wc->masks.ipv6_label, 0xff, sizeof wc->masks.ipv6_label);
    } else if (flow->dl_type == htons(ETH_TYPE_IP) ||
               (flow->dl_type == htons(ETH_TYPE_ARP)) ||
               (flow->dl_type == htons(ETH_TYPE_RARP))) {
        memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
        memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
    }

    if (flow->dl_type == htons(ETH_TYPE_ARP) ||
        flow->dl_type == htons(ETH_TYPE_RARP)) {
        memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
        memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
    }

    if (is_ip_any(flow)) {
        memset(&wc->masks.nw_tos, 0xff, sizeof wc->masks.nw_tos);
        memset(&wc->masks.nw_ttl, 0xff, sizeof wc->masks.nw_ttl);
    }

    if (flow->nw_frag) {
        memset(&wc->masks.nw_frag, 0xff, sizeof wc->masks.nw_frag);
    }

    if (flow->nw_proto == IPPROTO_ICMP || flow->nw_proto == IPPROTO_ICMPV6 ||
        (flow->tp_src || flow->tp_dst)) {
        memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
        memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
    }

    if (flow->nw_proto == IPPROTO_ICMPV6) {
        memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
        memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
    }

    return;
}
Exemplo n.º 4
0
/* Converts a flow into a match.  It sets the wildcard masks based on
 * the packet contents.  It will not set the mask for fields that do not
 * make sense for the packet type. */
void
match_wc_init(struct match *match, const struct flow *flow)
{
    struct flow_wildcards *wc;
    int i;

    match->flow = *flow;
    wc = &match->wc;
    memset(&wc->masks, 0x0, sizeof wc->masks);

    memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);

    if (flow->nw_proto) {
        memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
    }

    if (flow->skb_priority) {
        memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority);
    }

    if (flow->pkt_mark) {
        memset(&wc->masks.pkt_mark, 0xff, sizeof wc->masks.pkt_mark);
    }

    for (i = 0; i < FLOW_N_REGS; i++) {
        if (flow->regs[i]) {
            memset(&wc->masks.regs[i], 0xff, sizeof wc->masks.regs[i]);
        }
    }

    if (flow->tunnel.ip_dst) {
        if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
            memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
        }
        memset(&wc->masks.tunnel.ip_src, 0xff, sizeof wc->masks.tunnel.ip_src);
        memset(&wc->masks.tunnel.ip_dst, 0xff, sizeof wc->masks.tunnel.ip_dst);
        memset(&wc->masks.tunnel.flags, 0xff, sizeof wc->masks.tunnel.flags);
        memset(&wc->masks.tunnel.ip_tos, 0xff, sizeof wc->masks.tunnel.ip_tos);
        memset(&wc->masks.tunnel.ip_ttl, 0xff, sizeof wc->masks.tunnel.ip_ttl);
    } else if (flow->tunnel.tun_id) {
        memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
    }

    memset(&wc->masks.metadata, 0xff, sizeof wc->masks.metadata);
    memset(&wc->masks.in_port, 0xff, sizeof wc->masks.in_port);
    memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
    memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
    memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);

    if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
        memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
        memset(&wc->masks.ipv6_label, 0xff, sizeof wc->masks.ipv6_label);
    } else if (flow->dl_type == htons(ETH_TYPE_IP) ||
               (flow->dl_type == htons(ETH_TYPE_ARP)) ||
               (flow->dl_type == htons(ETH_TYPE_RARP))) {
        memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
        memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
    } else if (eth_type_mpls(flow->dl_type)) {
        int i;

        for (i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {
            wc->masks.mpls_lse[i] = OVS_BE32_MAX;
            if (flow->mpls_lse[i] & htonl(MPLS_BOS_MASK)) {
                break;
            }
        }
    }

    if (flow->dl_type == htons(ETH_TYPE_ARP) ||
        flow->dl_type == htons(ETH_TYPE_RARP)) {
        memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
        memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
    }

    if (is_ip_any(flow)) {
        memset(&wc->masks.nw_tos, 0xff, sizeof wc->masks.nw_tos);
        memset(&wc->masks.nw_ttl, 0xff, sizeof wc->masks.nw_ttl);

        if (flow->nw_frag) {
            memset(&wc->masks.nw_frag, 0xff, sizeof wc->masks.nw_frag);
            if (flow->nw_frag & FLOW_NW_FRAG_LATER) {
                /* No transport layer header in later fragments. */
                return;
            }
        }

        if (flow->nw_proto == IPPROTO_ICMP ||
            flow->nw_proto == IPPROTO_ICMPV6 ||
            (flow->tp_src || flow->tp_dst)) {
            memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
            memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
        }
        if (flow->nw_proto == IPPROTO_TCP) {
            memset(&wc->masks.tcp_flags, 0xff, sizeof wc->masks.tcp_flags);
        }

        if (flow->nw_proto == IPPROTO_ICMPV6) {
            memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha);
            memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha);
            memset(&wc->masks.nd_target, 0xff, sizeof wc->masks.nd_target);
        }
    }

    return;
}