cls_table_next_rule(const struct cls_table *table, const struct cls_rule *rule)
{
struct cls_rule *next
- = CONTAINER_OF(rule->list.next, struct cls_rule, hmap_node);
+ = CONTAINER_OF(rule->list.next, struct cls_rule, list);
return (next->priority < rule->priority
? next
&next->hmap_node)));
}
-static void
-cls_rule_init__(struct cls_rule *rule,
- const struct flow *flow, uint32_t wildcards)
+/* Converts the flow in 'flow' into a cls_rule in 'rule', with the given
+ * 'wildcards' and 'priority'. */
+void
+cls_rule_init(const struct flow *flow, const struct flow_wildcards *wildcards,
+ unsigned int priority, struct cls_rule *rule)
{
rule->flow = *flow;
- flow_wildcards_init(&rule->wc, wildcards);
+ rule->wc = *wildcards;
+ rule->priority = priority;
cls_rule_zero_wildcarded_fields(rule);
}
-/* Converts the flow in 'flow' into a cls_rule in 'rule', with the given
- * 'wildcards' and 'priority'.*/
+/* Converts the flow in 'flow' into an exact-match cls_rule in 'rule', with the
+ * given 'priority'. (For OpenFlow 1.0, exact-match rule are always highest
+ * priority, so 'priority' should be at least 65535.) */
void
-cls_rule_from_flow(const struct flow *flow, uint32_t wildcards,
- unsigned int priority, struct cls_rule *rule)
+cls_rule_init_exact(const struct flow *flow,
+ unsigned int priority, struct cls_rule *rule)
{
- cls_rule_init__(rule, flow, wildcards);
+ rule->flow = *flow;
+ flow_wildcards_init_exact(&rule->wc);
rule->priority = priority;
}
int flow_format, uint64_t cookie,
struct cls_rule *rule)
{
- uint32_t wildcards;
- struct flow flow;
-
- flow_from_match(match, flow_format, cookie, &flow, &wildcards);
- cls_rule_init__(rule, &flow, wildcards);
- rule->priority = rule->wc.wildcards ? priority : UINT16_MAX;
+ flow_from_match(match, flow_format, cookie, &rule->flow, &rule->wc);
+ rule->priority = !rule->wc.wildcards ? UINT16_MAX : priority;
+ cls_rule_zero_wildcarded_fields(rule);
}
/* Initializes 'rule' as a "catch-all" rule that matches every packet, with
cls_rule_init_catchall(struct cls_rule *rule, unsigned int priority)
{
memset(&rule->flow, 0, sizeof rule->flow);
- flow_wildcards_init(&rule->wc, OVSFW_ALL);
+ flow_wildcards_init(&rule->wc, OVSFW_ALL | FWW_ALL);
rule->priority = priority;
}
void
cls_rule_set_dl_dst(struct cls_rule *rule, const uint8_t dl_dst[ETH_ADDR_LEN])
{
- rule->wc.wildcards &= ~OFPFW_DL_DST;
+ rule->wc.wildcards &= ~(OFPFW_DL_DST | FWW_ETH_MCAST);
memcpy(rule->flow.dl_dst, dl_dst, ETH_ADDR_LEN);
}
const struct flow_wildcards *wildcards)
{
const uint32_t wc = wildcards->wildcards;
+ int i;
- BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 37);
+ BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 37 + FLOW_N_REGS * 4);
+
+ for (i = 0; i < FLOW_N_REGS; i++) {
+ if ((a->regs[i] ^ b->regs[i]) & wildcards->reg_masks[i]) {
+ return false;
+ }
+ }
return ((wc & NXFW_TUN_ID || a->tun_id == b->tun_id)
&& !((a->nw_src ^ b->nw_src) & wildcards->nw_src_mask)
&& (wc & OFPFW_TP_SRC || a->tp_src == b->tp_src)
&& (wc & OFPFW_TP_DST || a->tp_dst == b->tp_dst)
&& (wc & OFPFW_DL_SRC || eth_addr_equals(a->dl_src, b->dl_src))
- && (wc & OFPFW_DL_DST || eth_addr_equals(a->dl_dst, b->dl_dst))
+ && (wc & OFPFW_DL_DST
+ || (!((a->dl_dst[0] ^ b->dl_dst[0]) & 0xfe)
+ && a->dl_dst[1] == b->dl_dst[1]
+ && a->dl_dst[2] == b->dl_dst[2]
+ && a->dl_dst[3] == b->dl_dst[3]
+ && a->dl_dst[4] == b->dl_dst[4]
+ && a->dl_dst[5] == b->dl_dst[5]))
+ && (wc & FWW_ETH_MCAST || !((a->dl_dst[0] ^ b->dl_dst[0]) & 0x01))
&& (wc & OFPFW_NW_PROTO || a->nw_proto == b->nw_proto)
&& (wc & OFPFW_DL_VLAN_PCP || a->dl_vlan_pcp == b->dl_vlan_pcp)
&& (wc & OFPFW_NW_TOS || a->nw_tos == b->nw_tos));
zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
{
const uint32_t wc = wildcards->wildcards;
+ int i;
- BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 37);
+ BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 37 + 4 * FLOW_N_REGS);
+ for (i = 0; i < FLOW_N_REGS; i++) {
+ flow->regs[i] &= wildcards->reg_masks[i];
+ }
if (wc & NXFW_TUN_ID) {
flow->tun_id = 0;
}
memset(flow->dl_src, 0, sizeof flow->dl_src);
}
if (wc & OFPFW_DL_DST) {
- memset(flow->dl_dst, 0, sizeof flow->dl_dst);
+ flow->dl_dst[0] &= 0x01;
+ memset(&flow->dl_dst[1], 0, 5);
+ }
+ if (wc & FWW_ETH_MCAST) {
+ flow->dl_dst[0] &= 0xfe;
}
if (wc & OFPFW_NW_PROTO) {
flow->nw_proto = 0;