X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=5aa2b825e1142d0147ff461d291c42057dbce502;hb=dc432c2e8159a406e0e45fae4ff49532191b9129;hp=e42abc50f9a630135a956042e3ba425069661fe5;hpb=ebb57021a9827b59997a00defc32bf761bc16148;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index e42abc50..5aa2b825 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -19,6 +19,7 @@ #include #include #include +#include "autopath.h" #include "byte-order.h" #include "classifier.h" #include "dynamic-string.h" @@ -101,25 +102,17 @@ enum { }; /* Converts the ofp_match in 'match' into a cls_rule in 'rule', with the given - * 'priority'. - * - * 'flow_format' must either NXFF_OPENFLOW10 or NXFF_TUN_ID_FROM_COOKIE. In - * the latter case only, 'flow''s tun_id field will be taken from the high bits - * of 'cookie', if 'match''s wildcards do not indicate that tun_id is - * wildcarded. */ + * 'priority'. */ void ofputil_cls_rule_from_match(const struct ofp_match *match, - unsigned int priority, - enum nx_flow_format flow_format, - ovs_be64 cookie, struct cls_rule *rule) + unsigned int priority, struct cls_rule *rule) { struct flow_wildcards *wc = &rule->wc; unsigned int ofpfw; ovs_be16 vid, pcp; /* Initialize rule->priority. */ - ofpfw = ntohl(match->wildcards); - ofpfw &= flow_format == NXFF_TUN_ID_FROM_COOKIE ? OVSFW_ALL : OFPFW_ALL; + ofpfw = ntohl(match->wildcards) & OFPFW_ALL; rule->priority = !ofpfw ? UINT16_MAX : priority; /* Initialize most of rule->wc. */ @@ -135,10 +128,6 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, wc->nw_src_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_SRC_SHIFT); wc->nw_dst_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_DST_SHIFT); - if (flow_format == NXFF_TUN_ID_FROM_COOKIE && !(ofpfw & NXFW_TUN_ID)) { - rule->flow.tun_id = htonll(ntohll(cookie) >> 32); - } - if (ofpfw & OFPFW_DL_DST) { /* OpenFlow 1.0 OFPFW_DL_DST covers the whole Ethernet destination, but * Open vSwitch breaks the Ethernet destination into bits as FWW_DL_DST @@ -206,21 +195,9 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, cls_rule_zero_wildcarded_fields(rule); } -/* Convert 'rule' into the OpenFlow match structure 'match'. 'flow_format' - * must either NXFF_OPENFLOW10 or NXFF_TUN_ID_FROM_COOKIE. - * - * The NXFF_TUN_ID_FROM_COOKIE flow format requires modifying the flow cookie. - * This function can help with that, if 'cookie_out' is nonnull. For - * NXFF_OPENFLOW10, or if the tunnel ID is wildcarded, 'cookie_in' will be - * copied directly to '*cookie_out'. For NXFF_TUN_ID_FROM_COOKIE when tunnel - * ID is matched, 'cookie_in' will be modified appropriately before setting - * '*cookie_out'. - */ +/* Convert 'rule' into the OpenFlow match structure 'match'. */ void -ofputil_cls_rule_to_match(const struct cls_rule *rule, - enum nx_flow_format flow_format, - struct ofp_match *match, - ovs_be64 cookie_in, ovs_be64 *cookie_out) +ofputil_cls_rule_to_match(const struct cls_rule *rule, struct ofp_match *match) { const struct flow_wildcards *wc = &rule->wc; unsigned int ofpfw; @@ -233,20 +210,6 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, ofpfw |= OFPFW_NW_TOS; } - /* Tunnel ID. */ - if (flow_format == NXFF_TUN_ID_FROM_COOKIE) { - if (wc->tun_id_mask == htonll(0)) { - ofpfw |= NXFW_TUN_ID; - } else { - uint32_t cookie_lo = ntohll(cookie_in); - uint32_t cookie_hi = ntohll(rule->flow.tun_id); - cookie_in = htonll(cookie_lo | ((uint64_t) cookie_hi << 32)); - } - } - if (cookie_out) { - *cookie_out = cookie_in; - } - /* Translate VLANs. */ match->dl_vlan = htons(0); match->dl_vlan_pcp = 0; @@ -399,10 +362,6 @@ ofputil_decode_vendor(const struct ofp_header *oh, const struct ofputil_msg_type **typep) { static const struct ofputil_msg_type nxt_messages[] = { - { OFPUTIL_NXT_TUN_ID_FROM_COOKIE, - NXT_TUN_ID_FROM_COOKIE, "NXT_TUN_ID_FROM_COOKIE", - sizeof(struct nxt_tun_id_cookie), 0 }, - { OFPUTIL_NXT_ROLE_REQUEST, NXT_ROLE_REQUEST, "NXT_ROLE_REQUEST", sizeof(struct nx_role_request), 0 }, @@ -799,7 +758,6 @@ ofputil_flow_format_is_valid(enum nx_flow_format flow_format) { switch (flow_format) { case NXFF_OPENFLOW10: - case NXFF_TUN_ID_FROM_COOKIE: case NXFF_NXM: return true; } @@ -813,8 +771,6 @@ ofputil_flow_format_to_string(enum nx_flow_format flow_format) switch (flow_format) { case NXFF_OPENFLOW10: return "openflow10"; - case NXFF_TUN_ID_FROM_COOKIE: - return "tun_id_from_cookie"; case NXFF_NXM: return "nxm"; default: @@ -826,7 +782,6 @@ int ofputil_flow_format_from_string(const char *s) { return (!strcmp(s, "openflow10") ? NXFF_OPENFLOW10 - : !strcmp(s, "tun_id_from_cookie") ? NXFF_TUN_ID_FROM_COOKIE : !strcmp(s, "nxm") ? NXFF_NXM : -1); } @@ -844,100 +799,43 @@ 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) +/* Returns the minimum nx_flow_format to use for sending 'rule' to a switch + * (e.g. to add or remove a flow). Only NXM can handle tunnel IDs, registers, + * or fixing the Ethernet multicast bit. Otherwise, it's better to use + * NXFF_OPENFLOW10 for backward compatibility. */ +enum nx_flow_format +ofputil_min_flow_format(const struct cls_rule *rule) { 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; + return NXFF_NXM; } /* Only NXM supports matching ARP hardware addresses. */ if (!(wc->wildcards & FWW_ARP_SHA) || !(wc->wildcards & FWW_ARP_THA)) { - return true; + return NXFF_NXM; } /* Only NXM supports matching IPv6 traffic. */ if (!(wc->wildcards & FWW_DL_TYPE) && (rule->flow.dl_type == htons(ETH_TYPE_IPV6))) { - return true; + return NXFF_NXM; } /* Only NXM supports matching registers. */ if (!regs_fully_wildcarded(wc)) { - return true; + return NXFF_NXM; } - 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; + /* Only NXM supports matching tun_id. */ + if (wc->tun_id_mask != htonll(0)) { + return NXFF_NXM; } /* 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 - * example) or false if the command does not (OFPST_FLOW and OFPST_AGGREGATE do - * not, for example). If 'cookie_support' is true, then 'cookie' should be the - * cookie to be sent; otherwise its value is ignored. - * - * The "best" flow format is chosen on this basis: - * - * - It must be capable of expressing the rule. NXFF_OPENFLOW10 flows can't - * handle tunnel IDs. NXFF_TUN_ID_FROM_COOKIE flows can't handle registers - * or fixing the Ethernet multicast bit, and can't handle tunnel IDs that - * conflict with the high 32 bits of the cookie or commands that don't - * support cookies. - * - * - Otherwise, the chosen format should be as backward compatible as - * possible. (NXFF_OPENFLOW10 is more backward compatible than - * NXFF_TUN_ID_FROM_COOKIE, which is more backward compatible than - * NXFF_NXM.) - */ -enum nx_flow_format -ofputil_min_flow_format(const struct cls_rule *rule, bool cookie_support, - ovs_be64 cookie) -{ - if (is_nxm_required(rule, cookie_support, cookie)) { - return NXFF_NXM; - } else if (rule->wc.tun_id_mask != htonll(0)) { - return NXFF_TUN_ID_FROM_COOKIE; - } else { - return NXFF_OPENFLOW10; - } + return NXFF_OPENFLOW10; } /* Returns an OpenFlow message that can be used to set the flow format to @@ -945,20 +843,11 @@ ofputil_min_flow_format(const struct cls_rule *rule, bool cookie_support, struct ofpbuf * ofputil_make_set_flow_format(enum nx_flow_format flow_format) { + struct nxt_set_flow_format *sff; struct ofpbuf *msg; - if (flow_format == NXFF_OPENFLOW10 - || flow_format == NXFF_TUN_ID_FROM_COOKIE) { - struct nxt_tun_id_cookie *tic; - - tic = make_nxmsg(sizeof *tic, NXT_TUN_ID_FROM_COOKIE, &msg); - tic->set = flow_format == NXFF_TUN_ID_FROM_COOKIE; - } else { - struct nxt_set_flow_format *sff; - - sff = make_nxmsg(sizeof *sff, NXT_SET_FLOW_FORMAT, &msg); - sff->format = htonl(flow_format); - } + sff = make_nxmsg(sizeof *sff, NXT_SET_FLOW_FORMAT, &msg); + sff->format = htonl(flow_format); return msg; } @@ -967,14 +856,9 @@ ofputil_make_set_flow_format(enum nx_flow_format flow_format) * flow_mod in 'fm'. Returns 0 if successful, otherwise an OpenFlow error * code. * - * For OFPT_FLOW_MOD messages, 'flow_format' should be the current flow format - * at the time when the message was received. Otherwise 'flow_format' is - * ignored. - * * Does not validate the flow_mod actions. */ int -ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh, - enum nx_flow_format flow_format) +ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh) { const struct ofputil_msg_type *type; struct ofpbuf b; @@ -1014,8 +898,7 @@ ofputil_decode_flow_mod(struct flow_mod *fm, const struct ofp_header *oh, } /* Translate the message. */ - ofputil_cls_rule_from_match(&match, ntohs(ofm->priority), flow_format, - ofm->cookie, &fm->cr); + ofputil_cls_rule_from_match(&match, ntohs(ofm->priority), &fm->cr); fm->cookie = ofm->cookie; fm->command = ntohs(ofm->command); fm->idle_timeout = ntohs(ofm->idle_timeout); @@ -1064,14 +947,13 @@ ofputil_encode_flow_mod(const struct flow_mod *fm, size_t actions_len = fm->n_actions * sizeof *fm->actions; struct ofpbuf *msg; - if (flow_format == NXFF_OPENFLOW10 - || flow_format == NXFF_TUN_ID_FROM_COOKIE) { + if (flow_format == NXFF_OPENFLOW10) { struct ofp_flow_mod *ofm; msg = ofpbuf_new(sizeof *ofm + actions_len); ofm = put_openflow(sizeof *ofm, OFPT_FLOW_MOD, msg); - ofputil_cls_rule_to_match(&fm->cr, flow_format, &ofm->match, - fm->cookie, &ofm->cookie); + ofputil_cls_rule_to_match(&fm->cr, &ofm->match); + ofm->cookie = fm->cookie; ofm->command = htons(fm->command); ofm->idle_timeout = htons(fm->idle_timeout); ofm->hard_timeout = htons(fm->hard_timeout); @@ -1109,13 +991,12 @@ ofputil_encode_flow_mod(const struct flow_mod *fm, static int ofputil_decode_ofpst_flow_request(struct flow_stats_request *fsr, const struct ofp_header *oh, - enum nx_flow_format flow_format, bool aggregate) { const struct ofp_flow_stats_request *ofsr = ofputil_stats_body(oh); fsr->aggregate = aggregate; - ofputil_cls_rule_from_match(&ofsr->match, 0, flow_format, 0, &fsr->match); + ofputil_cls_rule_from_match(&ofsr->match, 0, &fsr->match); fsr->out_port = ntohs(ofsr->out_port); fsr->table_id = ofsr->table_id; @@ -1150,17 +1031,11 @@ ofputil_decode_nxst_flow_request(struct flow_stats_request *fsr, } /* Converts an OFPST_FLOW, OFPST_AGGREGATE, NXST_FLOW, or NXST_AGGREGATE - * request 'oh', received when the current flow format was 'flow_format', into - * an abstract flow_stats_request in 'fsr'. Returns 0 if successful, otherwise - * an OpenFlow error code. - * - * For OFPST_FLOW and OFPST_AGGREGATE messages, 'flow_format' should be the - * current flow format at the time when the message was received. Otherwise - * 'flow_format' is ignored. */ + * request 'oh', into an abstract flow_stats_request in 'fsr'. Returns 0 if + * successful, otherwise an OpenFlow error code. */ int ofputil_decode_flow_stats_request(struct flow_stats_request *fsr, - const struct ofp_header *oh, - enum nx_flow_format flow_format) + const struct ofp_header *oh) { const struct ofputil_msg_type *type; struct ofpbuf b; @@ -1172,10 +1047,10 @@ ofputil_decode_flow_stats_request(struct flow_stats_request *fsr, code = ofputil_msg_type_code(type); switch (code) { case OFPUTIL_OFPST_FLOW_REQUEST: - return ofputil_decode_ofpst_flow_request(fsr, oh, flow_format, false); + return ofputil_decode_ofpst_flow_request(fsr, oh, false); case OFPUTIL_OFPST_AGGREGATE_REQUEST: - return ofputil_decode_ofpst_flow_request(fsr, oh, flow_format, true); + return ofputil_decode_ofpst_flow_request(fsr, oh, true); case OFPUTIL_NXST_FLOW_REQUEST: return ofputil_decode_nxst_flow_request(fsr, oh, false); @@ -1198,8 +1073,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr, { struct ofpbuf *msg; - if (flow_format == NXFF_OPENFLOW10 - || flow_format == NXFF_TUN_ID_FROM_COOKIE) { + if (flow_format == NXFF_OPENFLOW10) { struct ofp_flow_stats_request *ofsr; int type; @@ -1208,8 +1082,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr, type = fsr->aggregate ? OFPST_AGGREGATE : OFPST_FLOW; ofsr = ofputil_make_stats_request(sizeof *ofsr, type, &msg); - ofputil_cls_rule_to_match(&fsr->match, flow_format, &ofsr->match, - 0, NULL); + ofputil_cls_rule_to_match(&fsr->match, &ofsr->match); ofsr->table_id = fsr->table_id; ofsr->out_port = htons(fsr->out_port); } else if (flow_format == NXFF_NXM) { @@ -1233,9 +1106,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr, } /* Converts an OFPST_FLOW or NXST_FLOW reply in 'msg' into an abstract - * ofputil_flow_stats in 'fs'. For OFPST_FLOW messages, 'flow_format' should - * be the current flow format at the time when the request corresponding to the - * reply in 'msg' was sent. Otherwise 'flow_format' is ignored. + * ofputil_flow_stats in 'fs'. * * Multiple OFPST_FLOW or NXST_FLOW replies can be packed into a single * OpenFlow message. Calling this function multiple times for a single 'msg' @@ -1246,8 +1117,7 @@ ofputil_encode_flow_stats_request(const struct flow_stats_request *fsr, * otherwise a positive errno value. */ int ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, - struct ofpbuf *msg, - enum nx_flow_format flow_format) + struct ofpbuf *msg) { const struct ofputil_msg_type *type; int code; @@ -1292,7 +1162,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, fs->cookie = get_32aligned_be64(&ofs->cookie); ofputil_cls_rule_from_match(&ofs->match, ntohs(ofs->priority), - flow_format, fs->cookie, &fs->rule); + &fs->rule); fs->table_id = ofs->table_id; fs->duration_sec = ntohl(ofs->duration_sec); fs->duration_nsec = ntohl(ofs->duration_nsec); @@ -1343,18 +1213,12 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, return 0; } -/* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh', received - * when the current flow format was 'flow_format', into an abstract - * ofputil_flow_removed in 'fr'. Returns 0 if successful, otherwise an - * OpenFlow error code. - * - * For OFPT_FLOW_REMOVED messages, 'flow_format' should be the current flow - * format at the time when the message was received. Otherwise 'flow_format' - * is ignored. */ +/* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh' into an + * abstract ofputil_flow_removed in 'fr'. Returns 0 if successful, otherwise + * an OpenFlow error code. */ int ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, - const struct ofp_header *oh, - enum nx_flow_format flow_format) + const struct ofp_header *oh) { const struct ofputil_msg_type *type; enum ofputil_msg_code code; @@ -1366,7 +1230,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, ofr = (const struct ofp_flow_removed *) oh; ofputil_cls_rule_from_match(&ofr->match, ntohs(ofr->priority), - flow_format, ofr->cookie, &fr->rule); + &fr->rule); fr->cookie = ofr->cookie; fr->reason = ofr->reason; fr->duration_sec = ntohl(ofr->duration_sec); @@ -1414,14 +1278,12 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, { struct ofpbuf *msg; - if (flow_format == NXFF_OPENFLOW10 - || flow_format == NXFF_TUN_ID_FROM_COOKIE) { + if (flow_format == NXFF_OPENFLOW10) { struct ofp_flow_removed *ofr; ofr = make_openflow_xid(sizeof *ofr, OFPT_FLOW_REMOVED, htonl(0), &msg); - ofputil_cls_rule_to_match(&fr->rule, flow_format, &ofr->match, - fr->cookie, &ofr->cookie); + ofputil_cls_rule_to_match(&fr->rule, &ofr->match); ofr->priority = htons(fr->rule.priority); ofr->reason = fr->reason; ofr->duration_sec = htonl(fr->duration_sec); @@ -1716,7 +1578,7 @@ make_flow_mod(uint16_t command, const struct cls_rule *rule, ofm->header.length = htons(size); ofm->cookie = 0; ofm->priority = htons(MIN(rule->priority, UINT16_MAX)); - ofputil_cls_rule_to_match(rule, NXFF_OPENFLOW10, &ofm->match, 0, NULL); + ofputil_cls_rule_to_match(rule, &ofm->match); ofm->command = htons(command); return out; } @@ -1863,49 +1725,17 @@ make_echo_reply(const struct ofp_header *rq) return out; } -const struct ofp_flow_stats * -flow_stats_first(struct flow_stats_iterator *iter, - const struct ofp_stats_reply *osr) +/* Converts the members of 'opp' from host to network byte order. */ +void +hton_ofp_phy_port(struct ofp_phy_port *opp) { - iter->pos = osr->body; - iter->end = osr->body + (ntohs(osr->header.length) - - offsetof(struct ofp_stats_reply, body)); - return flow_stats_next(iter); -} - -const struct ofp_flow_stats * -flow_stats_next(struct flow_stats_iterator *iter) -{ - ptrdiff_t bytes_left = iter->end - iter->pos; - const struct ofp_flow_stats *fs; - size_t length; - - if (bytes_left < sizeof *fs) { - if (bytes_left != 0) { - VLOG_WARN_RL(&bad_ofmsg_rl, - "%td leftover bytes in flow stats reply", bytes_left); - } - return NULL; - } - - fs = (const void *) iter->pos; - length = ntohs(fs->length); - if (length < sizeof *fs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "flow stats length %zu is shorter than " - "min %zu", length, sizeof *fs); - return NULL; - } else if (length > bytes_left) { - VLOG_WARN_RL(&bad_ofmsg_rl, "flow stats length %zu but only %td " - "bytes left", length, bytes_left); - return NULL; - } else if ((length - sizeof *fs) % sizeof fs->actions[0]) { - VLOG_WARN_RL(&bad_ofmsg_rl, "flow stats length %zu has %zu bytes " - "left over in final action", length, - (length - sizeof *fs) % sizeof fs->actions[0]); - return NULL; - } - iter->pos += length; - return fs; + opp->port_no = htons(opp->port_no); + opp->config = htonl(opp->config); + opp->state = htonl(opp->state); + opp->curr = htonl(opp->curr); + opp->advertised = htonl(opp->advertised); + opp->supported = htonl(opp->supported); + opp->peer = htonl(opp->peer); } static int @@ -1990,7 +1820,7 @@ check_nicira_action(const union ofp_action *a, unsigned int len, const struct flow *flow) { const struct nx_action_header *nah; - uint16_t subtype; + int subtype; int error; if (len < 16) { @@ -2002,7 +1832,7 @@ check_nicira_action(const union ofp_action *a, unsigned int len, subtype = ntohs(nah->subtype); if (subtype > TYPE_MAXIMUM(enum nx_action_subtype)) { - /* This is necessary because enum nx_action_subtype is probably an + /* This is necessary because enum nx_action_subtype may be an * 8-bit type, so the cast below throws away the top 8 bits. */ return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE); } @@ -2046,11 +1876,18 @@ check_nicira_action(const union ofp_action *a, unsigned int len, } return multipath_check((const struct nx_action_multipath *) a); + case NXAST_AUTOPATH: + error = check_nx_action_exact_len( + nah, len, sizeof(struct nx_action_autopath)); + if (error) { + return error; + } + return autopath_check((const struct nx_action_autopath *) a); + case NXAST_SNAT__OBSOLETE: default: VLOG_WARN_RL(&bad_ofmsg_rl, - "unknown Nicira vendor action subtype %"PRIu16, - ntohs(nah->subtype)); + "unknown Nicira vendor action subtype %d", subtype); return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE); } } @@ -2199,7 +2036,7 @@ normalize_match(struct ofp_match *m) enum { OFPFW_TP = OFPFW_TP_SRC | OFPFW_TP_DST }; uint32_t wc; - wc = ntohl(m->wildcards) & OVSFW_ALL; + wc = ntohl(m->wildcards) & OFPFW_ALL; if (wc & OFPFW_DL_TYPE) { m->dl_type = 0;