X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=d58f7ea5ce2627f4c4ba1ce36e5f23d7714d07bb;hb=4029c21acb33723ecc3f621c1c75819651889b58;hp=82797d4d5f1cbf806fa32814e4f11725b1260064;hpb=d8ae4d672673cd72285eb405a96b4ac3590a7639;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 82797d4d..d58f7ea5 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -72,7 +72,6 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask) * name. */ #define WC_INVARIANT_LIST \ WC_INVARIANT_BIT(IN_PORT) \ - WC_INVARIANT_BIT(DL_VLAN) \ WC_INVARIANT_BIT(DL_SRC) \ WC_INVARIANT_BIT(DL_DST) \ WC_INVARIANT_BIT(DL_TYPE) \ @@ -109,6 +108,7 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, { struct flow_wildcards *wc = &rule->wc; unsigned int ofpfw; + ovs_be16 vid, pcp; /* Initialize rule->priority. */ ofpfw = ntohl(match->wildcards); @@ -117,9 +117,6 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, /* Initialize most of rule->wc. */ wc->wildcards = ofpfw & WC_INVARIANTS; - if (ofpfw & OFPFW_DL_VLAN_PCP) { - wc->wildcards |= FWW_DL_VLAN_PCP; - } if (ofpfw & OFPFW_NW_TOS) { wc->wildcards |= FWW_NW_TOS; } @@ -127,7 +124,7 @@ 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 (!(ofpfw & NXFW_TUN_ID)) { + if (flow_format == NXFF_TUN_ID_FROM_COOKIE && !(ofpfw & NXFW_TUN_ID)) { rule->flow.tun_id = htonl(ntohll(cookie) >> 32); } else { wc->wildcards |= FWW_TUN_ID; @@ -141,13 +138,11 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, wc->wildcards |= FWW_ETH_MCAST; } - /* Initialize rule->flow. */ + /* Initialize most of rule->flow. */ rule->flow.nw_src = match->nw_src; 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_vlan = match->dl_vlan; - rule->flow.dl_vlan_pcp = match->dl_vlan_pcp; rule->flow.dl_type = match->dl_type; rule->flow.tp_src = match->tp_src; rule->flow.tp_dst = match->tp_dst; @@ -156,6 +151,49 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, rule->flow.nw_tos = match->nw_tos; rule->flow.nw_proto = match->nw_proto; + /* Translate VLANs. */ + vid = match->dl_vlan & htons(VLAN_VID_MASK); + pcp = htons((match->dl_vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK); + switch (ofpfw & (OFPFW_DL_VLAN | OFPFW_DL_VLAN_PCP)) { + case OFPFW_DL_VLAN | OFPFW_DL_VLAN_PCP: + /* Wildcard everything. */ + rule->flow.vlan_tci = htons(0); + rule->wc.vlan_tci_mask = htons(0); + break; + + case OFPFW_DL_VLAN_PCP: + if (match->dl_vlan == htons(OFP_VLAN_NONE)) { + /* Match only packets without 802.1Q header. */ + rule->flow.vlan_tci = htons(0); + rule->wc.vlan_tci_mask = htons(0xffff); + } else { + /* Wildcard PCP, specific VID. */ + rule->flow.vlan_tci = vid | htons(VLAN_CFI); + rule->wc.vlan_tci_mask = htons(VLAN_VID_MASK | VLAN_CFI); + } + break; + + case OFPFW_DL_VLAN: + /* Wildcard VID, specific PCP. */ + rule->flow.vlan_tci = pcp | htons(VLAN_CFI); + rule->wc.vlan_tci_mask = htons(VLAN_PCP_MASK | VLAN_CFI); + break; + + case 0: + if (match->dl_vlan == htons(OFP_VLAN_NONE)) { + /* This case is odd, since we can't have a specific PCP without an + * 802.1Q header. However, older versions of OVS treated this as + * matching packets withut an 802.1Q header, so we do here too. */ + rule->flow.vlan_tci = htons(0); + rule->wc.vlan_tci_mask = htons(0xffff); + } else { + /* Specific VID and PCP. */ + rule->flow.vlan_tci = vid | pcp | htons(VLAN_CFI); + rule->wc.vlan_tci_mask = htons(0xffff); + } + break; + } + /* Clean up. */ cls_rule_zero_wildcarded_fields(rule); } @@ -173,13 +211,10 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, int flow_format, const struct flow_wildcards *wc = &rule->wc; unsigned int ofpfw; - /* Figure out OpenFlow wildcards. */ + /* Figure out most OpenFlow wildcards. */ ofpfw = wc->wildcards & WC_INVARIANTS; ofpfw |= ofputil_netmask_to_wcbits(wc->nw_src_mask) << OFPFW_NW_SRC_SHIFT; ofpfw |= ofputil_netmask_to_wcbits(wc->nw_dst_mask) << OFPFW_NW_DST_SHIFT; - if (wc->wildcards & FWW_DL_VLAN_PCP) { - ofpfw |= OFPFW_DL_VLAN_PCP; - } if (wc->wildcards & FWW_NW_TOS) { ofpfw |= OFPFW_NW_TOS; } @@ -187,12 +222,32 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, int flow_format, ofpfw |= NXFW_TUN_ID; } - /* Compose match structure. */ + /* Translate VLANs. */ + match->dl_vlan = htons(0); + match->dl_vlan_pcp = 0; + if (rule->wc.vlan_tci_mask == htons(0)) { + ofpfw |= OFPFW_DL_VLAN | OFPFW_DL_VLAN_PCP; + } else if (rule->wc.vlan_tci_mask & htons(VLAN_CFI) + && !(rule->flow.vlan_tci & htons(VLAN_CFI))) { + match->dl_vlan = htons(OFP_VLAN_NONE); + } else { + if (!(rule->wc.vlan_tci_mask & htons(VLAN_VID_MASK))) { + ofpfw |= OFPFW_DL_VLAN; + } else { + match->dl_vlan = htons(vlan_tci_to_vid(rule->flow.vlan_tci)); + } + + if (!(rule->wc.vlan_tci_mask & htons(VLAN_PCP_MASK))) { + ofpfw |= OFPFW_DL_VLAN_PCP; + } else { + match->dl_vlan_pcp = vlan_tci_to_pcp(rule->flow.vlan_tci); + } + } + + /* Compose most of the match structure. */ match->wildcards = htonl(ofpfw); match->in_port = htons(rule->flow.in_port == ODPP_LOCAL ? OFPP_LOCAL : rule->flow.in_port); - match->dl_vlan = rule->flow.dl_vlan; - match->dl_vlan_pcp = rule->flow.dl_vlan_pcp; 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; @@ -328,7 +383,8 @@ update_openflow_length(struct ofpbuf *buffer) } struct ofpbuf * -make_flow_mod(uint16_t command, const struct flow *flow, size_t actions_len) +make_flow_mod(uint16_t command, const struct cls_rule *rule, + size_t actions_len) { struct ofp_flow_mod *ofm; size_t size = sizeof *ofm + actions_len; @@ -338,29 +394,17 @@ make_flow_mod(uint16_t command, const struct flow *flow, size_t actions_len) ofm->header.type = OFPT_FLOW_MOD; ofm->header.length = htons(size); ofm->cookie = 0; - ofm->match.wildcards = htonl(0); - ofm->match.in_port = htons(flow->in_port == ODPP_LOCAL ? OFPP_LOCAL - : flow->in_port); - memcpy(ofm->match.dl_src, flow->dl_src, sizeof ofm->match.dl_src); - memcpy(ofm->match.dl_dst, flow->dl_dst, sizeof ofm->match.dl_dst); - ofm->match.dl_vlan = flow->dl_vlan; - ofm->match.dl_vlan_pcp = flow->dl_vlan_pcp; - ofm->match.dl_type = flow->dl_type; - ofm->match.nw_src = flow->nw_src; - ofm->match.nw_dst = flow->nw_dst; - ofm->match.nw_proto = flow->nw_proto; - ofm->match.nw_tos = flow->nw_tos; - ofm->match.tp_src = flow->tp_src; - ofm->match.tp_dst = flow->tp_dst; + ofm->priority = htons(MIN(rule->priority, UINT16_MAX)); + ofputil_cls_rule_to_match(rule, NXFF_OPENFLOW10, &ofm->match); ofm->command = htons(command); return out; } struct ofpbuf * -make_add_flow(const struct flow *flow, uint32_t buffer_id, +make_add_flow(const struct cls_rule *rule, uint32_t buffer_id, uint16_t idle_timeout, size_t actions_len) { - struct ofpbuf *out = make_flow_mod(OFPFC_ADD, flow, actions_len); + struct ofpbuf *out = make_flow_mod(OFPFC_ADD, rule, actions_len); struct ofp_flow_mod *ofm = out->data; ofm->idle_timeout = htons(idle_timeout); ofm->hard_timeout = htons(OFP_FLOW_PERMANENT); @@ -369,16 +413,16 @@ make_add_flow(const struct flow *flow, uint32_t buffer_id, } struct ofpbuf * -make_del_flow(const struct flow *flow) +make_del_flow(const struct cls_rule *rule) { - struct ofpbuf *out = make_flow_mod(OFPFC_DELETE_STRICT, flow, 0); + struct ofpbuf *out = make_flow_mod(OFPFC_DELETE_STRICT, rule, 0); struct ofp_flow_mod *ofm = out->data; ofm->out_port = htons(OFPP_NONE); return out; } struct ofpbuf * -make_add_simple_flow(const struct flow *flow, +make_add_simple_flow(const struct cls_rule *rule, uint32_t buffer_id, uint16_t out_port, uint16_t idle_timeout) { @@ -386,14 +430,14 @@ make_add_simple_flow(const struct flow *flow, struct ofp_action_output *oao; struct ofpbuf *buffer; - buffer = make_add_flow(flow, buffer_id, idle_timeout, sizeof *oao); + buffer = make_add_flow(rule, buffer_id, idle_timeout, sizeof *oao); oao = ofpbuf_put_zeros(buffer, sizeof *oao); oao->type = htons(OFPAT_OUTPUT); oao->len = htons(sizeof *oao); oao->port = htons(out_port); return buffer; } else { - return make_add_flow(flow, buffer_id, idle_timeout, 0); + return make_add_flow(rule, buffer_id, idle_timeout, 0); } }