{
MFF_TCP_SRC, "tcp_src", "tp_src",
MF_FIELD_SIZES(be16),
- MFM_NONE, FWW_TP_SRC,
+ MFM_FULLY, 0,
MFS_DECIMAL,
MFP_TCP,
true,
}, {
MFF_TCP_DST, "tcp_dst", "tp_dst",
MF_FIELD_SIZES(be16),
- MFM_NONE, FWW_TP_DST,
+ MFM_FULLY, 0,
MFS_DECIMAL,
MFP_TCP,
true,
{
MFF_UDP_SRC, "udp_src", NULL,
MF_FIELD_SIZES(be16),
- MFM_NONE, FWW_TP_SRC,
+ MFM_FULLY, 0,
MFS_DECIMAL,
MFP_UDP,
true,
}, {
MFF_UDP_DST, "udp_dst", NULL,
MF_FIELD_SIZES(be16),
- MFM_NONE, FWW_TP_DST,
+ MFM_FULLY, 0,
MFS_DECIMAL,
MFP_UDP,
true,
{
MFF_ICMPV4_TYPE, "icmp_type", NULL,
MF_FIELD_SIZES(u8),
- MFM_NONE, FWW_TP_SRC,
+ MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV4,
false,
}, {
MFF_ICMPV4_CODE, "icmp_code", NULL,
MF_FIELD_SIZES(u8),
- MFM_NONE, FWW_TP_DST,
+ MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV4,
false,
{
MFF_ICMPV6_TYPE, "icmpv6_type", NULL,
MF_FIELD_SIZES(u8),
- MFM_NONE, FWW_TP_SRC,
+ MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV6,
false,
}, {
MFF_ICMPV6_CODE, "icmpv6_code", NULL,
MF_FIELD_SIZES(u8),
- MFM_NONE, FWW_TP_DST,
+ MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV6,
false,
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
- case MFF_TCP_SRC:
- case MFF_TCP_DST:
- case MFF_UDP_SRC:
- case MFF_UDP_DST:
- case MFF_ICMPV4_TYPE:
- case MFF_ICMPV4_CODE:
- case MFF_ICMPV6_TYPE:
- case MFF_ICMPV6_CODE:
case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
case MFF_ARP_TPA:
return !wc->nw_dst_mask;
+ case MFF_TCP_SRC:
+ case MFF_UDP_SRC:
+ case MFF_ICMPV4_TYPE:
+ case MFF_ICMPV6_TYPE:
+ return !wc->tp_src_mask;
+ case MFF_TCP_DST:
+ case MFF_UDP_DST:
+ case MFF_ICMPV4_CODE:
+ case MFF_ICMPV6_CODE:
+ return !wc->tp_dst_mask;
+
case MFF_N_IDS:
default:
NOT_REACHED();
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
- case MFF_TCP_SRC:
- case MFF_TCP_DST:
- case MFF_UDP_SRC:
- case MFF_UDP_DST:
- case MFF_ICMPV4_TYPE:
- case MFF_ICMPV4_CODE:
- case MFF_ICMPV6_TYPE:
- case MFF_ICMPV6_CODE:
case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
mask->be32 = wc->nw_dst_mask;
break;
+ case MFF_TCP_SRC:
+ case MFF_UDP_SRC:
+ mask->be16 = wc->tp_src_mask;
+ break;
+ case MFF_TCP_DST:
+ case MFF_UDP_DST:
+ mask->be16 = wc->tp_dst_mask;
+ break;
+
+ case MFF_ICMPV4_TYPE:
+ case MFF_ICMPV6_TYPE:
+ mask->u8 = ntohs(wc->tp_src_mask);
+ break;
+ case MFF_ICMPV4_CODE:
+ case MFF_ICMPV6_CODE:
+ mask->u8 = ntohs(wc->tp_dst_mask);
+ break;
+
case MFF_N_IDS:
default:
NOT_REACHED();
case MFF_UDP_SRC:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV6_TYPE:
- rule->wc.wildcards |= FWW_TP_SRC;
+ rule->wc.tp_src_mask = htons(0);
rule->flow.tp_src = htons(0);
break;
case MFF_UDP_DST:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_CODE:
- rule->wc.wildcards |= FWW_TP_DST;
+ rule->wc.tp_dst_mask = htons(0);
rule->flow.tp_dst = htons(0);
break;
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
- case MFF_TCP_SRC:
- case MFF_TCP_DST:
- case MFF_UDP_SRC:
- case MFF_UDP_DST:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_TYPE:
cls_rule_set_nw_dst_masked(rule, value->be32, mask->be32);
break;
+ case MFF_TCP_SRC:
+ case MFF_UDP_SRC:
+ cls_rule_set_tp_src_masked(rule, value->be16, mask->be16);
+ break;
+
+ case MFF_TCP_DST:
+ case MFF_UDP_DST:
+ cls_rule_set_tp_dst_masked(rule, value->be16, mask->be16);
+ break;
+
case MFF_N_IDS:
default:
NOT_REACHED();
}
}
\f
-/* Makes a subfield starting at bit offset 'ofs' and continuing for 'n_bits' in
- * 'rule''s field 'mf' exactly match the 'n_bits' least-significant bits of
- * 'x'.
+/* Makes subfield 'sf' within 'rule' exactly match the 'sf->n_bits'
+ * least-significant bits in 'x'.
+ *
+ * See mf_set_subfield() for an example.
+ *
+ * The difference between this function and mf_set_subfield() is that the
+ * latter function can only handle subfields up to 64 bits wide, whereas this
+ * one handles the general case. On the other hand, mf_set_subfield() is
+ * arguably easier to use. */
+void
+mf_write_subfield(const struct mf_subfield *sf, const union mf_subvalue *x,
+ struct cls_rule *rule)
+{
+ const struct mf_field *field = sf->field;
+ union mf_value value, mask;
+
+ mf_get(field, rule, &value, &mask);
+ bitwise_copy(x, sizeof *x, 0, &value, field->n_bytes, sf->ofs, sf->n_bits);
+ bitwise_one ( &mask, field->n_bytes, sf->ofs, sf->n_bits);
+ mf_set(field, &value, &mask, rule);
+}
+
+/* Makes subfield 'sf' within 'rule' exactly match the 'sf->n_bits'
+ * least-significant bits of 'x'.
*
- * Example: suppose that 'mf' is originally the following 2-byte field in
- * 'rule':
+ * Example: suppose that 'sf->field' is originally the following 2-byte field
+ * in 'rule':
*
* value == 0xe00a == 2#1110000000001010
* mask == 0xfc3f == 2#1111110000111111
*
- * The call mf_set_subfield(mf, 0x55, 8, 7, rule) would have the following
- * effect (note that 0x55 is 2#1010101):
+ * The call mf_set_subfield(sf, 0x55, 8, 7, rule), where sf->ofs == 8 and
+ * sf->n_bits == 7 would have the following effect (note that 0x55 is
+ * 2#1010101):
*
* value == 0xd50a == 2#1101010100001010
* mask == 0xff3f == 2#1111111100111111
+ * ^^^^^^^ affected bits
*
* The caller is responsible for ensuring that the result will be a valid
- * wildcard pattern for 'mf'. The caller is responsible for ensuring that
- * 'rule' meets 'mf''s prerequisites. */
+ * wildcard pattern for 'sf->field'. The caller is responsible for ensuring
+ * that 'rule' meets 'sf->field''s prerequisites. */
void
mf_set_subfield(const struct mf_subfield *sf, uint64_t x,
struct cls_rule *rule)
}
}
+/* Initializes 'x' to the value of 'sf' within 'flow'. 'sf' must be valid for
+ * reading 'flow', e.g. as checked by mf_check_src(). */
+void
+mf_read_subfield(const struct mf_subfield *sf, const struct flow *flow,
+ union mf_subvalue *x)
+{
+ union mf_value value;
+
+ mf_get_value(sf->field, flow, &value);
+
+ memset(x, 0, sizeof *x);
+ bitwise_copy(&value, sf->field->n_bytes, sf->ofs,
+ x, sizeof *x, 0,
+ sf->n_bits);
+}
+
/* Returns the value of 'sf' within 'flow'. 'sf' must be valid for reading
* 'flow', e.g. as checked by mf_check_src() and sf->n_bits must be 64 or
* less. */
ds_put_cstr(s, sf->field->name);
}
- if (sf->ofs == 0 && sf->n_bits == sf->field->n_bits) {
+ if (sf->field && sf->ofs == 0 && sf->n_bits == sf->field->n_bits) {
ds_put_cstr(s, "[]");
} else if (sf->n_bits == 1) {
ds_put_format(s, "[%d]", sf->ofs);