Ejemplo n.º 1
0
/* Returns true if 'wc' matches every packet, false if 'wc' fixes any bits or
 * fields. */
bool
flow_wildcards_is_catchall(const struct flow_wildcards *wc)
{
    int i;

    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14);

    if (wc->wildcards != FWW_ALL
        || wc->tun_id_mask != htonll(0)
        || wc->nw_src_mask != htonl(0)
        || wc->nw_dst_mask != htonl(0)
        || wc->tp_src_mask != htons(0)
        || wc->tp_dst_mask != htons(0)
        || wc->vlan_tci_mask != htons(0)
        || wc->metadata_mask != htonll(0)
        || !eth_addr_is_zero(wc->dl_src_mask)
        || !eth_addr_is_zero(wc->dl_dst_mask)
        || !eth_addr_is_zero(wc->arp_sha_mask)
        || !eth_addr_is_zero(wc->arp_tha_mask)
        || !ipv6_mask_is_any(&wc->ipv6_src_mask)
        || !ipv6_mask_is_any(&wc->ipv6_dst_mask)
        || wc->ipv6_label_mask != htonl(0)
        || !ipv6_mask_is_any(&wc->nd_target_mask)
        || wc->nw_frag_mask != 0) {
        return false;
    }

    for (i = 0; i < FLOW_N_REGS; i++) {
        if (wc->reg_masks[i] != 0) {
            return false;
        }
    }

    return true;
}
Ejemplo n.º 2
0
void
flow_format(struct ds *ds, const struct flow *flow)
{
    ds_put_format(ds, "priority:%"PRIu32
                      ",tunnel:%#"PRIx64
                      ",metadata:%#"PRIx64
                      ",in_port:%04"PRIx16,
                      flow->skb_priority,
                      ntohll(flow->tun_id),
                      ntohll(flow->metadata),
                      flow->in_port);

    ds_put_format(ds, ",tci(");
    if (flow->vlan_tci) {
        ds_put_format(ds, "vlan:%"PRIu16",pcp:%d",
                      vlan_tci_to_vid(flow->vlan_tci),
                      vlan_tci_to_pcp(flow->vlan_tci));
    } else {
        ds_put_char(ds, '0');
    }
    ds_put_format(ds, ") mac("ETH_ADDR_FMT"->"ETH_ADDR_FMT
                      ") type:%04"PRIx16,
                  ETH_ADDR_ARGS(flow->dl_src),
                  ETH_ADDR_ARGS(flow->dl_dst),
                  ntohs(flow->dl_type));

    if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        ds_put_format(ds, " label:%#"PRIx32" proto:%"PRIu8" tos:%#"PRIx8
                          " ttl:%"PRIu8" ipv6(",
                      ntohl(flow->ipv6_label), flow->nw_proto,
                      flow->nw_tos, flow->nw_ttl);
        print_ipv6_addr(ds, &flow->ipv6_src);
        ds_put_cstr(ds, "->");
        print_ipv6_addr(ds, &flow->ipv6_dst);
        ds_put_char(ds, ')');
    } else {
        ds_put_format(ds, " proto:%"PRIu8" tos:%#"PRIx8" ttl:%"PRIu8
                          " ip("IP_FMT"->"IP_FMT")",
                          flow->nw_proto, flow->nw_tos, flow->nw_ttl,
                          IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst));
    }
    if (flow->nw_frag) {
        ds_put_format(ds, " frag(%s)",
                      flow->nw_frag == FLOW_NW_FRAG_ANY ? "first"
                      : flow->nw_frag == (FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER)
                      ? "later" : "<error>");
    }
    if (flow->tp_src || flow->tp_dst) {
        ds_put_format(ds, " port(%"PRIu16"->%"PRIu16")",
                ntohs(flow->tp_src), ntohs(flow->tp_dst));
    }
    if (!eth_addr_is_zero(flow->arp_sha) || !eth_addr_is_zero(flow->arp_tha)) {
        ds_put_format(ds, " arp_ha("ETH_ADDR_FMT"->"ETH_ADDR_FMT")",
                ETH_ADDR_ARGS(flow->arp_sha),
                ETH_ADDR_ARGS(flow->arp_tha));
    }
}
Ejemplo n.º 3
0
static void
format_eth_masked(struct ds *s, const char *name, const uint8_t eth[6],
                  const uint8_t mask[6])
{
    if (!eth_addr_is_zero(mask)) {
        ds_put_format(s, "%s=", name);
        eth_format_masked(eth, mask, s);
        ds_put_char(s, ',');
    }
}
Ejemplo n.º 4
0
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);
        }
    }
}
Ejemplo n.º 5
0
static bool
parse_icmpv6(struct ofpbuf *b, struct flow *flow)
{
    const struct icmp6_hdr *icmp = pull_icmpv6(b);

    if (!icmp) {
        return false;
    }

    /* The ICMPv6 type and code fields use the 16-bit transport port
     * fields, so we need to store them in 16-bit network byte order. */
    flow->tp_src = htons(icmp->icmp6_type);
    flow->tp_dst = htons(icmp->icmp6_code);

    if (icmp->icmp6_code == 0 &&
        (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
         icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) {
        const struct in6_addr *nd_target;

        nd_target = ofpbuf_try_pull(b, sizeof *nd_target);
        if (!nd_target) {
            return false;
        }
        flow->nd_target = *nd_target;

        while (b->size >= 8) {
            /* The minimum size of an option is 8 bytes, which also is
             * the size of Ethernet link-layer options. */
            const struct nd_opt_hdr *nd_opt = b->data;
            int opt_len = nd_opt->nd_opt_len * 8;

            if (!opt_len || opt_len > b->size) {
                goto invalid;
            }

            /* Store the link layer address if the appropriate option is
             * provided.  It is considered an error if the same link
             * layer option is specified twice. */
            if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR
                    && opt_len == 8) {
                if (eth_addr_is_zero(flow->arp_sha)) {
                    memcpy(flow->arp_sha, nd_opt + 1, ETH_ADDR_LEN);
                } else {
                    goto invalid;
                }
            } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR
                    && opt_len == 8) {
                if (eth_addr_is_zero(flow->arp_tha)) {
                    memcpy(flow->arp_tha, nd_opt + 1, ETH_ADDR_LEN);
                } else {
                    goto invalid;
                }
            }

            if (!ofpbuf_try_pull(b, opt_len)) {
                goto invalid;
            }
        }
    }

    return true;

invalid:
    memset(&flow->nd_target, 0, sizeof(flow->nd_target));
    memset(flow->arp_sha, 0, sizeof(flow->arp_sha));
    memset(flow->arp_tha, 0, sizeof(flow->arp_tha));

    return false;

}