X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=f017fc9f42baf577005dcbeffa5930f66f12270f;hb=23e795f4dd9af5191773a5ee840642737a37e91d;hp=7aea3319e727b0074ac2d77aa713e08f61e51baf;hpb=dc4762edd02693770d392b8f6495deb7e52635bf;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 7aea3319..f017fc9f 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -124,6 +124,10 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, /* Initialize most of rule->wc. */ flow_wildcards_init_catchall(wc); wc->wildcards = ofpfw & WC_INVARIANTS; + + /* Wildcard fields that aren't defined by ofp_match or tun_id. */ + wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_ND_TARGET); + if (ofpfw & OFPFW_NW_TOS) { wc->wildcards |= FWW_NW_TOS; } @@ -132,9 +136,6 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, if (flow_format == NXFF_TUN_ID_FROM_COOKIE && !(ofpfw & NXFW_TUN_ID)) { rule->flow.tun_id = htonll(ntohll(cookie) >> 32); - } else { - wc->wildcards |= FWW_TUN_ID; - rule->flow.tun_id = htonll(0); } if (ofpfw & OFPFW_DL_DST) { @@ -149,7 +150,7 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, rule->flow.nw_dst = match->nw_dst; rule->flow.in_port = (match->in_port == htons(OFPP_LOCAL) ? ODPP_LOCAL : ntohs(match->in_port)); - rule->flow.dl_type = match->dl_type; + rule->flow.dl_type = ofputil_dl_type_from_openflow(match->dl_type); rule->flow.tp_src = match->tp_src; rule->flow.tp_dst = match->tp_dst; memcpy(rule->flow.dl_src, match->dl_src, ETH_ADDR_LEN); @@ -233,7 +234,7 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, /* Tunnel ID. */ if (flow_format == NXFF_TUN_ID_FROM_COOKIE) { - if (wc->wildcards & FWW_TUN_ID) { + if (wc->tun_id_mask == htonll(0)) { ofpfw |= NXFW_TUN_ID; } else { uint32_t cookie_lo = ntohll(cookie_in); @@ -273,7 +274,7 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, : rule->flow.in_port); memcpy(match->dl_src, rule->flow.dl_src, ETH_ADDR_LEN); memcpy(match->dl_dst, rule->flow.dl_dst, ETH_ADDR_LEN); - match->dl_type = rule->flow.dl_type; + match->dl_type = ofputil_dl_type_to_openflow(rule->flow.dl_type); match->nw_src = rule->flow.nw_src; match->nw_dst = rule->flow.nw_dst; match->nw_tos = rule->flow.nw_tos; @@ -284,6 +285,27 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, memset(match->pad2, '\0', sizeof match->pad2); } +/* Given a 'dl_type' value in the format used in struct flow, returns the + * corresponding 'dl_type' value for use in an OpenFlow ofp_match structure. */ +ovs_be16 +ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type) +{ + return (flow_dl_type == htons(FLOW_DL_TYPE_NONE) + ? htons(OFP_DL_TYPE_NOT_ETH_TYPE) + : flow_dl_type); +} + +/* Given a 'dl_type' value in the format used in an OpenFlow ofp_match + * structure, returns the corresponding 'dl_type' value for use in struct + * flow. */ +ovs_be16 +ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type) +{ + return (ofp_dl_type == htons(OFP_DL_TYPE_NOT_ETH_TYPE) + ? htons(FLOW_DL_TYPE_NONE) + : ofp_dl_type); +} + /* Returns a transaction ID to use for an outgoing OpenFlow message. */ static ovs_be32 alloc_xid(void) @@ -829,6 +851,69 @@ regs_fully_wildcarded(const struct flow_wildcards *wc) return true; } +static inline bool +is_nxm_required(const struct cls_rule *rule, bool cookie_support, + ovs_be64 cookie) +{ + const struct flow_wildcards *wc = &rule->wc; + uint32_t cookie_hi; + uint64_t tun_id; + + /* Only NXM supports separately wildcards the Ethernet multicast bit. */ + if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) { + return true; + } + + /* Only NXM supports matching ARP hardware addresses. */ + if (!(wc->wildcards & FWW_ARP_SHA) || !(wc->wildcards & FWW_ARP_THA)) { + return true; + } + + /* Only NXM supports matching IPv6 traffic. */ + if (!(wc->wildcards & FWW_DL_TYPE) + && (rule->flow.dl_type == htons(ETH_TYPE_IPV6))) { + return true; + } + + /* Only NXM supports matching registers. */ + if (!regs_fully_wildcarded(wc)) { + return true; + } + + switch (wc->tun_id_mask) { + case CONSTANT_HTONLL(0): + /* Other formats can fully wildcard tun_id. */ + break; + + case CONSTANT_HTONLL(UINT64_MAX): + /* Only NXM supports tunnel ID matching without a cookie. */ + if (!cookie_support) { + return true; + } + + /* Only NXM supports 64-bit tunnel IDs. */ + tun_id = ntohll(rule->flow.tun_id); + if (tun_id > UINT32_MAX) { + return true; + } + + /* Only NXM supports a cookie whose top 32 bits conflict with the + * tunnel ID. */ + cookie_hi = ntohll(cookie) >> 32; + if (cookie_hi && cookie_hi != tun_id) { + return true; + } + break; + + default: + /* Only NXM supports partial matches on tunnel ID. */ + return true; + } + + /* Other formats can express this rule. */ + return false; +} + /* Returns the minimum nx_flow_format to use for sending 'rule' to a switch * (e.g. to add or remove a flow). 'cookie_support' should be true if the * command to be sent includes a flow cookie (as OFPT_FLOW_MOD does, for @@ -853,16 +938,9 @@ enum nx_flow_format ofputil_min_flow_format(const struct cls_rule *rule, bool cookie_support, ovs_be64 cookie) { - const struct flow_wildcards *wc = &rule->wc; - ovs_be32 cookie_hi = htonl(ntohll(cookie) >> 32); - - if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST) - || !regs_fully_wildcarded(wc) - || (!(wc->wildcards & FWW_TUN_ID) - && (!cookie_support - || (cookie_hi && cookie_hi != ntohll(rule->flow.tun_id))))) { + if (is_nxm_required(rule, cookie_support, cookie)) { return NXFF_NXM; - } else if (!(wc->wildcards & FWW_TUN_ID)) { + } else if (rule->wc.tun_id_mask != htonll(0)) { return NXFF_TUN_ID_FROM_COOKIE; } else { return NXFF_OPENFLOW10; @@ -1980,6 +2058,9 @@ normalize_match(struct ofp_match *m) m->nw_dst &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_DST_SHIFT); } m->tp_src = m->tp_dst = m->nw_tos = 0; + } else if (m->dl_type == htons(ETH_TYPE_IPV6)) { + /* Don't normalize IPv6 traffic, since OpenFlow doesn't have a + * way to express it. */ } else { /* Network and transport layer fields will always be extracted as * zeros, so we can do an exact-match on those values. */