X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fmeta-flow.c;h=41cbf4944d6f7c7337488d5d11c499ba79d8307f;hb=c2b565b54e36bc33d0406afb225c9bf3d01405ef;hp=483fff4f67c8661fda342ad1111b99672a65341a;hpb=268a95e009c4cc57e967e88f916932fac89fdf1c;p=openvswitch diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 483fff4f..41cbf494 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -48,14 +48,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_FULLY, 0, MFS_HEXADECIMAL, MFP_NONE, - NXM_NX_TUN_ID, + true, + NXM_NX_TUN_ID, "NXM_NX_TUN_ID", }, { MFF_IN_PORT, "in_port", NULL, MF_FIELD_SIZES(be16), MFM_NONE, FWW_IN_PORT, MFS_OFP_PORT, MFP_NONE, - NXM_OF_IN_PORT, + false, + NXM_OF_IN_PORT, "NXM_OF_IN_PORT", }, #define REGISTER(IDX) \ @@ -65,7 +67,9 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_FULLY, 0, \ MFS_HEXADECIMAL, \ MFP_NONE, \ + true, \ NXM_NX_REG(IDX), \ + "NXM_NX_REG" #IDX \ } #if FLOW_N_REGS > 0 REGISTER(0), @@ -96,21 +100,24 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_DL_SRC, MFS_ETHERNET, MFP_NONE, - NXM_OF_ETH_SRC, + true, + NXM_OF_ETH_SRC, "NXM_OF_ETH_SRC", }, { MFF_ETH_DST, "eth_dst", "dl_dst", MF_FIELD_SIZES(mac), MFM_MCAST, 0, MFS_ETHERNET, MFP_NONE, - NXM_OF_ETH_DST, + true, + NXM_OF_ETH_DST, "NXM_OF_ETH_DST", }, { MFF_ETH_TYPE, "eth_type", "dl_type", MF_FIELD_SIZES(be16), MFM_NONE, FWW_DL_TYPE, MFS_HEXADECIMAL, MFP_NONE, - NXM_OF_ETH_TYPE, + false, + NXM_OF_ETH_TYPE, "NXM_OF_ETH_TYPE", }, { @@ -119,21 +126,24 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_FULLY, 0, MFS_HEXADECIMAL, MFP_NONE, - NXM_OF_VLAN_TCI, + true, + NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI", }, { MFF_VLAN_VID, "dl_vlan", NULL, sizeof(ovs_be16), 12, MFM_NONE, 0, MFS_DECIMAL, MFP_NONE, - 0, + true, + 0, NULL }, { MFF_VLAN_PCP, "dl_vlan_pcp", NULL, 1, 3, MFM_NONE, 0, MFS_DECIMAL, MFP_NONE, - 0, + true, + 0, NULL }, /* ## -- ## */ @@ -146,14 +156,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_CIDR, 0, MFS_IPV4, MFP_IPV4, - NXM_OF_IP_SRC, + true, + NXM_OF_IP_SRC, "NXM_OF_IP_SRC", }, { MFF_IPV4_DST, "ip_dst", "nw_dst", MF_FIELD_SIZES(be32), MFM_CIDR, 0, MFS_IPV4, MFP_IPV4, - NXM_OF_IP_DST, + true, + NXM_OF_IP_DST, "NXM_OF_IP_DST", }, { @@ -162,14 +174,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_CIDR, 0, MFS_IPV6, MFP_IPV6, - NXM_NX_IPV6_SRC, + true, + NXM_NX_IPV6_SRC, "NXM_NX_IPV6_SRC", }, { MFF_IPV6_DST, "ipv6_dst", NULL, MF_FIELD_SIZES(ipv6), MFM_CIDR, 0, MFS_IPV6, MFP_IPV6, - NXM_NX_IPV6_DST, + true, + NXM_NX_IPV6_DST, "NXM_NX_IPV6_DST", }, { MFF_IPV6_LABEL, "ipv6_label", NULL, @@ -177,7 +191,8 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_IPV6_LABEL, MFS_HEXADECIMAL, MFP_IPV6, - NXM_NX_IPV6_LABEL, + false, + NXM_NX_IPV6_LABEL, "NXM_NX_IPV6_LABEL", }, { @@ -186,35 +201,40 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_NW_PROTO, MFS_DECIMAL, MFP_IP_ANY, - NXM_OF_IP_PROTO, + false, + NXM_OF_IP_PROTO, "NXM_OF_IP_PROTO", }, { MFF_IP_DSCP, "nw_tos", NULL, MF_FIELD_SIZES(u8), MFM_NONE, FWW_NW_DSCP, MFS_DECIMAL, MFP_IP_ANY, - NXM_OF_IP_TOS, + true, + NXM_OF_IP_TOS, "NXM_OF_IP_TOS" }, { MFF_IP_ECN, "nw_ecn", NULL, 1, 2, MFM_NONE, FWW_NW_ECN, MFS_DECIMAL, MFP_IP_ANY, - NXM_NX_IP_ECN, + true, + NXM_NX_IP_ECN, "NXM_NX_IP_ECN", }, { MFF_IP_TTL, "nw_ttl", NULL, MF_FIELD_SIZES(u8), MFM_NONE, FWW_NW_TTL, MFS_DECIMAL, MFP_IP_ANY, - NXM_NX_IP_TTL, + true, + NXM_NX_IP_TTL, "NXM_NX_IP_TTL" }, { MFF_IP_FRAG, "ip_frag", NULL, 1, 2, MFM_FULLY, 0, MFS_FRAG, MFP_IP_ANY, - NXM_NX_IP_FRAG, + false, + NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG" }, { @@ -223,35 +243,40 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_NW_PROTO, MFS_DECIMAL, MFP_ARP, - NXM_OF_ARP_OP, + false, + NXM_OF_ARP_OP, "NXM_OF_ARP_OP", }, { MFF_ARP_SPA, "arp_spa", NULL, MF_FIELD_SIZES(be32), MFM_CIDR, 0, MFS_IPV4, MFP_ARP, - NXM_OF_ARP_SPA, + false, + NXM_OF_ARP_SPA, "NXM_OF_ARP_SPA", }, { MFF_ARP_TPA, "arp_tpa", NULL, MF_FIELD_SIZES(be32), MFM_CIDR, 0, MFS_IPV4, MFP_ARP, - NXM_OF_ARP_TPA, + false, + NXM_OF_ARP_TPA, "NXM_OF_ARP_TPA", }, { MFF_ARP_SHA, "arp_sha", NULL, MF_FIELD_SIZES(mac), MFM_NONE, FWW_ARP_SHA, MFS_ETHERNET, MFP_ARP, - NXM_NX_ARP_SHA, + false, + NXM_NX_ARP_SHA, "NXM_NX_ARP_SHA", }, { MFF_ARP_THA, "arp_tha", NULL, MF_FIELD_SIZES(mac), MFM_NONE, FWW_ARP_THA, MFS_ETHERNET, MFP_ARP, - NXM_NX_ARP_THA, + false, + NXM_NX_ARP_THA, "NXM_NX_ARP_THA", }, /* ## -- ## */ @@ -264,14 +289,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_TP_SRC, MFS_DECIMAL, MFP_TCP, - NXM_OF_TCP_SRC, + true, + NXM_OF_TCP_SRC, "NXM_OF_TCP_SRC", }, { MFF_TCP_DST, "tcp_dst", "tp_dst", MF_FIELD_SIZES(be16), MFM_NONE, FWW_TP_DST, MFS_DECIMAL, MFP_TCP, - NXM_OF_TCP_DST, + true, + NXM_OF_TCP_DST, "NXM_OF_TCP_DST", }, { @@ -280,14 +307,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_TP_SRC, MFS_DECIMAL, MFP_UDP, - NXM_OF_UDP_SRC, + true, + NXM_OF_UDP_SRC, "NXM_OF_UDP_SRC", }, { MFF_UDP_DST, "udp_dst", NULL, MF_FIELD_SIZES(be16), MFM_NONE, FWW_TP_DST, MFS_DECIMAL, MFP_UDP, - NXM_OF_UDP_DST, + true, + NXM_OF_UDP_DST, "NXM_OF_UDP_DST", }, { @@ -296,28 +325,34 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_TP_SRC, MFS_DECIMAL, MFP_ICMPV4, - NXM_OF_ICMP_TYPE, + false, + NXM_OF_ICMP_TYPE, "NXM_OF_ICMP_TYPE", }, { MFF_ICMPV4_CODE, "icmp_code", NULL, MF_FIELD_SIZES(u8), MFM_NONE, FWW_TP_DST, MFS_DECIMAL, MFP_ICMPV4, - NXM_OF_ICMP_CODE, - }, { + false, + NXM_OF_ICMP_CODE, "NXM_OF_ICMP_CODE", + }, + + { MFF_ICMPV6_TYPE, "icmpv6_type", NULL, MF_FIELD_SIZES(u8), MFM_NONE, FWW_TP_SRC, MFS_DECIMAL, MFP_ICMPV6, - NXM_NX_ICMPV6_TYPE, + false, + NXM_NX_ICMPV6_TYPE, "NXM_NX_ICMPV6_TYPE", }, { MFF_ICMPV6_CODE, "icmpv6_code", NULL, MF_FIELD_SIZES(u8), MFM_NONE, FWW_TP_DST, MFS_DECIMAL, MFP_ICMPV6, - NXM_NX_ICMPV6_CODE, + false, + NXM_NX_ICMPV6_CODE, "NXM_NX_ICMPV6_CODE", }, /* ## ---- ## */ @@ -330,24 +365,35 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { MFM_NONE, FWW_ND_TARGET, MFS_IPV6, MFP_ND, - NXM_NX_ND_TARGET, + false, + NXM_NX_ND_TARGET, "NXM_NX_ND_TARGET", }, { MFF_ND_SLL, "nd_sll", NULL, MF_FIELD_SIZES(mac), MFM_NONE, FWW_ARP_SHA, MFS_ETHERNET, MFP_ND_SOLICIT, - NXM_NX_ND_SLL, + false, + NXM_NX_ND_SLL, "NXM_NX_ND_SLL", }, { MFF_ND_TLL, "nd_tll", NULL, MF_FIELD_SIZES(mac), MFM_NONE, FWW_ARP_THA, MFS_ETHERNET, MFP_ND_ADVERT, - NXM_NX_ND_TLL, + false, + NXM_NX_ND_TLL, "NXM_NX_ND_TLL", } }; +struct nxm_field { + struct hmap_node hmap_node; + uint32_t nxm_header; + const struct mf_field *mf; +}; + +static struct hmap all_nxm_fields = HMAP_INITIALIZER(&all_nxm_fields); + /* Returns the field with the given 'id'. */ const struct mf_field * mf_from_id(enum mf_field_id id) @@ -377,6 +423,64 @@ mf_from_name(const char *name) return shash_find_data(&mf_by_name, name); } +static void +add_nxm_field(uint32_t nxm_header, const struct mf_field *mf) +{ + struct nxm_field *f; + + f = xmalloc(sizeof *f); + hmap_insert(&all_nxm_fields, &f->hmap_node, hash_int(nxm_header, 0)); + f->nxm_header = nxm_header; + f->mf = mf; +} + +static void +nxm_init(void) +{ + const struct mf_field *mf; + + for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) { + if (mf->nxm_header) { + add_nxm_field(mf->nxm_header, mf); + if (mf->maskable != MFM_NONE) { + add_nxm_field(NXM_MAKE_WILD_HEADER(mf->nxm_header), mf); + } + } + } + +#ifndef NDEBUG + /* Verify that the header values are unique. */ + for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) { + if (mf->nxm_header) { + assert(mf_from_nxm_header(mf->nxm_header) == mf); + if (mf->maskable != MFM_NONE) { + assert(mf_from_nxm_header(NXM_MAKE_WILD_HEADER(mf->nxm_header)) + == mf); + } + } + } +#endif +} + +const struct mf_field * +mf_from_nxm_header(uint32_t header) +{ + const struct nxm_field *f; + + if (hmap_is_empty(&all_nxm_fields)) { + nxm_init(); + } + + HMAP_FOR_EACH_IN_BUCKET (f, hmap_node, hash_int(header, 0), + &all_nxm_fields) { + if (f->nxm_header == header) { + return f->mf; + } + } + + return NULL; +} + /* Returns true if 'wc' wildcards all the bits in field 'mf', false if 'wc' * specifies at least one bit in the field. * @@ -1072,6 +1176,163 @@ mf_set_value(const struct mf_field *mf, } } +/* Makes 'rule' match field 'mf' exactly, with the value matched taken from + * 'value'. The caller is responsible for ensuring that 'rule' meets 'mf''s + * prerequisites. */ +void +mf_set_flow_value(const struct mf_field *mf, + const union mf_value *value, struct flow *flow) +{ + switch (mf->id) { + case MFF_TUN_ID: + flow->tun_id = value->be64; + break; + + case MFF_IN_PORT: + flow->in_port = ntohs(value->be16); + break; + +#if FLOW_N_REGS > 0 + case MFF_REG0: +#endif +#if FLOW_N_REGS > 1 + case MFF_REG1: +#endif +#if FLOW_N_REGS > 2 + case MFF_REG2: +#endif +#if FLOW_N_REGS > 3 + case MFF_REG3: +#endif +#if FLOW_N_REGS > 4 + case MFF_REG4: +#endif +#if FLOW_N_REGS > 5 +#error +#endif +#if FLOW_N_REGS > 0 + flow->regs[mf->id - MFF_REG0] = ntohl(value->be32); + break; +#endif + + case MFF_ETH_SRC: + memcpy(flow->dl_src, value->mac, ETH_ADDR_LEN); + break; + + case MFF_ETH_DST: + memcpy(flow->dl_src, value->mac, ETH_ADDR_LEN); + break; + + case MFF_ETH_TYPE: + flow->dl_type = value->be16; + break; + + case MFF_VLAN_TCI: + flow->vlan_tci = value->be16; + break; + + case MFF_VLAN_VID: + flow_set_vlan_vid(flow, value->be16); + break; + + case MFF_VLAN_PCP: + flow_set_vlan_pcp(flow, value->u8); + break; + + case MFF_IPV4_SRC: + flow->nw_src = value->be32; + break; + + case MFF_IPV4_DST: + flow->nw_dst = value->be32; + break; + + case MFF_IPV6_SRC: + flow->ipv6_src = value->ipv6; + break; + + case MFF_IPV6_DST: + flow->ipv6_dst = value->ipv6; + break; + + case MFF_IPV6_LABEL: + flow->ipv6_label = value->be32 & ~htonl(IPV6_LABEL_MASK); + break; + + case MFF_IP_PROTO: + flow->nw_proto = value->u8; + break; + + case MFF_IP_DSCP: + flow->nw_tos &= ~IP_DSCP_MASK; + flow->nw_tos |= value->u8 & IP_DSCP_MASK; + break; + + case MFF_IP_ECN: + flow->nw_tos &= ~IP_ECN_MASK; + flow->nw_tos |= value->u8 & IP_ECN_MASK; + break; + + case MFF_IP_TTL: + flow->nw_ttl = value->u8; + break; + + case MFF_IP_FRAG: + flow->nw_frag &= value->u8; + break; + + case MFF_ARP_OP: + flow->nw_proto = ntohs(value->be16); + break; + + case MFF_ARP_SPA: + flow->nw_src = value->be32; + break; + + case MFF_ARP_TPA: + flow->nw_dst = value->be32; + break; + + case MFF_ARP_SHA: + case MFF_ND_SLL: + memcpy(flow->arp_sha, value->mac, ETH_ADDR_LEN); + break; + + case MFF_ARP_THA: + case MFF_ND_TLL: + memcpy(flow->arp_tha, value->mac, ETH_ADDR_LEN); + break; + + case MFF_TCP_SRC: + case MFF_UDP_SRC: + flow->tp_src = value->be16; + break; + + case MFF_TCP_DST: + case MFF_UDP_DST: + flow->tp_dst = value->be16; + break; + + case MFF_ICMPV4_TYPE: + case MFF_ICMPV6_TYPE: + flow->tp_src = htons(value->u8); + break; + + case MFF_ICMPV4_CODE: + case MFF_ICMPV6_CODE: + flow->tp_dst = htons(value->u8); + break; + + case MFF_ND_TARGET: + flow->nd_target = value->ipv6; + break; + + case MFF_N_IDS: + default: + NOT_REACHED(); + } +} + /* Makes 'rule' wildcard field 'mf'. * * The caller is responsible for ensuring that 'rule' meets 'mf''s